##// END OF EJS Templates
bisect: move the 'extendrange' to the 'hbisect' module...
Pierre-Yves David -
r30066:5f93737d default
parent child Browse files
Show More
@@ -1,7395 +1,7381 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import operator
12 import operator
13 import os
13 import os
14 import random
14 import random
15 import re
15 import re
16 import shlex
16 import shlex
17 import socket
17 import socket
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 import time
20 import time
21
21
22 from .i18n import _
22 from .i18n import _
23 from .node import (
23 from .node import (
24 bin,
24 bin,
25 hex,
25 hex,
26 nullhex,
26 nullhex,
27 nullid,
27 nullid,
28 nullrev,
28 nullrev,
29 short,
29 short,
30 )
30 )
31 from . import (
31 from . import (
32 archival,
32 archival,
33 bookmarks,
33 bookmarks,
34 bundle2,
34 bundle2,
35 changegroup,
35 changegroup,
36 cmdutil,
36 cmdutil,
37 commandserver,
37 commandserver,
38 context,
38 context,
39 copies,
39 copies,
40 dagparser,
40 dagparser,
41 dagutil,
41 dagutil,
42 destutil,
42 destutil,
43 discovery,
43 discovery,
44 encoding,
44 encoding,
45 error,
45 error,
46 exchange,
46 exchange,
47 extensions,
47 extensions,
48 fileset,
48 fileset,
49 formatter,
49 formatter,
50 graphmod,
50 graphmod,
51 hbisect,
51 hbisect,
52 help,
52 help,
53 hg,
53 hg,
54 hgweb,
54 hgweb,
55 localrepo,
55 localrepo,
56 lock as lockmod,
56 lock as lockmod,
57 merge as mergemod,
57 merge as mergemod,
58 minirst,
58 minirst,
59 obsolete,
59 obsolete,
60 patch,
60 patch,
61 phases,
61 phases,
62 policy,
62 policy,
63 pvec,
63 pvec,
64 repair,
64 repair,
65 revlog,
65 revlog,
66 revset,
66 revset,
67 scmutil,
67 scmutil,
68 setdiscovery,
68 setdiscovery,
69 simplemerge,
69 simplemerge,
70 sshserver,
70 sshserver,
71 streamclone,
71 streamclone,
72 templatekw,
72 templatekw,
73 templater,
73 templater,
74 treediscovery,
74 treediscovery,
75 ui as uimod,
75 ui as uimod,
76 util,
76 util,
77 )
77 )
78
78
79 release = lockmod.release
79 release = lockmod.release
80
80
81 table = {}
81 table = {}
82
82
83 command = cmdutil.command(table)
83 command = cmdutil.command(table)
84
84
85 # label constants
85 # label constants
86 # until 3.5, bookmarks.current was the advertised name, not
86 # until 3.5, bookmarks.current was the advertised name, not
87 # bookmarks.active, so we must use both to avoid breaking old
87 # bookmarks.active, so we must use both to avoid breaking old
88 # custom styles
88 # custom styles
89 activebookmarklabel = 'bookmarks.active bookmarks.current'
89 activebookmarklabel = 'bookmarks.active bookmarks.current'
90
90
91 # common command options
91 # common command options
92
92
93 globalopts = [
93 globalopts = [
94 ('R', 'repository', '',
94 ('R', 'repository', '',
95 _('repository root directory or name of overlay bundle file'),
95 _('repository root directory or name of overlay bundle file'),
96 _('REPO')),
96 _('REPO')),
97 ('', 'cwd', '',
97 ('', 'cwd', '',
98 _('change working directory'), _('DIR')),
98 _('change working directory'), _('DIR')),
99 ('y', 'noninteractive', None,
99 ('y', 'noninteractive', None,
100 _('do not prompt, automatically pick the first choice for all prompts')),
100 _('do not prompt, automatically pick the first choice for all prompts')),
101 ('q', 'quiet', None, _('suppress output')),
101 ('q', 'quiet', None, _('suppress output')),
102 ('v', 'verbose', None, _('enable additional output')),
102 ('v', 'verbose', None, _('enable additional output')),
103 ('', 'config', [],
103 ('', 'config', [],
104 _('set/override config option (use \'section.name=value\')'),
104 _('set/override config option (use \'section.name=value\')'),
105 _('CONFIG')),
105 _('CONFIG')),
106 ('', 'debug', None, _('enable debugging output')),
106 ('', 'debug', None, _('enable debugging output')),
107 ('', 'debugger', None, _('start debugger')),
107 ('', 'debugger', None, _('start debugger')),
108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
109 _('ENCODE')),
109 _('ENCODE')),
110 ('', 'encodingmode', encoding.encodingmode,
110 ('', 'encodingmode', encoding.encodingmode,
111 _('set the charset encoding mode'), _('MODE')),
111 _('set the charset encoding mode'), _('MODE')),
112 ('', 'traceback', None, _('always print a traceback on exception')),
112 ('', 'traceback', None, _('always print a traceback on exception')),
113 ('', 'time', None, _('time how long the command takes')),
113 ('', 'time', None, _('time how long the command takes')),
114 ('', 'profile', None, _('print command execution profile')),
114 ('', 'profile', None, _('print command execution profile')),
115 ('', 'version', None, _('output version information and exit')),
115 ('', 'version', None, _('output version information and exit')),
116 ('h', 'help', None, _('display help and exit')),
116 ('h', 'help', None, _('display help and exit')),
117 ('', 'hidden', False, _('consider hidden changesets')),
117 ('', 'hidden', False, _('consider hidden changesets')),
118 ]
118 ]
119
119
120 dryrunopts = [('n', 'dry-run', None,
120 dryrunopts = [('n', 'dry-run', None,
121 _('do not perform actions, just print output'))]
121 _('do not perform actions, just print output'))]
122
122
123 remoteopts = [
123 remoteopts = [
124 ('e', 'ssh', '',
124 ('e', 'ssh', '',
125 _('specify ssh command to use'), _('CMD')),
125 _('specify ssh command to use'), _('CMD')),
126 ('', 'remotecmd', '',
126 ('', 'remotecmd', '',
127 _('specify hg command to run on the remote side'), _('CMD')),
127 _('specify hg command to run on the remote side'), _('CMD')),
128 ('', 'insecure', None,
128 ('', 'insecure', None,
129 _('do not verify server certificate (ignoring web.cacerts config)')),
129 _('do not verify server certificate (ignoring web.cacerts config)')),
130 ]
130 ]
131
131
132 walkopts = [
132 walkopts = [
133 ('I', 'include', [],
133 ('I', 'include', [],
134 _('include names matching the given patterns'), _('PATTERN')),
134 _('include names matching the given patterns'), _('PATTERN')),
135 ('X', 'exclude', [],
135 ('X', 'exclude', [],
136 _('exclude names matching the given patterns'), _('PATTERN')),
136 _('exclude names matching the given patterns'), _('PATTERN')),
137 ]
137 ]
138
138
139 commitopts = [
139 commitopts = [
140 ('m', 'message', '',
140 ('m', 'message', '',
141 _('use text as commit message'), _('TEXT')),
141 _('use text as commit message'), _('TEXT')),
142 ('l', 'logfile', '',
142 ('l', 'logfile', '',
143 _('read commit message from file'), _('FILE')),
143 _('read commit message from file'), _('FILE')),
144 ]
144 ]
145
145
146 commitopts2 = [
146 commitopts2 = [
147 ('d', 'date', '',
147 ('d', 'date', '',
148 _('record the specified date as commit date'), _('DATE')),
148 _('record the specified date as commit date'), _('DATE')),
149 ('u', 'user', '',
149 ('u', 'user', '',
150 _('record the specified user as committer'), _('USER')),
150 _('record the specified user as committer'), _('USER')),
151 ]
151 ]
152
152
153 # hidden for now
153 # hidden for now
154 formatteropts = [
154 formatteropts = [
155 ('T', 'template', '',
155 ('T', 'template', '',
156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
157 ]
157 ]
158
158
159 templateopts = [
159 templateopts = [
160 ('', 'style', '',
160 ('', 'style', '',
161 _('display using template map file (DEPRECATED)'), _('STYLE')),
161 _('display using template map file (DEPRECATED)'), _('STYLE')),
162 ('T', 'template', '',
162 ('T', 'template', '',
163 _('display with template'), _('TEMPLATE')),
163 _('display with template'), _('TEMPLATE')),
164 ]
164 ]
165
165
166 logopts = [
166 logopts = [
167 ('p', 'patch', None, _('show patch')),
167 ('p', 'patch', None, _('show patch')),
168 ('g', 'git', None, _('use git extended diff format')),
168 ('g', 'git', None, _('use git extended diff format')),
169 ('l', 'limit', '',
169 ('l', 'limit', '',
170 _('limit number of changes displayed'), _('NUM')),
170 _('limit number of changes displayed'), _('NUM')),
171 ('M', 'no-merges', None, _('do not show merges')),
171 ('M', 'no-merges', None, _('do not show merges')),
172 ('', 'stat', None, _('output diffstat-style summary of changes')),
172 ('', 'stat', None, _('output diffstat-style summary of changes')),
173 ('G', 'graph', None, _("show the revision DAG")),
173 ('G', 'graph', None, _("show the revision DAG")),
174 ] + templateopts
174 ] + templateopts
175
175
176 diffopts = [
176 diffopts = [
177 ('a', 'text', None, _('treat all files as text')),
177 ('a', 'text', None, _('treat all files as text')),
178 ('g', 'git', None, _('use git extended diff format')),
178 ('g', 'git', None, _('use git extended diff format')),
179 ('', 'nodates', None, _('omit dates from diff headers'))
179 ('', 'nodates', None, _('omit dates from diff headers'))
180 ]
180 ]
181
181
182 diffwsopts = [
182 diffwsopts = [
183 ('w', 'ignore-all-space', None,
183 ('w', 'ignore-all-space', None,
184 _('ignore white space when comparing lines')),
184 _('ignore white space when comparing lines')),
185 ('b', 'ignore-space-change', None,
185 ('b', 'ignore-space-change', None,
186 _('ignore changes in the amount of white space')),
186 _('ignore changes in the amount of white space')),
187 ('B', 'ignore-blank-lines', None,
187 ('B', 'ignore-blank-lines', None,
188 _('ignore changes whose lines are all blank')),
188 _('ignore changes whose lines are all blank')),
189 ]
189 ]
190
190
191 diffopts2 = [
191 diffopts2 = [
192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
193 ('p', 'show-function', None, _('show which function each change is in')),
193 ('p', 'show-function', None, _('show which function each change is in')),
194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
195 ] + diffwsopts + [
195 ] + diffwsopts + [
196 ('U', 'unified', '',
196 ('U', 'unified', '',
197 _('number of lines of context to show'), _('NUM')),
197 _('number of lines of context to show'), _('NUM')),
198 ('', 'stat', None, _('output diffstat-style summary of changes')),
198 ('', 'stat', None, _('output diffstat-style summary of changes')),
199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
200 ]
200 ]
201
201
202 mergetoolopts = [
202 mergetoolopts = [
203 ('t', 'tool', '', _('specify merge tool')),
203 ('t', 'tool', '', _('specify merge tool')),
204 ]
204 ]
205
205
206 similarityopts = [
206 similarityopts = [
207 ('s', 'similarity', '',
207 ('s', 'similarity', '',
208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
209 ]
209 ]
210
210
211 subrepoopts = [
211 subrepoopts = [
212 ('S', 'subrepos', None,
212 ('S', 'subrepos', None,
213 _('recurse into subrepositories'))
213 _('recurse into subrepositories'))
214 ]
214 ]
215
215
216 debugrevlogopts = [
216 debugrevlogopts = [
217 ('c', 'changelog', False, _('open changelog')),
217 ('c', 'changelog', False, _('open changelog')),
218 ('m', 'manifest', False, _('open manifest')),
218 ('m', 'manifest', False, _('open manifest')),
219 ('', 'dir', '', _('open directory manifest')),
219 ('', 'dir', '', _('open directory manifest')),
220 ]
220 ]
221
221
222 # Commands start here, listed alphabetically
222 # Commands start here, listed alphabetically
223
223
224 @command('^add',
224 @command('^add',
225 walkopts + subrepoopts + dryrunopts,
225 walkopts + subrepoopts + dryrunopts,
226 _('[OPTION]... [FILE]...'),
226 _('[OPTION]... [FILE]...'),
227 inferrepo=True)
227 inferrepo=True)
228 def add(ui, repo, *pats, **opts):
228 def add(ui, repo, *pats, **opts):
229 """add the specified files on the next commit
229 """add the specified files on the next commit
230
230
231 Schedule files to be version controlled and added to the
231 Schedule files to be version controlled and added to the
232 repository.
232 repository.
233
233
234 The files will be added to the repository at the next commit. To
234 The files will be added to the repository at the next commit. To
235 undo an add before that, see :hg:`forget`.
235 undo an add before that, see :hg:`forget`.
236
236
237 If no names are given, add all files to the repository (except
237 If no names are given, add all files to the repository (except
238 files matching ``.hgignore``).
238 files matching ``.hgignore``).
239
239
240 .. container:: verbose
240 .. container:: verbose
241
241
242 Examples:
242 Examples:
243
243
244 - New (unknown) files are added
244 - New (unknown) files are added
245 automatically by :hg:`add`::
245 automatically by :hg:`add`::
246
246
247 $ ls
247 $ ls
248 foo.c
248 foo.c
249 $ hg status
249 $ hg status
250 ? foo.c
250 ? foo.c
251 $ hg add
251 $ hg add
252 adding foo.c
252 adding foo.c
253 $ hg status
253 $ hg status
254 A foo.c
254 A foo.c
255
255
256 - Specific files to be added can be specified::
256 - Specific files to be added can be specified::
257
257
258 $ ls
258 $ ls
259 bar.c foo.c
259 bar.c foo.c
260 $ hg status
260 $ hg status
261 ? bar.c
261 ? bar.c
262 ? foo.c
262 ? foo.c
263 $ hg add bar.c
263 $ hg add bar.c
264 $ hg status
264 $ hg status
265 A bar.c
265 A bar.c
266 ? foo.c
266 ? foo.c
267
267
268 Returns 0 if all files are successfully added.
268 Returns 0 if all files are successfully added.
269 """
269 """
270
270
271 m = scmutil.match(repo[None], pats, opts)
271 m = scmutil.match(repo[None], pats, opts)
272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
273 return rejected and 1 or 0
273 return rejected and 1 or 0
274
274
275 @command('addremove',
275 @command('addremove',
276 similarityopts + subrepoopts + walkopts + dryrunopts,
276 similarityopts + subrepoopts + walkopts + dryrunopts,
277 _('[OPTION]... [FILE]...'),
277 _('[OPTION]... [FILE]...'),
278 inferrepo=True)
278 inferrepo=True)
279 def addremove(ui, repo, *pats, **opts):
279 def addremove(ui, repo, *pats, **opts):
280 """add all new files, delete all missing files
280 """add all new files, delete all missing files
281
281
282 Add all new files and remove all missing files from the
282 Add all new files and remove all missing files from the
283 repository.
283 repository.
284
284
285 Unless names are given, new files are ignored if they match any of
285 Unless names are given, new files are ignored if they match any of
286 the patterns in ``.hgignore``. As with add, these changes take
286 the patterns in ``.hgignore``. As with add, these changes take
287 effect at the next commit.
287 effect at the next commit.
288
288
289 Use the -s/--similarity option to detect renamed files. This
289 Use the -s/--similarity option to detect renamed files. This
290 option takes a percentage between 0 (disabled) and 100 (files must
290 option takes a percentage between 0 (disabled) and 100 (files must
291 be identical) as its parameter. With a parameter greater than 0,
291 be identical) as its parameter. With a parameter greater than 0,
292 this compares every removed file with every added file and records
292 this compares every removed file with every added file and records
293 those similar enough as renames. Detecting renamed files this way
293 those similar enough as renames. Detecting renamed files this way
294 can be expensive. After using this option, :hg:`status -C` can be
294 can be expensive. After using this option, :hg:`status -C` can be
295 used to check which files were identified as moved or renamed. If
295 used to check which files were identified as moved or renamed. If
296 not specified, -s/--similarity defaults to 100 and only renames of
296 not specified, -s/--similarity defaults to 100 and only renames of
297 identical files are detected.
297 identical files are detected.
298
298
299 .. container:: verbose
299 .. container:: verbose
300
300
301 Examples:
301 Examples:
302
302
303 - A number of files (bar.c and foo.c) are new,
303 - A number of files (bar.c and foo.c) are new,
304 while foobar.c has been removed (without using :hg:`remove`)
304 while foobar.c has been removed (without using :hg:`remove`)
305 from the repository::
305 from the repository::
306
306
307 $ ls
307 $ ls
308 bar.c foo.c
308 bar.c foo.c
309 $ hg status
309 $ hg status
310 ! foobar.c
310 ! foobar.c
311 ? bar.c
311 ? bar.c
312 ? foo.c
312 ? foo.c
313 $ hg addremove
313 $ hg addremove
314 adding bar.c
314 adding bar.c
315 adding foo.c
315 adding foo.c
316 removing foobar.c
316 removing foobar.c
317 $ hg status
317 $ hg status
318 A bar.c
318 A bar.c
319 A foo.c
319 A foo.c
320 R foobar.c
320 R foobar.c
321
321
322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
323 Afterwards, it was edited slightly::
323 Afterwards, it was edited slightly::
324
324
325 $ ls
325 $ ls
326 foo.c
326 foo.c
327 $ hg status
327 $ hg status
328 ! foobar.c
328 ! foobar.c
329 ? foo.c
329 ? foo.c
330 $ hg addremove --similarity 90
330 $ hg addremove --similarity 90
331 removing foobar.c
331 removing foobar.c
332 adding foo.c
332 adding foo.c
333 recording removal of foobar.c as rename to foo.c (94% similar)
333 recording removal of foobar.c as rename to foo.c (94% similar)
334 $ hg status -C
334 $ hg status -C
335 A foo.c
335 A foo.c
336 foobar.c
336 foobar.c
337 R foobar.c
337 R foobar.c
338
338
339 Returns 0 if all files are successfully added.
339 Returns 0 if all files are successfully added.
340 """
340 """
341 try:
341 try:
342 sim = float(opts.get('similarity') or 100)
342 sim = float(opts.get('similarity') or 100)
343 except ValueError:
343 except ValueError:
344 raise error.Abort(_('similarity must be a number'))
344 raise error.Abort(_('similarity must be a number'))
345 if sim < 0 or sim > 100:
345 if sim < 0 or sim > 100:
346 raise error.Abort(_('similarity must be between 0 and 100'))
346 raise error.Abort(_('similarity must be between 0 and 100'))
347 matcher = scmutil.match(repo[None], pats, opts)
347 matcher = scmutil.match(repo[None], pats, opts)
348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
349
349
350 @command('^annotate|blame',
350 @command('^annotate|blame',
351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
352 ('', 'follow', None,
352 ('', 'follow', None,
353 _('follow copies/renames and list the filename (DEPRECATED)')),
353 _('follow copies/renames and list the filename (DEPRECATED)')),
354 ('', 'no-follow', None, _("don't follow copies and renames")),
354 ('', 'no-follow', None, _("don't follow copies and renames")),
355 ('a', 'text', None, _('treat all files as text')),
355 ('a', 'text', None, _('treat all files as text')),
356 ('u', 'user', None, _('list the author (long with -v)')),
356 ('u', 'user', None, _('list the author (long with -v)')),
357 ('f', 'file', None, _('list the filename')),
357 ('f', 'file', None, _('list the filename')),
358 ('d', 'date', None, _('list the date (short with -q)')),
358 ('d', 'date', None, _('list the date (short with -q)')),
359 ('n', 'number', None, _('list the revision number (default)')),
359 ('n', 'number', None, _('list the revision number (default)')),
360 ('c', 'changeset', None, _('list the changeset')),
360 ('c', 'changeset', None, _('list the changeset')),
361 ('l', 'line-number', None, _('show line number at the first appearance'))
361 ('l', 'line-number', None, _('show line number at the first appearance'))
362 ] + diffwsopts + walkopts + formatteropts,
362 ] + diffwsopts + walkopts + formatteropts,
363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
364 inferrepo=True)
364 inferrepo=True)
365 def annotate(ui, repo, *pats, **opts):
365 def annotate(ui, repo, *pats, **opts):
366 """show changeset information by line for each file
366 """show changeset information by line for each file
367
367
368 List changes in files, showing the revision id responsible for
368 List changes in files, showing the revision id responsible for
369 each line.
369 each line.
370
370
371 This command is useful for discovering when a change was made and
371 This command is useful for discovering when a change was made and
372 by whom.
372 by whom.
373
373
374 If you include --file, --user, or --date, the revision number is
374 If you include --file, --user, or --date, the revision number is
375 suppressed unless you also include --number.
375 suppressed unless you also include --number.
376
376
377 Without the -a/--text option, annotate will avoid processing files
377 Without the -a/--text option, annotate will avoid processing files
378 it detects as binary. With -a, annotate will annotate the file
378 it detects as binary. With -a, annotate will annotate the file
379 anyway, although the results will probably be neither useful
379 anyway, although the results will probably be neither useful
380 nor desirable.
380 nor desirable.
381
381
382 Returns 0 on success.
382 Returns 0 on success.
383 """
383 """
384 if not pats:
384 if not pats:
385 raise error.Abort(_('at least one filename or pattern is required'))
385 raise error.Abort(_('at least one filename or pattern is required'))
386
386
387 if opts.get('follow'):
387 if opts.get('follow'):
388 # --follow is deprecated and now just an alias for -f/--file
388 # --follow is deprecated and now just an alias for -f/--file
389 # to mimic the behavior of Mercurial before version 1.5
389 # to mimic the behavior of Mercurial before version 1.5
390 opts['file'] = True
390 opts['file'] = True
391
391
392 ctx = scmutil.revsingle(repo, opts.get('rev'))
392 ctx = scmutil.revsingle(repo, opts.get('rev'))
393
393
394 fm = ui.formatter('annotate', opts)
394 fm = ui.formatter('annotate', opts)
395 if ui.quiet:
395 if ui.quiet:
396 datefunc = util.shortdate
396 datefunc = util.shortdate
397 else:
397 else:
398 datefunc = util.datestr
398 datefunc = util.datestr
399 if ctx.rev() is None:
399 if ctx.rev() is None:
400 def hexfn(node):
400 def hexfn(node):
401 if node is None:
401 if node is None:
402 return None
402 return None
403 else:
403 else:
404 return fm.hexfunc(node)
404 return fm.hexfunc(node)
405 if opts.get('changeset'):
405 if opts.get('changeset'):
406 # omit "+" suffix which is appended to node hex
406 # omit "+" suffix which is appended to node hex
407 def formatrev(rev):
407 def formatrev(rev):
408 if rev is None:
408 if rev is None:
409 return '%d' % ctx.p1().rev()
409 return '%d' % ctx.p1().rev()
410 else:
410 else:
411 return '%d' % rev
411 return '%d' % rev
412 else:
412 else:
413 def formatrev(rev):
413 def formatrev(rev):
414 if rev is None:
414 if rev is None:
415 return '%d+' % ctx.p1().rev()
415 return '%d+' % ctx.p1().rev()
416 else:
416 else:
417 return '%d ' % rev
417 return '%d ' % rev
418 def formathex(hex):
418 def formathex(hex):
419 if hex is None:
419 if hex is None:
420 return '%s+' % fm.hexfunc(ctx.p1().node())
420 return '%s+' % fm.hexfunc(ctx.p1().node())
421 else:
421 else:
422 return '%s ' % hex
422 return '%s ' % hex
423 else:
423 else:
424 hexfn = fm.hexfunc
424 hexfn = fm.hexfunc
425 formatrev = formathex = str
425 formatrev = formathex = str
426
426
427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
428 ('number', ' ', lambda x: x[0].rev(), formatrev),
428 ('number', ' ', lambda x: x[0].rev(), formatrev),
429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
431 ('file', ' ', lambda x: x[0].path(), str),
431 ('file', ' ', lambda x: x[0].path(), str),
432 ('line_number', ':', lambda x: x[1], str),
432 ('line_number', ':', lambda x: x[1], str),
433 ]
433 ]
434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
435
435
436 if (not opts.get('user') and not opts.get('changeset')
436 if (not opts.get('user') and not opts.get('changeset')
437 and not opts.get('date') and not opts.get('file')):
437 and not opts.get('date') and not opts.get('file')):
438 opts['number'] = True
438 opts['number'] = True
439
439
440 linenumber = opts.get('line_number') is not None
440 linenumber = opts.get('line_number') is not None
441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
442 raise error.Abort(_('at least one of -n/-c is required for -l'))
442 raise error.Abort(_('at least one of -n/-c is required for -l'))
443
443
444 if fm.isplain():
444 if fm.isplain():
445 def makefunc(get, fmt):
445 def makefunc(get, fmt):
446 return lambda x: fmt(get(x))
446 return lambda x: fmt(get(x))
447 else:
447 else:
448 def makefunc(get, fmt):
448 def makefunc(get, fmt):
449 return get
449 return get
450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
451 if opts.get(op)]
451 if opts.get(op)]
452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
454 if opts.get(op))
454 if opts.get(op))
455
455
456 def bad(x, y):
456 def bad(x, y):
457 raise error.Abort("%s: %s" % (x, y))
457 raise error.Abort("%s: %s" % (x, y))
458
458
459 m = scmutil.match(ctx, pats, opts, badfn=bad)
459 m = scmutil.match(ctx, pats, opts, badfn=bad)
460
460
461 follow = not opts.get('no_follow')
461 follow = not opts.get('no_follow')
462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
463 whitespace=True)
463 whitespace=True)
464 for abs in ctx.walk(m):
464 for abs in ctx.walk(m):
465 fctx = ctx[abs]
465 fctx = ctx[abs]
466 if not opts.get('text') and util.binary(fctx.data()):
466 if not opts.get('text') and util.binary(fctx.data()):
467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
468 continue
468 continue
469
469
470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
471 diffopts=diffopts)
471 diffopts=diffopts)
472 if not lines:
472 if not lines:
473 continue
473 continue
474 formats = []
474 formats = []
475 pieces = []
475 pieces = []
476
476
477 for f, sep in funcmap:
477 for f, sep in funcmap:
478 l = [f(n) for n, dummy in lines]
478 l = [f(n) for n, dummy in lines]
479 if fm.isplain():
479 if fm.isplain():
480 sizes = [encoding.colwidth(x) for x in l]
480 sizes = [encoding.colwidth(x) for x in l]
481 ml = max(sizes)
481 ml = max(sizes)
482 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
482 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
483 else:
483 else:
484 formats.append(['%s' for x in l])
484 formats.append(['%s' for x in l])
485 pieces.append(l)
485 pieces.append(l)
486
486
487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
488 fm.startitem()
488 fm.startitem()
489 fm.write(fields, "".join(f), *p)
489 fm.write(fields, "".join(f), *p)
490 fm.write('line', ": %s", l[1])
490 fm.write('line', ": %s", l[1])
491
491
492 if not lines[-1][1].endswith('\n'):
492 if not lines[-1][1].endswith('\n'):
493 fm.plain('\n')
493 fm.plain('\n')
494
494
495 fm.end()
495 fm.end()
496
496
497 @command('archive',
497 @command('archive',
498 [('', 'no-decode', None, _('do not pass files through decoders')),
498 [('', 'no-decode', None, _('do not pass files through decoders')),
499 ('p', 'prefix', '', _('directory prefix for files in archive'),
499 ('p', 'prefix', '', _('directory prefix for files in archive'),
500 _('PREFIX')),
500 _('PREFIX')),
501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
503 ] + subrepoopts + walkopts,
503 ] + subrepoopts + walkopts,
504 _('[OPTION]... DEST'))
504 _('[OPTION]... DEST'))
505 def archive(ui, repo, dest, **opts):
505 def archive(ui, repo, dest, **opts):
506 '''create an unversioned archive of a repository revision
506 '''create an unversioned archive of a repository revision
507
507
508 By default, the revision used is the parent of the working
508 By default, the revision used is the parent of the working
509 directory; use -r/--rev to specify a different revision.
509 directory; use -r/--rev to specify a different revision.
510
510
511 The archive type is automatically detected based on file
511 The archive type is automatically detected based on file
512 extension (to override, use -t/--type).
512 extension (to override, use -t/--type).
513
513
514 .. container:: verbose
514 .. container:: verbose
515
515
516 Examples:
516 Examples:
517
517
518 - create a zip file containing the 1.0 release::
518 - create a zip file containing the 1.0 release::
519
519
520 hg archive -r 1.0 project-1.0.zip
520 hg archive -r 1.0 project-1.0.zip
521
521
522 - create a tarball excluding .hg files::
522 - create a tarball excluding .hg files::
523
523
524 hg archive project.tar.gz -X ".hg*"
524 hg archive project.tar.gz -X ".hg*"
525
525
526 Valid types are:
526 Valid types are:
527
527
528 :``files``: a directory full of files (default)
528 :``files``: a directory full of files (default)
529 :``tar``: tar archive, uncompressed
529 :``tar``: tar archive, uncompressed
530 :``tbz2``: tar archive, compressed using bzip2
530 :``tbz2``: tar archive, compressed using bzip2
531 :``tgz``: tar archive, compressed using gzip
531 :``tgz``: tar archive, compressed using gzip
532 :``uzip``: zip archive, uncompressed
532 :``uzip``: zip archive, uncompressed
533 :``zip``: zip archive, compressed using deflate
533 :``zip``: zip archive, compressed using deflate
534
534
535 The exact name of the destination archive or directory is given
535 The exact name of the destination archive or directory is given
536 using a format string; see :hg:`help export` for details.
536 using a format string; see :hg:`help export` for details.
537
537
538 Each member added to an archive file has a directory prefix
538 Each member added to an archive file has a directory prefix
539 prepended. Use -p/--prefix to specify a format string for the
539 prepended. Use -p/--prefix to specify a format string for the
540 prefix. The default is the basename of the archive, with suffixes
540 prefix. The default is the basename of the archive, with suffixes
541 removed.
541 removed.
542
542
543 Returns 0 on success.
543 Returns 0 on success.
544 '''
544 '''
545
545
546 ctx = scmutil.revsingle(repo, opts.get('rev'))
546 ctx = scmutil.revsingle(repo, opts.get('rev'))
547 if not ctx:
547 if not ctx:
548 raise error.Abort(_('no working directory: please specify a revision'))
548 raise error.Abort(_('no working directory: please specify a revision'))
549 node = ctx.node()
549 node = ctx.node()
550 dest = cmdutil.makefilename(repo, dest, node)
550 dest = cmdutil.makefilename(repo, dest, node)
551 if os.path.realpath(dest) == repo.root:
551 if os.path.realpath(dest) == repo.root:
552 raise error.Abort(_('repository root cannot be destination'))
552 raise error.Abort(_('repository root cannot be destination'))
553
553
554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
555 prefix = opts.get('prefix')
555 prefix = opts.get('prefix')
556
556
557 if dest == '-':
557 if dest == '-':
558 if kind == 'files':
558 if kind == 'files':
559 raise error.Abort(_('cannot archive plain files to stdout'))
559 raise error.Abort(_('cannot archive plain files to stdout'))
560 dest = cmdutil.makefileobj(repo, dest)
560 dest = cmdutil.makefileobj(repo, dest)
561 if not prefix:
561 if not prefix:
562 prefix = os.path.basename(repo.root) + '-%h'
562 prefix = os.path.basename(repo.root) + '-%h'
563
563
564 prefix = cmdutil.makefilename(repo, prefix, node)
564 prefix = cmdutil.makefilename(repo, prefix, node)
565 matchfn = scmutil.match(ctx, [], opts)
565 matchfn = scmutil.match(ctx, [], opts)
566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
567 matchfn, prefix, subrepos=opts.get('subrepos'))
567 matchfn, prefix, subrepos=opts.get('subrepos'))
568
568
569 @command('backout',
569 @command('backout',
570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
571 ('', 'commit', None,
571 ('', 'commit', None,
572 _('commit if no conflicts were encountered (DEPRECATED)')),
572 _('commit if no conflicts were encountered (DEPRECATED)')),
573 ('', 'no-commit', None, _('do not commit')),
573 ('', 'no-commit', None, _('do not commit')),
574 ('', 'parent', '',
574 ('', 'parent', '',
575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
576 ('r', 'rev', '', _('revision to backout'), _('REV')),
576 ('r', 'rev', '', _('revision to backout'), _('REV')),
577 ('e', 'edit', False, _('invoke editor on commit messages')),
577 ('e', 'edit', False, _('invoke editor on commit messages')),
578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
579 _('[OPTION]... [-r] REV'))
579 _('[OPTION]... [-r] REV'))
580 def backout(ui, repo, node=None, rev=None, **opts):
580 def backout(ui, repo, node=None, rev=None, **opts):
581 '''reverse effect of earlier changeset
581 '''reverse effect of earlier changeset
582
582
583 Prepare a new changeset with the effect of REV undone in the
583 Prepare a new changeset with the effect of REV undone in the
584 current working directory. If no conflicts were encountered,
584 current working directory. If no conflicts were encountered,
585 it will be committed immediately.
585 it will be committed immediately.
586
586
587 If REV is the parent of the working directory, then this new changeset
587 If REV is the parent of the working directory, then this new changeset
588 is committed automatically (unless --no-commit is specified).
588 is committed automatically (unless --no-commit is specified).
589
589
590 .. note::
590 .. note::
591
591
592 :hg:`backout` cannot be used to fix either an unwanted or
592 :hg:`backout` cannot be used to fix either an unwanted or
593 incorrect merge.
593 incorrect merge.
594
594
595 .. container:: verbose
595 .. container:: verbose
596
596
597 Examples:
597 Examples:
598
598
599 - Reverse the effect of the parent of the working directory.
599 - Reverse the effect of the parent of the working directory.
600 This backout will be committed immediately::
600 This backout will be committed immediately::
601
601
602 hg backout -r .
602 hg backout -r .
603
603
604 - Reverse the effect of previous bad revision 23::
604 - Reverse the effect of previous bad revision 23::
605
605
606 hg backout -r 23
606 hg backout -r 23
607
607
608 - Reverse the effect of previous bad revision 23 and
608 - Reverse the effect of previous bad revision 23 and
609 leave changes uncommitted::
609 leave changes uncommitted::
610
610
611 hg backout -r 23 --no-commit
611 hg backout -r 23 --no-commit
612 hg commit -m "Backout revision 23"
612 hg commit -m "Backout revision 23"
613
613
614 By default, the pending changeset will have one parent,
614 By default, the pending changeset will have one parent,
615 maintaining a linear history. With --merge, the pending
615 maintaining a linear history. With --merge, the pending
616 changeset will instead have two parents: the old parent of the
616 changeset will instead have two parents: the old parent of the
617 working directory and a new child of REV that simply undoes REV.
617 working directory and a new child of REV that simply undoes REV.
618
618
619 Before version 1.7, the behavior without --merge was equivalent
619 Before version 1.7, the behavior without --merge was equivalent
620 to specifying --merge followed by :hg:`update --clean .` to
620 to specifying --merge followed by :hg:`update --clean .` to
621 cancel the merge and leave the child of REV as a head to be
621 cancel the merge and leave the child of REV as a head to be
622 merged separately.
622 merged separately.
623
623
624 See :hg:`help dates` for a list of formats valid for -d/--date.
624 See :hg:`help dates` for a list of formats valid for -d/--date.
625
625
626 See :hg:`help revert` for a way to restore files to the state
626 See :hg:`help revert` for a way to restore files to the state
627 of another revision.
627 of another revision.
628
628
629 Returns 0 on success, 1 if nothing to backout or there are unresolved
629 Returns 0 on success, 1 if nothing to backout or there are unresolved
630 files.
630 files.
631 '''
631 '''
632 wlock = lock = None
632 wlock = lock = None
633 try:
633 try:
634 wlock = repo.wlock()
634 wlock = repo.wlock()
635 lock = repo.lock()
635 lock = repo.lock()
636 return _dobackout(ui, repo, node, rev, **opts)
636 return _dobackout(ui, repo, node, rev, **opts)
637 finally:
637 finally:
638 release(lock, wlock)
638 release(lock, wlock)
639
639
640 def _dobackout(ui, repo, node=None, rev=None, **opts):
640 def _dobackout(ui, repo, node=None, rev=None, **opts):
641 if opts.get('commit') and opts.get('no_commit'):
641 if opts.get('commit') and opts.get('no_commit'):
642 raise error.Abort(_("cannot use --commit with --no-commit"))
642 raise error.Abort(_("cannot use --commit with --no-commit"))
643 if opts.get('merge') and opts.get('no_commit'):
643 if opts.get('merge') and opts.get('no_commit'):
644 raise error.Abort(_("cannot use --merge with --no-commit"))
644 raise error.Abort(_("cannot use --merge with --no-commit"))
645
645
646 if rev and node:
646 if rev and node:
647 raise error.Abort(_("please specify just one revision"))
647 raise error.Abort(_("please specify just one revision"))
648
648
649 if not rev:
649 if not rev:
650 rev = node
650 rev = node
651
651
652 if not rev:
652 if not rev:
653 raise error.Abort(_("please specify a revision to backout"))
653 raise error.Abort(_("please specify a revision to backout"))
654
654
655 date = opts.get('date')
655 date = opts.get('date')
656 if date:
656 if date:
657 opts['date'] = util.parsedate(date)
657 opts['date'] = util.parsedate(date)
658
658
659 cmdutil.checkunfinished(repo)
659 cmdutil.checkunfinished(repo)
660 cmdutil.bailifchanged(repo)
660 cmdutil.bailifchanged(repo)
661 node = scmutil.revsingle(repo, rev).node()
661 node = scmutil.revsingle(repo, rev).node()
662
662
663 op1, op2 = repo.dirstate.parents()
663 op1, op2 = repo.dirstate.parents()
664 if not repo.changelog.isancestor(node, op1):
664 if not repo.changelog.isancestor(node, op1):
665 raise error.Abort(_('cannot backout change that is not an ancestor'))
665 raise error.Abort(_('cannot backout change that is not an ancestor'))
666
666
667 p1, p2 = repo.changelog.parents(node)
667 p1, p2 = repo.changelog.parents(node)
668 if p1 == nullid:
668 if p1 == nullid:
669 raise error.Abort(_('cannot backout a change with no parents'))
669 raise error.Abort(_('cannot backout a change with no parents'))
670 if p2 != nullid:
670 if p2 != nullid:
671 if not opts.get('parent'):
671 if not opts.get('parent'):
672 raise error.Abort(_('cannot backout a merge changeset'))
672 raise error.Abort(_('cannot backout a merge changeset'))
673 p = repo.lookup(opts['parent'])
673 p = repo.lookup(opts['parent'])
674 if p not in (p1, p2):
674 if p not in (p1, p2):
675 raise error.Abort(_('%s is not a parent of %s') %
675 raise error.Abort(_('%s is not a parent of %s') %
676 (short(p), short(node)))
676 (short(p), short(node)))
677 parent = p
677 parent = p
678 else:
678 else:
679 if opts.get('parent'):
679 if opts.get('parent'):
680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
681 parent = p1
681 parent = p1
682
682
683 # the backout should appear on the same branch
683 # the backout should appear on the same branch
684 branch = repo.dirstate.branch()
684 branch = repo.dirstate.branch()
685 bheads = repo.branchheads(branch)
685 bheads = repo.branchheads(branch)
686 rctx = scmutil.revsingle(repo, hex(parent))
686 rctx = scmutil.revsingle(repo, hex(parent))
687 if not opts.get('merge') and op1 != node:
687 if not opts.get('merge') and op1 != node:
688 dsguard = cmdutil.dirstateguard(repo, 'backout')
688 dsguard = cmdutil.dirstateguard(repo, 'backout')
689 try:
689 try:
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
691 'backout')
691 'backout')
692 stats = mergemod.update(repo, parent, True, True, node, False)
692 stats = mergemod.update(repo, parent, True, True, node, False)
693 repo.setparents(op1, op2)
693 repo.setparents(op1, op2)
694 dsguard.close()
694 dsguard.close()
695 hg._showstats(repo, stats)
695 hg._showstats(repo, stats)
696 if stats[3]:
696 if stats[3]:
697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
698 "file merges\n"))
698 "file merges\n"))
699 return 1
699 return 1
700 finally:
700 finally:
701 ui.setconfig('ui', 'forcemerge', '', '')
701 ui.setconfig('ui', 'forcemerge', '', '')
702 lockmod.release(dsguard)
702 lockmod.release(dsguard)
703 else:
703 else:
704 hg.clean(repo, node, show_stats=False)
704 hg.clean(repo, node, show_stats=False)
705 repo.dirstate.setbranch(branch)
705 repo.dirstate.setbranch(branch)
706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
707
707
708 if opts.get('no_commit'):
708 if opts.get('no_commit'):
709 msg = _("changeset %s backed out, "
709 msg = _("changeset %s backed out, "
710 "don't forget to commit.\n")
710 "don't forget to commit.\n")
711 ui.status(msg % short(node))
711 ui.status(msg % short(node))
712 return 0
712 return 0
713
713
714 def commitfunc(ui, repo, message, match, opts):
714 def commitfunc(ui, repo, message, match, opts):
715 editform = 'backout'
715 editform = 'backout'
716 e = cmdutil.getcommiteditor(editform=editform, **opts)
716 e = cmdutil.getcommiteditor(editform=editform, **opts)
717 if not message:
717 if not message:
718 # we don't translate commit messages
718 # we don't translate commit messages
719 message = "Backed out changeset %s" % short(node)
719 message = "Backed out changeset %s" % short(node)
720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
721 return repo.commit(message, opts.get('user'), opts.get('date'),
721 return repo.commit(message, opts.get('user'), opts.get('date'),
722 match, editor=e)
722 match, editor=e)
723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
724 if not newnode:
724 if not newnode:
725 ui.status(_("nothing changed\n"))
725 ui.status(_("nothing changed\n"))
726 return 1
726 return 1
727 cmdutil.commitstatus(repo, newnode, branch, bheads)
727 cmdutil.commitstatus(repo, newnode, branch, bheads)
728
728
729 def nice(node):
729 def nice(node):
730 return '%d:%s' % (repo.changelog.rev(node), short(node))
730 return '%d:%s' % (repo.changelog.rev(node), short(node))
731 ui.status(_('changeset %s backs out changeset %s\n') %
731 ui.status(_('changeset %s backs out changeset %s\n') %
732 (nice(repo.changelog.tip()), nice(node)))
732 (nice(repo.changelog.tip()), nice(node)))
733 if opts.get('merge') and op1 != node:
733 if opts.get('merge') and op1 != node:
734 hg.clean(repo, op1, show_stats=False)
734 hg.clean(repo, op1, show_stats=False)
735 ui.status(_('merging with changeset %s\n')
735 ui.status(_('merging with changeset %s\n')
736 % nice(repo.changelog.tip()))
736 % nice(repo.changelog.tip()))
737 try:
737 try:
738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
739 'backout')
739 'backout')
740 return hg.merge(repo, hex(repo.changelog.tip()))
740 return hg.merge(repo, hex(repo.changelog.tip()))
741 finally:
741 finally:
742 ui.setconfig('ui', 'forcemerge', '', '')
742 ui.setconfig('ui', 'forcemerge', '', '')
743 return 0
743 return 0
744
744
745 @command('bisect',
745 @command('bisect',
746 [('r', 'reset', False, _('reset bisect state')),
746 [('r', 'reset', False, _('reset bisect state')),
747 ('g', 'good', False, _('mark changeset good')),
747 ('g', 'good', False, _('mark changeset good')),
748 ('b', 'bad', False, _('mark changeset bad')),
748 ('b', 'bad', False, _('mark changeset bad')),
749 ('s', 'skip', False, _('skip testing changeset')),
749 ('s', 'skip', False, _('skip testing changeset')),
750 ('e', 'extend', False, _('extend the bisect range')),
750 ('e', 'extend', False, _('extend the bisect range')),
751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
752 ('U', 'noupdate', False, _('do not update to target'))],
752 ('U', 'noupdate', False, _('do not update to target'))],
753 _("[-gbsr] [-U] [-c CMD] [REV]"))
753 _("[-gbsr] [-U] [-c CMD] [REV]"))
754 def bisect(ui, repo, rev=None, extra=None, command=None,
754 def bisect(ui, repo, rev=None, extra=None, command=None,
755 reset=None, good=None, bad=None, skip=None, extend=None,
755 reset=None, good=None, bad=None, skip=None, extend=None,
756 noupdate=None):
756 noupdate=None):
757 """subdivision search of changesets
757 """subdivision search of changesets
758
758
759 This command helps to find changesets which introduce problems. To
759 This command helps to find changesets which introduce problems. To
760 use, mark the earliest changeset you know exhibits the problem as
760 use, mark the earliest changeset you know exhibits the problem as
761 bad, then mark the latest changeset which is free from the problem
761 bad, then mark the latest changeset which is free from the problem
762 as good. Bisect will update your working directory to a revision
762 as good. Bisect will update your working directory to a revision
763 for testing (unless the -U/--noupdate option is specified). Once
763 for testing (unless the -U/--noupdate option is specified). Once
764 you have performed tests, mark the working directory as good or
764 you have performed tests, mark the working directory as good or
765 bad, and bisect will either update to another candidate changeset
765 bad, and bisect will either update to another candidate changeset
766 or announce that it has found the bad revision.
766 or announce that it has found the bad revision.
767
767
768 As a shortcut, you can also use the revision argument to mark a
768 As a shortcut, you can also use the revision argument to mark a
769 revision as good or bad without checking it out first.
769 revision as good or bad without checking it out first.
770
770
771 If you supply a command, it will be used for automatic bisection.
771 If you supply a command, it will be used for automatic bisection.
772 The environment variable HG_NODE will contain the ID of the
772 The environment variable HG_NODE will contain the ID of the
773 changeset being tested. The exit status of the command will be
773 changeset being tested. The exit status of the command will be
774 used to mark revisions as good or bad: status 0 means good, 125
774 used to mark revisions as good or bad: status 0 means good, 125
775 means to skip the revision, 127 (command not found) will abort the
775 means to skip the revision, 127 (command not found) will abort the
776 bisection, and any other non-zero exit status means the revision
776 bisection, and any other non-zero exit status means the revision
777 is bad.
777 is bad.
778
778
779 .. container:: verbose
779 .. container:: verbose
780
780
781 Some examples:
781 Some examples:
782
782
783 - start a bisection with known bad revision 34, and good revision 12::
783 - start a bisection with known bad revision 34, and good revision 12::
784
784
785 hg bisect --bad 34
785 hg bisect --bad 34
786 hg bisect --good 12
786 hg bisect --good 12
787
787
788 - advance the current bisection by marking current revision as good or
788 - advance the current bisection by marking current revision as good or
789 bad::
789 bad::
790
790
791 hg bisect --good
791 hg bisect --good
792 hg bisect --bad
792 hg bisect --bad
793
793
794 - mark the current revision, or a known revision, to be skipped (e.g. if
794 - mark the current revision, or a known revision, to be skipped (e.g. if
795 that revision is not usable because of another issue)::
795 that revision is not usable because of another issue)::
796
796
797 hg bisect --skip
797 hg bisect --skip
798 hg bisect --skip 23
798 hg bisect --skip 23
799
799
800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
801
801
802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
803
803
804 - forget the current bisection::
804 - forget the current bisection::
805
805
806 hg bisect --reset
806 hg bisect --reset
807
807
808 - use 'make && make tests' to automatically find the first broken
808 - use 'make && make tests' to automatically find the first broken
809 revision::
809 revision::
810
810
811 hg bisect --reset
811 hg bisect --reset
812 hg bisect --bad 34
812 hg bisect --bad 34
813 hg bisect --good 12
813 hg bisect --good 12
814 hg bisect --command "make && make tests"
814 hg bisect --command "make && make tests"
815
815
816 - see all changesets whose states are already known in the current
816 - see all changesets whose states are already known in the current
817 bisection::
817 bisection::
818
818
819 hg log -r "bisect(pruned)"
819 hg log -r "bisect(pruned)"
820
820
821 - see the changeset currently being bisected (especially useful
821 - see the changeset currently being bisected (especially useful
822 if running with -U/--noupdate)::
822 if running with -U/--noupdate)::
823
823
824 hg log -r "bisect(current)"
824 hg log -r "bisect(current)"
825
825
826 - see all changesets that took part in the current bisection::
826 - see all changesets that took part in the current bisection::
827
827
828 hg log -r "bisect(range)"
828 hg log -r "bisect(range)"
829
829
830 - you can even get a nice graph::
830 - you can even get a nice graph::
831
831
832 hg log --graph -r "bisect(range)"
832 hg log --graph -r "bisect(range)"
833
833
834 See :hg:`help revsets` for more about the `bisect()` keyword.
834 See :hg:`help revsets` for more about the `bisect()` keyword.
835
835
836 Returns 0 on success.
836 Returns 0 on success.
837 """
837 """
838 def extendbisectrange(nodes, good):
839 # bisect is incomplete when it ends on a merge node and
840 # one of the parent was not checked.
841 parents = repo[nodes[0]].parents()
842 if len(parents) > 1:
843 if good:
844 side = state['bad']
845 else:
846 side = state['good']
847 num = len(set(i.node() for i in parents) & set(side))
848 if num == 1:
849 return parents[0].ancestor(parents[1])
850 return None
851
852 def print_result(nodes, good):
838 def print_result(nodes, good):
853 displayer = cmdutil.show_changeset(ui, repo, {})
839 displayer = cmdutil.show_changeset(ui, repo, {})
854 if len(nodes) == 1:
840 if len(nodes) == 1:
855 # narrowed it down to a single revision
841 # narrowed it down to a single revision
856 if good:
842 if good:
857 ui.write(_("The first good revision is:\n"))
843 ui.write(_("The first good revision is:\n"))
858 else:
844 else:
859 ui.write(_("The first bad revision is:\n"))
845 ui.write(_("The first bad revision is:\n"))
860 displayer.show(repo[nodes[0]])
846 displayer.show(repo[nodes[0]])
861 extendnode = extendbisectrange(nodes, good)
847 extendnode = hbisect.extendrange(repo, state, nodes, good)
862 if extendnode is not None:
848 if extendnode is not None:
863 ui.write(_('Not all ancestors of this changeset have been'
849 ui.write(_('Not all ancestors of this changeset have been'
864 ' checked.\nUse bisect --extend to continue the '
850 ' checked.\nUse bisect --extend to continue the '
865 'bisection from\nthe common ancestor, %s.\n')
851 'bisection from\nthe common ancestor, %s.\n')
866 % extendnode)
852 % extendnode)
867 else:
853 else:
868 # multiple possible revisions
854 # multiple possible revisions
869 if good:
855 if good:
870 ui.write(_("Due to skipped revisions, the first "
856 ui.write(_("Due to skipped revisions, the first "
871 "good revision could be any of:\n"))
857 "good revision could be any of:\n"))
872 else:
858 else:
873 ui.write(_("Due to skipped revisions, the first "
859 ui.write(_("Due to skipped revisions, the first "
874 "bad revision could be any of:\n"))
860 "bad revision could be any of:\n"))
875 for n in nodes:
861 for n in nodes:
876 displayer.show(repo[n])
862 displayer.show(repo[n])
877 displayer.close()
863 displayer.close()
878
864
879 def check_state(state, interactive=True):
865 def check_state(state, interactive=True):
880 if not state['good'] or not state['bad']:
866 if not state['good'] or not state['bad']:
881 if (good or bad or skip or reset) and interactive:
867 if (good or bad or skip or reset) and interactive:
882 return
868 return
883 if not state['good']:
869 if not state['good']:
884 raise error.Abort(_('cannot bisect (no known good revisions)'))
870 raise error.Abort(_('cannot bisect (no known good revisions)'))
885 else:
871 else:
886 raise error.Abort(_('cannot bisect (no known bad revisions)'))
872 raise error.Abort(_('cannot bisect (no known bad revisions)'))
887 return True
873 return True
888
874
889 # backward compatibility
875 # backward compatibility
890 if rev in "good bad reset init".split():
876 if rev in "good bad reset init".split():
891 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
877 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
892 cmd, rev, extra = rev, extra, None
878 cmd, rev, extra = rev, extra, None
893 if cmd == "good":
879 if cmd == "good":
894 good = True
880 good = True
895 elif cmd == "bad":
881 elif cmd == "bad":
896 bad = True
882 bad = True
897 else:
883 else:
898 reset = True
884 reset = True
899 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
885 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
900 raise error.Abort(_('incompatible arguments'))
886 raise error.Abort(_('incompatible arguments'))
901
887
902 cmdutil.checkunfinished(repo)
888 cmdutil.checkunfinished(repo)
903
889
904 if reset:
890 if reset:
905 hbisect.resetstate(repo)
891 hbisect.resetstate(repo)
906 return
892 return
907
893
908 state = hbisect.load_state(repo)
894 state = hbisect.load_state(repo)
909
895
910 if command:
896 if command:
911 changesets = 1
897 changesets = 1
912 if noupdate:
898 if noupdate:
913 try:
899 try:
914 node = state['current'][0]
900 node = state['current'][0]
915 except LookupError:
901 except LookupError:
916 raise error.Abort(_('current bisect revision is unknown - '
902 raise error.Abort(_('current bisect revision is unknown - '
917 'start a new bisect to fix'))
903 'start a new bisect to fix'))
918 else:
904 else:
919 node, p2 = repo.dirstate.parents()
905 node, p2 = repo.dirstate.parents()
920 if p2 != nullid:
906 if p2 != nullid:
921 raise error.Abort(_('current bisect revision is a merge'))
907 raise error.Abort(_('current bisect revision is a merge'))
922 try:
908 try:
923 while changesets:
909 while changesets:
924 # update state
910 # update state
925 state['current'] = [node]
911 state['current'] = [node]
926 hbisect.save_state(repo, state)
912 hbisect.save_state(repo, state)
927 status = ui.system(command, environ={'HG_NODE': hex(node)})
913 status = ui.system(command, environ={'HG_NODE': hex(node)})
928 if status == 125:
914 if status == 125:
929 transition = "skip"
915 transition = "skip"
930 elif status == 0:
916 elif status == 0:
931 transition = "good"
917 transition = "good"
932 # status < 0 means process was killed
918 # status < 0 means process was killed
933 elif status == 127:
919 elif status == 127:
934 raise error.Abort(_("failed to execute %s") % command)
920 raise error.Abort(_("failed to execute %s") % command)
935 elif status < 0:
921 elif status < 0:
936 raise error.Abort(_("%s killed") % command)
922 raise error.Abort(_("%s killed") % command)
937 else:
923 else:
938 transition = "bad"
924 transition = "bad"
939 ctx = scmutil.revsingle(repo, rev, node)
925 ctx = scmutil.revsingle(repo, rev, node)
940 rev = None # clear for future iterations
926 rev = None # clear for future iterations
941 state[transition].append(ctx.node())
927 state[transition].append(ctx.node())
942 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
928 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
943 check_state(state, interactive=False)
929 check_state(state, interactive=False)
944 # bisect
930 # bisect
945 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
931 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
946 # update to next check
932 # update to next check
947 node = nodes[0]
933 node = nodes[0]
948 if not noupdate:
934 if not noupdate:
949 cmdutil.bailifchanged(repo)
935 cmdutil.bailifchanged(repo)
950 hg.clean(repo, node, show_stats=False)
936 hg.clean(repo, node, show_stats=False)
951 finally:
937 finally:
952 state['current'] = [node]
938 state['current'] = [node]
953 hbisect.save_state(repo, state)
939 hbisect.save_state(repo, state)
954 print_result(nodes, bgood)
940 print_result(nodes, bgood)
955 return
941 return
956
942
957 # update state
943 # update state
958
944
959 if rev:
945 if rev:
960 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
946 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
961 else:
947 else:
962 nodes = [repo.lookup('.')]
948 nodes = [repo.lookup('.')]
963
949
964 if good or bad or skip:
950 if good or bad or skip:
965 if good:
951 if good:
966 state['good'] += nodes
952 state['good'] += nodes
967 elif bad:
953 elif bad:
968 state['bad'] += nodes
954 state['bad'] += nodes
969 elif skip:
955 elif skip:
970 state['skip'] += nodes
956 state['skip'] += nodes
971 hbisect.save_state(repo, state)
957 hbisect.save_state(repo, state)
972
958
973 if not check_state(state):
959 if not check_state(state):
974 return
960 return
975
961
976 # actually bisect
962 # actually bisect
977 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
963 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
978 if extend:
964 if extend:
979 if not changesets:
965 if not changesets:
980 extendnode = extendbisectrange(nodes, good)
966 extendnode = hbisect.extendrange(repo, state, nodes, good)
981 if extendnode is not None:
967 if extendnode is not None:
982 ui.write(_("Extending search to changeset %d:%s\n")
968 ui.write(_("Extending search to changeset %d:%s\n")
983 % (extendnode.rev(), extendnode))
969 % (extendnode.rev(), extendnode))
984 state['current'] = [extendnode.node()]
970 state['current'] = [extendnode.node()]
985 hbisect.save_state(repo, state)
971 hbisect.save_state(repo, state)
986 if noupdate:
972 if noupdate:
987 return
973 return
988 cmdutil.bailifchanged(repo)
974 cmdutil.bailifchanged(repo)
989 return hg.clean(repo, extendnode.node())
975 return hg.clean(repo, extendnode.node())
990 raise error.Abort(_("nothing to extend"))
976 raise error.Abort(_("nothing to extend"))
991
977
992 if changesets == 0:
978 if changesets == 0:
993 print_result(nodes, good)
979 print_result(nodes, good)
994 else:
980 else:
995 assert len(nodes) == 1 # only a single node can be tested next
981 assert len(nodes) == 1 # only a single node can be tested next
996 node = nodes[0]
982 node = nodes[0]
997 # compute the approximate number of remaining tests
983 # compute the approximate number of remaining tests
998 tests, size = 0, 2
984 tests, size = 0, 2
999 while size <= changesets:
985 while size <= changesets:
1000 tests, size = tests + 1, size * 2
986 tests, size = tests + 1, size * 2
1001 rev = repo.changelog.rev(node)
987 rev = repo.changelog.rev(node)
1002 ui.write(_("Testing changeset %d:%s "
988 ui.write(_("Testing changeset %d:%s "
1003 "(%d changesets remaining, ~%d tests)\n")
989 "(%d changesets remaining, ~%d tests)\n")
1004 % (rev, short(node), changesets, tests))
990 % (rev, short(node), changesets, tests))
1005 state['current'] = [node]
991 state['current'] = [node]
1006 hbisect.save_state(repo, state)
992 hbisect.save_state(repo, state)
1007 if not noupdate:
993 if not noupdate:
1008 cmdutil.bailifchanged(repo)
994 cmdutil.bailifchanged(repo)
1009 return hg.clean(repo, node)
995 return hg.clean(repo, node)
1010
996
1011 @command('bookmarks|bookmark',
997 @command('bookmarks|bookmark',
1012 [('f', 'force', False, _('force')),
998 [('f', 'force', False, _('force')),
1013 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
999 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
1014 ('d', 'delete', False, _('delete a given bookmark')),
1000 ('d', 'delete', False, _('delete a given bookmark')),
1015 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
1001 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
1016 ('i', 'inactive', False, _('mark a bookmark inactive')),
1002 ('i', 'inactive', False, _('mark a bookmark inactive')),
1017 ] + formatteropts,
1003 ] + formatteropts,
1018 _('hg bookmarks [OPTIONS]... [NAME]...'))
1004 _('hg bookmarks [OPTIONS]... [NAME]...'))
1019 def bookmark(ui, repo, *names, **opts):
1005 def bookmark(ui, repo, *names, **opts):
1020 '''create a new bookmark or list existing bookmarks
1006 '''create a new bookmark or list existing bookmarks
1021
1007
1022 Bookmarks are labels on changesets to help track lines of development.
1008 Bookmarks are labels on changesets to help track lines of development.
1023 Bookmarks are unversioned and can be moved, renamed and deleted.
1009 Bookmarks are unversioned and can be moved, renamed and deleted.
1024 Deleting or moving a bookmark has no effect on the associated changesets.
1010 Deleting or moving a bookmark has no effect on the associated changesets.
1025
1011
1026 Creating or updating to a bookmark causes it to be marked as 'active'.
1012 Creating or updating to a bookmark causes it to be marked as 'active'.
1027 The active bookmark is indicated with a '*'.
1013 The active bookmark is indicated with a '*'.
1028 When a commit is made, the active bookmark will advance to the new commit.
1014 When a commit is made, the active bookmark will advance to the new commit.
1029 A plain :hg:`update` will also advance an active bookmark, if possible.
1015 A plain :hg:`update` will also advance an active bookmark, if possible.
1030 Updating away from a bookmark will cause it to be deactivated.
1016 Updating away from a bookmark will cause it to be deactivated.
1031
1017
1032 Bookmarks can be pushed and pulled between repositories (see
1018 Bookmarks can be pushed and pulled between repositories (see
1033 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1019 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1034 diverged, a new 'divergent bookmark' of the form 'name@path' will
1020 diverged, a new 'divergent bookmark' of the form 'name@path' will
1035 be created. Using :hg:`merge` will resolve the divergence.
1021 be created. Using :hg:`merge` will resolve the divergence.
1036
1022
1037 A bookmark named '@' has the special property that :hg:`clone` will
1023 A bookmark named '@' has the special property that :hg:`clone` will
1038 check it out by default if it exists.
1024 check it out by default if it exists.
1039
1025
1040 .. container:: verbose
1026 .. container:: verbose
1041
1027
1042 Examples:
1028 Examples:
1043
1029
1044 - create an active bookmark for a new line of development::
1030 - create an active bookmark for a new line of development::
1045
1031
1046 hg book new-feature
1032 hg book new-feature
1047
1033
1048 - create an inactive bookmark as a place marker::
1034 - create an inactive bookmark as a place marker::
1049
1035
1050 hg book -i reviewed
1036 hg book -i reviewed
1051
1037
1052 - create an inactive bookmark on another changeset::
1038 - create an inactive bookmark on another changeset::
1053
1039
1054 hg book -r .^ tested
1040 hg book -r .^ tested
1055
1041
1056 - rename bookmark turkey to dinner::
1042 - rename bookmark turkey to dinner::
1057
1043
1058 hg book -m turkey dinner
1044 hg book -m turkey dinner
1059
1045
1060 - move the '@' bookmark from another branch::
1046 - move the '@' bookmark from another branch::
1061
1047
1062 hg book -f @
1048 hg book -f @
1063 '''
1049 '''
1064 force = opts.get('force')
1050 force = opts.get('force')
1065 rev = opts.get('rev')
1051 rev = opts.get('rev')
1066 delete = opts.get('delete')
1052 delete = opts.get('delete')
1067 rename = opts.get('rename')
1053 rename = opts.get('rename')
1068 inactive = opts.get('inactive')
1054 inactive = opts.get('inactive')
1069
1055
1070 def checkformat(mark):
1056 def checkformat(mark):
1071 mark = mark.strip()
1057 mark = mark.strip()
1072 if not mark:
1058 if not mark:
1073 raise error.Abort(_("bookmark names cannot consist entirely of "
1059 raise error.Abort(_("bookmark names cannot consist entirely of "
1074 "whitespace"))
1060 "whitespace"))
1075 scmutil.checknewlabel(repo, mark, 'bookmark')
1061 scmutil.checknewlabel(repo, mark, 'bookmark')
1076 return mark
1062 return mark
1077
1063
1078 def checkconflict(repo, mark, cur, force=False, target=None):
1064 def checkconflict(repo, mark, cur, force=False, target=None):
1079 if mark in marks and not force:
1065 if mark in marks and not force:
1080 if target:
1066 if target:
1081 if marks[mark] == target and target == cur:
1067 if marks[mark] == target and target == cur:
1082 # re-activating a bookmark
1068 # re-activating a bookmark
1083 return
1069 return
1084 anc = repo.changelog.ancestors([repo[target].rev()])
1070 anc = repo.changelog.ancestors([repo[target].rev()])
1085 bmctx = repo[marks[mark]]
1071 bmctx = repo[marks[mark]]
1086 divs = [repo[b].node() for b in marks
1072 divs = [repo[b].node() for b in marks
1087 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1073 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1088
1074
1089 # allow resolving a single divergent bookmark even if moving
1075 # allow resolving a single divergent bookmark even if moving
1090 # the bookmark across branches when a revision is specified
1076 # the bookmark across branches when a revision is specified
1091 # that contains a divergent bookmark
1077 # that contains a divergent bookmark
1092 if bmctx.rev() not in anc and target in divs:
1078 if bmctx.rev() not in anc and target in divs:
1093 bookmarks.deletedivergent(repo, [target], mark)
1079 bookmarks.deletedivergent(repo, [target], mark)
1094 return
1080 return
1095
1081
1096 deletefrom = [b for b in divs
1082 deletefrom = [b for b in divs
1097 if repo[b].rev() in anc or b == target]
1083 if repo[b].rev() in anc or b == target]
1098 bookmarks.deletedivergent(repo, deletefrom, mark)
1084 bookmarks.deletedivergent(repo, deletefrom, mark)
1099 if bookmarks.validdest(repo, bmctx, repo[target]):
1085 if bookmarks.validdest(repo, bmctx, repo[target]):
1100 ui.status(_("moving bookmark '%s' forward from %s\n") %
1086 ui.status(_("moving bookmark '%s' forward from %s\n") %
1101 (mark, short(bmctx.node())))
1087 (mark, short(bmctx.node())))
1102 return
1088 return
1103 raise error.Abort(_("bookmark '%s' already exists "
1089 raise error.Abort(_("bookmark '%s' already exists "
1104 "(use -f to force)") % mark)
1090 "(use -f to force)") % mark)
1105 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1091 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1106 and not force):
1092 and not force):
1107 raise error.Abort(
1093 raise error.Abort(
1108 _("a bookmark cannot have the name of an existing branch"))
1094 _("a bookmark cannot have the name of an existing branch"))
1109
1095
1110 if delete and rename:
1096 if delete and rename:
1111 raise error.Abort(_("--delete and --rename are incompatible"))
1097 raise error.Abort(_("--delete and --rename are incompatible"))
1112 if delete and rev:
1098 if delete and rev:
1113 raise error.Abort(_("--rev is incompatible with --delete"))
1099 raise error.Abort(_("--rev is incompatible with --delete"))
1114 if rename and rev:
1100 if rename and rev:
1115 raise error.Abort(_("--rev is incompatible with --rename"))
1101 raise error.Abort(_("--rev is incompatible with --rename"))
1116 if not names and (delete or rev):
1102 if not names and (delete or rev):
1117 raise error.Abort(_("bookmark name required"))
1103 raise error.Abort(_("bookmark name required"))
1118
1104
1119 if delete or rename or names or inactive:
1105 if delete or rename or names or inactive:
1120 wlock = lock = tr = None
1106 wlock = lock = tr = None
1121 try:
1107 try:
1122 wlock = repo.wlock()
1108 wlock = repo.wlock()
1123 lock = repo.lock()
1109 lock = repo.lock()
1124 cur = repo.changectx('.').node()
1110 cur = repo.changectx('.').node()
1125 marks = repo._bookmarks
1111 marks = repo._bookmarks
1126 if delete:
1112 if delete:
1127 tr = repo.transaction('bookmark')
1113 tr = repo.transaction('bookmark')
1128 for mark in names:
1114 for mark in names:
1129 if mark not in marks:
1115 if mark not in marks:
1130 raise error.Abort(_("bookmark '%s' does not exist") %
1116 raise error.Abort(_("bookmark '%s' does not exist") %
1131 mark)
1117 mark)
1132 if mark == repo._activebookmark:
1118 if mark == repo._activebookmark:
1133 bookmarks.deactivate(repo)
1119 bookmarks.deactivate(repo)
1134 del marks[mark]
1120 del marks[mark]
1135
1121
1136 elif rename:
1122 elif rename:
1137 tr = repo.transaction('bookmark')
1123 tr = repo.transaction('bookmark')
1138 if not names:
1124 if not names:
1139 raise error.Abort(_("new bookmark name required"))
1125 raise error.Abort(_("new bookmark name required"))
1140 elif len(names) > 1:
1126 elif len(names) > 1:
1141 raise error.Abort(_("only one new bookmark name allowed"))
1127 raise error.Abort(_("only one new bookmark name allowed"))
1142 mark = checkformat(names[0])
1128 mark = checkformat(names[0])
1143 if rename not in marks:
1129 if rename not in marks:
1144 raise error.Abort(_("bookmark '%s' does not exist")
1130 raise error.Abort(_("bookmark '%s' does not exist")
1145 % rename)
1131 % rename)
1146 checkconflict(repo, mark, cur, force)
1132 checkconflict(repo, mark, cur, force)
1147 marks[mark] = marks[rename]
1133 marks[mark] = marks[rename]
1148 if repo._activebookmark == rename and not inactive:
1134 if repo._activebookmark == rename and not inactive:
1149 bookmarks.activate(repo, mark)
1135 bookmarks.activate(repo, mark)
1150 del marks[rename]
1136 del marks[rename]
1151 elif names:
1137 elif names:
1152 tr = repo.transaction('bookmark')
1138 tr = repo.transaction('bookmark')
1153 newact = None
1139 newact = None
1154 for mark in names:
1140 for mark in names:
1155 mark = checkformat(mark)
1141 mark = checkformat(mark)
1156 if newact is None:
1142 if newact is None:
1157 newact = mark
1143 newact = mark
1158 if inactive and mark == repo._activebookmark:
1144 if inactive and mark == repo._activebookmark:
1159 bookmarks.deactivate(repo)
1145 bookmarks.deactivate(repo)
1160 return
1146 return
1161 tgt = cur
1147 tgt = cur
1162 if rev:
1148 if rev:
1163 tgt = scmutil.revsingle(repo, rev).node()
1149 tgt = scmutil.revsingle(repo, rev).node()
1164 checkconflict(repo, mark, cur, force, tgt)
1150 checkconflict(repo, mark, cur, force, tgt)
1165 marks[mark] = tgt
1151 marks[mark] = tgt
1166 if not inactive and cur == marks[newact] and not rev:
1152 if not inactive and cur == marks[newact] and not rev:
1167 bookmarks.activate(repo, newact)
1153 bookmarks.activate(repo, newact)
1168 elif cur != tgt and newact == repo._activebookmark:
1154 elif cur != tgt and newact == repo._activebookmark:
1169 bookmarks.deactivate(repo)
1155 bookmarks.deactivate(repo)
1170 elif inactive:
1156 elif inactive:
1171 if len(marks) == 0:
1157 if len(marks) == 0:
1172 ui.status(_("no bookmarks set\n"))
1158 ui.status(_("no bookmarks set\n"))
1173 elif not repo._activebookmark:
1159 elif not repo._activebookmark:
1174 ui.status(_("no active bookmark\n"))
1160 ui.status(_("no active bookmark\n"))
1175 else:
1161 else:
1176 bookmarks.deactivate(repo)
1162 bookmarks.deactivate(repo)
1177 if tr is not None:
1163 if tr is not None:
1178 marks.recordchange(tr)
1164 marks.recordchange(tr)
1179 tr.close()
1165 tr.close()
1180 finally:
1166 finally:
1181 lockmod.release(tr, lock, wlock)
1167 lockmod.release(tr, lock, wlock)
1182 else: # show bookmarks
1168 else: # show bookmarks
1183 fm = ui.formatter('bookmarks', opts)
1169 fm = ui.formatter('bookmarks', opts)
1184 hexfn = fm.hexfunc
1170 hexfn = fm.hexfunc
1185 marks = repo._bookmarks
1171 marks = repo._bookmarks
1186 if len(marks) == 0 and fm.isplain():
1172 if len(marks) == 0 and fm.isplain():
1187 ui.status(_("no bookmarks set\n"))
1173 ui.status(_("no bookmarks set\n"))
1188 for bmark, n in sorted(marks.iteritems()):
1174 for bmark, n in sorted(marks.iteritems()):
1189 active = repo._activebookmark
1175 active = repo._activebookmark
1190 if bmark == active:
1176 if bmark == active:
1191 prefix, label = '*', activebookmarklabel
1177 prefix, label = '*', activebookmarklabel
1192 else:
1178 else:
1193 prefix, label = ' ', ''
1179 prefix, label = ' ', ''
1194
1180
1195 fm.startitem()
1181 fm.startitem()
1196 if not ui.quiet:
1182 if not ui.quiet:
1197 fm.plain(' %s ' % prefix, label=label)
1183 fm.plain(' %s ' % prefix, label=label)
1198 fm.write('bookmark', '%s', bmark, label=label)
1184 fm.write('bookmark', '%s', bmark, label=label)
1199 pad = " " * (25 - encoding.colwidth(bmark))
1185 pad = " " * (25 - encoding.colwidth(bmark))
1200 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1186 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1201 repo.changelog.rev(n), hexfn(n), label=label)
1187 repo.changelog.rev(n), hexfn(n), label=label)
1202 fm.data(active=(bmark == active))
1188 fm.data(active=(bmark == active))
1203 fm.plain('\n')
1189 fm.plain('\n')
1204 fm.end()
1190 fm.end()
1205
1191
1206 @command('branch',
1192 @command('branch',
1207 [('f', 'force', None,
1193 [('f', 'force', None,
1208 _('set branch name even if it shadows an existing branch')),
1194 _('set branch name even if it shadows an existing branch')),
1209 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1195 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1210 _('[-fC] [NAME]'))
1196 _('[-fC] [NAME]'))
1211 def branch(ui, repo, label=None, **opts):
1197 def branch(ui, repo, label=None, **opts):
1212 """set or show the current branch name
1198 """set or show the current branch name
1213
1199
1214 .. note::
1200 .. note::
1215
1201
1216 Branch names are permanent and global. Use :hg:`bookmark` to create a
1202 Branch names are permanent and global. Use :hg:`bookmark` to create a
1217 light-weight bookmark instead. See :hg:`help glossary` for more
1203 light-weight bookmark instead. See :hg:`help glossary` for more
1218 information about named branches and bookmarks.
1204 information about named branches and bookmarks.
1219
1205
1220 With no argument, show the current branch name. With one argument,
1206 With no argument, show the current branch name. With one argument,
1221 set the working directory branch name (the branch will not exist
1207 set the working directory branch name (the branch will not exist
1222 in the repository until the next commit). Standard practice
1208 in the repository until the next commit). Standard practice
1223 recommends that primary development take place on the 'default'
1209 recommends that primary development take place on the 'default'
1224 branch.
1210 branch.
1225
1211
1226 Unless -f/--force is specified, branch will not let you set a
1212 Unless -f/--force is specified, branch will not let you set a
1227 branch name that already exists.
1213 branch name that already exists.
1228
1214
1229 Use -C/--clean to reset the working directory branch to that of
1215 Use -C/--clean to reset the working directory branch to that of
1230 the parent of the working directory, negating a previous branch
1216 the parent of the working directory, negating a previous branch
1231 change.
1217 change.
1232
1218
1233 Use the command :hg:`update` to switch to an existing branch. Use
1219 Use the command :hg:`update` to switch to an existing branch. Use
1234 :hg:`commit --close-branch` to mark this branch head as closed.
1220 :hg:`commit --close-branch` to mark this branch head as closed.
1235 When all heads of a branch are closed, the branch will be
1221 When all heads of a branch are closed, the branch will be
1236 considered closed.
1222 considered closed.
1237
1223
1238 Returns 0 on success.
1224 Returns 0 on success.
1239 """
1225 """
1240 if label:
1226 if label:
1241 label = label.strip()
1227 label = label.strip()
1242
1228
1243 if not opts.get('clean') and not label:
1229 if not opts.get('clean') and not label:
1244 ui.write("%s\n" % repo.dirstate.branch())
1230 ui.write("%s\n" % repo.dirstate.branch())
1245 return
1231 return
1246
1232
1247 with repo.wlock():
1233 with repo.wlock():
1248 if opts.get('clean'):
1234 if opts.get('clean'):
1249 label = repo[None].p1().branch()
1235 label = repo[None].p1().branch()
1250 repo.dirstate.setbranch(label)
1236 repo.dirstate.setbranch(label)
1251 ui.status(_('reset working directory to branch %s\n') % label)
1237 ui.status(_('reset working directory to branch %s\n') % label)
1252 elif label:
1238 elif label:
1253 if not opts.get('force') and label in repo.branchmap():
1239 if not opts.get('force') and label in repo.branchmap():
1254 if label not in [p.branch() for p in repo[None].parents()]:
1240 if label not in [p.branch() for p in repo[None].parents()]:
1255 raise error.Abort(_('a branch of the same name already'
1241 raise error.Abort(_('a branch of the same name already'
1256 ' exists'),
1242 ' exists'),
1257 # i18n: "it" refers to an existing branch
1243 # i18n: "it" refers to an existing branch
1258 hint=_("use 'hg update' to switch to it"))
1244 hint=_("use 'hg update' to switch to it"))
1259 scmutil.checknewlabel(repo, label, 'branch')
1245 scmutil.checknewlabel(repo, label, 'branch')
1260 repo.dirstate.setbranch(label)
1246 repo.dirstate.setbranch(label)
1261 ui.status(_('marked working directory as branch %s\n') % label)
1247 ui.status(_('marked working directory as branch %s\n') % label)
1262
1248
1263 # find any open named branches aside from default
1249 # find any open named branches aside from default
1264 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1250 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1265 if n != "default" and not c]
1251 if n != "default" and not c]
1266 if not others:
1252 if not others:
1267 ui.status(_('(branches are permanent and global, '
1253 ui.status(_('(branches are permanent and global, '
1268 'did you want a bookmark?)\n'))
1254 'did you want a bookmark?)\n'))
1269
1255
1270 @command('branches',
1256 @command('branches',
1271 [('a', 'active', False,
1257 [('a', 'active', False,
1272 _('show only branches that have unmerged heads (DEPRECATED)')),
1258 _('show only branches that have unmerged heads (DEPRECATED)')),
1273 ('c', 'closed', False, _('show normal and closed branches')),
1259 ('c', 'closed', False, _('show normal and closed branches')),
1274 ] + formatteropts,
1260 ] + formatteropts,
1275 _('[-c]'))
1261 _('[-c]'))
1276 def branches(ui, repo, active=False, closed=False, **opts):
1262 def branches(ui, repo, active=False, closed=False, **opts):
1277 """list repository named branches
1263 """list repository named branches
1278
1264
1279 List the repository's named branches, indicating which ones are
1265 List the repository's named branches, indicating which ones are
1280 inactive. If -c/--closed is specified, also list branches which have
1266 inactive. If -c/--closed is specified, also list branches which have
1281 been marked closed (see :hg:`commit --close-branch`).
1267 been marked closed (see :hg:`commit --close-branch`).
1282
1268
1283 Use the command :hg:`update` to switch to an existing branch.
1269 Use the command :hg:`update` to switch to an existing branch.
1284
1270
1285 Returns 0.
1271 Returns 0.
1286 """
1272 """
1287
1273
1288 fm = ui.formatter('branches', opts)
1274 fm = ui.formatter('branches', opts)
1289 hexfunc = fm.hexfunc
1275 hexfunc = fm.hexfunc
1290
1276
1291 allheads = set(repo.heads())
1277 allheads = set(repo.heads())
1292 branches = []
1278 branches = []
1293 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1279 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1294 isactive = not isclosed and bool(set(heads) & allheads)
1280 isactive = not isclosed and bool(set(heads) & allheads)
1295 branches.append((tag, repo[tip], isactive, not isclosed))
1281 branches.append((tag, repo[tip], isactive, not isclosed))
1296 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1282 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1297 reverse=True)
1283 reverse=True)
1298
1284
1299 for tag, ctx, isactive, isopen in branches:
1285 for tag, ctx, isactive, isopen in branches:
1300 if active and not isactive:
1286 if active and not isactive:
1301 continue
1287 continue
1302 if isactive:
1288 if isactive:
1303 label = 'branches.active'
1289 label = 'branches.active'
1304 notice = ''
1290 notice = ''
1305 elif not isopen:
1291 elif not isopen:
1306 if not closed:
1292 if not closed:
1307 continue
1293 continue
1308 label = 'branches.closed'
1294 label = 'branches.closed'
1309 notice = _(' (closed)')
1295 notice = _(' (closed)')
1310 else:
1296 else:
1311 label = 'branches.inactive'
1297 label = 'branches.inactive'
1312 notice = _(' (inactive)')
1298 notice = _(' (inactive)')
1313 current = (tag == repo.dirstate.branch())
1299 current = (tag == repo.dirstate.branch())
1314 if current:
1300 if current:
1315 label = 'branches.current'
1301 label = 'branches.current'
1316
1302
1317 fm.startitem()
1303 fm.startitem()
1318 fm.write('branch', '%s', tag, label=label)
1304 fm.write('branch', '%s', tag, label=label)
1319 rev = ctx.rev()
1305 rev = ctx.rev()
1320 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1306 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1321 fmt = ' ' * padsize + ' %d:%s'
1307 fmt = ' ' * padsize + ' %d:%s'
1322 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1308 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1323 label='log.changeset changeset.%s' % ctx.phasestr())
1309 label='log.changeset changeset.%s' % ctx.phasestr())
1324 fm.data(active=isactive, closed=not isopen, current=current)
1310 fm.data(active=isactive, closed=not isopen, current=current)
1325 if not ui.quiet:
1311 if not ui.quiet:
1326 fm.plain(notice)
1312 fm.plain(notice)
1327 fm.plain('\n')
1313 fm.plain('\n')
1328 fm.end()
1314 fm.end()
1329
1315
1330 @command('bundle',
1316 @command('bundle',
1331 [('f', 'force', None, _('run even when the destination is unrelated')),
1317 [('f', 'force', None, _('run even when the destination is unrelated')),
1332 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1318 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1333 _('REV')),
1319 _('REV')),
1334 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1320 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1335 _('BRANCH')),
1321 _('BRANCH')),
1336 ('', 'base', [],
1322 ('', 'base', [],
1337 _('a base changeset assumed to be available at the destination'),
1323 _('a base changeset assumed to be available at the destination'),
1338 _('REV')),
1324 _('REV')),
1339 ('a', 'all', None, _('bundle all changesets in the repository')),
1325 ('a', 'all', None, _('bundle all changesets in the repository')),
1340 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1326 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1341 ] + remoteopts,
1327 ] + remoteopts,
1342 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1328 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1343 def bundle(ui, repo, fname, dest=None, **opts):
1329 def bundle(ui, repo, fname, dest=None, **opts):
1344 """create a changegroup file
1330 """create a changegroup file
1345
1331
1346 Generate a changegroup file collecting changesets to be added
1332 Generate a changegroup file collecting changesets to be added
1347 to a repository.
1333 to a repository.
1348
1334
1349 To create a bundle containing all changesets, use -a/--all
1335 To create a bundle containing all changesets, use -a/--all
1350 (or --base null). Otherwise, hg assumes the destination will have
1336 (or --base null). Otherwise, hg assumes the destination will have
1351 all the nodes you specify with --base parameters. Otherwise, hg
1337 all the nodes you specify with --base parameters. Otherwise, hg
1352 will assume the repository has all the nodes in destination, or
1338 will assume the repository has all the nodes in destination, or
1353 default-push/default if no destination is specified.
1339 default-push/default if no destination is specified.
1354
1340
1355 You can change bundle format with the -t/--type option. You can
1341 You can change bundle format with the -t/--type option. You can
1356 specify a compression, a bundle version or both using a dash
1342 specify a compression, a bundle version or both using a dash
1357 (comp-version). The available compression methods are: none, bzip2,
1343 (comp-version). The available compression methods are: none, bzip2,
1358 and gzip (by default, bundles are compressed using bzip2). The
1344 and gzip (by default, bundles are compressed using bzip2). The
1359 available formats are: v1, v2 (default to most suitable).
1345 available formats are: v1, v2 (default to most suitable).
1360
1346
1361 The bundle file can then be transferred using conventional means
1347 The bundle file can then be transferred using conventional means
1362 and applied to another repository with the unbundle or pull
1348 and applied to another repository with the unbundle or pull
1363 command. This is useful when direct push and pull are not
1349 command. This is useful when direct push and pull are not
1364 available or when exporting an entire repository is undesirable.
1350 available or when exporting an entire repository is undesirable.
1365
1351
1366 Applying bundles preserves all changeset contents including
1352 Applying bundles preserves all changeset contents including
1367 permissions, copy/rename information, and revision history.
1353 permissions, copy/rename information, and revision history.
1368
1354
1369 Returns 0 on success, 1 if no changes found.
1355 Returns 0 on success, 1 if no changes found.
1370 """
1356 """
1371 revs = None
1357 revs = None
1372 if 'rev' in opts:
1358 if 'rev' in opts:
1373 revstrings = opts['rev']
1359 revstrings = opts['rev']
1374 revs = scmutil.revrange(repo, revstrings)
1360 revs = scmutil.revrange(repo, revstrings)
1375 if revstrings and not revs:
1361 if revstrings and not revs:
1376 raise error.Abort(_('no commits to bundle'))
1362 raise error.Abort(_('no commits to bundle'))
1377
1363
1378 bundletype = opts.get('type', 'bzip2').lower()
1364 bundletype = opts.get('type', 'bzip2').lower()
1379 try:
1365 try:
1380 bcompression, cgversion, params = exchange.parsebundlespec(
1366 bcompression, cgversion, params = exchange.parsebundlespec(
1381 repo, bundletype, strict=False)
1367 repo, bundletype, strict=False)
1382 except error.UnsupportedBundleSpecification as e:
1368 except error.UnsupportedBundleSpecification as e:
1383 raise error.Abort(str(e),
1369 raise error.Abort(str(e),
1384 hint=_("see 'hg help bundle' for supported "
1370 hint=_("see 'hg help bundle' for supported "
1385 "values for --type"))
1371 "values for --type"))
1386
1372
1387 # Packed bundles are a pseudo bundle format for now.
1373 # Packed bundles are a pseudo bundle format for now.
1388 if cgversion == 's1':
1374 if cgversion == 's1':
1389 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1375 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1390 hint=_("use 'hg debugcreatestreamclonebundle'"))
1376 hint=_("use 'hg debugcreatestreamclonebundle'"))
1391
1377
1392 if opts.get('all'):
1378 if opts.get('all'):
1393 if dest:
1379 if dest:
1394 raise error.Abort(_("--all is incompatible with specifying "
1380 raise error.Abort(_("--all is incompatible with specifying "
1395 "a destination"))
1381 "a destination"))
1396 if opts.get('base'):
1382 if opts.get('base'):
1397 ui.warn(_("ignoring --base because --all was specified\n"))
1383 ui.warn(_("ignoring --base because --all was specified\n"))
1398 base = ['null']
1384 base = ['null']
1399 else:
1385 else:
1400 base = scmutil.revrange(repo, opts.get('base'))
1386 base = scmutil.revrange(repo, opts.get('base'))
1401 # TODO: get desired bundlecaps from command line.
1387 # TODO: get desired bundlecaps from command line.
1402 bundlecaps = None
1388 bundlecaps = None
1403 if cgversion not in changegroup.supportedoutgoingversions(repo):
1389 if cgversion not in changegroup.supportedoutgoingversions(repo):
1404 raise error.Abort(_("repository does not support bundle version %s") %
1390 raise error.Abort(_("repository does not support bundle version %s") %
1405 cgversion)
1391 cgversion)
1406
1392
1407 if base:
1393 if base:
1408 if dest:
1394 if dest:
1409 raise error.Abort(_("--base is incompatible with specifying "
1395 raise error.Abort(_("--base is incompatible with specifying "
1410 "a destination"))
1396 "a destination"))
1411 common = [repo.lookup(rev) for rev in base]
1397 common = [repo.lookup(rev) for rev in base]
1412 heads = revs and map(repo.lookup, revs) or None
1398 heads = revs and map(repo.lookup, revs) or None
1413 outgoing = discovery.outgoing(repo, common, heads)
1399 outgoing = discovery.outgoing(repo, common, heads)
1414 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1400 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1415 bundlecaps=bundlecaps,
1401 bundlecaps=bundlecaps,
1416 version=cgversion)
1402 version=cgversion)
1417 outgoing = None
1403 outgoing = None
1418 else:
1404 else:
1419 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1405 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1420 dest, branches = hg.parseurl(dest, opts.get('branch'))
1406 dest, branches = hg.parseurl(dest, opts.get('branch'))
1421 other = hg.peer(repo, opts, dest)
1407 other = hg.peer(repo, opts, dest)
1422 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1408 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1423 heads = revs and map(repo.lookup, revs) or revs
1409 heads = revs and map(repo.lookup, revs) or revs
1424 outgoing = discovery.findcommonoutgoing(repo, other,
1410 outgoing = discovery.findcommonoutgoing(repo, other,
1425 onlyheads=heads,
1411 onlyheads=heads,
1426 force=opts.get('force'),
1412 force=opts.get('force'),
1427 portable=True)
1413 portable=True)
1428 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1414 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1429 bundlecaps, version=cgversion)
1415 bundlecaps, version=cgversion)
1430 if not cg:
1416 if not cg:
1431 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1417 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1432 return 1
1418 return 1
1433
1419
1434 if cgversion == '01': #bundle1
1420 if cgversion == '01': #bundle1
1435 if bcompression is None:
1421 if bcompression is None:
1436 bcompression = 'UN'
1422 bcompression = 'UN'
1437 bversion = 'HG10' + bcompression
1423 bversion = 'HG10' + bcompression
1438 bcompression = None
1424 bcompression = None
1439 else:
1425 else:
1440 assert cgversion == '02'
1426 assert cgversion == '02'
1441 bversion = 'HG20'
1427 bversion = 'HG20'
1442
1428
1443 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1429 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1444
1430
1445 @command('cat',
1431 @command('cat',
1446 [('o', 'output', '',
1432 [('o', 'output', '',
1447 _('print output to file with formatted name'), _('FORMAT')),
1433 _('print output to file with formatted name'), _('FORMAT')),
1448 ('r', 'rev', '', _('print the given revision'), _('REV')),
1434 ('r', 'rev', '', _('print the given revision'), _('REV')),
1449 ('', 'decode', None, _('apply any matching decode filter')),
1435 ('', 'decode', None, _('apply any matching decode filter')),
1450 ] + walkopts,
1436 ] + walkopts,
1451 _('[OPTION]... FILE...'),
1437 _('[OPTION]... FILE...'),
1452 inferrepo=True)
1438 inferrepo=True)
1453 def cat(ui, repo, file1, *pats, **opts):
1439 def cat(ui, repo, file1, *pats, **opts):
1454 """output the current or given revision of files
1440 """output the current or given revision of files
1455
1441
1456 Print the specified files as they were at the given revision. If
1442 Print the specified files as they were at the given revision. If
1457 no revision is given, the parent of the working directory is used.
1443 no revision is given, the parent of the working directory is used.
1458
1444
1459 Output may be to a file, in which case the name of the file is
1445 Output may be to a file, in which case the name of the file is
1460 given using a format string. The formatting rules as follows:
1446 given using a format string. The formatting rules as follows:
1461
1447
1462 :``%%``: literal "%" character
1448 :``%%``: literal "%" character
1463 :``%s``: basename of file being printed
1449 :``%s``: basename of file being printed
1464 :``%d``: dirname of file being printed, or '.' if in repository root
1450 :``%d``: dirname of file being printed, or '.' if in repository root
1465 :``%p``: root-relative path name of file being printed
1451 :``%p``: root-relative path name of file being printed
1466 :``%H``: changeset hash (40 hexadecimal digits)
1452 :``%H``: changeset hash (40 hexadecimal digits)
1467 :``%R``: changeset revision number
1453 :``%R``: changeset revision number
1468 :``%h``: short-form changeset hash (12 hexadecimal digits)
1454 :``%h``: short-form changeset hash (12 hexadecimal digits)
1469 :``%r``: zero-padded changeset revision number
1455 :``%r``: zero-padded changeset revision number
1470 :``%b``: basename of the exporting repository
1456 :``%b``: basename of the exporting repository
1471
1457
1472 Returns 0 on success.
1458 Returns 0 on success.
1473 """
1459 """
1474 ctx = scmutil.revsingle(repo, opts.get('rev'))
1460 ctx = scmutil.revsingle(repo, opts.get('rev'))
1475 m = scmutil.match(ctx, (file1,) + pats, opts)
1461 m = scmutil.match(ctx, (file1,) + pats, opts)
1476
1462
1477 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1463 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1478
1464
1479 @command('^clone',
1465 @command('^clone',
1480 [('U', 'noupdate', None, _('the clone will include an empty working '
1466 [('U', 'noupdate', None, _('the clone will include an empty working '
1481 'directory (only a repository)')),
1467 'directory (only a repository)')),
1482 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1468 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1483 _('REV')),
1469 _('REV')),
1484 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1470 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1485 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1471 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1486 ('', 'pull', None, _('use pull protocol to copy metadata')),
1472 ('', 'pull', None, _('use pull protocol to copy metadata')),
1487 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1473 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1488 ] + remoteopts,
1474 ] + remoteopts,
1489 _('[OPTION]... SOURCE [DEST]'),
1475 _('[OPTION]... SOURCE [DEST]'),
1490 norepo=True)
1476 norepo=True)
1491 def clone(ui, source, dest=None, **opts):
1477 def clone(ui, source, dest=None, **opts):
1492 """make a copy of an existing repository
1478 """make a copy of an existing repository
1493
1479
1494 Create a copy of an existing repository in a new directory.
1480 Create a copy of an existing repository in a new directory.
1495
1481
1496 If no destination directory name is specified, it defaults to the
1482 If no destination directory name is specified, it defaults to the
1497 basename of the source.
1483 basename of the source.
1498
1484
1499 The location of the source is added to the new repository's
1485 The location of the source is added to the new repository's
1500 ``.hg/hgrc`` file, as the default to be used for future pulls.
1486 ``.hg/hgrc`` file, as the default to be used for future pulls.
1501
1487
1502 Only local paths and ``ssh://`` URLs are supported as
1488 Only local paths and ``ssh://`` URLs are supported as
1503 destinations. For ``ssh://`` destinations, no working directory or
1489 destinations. For ``ssh://`` destinations, no working directory or
1504 ``.hg/hgrc`` will be created on the remote side.
1490 ``.hg/hgrc`` will be created on the remote side.
1505
1491
1506 If the source repository has a bookmark called '@' set, that
1492 If the source repository has a bookmark called '@' set, that
1507 revision will be checked out in the new repository by default.
1493 revision will be checked out in the new repository by default.
1508
1494
1509 To check out a particular version, use -u/--update, or
1495 To check out a particular version, use -u/--update, or
1510 -U/--noupdate to create a clone with no working directory.
1496 -U/--noupdate to create a clone with no working directory.
1511
1497
1512 To pull only a subset of changesets, specify one or more revisions
1498 To pull only a subset of changesets, specify one or more revisions
1513 identifiers with -r/--rev or branches with -b/--branch. The
1499 identifiers with -r/--rev or branches with -b/--branch. The
1514 resulting clone will contain only the specified changesets and
1500 resulting clone will contain only the specified changesets and
1515 their ancestors. These options (or 'clone src#rev dest') imply
1501 their ancestors. These options (or 'clone src#rev dest') imply
1516 --pull, even for local source repositories.
1502 --pull, even for local source repositories.
1517
1503
1518 .. note::
1504 .. note::
1519
1505
1520 Specifying a tag will include the tagged changeset but not the
1506 Specifying a tag will include the tagged changeset but not the
1521 changeset containing the tag.
1507 changeset containing the tag.
1522
1508
1523 .. container:: verbose
1509 .. container:: verbose
1524
1510
1525 For efficiency, hardlinks are used for cloning whenever the
1511 For efficiency, hardlinks are used for cloning whenever the
1526 source and destination are on the same filesystem (note this
1512 source and destination are on the same filesystem (note this
1527 applies only to the repository data, not to the working
1513 applies only to the repository data, not to the working
1528 directory). Some filesystems, such as AFS, implement hardlinking
1514 directory). Some filesystems, such as AFS, implement hardlinking
1529 incorrectly, but do not report errors. In these cases, use the
1515 incorrectly, but do not report errors. In these cases, use the
1530 --pull option to avoid hardlinking.
1516 --pull option to avoid hardlinking.
1531
1517
1532 In some cases, you can clone repositories and the working
1518 In some cases, you can clone repositories and the working
1533 directory using full hardlinks with ::
1519 directory using full hardlinks with ::
1534
1520
1535 $ cp -al REPO REPOCLONE
1521 $ cp -al REPO REPOCLONE
1536
1522
1537 This is the fastest way to clone, but it is not always safe. The
1523 This is the fastest way to clone, but it is not always safe. The
1538 operation is not atomic (making sure REPO is not modified during
1524 operation is not atomic (making sure REPO is not modified during
1539 the operation is up to you) and you have to make sure your
1525 the operation is up to you) and you have to make sure your
1540 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1526 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1541 so). Also, this is not compatible with certain extensions that
1527 so). Also, this is not compatible with certain extensions that
1542 place their metadata under the .hg directory, such as mq.
1528 place their metadata under the .hg directory, such as mq.
1543
1529
1544 Mercurial will update the working directory to the first applicable
1530 Mercurial will update the working directory to the first applicable
1545 revision from this list:
1531 revision from this list:
1546
1532
1547 a) null if -U or the source repository has no changesets
1533 a) null if -U or the source repository has no changesets
1548 b) if -u . and the source repository is local, the first parent of
1534 b) if -u . and the source repository is local, the first parent of
1549 the source repository's working directory
1535 the source repository's working directory
1550 c) the changeset specified with -u (if a branch name, this means the
1536 c) the changeset specified with -u (if a branch name, this means the
1551 latest head of that branch)
1537 latest head of that branch)
1552 d) the changeset specified with -r
1538 d) the changeset specified with -r
1553 e) the tipmost head specified with -b
1539 e) the tipmost head specified with -b
1554 f) the tipmost head specified with the url#branch source syntax
1540 f) the tipmost head specified with the url#branch source syntax
1555 g) the revision marked with the '@' bookmark, if present
1541 g) the revision marked with the '@' bookmark, if present
1556 h) the tipmost head of the default branch
1542 h) the tipmost head of the default branch
1557 i) tip
1543 i) tip
1558
1544
1559 When cloning from servers that support it, Mercurial may fetch
1545 When cloning from servers that support it, Mercurial may fetch
1560 pre-generated data from a server-advertised URL. When this is done,
1546 pre-generated data from a server-advertised URL. When this is done,
1561 hooks operating on incoming changesets and changegroups may fire twice,
1547 hooks operating on incoming changesets and changegroups may fire twice,
1562 once for the bundle fetched from the URL and another for any additional
1548 once for the bundle fetched from the URL and another for any additional
1563 data not fetched from this URL. In addition, if an error occurs, the
1549 data not fetched from this URL. In addition, if an error occurs, the
1564 repository may be rolled back to a partial clone. This behavior may
1550 repository may be rolled back to a partial clone. This behavior may
1565 change in future releases. See :hg:`help -e clonebundles` for more.
1551 change in future releases. See :hg:`help -e clonebundles` for more.
1566
1552
1567 Examples:
1553 Examples:
1568
1554
1569 - clone a remote repository to a new directory named hg/::
1555 - clone a remote repository to a new directory named hg/::
1570
1556
1571 hg clone http://selenic.com/hg
1557 hg clone http://selenic.com/hg
1572
1558
1573 - create a lightweight local clone::
1559 - create a lightweight local clone::
1574
1560
1575 hg clone project/ project-feature/
1561 hg clone project/ project-feature/
1576
1562
1577 - clone from an absolute path on an ssh server (note double-slash)::
1563 - clone from an absolute path on an ssh server (note double-slash)::
1578
1564
1579 hg clone ssh://user@server//home/projects/alpha/
1565 hg clone ssh://user@server//home/projects/alpha/
1580
1566
1581 - do a high-speed clone over a LAN while checking out a
1567 - do a high-speed clone over a LAN while checking out a
1582 specified version::
1568 specified version::
1583
1569
1584 hg clone --uncompressed http://server/repo -u 1.5
1570 hg clone --uncompressed http://server/repo -u 1.5
1585
1571
1586 - create a repository without changesets after a particular revision::
1572 - create a repository without changesets after a particular revision::
1587
1573
1588 hg clone -r 04e544 experimental/ good/
1574 hg clone -r 04e544 experimental/ good/
1589
1575
1590 - clone (and track) a particular named branch::
1576 - clone (and track) a particular named branch::
1591
1577
1592 hg clone http://selenic.com/hg#stable
1578 hg clone http://selenic.com/hg#stable
1593
1579
1594 See :hg:`help urls` for details on specifying URLs.
1580 See :hg:`help urls` for details on specifying URLs.
1595
1581
1596 Returns 0 on success.
1582 Returns 0 on success.
1597 """
1583 """
1598 if opts.get('noupdate') and opts.get('updaterev'):
1584 if opts.get('noupdate') and opts.get('updaterev'):
1599 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1585 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1600
1586
1601 r = hg.clone(ui, opts, source, dest,
1587 r = hg.clone(ui, opts, source, dest,
1602 pull=opts.get('pull'),
1588 pull=opts.get('pull'),
1603 stream=opts.get('uncompressed'),
1589 stream=opts.get('uncompressed'),
1604 rev=opts.get('rev'),
1590 rev=opts.get('rev'),
1605 update=opts.get('updaterev') or not opts.get('noupdate'),
1591 update=opts.get('updaterev') or not opts.get('noupdate'),
1606 branch=opts.get('branch'),
1592 branch=opts.get('branch'),
1607 shareopts=opts.get('shareopts'))
1593 shareopts=opts.get('shareopts'))
1608
1594
1609 return r is None
1595 return r is None
1610
1596
1611 @command('^commit|ci',
1597 @command('^commit|ci',
1612 [('A', 'addremove', None,
1598 [('A', 'addremove', None,
1613 _('mark new/missing files as added/removed before committing')),
1599 _('mark new/missing files as added/removed before committing')),
1614 ('', 'close-branch', None,
1600 ('', 'close-branch', None,
1615 _('mark a branch head as closed')),
1601 _('mark a branch head as closed')),
1616 ('', 'amend', None, _('amend the parent of the working directory')),
1602 ('', 'amend', None, _('amend the parent of the working directory')),
1617 ('s', 'secret', None, _('use the secret phase for committing')),
1603 ('s', 'secret', None, _('use the secret phase for committing')),
1618 ('e', 'edit', None, _('invoke editor on commit messages')),
1604 ('e', 'edit', None, _('invoke editor on commit messages')),
1619 ('i', 'interactive', None, _('use interactive mode')),
1605 ('i', 'interactive', None, _('use interactive mode')),
1620 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1606 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1621 _('[OPTION]... [FILE]...'),
1607 _('[OPTION]... [FILE]...'),
1622 inferrepo=True)
1608 inferrepo=True)
1623 def commit(ui, repo, *pats, **opts):
1609 def commit(ui, repo, *pats, **opts):
1624 """commit the specified files or all outstanding changes
1610 """commit the specified files or all outstanding changes
1625
1611
1626 Commit changes to the given files into the repository. Unlike a
1612 Commit changes to the given files into the repository. Unlike a
1627 centralized SCM, this operation is a local operation. See
1613 centralized SCM, this operation is a local operation. See
1628 :hg:`push` for a way to actively distribute your changes.
1614 :hg:`push` for a way to actively distribute your changes.
1629
1615
1630 If a list of files is omitted, all changes reported by :hg:`status`
1616 If a list of files is omitted, all changes reported by :hg:`status`
1631 will be committed.
1617 will be committed.
1632
1618
1633 If you are committing the result of a merge, do not provide any
1619 If you are committing the result of a merge, do not provide any
1634 filenames or -I/-X filters.
1620 filenames or -I/-X filters.
1635
1621
1636 If no commit message is specified, Mercurial starts your
1622 If no commit message is specified, Mercurial starts your
1637 configured editor where you can enter a message. In case your
1623 configured editor where you can enter a message. In case your
1638 commit fails, you will find a backup of your message in
1624 commit fails, you will find a backup of your message in
1639 ``.hg/last-message.txt``.
1625 ``.hg/last-message.txt``.
1640
1626
1641 The --close-branch flag can be used to mark the current branch
1627 The --close-branch flag can be used to mark the current branch
1642 head closed. When all heads of a branch are closed, the branch
1628 head closed. When all heads of a branch are closed, the branch
1643 will be considered closed and no longer listed.
1629 will be considered closed and no longer listed.
1644
1630
1645 The --amend flag can be used to amend the parent of the
1631 The --amend flag can be used to amend the parent of the
1646 working directory with a new commit that contains the changes
1632 working directory with a new commit that contains the changes
1647 in the parent in addition to those currently reported by :hg:`status`,
1633 in the parent in addition to those currently reported by :hg:`status`,
1648 if there are any. The old commit is stored in a backup bundle in
1634 if there are any. The old commit is stored in a backup bundle in
1649 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1635 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1650 on how to restore it).
1636 on how to restore it).
1651
1637
1652 Message, user and date are taken from the amended commit unless
1638 Message, user and date are taken from the amended commit unless
1653 specified. When a message isn't specified on the command line,
1639 specified. When a message isn't specified on the command line,
1654 the editor will open with the message of the amended commit.
1640 the editor will open with the message of the amended commit.
1655
1641
1656 It is not possible to amend public changesets (see :hg:`help phases`)
1642 It is not possible to amend public changesets (see :hg:`help phases`)
1657 or changesets that have children.
1643 or changesets that have children.
1658
1644
1659 See :hg:`help dates` for a list of formats valid for -d/--date.
1645 See :hg:`help dates` for a list of formats valid for -d/--date.
1660
1646
1661 Returns 0 on success, 1 if nothing changed.
1647 Returns 0 on success, 1 if nothing changed.
1662
1648
1663 .. container:: verbose
1649 .. container:: verbose
1664
1650
1665 Examples:
1651 Examples:
1666
1652
1667 - commit all files ending in .py::
1653 - commit all files ending in .py::
1668
1654
1669 hg commit --include "set:**.py"
1655 hg commit --include "set:**.py"
1670
1656
1671 - commit all non-binary files::
1657 - commit all non-binary files::
1672
1658
1673 hg commit --exclude "set:binary()"
1659 hg commit --exclude "set:binary()"
1674
1660
1675 - amend the current commit and set the date to now::
1661 - amend the current commit and set the date to now::
1676
1662
1677 hg commit --amend --date now
1663 hg commit --amend --date now
1678 """
1664 """
1679 wlock = lock = None
1665 wlock = lock = None
1680 try:
1666 try:
1681 wlock = repo.wlock()
1667 wlock = repo.wlock()
1682 lock = repo.lock()
1668 lock = repo.lock()
1683 return _docommit(ui, repo, *pats, **opts)
1669 return _docommit(ui, repo, *pats, **opts)
1684 finally:
1670 finally:
1685 release(lock, wlock)
1671 release(lock, wlock)
1686
1672
1687 def _docommit(ui, repo, *pats, **opts):
1673 def _docommit(ui, repo, *pats, **opts):
1688 if opts.get('interactive'):
1674 if opts.get('interactive'):
1689 opts.pop('interactive')
1675 opts.pop('interactive')
1690 cmdutil.dorecord(ui, repo, commit, None, False,
1676 cmdutil.dorecord(ui, repo, commit, None, False,
1691 cmdutil.recordfilter, *pats, **opts)
1677 cmdutil.recordfilter, *pats, **opts)
1692 return
1678 return
1693
1679
1694 if opts.get('subrepos'):
1680 if opts.get('subrepos'):
1695 if opts.get('amend'):
1681 if opts.get('amend'):
1696 raise error.Abort(_('cannot amend with --subrepos'))
1682 raise error.Abort(_('cannot amend with --subrepos'))
1697 # Let --subrepos on the command line override config setting.
1683 # Let --subrepos on the command line override config setting.
1698 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1684 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1699
1685
1700 cmdutil.checkunfinished(repo, commit=True)
1686 cmdutil.checkunfinished(repo, commit=True)
1701
1687
1702 branch = repo[None].branch()
1688 branch = repo[None].branch()
1703 bheads = repo.branchheads(branch)
1689 bheads = repo.branchheads(branch)
1704
1690
1705 extra = {}
1691 extra = {}
1706 if opts.get('close_branch'):
1692 if opts.get('close_branch'):
1707 extra['close'] = 1
1693 extra['close'] = 1
1708
1694
1709 if not bheads:
1695 if not bheads:
1710 raise error.Abort(_('can only close branch heads'))
1696 raise error.Abort(_('can only close branch heads'))
1711 elif opts.get('amend'):
1697 elif opts.get('amend'):
1712 if repo[None].parents()[0].p1().branch() != branch and \
1698 if repo[None].parents()[0].p1().branch() != branch and \
1713 repo[None].parents()[0].p2().branch() != branch:
1699 repo[None].parents()[0].p2().branch() != branch:
1714 raise error.Abort(_('can only close branch heads'))
1700 raise error.Abort(_('can only close branch heads'))
1715
1701
1716 if opts.get('amend'):
1702 if opts.get('amend'):
1717 if ui.configbool('ui', 'commitsubrepos'):
1703 if ui.configbool('ui', 'commitsubrepos'):
1718 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1704 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1719
1705
1720 old = repo['.']
1706 old = repo['.']
1721 if not old.mutable():
1707 if not old.mutable():
1722 raise error.Abort(_('cannot amend public changesets'))
1708 raise error.Abort(_('cannot amend public changesets'))
1723 if len(repo[None].parents()) > 1:
1709 if len(repo[None].parents()) > 1:
1724 raise error.Abort(_('cannot amend while merging'))
1710 raise error.Abort(_('cannot amend while merging'))
1725 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1711 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1726 if not allowunstable and old.children():
1712 if not allowunstable and old.children():
1727 raise error.Abort(_('cannot amend changeset with children'))
1713 raise error.Abort(_('cannot amend changeset with children'))
1728
1714
1729 # Currently histedit gets confused if an amend happens while histedit
1715 # Currently histedit gets confused if an amend happens while histedit
1730 # is in progress. Since we have a checkunfinished command, we are
1716 # is in progress. Since we have a checkunfinished command, we are
1731 # temporarily honoring it.
1717 # temporarily honoring it.
1732 #
1718 #
1733 # Note: eventually this guard will be removed. Please do not expect
1719 # Note: eventually this guard will be removed. Please do not expect
1734 # this behavior to remain.
1720 # this behavior to remain.
1735 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1721 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1736 cmdutil.checkunfinished(repo)
1722 cmdutil.checkunfinished(repo)
1737
1723
1738 # commitfunc is used only for temporary amend commit by cmdutil.amend
1724 # commitfunc is used only for temporary amend commit by cmdutil.amend
1739 def commitfunc(ui, repo, message, match, opts):
1725 def commitfunc(ui, repo, message, match, opts):
1740 return repo.commit(message,
1726 return repo.commit(message,
1741 opts.get('user') or old.user(),
1727 opts.get('user') or old.user(),
1742 opts.get('date') or old.date(),
1728 opts.get('date') or old.date(),
1743 match,
1729 match,
1744 extra=extra)
1730 extra=extra)
1745
1731
1746 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1732 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1747 if node == old.node():
1733 if node == old.node():
1748 ui.status(_("nothing changed\n"))
1734 ui.status(_("nothing changed\n"))
1749 return 1
1735 return 1
1750 else:
1736 else:
1751 def commitfunc(ui, repo, message, match, opts):
1737 def commitfunc(ui, repo, message, match, opts):
1752 backup = ui.backupconfig('phases', 'new-commit')
1738 backup = ui.backupconfig('phases', 'new-commit')
1753 baseui = repo.baseui
1739 baseui = repo.baseui
1754 basebackup = baseui.backupconfig('phases', 'new-commit')
1740 basebackup = baseui.backupconfig('phases', 'new-commit')
1755 try:
1741 try:
1756 if opts.get('secret'):
1742 if opts.get('secret'):
1757 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1743 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1758 # Propagate to subrepos
1744 # Propagate to subrepos
1759 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1745 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1760
1746
1761 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1747 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1762 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1748 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1763 return repo.commit(message, opts.get('user'), opts.get('date'),
1749 return repo.commit(message, opts.get('user'), opts.get('date'),
1764 match,
1750 match,
1765 editor=editor,
1751 editor=editor,
1766 extra=extra)
1752 extra=extra)
1767 finally:
1753 finally:
1768 ui.restoreconfig(backup)
1754 ui.restoreconfig(backup)
1769 repo.baseui.restoreconfig(basebackup)
1755 repo.baseui.restoreconfig(basebackup)
1770
1756
1771
1757
1772 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1758 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1773
1759
1774 if not node:
1760 if not node:
1775 stat = cmdutil.postcommitstatus(repo, pats, opts)
1761 stat = cmdutil.postcommitstatus(repo, pats, opts)
1776 if stat[3]:
1762 if stat[3]:
1777 ui.status(_("nothing changed (%d missing files, see "
1763 ui.status(_("nothing changed (%d missing files, see "
1778 "'hg status')\n") % len(stat[3]))
1764 "'hg status')\n") % len(stat[3]))
1779 else:
1765 else:
1780 ui.status(_("nothing changed\n"))
1766 ui.status(_("nothing changed\n"))
1781 return 1
1767 return 1
1782
1768
1783 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1769 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1784
1770
1785 @command('config|showconfig|debugconfig',
1771 @command('config|showconfig|debugconfig',
1786 [('u', 'untrusted', None, _('show untrusted configuration options')),
1772 [('u', 'untrusted', None, _('show untrusted configuration options')),
1787 ('e', 'edit', None, _('edit user config')),
1773 ('e', 'edit', None, _('edit user config')),
1788 ('l', 'local', None, _('edit repository config')),
1774 ('l', 'local', None, _('edit repository config')),
1789 ('g', 'global', None, _('edit global config'))] + formatteropts,
1775 ('g', 'global', None, _('edit global config'))] + formatteropts,
1790 _('[-u] [NAME]...'),
1776 _('[-u] [NAME]...'),
1791 optionalrepo=True)
1777 optionalrepo=True)
1792 def config(ui, repo, *values, **opts):
1778 def config(ui, repo, *values, **opts):
1793 """show combined config settings from all hgrc files
1779 """show combined config settings from all hgrc files
1794
1780
1795 With no arguments, print names and values of all config items.
1781 With no arguments, print names and values of all config items.
1796
1782
1797 With one argument of the form section.name, print just the value
1783 With one argument of the form section.name, print just the value
1798 of that config item.
1784 of that config item.
1799
1785
1800 With multiple arguments, print names and values of all config
1786 With multiple arguments, print names and values of all config
1801 items with matching section names.
1787 items with matching section names.
1802
1788
1803 With --edit, start an editor on the user-level config file. With
1789 With --edit, start an editor on the user-level config file. With
1804 --global, edit the system-wide config file. With --local, edit the
1790 --global, edit the system-wide config file. With --local, edit the
1805 repository-level config file.
1791 repository-level config file.
1806
1792
1807 With --debug, the source (filename and line number) is printed
1793 With --debug, the source (filename and line number) is printed
1808 for each config item.
1794 for each config item.
1809
1795
1810 See :hg:`help config` for more information about config files.
1796 See :hg:`help config` for more information about config files.
1811
1797
1812 Returns 0 on success, 1 if NAME does not exist.
1798 Returns 0 on success, 1 if NAME does not exist.
1813
1799
1814 """
1800 """
1815
1801
1816 if opts.get('edit') or opts.get('local') or opts.get('global'):
1802 if opts.get('edit') or opts.get('local') or opts.get('global'):
1817 if opts.get('local') and opts.get('global'):
1803 if opts.get('local') and opts.get('global'):
1818 raise error.Abort(_("can't use --local and --global together"))
1804 raise error.Abort(_("can't use --local and --global together"))
1819
1805
1820 if opts.get('local'):
1806 if opts.get('local'):
1821 if not repo:
1807 if not repo:
1822 raise error.Abort(_("can't use --local outside a repository"))
1808 raise error.Abort(_("can't use --local outside a repository"))
1823 paths = [repo.join('hgrc')]
1809 paths = [repo.join('hgrc')]
1824 elif opts.get('global'):
1810 elif opts.get('global'):
1825 paths = scmutil.systemrcpath()
1811 paths = scmutil.systemrcpath()
1826 else:
1812 else:
1827 paths = scmutil.userrcpath()
1813 paths = scmutil.userrcpath()
1828
1814
1829 for f in paths:
1815 for f in paths:
1830 if os.path.exists(f):
1816 if os.path.exists(f):
1831 break
1817 break
1832 else:
1818 else:
1833 if opts.get('global'):
1819 if opts.get('global'):
1834 samplehgrc = uimod.samplehgrcs['global']
1820 samplehgrc = uimod.samplehgrcs['global']
1835 elif opts.get('local'):
1821 elif opts.get('local'):
1836 samplehgrc = uimod.samplehgrcs['local']
1822 samplehgrc = uimod.samplehgrcs['local']
1837 else:
1823 else:
1838 samplehgrc = uimod.samplehgrcs['user']
1824 samplehgrc = uimod.samplehgrcs['user']
1839
1825
1840 f = paths[0]
1826 f = paths[0]
1841 fp = open(f, "w")
1827 fp = open(f, "w")
1842 fp.write(samplehgrc)
1828 fp.write(samplehgrc)
1843 fp.close()
1829 fp.close()
1844
1830
1845 editor = ui.geteditor()
1831 editor = ui.geteditor()
1846 ui.system("%s \"%s\"" % (editor, f),
1832 ui.system("%s \"%s\"" % (editor, f),
1847 onerr=error.Abort, errprefix=_("edit failed"))
1833 onerr=error.Abort, errprefix=_("edit failed"))
1848 return
1834 return
1849
1835
1850 fm = ui.formatter('config', opts)
1836 fm = ui.formatter('config', opts)
1851 for f in scmutil.rcpath():
1837 for f in scmutil.rcpath():
1852 ui.debug('read config from: %s\n' % f)
1838 ui.debug('read config from: %s\n' % f)
1853 untrusted = bool(opts.get('untrusted'))
1839 untrusted = bool(opts.get('untrusted'))
1854 if values:
1840 if values:
1855 sections = [v for v in values if '.' not in v]
1841 sections = [v for v in values if '.' not in v]
1856 items = [v for v in values if '.' in v]
1842 items = [v for v in values if '.' in v]
1857 if len(items) > 1 or items and sections:
1843 if len(items) > 1 or items and sections:
1858 raise error.Abort(_('only one config item permitted'))
1844 raise error.Abort(_('only one config item permitted'))
1859 matched = False
1845 matched = False
1860 for section, name, value in ui.walkconfig(untrusted=untrusted):
1846 for section, name, value in ui.walkconfig(untrusted=untrusted):
1861 value = str(value)
1847 value = str(value)
1862 if fm.isplain():
1848 if fm.isplain():
1863 value = value.replace('\n', '\\n')
1849 value = value.replace('\n', '\\n')
1864 entryname = section + '.' + name
1850 entryname = section + '.' + name
1865 if values:
1851 if values:
1866 for v in values:
1852 for v in values:
1867 if v == section:
1853 if v == section:
1868 fm.startitem()
1854 fm.startitem()
1869 fm.condwrite(ui.debugflag, 'source', '%s: ',
1855 fm.condwrite(ui.debugflag, 'source', '%s: ',
1870 ui.configsource(section, name, untrusted))
1856 ui.configsource(section, name, untrusted))
1871 fm.write('name value', '%s=%s\n', entryname, value)
1857 fm.write('name value', '%s=%s\n', entryname, value)
1872 matched = True
1858 matched = True
1873 elif v == entryname:
1859 elif v == entryname:
1874 fm.startitem()
1860 fm.startitem()
1875 fm.condwrite(ui.debugflag, 'source', '%s: ',
1861 fm.condwrite(ui.debugflag, 'source', '%s: ',
1876 ui.configsource(section, name, untrusted))
1862 ui.configsource(section, name, untrusted))
1877 fm.write('value', '%s\n', value)
1863 fm.write('value', '%s\n', value)
1878 fm.data(name=entryname)
1864 fm.data(name=entryname)
1879 matched = True
1865 matched = True
1880 else:
1866 else:
1881 fm.startitem()
1867 fm.startitem()
1882 fm.condwrite(ui.debugflag, 'source', '%s: ',
1868 fm.condwrite(ui.debugflag, 'source', '%s: ',
1883 ui.configsource(section, name, untrusted))
1869 ui.configsource(section, name, untrusted))
1884 fm.write('name value', '%s=%s\n', entryname, value)
1870 fm.write('name value', '%s=%s\n', entryname, value)
1885 matched = True
1871 matched = True
1886 fm.end()
1872 fm.end()
1887 if matched:
1873 if matched:
1888 return 0
1874 return 0
1889 return 1
1875 return 1
1890
1876
1891 @command('copy|cp',
1877 @command('copy|cp',
1892 [('A', 'after', None, _('record a copy that has already occurred')),
1878 [('A', 'after', None, _('record a copy that has already occurred')),
1893 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1879 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1894 ] + walkopts + dryrunopts,
1880 ] + walkopts + dryrunopts,
1895 _('[OPTION]... [SOURCE]... DEST'))
1881 _('[OPTION]... [SOURCE]... DEST'))
1896 def copy(ui, repo, *pats, **opts):
1882 def copy(ui, repo, *pats, **opts):
1897 """mark files as copied for the next commit
1883 """mark files as copied for the next commit
1898
1884
1899 Mark dest as having copies of source files. If dest is a
1885 Mark dest as having copies of source files. If dest is a
1900 directory, copies are put in that directory. If dest is a file,
1886 directory, copies are put in that directory. If dest is a file,
1901 the source must be a single file.
1887 the source must be a single file.
1902
1888
1903 By default, this command copies the contents of files as they
1889 By default, this command copies the contents of files as they
1904 exist in the working directory. If invoked with -A/--after, the
1890 exist in the working directory. If invoked with -A/--after, the
1905 operation is recorded, but no copying is performed.
1891 operation is recorded, but no copying is performed.
1906
1892
1907 This command takes effect with the next commit. To undo a copy
1893 This command takes effect with the next commit. To undo a copy
1908 before that, see :hg:`revert`.
1894 before that, see :hg:`revert`.
1909
1895
1910 Returns 0 on success, 1 if errors are encountered.
1896 Returns 0 on success, 1 if errors are encountered.
1911 """
1897 """
1912 with repo.wlock(False):
1898 with repo.wlock(False):
1913 return cmdutil.copy(ui, repo, pats, opts)
1899 return cmdutil.copy(ui, repo, pats, opts)
1914
1900
1915 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1901 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1916 def debugancestor(ui, repo, *args):
1902 def debugancestor(ui, repo, *args):
1917 """find the ancestor revision of two revisions in a given index"""
1903 """find the ancestor revision of two revisions in a given index"""
1918 if len(args) == 3:
1904 if len(args) == 3:
1919 index, rev1, rev2 = args
1905 index, rev1, rev2 = args
1920 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1906 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1921 lookup = r.lookup
1907 lookup = r.lookup
1922 elif len(args) == 2:
1908 elif len(args) == 2:
1923 if not repo:
1909 if not repo:
1924 raise error.Abort(_("there is no Mercurial repository here "
1910 raise error.Abort(_("there is no Mercurial repository here "
1925 "(.hg not found)"))
1911 "(.hg not found)"))
1926 rev1, rev2 = args
1912 rev1, rev2 = args
1927 r = repo.changelog
1913 r = repo.changelog
1928 lookup = repo.lookup
1914 lookup = repo.lookup
1929 else:
1915 else:
1930 raise error.Abort(_('either two or three arguments required'))
1916 raise error.Abort(_('either two or three arguments required'))
1931 a = r.ancestor(lookup(rev1), lookup(rev2))
1917 a = r.ancestor(lookup(rev1), lookup(rev2))
1932 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1918 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1933
1919
1934 @command('debugbuilddag',
1920 @command('debugbuilddag',
1935 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1921 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1936 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1922 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1937 ('n', 'new-file', None, _('add new file at each rev'))],
1923 ('n', 'new-file', None, _('add new file at each rev'))],
1938 _('[OPTION]... [TEXT]'))
1924 _('[OPTION]... [TEXT]'))
1939 def debugbuilddag(ui, repo, text=None,
1925 def debugbuilddag(ui, repo, text=None,
1940 mergeable_file=False,
1926 mergeable_file=False,
1941 overwritten_file=False,
1927 overwritten_file=False,
1942 new_file=False):
1928 new_file=False):
1943 """builds a repo with a given DAG from scratch in the current empty repo
1929 """builds a repo with a given DAG from scratch in the current empty repo
1944
1930
1945 The description of the DAG is read from stdin if not given on the
1931 The description of the DAG is read from stdin if not given on the
1946 command line.
1932 command line.
1947
1933
1948 Elements:
1934 Elements:
1949
1935
1950 - "+n" is a linear run of n nodes based on the current default parent
1936 - "+n" is a linear run of n nodes based on the current default parent
1951 - "." is a single node based on the current default parent
1937 - "." is a single node based on the current default parent
1952 - "$" resets the default parent to null (implied at the start);
1938 - "$" resets the default parent to null (implied at the start);
1953 otherwise the default parent is always the last node created
1939 otherwise the default parent is always the last node created
1954 - "<p" sets the default parent to the backref p
1940 - "<p" sets the default parent to the backref p
1955 - "*p" is a fork at parent p, which is a backref
1941 - "*p" is a fork at parent p, which is a backref
1956 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1942 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1957 - "/p2" is a merge of the preceding node and p2
1943 - "/p2" is a merge of the preceding node and p2
1958 - ":tag" defines a local tag for the preceding node
1944 - ":tag" defines a local tag for the preceding node
1959 - "@branch" sets the named branch for subsequent nodes
1945 - "@branch" sets the named branch for subsequent nodes
1960 - "#...\\n" is a comment up to the end of the line
1946 - "#...\\n" is a comment up to the end of the line
1961
1947
1962 Whitespace between the above elements is ignored.
1948 Whitespace between the above elements is ignored.
1963
1949
1964 A backref is either
1950 A backref is either
1965
1951
1966 - a number n, which references the node curr-n, where curr is the current
1952 - a number n, which references the node curr-n, where curr is the current
1967 node, or
1953 node, or
1968 - the name of a local tag you placed earlier using ":tag", or
1954 - the name of a local tag you placed earlier using ":tag", or
1969 - empty to denote the default parent.
1955 - empty to denote the default parent.
1970
1956
1971 All string valued-elements are either strictly alphanumeric, or must
1957 All string valued-elements are either strictly alphanumeric, or must
1972 be enclosed in double quotes ("..."), with "\\" as escape character.
1958 be enclosed in double quotes ("..."), with "\\" as escape character.
1973 """
1959 """
1974
1960
1975 if text is None:
1961 if text is None:
1976 ui.status(_("reading DAG from stdin\n"))
1962 ui.status(_("reading DAG from stdin\n"))
1977 text = ui.fin.read()
1963 text = ui.fin.read()
1978
1964
1979 cl = repo.changelog
1965 cl = repo.changelog
1980 if len(cl) > 0:
1966 if len(cl) > 0:
1981 raise error.Abort(_('repository is not empty'))
1967 raise error.Abort(_('repository is not empty'))
1982
1968
1983 # determine number of revs in DAG
1969 # determine number of revs in DAG
1984 total = 0
1970 total = 0
1985 for type, data in dagparser.parsedag(text):
1971 for type, data in dagparser.parsedag(text):
1986 if type == 'n':
1972 if type == 'n':
1987 total += 1
1973 total += 1
1988
1974
1989 if mergeable_file:
1975 if mergeable_file:
1990 linesperrev = 2
1976 linesperrev = 2
1991 # make a file with k lines per rev
1977 # make a file with k lines per rev
1992 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1978 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1993 initialmergedlines.append("")
1979 initialmergedlines.append("")
1994
1980
1995 tags = []
1981 tags = []
1996
1982
1997 wlock = lock = tr = None
1983 wlock = lock = tr = None
1998 try:
1984 try:
1999 wlock = repo.wlock()
1985 wlock = repo.wlock()
2000 lock = repo.lock()
1986 lock = repo.lock()
2001 tr = repo.transaction("builddag")
1987 tr = repo.transaction("builddag")
2002
1988
2003 at = -1
1989 at = -1
2004 atbranch = 'default'
1990 atbranch = 'default'
2005 nodeids = []
1991 nodeids = []
2006 id = 0
1992 id = 0
2007 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1993 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2008 for type, data in dagparser.parsedag(text):
1994 for type, data in dagparser.parsedag(text):
2009 if type == 'n':
1995 if type == 'n':
2010 ui.note(('node %s\n' % str(data)))
1996 ui.note(('node %s\n' % str(data)))
2011 id, ps = data
1997 id, ps = data
2012
1998
2013 files = []
1999 files = []
2014 fctxs = {}
2000 fctxs = {}
2015
2001
2016 p2 = None
2002 p2 = None
2017 if mergeable_file:
2003 if mergeable_file:
2018 fn = "mf"
2004 fn = "mf"
2019 p1 = repo[ps[0]]
2005 p1 = repo[ps[0]]
2020 if len(ps) > 1:
2006 if len(ps) > 1:
2021 p2 = repo[ps[1]]
2007 p2 = repo[ps[1]]
2022 pa = p1.ancestor(p2)
2008 pa = p1.ancestor(p2)
2023 base, local, other = [x[fn].data() for x in (pa, p1,
2009 base, local, other = [x[fn].data() for x in (pa, p1,
2024 p2)]
2010 p2)]
2025 m3 = simplemerge.Merge3Text(base, local, other)
2011 m3 = simplemerge.Merge3Text(base, local, other)
2026 ml = [l.strip() for l in m3.merge_lines()]
2012 ml = [l.strip() for l in m3.merge_lines()]
2027 ml.append("")
2013 ml.append("")
2028 elif at > 0:
2014 elif at > 0:
2029 ml = p1[fn].data().split("\n")
2015 ml = p1[fn].data().split("\n")
2030 else:
2016 else:
2031 ml = initialmergedlines
2017 ml = initialmergedlines
2032 ml[id * linesperrev] += " r%i" % id
2018 ml[id * linesperrev] += " r%i" % id
2033 mergedtext = "\n".join(ml)
2019 mergedtext = "\n".join(ml)
2034 files.append(fn)
2020 files.append(fn)
2035 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
2021 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
2036
2022
2037 if overwritten_file:
2023 if overwritten_file:
2038 fn = "of"
2024 fn = "of"
2039 files.append(fn)
2025 files.append(fn)
2040 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2026 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2041
2027
2042 if new_file:
2028 if new_file:
2043 fn = "nf%i" % id
2029 fn = "nf%i" % id
2044 files.append(fn)
2030 files.append(fn)
2045 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2031 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2046 if len(ps) > 1:
2032 if len(ps) > 1:
2047 if not p2:
2033 if not p2:
2048 p2 = repo[ps[1]]
2034 p2 = repo[ps[1]]
2049 for fn in p2:
2035 for fn in p2:
2050 if fn.startswith("nf"):
2036 if fn.startswith("nf"):
2051 files.append(fn)
2037 files.append(fn)
2052 fctxs[fn] = p2[fn]
2038 fctxs[fn] = p2[fn]
2053
2039
2054 def fctxfn(repo, cx, path):
2040 def fctxfn(repo, cx, path):
2055 return fctxs.get(path)
2041 return fctxs.get(path)
2056
2042
2057 if len(ps) == 0 or ps[0] < 0:
2043 if len(ps) == 0 or ps[0] < 0:
2058 pars = [None, None]
2044 pars = [None, None]
2059 elif len(ps) == 1:
2045 elif len(ps) == 1:
2060 pars = [nodeids[ps[0]], None]
2046 pars = [nodeids[ps[0]], None]
2061 else:
2047 else:
2062 pars = [nodeids[p] for p in ps]
2048 pars = [nodeids[p] for p in ps]
2063 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2049 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2064 date=(id, 0),
2050 date=(id, 0),
2065 user="debugbuilddag",
2051 user="debugbuilddag",
2066 extra={'branch': atbranch})
2052 extra={'branch': atbranch})
2067 nodeid = repo.commitctx(cx)
2053 nodeid = repo.commitctx(cx)
2068 nodeids.append(nodeid)
2054 nodeids.append(nodeid)
2069 at = id
2055 at = id
2070 elif type == 'l':
2056 elif type == 'l':
2071 id, name = data
2057 id, name = data
2072 ui.note(('tag %s\n' % name))
2058 ui.note(('tag %s\n' % name))
2073 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2059 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2074 elif type == 'a':
2060 elif type == 'a':
2075 ui.note(('branch %s\n' % data))
2061 ui.note(('branch %s\n' % data))
2076 atbranch = data
2062 atbranch = data
2077 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2063 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2078 tr.close()
2064 tr.close()
2079
2065
2080 if tags:
2066 if tags:
2081 repo.vfs.write("localtags", "".join(tags))
2067 repo.vfs.write("localtags", "".join(tags))
2082 finally:
2068 finally:
2083 ui.progress(_('building'), None)
2069 ui.progress(_('building'), None)
2084 release(tr, lock, wlock)
2070 release(tr, lock, wlock)
2085
2071
2086 @command('debugbundle',
2072 @command('debugbundle',
2087 [('a', 'all', None, _('show all details')),
2073 [('a', 'all', None, _('show all details')),
2088 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2074 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2089 _('FILE'),
2075 _('FILE'),
2090 norepo=True)
2076 norepo=True)
2091 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2077 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2092 """lists the contents of a bundle"""
2078 """lists the contents of a bundle"""
2093 with hg.openpath(ui, bundlepath) as f:
2079 with hg.openpath(ui, bundlepath) as f:
2094 if spec:
2080 if spec:
2095 spec = exchange.getbundlespec(ui, f)
2081 spec = exchange.getbundlespec(ui, f)
2096 ui.write('%s\n' % spec)
2082 ui.write('%s\n' % spec)
2097 return
2083 return
2098
2084
2099 gen = exchange.readbundle(ui, f, bundlepath)
2085 gen = exchange.readbundle(ui, f, bundlepath)
2100 if isinstance(gen, bundle2.unbundle20):
2086 if isinstance(gen, bundle2.unbundle20):
2101 return _debugbundle2(ui, gen, all=all, **opts)
2087 return _debugbundle2(ui, gen, all=all, **opts)
2102 _debugchangegroup(ui, gen, all=all, **opts)
2088 _debugchangegroup(ui, gen, all=all, **opts)
2103
2089
2104 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2090 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2105 indent_string = ' ' * indent
2091 indent_string = ' ' * indent
2106 if all:
2092 if all:
2107 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2093 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2108 % indent_string)
2094 % indent_string)
2109
2095
2110 def showchunks(named):
2096 def showchunks(named):
2111 ui.write("\n%s%s\n" % (indent_string, named))
2097 ui.write("\n%s%s\n" % (indent_string, named))
2112 chain = None
2098 chain = None
2113 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2099 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2114 node = chunkdata['node']
2100 node = chunkdata['node']
2115 p1 = chunkdata['p1']
2101 p1 = chunkdata['p1']
2116 p2 = chunkdata['p2']
2102 p2 = chunkdata['p2']
2117 cs = chunkdata['cs']
2103 cs = chunkdata['cs']
2118 deltabase = chunkdata['deltabase']
2104 deltabase = chunkdata['deltabase']
2119 delta = chunkdata['delta']
2105 delta = chunkdata['delta']
2120 ui.write("%s%s %s %s %s %s %s\n" %
2106 ui.write("%s%s %s %s %s %s %s\n" %
2121 (indent_string, hex(node), hex(p1), hex(p2),
2107 (indent_string, hex(node), hex(p1), hex(p2),
2122 hex(cs), hex(deltabase), len(delta)))
2108 hex(cs), hex(deltabase), len(delta)))
2123 chain = node
2109 chain = node
2124
2110
2125 chunkdata = gen.changelogheader()
2111 chunkdata = gen.changelogheader()
2126 showchunks("changelog")
2112 showchunks("changelog")
2127 chunkdata = gen.manifestheader()
2113 chunkdata = gen.manifestheader()
2128 showchunks("manifest")
2114 showchunks("manifest")
2129 for chunkdata in iter(gen.filelogheader, {}):
2115 for chunkdata in iter(gen.filelogheader, {}):
2130 fname = chunkdata['filename']
2116 fname = chunkdata['filename']
2131 showchunks(fname)
2117 showchunks(fname)
2132 else:
2118 else:
2133 if isinstance(gen, bundle2.unbundle20):
2119 if isinstance(gen, bundle2.unbundle20):
2134 raise error.Abort(_('use debugbundle2 for this file'))
2120 raise error.Abort(_('use debugbundle2 for this file'))
2135 chunkdata = gen.changelogheader()
2121 chunkdata = gen.changelogheader()
2136 chain = None
2122 chain = None
2137 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2123 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2138 node = chunkdata['node']
2124 node = chunkdata['node']
2139 ui.write("%s%s\n" % (indent_string, hex(node)))
2125 ui.write("%s%s\n" % (indent_string, hex(node)))
2140 chain = node
2126 chain = node
2141
2127
2142 def _debugbundle2(ui, gen, all=None, **opts):
2128 def _debugbundle2(ui, gen, all=None, **opts):
2143 """lists the contents of a bundle2"""
2129 """lists the contents of a bundle2"""
2144 if not isinstance(gen, bundle2.unbundle20):
2130 if not isinstance(gen, bundle2.unbundle20):
2145 raise error.Abort(_('not a bundle2 file'))
2131 raise error.Abort(_('not a bundle2 file'))
2146 ui.write(('Stream params: %s\n' % repr(gen.params)))
2132 ui.write(('Stream params: %s\n' % repr(gen.params)))
2147 for part in gen.iterparts():
2133 for part in gen.iterparts():
2148 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2134 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2149 if part.type == 'changegroup':
2135 if part.type == 'changegroup':
2150 version = part.params.get('version', '01')
2136 version = part.params.get('version', '01')
2151 cg = changegroup.getunbundler(version, part, 'UN')
2137 cg = changegroup.getunbundler(version, part, 'UN')
2152 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2138 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2153
2139
2154 @command('debugcreatestreamclonebundle', [], 'FILE')
2140 @command('debugcreatestreamclonebundle', [], 'FILE')
2155 def debugcreatestreamclonebundle(ui, repo, fname):
2141 def debugcreatestreamclonebundle(ui, repo, fname):
2156 """create a stream clone bundle file
2142 """create a stream clone bundle file
2157
2143
2158 Stream bundles are special bundles that are essentially archives of
2144 Stream bundles are special bundles that are essentially archives of
2159 revlog files. They are commonly used for cloning very quickly.
2145 revlog files. They are commonly used for cloning very quickly.
2160 """
2146 """
2161 requirements, gen = streamclone.generatebundlev1(repo)
2147 requirements, gen = streamclone.generatebundlev1(repo)
2162 changegroup.writechunks(ui, gen, fname)
2148 changegroup.writechunks(ui, gen, fname)
2163
2149
2164 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2150 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2165
2151
2166 @command('debugapplystreamclonebundle', [], 'FILE')
2152 @command('debugapplystreamclonebundle', [], 'FILE')
2167 def debugapplystreamclonebundle(ui, repo, fname):
2153 def debugapplystreamclonebundle(ui, repo, fname):
2168 """apply a stream clone bundle file"""
2154 """apply a stream clone bundle file"""
2169 f = hg.openpath(ui, fname)
2155 f = hg.openpath(ui, fname)
2170 gen = exchange.readbundle(ui, f, fname)
2156 gen = exchange.readbundle(ui, f, fname)
2171 gen.apply(repo)
2157 gen.apply(repo)
2172
2158
2173 @command('debugcheckstate', [], '')
2159 @command('debugcheckstate', [], '')
2174 def debugcheckstate(ui, repo):
2160 def debugcheckstate(ui, repo):
2175 """validate the correctness of the current dirstate"""
2161 """validate the correctness of the current dirstate"""
2176 parent1, parent2 = repo.dirstate.parents()
2162 parent1, parent2 = repo.dirstate.parents()
2177 m1 = repo[parent1].manifest()
2163 m1 = repo[parent1].manifest()
2178 m2 = repo[parent2].manifest()
2164 m2 = repo[parent2].manifest()
2179 errors = 0
2165 errors = 0
2180 for f in repo.dirstate:
2166 for f in repo.dirstate:
2181 state = repo.dirstate[f]
2167 state = repo.dirstate[f]
2182 if state in "nr" and f not in m1:
2168 if state in "nr" and f not in m1:
2183 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2169 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2184 errors += 1
2170 errors += 1
2185 if state in "a" and f in m1:
2171 if state in "a" and f in m1:
2186 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2172 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2187 errors += 1
2173 errors += 1
2188 if state in "m" and f not in m1 and f not in m2:
2174 if state in "m" and f not in m1 and f not in m2:
2189 ui.warn(_("%s in state %s, but not in either manifest\n") %
2175 ui.warn(_("%s in state %s, but not in either manifest\n") %
2190 (f, state))
2176 (f, state))
2191 errors += 1
2177 errors += 1
2192 for f in m1:
2178 for f in m1:
2193 state = repo.dirstate[f]
2179 state = repo.dirstate[f]
2194 if state not in "nrm":
2180 if state not in "nrm":
2195 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2181 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2196 errors += 1
2182 errors += 1
2197 if errors:
2183 if errors:
2198 error = _(".hg/dirstate inconsistent with current parent's manifest")
2184 error = _(".hg/dirstate inconsistent with current parent's manifest")
2199 raise error.Abort(error)
2185 raise error.Abort(error)
2200
2186
2201 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2187 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2202 def debugcommands(ui, cmd='', *args):
2188 def debugcommands(ui, cmd='', *args):
2203 """list all available commands and options"""
2189 """list all available commands and options"""
2204 for cmd, vals in sorted(table.iteritems()):
2190 for cmd, vals in sorted(table.iteritems()):
2205 cmd = cmd.split('|')[0].strip('^')
2191 cmd = cmd.split('|')[0].strip('^')
2206 opts = ', '.join([i[1] for i in vals[1]])
2192 opts = ', '.join([i[1] for i in vals[1]])
2207 ui.write('%s: %s\n' % (cmd, opts))
2193 ui.write('%s: %s\n' % (cmd, opts))
2208
2194
2209 @command('debugcomplete',
2195 @command('debugcomplete',
2210 [('o', 'options', None, _('show the command options'))],
2196 [('o', 'options', None, _('show the command options'))],
2211 _('[-o] CMD'),
2197 _('[-o] CMD'),
2212 norepo=True)
2198 norepo=True)
2213 def debugcomplete(ui, cmd='', **opts):
2199 def debugcomplete(ui, cmd='', **opts):
2214 """returns the completion list associated with the given command"""
2200 """returns the completion list associated with the given command"""
2215
2201
2216 if opts.get('options'):
2202 if opts.get('options'):
2217 options = []
2203 options = []
2218 otables = [globalopts]
2204 otables = [globalopts]
2219 if cmd:
2205 if cmd:
2220 aliases, entry = cmdutil.findcmd(cmd, table, False)
2206 aliases, entry = cmdutil.findcmd(cmd, table, False)
2221 otables.append(entry[1])
2207 otables.append(entry[1])
2222 for t in otables:
2208 for t in otables:
2223 for o in t:
2209 for o in t:
2224 if "(DEPRECATED)" in o[3]:
2210 if "(DEPRECATED)" in o[3]:
2225 continue
2211 continue
2226 if o[0]:
2212 if o[0]:
2227 options.append('-%s' % o[0])
2213 options.append('-%s' % o[0])
2228 options.append('--%s' % o[1])
2214 options.append('--%s' % o[1])
2229 ui.write("%s\n" % "\n".join(options))
2215 ui.write("%s\n" % "\n".join(options))
2230 return
2216 return
2231
2217
2232 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2218 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2233 if ui.verbose:
2219 if ui.verbose:
2234 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2220 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2235 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2221 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2236
2222
2237 @command('debugdag',
2223 @command('debugdag',
2238 [('t', 'tags', None, _('use tags as labels')),
2224 [('t', 'tags', None, _('use tags as labels')),
2239 ('b', 'branches', None, _('annotate with branch names')),
2225 ('b', 'branches', None, _('annotate with branch names')),
2240 ('', 'dots', None, _('use dots for runs')),
2226 ('', 'dots', None, _('use dots for runs')),
2241 ('s', 'spaces', None, _('separate elements by spaces'))],
2227 ('s', 'spaces', None, _('separate elements by spaces'))],
2242 _('[OPTION]... [FILE [REV]...]'),
2228 _('[OPTION]... [FILE [REV]...]'),
2243 optionalrepo=True)
2229 optionalrepo=True)
2244 def debugdag(ui, repo, file_=None, *revs, **opts):
2230 def debugdag(ui, repo, file_=None, *revs, **opts):
2245 """format the changelog or an index DAG as a concise textual description
2231 """format the changelog or an index DAG as a concise textual description
2246
2232
2247 If you pass a revlog index, the revlog's DAG is emitted. If you list
2233 If you pass a revlog index, the revlog's DAG is emitted. If you list
2248 revision numbers, they get labeled in the output as rN.
2234 revision numbers, they get labeled in the output as rN.
2249
2235
2250 Otherwise, the changelog DAG of the current repo is emitted.
2236 Otherwise, the changelog DAG of the current repo is emitted.
2251 """
2237 """
2252 spaces = opts.get('spaces')
2238 spaces = opts.get('spaces')
2253 dots = opts.get('dots')
2239 dots = opts.get('dots')
2254 if file_:
2240 if file_:
2255 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2241 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2256 revs = set((int(r) for r in revs))
2242 revs = set((int(r) for r in revs))
2257 def events():
2243 def events():
2258 for r in rlog:
2244 for r in rlog:
2259 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2245 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2260 if p != -1))
2246 if p != -1))
2261 if r in revs:
2247 if r in revs:
2262 yield 'l', (r, "r%i" % r)
2248 yield 'l', (r, "r%i" % r)
2263 elif repo:
2249 elif repo:
2264 cl = repo.changelog
2250 cl = repo.changelog
2265 tags = opts.get('tags')
2251 tags = opts.get('tags')
2266 branches = opts.get('branches')
2252 branches = opts.get('branches')
2267 if tags:
2253 if tags:
2268 labels = {}
2254 labels = {}
2269 for l, n in repo.tags().items():
2255 for l, n in repo.tags().items():
2270 labels.setdefault(cl.rev(n), []).append(l)
2256 labels.setdefault(cl.rev(n), []).append(l)
2271 def events():
2257 def events():
2272 b = "default"
2258 b = "default"
2273 for r in cl:
2259 for r in cl:
2274 if branches:
2260 if branches:
2275 newb = cl.read(cl.node(r))[5]['branch']
2261 newb = cl.read(cl.node(r))[5]['branch']
2276 if newb != b:
2262 if newb != b:
2277 yield 'a', newb
2263 yield 'a', newb
2278 b = newb
2264 b = newb
2279 yield 'n', (r, list(p for p in cl.parentrevs(r)
2265 yield 'n', (r, list(p for p in cl.parentrevs(r)
2280 if p != -1))
2266 if p != -1))
2281 if tags:
2267 if tags:
2282 ls = labels.get(r)
2268 ls = labels.get(r)
2283 if ls:
2269 if ls:
2284 for l in ls:
2270 for l in ls:
2285 yield 'l', (r, l)
2271 yield 'l', (r, l)
2286 else:
2272 else:
2287 raise error.Abort(_('need repo for changelog dag'))
2273 raise error.Abort(_('need repo for changelog dag'))
2288
2274
2289 for line in dagparser.dagtextlines(events(),
2275 for line in dagparser.dagtextlines(events(),
2290 addspaces=spaces,
2276 addspaces=spaces,
2291 wraplabels=True,
2277 wraplabels=True,
2292 wrapannotations=True,
2278 wrapannotations=True,
2293 wrapnonlinear=dots,
2279 wrapnonlinear=dots,
2294 usedots=dots,
2280 usedots=dots,
2295 maxlinewidth=70):
2281 maxlinewidth=70):
2296 ui.write(line)
2282 ui.write(line)
2297 ui.write("\n")
2283 ui.write("\n")
2298
2284
2299 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2285 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2300 def debugdata(ui, repo, file_, rev=None, **opts):
2286 def debugdata(ui, repo, file_, rev=None, **opts):
2301 """dump the contents of a data file revision"""
2287 """dump the contents of a data file revision"""
2302 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2288 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2303 if rev is not None:
2289 if rev is not None:
2304 raise error.CommandError('debugdata', _('invalid arguments'))
2290 raise error.CommandError('debugdata', _('invalid arguments'))
2305 file_, rev = None, file_
2291 file_, rev = None, file_
2306 elif rev is None:
2292 elif rev is None:
2307 raise error.CommandError('debugdata', _('invalid arguments'))
2293 raise error.CommandError('debugdata', _('invalid arguments'))
2308 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2294 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2309 try:
2295 try:
2310 ui.write(r.revision(r.lookup(rev)))
2296 ui.write(r.revision(r.lookup(rev)))
2311 except KeyError:
2297 except KeyError:
2312 raise error.Abort(_('invalid revision identifier %s') % rev)
2298 raise error.Abort(_('invalid revision identifier %s') % rev)
2313
2299
2314 @command('debugdate',
2300 @command('debugdate',
2315 [('e', 'extended', None, _('try extended date formats'))],
2301 [('e', 'extended', None, _('try extended date formats'))],
2316 _('[-e] DATE [RANGE]'),
2302 _('[-e] DATE [RANGE]'),
2317 norepo=True, optionalrepo=True)
2303 norepo=True, optionalrepo=True)
2318 def debugdate(ui, date, range=None, **opts):
2304 def debugdate(ui, date, range=None, **opts):
2319 """parse and display a date"""
2305 """parse and display a date"""
2320 if opts["extended"]:
2306 if opts["extended"]:
2321 d = util.parsedate(date, util.extendeddateformats)
2307 d = util.parsedate(date, util.extendeddateformats)
2322 else:
2308 else:
2323 d = util.parsedate(date)
2309 d = util.parsedate(date)
2324 ui.write(("internal: %s %s\n") % d)
2310 ui.write(("internal: %s %s\n") % d)
2325 ui.write(("standard: %s\n") % util.datestr(d))
2311 ui.write(("standard: %s\n") % util.datestr(d))
2326 if range:
2312 if range:
2327 m = util.matchdate(range)
2313 m = util.matchdate(range)
2328 ui.write(("match: %s\n") % m(d[0]))
2314 ui.write(("match: %s\n") % m(d[0]))
2329
2315
2330 @command('debugdiscovery',
2316 @command('debugdiscovery',
2331 [('', 'old', None, _('use old-style discovery')),
2317 [('', 'old', None, _('use old-style discovery')),
2332 ('', 'nonheads', None,
2318 ('', 'nonheads', None,
2333 _('use old-style discovery with non-heads included')),
2319 _('use old-style discovery with non-heads included')),
2334 ] + remoteopts,
2320 ] + remoteopts,
2335 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2321 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2336 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2322 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2337 """runs the changeset discovery protocol in isolation"""
2323 """runs the changeset discovery protocol in isolation"""
2338 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2324 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2339 opts.get('branch'))
2325 opts.get('branch'))
2340 remote = hg.peer(repo, opts, remoteurl)
2326 remote = hg.peer(repo, opts, remoteurl)
2341 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2327 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2342
2328
2343 # make sure tests are repeatable
2329 # make sure tests are repeatable
2344 random.seed(12323)
2330 random.seed(12323)
2345
2331
2346 def doit(localheads, remoteheads, remote=remote):
2332 def doit(localheads, remoteheads, remote=remote):
2347 if opts.get('old'):
2333 if opts.get('old'):
2348 if localheads:
2334 if localheads:
2349 raise error.Abort('cannot use localheads with old style '
2335 raise error.Abort('cannot use localheads with old style '
2350 'discovery')
2336 'discovery')
2351 if not util.safehasattr(remote, 'branches'):
2337 if not util.safehasattr(remote, 'branches'):
2352 # enable in-client legacy support
2338 # enable in-client legacy support
2353 remote = localrepo.locallegacypeer(remote.local())
2339 remote = localrepo.locallegacypeer(remote.local())
2354 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2340 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2355 force=True)
2341 force=True)
2356 common = set(common)
2342 common = set(common)
2357 if not opts.get('nonheads'):
2343 if not opts.get('nonheads'):
2358 ui.write(("unpruned common: %s\n") %
2344 ui.write(("unpruned common: %s\n") %
2359 " ".join(sorted(short(n) for n in common)))
2345 " ".join(sorted(short(n) for n in common)))
2360 dag = dagutil.revlogdag(repo.changelog)
2346 dag = dagutil.revlogdag(repo.changelog)
2361 all = dag.ancestorset(dag.internalizeall(common))
2347 all = dag.ancestorset(dag.internalizeall(common))
2362 common = dag.externalizeall(dag.headsetofconnecteds(all))
2348 common = dag.externalizeall(dag.headsetofconnecteds(all))
2363 else:
2349 else:
2364 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2350 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2365 common = set(common)
2351 common = set(common)
2366 rheads = set(hds)
2352 rheads = set(hds)
2367 lheads = set(repo.heads())
2353 lheads = set(repo.heads())
2368 ui.write(("common heads: %s\n") %
2354 ui.write(("common heads: %s\n") %
2369 " ".join(sorted(short(n) for n in common)))
2355 " ".join(sorted(short(n) for n in common)))
2370 if lheads <= common:
2356 if lheads <= common:
2371 ui.write(("local is subset\n"))
2357 ui.write(("local is subset\n"))
2372 elif rheads <= common:
2358 elif rheads <= common:
2373 ui.write(("remote is subset\n"))
2359 ui.write(("remote is subset\n"))
2374
2360
2375 serverlogs = opts.get('serverlog')
2361 serverlogs = opts.get('serverlog')
2376 if serverlogs:
2362 if serverlogs:
2377 for filename in serverlogs:
2363 for filename in serverlogs:
2378 with open(filename, 'r') as logfile:
2364 with open(filename, 'r') as logfile:
2379 line = logfile.readline()
2365 line = logfile.readline()
2380 while line:
2366 while line:
2381 parts = line.strip().split(';')
2367 parts = line.strip().split(';')
2382 op = parts[1]
2368 op = parts[1]
2383 if op == 'cg':
2369 if op == 'cg':
2384 pass
2370 pass
2385 elif op == 'cgss':
2371 elif op == 'cgss':
2386 doit(parts[2].split(' '), parts[3].split(' '))
2372 doit(parts[2].split(' '), parts[3].split(' '))
2387 elif op == 'unb':
2373 elif op == 'unb':
2388 doit(parts[3].split(' '), parts[2].split(' '))
2374 doit(parts[3].split(' '), parts[2].split(' '))
2389 line = logfile.readline()
2375 line = logfile.readline()
2390 else:
2376 else:
2391 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2377 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2392 opts.get('remote_head'))
2378 opts.get('remote_head'))
2393 localrevs = opts.get('local_head')
2379 localrevs = opts.get('local_head')
2394 doit(localrevs, remoterevs)
2380 doit(localrevs, remoterevs)
2395
2381
2396 @command('debugextensions', formatteropts, [], norepo=True)
2382 @command('debugextensions', formatteropts, [], norepo=True)
2397 def debugextensions(ui, **opts):
2383 def debugextensions(ui, **opts):
2398 '''show information about active extensions'''
2384 '''show information about active extensions'''
2399 exts = extensions.extensions(ui)
2385 exts = extensions.extensions(ui)
2400 hgver = util.version()
2386 hgver = util.version()
2401 fm = ui.formatter('debugextensions', opts)
2387 fm = ui.formatter('debugextensions', opts)
2402 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2388 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2403 isinternal = extensions.ismoduleinternal(extmod)
2389 isinternal = extensions.ismoduleinternal(extmod)
2404 extsource = extmod.__file__
2390 extsource = extmod.__file__
2405 if isinternal:
2391 if isinternal:
2406 exttestedwith = [] # never expose magic string to users
2392 exttestedwith = [] # never expose magic string to users
2407 else:
2393 else:
2408 exttestedwith = getattr(extmod, 'testedwith', '').split()
2394 exttestedwith = getattr(extmod, 'testedwith', '').split()
2409 extbuglink = getattr(extmod, 'buglink', None)
2395 extbuglink = getattr(extmod, 'buglink', None)
2410
2396
2411 fm.startitem()
2397 fm.startitem()
2412
2398
2413 if ui.quiet or ui.verbose:
2399 if ui.quiet or ui.verbose:
2414 fm.write('name', '%s\n', extname)
2400 fm.write('name', '%s\n', extname)
2415 else:
2401 else:
2416 fm.write('name', '%s', extname)
2402 fm.write('name', '%s', extname)
2417 if isinternal or hgver in exttestedwith:
2403 if isinternal or hgver in exttestedwith:
2418 fm.plain('\n')
2404 fm.plain('\n')
2419 elif not exttestedwith:
2405 elif not exttestedwith:
2420 fm.plain(_(' (untested!)\n'))
2406 fm.plain(_(' (untested!)\n'))
2421 else:
2407 else:
2422 lasttestedversion = exttestedwith[-1]
2408 lasttestedversion = exttestedwith[-1]
2423 fm.plain(' (%s!)\n' % lasttestedversion)
2409 fm.plain(' (%s!)\n' % lasttestedversion)
2424
2410
2425 fm.condwrite(ui.verbose and extsource, 'source',
2411 fm.condwrite(ui.verbose and extsource, 'source',
2426 _(' location: %s\n'), extsource or "")
2412 _(' location: %s\n'), extsource or "")
2427
2413
2428 if ui.verbose:
2414 if ui.verbose:
2429 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2415 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2430 fm.data(bundled=isinternal)
2416 fm.data(bundled=isinternal)
2431
2417
2432 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2418 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2433 _(' tested with: %s\n'),
2419 _(' tested with: %s\n'),
2434 fm.formatlist(exttestedwith, name='ver'))
2420 fm.formatlist(exttestedwith, name='ver'))
2435
2421
2436 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2422 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2437 _(' bug reporting: %s\n'), extbuglink or "")
2423 _(' bug reporting: %s\n'), extbuglink or "")
2438
2424
2439 fm.end()
2425 fm.end()
2440
2426
2441 @command('debugfileset',
2427 @command('debugfileset',
2442 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2428 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2443 _('[-r REV] FILESPEC'))
2429 _('[-r REV] FILESPEC'))
2444 def debugfileset(ui, repo, expr, **opts):
2430 def debugfileset(ui, repo, expr, **opts):
2445 '''parse and apply a fileset specification'''
2431 '''parse and apply a fileset specification'''
2446 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2432 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2447 if ui.verbose:
2433 if ui.verbose:
2448 tree = fileset.parse(expr)
2434 tree = fileset.parse(expr)
2449 ui.note(fileset.prettyformat(tree), "\n")
2435 ui.note(fileset.prettyformat(tree), "\n")
2450
2436
2451 for f in ctx.getfileset(expr):
2437 for f in ctx.getfileset(expr):
2452 ui.write("%s\n" % f)
2438 ui.write("%s\n" % f)
2453
2439
2454 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2440 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2455 def debugfsinfo(ui, path="."):
2441 def debugfsinfo(ui, path="."):
2456 """show information detected about current filesystem"""
2442 """show information detected about current filesystem"""
2457 util.writefile('.debugfsinfo', '')
2443 util.writefile('.debugfsinfo', '')
2458 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2444 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2459 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2445 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2460 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2446 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2461 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2447 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2462 and 'yes' or 'no'))
2448 and 'yes' or 'no'))
2463 os.unlink('.debugfsinfo')
2449 os.unlink('.debugfsinfo')
2464
2450
2465 @command('debuggetbundle',
2451 @command('debuggetbundle',
2466 [('H', 'head', [], _('id of head node'), _('ID')),
2452 [('H', 'head', [], _('id of head node'), _('ID')),
2467 ('C', 'common', [], _('id of common node'), _('ID')),
2453 ('C', 'common', [], _('id of common node'), _('ID')),
2468 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2454 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2469 _('REPO FILE [-H|-C ID]...'),
2455 _('REPO FILE [-H|-C ID]...'),
2470 norepo=True)
2456 norepo=True)
2471 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2457 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2472 """retrieves a bundle from a repo
2458 """retrieves a bundle from a repo
2473
2459
2474 Every ID must be a full-length hex node id string. Saves the bundle to the
2460 Every ID must be a full-length hex node id string. Saves the bundle to the
2475 given file.
2461 given file.
2476 """
2462 """
2477 repo = hg.peer(ui, opts, repopath)
2463 repo = hg.peer(ui, opts, repopath)
2478 if not repo.capable('getbundle'):
2464 if not repo.capable('getbundle'):
2479 raise error.Abort("getbundle() not supported by target repository")
2465 raise error.Abort("getbundle() not supported by target repository")
2480 args = {}
2466 args = {}
2481 if common:
2467 if common:
2482 args['common'] = [bin(s) for s in common]
2468 args['common'] = [bin(s) for s in common]
2483 if head:
2469 if head:
2484 args['heads'] = [bin(s) for s in head]
2470 args['heads'] = [bin(s) for s in head]
2485 # TODO: get desired bundlecaps from command line.
2471 # TODO: get desired bundlecaps from command line.
2486 args['bundlecaps'] = None
2472 args['bundlecaps'] = None
2487 bundle = repo.getbundle('debug', **args)
2473 bundle = repo.getbundle('debug', **args)
2488
2474
2489 bundletype = opts.get('type', 'bzip2').lower()
2475 bundletype = opts.get('type', 'bzip2').lower()
2490 btypes = {'none': 'HG10UN',
2476 btypes = {'none': 'HG10UN',
2491 'bzip2': 'HG10BZ',
2477 'bzip2': 'HG10BZ',
2492 'gzip': 'HG10GZ',
2478 'gzip': 'HG10GZ',
2493 'bundle2': 'HG20'}
2479 'bundle2': 'HG20'}
2494 bundletype = btypes.get(bundletype)
2480 bundletype = btypes.get(bundletype)
2495 if bundletype not in bundle2.bundletypes:
2481 if bundletype not in bundle2.bundletypes:
2496 raise error.Abort(_('unknown bundle type specified with --type'))
2482 raise error.Abort(_('unknown bundle type specified with --type'))
2497 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2483 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2498
2484
2499 @command('debugignore', [], '[FILE]')
2485 @command('debugignore', [], '[FILE]')
2500 def debugignore(ui, repo, *files, **opts):
2486 def debugignore(ui, repo, *files, **opts):
2501 """display the combined ignore pattern and information about ignored files
2487 """display the combined ignore pattern and information about ignored files
2502
2488
2503 With no argument display the combined ignore pattern.
2489 With no argument display the combined ignore pattern.
2504
2490
2505 Given space separated file names, shows if the given file is ignored and
2491 Given space separated file names, shows if the given file is ignored and
2506 if so, show the ignore rule (file and line number) that matched it.
2492 if so, show the ignore rule (file and line number) that matched it.
2507 """
2493 """
2508 ignore = repo.dirstate._ignore
2494 ignore = repo.dirstate._ignore
2509 if not files:
2495 if not files:
2510 # Show all the patterns
2496 # Show all the patterns
2511 includepat = getattr(ignore, 'includepat', None)
2497 includepat = getattr(ignore, 'includepat', None)
2512 if includepat is not None:
2498 if includepat is not None:
2513 ui.write("%s\n" % includepat)
2499 ui.write("%s\n" % includepat)
2514 else:
2500 else:
2515 raise error.Abort(_("no ignore patterns found"))
2501 raise error.Abort(_("no ignore patterns found"))
2516 else:
2502 else:
2517 for f in files:
2503 for f in files:
2518 nf = util.normpath(f)
2504 nf = util.normpath(f)
2519 ignored = None
2505 ignored = None
2520 ignoredata = None
2506 ignoredata = None
2521 if nf != '.':
2507 if nf != '.':
2522 if ignore(nf):
2508 if ignore(nf):
2523 ignored = nf
2509 ignored = nf
2524 ignoredata = repo.dirstate._ignorefileandline(nf)
2510 ignoredata = repo.dirstate._ignorefileandline(nf)
2525 else:
2511 else:
2526 for p in util.finddirs(nf):
2512 for p in util.finddirs(nf):
2527 if ignore(p):
2513 if ignore(p):
2528 ignored = p
2514 ignored = p
2529 ignoredata = repo.dirstate._ignorefileandline(p)
2515 ignoredata = repo.dirstate._ignorefileandline(p)
2530 break
2516 break
2531 if ignored:
2517 if ignored:
2532 if ignored == nf:
2518 if ignored == nf:
2533 ui.write(_("%s is ignored\n") % f)
2519 ui.write(_("%s is ignored\n") % f)
2534 else:
2520 else:
2535 ui.write(_("%s is ignored because of "
2521 ui.write(_("%s is ignored because of "
2536 "containing folder %s\n")
2522 "containing folder %s\n")
2537 % (f, ignored))
2523 % (f, ignored))
2538 ignorefile, lineno, line = ignoredata
2524 ignorefile, lineno, line = ignoredata
2539 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2525 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2540 % (ignorefile, lineno, line))
2526 % (ignorefile, lineno, line))
2541 else:
2527 else:
2542 ui.write(_("%s is not ignored\n") % f)
2528 ui.write(_("%s is not ignored\n") % f)
2543
2529
2544 @command('debugindex', debugrevlogopts +
2530 @command('debugindex', debugrevlogopts +
2545 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2531 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2546 _('[-f FORMAT] -c|-m|FILE'),
2532 _('[-f FORMAT] -c|-m|FILE'),
2547 optionalrepo=True)
2533 optionalrepo=True)
2548 def debugindex(ui, repo, file_=None, **opts):
2534 def debugindex(ui, repo, file_=None, **opts):
2549 """dump the contents of an index file"""
2535 """dump the contents of an index file"""
2550 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2536 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2551 format = opts.get('format', 0)
2537 format = opts.get('format', 0)
2552 if format not in (0, 1):
2538 if format not in (0, 1):
2553 raise error.Abort(_("unknown format %d") % format)
2539 raise error.Abort(_("unknown format %d") % format)
2554
2540
2555 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2541 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2556 if generaldelta:
2542 if generaldelta:
2557 basehdr = ' delta'
2543 basehdr = ' delta'
2558 else:
2544 else:
2559 basehdr = ' base'
2545 basehdr = ' base'
2560
2546
2561 if ui.debugflag:
2547 if ui.debugflag:
2562 shortfn = hex
2548 shortfn = hex
2563 else:
2549 else:
2564 shortfn = short
2550 shortfn = short
2565
2551
2566 # There might not be anything in r, so have a sane default
2552 # There might not be anything in r, so have a sane default
2567 idlen = 12
2553 idlen = 12
2568 for i in r:
2554 for i in r:
2569 idlen = len(shortfn(r.node(i)))
2555 idlen = len(shortfn(r.node(i)))
2570 break
2556 break
2571
2557
2572 if format == 0:
2558 if format == 0:
2573 ui.write((" rev offset length " + basehdr + " linkrev"
2559 ui.write((" rev offset length " + basehdr + " linkrev"
2574 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2560 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2575 elif format == 1:
2561 elif format == 1:
2576 ui.write((" rev flag offset length"
2562 ui.write((" rev flag offset length"
2577 " size " + basehdr + " link p1 p2"
2563 " size " + basehdr + " link p1 p2"
2578 " %s\n") % "nodeid".rjust(idlen))
2564 " %s\n") % "nodeid".rjust(idlen))
2579
2565
2580 for i in r:
2566 for i in r:
2581 node = r.node(i)
2567 node = r.node(i)
2582 if generaldelta:
2568 if generaldelta:
2583 base = r.deltaparent(i)
2569 base = r.deltaparent(i)
2584 else:
2570 else:
2585 base = r.chainbase(i)
2571 base = r.chainbase(i)
2586 if format == 0:
2572 if format == 0:
2587 try:
2573 try:
2588 pp = r.parents(node)
2574 pp = r.parents(node)
2589 except Exception:
2575 except Exception:
2590 pp = [nullid, nullid]
2576 pp = [nullid, nullid]
2591 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2577 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2592 i, r.start(i), r.length(i), base, r.linkrev(i),
2578 i, r.start(i), r.length(i), base, r.linkrev(i),
2593 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2579 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2594 elif format == 1:
2580 elif format == 1:
2595 pr = r.parentrevs(i)
2581 pr = r.parentrevs(i)
2596 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2582 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2597 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2583 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2598 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2584 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2599
2585
2600 @command('debugindexdot', debugrevlogopts,
2586 @command('debugindexdot', debugrevlogopts,
2601 _('-c|-m|FILE'), optionalrepo=True)
2587 _('-c|-m|FILE'), optionalrepo=True)
2602 def debugindexdot(ui, repo, file_=None, **opts):
2588 def debugindexdot(ui, repo, file_=None, **opts):
2603 """dump an index DAG as a graphviz dot file"""
2589 """dump an index DAG as a graphviz dot file"""
2604 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2590 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2605 ui.write(("digraph G {\n"))
2591 ui.write(("digraph G {\n"))
2606 for i in r:
2592 for i in r:
2607 node = r.node(i)
2593 node = r.node(i)
2608 pp = r.parents(node)
2594 pp = r.parents(node)
2609 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2595 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2610 if pp[1] != nullid:
2596 if pp[1] != nullid:
2611 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2597 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2612 ui.write("}\n")
2598 ui.write("}\n")
2613
2599
2614 @command('debugdeltachain',
2600 @command('debugdeltachain',
2615 debugrevlogopts + formatteropts,
2601 debugrevlogopts + formatteropts,
2616 _('-c|-m|FILE'),
2602 _('-c|-m|FILE'),
2617 optionalrepo=True)
2603 optionalrepo=True)
2618 def debugdeltachain(ui, repo, file_=None, **opts):
2604 def debugdeltachain(ui, repo, file_=None, **opts):
2619 """dump information about delta chains in a revlog
2605 """dump information about delta chains in a revlog
2620
2606
2621 Output can be templatized. Available template keywords are:
2607 Output can be templatized. Available template keywords are:
2622
2608
2623 :``rev``: revision number
2609 :``rev``: revision number
2624 :``chainid``: delta chain identifier (numbered by unique base)
2610 :``chainid``: delta chain identifier (numbered by unique base)
2625 :``chainlen``: delta chain length to this revision
2611 :``chainlen``: delta chain length to this revision
2626 :``prevrev``: previous revision in delta chain
2612 :``prevrev``: previous revision in delta chain
2627 :``deltatype``: role of delta / how it was computed
2613 :``deltatype``: role of delta / how it was computed
2628 :``compsize``: compressed size of revision
2614 :``compsize``: compressed size of revision
2629 :``uncompsize``: uncompressed size of revision
2615 :``uncompsize``: uncompressed size of revision
2630 :``chainsize``: total size of compressed revisions in chain
2616 :``chainsize``: total size of compressed revisions in chain
2631 :``chainratio``: total chain size divided by uncompressed revision size
2617 :``chainratio``: total chain size divided by uncompressed revision size
2632 (new delta chains typically start at ratio 2.00)
2618 (new delta chains typically start at ratio 2.00)
2633 :``lindist``: linear distance from base revision in delta chain to end
2619 :``lindist``: linear distance from base revision in delta chain to end
2634 of this revision
2620 of this revision
2635 :``extradist``: total size of revisions not part of this delta chain from
2621 :``extradist``: total size of revisions not part of this delta chain from
2636 base of delta chain to end of this revision; a measurement
2622 base of delta chain to end of this revision; a measurement
2637 of how much extra data we need to read/seek across to read
2623 of how much extra data we need to read/seek across to read
2638 the delta chain for this revision
2624 the delta chain for this revision
2639 :``extraratio``: extradist divided by chainsize; another representation of
2625 :``extraratio``: extradist divided by chainsize; another representation of
2640 how much unrelated data is needed to load this delta chain
2626 how much unrelated data is needed to load this delta chain
2641 """
2627 """
2642 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2628 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2643 index = r.index
2629 index = r.index
2644 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2630 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2645
2631
2646 def revinfo(rev):
2632 def revinfo(rev):
2647 e = index[rev]
2633 e = index[rev]
2648 compsize = e[1]
2634 compsize = e[1]
2649 uncompsize = e[2]
2635 uncompsize = e[2]
2650 chainsize = 0
2636 chainsize = 0
2651
2637
2652 if generaldelta:
2638 if generaldelta:
2653 if e[3] == e[5]:
2639 if e[3] == e[5]:
2654 deltatype = 'p1'
2640 deltatype = 'p1'
2655 elif e[3] == e[6]:
2641 elif e[3] == e[6]:
2656 deltatype = 'p2'
2642 deltatype = 'p2'
2657 elif e[3] == rev - 1:
2643 elif e[3] == rev - 1:
2658 deltatype = 'prev'
2644 deltatype = 'prev'
2659 elif e[3] == rev:
2645 elif e[3] == rev:
2660 deltatype = 'base'
2646 deltatype = 'base'
2661 else:
2647 else:
2662 deltatype = 'other'
2648 deltatype = 'other'
2663 else:
2649 else:
2664 if e[3] == rev:
2650 if e[3] == rev:
2665 deltatype = 'base'
2651 deltatype = 'base'
2666 else:
2652 else:
2667 deltatype = 'prev'
2653 deltatype = 'prev'
2668
2654
2669 chain = r._deltachain(rev)[0]
2655 chain = r._deltachain(rev)[0]
2670 for iterrev in chain:
2656 for iterrev in chain:
2671 e = index[iterrev]
2657 e = index[iterrev]
2672 chainsize += e[1]
2658 chainsize += e[1]
2673
2659
2674 return compsize, uncompsize, deltatype, chain, chainsize
2660 return compsize, uncompsize, deltatype, chain, chainsize
2675
2661
2676 fm = ui.formatter('debugdeltachain', opts)
2662 fm = ui.formatter('debugdeltachain', opts)
2677
2663
2678 fm.plain(' rev chain# chainlen prev delta '
2664 fm.plain(' rev chain# chainlen prev delta '
2679 'size rawsize chainsize ratio lindist extradist '
2665 'size rawsize chainsize ratio lindist extradist '
2680 'extraratio\n')
2666 'extraratio\n')
2681
2667
2682 chainbases = {}
2668 chainbases = {}
2683 for rev in r:
2669 for rev in r:
2684 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2670 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2685 chainbase = chain[0]
2671 chainbase = chain[0]
2686 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2672 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2687 basestart = r.start(chainbase)
2673 basestart = r.start(chainbase)
2688 revstart = r.start(rev)
2674 revstart = r.start(rev)
2689 lineardist = revstart + comp - basestart
2675 lineardist = revstart + comp - basestart
2690 extradist = lineardist - chainsize
2676 extradist = lineardist - chainsize
2691 try:
2677 try:
2692 prevrev = chain[-2]
2678 prevrev = chain[-2]
2693 except IndexError:
2679 except IndexError:
2694 prevrev = -1
2680 prevrev = -1
2695
2681
2696 chainratio = float(chainsize) / float(uncomp)
2682 chainratio = float(chainsize) / float(uncomp)
2697 extraratio = float(extradist) / float(chainsize)
2683 extraratio = float(extradist) / float(chainsize)
2698
2684
2699 fm.startitem()
2685 fm.startitem()
2700 fm.write('rev chainid chainlen prevrev deltatype compsize '
2686 fm.write('rev chainid chainlen prevrev deltatype compsize '
2701 'uncompsize chainsize chainratio lindist extradist '
2687 'uncompsize chainsize chainratio lindist extradist '
2702 'extraratio',
2688 'extraratio',
2703 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2689 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2704 rev, chainid, len(chain), prevrev, deltatype, comp,
2690 rev, chainid, len(chain), prevrev, deltatype, comp,
2705 uncomp, chainsize, chainratio, lineardist, extradist,
2691 uncomp, chainsize, chainratio, lineardist, extradist,
2706 extraratio,
2692 extraratio,
2707 rev=rev, chainid=chainid, chainlen=len(chain),
2693 rev=rev, chainid=chainid, chainlen=len(chain),
2708 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2694 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2709 uncompsize=uncomp, chainsize=chainsize,
2695 uncompsize=uncomp, chainsize=chainsize,
2710 chainratio=chainratio, lindist=lineardist,
2696 chainratio=chainratio, lindist=lineardist,
2711 extradist=extradist, extraratio=extraratio)
2697 extradist=extradist, extraratio=extraratio)
2712
2698
2713 fm.end()
2699 fm.end()
2714
2700
2715 @command('debuginstall', [] + formatteropts, '', norepo=True)
2701 @command('debuginstall', [] + formatteropts, '', norepo=True)
2716 def debuginstall(ui, **opts):
2702 def debuginstall(ui, **opts):
2717 '''test Mercurial installation
2703 '''test Mercurial installation
2718
2704
2719 Returns 0 on success.
2705 Returns 0 on success.
2720 '''
2706 '''
2721
2707
2722 def writetemp(contents):
2708 def writetemp(contents):
2723 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2709 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2724 f = os.fdopen(fd, "wb")
2710 f = os.fdopen(fd, "wb")
2725 f.write(contents)
2711 f.write(contents)
2726 f.close()
2712 f.close()
2727 return name
2713 return name
2728
2714
2729 problems = 0
2715 problems = 0
2730
2716
2731 fm = ui.formatter('debuginstall', opts)
2717 fm = ui.formatter('debuginstall', opts)
2732 fm.startitem()
2718 fm.startitem()
2733
2719
2734 # encoding
2720 # encoding
2735 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2721 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2736 err = None
2722 err = None
2737 try:
2723 try:
2738 encoding.fromlocal("test")
2724 encoding.fromlocal("test")
2739 except error.Abort as inst:
2725 except error.Abort as inst:
2740 err = inst
2726 err = inst
2741 problems += 1
2727 problems += 1
2742 fm.condwrite(err, 'encodingerror', _(" %s\n"
2728 fm.condwrite(err, 'encodingerror', _(" %s\n"
2743 " (check that your locale is properly set)\n"), err)
2729 " (check that your locale is properly set)\n"), err)
2744
2730
2745 # Python
2731 # Python
2746 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2732 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2747 sys.executable)
2733 sys.executable)
2748 fm.write('pythonver', _("checking Python version (%s)\n"),
2734 fm.write('pythonver', _("checking Python version (%s)\n"),
2749 ("%s.%s.%s" % sys.version_info[:3]))
2735 ("%s.%s.%s" % sys.version_info[:3]))
2750 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2736 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2751 os.path.dirname(os.__file__))
2737 os.path.dirname(os.__file__))
2752
2738
2753 # hg version
2739 # hg version
2754 hgver = util.version()
2740 hgver = util.version()
2755 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2741 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2756 hgver.split('+')[0])
2742 hgver.split('+')[0])
2757 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2743 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2758 '+'.join(hgver.split('+')[1:]))
2744 '+'.join(hgver.split('+')[1:]))
2759
2745
2760 # compiled modules
2746 # compiled modules
2761 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2747 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2762 policy.policy)
2748 policy.policy)
2763 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2749 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2764 os.path.dirname(__file__))
2750 os.path.dirname(__file__))
2765
2751
2766 err = None
2752 err = None
2767 try:
2753 try:
2768 from . import (
2754 from . import (
2769 base85,
2755 base85,
2770 bdiff,
2756 bdiff,
2771 mpatch,
2757 mpatch,
2772 osutil,
2758 osutil,
2773 )
2759 )
2774 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2760 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2775 except Exception as inst:
2761 except Exception as inst:
2776 err = inst
2762 err = inst
2777 problems += 1
2763 problems += 1
2778 fm.condwrite(err, 'extensionserror', " %s\n", err)
2764 fm.condwrite(err, 'extensionserror', " %s\n", err)
2779
2765
2780 # templates
2766 # templates
2781 p = templater.templatepaths()
2767 p = templater.templatepaths()
2782 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2768 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2783 fm.condwrite(not p, '', _(" no template directories found\n"))
2769 fm.condwrite(not p, '', _(" no template directories found\n"))
2784 if p:
2770 if p:
2785 m = templater.templatepath("map-cmdline.default")
2771 m = templater.templatepath("map-cmdline.default")
2786 if m:
2772 if m:
2787 # template found, check if it is working
2773 # template found, check if it is working
2788 err = None
2774 err = None
2789 try:
2775 try:
2790 templater.templater.frommapfile(m)
2776 templater.templater.frommapfile(m)
2791 except Exception as inst:
2777 except Exception as inst:
2792 err = inst
2778 err = inst
2793 p = None
2779 p = None
2794 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2780 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2795 else:
2781 else:
2796 p = None
2782 p = None
2797 fm.condwrite(p, 'defaulttemplate',
2783 fm.condwrite(p, 'defaulttemplate',
2798 _("checking default template (%s)\n"), m)
2784 _("checking default template (%s)\n"), m)
2799 fm.condwrite(not m, 'defaulttemplatenotfound',
2785 fm.condwrite(not m, 'defaulttemplatenotfound',
2800 _(" template '%s' not found\n"), "default")
2786 _(" template '%s' not found\n"), "default")
2801 if not p:
2787 if not p:
2802 problems += 1
2788 problems += 1
2803 fm.condwrite(not p, '',
2789 fm.condwrite(not p, '',
2804 _(" (templates seem to have been installed incorrectly)\n"))
2790 _(" (templates seem to have been installed incorrectly)\n"))
2805
2791
2806 # editor
2792 # editor
2807 editor = ui.geteditor()
2793 editor = ui.geteditor()
2808 editor = util.expandpath(editor)
2794 editor = util.expandpath(editor)
2809 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2795 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2810 cmdpath = util.findexe(shlex.split(editor)[0])
2796 cmdpath = util.findexe(shlex.split(editor)[0])
2811 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2797 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2812 _(" No commit editor set and can't find %s in PATH\n"
2798 _(" No commit editor set and can't find %s in PATH\n"
2813 " (specify a commit editor in your configuration"
2799 " (specify a commit editor in your configuration"
2814 " file)\n"), not cmdpath and editor == 'vi' and editor)
2800 " file)\n"), not cmdpath and editor == 'vi' and editor)
2815 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2801 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2816 _(" Can't find editor '%s' in PATH\n"
2802 _(" Can't find editor '%s' in PATH\n"
2817 " (specify a commit editor in your configuration"
2803 " (specify a commit editor in your configuration"
2818 " file)\n"), not cmdpath and editor)
2804 " file)\n"), not cmdpath and editor)
2819 if not cmdpath and editor != 'vi':
2805 if not cmdpath and editor != 'vi':
2820 problems += 1
2806 problems += 1
2821
2807
2822 # check username
2808 # check username
2823 username = None
2809 username = None
2824 err = None
2810 err = None
2825 try:
2811 try:
2826 username = ui.username()
2812 username = ui.username()
2827 except error.Abort as e:
2813 except error.Abort as e:
2828 err = e
2814 err = e
2829 problems += 1
2815 problems += 1
2830
2816
2831 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2817 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2832 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2818 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2833 " (specify a username in your configuration file)\n"), err)
2819 " (specify a username in your configuration file)\n"), err)
2834
2820
2835 fm.condwrite(not problems, '',
2821 fm.condwrite(not problems, '',
2836 _("no problems detected\n"))
2822 _("no problems detected\n"))
2837 if not problems:
2823 if not problems:
2838 fm.data(problems=problems)
2824 fm.data(problems=problems)
2839 fm.condwrite(problems, 'problems',
2825 fm.condwrite(problems, 'problems',
2840 _("%s problems detected,"
2826 _("%s problems detected,"
2841 " please check your install!\n"), problems)
2827 " please check your install!\n"), problems)
2842 fm.end()
2828 fm.end()
2843
2829
2844 return problems
2830 return problems
2845
2831
2846 @command('debugknown', [], _('REPO ID...'), norepo=True)
2832 @command('debugknown', [], _('REPO ID...'), norepo=True)
2847 def debugknown(ui, repopath, *ids, **opts):
2833 def debugknown(ui, repopath, *ids, **opts):
2848 """test whether node ids are known to a repo
2834 """test whether node ids are known to a repo
2849
2835
2850 Every ID must be a full-length hex node id string. Returns a list of 0s
2836 Every ID must be a full-length hex node id string. Returns a list of 0s
2851 and 1s indicating unknown/known.
2837 and 1s indicating unknown/known.
2852 """
2838 """
2853 repo = hg.peer(ui, opts, repopath)
2839 repo = hg.peer(ui, opts, repopath)
2854 if not repo.capable('known'):
2840 if not repo.capable('known'):
2855 raise error.Abort("known() not supported by target repository")
2841 raise error.Abort("known() not supported by target repository")
2856 flags = repo.known([bin(s) for s in ids])
2842 flags = repo.known([bin(s) for s in ids])
2857 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2843 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2858
2844
2859 @command('debuglabelcomplete', [], _('LABEL...'))
2845 @command('debuglabelcomplete', [], _('LABEL...'))
2860 def debuglabelcomplete(ui, repo, *args):
2846 def debuglabelcomplete(ui, repo, *args):
2861 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2847 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2862 debugnamecomplete(ui, repo, *args)
2848 debugnamecomplete(ui, repo, *args)
2863
2849
2864 @command('debugmergestate', [], '')
2850 @command('debugmergestate', [], '')
2865 def debugmergestate(ui, repo, *args):
2851 def debugmergestate(ui, repo, *args):
2866 """print merge state
2852 """print merge state
2867
2853
2868 Use --verbose to print out information about whether v1 or v2 merge state
2854 Use --verbose to print out information about whether v1 or v2 merge state
2869 was chosen."""
2855 was chosen."""
2870 def _hashornull(h):
2856 def _hashornull(h):
2871 if h == nullhex:
2857 if h == nullhex:
2872 return 'null'
2858 return 'null'
2873 else:
2859 else:
2874 return h
2860 return h
2875
2861
2876 def printrecords(version):
2862 def printrecords(version):
2877 ui.write(('* version %s records\n') % version)
2863 ui.write(('* version %s records\n') % version)
2878 if version == 1:
2864 if version == 1:
2879 records = v1records
2865 records = v1records
2880 else:
2866 else:
2881 records = v2records
2867 records = v2records
2882
2868
2883 for rtype, record in records:
2869 for rtype, record in records:
2884 # pretty print some record types
2870 # pretty print some record types
2885 if rtype == 'L':
2871 if rtype == 'L':
2886 ui.write(('local: %s\n') % record)
2872 ui.write(('local: %s\n') % record)
2887 elif rtype == 'O':
2873 elif rtype == 'O':
2888 ui.write(('other: %s\n') % record)
2874 ui.write(('other: %s\n') % record)
2889 elif rtype == 'm':
2875 elif rtype == 'm':
2890 driver, mdstate = record.split('\0', 1)
2876 driver, mdstate = record.split('\0', 1)
2891 ui.write(('merge driver: %s (state "%s")\n')
2877 ui.write(('merge driver: %s (state "%s")\n')
2892 % (driver, mdstate))
2878 % (driver, mdstate))
2893 elif rtype in 'FDC':
2879 elif rtype in 'FDC':
2894 r = record.split('\0')
2880 r = record.split('\0')
2895 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2881 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2896 if version == 1:
2882 if version == 1:
2897 onode = 'not stored in v1 format'
2883 onode = 'not stored in v1 format'
2898 flags = r[7]
2884 flags = r[7]
2899 else:
2885 else:
2900 onode, flags = r[7:9]
2886 onode, flags = r[7:9]
2901 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2887 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2902 % (f, rtype, state, _hashornull(hash)))
2888 % (f, rtype, state, _hashornull(hash)))
2903 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2889 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2904 ui.write((' ancestor path: %s (node %s)\n')
2890 ui.write((' ancestor path: %s (node %s)\n')
2905 % (afile, _hashornull(anode)))
2891 % (afile, _hashornull(anode)))
2906 ui.write((' other path: %s (node %s)\n')
2892 ui.write((' other path: %s (node %s)\n')
2907 % (ofile, _hashornull(onode)))
2893 % (ofile, _hashornull(onode)))
2908 elif rtype == 'f':
2894 elif rtype == 'f':
2909 filename, rawextras = record.split('\0', 1)
2895 filename, rawextras = record.split('\0', 1)
2910 extras = rawextras.split('\0')
2896 extras = rawextras.split('\0')
2911 i = 0
2897 i = 0
2912 extrastrings = []
2898 extrastrings = []
2913 while i < len(extras):
2899 while i < len(extras):
2914 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2900 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2915 i += 2
2901 i += 2
2916
2902
2917 ui.write(('file extras: %s (%s)\n')
2903 ui.write(('file extras: %s (%s)\n')
2918 % (filename, ', '.join(extrastrings)))
2904 % (filename, ', '.join(extrastrings)))
2919 elif rtype == 'l':
2905 elif rtype == 'l':
2920 labels = record.split('\0', 2)
2906 labels = record.split('\0', 2)
2921 labels = [l for l in labels if len(l) > 0]
2907 labels = [l for l in labels if len(l) > 0]
2922 ui.write(('labels:\n'))
2908 ui.write(('labels:\n'))
2923 ui.write((' local: %s\n' % labels[0]))
2909 ui.write((' local: %s\n' % labels[0]))
2924 ui.write((' other: %s\n' % labels[1]))
2910 ui.write((' other: %s\n' % labels[1]))
2925 if len(labels) > 2:
2911 if len(labels) > 2:
2926 ui.write((' base: %s\n' % labels[2]))
2912 ui.write((' base: %s\n' % labels[2]))
2927 else:
2913 else:
2928 ui.write(('unrecognized entry: %s\t%s\n')
2914 ui.write(('unrecognized entry: %s\t%s\n')
2929 % (rtype, record.replace('\0', '\t')))
2915 % (rtype, record.replace('\0', '\t')))
2930
2916
2931 # Avoid mergestate.read() since it may raise an exception for unsupported
2917 # Avoid mergestate.read() since it may raise an exception for unsupported
2932 # merge state records. We shouldn't be doing this, but this is OK since this
2918 # merge state records. We shouldn't be doing this, but this is OK since this
2933 # command is pretty low-level.
2919 # command is pretty low-level.
2934 ms = mergemod.mergestate(repo)
2920 ms = mergemod.mergestate(repo)
2935
2921
2936 # sort so that reasonable information is on top
2922 # sort so that reasonable information is on top
2937 v1records = ms._readrecordsv1()
2923 v1records = ms._readrecordsv1()
2938 v2records = ms._readrecordsv2()
2924 v2records = ms._readrecordsv2()
2939 order = 'LOml'
2925 order = 'LOml'
2940 def key(r):
2926 def key(r):
2941 idx = order.find(r[0])
2927 idx = order.find(r[0])
2942 if idx == -1:
2928 if idx == -1:
2943 return (1, r[1])
2929 return (1, r[1])
2944 else:
2930 else:
2945 return (0, idx)
2931 return (0, idx)
2946 v1records.sort(key=key)
2932 v1records.sort(key=key)
2947 v2records.sort(key=key)
2933 v2records.sort(key=key)
2948
2934
2949 if not v1records and not v2records:
2935 if not v1records and not v2records:
2950 ui.write(('no merge state found\n'))
2936 ui.write(('no merge state found\n'))
2951 elif not v2records:
2937 elif not v2records:
2952 ui.note(('no version 2 merge state\n'))
2938 ui.note(('no version 2 merge state\n'))
2953 printrecords(1)
2939 printrecords(1)
2954 elif ms._v1v2match(v1records, v2records):
2940 elif ms._v1v2match(v1records, v2records):
2955 ui.note(('v1 and v2 states match: using v2\n'))
2941 ui.note(('v1 and v2 states match: using v2\n'))
2956 printrecords(2)
2942 printrecords(2)
2957 else:
2943 else:
2958 ui.note(('v1 and v2 states mismatch: using v1\n'))
2944 ui.note(('v1 and v2 states mismatch: using v1\n'))
2959 printrecords(1)
2945 printrecords(1)
2960 if ui.verbose:
2946 if ui.verbose:
2961 printrecords(2)
2947 printrecords(2)
2962
2948
2963 @command('debugnamecomplete', [], _('NAME...'))
2949 @command('debugnamecomplete', [], _('NAME...'))
2964 def debugnamecomplete(ui, repo, *args):
2950 def debugnamecomplete(ui, repo, *args):
2965 '''complete "names" - tags, open branch names, bookmark names'''
2951 '''complete "names" - tags, open branch names, bookmark names'''
2966
2952
2967 names = set()
2953 names = set()
2968 # since we previously only listed open branches, we will handle that
2954 # since we previously only listed open branches, we will handle that
2969 # specially (after this for loop)
2955 # specially (after this for loop)
2970 for name, ns in repo.names.iteritems():
2956 for name, ns in repo.names.iteritems():
2971 if name != 'branches':
2957 if name != 'branches':
2972 names.update(ns.listnames(repo))
2958 names.update(ns.listnames(repo))
2973 names.update(tag for (tag, heads, tip, closed)
2959 names.update(tag for (tag, heads, tip, closed)
2974 in repo.branchmap().iterbranches() if not closed)
2960 in repo.branchmap().iterbranches() if not closed)
2975 completions = set()
2961 completions = set()
2976 if not args:
2962 if not args:
2977 args = ['']
2963 args = ['']
2978 for a in args:
2964 for a in args:
2979 completions.update(n for n in names if n.startswith(a))
2965 completions.update(n for n in names if n.startswith(a))
2980 ui.write('\n'.join(sorted(completions)))
2966 ui.write('\n'.join(sorted(completions)))
2981 ui.write('\n')
2967 ui.write('\n')
2982
2968
2983 @command('debuglocks',
2969 @command('debuglocks',
2984 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2970 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2985 ('W', 'force-wlock', None,
2971 ('W', 'force-wlock', None,
2986 _('free the working state lock (DANGEROUS)'))],
2972 _('free the working state lock (DANGEROUS)'))],
2987 _('[OPTION]...'))
2973 _('[OPTION]...'))
2988 def debuglocks(ui, repo, **opts):
2974 def debuglocks(ui, repo, **opts):
2989 """show or modify state of locks
2975 """show or modify state of locks
2990
2976
2991 By default, this command will show which locks are held. This
2977 By default, this command will show which locks are held. This
2992 includes the user and process holding the lock, the amount of time
2978 includes the user and process holding the lock, the amount of time
2993 the lock has been held, and the machine name where the process is
2979 the lock has been held, and the machine name where the process is
2994 running if it's not local.
2980 running if it's not local.
2995
2981
2996 Locks protect the integrity of Mercurial's data, so should be
2982 Locks protect the integrity of Mercurial's data, so should be
2997 treated with care. System crashes or other interruptions may cause
2983 treated with care. System crashes or other interruptions may cause
2998 locks to not be properly released, though Mercurial will usually
2984 locks to not be properly released, though Mercurial will usually
2999 detect and remove such stale locks automatically.
2985 detect and remove such stale locks automatically.
3000
2986
3001 However, detecting stale locks may not always be possible (for
2987 However, detecting stale locks may not always be possible (for
3002 instance, on a shared filesystem). Removing locks may also be
2988 instance, on a shared filesystem). Removing locks may also be
3003 blocked by filesystem permissions.
2989 blocked by filesystem permissions.
3004
2990
3005 Returns 0 if no locks are held.
2991 Returns 0 if no locks are held.
3006
2992
3007 """
2993 """
3008
2994
3009 if opts.get('force_lock'):
2995 if opts.get('force_lock'):
3010 repo.svfs.unlink('lock')
2996 repo.svfs.unlink('lock')
3011 if opts.get('force_wlock'):
2997 if opts.get('force_wlock'):
3012 repo.vfs.unlink('wlock')
2998 repo.vfs.unlink('wlock')
3013 if opts.get('force_lock') or opts.get('force_lock'):
2999 if opts.get('force_lock') or opts.get('force_lock'):
3014 return 0
3000 return 0
3015
3001
3016 now = time.time()
3002 now = time.time()
3017 held = 0
3003 held = 0
3018
3004
3019 def report(vfs, name, method):
3005 def report(vfs, name, method):
3020 # this causes stale locks to get reaped for more accurate reporting
3006 # this causes stale locks to get reaped for more accurate reporting
3021 try:
3007 try:
3022 l = method(False)
3008 l = method(False)
3023 except error.LockHeld:
3009 except error.LockHeld:
3024 l = None
3010 l = None
3025
3011
3026 if l:
3012 if l:
3027 l.release()
3013 l.release()
3028 else:
3014 else:
3029 try:
3015 try:
3030 stat = vfs.lstat(name)
3016 stat = vfs.lstat(name)
3031 age = now - stat.st_mtime
3017 age = now - stat.st_mtime
3032 user = util.username(stat.st_uid)
3018 user = util.username(stat.st_uid)
3033 locker = vfs.readlock(name)
3019 locker = vfs.readlock(name)
3034 if ":" in locker:
3020 if ":" in locker:
3035 host, pid = locker.split(':')
3021 host, pid = locker.split(':')
3036 if host == socket.gethostname():
3022 if host == socket.gethostname():
3037 locker = 'user %s, process %s' % (user, pid)
3023 locker = 'user %s, process %s' % (user, pid)
3038 else:
3024 else:
3039 locker = 'user %s, process %s, host %s' \
3025 locker = 'user %s, process %s, host %s' \
3040 % (user, pid, host)
3026 % (user, pid, host)
3041 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
3027 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
3042 return 1
3028 return 1
3043 except OSError as e:
3029 except OSError as e:
3044 if e.errno != errno.ENOENT:
3030 if e.errno != errno.ENOENT:
3045 raise
3031 raise
3046
3032
3047 ui.write(("%-6s free\n") % (name + ":"))
3033 ui.write(("%-6s free\n") % (name + ":"))
3048 return 0
3034 return 0
3049
3035
3050 held += report(repo.svfs, "lock", repo.lock)
3036 held += report(repo.svfs, "lock", repo.lock)
3051 held += report(repo.vfs, "wlock", repo.wlock)
3037 held += report(repo.vfs, "wlock", repo.wlock)
3052
3038
3053 return held
3039 return held
3054
3040
3055 @command('debugobsolete',
3041 @command('debugobsolete',
3056 [('', 'flags', 0, _('markers flag')),
3042 [('', 'flags', 0, _('markers flag')),
3057 ('', 'record-parents', False,
3043 ('', 'record-parents', False,
3058 _('record parent information for the precursor')),
3044 _('record parent information for the precursor')),
3059 ('r', 'rev', [], _('display markers relevant to REV')),
3045 ('r', 'rev', [], _('display markers relevant to REV')),
3060 ('', 'index', False, _('display index of the marker')),
3046 ('', 'index', False, _('display index of the marker')),
3061 ('', 'delete', [], _('delete markers specified by indices')),
3047 ('', 'delete', [], _('delete markers specified by indices')),
3062 ] + commitopts2 + formatteropts,
3048 ] + commitopts2 + formatteropts,
3063 _('[OBSOLETED [REPLACEMENT ...]]'))
3049 _('[OBSOLETED [REPLACEMENT ...]]'))
3064 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3050 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3065 """create arbitrary obsolete marker
3051 """create arbitrary obsolete marker
3066
3052
3067 With no arguments, displays the list of obsolescence markers."""
3053 With no arguments, displays the list of obsolescence markers."""
3068
3054
3069 def parsenodeid(s):
3055 def parsenodeid(s):
3070 try:
3056 try:
3071 # We do not use revsingle/revrange functions here to accept
3057 # We do not use revsingle/revrange functions here to accept
3072 # arbitrary node identifiers, possibly not present in the
3058 # arbitrary node identifiers, possibly not present in the
3073 # local repository.
3059 # local repository.
3074 n = bin(s)
3060 n = bin(s)
3075 if len(n) != len(nullid):
3061 if len(n) != len(nullid):
3076 raise TypeError()
3062 raise TypeError()
3077 return n
3063 return n
3078 except TypeError:
3064 except TypeError:
3079 raise error.Abort('changeset references must be full hexadecimal '
3065 raise error.Abort('changeset references must be full hexadecimal '
3080 'node identifiers')
3066 'node identifiers')
3081
3067
3082 if opts.get('delete'):
3068 if opts.get('delete'):
3083 indices = []
3069 indices = []
3084 for v in opts.get('delete'):
3070 for v in opts.get('delete'):
3085 try:
3071 try:
3086 indices.append(int(v))
3072 indices.append(int(v))
3087 except ValueError:
3073 except ValueError:
3088 raise error.Abort(_('invalid index value: %r') % v,
3074 raise error.Abort(_('invalid index value: %r') % v,
3089 hint=_('use integers for indices'))
3075 hint=_('use integers for indices'))
3090
3076
3091 if repo.currenttransaction():
3077 if repo.currenttransaction():
3092 raise error.Abort(_('cannot delete obsmarkers in the middle '
3078 raise error.Abort(_('cannot delete obsmarkers in the middle '
3093 'of transaction.'))
3079 'of transaction.'))
3094
3080
3095 with repo.lock():
3081 with repo.lock():
3096 n = repair.deleteobsmarkers(repo.obsstore, indices)
3082 n = repair.deleteobsmarkers(repo.obsstore, indices)
3097 ui.write(_('deleted %i obsolescense markers\n') % n)
3083 ui.write(_('deleted %i obsolescense markers\n') % n)
3098
3084
3099 return
3085 return
3100
3086
3101 if precursor is not None:
3087 if precursor is not None:
3102 if opts['rev']:
3088 if opts['rev']:
3103 raise error.Abort('cannot select revision when creating marker')
3089 raise error.Abort('cannot select revision when creating marker')
3104 metadata = {}
3090 metadata = {}
3105 metadata['user'] = opts['user'] or ui.username()
3091 metadata['user'] = opts['user'] or ui.username()
3106 succs = tuple(parsenodeid(succ) for succ in successors)
3092 succs = tuple(parsenodeid(succ) for succ in successors)
3107 l = repo.lock()
3093 l = repo.lock()
3108 try:
3094 try:
3109 tr = repo.transaction('debugobsolete')
3095 tr = repo.transaction('debugobsolete')
3110 try:
3096 try:
3111 date = opts.get('date')
3097 date = opts.get('date')
3112 if date:
3098 if date:
3113 date = util.parsedate(date)
3099 date = util.parsedate(date)
3114 else:
3100 else:
3115 date = None
3101 date = None
3116 prec = parsenodeid(precursor)
3102 prec = parsenodeid(precursor)
3117 parents = None
3103 parents = None
3118 if opts['record_parents']:
3104 if opts['record_parents']:
3119 if prec not in repo.unfiltered():
3105 if prec not in repo.unfiltered():
3120 raise error.Abort('cannot used --record-parents on '
3106 raise error.Abort('cannot used --record-parents on '
3121 'unknown changesets')
3107 'unknown changesets')
3122 parents = repo.unfiltered()[prec].parents()
3108 parents = repo.unfiltered()[prec].parents()
3123 parents = tuple(p.node() for p in parents)
3109 parents = tuple(p.node() for p in parents)
3124 repo.obsstore.create(tr, prec, succs, opts['flags'],
3110 repo.obsstore.create(tr, prec, succs, opts['flags'],
3125 parents=parents, date=date,
3111 parents=parents, date=date,
3126 metadata=metadata)
3112 metadata=metadata)
3127 tr.close()
3113 tr.close()
3128 except ValueError as exc:
3114 except ValueError as exc:
3129 raise error.Abort(_('bad obsmarker input: %s') % exc)
3115 raise error.Abort(_('bad obsmarker input: %s') % exc)
3130 finally:
3116 finally:
3131 tr.release()
3117 tr.release()
3132 finally:
3118 finally:
3133 l.release()
3119 l.release()
3134 else:
3120 else:
3135 if opts['rev']:
3121 if opts['rev']:
3136 revs = scmutil.revrange(repo, opts['rev'])
3122 revs = scmutil.revrange(repo, opts['rev'])
3137 nodes = [repo[r].node() for r in revs]
3123 nodes = [repo[r].node() for r in revs]
3138 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3124 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3139 markers.sort(key=lambda x: x._data)
3125 markers.sort(key=lambda x: x._data)
3140 else:
3126 else:
3141 markers = obsolete.getmarkers(repo)
3127 markers = obsolete.getmarkers(repo)
3142
3128
3143 markerstoiter = markers
3129 markerstoiter = markers
3144 isrelevant = lambda m: True
3130 isrelevant = lambda m: True
3145 if opts.get('rev') and opts.get('index'):
3131 if opts.get('rev') and opts.get('index'):
3146 markerstoiter = obsolete.getmarkers(repo)
3132 markerstoiter = obsolete.getmarkers(repo)
3147 markerset = set(markers)
3133 markerset = set(markers)
3148 isrelevant = lambda m: m in markerset
3134 isrelevant = lambda m: m in markerset
3149
3135
3150 fm = ui.formatter('debugobsolete', opts)
3136 fm = ui.formatter('debugobsolete', opts)
3151 for i, m in enumerate(markerstoiter):
3137 for i, m in enumerate(markerstoiter):
3152 if not isrelevant(m):
3138 if not isrelevant(m):
3153 # marker can be irrelevant when we're iterating over a set
3139 # marker can be irrelevant when we're iterating over a set
3154 # of markers (markerstoiter) which is bigger than the set
3140 # of markers (markerstoiter) which is bigger than the set
3155 # of markers we want to display (markers)
3141 # of markers we want to display (markers)
3156 # this can happen if both --index and --rev options are
3142 # this can happen if both --index and --rev options are
3157 # provided and thus we need to iterate over all of the markers
3143 # provided and thus we need to iterate over all of the markers
3158 # to get the correct indices, but only display the ones that
3144 # to get the correct indices, but only display the ones that
3159 # are relevant to --rev value
3145 # are relevant to --rev value
3160 continue
3146 continue
3161 fm.startitem()
3147 fm.startitem()
3162 ind = i if opts.get('index') else None
3148 ind = i if opts.get('index') else None
3163 cmdutil.showmarker(fm, m, index=ind)
3149 cmdutil.showmarker(fm, m, index=ind)
3164 fm.end()
3150 fm.end()
3165
3151
3166 @command('debugpathcomplete',
3152 @command('debugpathcomplete',
3167 [('f', 'full', None, _('complete an entire path')),
3153 [('f', 'full', None, _('complete an entire path')),
3168 ('n', 'normal', None, _('show only normal files')),
3154 ('n', 'normal', None, _('show only normal files')),
3169 ('a', 'added', None, _('show only added files')),
3155 ('a', 'added', None, _('show only added files')),
3170 ('r', 'removed', None, _('show only removed files'))],
3156 ('r', 'removed', None, _('show only removed files'))],
3171 _('FILESPEC...'))
3157 _('FILESPEC...'))
3172 def debugpathcomplete(ui, repo, *specs, **opts):
3158 def debugpathcomplete(ui, repo, *specs, **opts):
3173 '''complete part or all of a tracked path
3159 '''complete part or all of a tracked path
3174
3160
3175 This command supports shells that offer path name completion. It
3161 This command supports shells that offer path name completion. It
3176 currently completes only files already known to the dirstate.
3162 currently completes only files already known to the dirstate.
3177
3163
3178 Completion extends only to the next path segment unless
3164 Completion extends only to the next path segment unless
3179 --full is specified, in which case entire paths are used.'''
3165 --full is specified, in which case entire paths are used.'''
3180
3166
3181 def complete(path, acceptable):
3167 def complete(path, acceptable):
3182 dirstate = repo.dirstate
3168 dirstate = repo.dirstate
3183 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3169 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3184 rootdir = repo.root + os.sep
3170 rootdir = repo.root + os.sep
3185 if spec != repo.root and not spec.startswith(rootdir):
3171 if spec != repo.root and not spec.startswith(rootdir):
3186 return [], []
3172 return [], []
3187 if os.path.isdir(spec):
3173 if os.path.isdir(spec):
3188 spec += '/'
3174 spec += '/'
3189 spec = spec[len(rootdir):]
3175 spec = spec[len(rootdir):]
3190 fixpaths = os.sep != '/'
3176 fixpaths = os.sep != '/'
3191 if fixpaths:
3177 if fixpaths:
3192 spec = spec.replace(os.sep, '/')
3178 spec = spec.replace(os.sep, '/')
3193 speclen = len(spec)
3179 speclen = len(spec)
3194 fullpaths = opts['full']
3180 fullpaths = opts['full']
3195 files, dirs = set(), set()
3181 files, dirs = set(), set()
3196 adddir, addfile = dirs.add, files.add
3182 adddir, addfile = dirs.add, files.add
3197 for f, st in dirstate.iteritems():
3183 for f, st in dirstate.iteritems():
3198 if f.startswith(spec) and st[0] in acceptable:
3184 if f.startswith(spec) and st[0] in acceptable:
3199 if fixpaths:
3185 if fixpaths:
3200 f = f.replace('/', os.sep)
3186 f = f.replace('/', os.sep)
3201 if fullpaths:
3187 if fullpaths:
3202 addfile(f)
3188 addfile(f)
3203 continue
3189 continue
3204 s = f.find(os.sep, speclen)
3190 s = f.find(os.sep, speclen)
3205 if s >= 0:
3191 if s >= 0:
3206 adddir(f[:s])
3192 adddir(f[:s])
3207 else:
3193 else:
3208 addfile(f)
3194 addfile(f)
3209 return files, dirs
3195 return files, dirs
3210
3196
3211 acceptable = ''
3197 acceptable = ''
3212 if opts['normal']:
3198 if opts['normal']:
3213 acceptable += 'nm'
3199 acceptable += 'nm'
3214 if opts['added']:
3200 if opts['added']:
3215 acceptable += 'a'
3201 acceptable += 'a'
3216 if opts['removed']:
3202 if opts['removed']:
3217 acceptable += 'r'
3203 acceptable += 'r'
3218 cwd = repo.getcwd()
3204 cwd = repo.getcwd()
3219 if not specs:
3205 if not specs:
3220 specs = ['.']
3206 specs = ['.']
3221
3207
3222 files, dirs = set(), set()
3208 files, dirs = set(), set()
3223 for spec in specs:
3209 for spec in specs:
3224 f, d = complete(spec, acceptable or 'nmar')
3210 f, d = complete(spec, acceptable or 'nmar')
3225 files.update(f)
3211 files.update(f)
3226 dirs.update(d)
3212 dirs.update(d)
3227 files.update(dirs)
3213 files.update(dirs)
3228 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3214 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3229 ui.write('\n')
3215 ui.write('\n')
3230
3216
3231 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3217 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3232 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3218 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3233 '''access the pushkey key/value protocol
3219 '''access the pushkey key/value protocol
3234
3220
3235 With two args, list the keys in the given namespace.
3221 With two args, list the keys in the given namespace.
3236
3222
3237 With five args, set a key to new if it currently is set to old.
3223 With five args, set a key to new if it currently is set to old.
3238 Reports success or failure.
3224 Reports success or failure.
3239 '''
3225 '''
3240
3226
3241 target = hg.peer(ui, {}, repopath)
3227 target = hg.peer(ui, {}, repopath)
3242 if keyinfo:
3228 if keyinfo:
3243 key, old, new = keyinfo
3229 key, old, new = keyinfo
3244 r = target.pushkey(namespace, key, old, new)
3230 r = target.pushkey(namespace, key, old, new)
3245 ui.status(str(r) + '\n')
3231 ui.status(str(r) + '\n')
3246 return not r
3232 return not r
3247 else:
3233 else:
3248 for k, v in sorted(target.listkeys(namespace).iteritems()):
3234 for k, v in sorted(target.listkeys(namespace).iteritems()):
3249 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3235 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3250 v.encode('string-escape')))
3236 v.encode('string-escape')))
3251
3237
3252 @command('debugpvec', [], _('A B'))
3238 @command('debugpvec', [], _('A B'))
3253 def debugpvec(ui, repo, a, b=None):
3239 def debugpvec(ui, repo, a, b=None):
3254 ca = scmutil.revsingle(repo, a)
3240 ca = scmutil.revsingle(repo, a)
3255 cb = scmutil.revsingle(repo, b)
3241 cb = scmutil.revsingle(repo, b)
3256 pa = pvec.ctxpvec(ca)
3242 pa = pvec.ctxpvec(ca)
3257 pb = pvec.ctxpvec(cb)
3243 pb = pvec.ctxpvec(cb)
3258 if pa == pb:
3244 if pa == pb:
3259 rel = "="
3245 rel = "="
3260 elif pa > pb:
3246 elif pa > pb:
3261 rel = ">"
3247 rel = ">"
3262 elif pa < pb:
3248 elif pa < pb:
3263 rel = "<"
3249 rel = "<"
3264 elif pa | pb:
3250 elif pa | pb:
3265 rel = "|"
3251 rel = "|"
3266 ui.write(_("a: %s\n") % pa)
3252 ui.write(_("a: %s\n") % pa)
3267 ui.write(_("b: %s\n") % pb)
3253 ui.write(_("b: %s\n") % pb)
3268 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3254 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3269 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3255 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3270 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3256 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3271 pa.distance(pb), rel))
3257 pa.distance(pb), rel))
3272
3258
3273 @command('debugrebuilddirstate|debugrebuildstate',
3259 @command('debugrebuilddirstate|debugrebuildstate',
3274 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3260 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3275 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3261 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3276 'the working copy parent')),
3262 'the working copy parent')),
3277 ],
3263 ],
3278 _('[-r REV]'))
3264 _('[-r REV]'))
3279 def debugrebuilddirstate(ui, repo, rev, **opts):
3265 def debugrebuilddirstate(ui, repo, rev, **opts):
3280 """rebuild the dirstate as it would look like for the given revision
3266 """rebuild the dirstate as it would look like for the given revision
3281
3267
3282 If no revision is specified the first current parent will be used.
3268 If no revision is specified the first current parent will be used.
3283
3269
3284 The dirstate will be set to the files of the given revision.
3270 The dirstate will be set to the files of the given revision.
3285 The actual working directory content or existing dirstate
3271 The actual working directory content or existing dirstate
3286 information such as adds or removes is not considered.
3272 information such as adds or removes is not considered.
3287
3273
3288 ``minimal`` will only rebuild the dirstate status for files that claim to be
3274 ``minimal`` will only rebuild the dirstate status for files that claim to be
3289 tracked but are not in the parent manifest, or that exist in the parent
3275 tracked but are not in the parent manifest, or that exist in the parent
3290 manifest but are not in the dirstate. It will not change adds, removes, or
3276 manifest but are not in the dirstate. It will not change adds, removes, or
3291 modified files that are in the working copy parent.
3277 modified files that are in the working copy parent.
3292
3278
3293 One use of this command is to make the next :hg:`status` invocation
3279 One use of this command is to make the next :hg:`status` invocation
3294 check the actual file content.
3280 check the actual file content.
3295 """
3281 """
3296 ctx = scmutil.revsingle(repo, rev)
3282 ctx = scmutil.revsingle(repo, rev)
3297 with repo.wlock():
3283 with repo.wlock():
3298 dirstate = repo.dirstate
3284 dirstate = repo.dirstate
3299 changedfiles = None
3285 changedfiles = None
3300 # See command doc for what minimal does.
3286 # See command doc for what minimal does.
3301 if opts.get('minimal'):
3287 if opts.get('minimal'):
3302 manifestfiles = set(ctx.manifest().keys())
3288 manifestfiles = set(ctx.manifest().keys())
3303 dirstatefiles = set(dirstate)
3289 dirstatefiles = set(dirstate)
3304 manifestonly = manifestfiles - dirstatefiles
3290 manifestonly = manifestfiles - dirstatefiles
3305 dsonly = dirstatefiles - manifestfiles
3291 dsonly = dirstatefiles - manifestfiles
3306 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3292 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3307 changedfiles = manifestonly | dsnotadded
3293 changedfiles = manifestonly | dsnotadded
3308
3294
3309 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3295 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3310
3296
3311 @command('debugrebuildfncache', [], '')
3297 @command('debugrebuildfncache', [], '')
3312 def debugrebuildfncache(ui, repo):
3298 def debugrebuildfncache(ui, repo):
3313 """rebuild the fncache file"""
3299 """rebuild the fncache file"""
3314 repair.rebuildfncache(ui, repo)
3300 repair.rebuildfncache(ui, repo)
3315
3301
3316 @command('debugrename',
3302 @command('debugrename',
3317 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3303 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3318 _('[-r REV] FILE'))
3304 _('[-r REV] FILE'))
3319 def debugrename(ui, repo, file1, *pats, **opts):
3305 def debugrename(ui, repo, file1, *pats, **opts):
3320 """dump rename information"""
3306 """dump rename information"""
3321
3307
3322 ctx = scmutil.revsingle(repo, opts.get('rev'))
3308 ctx = scmutil.revsingle(repo, opts.get('rev'))
3323 m = scmutil.match(ctx, (file1,) + pats, opts)
3309 m = scmutil.match(ctx, (file1,) + pats, opts)
3324 for abs in ctx.walk(m):
3310 for abs in ctx.walk(m):
3325 fctx = ctx[abs]
3311 fctx = ctx[abs]
3326 o = fctx.filelog().renamed(fctx.filenode())
3312 o = fctx.filelog().renamed(fctx.filenode())
3327 rel = m.rel(abs)
3313 rel = m.rel(abs)
3328 if o:
3314 if o:
3329 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3315 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3330 else:
3316 else:
3331 ui.write(_("%s not renamed\n") % rel)
3317 ui.write(_("%s not renamed\n") % rel)
3332
3318
3333 @command('debugrevlog', debugrevlogopts +
3319 @command('debugrevlog', debugrevlogopts +
3334 [('d', 'dump', False, _('dump index data'))],
3320 [('d', 'dump', False, _('dump index data'))],
3335 _('-c|-m|FILE'),
3321 _('-c|-m|FILE'),
3336 optionalrepo=True)
3322 optionalrepo=True)
3337 def debugrevlog(ui, repo, file_=None, **opts):
3323 def debugrevlog(ui, repo, file_=None, **opts):
3338 """show data and statistics about a revlog"""
3324 """show data and statistics about a revlog"""
3339 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3325 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3340
3326
3341 if opts.get("dump"):
3327 if opts.get("dump"):
3342 numrevs = len(r)
3328 numrevs = len(r)
3343 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3329 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3344 " rawsize totalsize compression heads chainlen\n"))
3330 " rawsize totalsize compression heads chainlen\n"))
3345 ts = 0
3331 ts = 0
3346 heads = set()
3332 heads = set()
3347
3333
3348 for rev in xrange(numrevs):
3334 for rev in xrange(numrevs):
3349 dbase = r.deltaparent(rev)
3335 dbase = r.deltaparent(rev)
3350 if dbase == -1:
3336 if dbase == -1:
3351 dbase = rev
3337 dbase = rev
3352 cbase = r.chainbase(rev)
3338 cbase = r.chainbase(rev)
3353 clen = r.chainlen(rev)
3339 clen = r.chainlen(rev)
3354 p1, p2 = r.parentrevs(rev)
3340 p1, p2 = r.parentrevs(rev)
3355 rs = r.rawsize(rev)
3341 rs = r.rawsize(rev)
3356 ts = ts + rs
3342 ts = ts + rs
3357 heads -= set(r.parentrevs(rev))
3343 heads -= set(r.parentrevs(rev))
3358 heads.add(rev)
3344 heads.add(rev)
3359 try:
3345 try:
3360 compression = ts / r.end(rev)
3346 compression = ts / r.end(rev)
3361 except ZeroDivisionError:
3347 except ZeroDivisionError:
3362 compression = 0
3348 compression = 0
3363 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3349 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3364 "%11d %5d %8d\n" %
3350 "%11d %5d %8d\n" %
3365 (rev, p1, p2, r.start(rev), r.end(rev),
3351 (rev, p1, p2, r.start(rev), r.end(rev),
3366 r.start(dbase), r.start(cbase),
3352 r.start(dbase), r.start(cbase),
3367 r.start(p1), r.start(p2),
3353 r.start(p1), r.start(p2),
3368 rs, ts, compression, len(heads), clen))
3354 rs, ts, compression, len(heads), clen))
3369 return 0
3355 return 0
3370
3356
3371 v = r.version
3357 v = r.version
3372 format = v & 0xFFFF
3358 format = v & 0xFFFF
3373 flags = []
3359 flags = []
3374 gdelta = False
3360 gdelta = False
3375 if v & revlog.REVLOGNGINLINEDATA:
3361 if v & revlog.REVLOGNGINLINEDATA:
3376 flags.append('inline')
3362 flags.append('inline')
3377 if v & revlog.REVLOGGENERALDELTA:
3363 if v & revlog.REVLOGGENERALDELTA:
3378 gdelta = True
3364 gdelta = True
3379 flags.append('generaldelta')
3365 flags.append('generaldelta')
3380 if not flags:
3366 if not flags:
3381 flags = ['(none)']
3367 flags = ['(none)']
3382
3368
3383 nummerges = 0
3369 nummerges = 0
3384 numfull = 0
3370 numfull = 0
3385 numprev = 0
3371 numprev = 0
3386 nump1 = 0
3372 nump1 = 0
3387 nump2 = 0
3373 nump2 = 0
3388 numother = 0
3374 numother = 0
3389 nump1prev = 0
3375 nump1prev = 0
3390 nump2prev = 0
3376 nump2prev = 0
3391 chainlengths = []
3377 chainlengths = []
3392
3378
3393 datasize = [None, 0, 0]
3379 datasize = [None, 0, 0]
3394 fullsize = [None, 0, 0]
3380 fullsize = [None, 0, 0]
3395 deltasize = [None, 0, 0]
3381 deltasize = [None, 0, 0]
3396
3382
3397 def addsize(size, l):
3383 def addsize(size, l):
3398 if l[0] is None or size < l[0]:
3384 if l[0] is None or size < l[0]:
3399 l[0] = size
3385 l[0] = size
3400 if size > l[1]:
3386 if size > l[1]:
3401 l[1] = size
3387 l[1] = size
3402 l[2] += size
3388 l[2] += size
3403
3389
3404 numrevs = len(r)
3390 numrevs = len(r)
3405 for rev in xrange(numrevs):
3391 for rev in xrange(numrevs):
3406 p1, p2 = r.parentrevs(rev)
3392 p1, p2 = r.parentrevs(rev)
3407 delta = r.deltaparent(rev)
3393 delta = r.deltaparent(rev)
3408 if format > 0:
3394 if format > 0:
3409 addsize(r.rawsize(rev), datasize)
3395 addsize(r.rawsize(rev), datasize)
3410 if p2 != nullrev:
3396 if p2 != nullrev:
3411 nummerges += 1
3397 nummerges += 1
3412 size = r.length(rev)
3398 size = r.length(rev)
3413 if delta == nullrev:
3399 if delta == nullrev:
3414 chainlengths.append(0)
3400 chainlengths.append(0)
3415 numfull += 1
3401 numfull += 1
3416 addsize(size, fullsize)
3402 addsize(size, fullsize)
3417 else:
3403 else:
3418 chainlengths.append(chainlengths[delta] + 1)
3404 chainlengths.append(chainlengths[delta] + 1)
3419 addsize(size, deltasize)
3405 addsize(size, deltasize)
3420 if delta == rev - 1:
3406 if delta == rev - 1:
3421 numprev += 1
3407 numprev += 1
3422 if delta == p1:
3408 if delta == p1:
3423 nump1prev += 1
3409 nump1prev += 1
3424 elif delta == p2:
3410 elif delta == p2:
3425 nump2prev += 1
3411 nump2prev += 1
3426 elif delta == p1:
3412 elif delta == p1:
3427 nump1 += 1
3413 nump1 += 1
3428 elif delta == p2:
3414 elif delta == p2:
3429 nump2 += 1
3415 nump2 += 1
3430 elif delta != nullrev:
3416 elif delta != nullrev:
3431 numother += 1
3417 numother += 1
3432
3418
3433 # Adjust size min value for empty cases
3419 # Adjust size min value for empty cases
3434 for size in (datasize, fullsize, deltasize):
3420 for size in (datasize, fullsize, deltasize):
3435 if size[0] is None:
3421 if size[0] is None:
3436 size[0] = 0
3422 size[0] = 0
3437
3423
3438 numdeltas = numrevs - numfull
3424 numdeltas = numrevs - numfull
3439 numoprev = numprev - nump1prev - nump2prev
3425 numoprev = numprev - nump1prev - nump2prev
3440 totalrawsize = datasize[2]
3426 totalrawsize = datasize[2]
3441 datasize[2] /= numrevs
3427 datasize[2] /= numrevs
3442 fulltotal = fullsize[2]
3428 fulltotal = fullsize[2]
3443 fullsize[2] /= numfull
3429 fullsize[2] /= numfull
3444 deltatotal = deltasize[2]
3430 deltatotal = deltasize[2]
3445 if numrevs - numfull > 0:
3431 if numrevs - numfull > 0:
3446 deltasize[2] /= numrevs - numfull
3432 deltasize[2] /= numrevs - numfull
3447 totalsize = fulltotal + deltatotal
3433 totalsize = fulltotal + deltatotal
3448 avgchainlen = sum(chainlengths) / numrevs
3434 avgchainlen = sum(chainlengths) / numrevs
3449 maxchainlen = max(chainlengths)
3435 maxchainlen = max(chainlengths)
3450 compratio = 1
3436 compratio = 1
3451 if totalsize:
3437 if totalsize:
3452 compratio = totalrawsize / totalsize
3438 compratio = totalrawsize / totalsize
3453
3439
3454 basedfmtstr = '%%%dd\n'
3440 basedfmtstr = '%%%dd\n'
3455 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3441 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3456
3442
3457 def dfmtstr(max):
3443 def dfmtstr(max):
3458 return basedfmtstr % len(str(max))
3444 return basedfmtstr % len(str(max))
3459 def pcfmtstr(max, padding=0):
3445 def pcfmtstr(max, padding=0):
3460 return basepcfmtstr % (len(str(max)), ' ' * padding)
3446 return basepcfmtstr % (len(str(max)), ' ' * padding)
3461
3447
3462 def pcfmt(value, total):
3448 def pcfmt(value, total):
3463 if total:
3449 if total:
3464 return (value, 100 * float(value) / total)
3450 return (value, 100 * float(value) / total)
3465 else:
3451 else:
3466 return value, 100.0
3452 return value, 100.0
3467
3453
3468 ui.write(('format : %d\n') % format)
3454 ui.write(('format : %d\n') % format)
3469 ui.write(('flags : %s\n') % ', '.join(flags))
3455 ui.write(('flags : %s\n') % ', '.join(flags))
3470
3456
3471 ui.write('\n')
3457 ui.write('\n')
3472 fmt = pcfmtstr(totalsize)
3458 fmt = pcfmtstr(totalsize)
3473 fmt2 = dfmtstr(totalsize)
3459 fmt2 = dfmtstr(totalsize)
3474 ui.write(('revisions : ') + fmt2 % numrevs)
3460 ui.write(('revisions : ') + fmt2 % numrevs)
3475 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3461 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3476 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3462 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3477 ui.write(('revisions : ') + fmt2 % numrevs)
3463 ui.write(('revisions : ') + fmt2 % numrevs)
3478 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3464 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3479 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3465 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3480 ui.write(('revision size : ') + fmt2 % totalsize)
3466 ui.write(('revision size : ') + fmt2 % totalsize)
3481 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3467 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3482 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3468 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3483
3469
3484 ui.write('\n')
3470 ui.write('\n')
3485 fmt = dfmtstr(max(avgchainlen, compratio))
3471 fmt = dfmtstr(max(avgchainlen, compratio))
3486 ui.write(('avg chain length : ') + fmt % avgchainlen)
3472 ui.write(('avg chain length : ') + fmt % avgchainlen)
3487 ui.write(('max chain length : ') + fmt % maxchainlen)
3473 ui.write(('max chain length : ') + fmt % maxchainlen)
3488 ui.write(('compression ratio : ') + fmt % compratio)
3474 ui.write(('compression ratio : ') + fmt % compratio)
3489
3475
3490 if format > 0:
3476 if format > 0:
3491 ui.write('\n')
3477 ui.write('\n')
3492 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3478 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3493 % tuple(datasize))
3479 % tuple(datasize))
3494 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3480 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3495 % tuple(fullsize))
3481 % tuple(fullsize))
3496 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3482 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3497 % tuple(deltasize))
3483 % tuple(deltasize))
3498
3484
3499 if numdeltas > 0:
3485 if numdeltas > 0:
3500 ui.write('\n')
3486 ui.write('\n')
3501 fmt = pcfmtstr(numdeltas)
3487 fmt = pcfmtstr(numdeltas)
3502 fmt2 = pcfmtstr(numdeltas, 4)
3488 fmt2 = pcfmtstr(numdeltas, 4)
3503 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3489 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3504 if numprev > 0:
3490 if numprev > 0:
3505 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3491 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3506 numprev))
3492 numprev))
3507 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3493 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3508 numprev))
3494 numprev))
3509 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3495 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3510 numprev))
3496 numprev))
3511 if gdelta:
3497 if gdelta:
3512 ui.write(('deltas against p1 : ')
3498 ui.write(('deltas against p1 : ')
3513 + fmt % pcfmt(nump1, numdeltas))
3499 + fmt % pcfmt(nump1, numdeltas))
3514 ui.write(('deltas against p2 : ')
3500 ui.write(('deltas against p2 : ')
3515 + fmt % pcfmt(nump2, numdeltas))
3501 + fmt % pcfmt(nump2, numdeltas))
3516 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3502 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3517 numdeltas))
3503 numdeltas))
3518
3504
3519 @command('debugrevspec',
3505 @command('debugrevspec',
3520 [('', 'optimize', None,
3506 [('', 'optimize', None,
3521 _('print parsed tree after optimizing (DEPRECATED)')),
3507 _('print parsed tree after optimizing (DEPRECATED)')),
3522 ('p', 'show-stage', [],
3508 ('p', 'show-stage', [],
3523 _('print parsed tree at the given stage'), _('NAME')),
3509 _('print parsed tree at the given stage'), _('NAME')),
3524 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3510 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3525 ('', 'verify-optimized', False, _('verify optimized result')),
3511 ('', 'verify-optimized', False, _('verify optimized result')),
3526 ],
3512 ],
3527 ('REVSPEC'))
3513 ('REVSPEC'))
3528 def debugrevspec(ui, repo, expr, **opts):
3514 def debugrevspec(ui, repo, expr, **opts):
3529 """parse and apply a revision specification
3515 """parse and apply a revision specification
3530
3516
3531 Use -p/--show-stage option to print the parsed tree at the given stages.
3517 Use -p/--show-stage option to print the parsed tree at the given stages.
3532 Use -p all to print tree at every stage.
3518 Use -p all to print tree at every stage.
3533
3519
3534 Use --verify-optimized to compare the optimized result with the unoptimized
3520 Use --verify-optimized to compare the optimized result with the unoptimized
3535 one. Returns 1 if the optimized result differs.
3521 one. Returns 1 if the optimized result differs.
3536 """
3522 """
3537 stages = [
3523 stages = [
3538 ('parsed', lambda tree: tree),
3524 ('parsed', lambda tree: tree),
3539 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3525 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3540 ('concatenated', revset.foldconcat),
3526 ('concatenated', revset.foldconcat),
3541 ('analyzed', revset.analyze),
3527 ('analyzed', revset.analyze),
3542 ('optimized', revset.optimize),
3528 ('optimized', revset.optimize),
3543 ]
3529 ]
3544 if opts['no_optimized']:
3530 if opts['no_optimized']:
3545 stages = stages[:-1]
3531 stages = stages[:-1]
3546 if opts['verify_optimized'] and opts['no_optimized']:
3532 if opts['verify_optimized'] and opts['no_optimized']:
3547 raise error.Abort(_('cannot use --verify-optimized with '
3533 raise error.Abort(_('cannot use --verify-optimized with '
3548 '--no-optimized'))
3534 '--no-optimized'))
3549 stagenames = set(n for n, f in stages)
3535 stagenames = set(n for n, f in stages)
3550
3536
3551 showalways = set()
3537 showalways = set()
3552 showchanged = set()
3538 showchanged = set()
3553 if ui.verbose and not opts['show_stage']:
3539 if ui.verbose and not opts['show_stage']:
3554 # show parsed tree by --verbose (deprecated)
3540 # show parsed tree by --verbose (deprecated)
3555 showalways.add('parsed')
3541 showalways.add('parsed')
3556 showchanged.update(['expanded', 'concatenated'])
3542 showchanged.update(['expanded', 'concatenated'])
3557 if opts['optimize']:
3543 if opts['optimize']:
3558 showalways.add('optimized')
3544 showalways.add('optimized')
3559 if opts['show_stage'] and opts['optimize']:
3545 if opts['show_stage'] and opts['optimize']:
3560 raise error.Abort(_('cannot use --optimize with --show-stage'))
3546 raise error.Abort(_('cannot use --optimize with --show-stage'))
3561 if opts['show_stage'] == ['all']:
3547 if opts['show_stage'] == ['all']:
3562 showalways.update(stagenames)
3548 showalways.update(stagenames)
3563 else:
3549 else:
3564 for n in opts['show_stage']:
3550 for n in opts['show_stage']:
3565 if n not in stagenames:
3551 if n not in stagenames:
3566 raise error.Abort(_('invalid stage name: %s') % n)
3552 raise error.Abort(_('invalid stage name: %s') % n)
3567 showalways.update(opts['show_stage'])
3553 showalways.update(opts['show_stage'])
3568
3554
3569 treebystage = {}
3555 treebystage = {}
3570 printedtree = None
3556 printedtree = None
3571 tree = revset.parse(expr, lookup=repo.__contains__)
3557 tree = revset.parse(expr, lookup=repo.__contains__)
3572 for n, f in stages:
3558 for n, f in stages:
3573 treebystage[n] = tree = f(tree)
3559 treebystage[n] = tree = f(tree)
3574 if n in showalways or (n in showchanged and tree != printedtree):
3560 if n in showalways or (n in showchanged and tree != printedtree):
3575 if opts['show_stage'] or n != 'parsed':
3561 if opts['show_stage'] or n != 'parsed':
3576 ui.write(("* %s:\n") % n)
3562 ui.write(("* %s:\n") % n)
3577 ui.write(revset.prettyformat(tree), "\n")
3563 ui.write(revset.prettyformat(tree), "\n")
3578 printedtree = tree
3564 printedtree = tree
3579
3565
3580 if opts['verify_optimized']:
3566 if opts['verify_optimized']:
3581 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3567 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3582 brevs = revset.makematcher(treebystage['optimized'])(repo)
3568 brevs = revset.makematcher(treebystage['optimized'])(repo)
3583 if ui.verbose:
3569 if ui.verbose:
3584 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3570 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3585 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3571 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3586 arevs = list(arevs)
3572 arevs = list(arevs)
3587 brevs = list(brevs)
3573 brevs = list(brevs)
3588 if arevs == brevs:
3574 if arevs == brevs:
3589 return 0
3575 return 0
3590 ui.write(('--- analyzed\n'), label='diff.file_a')
3576 ui.write(('--- analyzed\n'), label='diff.file_a')
3591 ui.write(('+++ optimized\n'), label='diff.file_b')
3577 ui.write(('+++ optimized\n'), label='diff.file_b')
3592 sm = difflib.SequenceMatcher(None, arevs, brevs)
3578 sm = difflib.SequenceMatcher(None, arevs, brevs)
3593 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3579 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3594 if tag in ('delete', 'replace'):
3580 if tag in ('delete', 'replace'):
3595 for c in arevs[alo:ahi]:
3581 for c in arevs[alo:ahi]:
3596 ui.write('-%s\n' % c, label='diff.deleted')
3582 ui.write('-%s\n' % c, label='diff.deleted')
3597 if tag in ('insert', 'replace'):
3583 if tag in ('insert', 'replace'):
3598 for c in brevs[blo:bhi]:
3584 for c in brevs[blo:bhi]:
3599 ui.write('+%s\n' % c, label='diff.inserted')
3585 ui.write('+%s\n' % c, label='diff.inserted')
3600 if tag == 'equal':
3586 if tag == 'equal':
3601 for c in arevs[alo:ahi]:
3587 for c in arevs[alo:ahi]:
3602 ui.write(' %s\n' % c)
3588 ui.write(' %s\n' % c)
3603 return 1
3589 return 1
3604
3590
3605 func = revset.makematcher(tree)
3591 func = revset.makematcher(tree)
3606 revs = func(repo)
3592 revs = func(repo)
3607 if ui.verbose:
3593 if ui.verbose:
3608 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3594 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3609 for c in revs:
3595 for c in revs:
3610 ui.write("%s\n" % c)
3596 ui.write("%s\n" % c)
3611
3597
3612 @command('debugsetparents', [], _('REV1 [REV2]'))
3598 @command('debugsetparents', [], _('REV1 [REV2]'))
3613 def debugsetparents(ui, repo, rev1, rev2=None):
3599 def debugsetparents(ui, repo, rev1, rev2=None):
3614 """manually set the parents of the current working directory
3600 """manually set the parents of the current working directory
3615
3601
3616 This is useful for writing repository conversion tools, but should
3602 This is useful for writing repository conversion tools, but should
3617 be used with care. For example, neither the working directory nor the
3603 be used with care. For example, neither the working directory nor the
3618 dirstate is updated, so file status may be incorrect after running this
3604 dirstate is updated, so file status may be incorrect after running this
3619 command.
3605 command.
3620
3606
3621 Returns 0 on success.
3607 Returns 0 on success.
3622 """
3608 """
3623
3609
3624 r1 = scmutil.revsingle(repo, rev1).node()
3610 r1 = scmutil.revsingle(repo, rev1).node()
3625 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3611 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3626
3612
3627 with repo.wlock():
3613 with repo.wlock():
3628 repo.setparents(r1, r2)
3614 repo.setparents(r1, r2)
3629
3615
3630 @command('debugdirstate|debugstate',
3616 @command('debugdirstate|debugstate',
3631 [('', 'nodates', None, _('do not display the saved mtime')),
3617 [('', 'nodates', None, _('do not display the saved mtime')),
3632 ('', 'datesort', None, _('sort by saved mtime'))],
3618 ('', 'datesort', None, _('sort by saved mtime'))],
3633 _('[OPTION]...'))
3619 _('[OPTION]...'))
3634 def debugstate(ui, repo, **opts):
3620 def debugstate(ui, repo, **opts):
3635 """show the contents of the current dirstate"""
3621 """show the contents of the current dirstate"""
3636
3622
3637 nodates = opts.get('nodates')
3623 nodates = opts.get('nodates')
3638 datesort = opts.get('datesort')
3624 datesort = opts.get('datesort')
3639
3625
3640 timestr = ""
3626 timestr = ""
3641 if datesort:
3627 if datesort:
3642 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3628 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3643 else:
3629 else:
3644 keyfunc = None # sort by filename
3630 keyfunc = None # sort by filename
3645 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3631 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3646 if ent[3] == -1:
3632 if ent[3] == -1:
3647 timestr = 'unset '
3633 timestr = 'unset '
3648 elif nodates:
3634 elif nodates:
3649 timestr = 'set '
3635 timestr = 'set '
3650 else:
3636 else:
3651 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3637 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3652 time.localtime(ent[3]))
3638 time.localtime(ent[3]))
3653 if ent[1] & 0o20000:
3639 if ent[1] & 0o20000:
3654 mode = 'lnk'
3640 mode = 'lnk'
3655 else:
3641 else:
3656 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3642 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3657 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3643 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3658 for f in repo.dirstate.copies():
3644 for f in repo.dirstate.copies():
3659 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3645 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3660
3646
3661 @command('debugsub',
3647 @command('debugsub',
3662 [('r', 'rev', '',
3648 [('r', 'rev', '',
3663 _('revision to check'), _('REV'))],
3649 _('revision to check'), _('REV'))],
3664 _('[-r REV] [REV]'))
3650 _('[-r REV] [REV]'))
3665 def debugsub(ui, repo, rev=None):
3651 def debugsub(ui, repo, rev=None):
3666 ctx = scmutil.revsingle(repo, rev, None)
3652 ctx = scmutil.revsingle(repo, rev, None)
3667 for k, v in sorted(ctx.substate.items()):
3653 for k, v in sorted(ctx.substate.items()):
3668 ui.write(('path %s\n') % k)
3654 ui.write(('path %s\n') % k)
3669 ui.write((' source %s\n') % v[0])
3655 ui.write((' source %s\n') % v[0])
3670 ui.write((' revision %s\n') % v[1])
3656 ui.write((' revision %s\n') % v[1])
3671
3657
3672 @command('debugsuccessorssets',
3658 @command('debugsuccessorssets',
3673 [],
3659 [],
3674 _('[REV]'))
3660 _('[REV]'))
3675 def debugsuccessorssets(ui, repo, *revs):
3661 def debugsuccessorssets(ui, repo, *revs):
3676 """show set of successors for revision
3662 """show set of successors for revision
3677
3663
3678 A successors set of changeset A is a consistent group of revisions that
3664 A successors set of changeset A is a consistent group of revisions that
3679 succeed A. It contains non-obsolete changesets only.
3665 succeed A. It contains non-obsolete changesets only.
3680
3666
3681 In most cases a changeset A has a single successors set containing a single
3667 In most cases a changeset A has a single successors set containing a single
3682 successor (changeset A replaced by A').
3668 successor (changeset A replaced by A').
3683
3669
3684 A changeset that is made obsolete with no successors are called "pruned".
3670 A changeset that is made obsolete with no successors are called "pruned".
3685 Such changesets have no successors sets at all.
3671 Such changesets have no successors sets at all.
3686
3672
3687 A changeset that has been "split" will have a successors set containing
3673 A changeset that has been "split" will have a successors set containing
3688 more than one successor.
3674 more than one successor.
3689
3675
3690 A changeset that has been rewritten in multiple different ways is called
3676 A changeset that has been rewritten in multiple different ways is called
3691 "divergent". Such changesets have multiple successor sets (each of which
3677 "divergent". Such changesets have multiple successor sets (each of which
3692 may also be split, i.e. have multiple successors).
3678 may also be split, i.e. have multiple successors).
3693
3679
3694 Results are displayed as follows::
3680 Results are displayed as follows::
3695
3681
3696 <rev1>
3682 <rev1>
3697 <successors-1A>
3683 <successors-1A>
3698 <rev2>
3684 <rev2>
3699 <successors-2A>
3685 <successors-2A>
3700 <successors-2B1> <successors-2B2> <successors-2B3>
3686 <successors-2B1> <successors-2B2> <successors-2B3>
3701
3687
3702 Here rev2 has two possible (i.e. divergent) successors sets. The first
3688 Here rev2 has two possible (i.e. divergent) successors sets. The first
3703 holds one element, whereas the second holds three (i.e. the changeset has
3689 holds one element, whereas the second holds three (i.e. the changeset has
3704 been split).
3690 been split).
3705 """
3691 """
3706 # passed to successorssets caching computation from one call to another
3692 # passed to successorssets caching computation from one call to another
3707 cache = {}
3693 cache = {}
3708 ctx2str = str
3694 ctx2str = str
3709 node2str = short
3695 node2str = short
3710 if ui.debug():
3696 if ui.debug():
3711 def ctx2str(ctx):
3697 def ctx2str(ctx):
3712 return ctx.hex()
3698 return ctx.hex()
3713 node2str = hex
3699 node2str = hex
3714 for rev in scmutil.revrange(repo, revs):
3700 for rev in scmutil.revrange(repo, revs):
3715 ctx = repo[rev]
3701 ctx = repo[rev]
3716 ui.write('%s\n'% ctx2str(ctx))
3702 ui.write('%s\n'% ctx2str(ctx))
3717 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3703 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3718 if succsset:
3704 if succsset:
3719 ui.write(' ')
3705 ui.write(' ')
3720 ui.write(node2str(succsset[0]))
3706 ui.write(node2str(succsset[0]))
3721 for node in succsset[1:]:
3707 for node in succsset[1:]:
3722 ui.write(' ')
3708 ui.write(' ')
3723 ui.write(node2str(node))
3709 ui.write(node2str(node))
3724 ui.write('\n')
3710 ui.write('\n')
3725
3711
3726 @command('debugtemplate',
3712 @command('debugtemplate',
3727 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3713 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3728 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3714 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3729 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3715 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3730 optionalrepo=True)
3716 optionalrepo=True)
3731 def debugtemplate(ui, repo, tmpl, **opts):
3717 def debugtemplate(ui, repo, tmpl, **opts):
3732 """parse and apply a template
3718 """parse and apply a template
3733
3719
3734 If -r/--rev is given, the template is processed as a log template and
3720 If -r/--rev is given, the template is processed as a log template and
3735 applied to the given changesets. Otherwise, it is processed as a generic
3721 applied to the given changesets. Otherwise, it is processed as a generic
3736 template.
3722 template.
3737
3723
3738 Use --verbose to print the parsed tree.
3724 Use --verbose to print the parsed tree.
3739 """
3725 """
3740 revs = None
3726 revs = None
3741 if opts['rev']:
3727 if opts['rev']:
3742 if repo is None:
3728 if repo is None:
3743 raise error.RepoError(_('there is no Mercurial repository here '
3729 raise error.RepoError(_('there is no Mercurial repository here '
3744 '(.hg not found)'))
3730 '(.hg not found)'))
3745 revs = scmutil.revrange(repo, opts['rev'])
3731 revs = scmutil.revrange(repo, opts['rev'])
3746
3732
3747 props = {}
3733 props = {}
3748 for d in opts['define']:
3734 for d in opts['define']:
3749 try:
3735 try:
3750 k, v = (e.strip() for e in d.split('=', 1))
3736 k, v = (e.strip() for e in d.split('=', 1))
3751 if not k:
3737 if not k:
3752 raise ValueError
3738 raise ValueError
3753 props[k] = v
3739 props[k] = v
3754 except ValueError:
3740 except ValueError:
3755 raise error.Abort(_('malformed keyword definition: %s') % d)
3741 raise error.Abort(_('malformed keyword definition: %s') % d)
3756
3742
3757 if ui.verbose:
3743 if ui.verbose:
3758 aliases = ui.configitems('templatealias')
3744 aliases = ui.configitems('templatealias')
3759 tree = templater.parse(tmpl)
3745 tree = templater.parse(tmpl)
3760 ui.note(templater.prettyformat(tree), '\n')
3746 ui.note(templater.prettyformat(tree), '\n')
3761 newtree = templater.expandaliases(tree, aliases)
3747 newtree = templater.expandaliases(tree, aliases)
3762 if newtree != tree:
3748 if newtree != tree:
3763 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3749 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3764
3750
3765 mapfile = None
3751 mapfile = None
3766 if revs is None:
3752 if revs is None:
3767 k = 'debugtemplate'
3753 k = 'debugtemplate'
3768 t = formatter.maketemplater(ui, k, tmpl)
3754 t = formatter.maketemplater(ui, k, tmpl)
3769 ui.write(templater.stringify(t(k, **props)))
3755 ui.write(templater.stringify(t(k, **props)))
3770 else:
3756 else:
3771 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3757 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3772 mapfile, buffered=False)
3758 mapfile, buffered=False)
3773 for r in revs:
3759 for r in revs:
3774 displayer.show(repo[r], **props)
3760 displayer.show(repo[r], **props)
3775 displayer.close()
3761 displayer.close()
3776
3762
3777 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3763 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3778 def debugwalk(ui, repo, *pats, **opts):
3764 def debugwalk(ui, repo, *pats, **opts):
3779 """show how files match on given patterns"""
3765 """show how files match on given patterns"""
3780 m = scmutil.match(repo[None], pats, opts)
3766 m = scmutil.match(repo[None], pats, opts)
3781 items = list(repo.walk(m))
3767 items = list(repo.walk(m))
3782 if not items:
3768 if not items:
3783 return
3769 return
3784 f = lambda fn: fn
3770 f = lambda fn: fn
3785 if ui.configbool('ui', 'slash') and os.sep != '/':
3771 if ui.configbool('ui', 'slash') and os.sep != '/':
3786 f = lambda fn: util.normpath(fn)
3772 f = lambda fn: util.normpath(fn)
3787 fmt = 'f %%-%ds %%-%ds %%s' % (
3773 fmt = 'f %%-%ds %%-%ds %%s' % (
3788 max([len(abs) for abs in items]),
3774 max([len(abs) for abs in items]),
3789 max([len(m.rel(abs)) for abs in items]))
3775 max([len(m.rel(abs)) for abs in items]))
3790 for abs in items:
3776 for abs in items:
3791 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3777 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3792 ui.write("%s\n" % line.rstrip())
3778 ui.write("%s\n" % line.rstrip())
3793
3779
3794 @command('debugwireargs',
3780 @command('debugwireargs',
3795 [('', 'three', '', 'three'),
3781 [('', 'three', '', 'three'),
3796 ('', 'four', '', 'four'),
3782 ('', 'four', '', 'four'),
3797 ('', 'five', '', 'five'),
3783 ('', 'five', '', 'five'),
3798 ] + remoteopts,
3784 ] + remoteopts,
3799 _('REPO [OPTIONS]... [ONE [TWO]]'),
3785 _('REPO [OPTIONS]... [ONE [TWO]]'),
3800 norepo=True)
3786 norepo=True)
3801 def debugwireargs(ui, repopath, *vals, **opts):
3787 def debugwireargs(ui, repopath, *vals, **opts):
3802 repo = hg.peer(ui, opts, repopath)
3788 repo = hg.peer(ui, opts, repopath)
3803 for opt in remoteopts:
3789 for opt in remoteopts:
3804 del opts[opt[1]]
3790 del opts[opt[1]]
3805 args = {}
3791 args = {}
3806 for k, v in opts.iteritems():
3792 for k, v in opts.iteritems():
3807 if v:
3793 if v:
3808 args[k] = v
3794 args[k] = v
3809 # run twice to check that we don't mess up the stream for the next command
3795 # run twice to check that we don't mess up the stream for the next command
3810 res1 = repo.debugwireargs(*vals, **args)
3796 res1 = repo.debugwireargs(*vals, **args)
3811 res2 = repo.debugwireargs(*vals, **args)
3797 res2 = repo.debugwireargs(*vals, **args)
3812 ui.write("%s\n" % res1)
3798 ui.write("%s\n" % res1)
3813 if res1 != res2:
3799 if res1 != res2:
3814 ui.warn("%s\n" % res2)
3800 ui.warn("%s\n" % res2)
3815
3801
3816 @command('^diff',
3802 @command('^diff',
3817 [('r', 'rev', [], _('revision'), _('REV')),
3803 [('r', 'rev', [], _('revision'), _('REV')),
3818 ('c', 'change', '', _('change made by revision'), _('REV'))
3804 ('c', 'change', '', _('change made by revision'), _('REV'))
3819 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3805 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3820 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3806 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3821 inferrepo=True)
3807 inferrepo=True)
3822 def diff(ui, repo, *pats, **opts):
3808 def diff(ui, repo, *pats, **opts):
3823 """diff repository (or selected files)
3809 """diff repository (or selected files)
3824
3810
3825 Show differences between revisions for the specified files.
3811 Show differences between revisions for the specified files.
3826
3812
3827 Differences between files are shown using the unified diff format.
3813 Differences between files are shown using the unified diff format.
3828
3814
3829 .. note::
3815 .. note::
3830
3816
3831 :hg:`diff` may generate unexpected results for merges, as it will
3817 :hg:`diff` may generate unexpected results for merges, as it will
3832 default to comparing against the working directory's first
3818 default to comparing against the working directory's first
3833 parent changeset if no revisions are specified.
3819 parent changeset if no revisions are specified.
3834
3820
3835 When two revision arguments are given, then changes are shown
3821 When two revision arguments are given, then changes are shown
3836 between those revisions. If only one revision is specified then
3822 between those revisions. If only one revision is specified then
3837 that revision is compared to the working directory, and, when no
3823 that revision is compared to the working directory, and, when no
3838 revisions are specified, the working directory files are compared
3824 revisions are specified, the working directory files are compared
3839 to its first parent.
3825 to its first parent.
3840
3826
3841 Alternatively you can specify -c/--change with a revision to see
3827 Alternatively you can specify -c/--change with a revision to see
3842 the changes in that changeset relative to its first parent.
3828 the changes in that changeset relative to its first parent.
3843
3829
3844 Without the -a/--text option, diff will avoid generating diffs of
3830 Without the -a/--text option, diff will avoid generating diffs of
3845 files it detects as binary. With -a, diff will generate a diff
3831 files it detects as binary. With -a, diff will generate a diff
3846 anyway, probably with undesirable results.
3832 anyway, probably with undesirable results.
3847
3833
3848 Use the -g/--git option to generate diffs in the git extended diff
3834 Use the -g/--git option to generate diffs in the git extended diff
3849 format. For more information, read :hg:`help diffs`.
3835 format. For more information, read :hg:`help diffs`.
3850
3836
3851 .. container:: verbose
3837 .. container:: verbose
3852
3838
3853 Examples:
3839 Examples:
3854
3840
3855 - compare a file in the current working directory to its parent::
3841 - compare a file in the current working directory to its parent::
3856
3842
3857 hg diff foo.c
3843 hg diff foo.c
3858
3844
3859 - compare two historical versions of a directory, with rename info::
3845 - compare two historical versions of a directory, with rename info::
3860
3846
3861 hg diff --git -r 1.0:1.2 lib/
3847 hg diff --git -r 1.0:1.2 lib/
3862
3848
3863 - get change stats relative to the last change on some date::
3849 - get change stats relative to the last change on some date::
3864
3850
3865 hg diff --stat -r "date('may 2')"
3851 hg diff --stat -r "date('may 2')"
3866
3852
3867 - diff all newly-added files that contain a keyword::
3853 - diff all newly-added files that contain a keyword::
3868
3854
3869 hg diff "set:added() and grep(GNU)"
3855 hg diff "set:added() and grep(GNU)"
3870
3856
3871 - compare a revision and its parents::
3857 - compare a revision and its parents::
3872
3858
3873 hg diff -c 9353 # compare against first parent
3859 hg diff -c 9353 # compare against first parent
3874 hg diff -r 9353^:9353 # same using revset syntax
3860 hg diff -r 9353^:9353 # same using revset syntax
3875 hg diff -r 9353^2:9353 # compare against the second parent
3861 hg diff -r 9353^2:9353 # compare against the second parent
3876
3862
3877 Returns 0 on success.
3863 Returns 0 on success.
3878 """
3864 """
3879
3865
3880 revs = opts.get('rev')
3866 revs = opts.get('rev')
3881 change = opts.get('change')
3867 change = opts.get('change')
3882 stat = opts.get('stat')
3868 stat = opts.get('stat')
3883 reverse = opts.get('reverse')
3869 reverse = opts.get('reverse')
3884
3870
3885 if revs and change:
3871 if revs and change:
3886 msg = _('cannot specify --rev and --change at the same time')
3872 msg = _('cannot specify --rev and --change at the same time')
3887 raise error.Abort(msg)
3873 raise error.Abort(msg)
3888 elif change:
3874 elif change:
3889 node2 = scmutil.revsingle(repo, change, None).node()
3875 node2 = scmutil.revsingle(repo, change, None).node()
3890 node1 = repo[node2].p1().node()
3876 node1 = repo[node2].p1().node()
3891 else:
3877 else:
3892 node1, node2 = scmutil.revpair(repo, revs)
3878 node1, node2 = scmutil.revpair(repo, revs)
3893
3879
3894 if reverse:
3880 if reverse:
3895 node1, node2 = node2, node1
3881 node1, node2 = node2, node1
3896
3882
3897 diffopts = patch.diffallopts(ui, opts)
3883 diffopts = patch.diffallopts(ui, opts)
3898 m = scmutil.match(repo[node2], pats, opts)
3884 m = scmutil.match(repo[node2], pats, opts)
3899 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3885 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3900 listsubrepos=opts.get('subrepos'),
3886 listsubrepos=opts.get('subrepos'),
3901 root=opts.get('root'))
3887 root=opts.get('root'))
3902
3888
3903 @command('^export',
3889 @command('^export',
3904 [('o', 'output', '',
3890 [('o', 'output', '',
3905 _('print output to file with formatted name'), _('FORMAT')),
3891 _('print output to file with formatted name'), _('FORMAT')),
3906 ('', 'switch-parent', None, _('diff against the second parent')),
3892 ('', 'switch-parent', None, _('diff against the second parent')),
3907 ('r', 'rev', [], _('revisions to export'), _('REV')),
3893 ('r', 'rev', [], _('revisions to export'), _('REV')),
3908 ] + diffopts,
3894 ] + diffopts,
3909 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3895 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3910 def export(ui, repo, *changesets, **opts):
3896 def export(ui, repo, *changesets, **opts):
3911 """dump the header and diffs for one or more changesets
3897 """dump the header and diffs for one or more changesets
3912
3898
3913 Print the changeset header and diffs for one or more revisions.
3899 Print the changeset header and diffs for one or more revisions.
3914 If no revision is given, the parent of the working directory is used.
3900 If no revision is given, the parent of the working directory is used.
3915
3901
3916 The information shown in the changeset header is: author, date,
3902 The information shown in the changeset header is: author, date,
3917 branch name (if non-default), changeset hash, parent(s) and commit
3903 branch name (if non-default), changeset hash, parent(s) and commit
3918 comment.
3904 comment.
3919
3905
3920 .. note::
3906 .. note::
3921
3907
3922 :hg:`export` may generate unexpected diff output for merge
3908 :hg:`export` may generate unexpected diff output for merge
3923 changesets, as it will compare the merge changeset against its
3909 changesets, as it will compare the merge changeset against its
3924 first parent only.
3910 first parent only.
3925
3911
3926 Output may be to a file, in which case the name of the file is
3912 Output may be to a file, in which case the name of the file is
3927 given using a format string. The formatting rules are as follows:
3913 given using a format string. The formatting rules are as follows:
3928
3914
3929 :``%%``: literal "%" character
3915 :``%%``: literal "%" character
3930 :``%H``: changeset hash (40 hexadecimal digits)
3916 :``%H``: changeset hash (40 hexadecimal digits)
3931 :``%N``: number of patches being generated
3917 :``%N``: number of patches being generated
3932 :``%R``: changeset revision number
3918 :``%R``: changeset revision number
3933 :``%b``: basename of the exporting repository
3919 :``%b``: basename of the exporting repository
3934 :``%h``: short-form changeset hash (12 hexadecimal digits)
3920 :``%h``: short-form changeset hash (12 hexadecimal digits)
3935 :``%m``: first line of the commit message (only alphanumeric characters)
3921 :``%m``: first line of the commit message (only alphanumeric characters)
3936 :``%n``: zero-padded sequence number, starting at 1
3922 :``%n``: zero-padded sequence number, starting at 1
3937 :``%r``: zero-padded changeset revision number
3923 :``%r``: zero-padded changeset revision number
3938
3924
3939 Without the -a/--text option, export will avoid generating diffs
3925 Without the -a/--text option, export will avoid generating diffs
3940 of files it detects as binary. With -a, export will generate a
3926 of files it detects as binary. With -a, export will generate a
3941 diff anyway, probably with undesirable results.
3927 diff anyway, probably with undesirable results.
3942
3928
3943 Use the -g/--git option to generate diffs in the git extended diff
3929 Use the -g/--git option to generate diffs in the git extended diff
3944 format. See :hg:`help diffs` for more information.
3930 format. See :hg:`help diffs` for more information.
3945
3931
3946 With the --switch-parent option, the diff will be against the
3932 With the --switch-parent option, the diff will be against the
3947 second parent. It can be useful to review a merge.
3933 second parent. It can be useful to review a merge.
3948
3934
3949 .. container:: verbose
3935 .. container:: verbose
3950
3936
3951 Examples:
3937 Examples:
3952
3938
3953 - use export and import to transplant a bugfix to the current
3939 - use export and import to transplant a bugfix to the current
3954 branch::
3940 branch::
3955
3941
3956 hg export -r 9353 | hg import -
3942 hg export -r 9353 | hg import -
3957
3943
3958 - export all the changesets between two revisions to a file with
3944 - export all the changesets between two revisions to a file with
3959 rename information::
3945 rename information::
3960
3946
3961 hg export --git -r 123:150 > changes.txt
3947 hg export --git -r 123:150 > changes.txt
3962
3948
3963 - split outgoing changes into a series of patches with
3949 - split outgoing changes into a series of patches with
3964 descriptive names::
3950 descriptive names::
3965
3951
3966 hg export -r "outgoing()" -o "%n-%m.patch"
3952 hg export -r "outgoing()" -o "%n-%m.patch"
3967
3953
3968 Returns 0 on success.
3954 Returns 0 on success.
3969 """
3955 """
3970 changesets += tuple(opts.get('rev', []))
3956 changesets += tuple(opts.get('rev', []))
3971 if not changesets:
3957 if not changesets:
3972 changesets = ['.']
3958 changesets = ['.']
3973 revs = scmutil.revrange(repo, changesets)
3959 revs = scmutil.revrange(repo, changesets)
3974 if not revs:
3960 if not revs:
3975 raise error.Abort(_("export requires at least one changeset"))
3961 raise error.Abort(_("export requires at least one changeset"))
3976 if len(revs) > 1:
3962 if len(revs) > 1:
3977 ui.note(_('exporting patches:\n'))
3963 ui.note(_('exporting patches:\n'))
3978 else:
3964 else:
3979 ui.note(_('exporting patch:\n'))
3965 ui.note(_('exporting patch:\n'))
3980 cmdutil.export(repo, revs, template=opts.get('output'),
3966 cmdutil.export(repo, revs, template=opts.get('output'),
3981 switch_parent=opts.get('switch_parent'),
3967 switch_parent=opts.get('switch_parent'),
3982 opts=patch.diffallopts(ui, opts))
3968 opts=patch.diffallopts(ui, opts))
3983
3969
3984 @command('files',
3970 @command('files',
3985 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3971 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3986 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3972 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3987 ] + walkopts + formatteropts + subrepoopts,
3973 ] + walkopts + formatteropts + subrepoopts,
3988 _('[OPTION]... [FILE]...'))
3974 _('[OPTION]... [FILE]...'))
3989 def files(ui, repo, *pats, **opts):
3975 def files(ui, repo, *pats, **opts):
3990 """list tracked files
3976 """list tracked files
3991
3977
3992 Print files under Mercurial control in the working directory or
3978 Print files under Mercurial control in the working directory or
3993 specified revision for given files (excluding removed files).
3979 specified revision for given files (excluding removed files).
3994 Files can be specified as filenames or filesets.
3980 Files can be specified as filenames or filesets.
3995
3981
3996 If no files are given to match, this command prints the names
3982 If no files are given to match, this command prints the names
3997 of all files under Mercurial control.
3983 of all files under Mercurial control.
3998
3984
3999 .. container:: verbose
3985 .. container:: verbose
4000
3986
4001 Examples:
3987 Examples:
4002
3988
4003 - list all files under the current directory::
3989 - list all files under the current directory::
4004
3990
4005 hg files .
3991 hg files .
4006
3992
4007 - shows sizes and flags for current revision::
3993 - shows sizes and flags for current revision::
4008
3994
4009 hg files -vr .
3995 hg files -vr .
4010
3996
4011 - list all files named README::
3997 - list all files named README::
4012
3998
4013 hg files -I "**/README"
3999 hg files -I "**/README"
4014
4000
4015 - list all binary files::
4001 - list all binary files::
4016
4002
4017 hg files "set:binary()"
4003 hg files "set:binary()"
4018
4004
4019 - find files containing a regular expression::
4005 - find files containing a regular expression::
4020
4006
4021 hg files "set:grep('bob')"
4007 hg files "set:grep('bob')"
4022
4008
4023 - search tracked file contents with xargs and grep::
4009 - search tracked file contents with xargs and grep::
4024
4010
4025 hg files -0 | xargs -0 grep foo
4011 hg files -0 | xargs -0 grep foo
4026
4012
4027 See :hg:`help patterns` and :hg:`help filesets` for more information
4013 See :hg:`help patterns` and :hg:`help filesets` for more information
4028 on specifying file patterns.
4014 on specifying file patterns.
4029
4015
4030 Returns 0 if a match is found, 1 otherwise.
4016 Returns 0 if a match is found, 1 otherwise.
4031
4017
4032 """
4018 """
4033 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4019 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4034
4020
4035 end = '\n'
4021 end = '\n'
4036 if opts.get('print0'):
4022 if opts.get('print0'):
4037 end = '\0'
4023 end = '\0'
4038 fmt = '%s' + end
4024 fmt = '%s' + end
4039
4025
4040 m = scmutil.match(ctx, pats, opts)
4026 m = scmutil.match(ctx, pats, opts)
4041 with ui.formatter('files', opts) as fm:
4027 with ui.formatter('files', opts) as fm:
4042 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
4028 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
4043
4029
4044 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
4030 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
4045 def forget(ui, repo, *pats, **opts):
4031 def forget(ui, repo, *pats, **opts):
4046 """forget the specified files on the next commit
4032 """forget the specified files on the next commit
4047
4033
4048 Mark the specified files so they will no longer be tracked
4034 Mark the specified files so they will no longer be tracked
4049 after the next commit.
4035 after the next commit.
4050
4036
4051 This only removes files from the current branch, not from the
4037 This only removes files from the current branch, not from the
4052 entire project history, and it does not delete them from the
4038 entire project history, and it does not delete them from the
4053 working directory.
4039 working directory.
4054
4040
4055 To delete the file from the working directory, see :hg:`remove`.
4041 To delete the file from the working directory, see :hg:`remove`.
4056
4042
4057 To undo a forget before the next commit, see :hg:`add`.
4043 To undo a forget before the next commit, see :hg:`add`.
4058
4044
4059 .. container:: verbose
4045 .. container:: verbose
4060
4046
4061 Examples:
4047 Examples:
4062
4048
4063 - forget newly-added binary files::
4049 - forget newly-added binary files::
4064
4050
4065 hg forget "set:added() and binary()"
4051 hg forget "set:added() and binary()"
4066
4052
4067 - forget files that would be excluded by .hgignore::
4053 - forget files that would be excluded by .hgignore::
4068
4054
4069 hg forget "set:hgignore()"
4055 hg forget "set:hgignore()"
4070
4056
4071 Returns 0 on success.
4057 Returns 0 on success.
4072 """
4058 """
4073
4059
4074 if not pats:
4060 if not pats:
4075 raise error.Abort(_('no files specified'))
4061 raise error.Abort(_('no files specified'))
4076
4062
4077 m = scmutil.match(repo[None], pats, opts)
4063 m = scmutil.match(repo[None], pats, opts)
4078 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4064 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4079 return rejected and 1 or 0
4065 return rejected and 1 or 0
4080
4066
4081 @command(
4067 @command(
4082 'graft',
4068 'graft',
4083 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4069 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4084 ('c', 'continue', False, _('resume interrupted graft')),
4070 ('c', 'continue', False, _('resume interrupted graft')),
4085 ('e', 'edit', False, _('invoke editor on commit messages')),
4071 ('e', 'edit', False, _('invoke editor on commit messages')),
4086 ('', 'log', None, _('append graft info to log message')),
4072 ('', 'log', None, _('append graft info to log message')),
4087 ('f', 'force', False, _('force graft')),
4073 ('f', 'force', False, _('force graft')),
4088 ('D', 'currentdate', False,
4074 ('D', 'currentdate', False,
4089 _('record the current date as commit date')),
4075 _('record the current date as commit date')),
4090 ('U', 'currentuser', False,
4076 ('U', 'currentuser', False,
4091 _('record the current user as committer'), _('DATE'))]
4077 _('record the current user as committer'), _('DATE'))]
4092 + commitopts2 + mergetoolopts + dryrunopts,
4078 + commitopts2 + mergetoolopts + dryrunopts,
4093 _('[OPTION]... [-r REV]... REV...'))
4079 _('[OPTION]... [-r REV]... REV...'))
4094 def graft(ui, repo, *revs, **opts):
4080 def graft(ui, repo, *revs, **opts):
4095 '''copy changes from other branches onto the current branch
4081 '''copy changes from other branches onto the current branch
4096
4082
4097 This command uses Mercurial's merge logic to copy individual
4083 This command uses Mercurial's merge logic to copy individual
4098 changes from other branches without merging branches in the
4084 changes from other branches without merging branches in the
4099 history graph. This is sometimes known as 'backporting' or
4085 history graph. This is sometimes known as 'backporting' or
4100 'cherry-picking'. By default, graft will copy user, date, and
4086 'cherry-picking'. By default, graft will copy user, date, and
4101 description from the source changesets.
4087 description from the source changesets.
4102
4088
4103 Changesets that are ancestors of the current revision, that have
4089 Changesets that are ancestors of the current revision, that have
4104 already been grafted, or that are merges will be skipped.
4090 already been grafted, or that are merges will be skipped.
4105
4091
4106 If --log is specified, log messages will have a comment appended
4092 If --log is specified, log messages will have a comment appended
4107 of the form::
4093 of the form::
4108
4094
4109 (grafted from CHANGESETHASH)
4095 (grafted from CHANGESETHASH)
4110
4096
4111 If --force is specified, revisions will be grafted even if they
4097 If --force is specified, revisions will be grafted even if they
4112 are already ancestors of or have been grafted to the destination.
4098 are already ancestors of or have been grafted to the destination.
4113 This is useful when the revisions have since been backed out.
4099 This is useful when the revisions have since been backed out.
4114
4100
4115 If a graft merge results in conflicts, the graft process is
4101 If a graft merge results in conflicts, the graft process is
4116 interrupted so that the current merge can be manually resolved.
4102 interrupted so that the current merge can be manually resolved.
4117 Once all conflicts are addressed, the graft process can be
4103 Once all conflicts are addressed, the graft process can be
4118 continued with the -c/--continue option.
4104 continued with the -c/--continue option.
4119
4105
4120 .. note::
4106 .. note::
4121
4107
4122 The -c/--continue option does not reapply earlier options, except
4108 The -c/--continue option does not reapply earlier options, except
4123 for --force.
4109 for --force.
4124
4110
4125 .. container:: verbose
4111 .. container:: verbose
4126
4112
4127 Examples:
4113 Examples:
4128
4114
4129 - copy a single change to the stable branch and edit its description::
4115 - copy a single change to the stable branch and edit its description::
4130
4116
4131 hg update stable
4117 hg update stable
4132 hg graft --edit 9393
4118 hg graft --edit 9393
4133
4119
4134 - graft a range of changesets with one exception, updating dates::
4120 - graft a range of changesets with one exception, updating dates::
4135
4121
4136 hg graft -D "2085::2093 and not 2091"
4122 hg graft -D "2085::2093 and not 2091"
4137
4123
4138 - continue a graft after resolving conflicts::
4124 - continue a graft after resolving conflicts::
4139
4125
4140 hg graft -c
4126 hg graft -c
4141
4127
4142 - show the source of a grafted changeset::
4128 - show the source of a grafted changeset::
4143
4129
4144 hg log --debug -r .
4130 hg log --debug -r .
4145
4131
4146 - show revisions sorted by date::
4132 - show revisions sorted by date::
4147
4133
4148 hg log -r "sort(all(), date)"
4134 hg log -r "sort(all(), date)"
4149
4135
4150 See :hg:`help revisions` and :hg:`help revsets` for more about
4136 See :hg:`help revisions` and :hg:`help revsets` for more about
4151 specifying revisions.
4137 specifying revisions.
4152
4138
4153 Returns 0 on successful completion.
4139 Returns 0 on successful completion.
4154 '''
4140 '''
4155 with repo.wlock():
4141 with repo.wlock():
4156 return _dograft(ui, repo, *revs, **opts)
4142 return _dograft(ui, repo, *revs, **opts)
4157
4143
4158 def _dograft(ui, repo, *revs, **opts):
4144 def _dograft(ui, repo, *revs, **opts):
4159 if revs and opts.get('rev'):
4145 if revs and opts.get('rev'):
4160 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4146 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4161 'revision ordering!\n'))
4147 'revision ordering!\n'))
4162
4148
4163 revs = list(revs)
4149 revs = list(revs)
4164 revs.extend(opts.get('rev'))
4150 revs.extend(opts.get('rev'))
4165
4151
4166 if not opts.get('user') and opts.get('currentuser'):
4152 if not opts.get('user') and opts.get('currentuser'):
4167 opts['user'] = ui.username()
4153 opts['user'] = ui.username()
4168 if not opts.get('date') and opts.get('currentdate'):
4154 if not opts.get('date') and opts.get('currentdate'):
4169 opts['date'] = "%d %d" % util.makedate()
4155 opts['date'] = "%d %d" % util.makedate()
4170
4156
4171 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4157 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4172
4158
4173 cont = False
4159 cont = False
4174 if opts.get('continue'):
4160 if opts.get('continue'):
4175 cont = True
4161 cont = True
4176 if revs:
4162 if revs:
4177 raise error.Abort(_("can't specify --continue and revisions"))
4163 raise error.Abort(_("can't specify --continue and revisions"))
4178 # read in unfinished revisions
4164 # read in unfinished revisions
4179 try:
4165 try:
4180 nodes = repo.vfs.read('graftstate').splitlines()
4166 nodes = repo.vfs.read('graftstate').splitlines()
4181 revs = [repo[node].rev() for node in nodes]
4167 revs = [repo[node].rev() for node in nodes]
4182 except IOError as inst:
4168 except IOError as inst:
4183 if inst.errno != errno.ENOENT:
4169 if inst.errno != errno.ENOENT:
4184 raise
4170 raise
4185 cmdutil.wrongtooltocontinue(repo, _('graft'))
4171 cmdutil.wrongtooltocontinue(repo, _('graft'))
4186 else:
4172 else:
4187 cmdutil.checkunfinished(repo)
4173 cmdutil.checkunfinished(repo)
4188 cmdutil.bailifchanged(repo)
4174 cmdutil.bailifchanged(repo)
4189 if not revs:
4175 if not revs:
4190 raise error.Abort(_('no revisions specified'))
4176 raise error.Abort(_('no revisions specified'))
4191 revs = scmutil.revrange(repo, revs)
4177 revs = scmutil.revrange(repo, revs)
4192
4178
4193 skipped = set()
4179 skipped = set()
4194 # check for merges
4180 # check for merges
4195 for rev in repo.revs('%ld and merge()', revs):
4181 for rev in repo.revs('%ld and merge()', revs):
4196 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4182 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4197 skipped.add(rev)
4183 skipped.add(rev)
4198 revs = [r for r in revs if r not in skipped]
4184 revs = [r for r in revs if r not in skipped]
4199 if not revs:
4185 if not revs:
4200 return -1
4186 return -1
4201
4187
4202 # Don't check in the --continue case, in effect retaining --force across
4188 # Don't check in the --continue case, in effect retaining --force across
4203 # --continues. That's because without --force, any revisions we decided to
4189 # --continues. That's because without --force, any revisions we decided to
4204 # skip would have been filtered out here, so they wouldn't have made their
4190 # skip would have been filtered out here, so they wouldn't have made their
4205 # way to the graftstate. With --force, any revisions we would have otherwise
4191 # way to the graftstate. With --force, any revisions we would have otherwise
4206 # skipped would not have been filtered out, and if they hadn't been applied
4192 # skipped would not have been filtered out, and if they hadn't been applied
4207 # already, they'd have been in the graftstate.
4193 # already, they'd have been in the graftstate.
4208 if not (cont or opts.get('force')):
4194 if not (cont or opts.get('force')):
4209 # check for ancestors of dest branch
4195 # check for ancestors of dest branch
4210 crev = repo['.'].rev()
4196 crev = repo['.'].rev()
4211 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4197 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4212 # XXX make this lazy in the future
4198 # XXX make this lazy in the future
4213 # don't mutate while iterating, create a copy
4199 # don't mutate while iterating, create a copy
4214 for rev in list(revs):
4200 for rev in list(revs):
4215 if rev in ancestors:
4201 if rev in ancestors:
4216 ui.warn(_('skipping ancestor revision %d:%s\n') %
4202 ui.warn(_('skipping ancestor revision %d:%s\n') %
4217 (rev, repo[rev]))
4203 (rev, repo[rev]))
4218 # XXX remove on list is slow
4204 # XXX remove on list is slow
4219 revs.remove(rev)
4205 revs.remove(rev)
4220 if not revs:
4206 if not revs:
4221 return -1
4207 return -1
4222
4208
4223 # analyze revs for earlier grafts
4209 # analyze revs for earlier grafts
4224 ids = {}
4210 ids = {}
4225 for ctx in repo.set("%ld", revs):
4211 for ctx in repo.set("%ld", revs):
4226 ids[ctx.hex()] = ctx.rev()
4212 ids[ctx.hex()] = ctx.rev()
4227 n = ctx.extra().get('source')
4213 n = ctx.extra().get('source')
4228 if n:
4214 if n:
4229 ids[n] = ctx.rev()
4215 ids[n] = ctx.rev()
4230
4216
4231 # check ancestors for earlier grafts
4217 # check ancestors for earlier grafts
4232 ui.debug('scanning for duplicate grafts\n')
4218 ui.debug('scanning for duplicate grafts\n')
4233
4219
4234 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4220 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4235 ctx = repo[rev]
4221 ctx = repo[rev]
4236 n = ctx.extra().get('source')
4222 n = ctx.extra().get('source')
4237 if n in ids:
4223 if n in ids:
4238 try:
4224 try:
4239 r = repo[n].rev()
4225 r = repo[n].rev()
4240 except error.RepoLookupError:
4226 except error.RepoLookupError:
4241 r = None
4227 r = None
4242 if r in revs:
4228 if r in revs:
4243 ui.warn(_('skipping revision %d:%s '
4229 ui.warn(_('skipping revision %d:%s '
4244 '(already grafted to %d:%s)\n')
4230 '(already grafted to %d:%s)\n')
4245 % (r, repo[r], rev, ctx))
4231 % (r, repo[r], rev, ctx))
4246 revs.remove(r)
4232 revs.remove(r)
4247 elif ids[n] in revs:
4233 elif ids[n] in revs:
4248 if r is None:
4234 if r is None:
4249 ui.warn(_('skipping already grafted revision %d:%s '
4235 ui.warn(_('skipping already grafted revision %d:%s '
4250 '(%d:%s also has unknown origin %s)\n')
4236 '(%d:%s also has unknown origin %s)\n')
4251 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4237 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4252 else:
4238 else:
4253 ui.warn(_('skipping already grafted revision %d:%s '
4239 ui.warn(_('skipping already grafted revision %d:%s '
4254 '(%d:%s also has origin %d:%s)\n')
4240 '(%d:%s also has origin %d:%s)\n')
4255 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4241 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4256 revs.remove(ids[n])
4242 revs.remove(ids[n])
4257 elif ctx.hex() in ids:
4243 elif ctx.hex() in ids:
4258 r = ids[ctx.hex()]
4244 r = ids[ctx.hex()]
4259 ui.warn(_('skipping already grafted revision %d:%s '
4245 ui.warn(_('skipping already grafted revision %d:%s '
4260 '(was grafted from %d:%s)\n') %
4246 '(was grafted from %d:%s)\n') %
4261 (r, repo[r], rev, ctx))
4247 (r, repo[r], rev, ctx))
4262 revs.remove(r)
4248 revs.remove(r)
4263 if not revs:
4249 if not revs:
4264 return -1
4250 return -1
4265
4251
4266 for pos, ctx in enumerate(repo.set("%ld", revs)):
4252 for pos, ctx in enumerate(repo.set("%ld", revs)):
4267 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4253 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4268 ctx.description().split('\n', 1)[0])
4254 ctx.description().split('\n', 1)[0])
4269 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4255 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4270 if names:
4256 if names:
4271 desc += ' (%s)' % ' '.join(names)
4257 desc += ' (%s)' % ' '.join(names)
4272 ui.status(_('grafting %s\n') % desc)
4258 ui.status(_('grafting %s\n') % desc)
4273 if opts.get('dry_run'):
4259 if opts.get('dry_run'):
4274 continue
4260 continue
4275
4261
4276 source = ctx.extra().get('source')
4262 source = ctx.extra().get('source')
4277 extra = {}
4263 extra = {}
4278 if source:
4264 if source:
4279 extra['source'] = source
4265 extra['source'] = source
4280 extra['intermediate-source'] = ctx.hex()
4266 extra['intermediate-source'] = ctx.hex()
4281 else:
4267 else:
4282 extra['source'] = ctx.hex()
4268 extra['source'] = ctx.hex()
4283 user = ctx.user()
4269 user = ctx.user()
4284 if opts.get('user'):
4270 if opts.get('user'):
4285 user = opts['user']
4271 user = opts['user']
4286 date = ctx.date()
4272 date = ctx.date()
4287 if opts.get('date'):
4273 if opts.get('date'):
4288 date = opts['date']
4274 date = opts['date']
4289 message = ctx.description()
4275 message = ctx.description()
4290 if opts.get('log'):
4276 if opts.get('log'):
4291 message += '\n(grafted from %s)' % ctx.hex()
4277 message += '\n(grafted from %s)' % ctx.hex()
4292
4278
4293 # we don't merge the first commit when continuing
4279 # we don't merge the first commit when continuing
4294 if not cont:
4280 if not cont:
4295 # perform the graft merge with p1(rev) as 'ancestor'
4281 # perform the graft merge with p1(rev) as 'ancestor'
4296 try:
4282 try:
4297 # ui.forcemerge is an internal variable, do not document
4283 # ui.forcemerge is an internal variable, do not document
4298 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4284 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4299 'graft')
4285 'graft')
4300 stats = mergemod.graft(repo, ctx, ctx.p1(),
4286 stats = mergemod.graft(repo, ctx, ctx.p1(),
4301 ['local', 'graft'])
4287 ['local', 'graft'])
4302 finally:
4288 finally:
4303 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4289 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4304 # report any conflicts
4290 # report any conflicts
4305 if stats and stats[3] > 0:
4291 if stats and stats[3] > 0:
4306 # write out state for --continue
4292 # write out state for --continue
4307 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4293 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4308 repo.vfs.write('graftstate', ''.join(nodelines))
4294 repo.vfs.write('graftstate', ''.join(nodelines))
4309 extra = ''
4295 extra = ''
4310 if opts.get('user'):
4296 if opts.get('user'):
4311 extra += ' --user %s' % util.shellquote(opts['user'])
4297 extra += ' --user %s' % util.shellquote(opts['user'])
4312 if opts.get('date'):
4298 if opts.get('date'):
4313 extra += ' --date %s' % util.shellquote(opts['date'])
4299 extra += ' --date %s' % util.shellquote(opts['date'])
4314 if opts.get('log'):
4300 if opts.get('log'):
4315 extra += ' --log'
4301 extra += ' --log'
4316 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4302 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4317 raise error.Abort(
4303 raise error.Abort(
4318 _("unresolved conflicts, can't continue"),
4304 _("unresolved conflicts, can't continue"),
4319 hint=hint)
4305 hint=hint)
4320 else:
4306 else:
4321 cont = False
4307 cont = False
4322
4308
4323 # commit
4309 # commit
4324 node = repo.commit(text=message, user=user,
4310 node = repo.commit(text=message, user=user,
4325 date=date, extra=extra, editor=editor)
4311 date=date, extra=extra, editor=editor)
4326 if node is None:
4312 if node is None:
4327 ui.warn(
4313 ui.warn(
4328 _('note: graft of %d:%s created no changes to commit\n') %
4314 _('note: graft of %d:%s created no changes to commit\n') %
4329 (ctx.rev(), ctx))
4315 (ctx.rev(), ctx))
4330
4316
4331 # remove state when we complete successfully
4317 # remove state when we complete successfully
4332 if not opts.get('dry_run'):
4318 if not opts.get('dry_run'):
4333 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4319 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4334
4320
4335 return 0
4321 return 0
4336
4322
4337 @command('grep',
4323 @command('grep',
4338 [('0', 'print0', None, _('end fields with NUL')),
4324 [('0', 'print0', None, _('end fields with NUL')),
4339 ('', 'all', None, _('print all revisions that match')),
4325 ('', 'all', None, _('print all revisions that match')),
4340 ('a', 'text', None, _('treat all files as text')),
4326 ('a', 'text', None, _('treat all files as text')),
4341 ('f', 'follow', None,
4327 ('f', 'follow', None,
4342 _('follow changeset history,'
4328 _('follow changeset history,'
4343 ' or file history across copies and renames')),
4329 ' or file history across copies and renames')),
4344 ('i', 'ignore-case', None, _('ignore case when matching')),
4330 ('i', 'ignore-case', None, _('ignore case when matching')),
4345 ('l', 'files-with-matches', None,
4331 ('l', 'files-with-matches', None,
4346 _('print only filenames and revisions that match')),
4332 _('print only filenames and revisions that match')),
4347 ('n', 'line-number', None, _('print matching line numbers')),
4333 ('n', 'line-number', None, _('print matching line numbers')),
4348 ('r', 'rev', [],
4334 ('r', 'rev', [],
4349 _('only search files changed within revision range'), _('REV')),
4335 _('only search files changed within revision range'), _('REV')),
4350 ('u', 'user', None, _('list the author (long with -v)')),
4336 ('u', 'user', None, _('list the author (long with -v)')),
4351 ('d', 'date', None, _('list the date (short with -q)')),
4337 ('d', 'date', None, _('list the date (short with -q)')),
4352 ] + formatteropts + walkopts,
4338 ] + formatteropts + walkopts,
4353 _('[OPTION]... PATTERN [FILE]...'),
4339 _('[OPTION]... PATTERN [FILE]...'),
4354 inferrepo=True)
4340 inferrepo=True)
4355 def grep(ui, repo, pattern, *pats, **opts):
4341 def grep(ui, repo, pattern, *pats, **opts):
4356 """search revision history for a pattern in specified files
4342 """search revision history for a pattern in specified files
4357
4343
4358 Search revision history for a regular expression in the specified
4344 Search revision history for a regular expression in the specified
4359 files or the entire project.
4345 files or the entire project.
4360
4346
4361 By default, grep prints the most recent revision number for each
4347 By default, grep prints the most recent revision number for each
4362 file in which it finds a match. To get it to print every revision
4348 file in which it finds a match. To get it to print every revision
4363 that contains a change in match status ("-" for a match that becomes
4349 that contains a change in match status ("-" for a match that becomes
4364 a non-match, or "+" for a non-match that becomes a match), use the
4350 a non-match, or "+" for a non-match that becomes a match), use the
4365 --all flag.
4351 --all flag.
4366
4352
4367 PATTERN can be any Python (roughly Perl-compatible) regular
4353 PATTERN can be any Python (roughly Perl-compatible) regular
4368 expression.
4354 expression.
4369
4355
4370 If no FILEs are specified (and -f/--follow isn't set), all files in
4356 If no FILEs are specified (and -f/--follow isn't set), all files in
4371 the repository are searched, including those that don't exist in the
4357 the repository are searched, including those that don't exist in the
4372 current branch or have been deleted in a prior changeset.
4358 current branch or have been deleted in a prior changeset.
4373
4359
4374 Returns 0 if a match is found, 1 otherwise.
4360 Returns 0 if a match is found, 1 otherwise.
4375 """
4361 """
4376 reflags = re.M
4362 reflags = re.M
4377 if opts.get('ignore_case'):
4363 if opts.get('ignore_case'):
4378 reflags |= re.I
4364 reflags |= re.I
4379 try:
4365 try:
4380 regexp = util.re.compile(pattern, reflags)
4366 regexp = util.re.compile(pattern, reflags)
4381 except re.error as inst:
4367 except re.error as inst:
4382 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4368 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4383 return 1
4369 return 1
4384 sep, eol = ':', '\n'
4370 sep, eol = ':', '\n'
4385 if opts.get('print0'):
4371 if opts.get('print0'):
4386 sep = eol = '\0'
4372 sep = eol = '\0'
4387
4373
4388 getfile = util.lrucachefunc(repo.file)
4374 getfile = util.lrucachefunc(repo.file)
4389
4375
4390 def matchlines(body):
4376 def matchlines(body):
4391 begin = 0
4377 begin = 0
4392 linenum = 0
4378 linenum = 0
4393 while begin < len(body):
4379 while begin < len(body):
4394 match = regexp.search(body, begin)
4380 match = regexp.search(body, begin)
4395 if not match:
4381 if not match:
4396 break
4382 break
4397 mstart, mend = match.span()
4383 mstart, mend = match.span()
4398 linenum += body.count('\n', begin, mstart) + 1
4384 linenum += body.count('\n', begin, mstart) + 1
4399 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4385 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4400 begin = body.find('\n', mend) + 1 or len(body) + 1
4386 begin = body.find('\n', mend) + 1 or len(body) + 1
4401 lend = begin - 1
4387 lend = begin - 1
4402 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4388 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4403
4389
4404 class linestate(object):
4390 class linestate(object):
4405 def __init__(self, line, linenum, colstart, colend):
4391 def __init__(self, line, linenum, colstart, colend):
4406 self.line = line
4392 self.line = line
4407 self.linenum = linenum
4393 self.linenum = linenum
4408 self.colstart = colstart
4394 self.colstart = colstart
4409 self.colend = colend
4395 self.colend = colend
4410
4396
4411 def __hash__(self):
4397 def __hash__(self):
4412 return hash((self.linenum, self.line))
4398 return hash((self.linenum, self.line))
4413
4399
4414 def __eq__(self, other):
4400 def __eq__(self, other):
4415 return self.line == other.line
4401 return self.line == other.line
4416
4402
4417 def findpos(self):
4403 def findpos(self):
4418 """Iterate all (start, end) indices of matches"""
4404 """Iterate all (start, end) indices of matches"""
4419 yield self.colstart, self.colend
4405 yield self.colstart, self.colend
4420 p = self.colend
4406 p = self.colend
4421 while p < len(self.line):
4407 while p < len(self.line):
4422 m = regexp.search(self.line, p)
4408 m = regexp.search(self.line, p)
4423 if not m:
4409 if not m:
4424 break
4410 break
4425 yield m.span()
4411 yield m.span()
4426 p = m.end()
4412 p = m.end()
4427
4413
4428 matches = {}
4414 matches = {}
4429 copies = {}
4415 copies = {}
4430 def grepbody(fn, rev, body):
4416 def grepbody(fn, rev, body):
4431 matches[rev].setdefault(fn, [])
4417 matches[rev].setdefault(fn, [])
4432 m = matches[rev][fn]
4418 m = matches[rev][fn]
4433 for lnum, cstart, cend, line in matchlines(body):
4419 for lnum, cstart, cend, line in matchlines(body):
4434 s = linestate(line, lnum, cstart, cend)
4420 s = linestate(line, lnum, cstart, cend)
4435 m.append(s)
4421 m.append(s)
4436
4422
4437 def difflinestates(a, b):
4423 def difflinestates(a, b):
4438 sm = difflib.SequenceMatcher(None, a, b)
4424 sm = difflib.SequenceMatcher(None, a, b)
4439 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4425 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4440 if tag == 'insert':
4426 if tag == 'insert':
4441 for i in xrange(blo, bhi):
4427 for i in xrange(blo, bhi):
4442 yield ('+', b[i])
4428 yield ('+', b[i])
4443 elif tag == 'delete':
4429 elif tag == 'delete':
4444 for i in xrange(alo, ahi):
4430 for i in xrange(alo, ahi):
4445 yield ('-', a[i])
4431 yield ('-', a[i])
4446 elif tag == 'replace':
4432 elif tag == 'replace':
4447 for i in xrange(alo, ahi):
4433 for i in xrange(alo, ahi):
4448 yield ('-', a[i])
4434 yield ('-', a[i])
4449 for i in xrange(blo, bhi):
4435 for i in xrange(blo, bhi):
4450 yield ('+', b[i])
4436 yield ('+', b[i])
4451
4437
4452 def display(fm, fn, ctx, pstates, states):
4438 def display(fm, fn, ctx, pstates, states):
4453 rev = ctx.rev()
4439 rev = ctx.rev()
4454 if fm.isplain():
4440 if fm.isplain():
4455 formatuser = ui.shortuser
4441 formatuser = ui.shortuser
4456 else:
4442 else:
4457 formatuser = str
4443 formatuser = str
4458 if ui.quiet:
4444 if ui.quiet:
4459 datefmt = '%Y-%m-%d'
4445 datefmt = '%Y-%m-%d'
4460 else:
4446 else:
4461 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4447 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4462 found = False
4448 found = False
4463 @util.cachefunc
4449 @util.cachefunc
4464 def binary():
4450 def binary():
4465 flog = getfile(fn)
4451 flog = getfile(fn)
4466 return util.binary(flog.read(ctx.filenode(fn)))
4452 return util.binary(flog.read(ctx.filenode(fn)))
4467
4453
4468 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4454 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4469 if opts.get('all'):
4455 if opts.get('all'):
4470 iter = difflinestates(pstates, states)
4456 iter = difflinestates(pstates, states)
4471 else:
4457 else:
4472 iter = [('', l) for l in states]
4458 iter = [('', l) for l in states]
4473 for change, l in iter:
4459 for change, l in iter:
4474 fm.startitem()
4460 fm.startitem()
4475 fm.data(node=fm.hexfunc(ctx.node()))
4461 fm.data(node=fm.hexfunc(ctx.node()))
4476 cols = [
4462 cols = [
4477 ('filename', fn, True),
4463 ('filename', fn, True),
4478 ('rev', rev, True),
4464 ('rev', rev, True),
4479 ('linenumber', l.linenum, opts.get('line_number')),
4465 ('linenumber', l.linenum, opts.get('line_number')),
4480 ]
4466 ]
4481 if opts.get('all'):
4467 if opts.get('all'):
4482 cols.append(('change', change, True))
4468 cols.append(('change', change, True))
4483 cols.extend([
4469 cols.extend([
4484 ('user', formatuser(ctx.user()), opts.get('user')),
4470 ('user', formatuser(ctx.user()), opts.get('user')),
4485 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4471 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4486 ])
4472 ])
4487 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4473 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4488 for name, data, cond in cols:
4474 for name, data, cond in cols:
4489 field = fieldnamemap.get(name, name)
4475 field = fieldnamemap.get(name, name)
4490 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4476 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4491 if cond and name != lastcol:
4477 if cond and name != lastcol:
4492 fm.plain(sep, label='grep.sep')
4478 fm.plain(sep, label='grep.sep')
4493 if not opts.get('files_with_matches'):
4479 if not opts.get('files_with_matches'):
4494 fm.plain(sep, label='grep.sep')
4480 fm.plain(sep, label='grep.sep')
4495 if not opts.get('text') and binary():
4481 if not opts.get('text') and binary():
4496 fm.plain(_(" Binary file matches"))
4482 fm.plain(_(" Binary file matches"))
4497 else:
4483 else:
4498 displaymatches(fm.nested('texts'), l)
4484 displaymatches(fm.nested('texts'), l)
4499 fm.plain(eol)
4485 fm.plain(eol)
4500 found = True
4486 found = True
4501 if opts.get('files_with_matches'):
4487 if opts.get('files_with_matches'):
4502 break
4488 break
4503 return found
4489 return found
4504
4490
4505 def displaymatches(fm, l):
4491 def displaymatches(fm, l):
4506 p = 0
4492 p = 0
4507 for s, e in l.findpos():
4493 for s, e in l.findpos():
4508 if p < s:
4494 if p < s:
4509 fm.startitem()
4495 fm.startitem()
4510 fm.write('text', '%s', l.line[p:s])
4496 fm.write('text', '%s', l.line[p:s])
4511 fm.data(matched=False)
4497 fm.data(matched=False)
4512 fm.startitem()
4498 fm.startitem()
4513 fm.write('text', '%s', l.line[s:e], label='grep.match')
4499 fm.write('text', '%s', l.line[s:e], label='grep.match')
4514 fm.data(matched=True)
4500 fm.data(matched=True)
4515 p = e
4501 p = e
4516 if p < len(l.line):
4502 if p < len(l.line):
4517 fm.startitem()
4503 fm.startitem()
4518 fm.write('text', '%s', l.line[p:])
4504 fm.write('text', '%s', l.line[p:])
4519 fm.data(matched=False)
4505 fm.data(matched=False)
4520 fm.end()
4506 fm.end()
4521
4507
4522 skip = {}
4508 skip = {}
4523 revfiles = {}
4509 revfiles = {}
4524 matchfn = scmutil.match(repo[None], pats, opts)
4510 matchfn = scmutil.match(repo[None], pats, opts)
4525 found = False
4511 found = False
4526 follow = opts.get('follow')
4512 follow = opts.get('follow')
4527
4513
4528 def prep(ctx, fns):
4514 def prep(ctx, fns):
4529 rev = ctx.rev()
4515 rev = ctx.rev()
4530 pctx = ctx.p1()
4516 pctx = ctx.p1()
4531 parent = pctx.rev()
4517 parent = pctx.rev()
4532 matches.setdefault(rev, {})
4518 matches.setdefault(rev, {})
4533 matches.setdefault(parent, {})
4519 matches.setdefault(parent, {})
4534 files = revfiles.setdefault(rev, [])
4520 files = revfiles.setdefault(rev, [])
4535 for fn in fns:
4521 for fn in fns:
4536 flog = getfile(fn)
4522 flog = getfile(fn)
4537 try:
4523 try:
4538 fnode = ctx.filenode(fn)
4524 fnode = ctx.filenode(fn)
4539 except error.LookupError:
4525 except error.LookupError:
4540 continue
4526 continue
4541
4527
4542 copied = flog.renamed(fnode)
4528 copied = flog.renamed(fnode)
4543 copy = follow and copied and copied[0]
4529 copy = follow and copied and copied[0]
4544 if copy:
4530 if copy:
4545 copies.setdefault(rev, {})[fn] = copy
4531 copies.setdefault(rev, {})[fn] = copy
4546 if fn in skip:
4532 if fn in skip:
4547 if copy:
4533 if copy:
4548 skip[copy] = True
4534 skip[copy] = True
4549 continue
4535 continue
4550 files.append(fn)
4536 files.append(fn)
4551
4537
4552 if fn not in matches[rev]:
4538 if fn not in matches[rev]:
4553 grepbody(fn, rev, flog.read(fnode))
4539 grepbody(fn, rev, flog.read(fnode))
4554
4540
4555 pfn = copy or fn
4541 pfn = copy or fn
4556 if pfn not in matches[parent]:
4542 if pfn not in matches[parent]:
4557 try:
4543 try:
4558 fnode = pctx.filenode(pfn)
4544 fnode = pctx.filenode(pfn)
4559 grepbody(pfn, parent, flog.read(fnode))
4545 grepbody(pfn, parent, flog.read(fnode))
4560 except error.LookupError:
4546 except error.LookupError:
4561 pass
4547 pass
4562
4548
4563 fm = ui.formatter('grep', opts)
4549 fm = ui.formatter('grep', opts)
4564 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4550 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4565 rev = ctx.rev()
4551 rev = ctx.rev()
4566 parent = ctx.p1().rev()
4552 parent = ctx.p1().rev()
4567 for fn in sorted(revfiles.get(rev, [])):
4553 for fn in sorted(revfiles.get(rev, [])):
4568 states = matches[rev][fn]
4554 states = matches[rev][fn]
4569 copy = copies.get(rev, {}).get(fn)
4555 copy = copies.get(rev, {}).get(fn)
4570 if fn in skip:
4556 if fn in skip:
4571 if copy:
4557 if copy:
4572 skip[copy] = True
4558 skip[copy] = True
4573 continue
4559 continue
4574 pstates = matches.get(parent, {}).get(copy or fn, [])
4560 pstates = matches.get(parent, {}).get(copy or fn, [])
4575 if pstates or states:
4561 if pstates or states:
4576 r = display(fm, fn, ctx, pstates, states)
4562 r = display(fm, fn, ctx, pstates, states)
4577 found = found or r
4563 found = found or r
4578 if r and not opts.get('all'):
4564 if r and not opts.get('all'):
4579 skip[fn] = True
4565 skip[fn] = True
4580 if copy:
4566 if copy:
4581 skip[copy] = True
4567 skip[copy] = True
4582 del matches[rev]
4568 del matches[rev]
4583 del revfiles[rev]
4569 del revfiles[rev]
4584 fm.end()
4570 fm.end()
4585
4571
4586 return not found
4572 return not found
4587
4573
4588 @command('heads',
4574 @command('heads',
4589 [('r', 'rev', '',
4575 [('r', 'rev', '',
4590 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4576 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4591 ('t', 'topo', False, _('show topological heads only')),
4577 ('t', 'topo', False, _('show topological heads only')),
4592 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4578 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4593 ('c', 'closed', False, _('show normal and closed branch heads')),
4579 ('c', 'closed', False, _('show normal and closed branch heads')),
4594 ] + templateopts,
4580 ] + templateopts,
4595 _('[-ct] [-r STARTREV] [REV]...'))
4581 _('[-ct] [-r STARTREV] [REV]...'))
4596 def heads(ui, repo, *branchrevs, **opts):
4582 def heads(ui, repo, *branchrevs, **opts):
4597 """show branch heads
4583 """show branch heads
4598
4584
4599 With no arguments, show all open branch heads in the repository.
4585 With no arguments, show all open branch heads in the repository.
4600 Branch heads are changesets that have no descendants on the
4586 Branch heads are changesets that have no descendants on the
4601 same branch. They are where development generally takes place and
4587 same branch. They are where development generally takes place and
4602 are the usual targets for update and merge operations.
4588 are the usual targets for update and merge operations.
4603
4589
4604 If one or more REVs are given, only open branch heads on the
4590 If one or more REVs are given, only open branch heads on the
4605 branches associated with the specified changesets are shown. This
4591 branches associated with the specified changesets are shown. This
4606 means that you can use :hg:`heads .` to see the heads on the
4592 means that you can use :hg:`heads .` to see the heads on the
4607 currently checked-out branch.
4593 currently checked-out branch.
4608
4594
4609 If -c/--closed is specified, also show branch heads marked closed
4595 If -c/--closed is specified, also show branch heads marked closed
4610 (see :hg:`commit --close-branch`).
4596 (see :hg:`commit --close-branch`).
4611
4597
4612 If STARTREV is specified, only those heads that are descendants of
4598 If STARTREV is specified, only those heads that are descendants of
4613 STARTREV will be displayed.
4599 STARTREV will be displayed.
4614
4600
4615 If -t/--topo is specified, named branch mechanics will be ignored and only
4601 If -t/--topo is specified, named branch mechanics will be ignored and only
4616 topological heads (changesets with no children) will be shown.
4602 topological heads (changesets with no children) will be shown.
4617
4603
4618 Returns 0 if matching heads are found, 1 if not.
4604 Returns 0 if matching heads are found, 1 if not.
4619 """
4605 """
4620
4606
4621 start = None
4607 start = None
4622 if 'rev' in opts:
4608 if 'rev' in opts:
4623 start = scmutil.revsingle(repo, opts['rev'], None).node()
4609 start = scmutil.revsingle(repo, opts['rev'], None).node()
4624
4610
4625 if opts.get('topo'):
4611 if opts.get('topo'):
4626 heads = [repo[h] for h in repo.heads(start)]
4612 heads = [repo[h] for h in repo.heads(start)]
4627 else:
4613 else:
4628 heads = []
4614 heads = []
4629 for branch in repo.branchmap():
4615 for branch in repo.branchmap():
4630 heads += repo.branchheads(branch, start, opts.get('closed'))
4616 heads += repo.branchheads(branch, start, opts.get('closed'))
4631 heads = [repo[h] for h in heads]
4617 heads = [repo[h] for h in heads]
4632
4618
4633 if branchrevs:
4619 if branchrevs:
4634 branches = set(repo[br].branch() for br in branchrevs)
4620 branches = set(repo[br].branch() for br in branchrevs)
4635 heads = [h for h in heads if h.branch() in branches]
4621 heads = [h for h in heads if h.branch() in branches]
4636
4622
4637 if opts.get('active') and branchrevs:
4623 if opts.get('active') and branchrevs:
4638 dagheads = repo.heads(start)
4624 dagheads = repo.heads(start)
4639 heads = [h for h in heads if h.node() in dagheads]
4625 heads = [h for h in heads if h.node() in dagheads]
4640
4626
4641 if branchrevs:
4627 if branchrevs:
4642 haveheads = set(h.branch() for h in heads)
4628 haveheads = set(h.branch() for h in heads)
4643 if branches - haveheads:
4629 if branches - haveheads:
4644 headless = ', '.join(b for b in branches - haveheads)
4630 headless = ', '.join(b for b in branches - haveheads)
4645 msg = _('no open branch heads found on branches %s')
4631 msg = _('no open branch heads found on branches %s')
4646 if opts.get('rev'):
4632 if opts.get('rev'):
4647 msg += _(' (started at %s)') % opts['rev']
4633 msg += _(' (started at %s)') % opts['rev']
4648 ui.warn((msg + '\n') % headless)
4634 ui.warn((msg + '\n') % headless)
4649
4635
4650 if not heads:
4636 if not heads:
4651 return 1
4637 return 1
4652
4638
4653 heads = sorted(heads, key=lambda x: -x.rev())
4639 heads = sorted(heads, key=lambda x: -x.rev())
4654 displayer = cmdutil.show_changeset(ui, repo, opts)
4640 displayer = cmdutil.show_changeset(ui, repo, opts)
4655 for ctx in heads:
4641 for ctx in heads:
4656 displayer.show(ctx)
4642 displayer.show(ctx)
4657 displayer.close()
4643 displayer.close()
4658
4644
4659 @command('help',
4645 @command('help',
4660 [('e', 'extension', None, _('show only help for extensions')),
4646 [('e', 'extension', None, _('show only help for extensions')),
4661 ('c', 'command', None, _('show only help for commands')),
4647 ('c', 'command', None, _('show only help for commands')),
4662 ('k', 'keyword', None, _('show topics matching keyword')),
4648 ('k', 'keyword', None, _('show topics matching keyword')),
4663 ('s', 'system', [], _('show help for specific platform(s)')),
4649 ('s', 'system', [], _('show help for specific platform(s)')),
4664 ],
4650 ],
4665 _('[-ecks] [TOPIC]'),
4651 _('[-ecks] [TOPIC]'),
4666 norepo=True)
4652 norepo=True)
4667 def help_(ui, name=None, **opts):
4653 def help_(ui, name=None, **opts):
4668 """show help for a given topic or a help overview
4654 """show help for a given topic or a help overview
4669
4655
4670 With no arguments, print a list of commands with short help messages.
4656 With no arguments, print a list of commands with short help messages.
4671
4657
4672 Given a topic, extension, or command name, print help for that
4658 Given a topic, extension, or command name, print help for that
4673 topic.
4659 topic.
4674
4660
4675 Returns 0 if successful.
4661 Returns 0 if successful.
4676 """
4662 """
4677
4663
4678 textwidth = ui.configint('ui', 'textwidth', 78)
4664 textwidth = ui.configint('ui', 'textwidth', 78)
4679 termwidth = ui.termwidth() - 2
4665 termwidth = ui.termwidth() - 2
4680 if textwidth <= 0 or termwidth < textwidth:
4666 if textwidth <= 0 or termwidth < textwidth:
4681 textwidth = termwidth
4667 textwidth = termwidth
4682
4668
4683 keep = opts.get('system') or []
4669 keep = opts.get('system') or []
4684 if len(keep) == 0:
4670 if len(keep) == 0:
4685 if sys.platform.startswith('win'):
4671 if sys.platform.startswith('win'):
4686 keep.append('windows')
4672 keep.append('windows')
4687 elif sys.platform == 'OpenVMS':
4673 elif sys.platform == 'OpenVMS':
4688 keep.append('vms')
4674 keep.append('vms')
4689 elif sys.platform == 'plan9':
4675 elif sys.platform == 'plan9':
4690 keep.append('plan9')
4676 keep.append('plan9')
4691 else:
4677 else:
4692 keep.append('unix')
4678 keep.append('unix')
4693 keep.append(sys.platform.lower())
4679 keep.append(sys.platform.lower())
4694 if ui.verbose:
4680 if ui.verbose:
4695 keep.append('verbose')
4681 keep.append('verbose')
4696
4682
4697 section = None
4683 section = None
4698 subtopic = None
4684 subtopic = None
4699 if name and '.' in name:
4685 if name and '.' in name:
4700 name, remaining = name.split('.', 1)
4686 name, remaining = name.split('.', 1)
4701 remaining = encoding.lower(remaining)
4687 remaining = encoding.lower(remaining)
4702 if '.' in remaining:
4688 if '.' in remaining:
4703 subtopic, section = remaining.split('.', 1)
4689 subtopic, section = remaining.split('.', 1)
4704 else:
4690 else:
4705 if name in help.subtopics:
4691 if name in help.subtopics:
4706 subtopic = remaining
4692 subtopic = remaining
4707 else:
4693 else:
4708 section = remaining
4694 section = remaining
4709
4695
4710 text = help.help_(ui, name, subtopic=subtopic, **opts)
4696 text = help.help_(ui, name, subtopic=subtopic, **opts)
4711
4697
4712 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4698 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4713 section=section)
4699 section=section)
4714
4700
4715 # We could have been given a weird ".foo" section without a name
4701 # We could have been given a weird ".foo" section without a name
4716 # to look for, or we could have simply failed to found "foo.bar"
4702 # to look for, or we could have simply failed to found "foo.bar"
4717 # because bar isn't a section of foo
4703 # because bar isn't a section of foo
4718 if section and not (formatted and name):
4704 if section and not (formatted and name):
4719 raise error.Abort(_("help section not found"))
4705 raise error.Abort(_("help section not found"))
4720
4706
4721 if 'verbose' in pruned:
4707 if 'verbose' in pruned:
4722 keep.append('omitted')
4708 keep.append('omitted')
4723 else:
4709 else:
4724 keep.append('notomitted')
4710 keep.append('notomitted')
4725 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4711 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4726 section=section)
4712 section=section)
4727 ui.write(formatted)
4713 ui.write(formatted)
4728
4714
4729
4715
4730 @command('identify|id',
4716 @command('identify|id',
4731 [('r', 'rev', '',
4717 [('r', 'rev', '',
4732 _('identify the specified revision'), _('REV')),
4718 _('identify the specified revision'), _('REV')),
4733 ('n', 'num', None, _('show local revision number')),
4719 ('n', 'num', None, _('show local revision number')),
4734 ('i', 'id', None, _('show global revision id')),
4720 ('i', 'id', None, _('show global revision id')),
4735 ('b', 'branch', None, _('show branch')),
4721 ('b', 'branch', None, _('show branch')),
4736 ('t', 'tags', None, _('show tags')),
4722 ('t', 'tags', None, _('show tags')),
4737 ('B', 'bookmarks', None, _('show bookmarks')),
4723 ('B', 'bookmarks', None, _('show bookmarks')),
4738 ] + remoteopts,
4724 ] + remoteopts,
4739 _('[-nibtB] [-r REV] [SOURCE]'),
4725 _('[-nibtB] [-r REV] [SOURCE]'),
4740 optionalrepo=True)
4726 optionalrepo=True)
4741 def identify(ui, repo, source=None, rev=None,
4727 def identify(ui, repo, source=None, rev=None,
4742 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4728 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4743 """identify the working directory or specified revision
4729 """identify the working directory or specified revision
4744
4730
4745 Print a summary identifying the repository state at REV using one or
4731 Print a summary identifying the repository state at REV using one or
4746 two parent hash identifiers, followed by a "+" if the working
4732 two parent hash identifiers, followed by a "+" if the working
4747 directory has uncommitted changes, the branch name (if not default),
4733 directory has uncommitted changes, the branch name (if not default),
4748 a list of tags, and a list of bookmarks.
4734 a list of tags, and a list of bookmarks.
4749
4735
4750 When REV is not given, print a summary of the current state of the
4736 When REV is not given, print a summary of the current state of the
4751 repository.
4737 repository.
4752
4738
4753 Specifying a path to a repository root or Mercurial bundle will
4739 Specifying a path to a repository root or Mercurial bundle will
4754 cause lookup to operate on that repository/bundle.
4740 cause lookup to operate on that repository/bundle.
4755
4741
4756 .. container:: verbose
4742 .. container:: verbose
4757
4743
4758 Examples:
4744 Examples:
4759
4745
4760 - generate a build identifier for the working directory::
4746 - generate a build identifier for the working directory::
4761
4747
4762 hg id --id > build-id.dat
4748 hg id --id > build-id.dat
4763
4749
4764 - find the revision corresponding to a tag::
4750 - find the revision corresponding to a tag::
4765
4751
4766 hg id -n -r 1.3
4752 hg id -n -r 1.3
4767
4753
4768 - check the most recent revision of a remote repository::
4754 - check the most recent revision of a remote repository::
4769
4755
4770 hg id -r tip http://selenic.com/hg/
4756 hg id -r tip http://selenic.com/hg/
4771
4757
4772 See :hg:`log` for generating more information about specific revisions,
4758 See :hg:`log` for generating more information about specific revisions,
4773 including full hash identifiers.
4759 including full hash identifiers.
4774
4760
4775 Returns 0 if successful.
4761 Returns 0 if successful.
4776 """
4762 """
4777
4763
4778 if not repo and not source:
4764 if not repo and not source:
4779 raise error.Abort(_("there is no Mercurial repository here "
4765 raise error.Abort(_("there is no Mercurial repository here "
4780 "(.hg not found)"))
4766 "(.hg not found)"))
4781
4767
4782 if ui.debugflag:
4768 if ui.debugflag:
4783 hexfunc = hex
4769 hexfunc = hex
4784 else:
4770 else:
4785 hexfunc = short
4771 hexfunc = short
4786 default = not (num or id or branch or tags or bookmarks)
4772 default = not (num or id or branch or tags or bookmarks)
4787 output = []
4773 output = []
4788 revs = []
4774 revs = []
4789
4775
4790 if source:
4776 if source:
4791 source, branches = hg.parseurl(ui.expandpath(source))
4777 source, branches = hg.parseurl(ui.expandpath(source))
4792 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4778 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4793 repo = peer.local()
4779 repo = peer.local()
4794 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4780 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4795
4781
4796 if not repo:
4782 if not repo:
4797 if num or branch or tags:
4783 if num or branch or tags:
4798 raise error.Abort(
4784 raise error.Abort(
4799 _("can't query remote revision number, branch, or tags"))
4785 _("can't query remote revision number, branch, or tags"))
4800 if not rev and revs:
4786 if not rev and revs:
4801 rev = revs[0]
4787 rev = revs[0]
4802 if not rev:
4788 if not rev:
4803 rev = "tip"
4789 rev = "tip"
4804
4790
4805 remoterev = peer.lookup(rev)
4791 remoterev = peer.lookup(rev)
4806 if default or id:
4792 if default or id:
4807 output = [hexfunc(remoterev)]
4793 output = [hexfunc(remoterev)]
4808
4794
4809 def getbms():
4795 def getbms():
4810 bms = []
4796 bms = []
4811
4797
4812 if 'bookmarks' in peer.listkeys('namespaces'):
4798 if 'bookmarks' in peer.listkeys('namespaces'):
4813 hexremoterev = hex(remoterev)
4799 hexremoterev = hex(remoterev)
4814 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4800 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4815 if bmr == hexremoterev]
4801 if bmr == hexremoterev]
4816
4802
4817 return sorted(bms)
4803 return sorted(bms)
4818
4804
4819 if bookmarks:
4805 if bookmarks:
4820 output.extend(getbms())
4806 output.extend(getbms())
4821 elif default and not ui.quiet:
4807 elif default and not ui.quiet:
4822 # multiple bookmarks for a single parent separated by '/'
4808 # multiple bookmarks for a single parent separated by '/'
4823 bm = '/'.join(getbms())
4809 bm = '/'.join(getbms())
4824 if bm:
4810 if bm:
4825 output.append(bm)
4811 output.append(bm)
4826 else:
4812 else:
4827 ctx = scmutil.revsingle(repo, rev, None)
4813 ctx = scmutil.revsingle(repo, rev, None)
4828
4814
4829 if ctx.rev() is None:
4815 if ctx.rev() is None:
4830 ctx = repo[None]
4816 ctx = repo[None]
4831 parents = ctx.parents()
4817 parents = ctx.parents()
4832 taglist = []
4818 taglist = []
4833 for p in parents:
4819 for p in parents:
4834 taglist.extend(p.tags())
4820 taglist.extend(p.tags())
4835
4821
4836 changed = ""
4822 changed = ""
4837 if default or id or num:
4823 if default or id or num:
4838 if (any(repo.status())
4824 if (any(repo.status())
4839 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4825 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4840 changed = '+'
4826 changed = '+'
4841 if default or id:
4827 if default or id:
4842 output = ["%s%s" %
4828 output = ["%s%s" %
4843 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4829 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4844 if num:
4830 if num:
4845 output.append("%s%s" %
4831 output.append("%s%s" %
4846 ('+'.join([str(p.rev()) for p in parents]), changed))
4832 ('+'.join([str(p.rev()) for p in parents]), changed))
4847 else:
4833 else:
4848 if default or id:
4834 if default or id:
4849 output = [hexfunc(ctx.node())]
4835 output = [hexfunc(ctx.node())]
4850 if num:
4836 if num:
4851 output.append(str(ctx.rev()))
4837 output.append(str(ctx.rev()))
4852 taglist = ctx.tags()
4838 taglist = ctx.tags()
4853
4839
4854 if default and not ui.quiet:
4840 if default and not ui.quiet:
4855 b = ctx.branch()
4841 b = ctx.branch()
4856 if b != 'default':
4842 if b != 'default':
4857 output.append("(%s)" % b)
4843 output.append("(%s)" % b)
4858
4844
4859 # multiple tags for a single parent separated by '/'
4845 # multiple tags for a single parent separated by '/'
4860 t = '/'.join(taglist)
4846 t = '/'.join(taglist)
4861 if t:
4847 if t:
4862 output.append(t)
4848 output.append(t)
4863
4849
4864 # multiple bookmarks for a single parent separated by '/'
4850 # multiple bookmarks for a single parent separated by '/'
4865 bm = '/'.join(ctx.bookmarks())
4851 bm = '/'.join(ctx.bookmarks())
4866 if bm:
4852 if bm:
4867 output.append(bm)
4853 output.append(bm)
4868 else:
4854 else:
4869 if branch:
4855 if branch:
4870 output.append(ctx.branch())
4856 output.append(ctx.branch())
4871
4857
4872 if tags:
4858 if tags:
4873 output.extend(taglist)
4859 output.extend(taglist)
4874
4860
4875 if bookmarks:
4861 if bookmarks:
4876 output.extend(ctx.bookmarks())
4862 output.extend(ctx.bookmarks())
4877
4863
4878 ui.write("%s\n" % ' '.join(output))
4864 ui.write("%s\n" % ' '.join(output))
4879
4865
4880 @command('import|patch',
4866 @command('import|patch',
4881 [('p', 'strip', 1,
4867 [('p', 'strip', 1,
4882 _('directory strip option for patch. This has the same '
4868 _('directory strip option for patch. This has the same '
4883 'meaning as the corresponding patch option'), _('NUM')),
4869 'meaning as the corresponding patch option'), _('NUM')),
4884 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4870 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4885 ('e', 'edit', False, _('invoke editor on commit messages')),
4871 ('e', 'edit', False, _('invoke editor on commit messages')),
4886 ('f', 'force', None,
4872 ('f', 'force', None,
4887 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4873 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4888 ('', 'no-commit', None,
4874 ('', 'no-commit', None,
4889 _("don't commit, just update the working directory")),
4875 _("don't commit, just update the working directory")),
4890 ('', 'bypass', None,
4876 ('', 'bypass', None,
4891 _("apply patch without touching the working directory")),
4877 _("apply patch without touching the working directory")),
4892 ('', 'partial', None,
4878 ('', 'partial', None,
4893 _('commit even if some hunks fail')),
4879 _('commit even if some hunks fail')),
4894 ('', 'exact', None,
4880 ('', 'exact', None,
4895 _('abort if patch would apply lossily')),
4881 _('abort if patch would apply lossily')),
4896 ('', 'prefix', '',
4882 ('', 'prefix', '',
4897 _('apply patch to subdirectory'), _('DIR')),
4883 _('apply patch to subdirectory'), _('DIR')),
4898 ('', 'import-branch', None,
4884 ('', 'import-branch', None,
4899 _('use any branch information in patch (implied by --exact)'))] +
4885 _('use any branch information in patch (implied by --exact)'))] +
4900 commitopts + commitopts2 + similarityopts,
4886 commitopts + commitopts2 + similarityopts,
4901 _('[OPTION]... PATCH...'))
4887 _('[OPTION]... PATCH...'))
4902 def import_(ui, repo, patch1=None, *patches, **opts):
4888 def import_(ui, repo, patch1=None, *patches, **opts):
4903 """import an ordered set of patches
4889 """import an ordered set of patches
4904
4890
4905 Import a list of patches and commit them individually (unless
4891 Import a list of patches and commit them individually (unless
4906 --no-commit is specified).
4892 --no-commit is specified).
4907
4893
4908 To read a patch from standard input, use "-" as the patch name. If
4894 To read a patch from standard input, use "-" as the patch name. If
4909 a URL is specified, the patch will be downloaded from there.
4895 a URL is specified, the patch will be downloaded from there.
4910
4896
4911 Import first applies changes to the working directory (unless
4897 Import first applies changes to the working directory (unless
4912 --bypass is specified), import will abort if there are outstanding
4898 --bypass is specified), import will abort if there are outstanding
4913 changes.
4899 changes.
4914
4900
4915 Use --bypass to apply and commit patches directly to the
4901 Use --bypass to apply and commit patches directly to the
4916 repository, without affecting the working directory. Without
4902 repository, without affecting the working directory. Without
4917 --exact, patches will be applied on top of the working directory
4903 --exact, patches will be applied on top of the working directory
4918 parent revision.
4904 parent revision.
4919
4905
4920 You can import a patch straight from a mail message. Even patches
4906 You can import a patch straight from a mail message. Even patches
4921 as attachments work (to use the body part, it must have type
4907 as attachments work (to use the body part, it must have type
4922 text/plain or text/x-patch). From and Subject headers of email
4908 text/plain or text/x-patch). From and Subject headers of email
4923 message are used as default committer and commit message. All
4909 message are used as default committer and commit message. All
4924 text/plain body parts before first diff are added to the commit
4910 text/plain body parts before first diff are added to the commit
4925 message.
4911 message.
4926
4912
4927 If the imported patch was generated by :hg:`export`, user and
4913 If the imported patch was generated by :hg:`export`, user and
4928 description from patch override values from message headers and
4914 description from patch override values from message headers and
4929 body. Values given on command line with -m/--message and -u/--user
4915 body. Values given on command line with -m/--message and -u/--user
4930 override these.
4916 override these.
4931
4917
4932 If --exact is specified, import will set the working directory to
4918 If --exact is specified, import will set the working directory to
4933 the parent of each patch before applying it, and will abort if the
4919 the parent of each patch before applying it, and will abort if the
4934 resulting changeset has a different ID than the one recorded in
4920 resulting changeset has a different ID than the one recorded in
4935 the patch. This will guard against various ways that portable
4921 the patch. This will guard against various ways that portable
4936 patch formats and mail systems might fail to transfer Mercurial
4922 patch formats and mail systems might fail to transfer Mercurial
4937 data or metadata. See :hg:`bundle` for lossless transmission.
4923 data or metadata. See :hg:`bundle` for lossless transmission.
4938
4924
4939 Use --partial to ensure a changeset will be created from the patch
4925 Use --partial to ensure a changeset will be created from the patch
4940 even if some hunks fail to apply. Hunks that fail to apply will be
4926 even if some hunks fail to apply. Hunks that fail to apply will be
4941 written to a <target-file>.rej file. Conflicts can then be resolved
4927 written to a <target-file>.rej file. Conflicts can then be resolved
4942 by hand before :hg:`commit --amend` is run to update the created
4928 by hand before :hg:`commit --amend` is run to update the created
4943 changeset. This flag exists to let people import patches that
4929 changeset. This flag exists to let people import patches that
4944 partially apply without losing the associated metadata (author,
4930 partially apply without losing the associated metadata (author,
4945 date, description, ...).
4931 date, description, ...).
4946
4932
4947 .. note::
4933 .. note::
4948
4934
4949 When no hunks apply cleanly, :hg:`import --partial` will create
4935 When no hunks apply cleanly, :hg:`import --partial` will create
4950 an empty changeset, importing only the patch metadata.
4936 an empty changeset, importing only the patch metadata.
4951
4937
4952 With -s/--similarity, hg will attempt to discover renames and
4938 With -s/--similarity, hg will attempt to discover renames and
4953 copies in the patch in the same way as :hg:`addremove`.
4939 copies in the patch in the same way as :hg:`addremove`.
4954
4940
4955 It is possible to use external patch programs to perform the patch
4941 It is possible to use external patch programs to perform the patch
4956 by setting the ``ui.patch`` configuration option. For the default
4942 by setting the ``ui.patch`` configuration option. For the default
4957 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4943 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4958 See :hg:`help config` for more information about configuration
4944 See :hg:`help config` for more information about configuration
4959 files and how to use these options.
4945 files and how to use these options.
4960
4946
4961 See :hg:`help dates` for a list of formats valid for -d/--date.
4947 See :hg:`help dates` for a list of formats valid for -d/--date.
4962
4948
4963 .. container:: verbose
4949 .. container:: verbose
4964
4950
4965 Examples:
4951 Examples:
4966
4952
4967 - import a traditional patch from a website and detect renames::
4953 - import a traditional patch from a website and detect renames::
4968
4954
4969 hg import -s 80 http://example.com/bugfix.patch
4955 hg import -s 80 http://example.com/bugfix.patch
4970
4956
4971 - import a changeset from an hgweb server::
4957 - import a changeset from an hgweb server::
4972
4958
4973 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4959 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4974
4960
4975 - import all the patches in an Unix-style mbox::
4961 - import all the patches in an Unix-style mbox::
4976
4962
4977 hg import incoming-patches.mbox
4963 hg import incoming-patches.mbox
4978
4964
4979 - attempt to exactly restore an exported changeset (not always
4965 - attempt to exactly restore an exported changeset (not always
4980 possible)::
4966 possible)::
4981
4967
4982 hg import --exact proposed-fix.patch
4968 hg import --exact proposed-fix.patch
4983
4969
4984 - use an external tool to apply a patch which is too fuzzy for
4970 - use an external tool to apply a patch which is too fuzzy for
4985 the default internal tool.
4971 the default internal tool.
4986
4972
4987 hg import --config ui.patch="patch --merge" fuzzy.patch
4973 hg import --config ui.patch="patch --merge" fuzzy.patch
4988
4974
4989 - change the default fuzzing from 2 to a less strict 7
4975 - change the default fuzzing from 2 to a less strict 7
4990
4976
4991 hg import --config ui.fuzz=7 fuzz.patch
4977 hg import --config ui.fuzz=7 fuzz.patch
4992
4978
4993 Returns 0 on success, 1 on partial success (see --partial).
4979 Returns 0 on success, 1 on partial success (see --partial).
4994 """
4980 """
4995
4981
4996 if not patch1:
4982 if not patch1:
4997 raise error.Abort(_('need at least one patch to import'))
4983 raise error.Abort(_('need at least one patch to import'))
4998
4984
4999 patches = (patch1,) + patches
4985 patches = (patch1,) + patches
5000
4986
5001 date = opts.get('date')
4987 date = opts.get('date')
5002 if date:
4988 if date:
5003 opts['date'] = util.parsedate(date)
4989 opts['date'] = util.parsedate(date)
5004
4990
5005 exact = opts.get('exact')
4991 exact = opts.get('exact')
5006 update = not opts.get('bypass')
4992 update = not opts.get('bypass')
5007 if not update and opts.get('no_commit'):
4993 if not update and opts.get('no_commit'):
5008 raise error.Abort(_('cannot use --no-commit with --bypass'))
4994 raise error.Abort(_('cannot use --no-commit with --bypass'))
5009 try:
4995 try:
5010 sim = float(opts.get('similarity') or 0)
4996 sim = float(opts.get('similarity') or 0)
5011 except ValueError:
4997 except ValueError:
5012 raise error.Abort(_('similarity must be a number'))
4998 raise error.Abort(_('similarity must be a number'))
5013 if sim < 0 or sim > 100:
4999 if sim < 0 or sim > 100:
5014 raise error.Abort(_('similarity must be between 0 and 100'))
5000 raise error.Abort(_('similarity must be between 0 and 100'))
5015 if sim and not update:
5001 if sim and not update:
5016 raise error.Abort(_('cannot use --similarity with --bypass'))
5002 raise error.Abort(_('cannot use --similarity with --bypass'))
5017 if exact:
5003 if exact:
5018 if opts.get('edit'):
5004 if opts.get('edit'):
5019 raise error.Abort(_('cannot use --exact with --edit'))
5005 raise error.Abort(_('cannot use --exact with --edit'))
5020 if opts.get('prefix'):
5006 if opts.get('prefix'):
5021 raise error.Abort(_('cannot use --exact with --prefix'))
5007 raise error.Abort(_('cannot use --exact with --prefix'))
5022
5008
5023 base = opts["base"]
5009 base = opts["base"]
5024 wlock = dsguard = lock = tr = None
5010 wlock = dsguard = lock = tr = None
5025 msgs = []
5011 msgs = []
5026 ret = 0
5012 ret = 0
5027
5013
5028
5014
5029 try:
5015 try:
5030 wlock = repo.wlock()
5016 wlock = repo.wlock()
5031
5017
5032 if update:
5018 if update:
5033 cmdutil.checkunfinished(repo)
5019 cmdutil.checkunfinished(repo)
5034 if (exact or not opts.get('force')):
5020 if (exact or not opts.get('force')):
5035 cmdutil.bailifchanged(repo)
5021 cmdutil.bailifchanged(repo)
5036
5022
5037 if not opts.get('no_commit'):
5023 if not opts.get('no_commit'):
5038 lock = repo.lock()
5024 lock = repo.lock()
5039 tr = repo.transaction('import')
5025 tr = repo.transaction('import')
5040 else:
5026 else:
5041 dsguard = cmdutil.dirstateguard(repo, 'import')
5027 dsguard = cmdutil.dirstateguard(repo, 'import')
5042 parents = repo[None].parents()
5028 parents = repo[None].parents()
5043 for patchurl in patches:
5029 for patchurl in patches:
5044 if patchurl == '-':
5030 if patchurl == '-':
5045 ui.status(_('applying patch from stdin\n'))
5031 ui.status(_('applying patch from stdin\n'))
5046 patchfile = ui.fin
5032 patchfile = ui.fin
5047 patchurl = 'stdin' # for error message
5033 patchurl = 'stdin' # for error message
5048 else:
5034 else:
5049 patchurl = os.path.join(base, patchurl)
5035 patchurl = os.path.join(base, patchurl)
5050 ui.status(_('applying %s\n') % patchurl)
5036 ui.status(_('applying %s\n') % patchurl)
5051 patchfile = hg.openpath(ui, patchurl)
5037 patchfile = hg.openpath(ui, patchurl)
5052
5038
5053 haspatch = False
5039 haspatch = False
5054 for hunk in patch.split(patchfile):
5040 for hunk in patch.split(patchfile):
5055 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
5041 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
5056 parents, opts,
5042 parents, opts,
5057 msgs, hg.clean)
5043 msgs, hg.clean)
5058 if msg:
5044 if msg:
5059 haspatch = True
5045 haspatch = True
5060 ui.note(msg + '\n')
5046 ui.note(msg + '\n')
5061 if update or exact:
5047 if update or exact:
5062 parents = repo[None].parents()
5048 parents = repo[None].parents()
5063 else:
5049 else:
5064 parents = [repo[node]]
5050 parents = [repo[node]]
5065 if rej:
5051 if rej:
5066 ui.write_err(_("patch applied partially\n"))
5052 ui.write_err(_("patch applied partially\n"))
5067 ui.write_err(_("(fix the .rej files and run "
5053 ui.write_err(_("(fix the .rej files and run "
5068 "`hg commit --amend`)\n"))
5054 "`hg commit --amend`)\n"))
5069 ret = 1
5055 ret = 1
5070 break
5056 break
5071
5057
5072 if not haspatch:
5058 if not haspatch:
5073 raise error.Abort(_('%s: no diffs found') % patchurl)
5059 raise error.Abort(_('%s: no diffs found') % patchurl)
5074
5060
5075 if tr:
5061 if tr:
5076 tr.close()
5062 tr.close()
5077 if msgs:
5063 if msgs:
5078 repo.savecommitmessage('\n* * *\n'.join(msgs))
5064 repo.savecommitmessage('\n* * *\n'.join(msgs))
5079 if dsguard:
5065 if dsguard:
5080 dsguard.close()
5066 dsguard.close()
5081 return ret
5067 return ret
5082 finally:
5068 finally:
5083 if tr:
5069 if tr:
5084 tr.release()
5070 tr.release()
5085 release(lock, dsguard, wlock)
5071 release(lock, dsguard, wlock)
5086
5072
5087 @command('incoming|in',
5073 @command('incoming|in',
5088 [('f', 'force', None,
5074 [('f', 'force', None,
5089 _('run even if remote repository is unrelated')),
5075 _('run even if remote repository is unrelated')),
5090 ('n', 'newest-first', None, _('show newest record first')),
5076 ('n', 'newest-first', None, _('show newest record first')),
5091 ('', 'bundle', '',
5077 ('', 'bundle', '',
5092 _('file to store the bundles into'), _('FILE')),
5078 _('file to store the bundles into'), _('FILE')),
5093 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5079 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5094 ('B', 'bookmarks', False, _("compare bookmarks")),
5080 ('B', 'bookmarks', False, _("compare bookmarks")),
5095 ('b', 'branch', [],
5081 ('b', 'branch', [],
5096 _('a specific branch you would like to pull'), _('BRANCH')),
5082 _('a specific branch you would like to pull'), _('BRANCH')),
5097 ] + logopts + remoteopts + subrepoopts,
5083 ] + logopts + remoteopts + subrepoopts,
5098 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
5084 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
5099 def incoming(ui, repo, source="default", **opts):
5085 def incoming(ui, repo, source="default", **opts):
5100 """show new changesets found in source
5086 """show new changesets found in source
5101
5087
5102 Show new changesets found in the specified path/URL or the default
5088 Show new changesets found in the specified path/URL or the default
5103 pull location. These are the changesets that would have been pulled
5089 pull location. These are the changesets that would have been pulled
5104 if a pull at the time you issued this command.
5090 if a pull at the time you issued this command.
5105
5091
5106 See pull for valid source format details.
5092 See pull for valid source format details.
5107
5093
5108 .. container:: verbose
5094 .. container:: verbose
5109
5095
5110 With -B/--bookmarks, the result of bookmark comparison between
5096 With -B/--bookmarks, the result of bookmark comparison between
5111 local and remote repositories is displayed. With -v/--verbose,
5097 local and remote repositories is displayed. With -v/--verbose,
5112 status is also displayed for each bookmark like below::
5098 status is also displayed for each bookmark like below::
5113
5099
5114 BM1 01234567890a added
5100 BM1 01234567890a added
5115 BM2 1234567890ab advanced
5101 BM2 1234567890ab advanced
5116 BM3 234567890abc diverged
5102 BM3 234567890abc diverged
5117 BM4 34567890abcd changed
5103 BM4 34567890abcd changed
5118
5104
5119 The action taken locally when pulling depends on the
5105 The action taken locally when pulling depends on the
5120 status of each bookmark:
5106 status of each bookmark:
5121
5107
5122 :``added``: pull will create it
5108 :``added``: pull will create it
5123 :``advanced``: pull will update it
5109 :``advanced``: pull will update it
5124 :``diverged``: pull will create a divergent bookmark
5110 :``diverged``: pull will create a divergent bookmark
5125 :``changed``: result depends on remote changesets
5111 :``changed``: result depends on remote changesets
5126
5112
5127 From the point of view of pulling behavior, bookmark
5113 From the point of view of pulling behavior, bookmark
5128 existing only in the remote repository are treated as ``added``,
5114 existing only in the remote repository are treated as ``added``,
5129 even if it is in fact locally deleted.
5115 even if it is in fact locally deleted.
5130
5116
5131 .. container:: verbose
5117 .. container:: verbose
5132
5118
5133 For remote repository, using --bundle avoids downloading the
5119 For remote repository, using --bundle avoids downloading the
5134 changesets twice if the incoming is followed by a pull.
5120 changesets twice if the incoming is followed by a pull.
5135
5121
5136 Examples:
5122 Examples:
5137
5123
5138 - show incoming changes with patches and full description::
5124 - show incoming changes with patches and full description::
5139
5125
5140 hg incoming -vp
5126 hg incoming -vp
5141
5127
5142 - show incoming changes excluding merges, store a bundle::
5128 - show incoming changes excluding merges, store a bundle::
5143
5129
5144 hg in -vpM --bundle incoming.hg
5130 hg in -vpM --bundle incoming.hg
5145 hg pull incoming.hg
5131 hg pull incoming.hg
5146
5132
5147 - briefly list changes inside a bundle::
5133 - briefly list changes inside a bundle::
5148
5134
5149 hg in changes.hg -T "{desc|firstline}\\n"
5135 hg in changes.hg -T "{desc|firstline}\\n"
5150
5136
5151 Returns 0 if there are incoming changes, 1 otherwise.
5137 Returns 0 if there are incoming changes, 1 otherwise.
5152 """
5138 """
5153 if opts.get('graph'):
5139 if opts.get('graph'):
5154 cmdutil.checkunsupportedgraphflags([], opts)
5140 cmdutil.checkunsupportedgraphflags([], opts)
5155 def display(other, chlist, displayer):
5141 def display(other, chlist, displayer):
5156 revdag = cmdutil.graphrevs(other, chlist, opts)
5142 revdag = cmdutil.graphrevs(other, chlist, opts)
5157 cmdutil.displaygraph(ui, repo, revdag, displayer,
5143 cmdutil.displaygraph(ui, repo, revdag, displayer,
5158 graphmod.asciiedges)
5144 graphmod.asciiedges)
5159
5145
5160 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5146 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5161 return 0
5147 return 0
5162
5148
5163 if opts.get('bundle') and opts.get('subrepos'):
5149 if opts.get('bundle') and opts.get('subrepos'):
5164 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5150 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5165
5151
5166 if opts.get('bookmarks'):
5152 if opts.get('bookmarks'):
5167 source, branches = hg.parseurl(ui.expandpath(source),
5153 source, branches = hg.parseurl(ui.expandpath(source),
5168 opts.get('branch'))
5154 opts.get('branch'))
5169 other = hg.peer(repo, opts, source)
5155 other = hg.peer(repo, opts, source)
5170 if 'bookmarks' not in other.listkeys('namespaces'):
5156 if 'bookmarks' not in other.listkeys('namespaces'):
5171 ui.warn(_("remote doesn't support bookmarks\n"))
5157 ui.warn(_("remote doesn't support bookmarks\n"))
5172 return 0
5158 return 0
5173 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5159 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5174 return bookmarks.incoming(ui, repo, other)
5160 return bookmarks.incoming(ui, repo, other)
5175
5161
5176 repo._subtoppath = ui.expandpath(source)
5162 repo._subtoppath = ui.expandpath(source)
5177 try:
5163 try:
5178 return hg.incoming(ui, repo, source, opts)
5164 return hg.incoming(ui, repo, source, opts)
5179 finally:
5165 finally:
5180 del repo._subtoppath
5166 del repo._subtoppath
5181
5167
5182
5168
5183 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5169 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5184 norepo=True)
5170 norepo=True)
5185 def init(ui, dest=".", **opts):
5171 def init(ui, dest=".", **opts):
5186 """create a new repository in the given directory
5172 """create a new repository in the given directory
5187
5173
5188 Initialize a new repository in the given directory. If the given
5174 Initialize a new repository in the given directory. If the given
5189 directory does not exist, it will be created.
5175 directory does not exist, it will be created.
5190
5176
5191 If no directory is given, the current directory is used.
5177 If no directory is given, the current directory is used.
5192
5178
5193 It is possible to specify an ``ssh://`` URL as the destination.
5179 It is possible to specify an ``ssh://`` URL as the destination.
5194 See :hg:`help urls` for more information.
5180 See :hg:`help urls` for more information.
5195
5181
5196 Returns 0 on success.
5182 Returns 0 on success.
5197 """
5183 """
5198 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5184 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5199
5185
5200 @command('locate',
5186 @command('locate',
5201 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5187 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5202 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5188 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5203 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5189 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5204 ] + walkopts,
5190 ] + walkopts,
5205 _('[OPTION]... [PATTERN]...'))
5191 _('[OPTION]... [PATTERN]...'))
5206 def locate(ui, repo, *pats, **opts):
5192 def locate(ui, repo, *pats, **opts):
5207 """locate files matching specific patterns (DEPRECATED)
5193 """locate files matching specific patterns (DEPRECATED)
5208
5194
5209 Print files under Mercurial control in the working directory whose
5195 Print files under Mercurial control in the working directory whose
5210 names match the given patterns.
5196 names match the given patterns.
5211
5197
5212 By default, this command searches all directories in the working
5198 By default, this command searches all directories in the working
5213 directory. To search just the current directory and its
5199 directory. To search just the current directory and its
5214 subdirectories, use "--include .".
5200 subdirectories, use "--include .".
5215
5201
5216 If no patterns are given to match, this command prints the names
5202 If no patterns are given to match, this command prints the names
5217 of all files under Mercurial control in the working directory.
5203 of all files under Mercurial control in the working directory.
5218
5204
5219 If you want to feed the output of this command into the "xargs"
5205 If you want to feed the output of this command into the "xargs"
5220 command, use the -0 option to both this command and "xargs". This
5206 command, use the -0 option to both this command and "xargs". This
5221 will avoid the problem of "xargs" treating single filenames that
5207 will avoid the problem of "xargs" treating single filenames that
5222 contain whitespace as multiple filenames.
5208 contain whitespace as multiple filenames.
5223
5209
5224 See :hg:`help files` for a more versatile command.
5210 See :hg:`help files` for a more versatile command.
5225
5211
5226 Returns 0 if a match is found, 1 otherwise.
5212 Returns 0 if a match is found, 1 otherwise.
5227 """
5213 """
5228 if opts.get('print0'):
5214 if opts.get('print0'):
5229 end = '\0'
5215 end = '\0'
5230 else:
5216 else:
5231 end = '\n'
5217 end = '\n'
5232 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5218 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5233
5219
5234 ret = 1
5220 ret = 1
5235 ctx = repo[rev]
5221 ctx = repo[rev]
5236 m = scmutil.match(ctx, pats, opts, default='relglob',
5222 m = scmutil.match(ctx, pats, opts, default='relglob',
5237 badfn=lambda x, y: False)
5223 badfn=lambda x, y: False)
5238
5224
5239 for abs in ctx.matches(m):
5225 for abs in ctx.matches(m):
5240 if opts.get('fullpath'):
5226 if opts.get('fullpath'):
5241 ui.write(repo.wjoin(abs), end)
5227 ui.write(repo.wjoin(abs), end)
5242 else:
5228 else:
5243 ui.write(((pats and m.rel(abs)) or abs), end)
5229 ui.write(((pats and m.rel(abs)) or abs), end)
5244 ret = 0
5230 ret = 0
5245
5231
5246 return ret
5232 return ret
5247
5233
5248 @command('^log|history',
5234 @command('^log|history',
5249 [('f', 'follow', None,
5235 [('f', 'follow', None,
5250 _('follow changeset history, or file history across copies and renames')),
5236 _('follow changeset history, or file history across copies and renames')),
5251 ('', 'follow-first', None,
5237 ('', 'follow-first', None,
5252 _('only follow the first parent of merge changesets (DEPRECATED)')),
5238 _('only follow the first parent of merge changesets (DEPRECATED)')),
5253 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5239 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5254 ('C', 'copies', None, _('show copied files')),
5240 ('C', 'copies', None, _('show copied files')),
5255 ('k', 'keyword', [],
5241 ('k', 'keyword', [],
5256 _('do case-insensitive search for a given text'), _('TEXT')),
5242 _('do case-insensitive search for a given text'), _('TEXT')),
5257 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5243 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5258 ('', 'removed', None, _('include revisions where files were removed')),
5244 ('', 'removed', None, _('include revisions where files were removed')),
5259 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5245 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5260 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5246 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5261 ('', 'only-branch', [],
5247 ('', 'only-branch', [],
5262 _('show only changesets within the given named branch (DEPRECATED)'),
5248 _('show only changesets within the given named branch (DEPRECATED)'),
5263 _('BRANCH')),
5249 _('BRANCH')),
5264 ('b', 'branch', [],
5250 ('b', 'branch', [],
5265 _('show changesets within the given named branch'), _('BRANCH')),
5251 _('show changesets within the given named branch'), _('BRANCH')),
5266 ('P', 'prune', [],
5252 ('P', 'prune', [],
5267 _('do not display revision or any of its ancestors'), _('REV')),
5253 _('do not display revision or any of its ancestors'), _('REV')),
5268 ] + logopts + walkopts,
5254 ] + logopts + walkopts,
5269 _('[OPTION]... [FILE]'),
5255 _('[OPTION]... [FILE]'),
5270 inferrepo=True)
5256 inferrepo=True)
5271 def log(ui, repo, *pats, **opts):
5257 def log(ui, repo, *pats, **opts):
5272 """show revision history of entire repository or files
5258 """show revision history of entire repository or files
5273
5259
5274 Print the revision history of the specified files or the entire
5260 Print the revision history of the specified files or the entire
5275 project.
5261 project.
5276
5262
5277 If no revision range is specified, the default is ``tip:0`` unless
5263 If no revision range is specified, the default is ``tip:0`` unless
5278 --follow is set, in which case the working directory parent is
5264 --follow is set, in which case the working directory parent is
5279 used as the starting revision.
5265 used as the starting revision.
5280
5266
5281 File history is shown without following rename or copy history of
5267 File history is shown without following rename or copy history of
5282 files. Use -f/--follow with a filename to follow history across
5268 files. Use -f/--follow with a filename to follow history across
5283 renames and copies. --follow without a filename will only show
5269 renames and copies. --follow without a filename will only show
5284 ancestors or descendants of the starting revision.
5270 ancestors or descendants of the starting revision.
5285
5271
5286 By default this command prints revision number and changeset id,
5272 By default this command prints revision number and changeset id,
5287 tags, non-trivial parents, user, date and time, and a summary for
5273 tags, non-trivial parents, user, date and time, and a summary for
5288 each commit. When the -v/--verbose switch is used, the list of
5274 each commit. When the -v/--verbose switch is used, the list of
5289 changed files and full commit message are shown.
5275 changed files and full commit message are shown.
5290
5276
5291 With --graph the revisions are shown as an ASCII art DAG with the most
5277 With --graph the revisions are shown as an ASCII art DAG with the most
5292 recent changeset at the top.
5278 recent changeset at the top.
5293 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5279 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5294 and '+' represents a fork where the changeset from the lines below is a
5280 and '+' represents a fork where the changeset from the lines below is a
5295 parent of the 'o' merge on the same line.
5281 parent of the 'o' merge on the same line.
5296
5282
5297 .. note::
5283 .. note::
5298
5284
5299 :hg:`log --patch` may generate unexpected diff output for merge
5285 :hg:`log --patch` may generate unexpected diff output for merge
5300 changesets, as it will only compare the merge changeset against
5286 changesets, as it will only compare the merge changeset against
5301 its first parent. Also, only files different from BOTH parents
5287 its first parent. Also, only files different from BOTH parents
5302 will appear in files:.
5288 will appear in files:.
5303
5289
5304 .. note::
5290 .. note::
5305
5291
5306 For performance reasons, :hg:`log FILE` may omit duplicate changes
5292 For performance reasons, :hg:`log FILE` may omit duplicate changes
5307 made on branches and will not show removals or mode changes. To
5293 made on branches and will not show removals or mode changes. To
5308 see all such changes, use the --removed switch.
5294 see all such changes, use the --removed switch.
5309
5295
5310 .. container:: verbose
5296 .. container:: verbose
5311
5297
5312 Some examples:
5298 Some examples:
5313
5299
5314 - changesets with full descriptions and file lists::
5300 - changesets with full descriptions and file lists::
5315
5301
5316 hg log -v
5302 hg log -v
5317
5303
5318 - changesets ancestral to the working directory::
5304 - changesets ancestral to the working directory::
5319
5305
5320 hg log -f
5306 hg log -f
5321
5307
5322 - last 10 commits on the current branch::
5308 - last 10 commits on the current branch::
5323
5309
5324 hg log -l 10 -b .
5310 hg log -l 10 -b .
5325
5311
5326 - changesets showing all modifications of a file, including removals::
5312 - changesets showing all modifications of a file, including removals::
5327
5313
5328 hg log --removed file.c
5314 hg log --removed file.c
5329
5315
5330 - all changesets that touch a directory, with diffs, excluding merges::
5316 - all changesets that touch a directory, with diffs, excluding merges::
5331
5317
5332 hg log -Mp lib/
5318 hg log -Mp lib/
5333
5319
5334 - all revision numbers that match a keyword::
5320 - all revision numbers that match a keyword::
5335
5321
5336 hg log -k bug --template "{rev}\\n"
5322 hg log -k bug --template "{rev}\\n"
5337
5323
5338 - the full hash identifier of the working directory parent::
5324 - the full hash identifier of the working directory parent::
5339
5325
5340 hg log -r . --template "{node}\\n"
5326 hg log -r . --template "{node}\\n"
5341
5327
5342 - list available log templates::
5328 - list available log templates::
5343
5329
5344 hg log -T list
5330 hg log -T list
5345
5331
5346 - check if a given changeset is included in a tagged release::
5332 - check if a given changeset is included in a tagged release::
5347
5333
5348 hg log -r "a21ccf and ancestor(1.9)"
5334 hg log -r "a21ccf and ancestor(1.9)"
5349
5335
5350 - find all changesets by some user in a date range::
5336 - find all changesets by some user in a date range::
5351
5337
5352 hg log -k alice -d "may 2008 to jul 2008"
5338 hg log -k alice -d "may 2008 to jul 2008"
5353
5339
5354 - summary of all changesets after the last tag::
5340 - summary of all changesets after the last tag::
5355
5341
5356 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5342 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5357
5343
5358 See :hg:`help dates` for a list of formats valid for -d/--date.
5344 See :hg:`help dates` for a list of formats valid for -d/--date.
5359
5345
5360 See :hg:`help revisions` and :hg:`help revsets` for more about
5346 See :hg:`help revisions` and :hg:`help revsets` for more about
5361 specifying and ordering revisions.
5347 specifying and ordering revisions.
5362
5348
5363 See :hg:`help templates` for more about pre-packaged styles and
5349 See :hg:`help templates` for more about pre-packaged styles and
5364 specifying custom templates.
5350 specifying custom templates.
5365
5351
5366 Returns 0 on success.
5352 Returns 0 on success.
5367
5353
5368 """
5354 """
5369 if opts.get('follow') and opts.get('rev'):
5355 if opts.get('follow') and opts.get('rev'):
5370 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5356 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5371 del opts['follow']
5357 del opts['follow']
5372
5358
5373 if opts.get('graph'):
5359 if opts.get('graph'):
5374 return cmdutil.graphlog(ui, repo, *pats, **opts)
5360 return cmdutil.graphlog(ui, repo, *pats, **opts)
5375
5361
5376 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5362 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5377 limit = cmdutil.loglimit(opts)
5363 limit = cmdutil.loglimit(opts)
5378 count = 0
5364 count = 0
5379
5365
5380 getrenamed = None
5366 getrenamed = None
5381 if opts.get('copies'):
5367 if opts.get('copies'):
5382 endrev = None
5368 endrev = None
5383 if opts.get('rev'):
5369 if opts.get('rev'):
5384 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5370 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5385 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5371 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5386
5372
5387 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5373 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5388 for rev in revs:
5374 for rev in revs:
5389 if count == limit:
5375 if count == limit:
5390 break
5376 break
5391 ctx = repo[rev]
5377 ctx = repo[rev]
5392 copies = None
5378 copies = None
5393 if getrenamed is not None and rev:
5379 if getrenamed is not None and rev:
5394 copies = []
5380 copies = []
5395 for fn in ctx.files():
5381 for fn in ctx.files():
5396 rename = getrenamed(fn, rev)
5382 rename = getrenamed(fn, rev)
5397 if rename:
5383 if rename:
5398 copies.append((fn, rename[0]))
5384 copies.append((fn, rename[0]))
5399 if filematcher:
5385 if filematcher:
5400 revmatchfn = filematcher(ctx.rev())
5386 revmatchfn = filematcher(ctx.rev())
5401 else:
5387 else:
5402 revmatchfn = None
5388 revmatchfn = None
5403 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5389 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5404 if displayer.flush(ctx):
5390 if displayer.flush(ctx):
5405 count += 1
5391 count += 1
5406
5392
5407 displayer.close()
5393 displayer.close()
5408
5394
5409 @command('manifest',
5395 @command('manifest',
5410 [('r', 'rev', '', _('revision to display'), _('REV')),
5396 [('r', 'rev', '', _('revision to display'), _('REV')),
5411 ('', 'all', False, _("list files from all revisions"))]
5397 ('', 'all', False, _("list files from all revisions"))]
5412 + formatteropts,
5398 + formatteropts,
5413 _('[-r REV]'))
5399 _('[-r REV]'))
5414 def manifest(ui, repo, node=None, rev=None, **opts):
5400 def manifest(ui, repo, node=None, rev=None, **opts):
5415 """output the current or given revision of the project manifest
5401 """output the current or given revision of the project manifest
5416
5402
5417 Print a list of version controlled files for the given revision.
5403 Print a list of version controlled files for the given revision.
5418 If no revision is given, the first parent of the working directory
5404 If no revision is given, the first parent of the working directory
5419 is used, or the null revision if no revision is checked out.
5405 is used, or the null revision if no revision is checked out.
5420
5406
5421 With -v, print file permissions, symlink and executable bits.
5407 With -v, print file permissions, symlink and executable bits.
5422 With --debug, print file revision hashes.
5408 With --debug, print file revision hashes.
5423
5409
5424 If option --all is specified, the list of all files from all revisions
5410 If option --all is specified, the list of all files from all revisions
5425 is printed. This includes deleted and renamed files.
5411 is printed. This includes deleted and renamed files.
5426
5412
5427 Returns 0 on success.
5413 Returns 0 on success.
5428 """
5414 """
5429
5415
5430 fm = ui.formatter('manifest', opts)
5416 fm = ui.formatter('manifest', opts)
5431
5417
5432 if opts.get('all'):
5418 if opts.get('all'):
5433 if rev or node:
5419 if rev or node:
5434 raise error.Abort(_("can't specify a revision with --all"))
5420 raise error.Abort(_("can't specify a revision with --all"))
5435
5421
5436 res = []
5422 res = []
5437 prefix = "data/"
5423 prefix = "data/"
5438 suffix = ".i"
5424 suffix = ".i"
5439 plen = len(prefix)
5425 plen = len(prefix)
5440 slen = len(suffix)
5426 slen = len(suffix)
5441 with repo.lock():
5427 with repo.lock():
5442 for fn, b, size in repo.store.datafiles():
5428 for fn, b, size in repo.store.datafiles():
5443 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5429 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5444 res.append(fn[plen:-slen])
5430 res.append(fn[plen:-slen])
5445 for f in res:
5431 for f in res:
5446 fm.startitem()
5432 fm.startitem()
5447 fm.write("path", '%s\n', f)
5433 fm.write("path", '%s\n', f)
5448 fm.end()
5434 fm.end()
5449 return
5435 return
5450
5436
5451 if rev and node:
5437 if rev and node:
5452 raise error.Abort(_("please specify just one revision"))
5438 raise error.Abort(_("please specify just one revision"))
5453
5439
5454 if not node:
5440 if not node:
5455 node = rev
5441 node = rev
5456
5442
5457 char = {'l': '@', 'x': '*', '': ''}
5443 char = {'l': '@', 'x': '*', '': ''}
5458 mode = {'l': '644', 'x': '755', '': '644'}
5444 mode = {'l': '644', 'x': '755', '': '644'}
5459 ctx = scmutil.revsingle(repo, node)
5445 ctx = scmutil.revsingle(repo, node)
5460 mf = ctx.manifest()
5446 mf = ctx.manifest()
5461 for f in ctx:
5447 for f in ctx:
5462 fm.startitem()
5448 fm.startitem()
5463 fl = ctx[f].flags()
5449 fl = ctx[f].flags()
5464 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5450 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5465 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5451 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5466 fm.write('path', '%s\n', f)
5452 fm.write('path', '%s\n', f)
5467 fm.end()
5453 fm.end()
5468
5454
5469 @command('^merge',
5455 @command('^merge',
5470 [('f', 'force', None,
5456 [('f', 'force', None,
5471 _('force a merge including outstanding changes (DEPRECATED)')),
5457 _('force a merge including outstanding changes (DEPRECATED)')),
5472 ('r', 'rev', '', _('revision to merge'), _('REV')),
5458 ('r', 'rev', '', _('revision to merge'), _('REV')),
5473 ('P', 'preview', None,
5459 ('P', 'preview', None,
5474 _('review revisions to merge (no merge is performed)'))
5460 _('review revisions to merge (no merge is performed)'))
5475 ] + mergetoolopts,
5461 ] + mergetoolopts,
5476 _('[-P] [[-r] REV]'))
5462 _('[-P] [[-r] REV]'))
5477 def merge(ui, repo, node=None, **opts):
5463 def merge(ui, repo, node=None, **opts):
5478 """merge another revision into working directory
5464 """merge another revision into working directory
5479
5465
5480 The current working directory is updated with all changes made in
5466 The current working directory is updated with all changes made in
5481 the requested revision since the last common predecessor revision.
5467 the requested revision since the last common predecessor revision.
5482
5468
5483 Files that changed between either parent are marked as changed for
5469 Files that changed between either parent are marked as changed for
5484 the next commit and a commit must be performed before any further
5470 the next commit and a commit must be performed before any further
5485 updates to the repository are allowed. The next commit will have
5471 updates to the repository are allowed. The next commit will have
5486 two parents.
5472 two parents.
5487
5473
5488 ``--tool`` can be used to specify the merge tool used for file
5474 ``--tool`` can be used to specify the merge tool used for file
5489 merges. It overrides the HGMERGE environment variable and your
5475 merges. It overrides the HGMERGE environment variable and your
5490 configuration files. See :hg:`help merge-tools` for options.
5476 configuration files. See :hg:`help merge-tools` for options.
5491
5477
5492 If no revision is specified, the working directory's parent is a
5478 If no revision is specified, the working directory's parent is a
5493 head revision, and the current branch contains exactly one other
5479 head revision, and the current branch contains exactly one other
5494 head, the other head is merged with by default. Otherwise, an
5480 head, the other head is merged with by default. Otherwise, an
5495 explicit revision with which to merge with must be provided.
5481 explicit revision with which to merge with must be provided.
5496
5482
5497 See :hg:`help resolve` for information on handling file conflicts.
5483 See :hg:`help resolve` for information on handling file conflicts.
5498
5484
5499 To undo an uncommitted merge, use :hg:`update --clean .` which
5485 To undo an uncommitted merge, use :hg:`update --clean .` which
5500 will check out a clean copy of the original merge parent, losing
5486 will check out a clean copy of the original merge parent, losing
5501 all changes.
5487 all changes.
5502
5488
5503 Returns 0 on success, 1 if there are unresolved files.
5489 Returns 0 on success, 1 if there are unresolved files.
5504 """
5490 """
5505
5491
5506 if opts.get('rev') and node:
5492 if opts.get('rev') and node:
5507 raise error.Abort(_("please specify just one revision"))
5493 raise error.Abort(_("please specify just one revision"))
5508 if not node:
5494 if not node:
5509 node = opts.get('rev')
5495 node = opts.get('rev')
5510
5496
5511 if node:
5497 if node:
5512 node = scmutil.revsingle(repo, node).node()
5498 node = scmutil.revsingle(repo, node).node()
5513
5499
5514 if not node:
5500 if not node:
5515 node = repo[destutil.destmerge(repo)].node()
5501 node = repo[destutil.destmerge(repo)].node()
5516
5502
5517 if opts.get('preview'):
5503 if opts.get('preview'):
5518 # find nodes that are ancestors of p2 but not of p1
5504 # find nodes that are ancestors of p2 but not of p1
5519 p1 = repo.lookup('.')
5505 p1 = repo.lookup('.')
5520 p2 = repo.lookup(node)
5506 p2 = repo.lookup(node)
5521 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5507 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5522
5508
5523 displayer = cmdutil.show_changeset(ui, repo, opts)
5509 displayer = cmdutil.show_changeset(ui, repo, opts)
5524 for node in nodes:
5510 for node in nodes:
5525 displayer.show(repo[node])
5511 displayer.show(repo[node])
5526 displayer.close()
5512 displayer.close()
5527 return 0
5513 return 0
5528
5514
5529 try:
5515 try:
5530 # ui.forcemerge is an internal variable, do not document
5516 # ui.forcemerge is an internal variable, do not document
5531 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5517 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5532 force = opts.get('force')
5518 force = opts.get('force')
5533 labels = ['working copy', 'merge rev']
5519 labels = ['working copy', 'merge rev']
5534 return hg.merge(repo, node, force=force, mergeforce=force,
5520 return hg.merge(repo, node, force=force, mergeforce=force,
5535 labels=labels)
5521 labels=labels)
5536 finally:
5522 finally:
5537 ui.setconfig('ui', 'forcemerge', '', 'merge')
5523 ui.setconfig('ui', 'forcemerge', '', 'merge')
5538
5524
5539 @command('outgoing|out',
5525 @command('outgoing|out',
5540 [('f', 'force', None, _('run even when the destination is unrelated')),
5526 [('f', 'force', None, _('run even when the destination is unrelated')),
5541 ('r', 'rev', [],
5527 ('r', 'rev', [],
5542 _('a changeset intended to be included in the destination'), _('REV')),
5528 _('a changeset intended to be included in the destination'), _('REV')),
5543 ('n', 'newest-first', None, _('show newest record first')),
5529 ('n', 'newest-first', None, _('show newest record first')),
5544 ('B', 'bookmarks', False, _('compare bookmarks')),
5530 ('B', 'bookmarks', False, _('compare bookmarks')),
5545 ('b', 'branch', [], _('a specific branch you would like to push'),
5531 ('b', 'branch', [], _('a specific branch you would like to push'),
5546 _('BRANCH')),
5532 _('BRANCH')),
5547 ] + logopts + remoteopts + subrepoopts,
5533 ] + logopts + remoteopts + subrepoopts,
5548 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5534 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5549 def outgoing(ui, repo, dest=None, **opts):
5535 def outgoing(ui, repo, dest=None, **opts):
5550 """show changesets not found in the destination
5536 """show changesets not found in the destination
5551
5537
5552 Show changesets not found in the specified destination repository
5538 Show changesets not found in the specified destination repository
5553 or the default push location. These are the changesets that would
5539 or the default push location. These are the changesets that would
5554 be pushed if a push was requested.
5540 be pushed if a push was requested.
5555
5541
5556 See pull for details of valid destination formats.
5542 See pull for details of valid destination formats.
5557
5543
5558 .. container:: verbose
5544 .. container:: verbose
5559
5545
5560 With -B/--bookmarks, the result of bookmark comparison between
5546 With -B/--bookmarks, the result of bookmark comparison between
5561 local and remote repositories is displayed. With -v/--verbose,
5547 local and remote repositories is displayed. With -v/--verbose,
5562 status is also displayed for each bookmark like below::
5548 status is also displayed for each bookmark like below::
5563
5549
5564 BM1 01234567890a added
5550 BM1 01234567890a added
5565 BM2 deleted
5551 BM2 deleted
5566 BM3 234567890abc advanced
5552 BM3 234567890abc advanced
5567 BM4 34567890abcd diverged
5553 BM4 34567890abcd diverged
5568 BM5 4567890abcde changed
5554 BM5 4567890abcde changed
5569
5555
5570 The action taken when pushing depends on the
5556 The action taken when pushing depends on the
5571 status of each bookmark:
5557 status of each bookmark:
5572
5558
5573 :``added``: push with ``-B`` will create it
5559 :``added``: push with ``-B`` will create it
5574 :``deleted``: push with ``-B`` will delete it
5560 :``deleted``: push with ``-B`` will delete it
5575 :``advanced``: push will update it
5561 :``advanced``: push will update it
5576 :``diverged``: push with ``-B`` will update it
5562 :``diverged``: push with ``-B`` will update it
5577 :``changed``: push with ``-B`` will update it
5563 :``changed``: push with ``-B`` will update it
5578
5564
5579 From the point of view of pushing behavior, bookmarks
5565 From the point of view of pushing behavior, bookmarks
5580 existing only in the remote repository are treated as
5566 existing only in the remote repository are treated as
5581 ``deleted``, even if it is in fact added remotely.
5567 ``deleted``, even if it is in fact added remotely.
5582
5568
5583 Returns 0 if there are outgoing changes, 1 otherwise.
5569 Returns 0 if there are outgoing changes, 1 otherwise.
5584 """
5570 """
5585 if opts.get('graph'):
5571 if opts.get('graph'):
5586 cmdutil.checkunsupportedgraphflags([], opts)
5572 cmdutil.checkunsupportedgraphflags([], opts)
5587 o, other = hg._outgoing(ui, repo, dest, opts)
5573 o, other = hg._outgoing(ui, repo, dest, opts)
5588 if not o:
5574 if not o:
5589 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5575 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5590 return
5576 return
5591
5577
5592 revdag = cmdutil.graphrevs(repo, o, opts)
5578 revdag = cmdutil.graphrevs(repo, o, opts)
5593 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5579 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5594 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5580 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5595 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5581 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5596 return 0
5582 return 0
5597
5583
5598 if opts.get('bookmarks'):
5584 if opts.get('bookmarks'):
5599 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5585 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5600 dest, branches = hg.parseurl(dest, opts.get('branch'))
5586 dest, branches = hg.parseurl(dest, opts.get('branch'))
5601 other = hg.peer(repo, opts, dest)
5587 other = hg.peer(repo, opts, dest)
5602 if 'bookmarks' not in other.listkeys('namespaces'):
5588 if 'bookmarks' not in other.listkeys('namespaces'):
5603 ui.warn(_("remote doesn't support bookmarks\n"))
5589 ui.warn(_("remote doesn't support bookmarks\n"))
5604 return 0
5590 return 0
5605 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5591 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5606 return bookmarks.outgoing(ui, repo, other)
5592 return bookmarks.outgoing(ui, repo, other)
5607
5593
5608 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5594 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5609 try:
5595 try:
5610 return hg.outgoing(ui, repo, dest, opts)
5596 return hg.outgoing(ui, repo, dest, opts)
5611 finally:
5597 finally:
5612 del repo._subtoppath
5598 del repo._subtoppath
5613
5599
5614 @command('parents',
5600 @command('parents',
5615 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5601 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5616 ] + templateopts,
5602 ] + templateopts,
5617 _('[-r REV] [FILE]'),
5603 _('[-r REV] [FILE]'),
5618 inferrepo=True)
5604 inferrepo=True)
5619 def parents(ui, repo, file_=None, **opts):
5605 def parents(ui, repo, file_=None, **opts):
5620 """show the parents of the working directory or revision (DEPRECATED)
5606 """show the parents of the working directory or revision (DEPRECATED)
5621
5607
5622 Print the working directory's parent revisions. If a revision is
5608 Print the working directory's parent revisions. If a revision is
5623 given via -r/--rev, the parent of that revision will be printed.
5609 given via -r/--rev, the parent of that revision will be printed.
5624 If a file argument is given, the revision in which the file was
5610 If a file argument is given, the revision in which the file was
5625 last changed (before the working directory revision or the
5611 last changed (before the working directory revision or the
5626 argument to --rev if given) is printed.
5612 argument to --rev if given) is printed.
5627
5613
5628 This command is equivalent to::
5614 This command is equivalent to::
5629
5615
5630 hg log -r "p1()+p2()" or
5616 hg log -r "p1()+p2()" or
5631 hg log -r "p1(REV)+p2(REV)" or
5617 hg log -r "p1(REV)+p2(REV)" or
5632 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5618 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5633 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5619 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5634
5620
5635 See :hg:`summary` and :hg:`help revsets` for related information.
5621 See :hg:`summary` and :hg:`help revsets` for related information.
5636
5622
5637 Returns 0 on success.
5623 Returns 0 on success.
5638 """
5624 """
5639
5625
5640 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5626 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5641
5627
5642 if file_:
5628 if file_:
5643 m = scmutil.match(ctx, (file_,), opts)
5629 m = scmutil.match(ctx, (file_,), opts)
5644 if m.anypats() or len(m.files()) != 1:
5630 if m.anypats() or len(m.files()) != 1:
5645 raise error.Abort(_('can only specify an explicit filename'))
5631 raise error.Abort(_('can only specify an explicit filename'))
5646 file_ = m.files()[0]
5632 file_ = m.files()[0]
5647 filenodes = []
5633 filenodes = []
5648 for cp in ctx.parents():
5634 for cp in ctx.parents():
5649 if not cp:
5635 if not cp:
5650 continue
5636 continue
5651 try:
5637 try:
5652 filenodes.append(cp.filenode(file_))
5638 filenodes.append(cp.filenode(file_))
5653 except error.LookupError:
5639 except error.LookupError:
5654 pass
5640 pass
5655 if not filenodes:
5641 if not filenodes:
5656 raise error.Abort(_("'%s' not found in manifest!") % file_)
5642 raise error.Abort(_("'%s' not found in manifest!") % file_)
5657 p = []
5643 p = []
5658 for fn in filenodes:
5644 for fn in filenodes:
5659 fctx = repo.filectx(file_, fileid=fn)
5645 fctx = repo.filectx(file_, fileid=fn)
5660 p.append(fctx.node())
5646 p.append(fctx.node())
5661 else:
5647 else:
5662 p = [cp.node() for cp in ctx.parents()]
5648 p = [cp.node() for cp in ctx.parents()]
5663
5649
5664 displayer = cmdutil.show_changeset(ui, repo, opts)
5650 displayer = cmdutil.show_changeset(ui, repo, opts)
5665 for n in p:
5651 for n in p:
5666 if n != nullid:
5652 if n != nullid:
5667 displayer.show(repo[n])
5653 displayer.show(repo[n])
5668 displayer.close()
5654 displayer.close()
5669
5655
5670 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5656 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5671 def paths(ui, repo, search=None, **opts):
5657 def paths(ui, repo, search=None, **opts):
5672 """show aliases for remote repositories
5658 """show aliases for remote repositories
5673
5659
5674 Show definition of symbolic path name NAME. If no name is given,
5660 Show definition of symbolic path name NAME. If no name is given,
5675 show definition of all available names.
5661 show definition of all available names.
5676
5662
5677 Option -q/--quiet suppresses all output when searching for NAME
5663 Option -q/--quiet suppresses all output when searching for NAME
5678 and shows only the path names when listing all definitions.
5664 and shows only the path names when listing all definitions.
5679
5665
5680 Path names are defined in the [paths] section of your
5666 Path names are defined in the [paths] section of your
5681 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5667 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5682 repository, ``.hg/hgrc`` is used, too.
5668 repository, ``.hg/hgrc`` is used, too.
5683
5669
5684 The path names ``default`` and ``default-push`` have a special
5670 The path names ``default`` and ``default-push`` have a special
5685 meaning. When performing a push or pull operation, they are used
5671 meaning. When performing a push or pull operation, they are used
5686 as fallbacks if no location is specified on the command-line.
5672 as fallbacks if no location is specified on the command-line.
5687 When ``default-push`` is set, it will be used for push and
5673 When ``default-push`` is set, it will be used for push and
5688 ``default`` will be used for pull; otherwise ``default`` is used
5674 ``default`` will be used for pull; otherwise ``default`` is used
5689 as the fallback for both. When cloning a repository, the clone
5675 as the fallback for both. When cloning a repository, the clone
5690 source is written as ``default`` in ``.hg/hgrc``.
5676 source is written as ``default`` in ``.hg/hgrc``.
5691
5677
5692 .. note::
5678 .. note::
5693
5679
5694 ``default`` and ``default-push`` apply to all inbound (e.g.
5680 ``default`` and ``default-push`` apply to all inbound (e.g.
5695 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5681 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5696 and :hg:`bundle`) operations.
5682 and :hg:`bundle`) operations.
5697
5683
5698 See :hg:`help urls` for more information.
5684 See :hg:`help urls` for more information.
5699
5685
5700 Returns 0 on success.
5686 Returns 0 on success.
5701 """
5687 """
5702 if search:
5688 if search:
5703 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5689 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5704 if name == search]
5690 if name == search]
5705 else:
5691 else:
5706 pathitems = sorted(ui.paths.iteritems())
5692 pathitems = sorted(ui.paths.iteritems())
5707
5693
5708 fm = ui.formatter('paths', opts)
5694 fm = ui.formatter('paths', opts)
5709 if fm.isplain():
5695 if fm.isplain():
5710 hidepassword = util.hidepassword
5696 hidepassword = util.hidepassword
5711 else:
5697 else:
5712 hidepassword = str
5698 hidepassword = str
5713 if ui.quiet:
5699 if ui.quiet:
5714 namefmt = '%s\n'
5700 namefmt = '%s\n'
5715 else:
5701 else:
5716 namefmt = '%s = '
5702 namefmt = '%s = '
5717 showsubopts = not search and not ui.quiet
5703 showsubopts = not search and not ui.quiet
5718
5704
5719 for name, path in pathitems:
5705 for name, path in pathitems:
5720 fm.startitem()
5706 fm.startitem()
5721 fm.condwrite(not search, 'name', namefmt, name)
5707 fm.condwrite(not search, 'name', namefmt, name)
5722 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5708 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5723 for subopt, value in sorted(path.suboptions.items()):
5709 for subopt, value in sorted(path.suboptions.items()):
5724 assert subopt not in ('name', 'url')
5710 assert subopt not in ('name', 'url')
5725 if showsubopts:
5711 if showsubopts:
5726 fm.plain('%s:%s = ' % (name, subopt))
5712 fm.plain('%s:%s = ' % (name, subopt))
5727 fm.condwrite(showsubopts, subopt, '%s\n', value)
5713 fm.condwrite(showsubopts, subopt, '%s\n', value)
5728
5714
5729 fm.end()
5715 fm.end()
5730
5716
5731 if search and not pathitems:
5717 if search and not pathitems:
5732 if not ui.quiet:
5718 if not ui.quiet:
5733 ui.warn(_("not found!\n"))
5719 ui.warn(_("not found!\n"))
5734 return 1
5720 return 1
5735 else:
5721 else:
5736 return 0
5722 return 0
5737
5723
5738 @command('phase',
5724 @command('phase',
5739 [('p', 'public', False, _('set changeset phase to public')),
5725 [('p', 'public', False, _('set changeset phase to public')),
5740 ('d', 'draft', False, _('set changeset phase to draft')),
5726 ('d', 'draft', False, _('set changeset phase to draft')),
5741 ('s', 'secret', False, _('set changeset phase to secret')),
5727 ('s', 'secret', False, _('set changeset phase to secret')),
5742 ('f', 'force', False, _('allow to move boundary backward')),
5728 ('f', 'force', False, _('allow to move boundary backward')),
5743 ('r', 'rev', [], _('target revision'), _('REV')),
5729 ('r', 'rev', [], _('target revision'), _('REV')),
5744 ],
5730 ],
5745 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5731 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5746 def phase(ui, repo, *revs, **opts):
5732 def phase(ui, repo, *revs, **opts):
5747 """set or show the current phase name
5733 """set or show the current phase name
5748
5734
5749 With no argument, show the phase name of the current revision(s).
5735 With no argument, show the phase name of the current revision(s).
5750
5736
5751 With one of -p/--public, -d/--draft or -s/--secret, change the
5737 With one of -p/--public, -d/--draft or -s/--secret, change the
5752 phase value of the specified revisions.
5738 phase value of the specified revisions.
5753
5739
5754 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5740 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5755 lower phase to an higher phase. Phases are ordered as follows::
5741 lower phase to an higher phase. Phases are ordered as follows::
5756
5742
5757 public < draft < secret
5743 public < draft < secret
5758
5744
5759 Returns 0 on success, 1 if some phases could not be changed.
5745 Returns 0 on success, 1 if some phases could not be changed.
5760
5746
5761 (For more information about the phases concept, see :hg:`help phases`.)
5747 (For more information about the phases concept, see :hg:`help phases`.)
5762 """
5748 """
5763 # search for a unique phase argument
5749 # search for a unique phase argument
5764 targetphase = None
5750 targetphase = None
5765 for idx, name in enumerate(phases.phasenames):
5751 for idx, name in enumerate(phases.phasenames):
5766 if opts[name]:
5752 if opts[name]:
5767 if targetphase is not None:
5753 if targetphase is not None:
5768 raise error.Abort(_('only one phase can be specified'))
5754 raise error.Abort(_('only one phase can be specified'))
5769 targetphase = idx
5755 targetphase = idx
5770
5756
5771 # look for specified revision
5757 # look for specified revision
5772 revs = list(revs)
5758 revs = list(revs)
5773 revs.extend(opts['rev'])
5759 revs.extend(opts['rev'])
5774 if not revs:
5760 if not revs:
5775 # display both parents as the second parent phase can influence
5761 # display both parents as the second parent phase can influence
5776 # the phase of a merge commit
5762 # the phase of a merge commit
5777 revs = [c.rev() for c in repo[None].parents()]
5763 revs = [c.rev() for c in repo[None].parents()]
5778
5764
5779 revs = scmutil.revrange(repo, revs)
5765 revs = scmutil.revrange(repo, revs)
5780
5766
5781 lock = None
5767 lock = None
5782 ret = 0
5768 ret = 0
5783 if targetphase is None:
5769 if targetphase is None:
5784 # display
5770 # display
5785 for r in revs:
5771 for r in revs:
5786 ctx = repo[r]
5772 ctx = repo[r]
5787 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5773 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5788 else:
5774 else:
5789 tr = None
5775 tr = None
5790 lock = repo.lock()
5776 lock = repo.lock()
5791 try:
5777 try:
5792 tr = repo.transaction("phase")
5778 tr = repo.transaction("phase")
5793 # set phase
5779 # set phase
5794 if not revs:
5780 if not revs:
5795 raise error.Abort(_('empty revision set'))
5781 raise error.Abort(_('empty revision set'))
5796 nodes = [repo[r].node() for r in revs]
5782 nodes = [repo[r].node() for r in revs]
5797 # moving revision from public to draft may hide them
5783 # moving revision from public to draft may hide them
5798 # We have to check result on an unfiltered repository
5784 # We have to check result on an unfiltered repository
5799 unfi = repo.unfiltered()
5785 unfi = repo.unfiltered()
5800 getphase = unfi._phasecache.phase
5786 getphase = unfi._phasecache.phase
5801 olddata = [getphase(unfi, r) for r in unfi]
5787 olddata = [getphase(unfi, r) for r in unfi]
5802 phases.advanceboundary(repo, tr, targetphase, nodes)
5788 phases.advanceboundary(repo, tr, targetphase, nodes)
5803 if opts['force']:
5789 if opts['force']:
5804 phases.retractboundary(repo, tr, targetphase, nodes)
5790 phases.retractboundary(repo, tr, targetphase, nodes)
5805 tr.close()
5791 tr.close()
5806 finally:
5792 finally:
5807 if tr is not None:
5793 if tr is not None:
5808 tr.release()
5794 tr.release()
5809 lock.release()
5795 lock.release()
5810 getphase = unfi._phasecache.phase
5796 getphase = unfi._phasecache.phase
5811 newdata = [getphase(unfi, r) for r in unfi]
5797 newdata = [getphase(unfi, r) for r in unfi]
5812 changes = sum(newdata[r] != olddata[r] for r in unfi)
5798 changes = sum(newdata[r] != olddata[r] for r in unfi)
5813 cl = unfi.changelog
5799 cl = unfi.changelog
5814 rejected = [n for n in nodes
5800 rejected = [n for n in nodes
5815 if newdata[cl.rev(n)] < targetphase]
5801 if newdata[cl.rev(n)] < targetphase]
5816 if rejected:
5802 if rejected:
5817 ui.warn(_('cannot move %i changesets to a higher '
5803 ui.warn(_('cannot move %i changesets to a higher '
5818 'phase, use --force\n') % len(rejected))
5804 'phase, use --force\n') % len(rejected))
5819 ret = 1
5805 ret = 1
5820 if changes:
5806 if changes:
5821 msg = _('phase changed for %i changesets\n') % changes
5807 msg = _('phase changed for %i changesets\n') % changes
5822 if ret:
5808 if ret:
5823 ui.status(msg)
5809 ui.status(msg)
5824 else:
5810 else:
5825 ui.note(msg)
5811 ui.note(msg)
5826 else:
5812 else:
5827 ui.warn(_('no phases changed\n'))
5813 ui.warn(_('no phases changed\n'))
5828 return ret
5814 return ret
5829
5815
5830 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5816 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5831 """Run after a changegroup has been added via pull/unbundle
5817 """Run after a changegroup has been added via pull/unbundle
5832
5818
5833 This takes arguments below:
5819 This takes arguments below:
5834
5820
5835 :modheads: change of heads by pull/unbundle
5821 :modheads: change of heads by pull/unbundle
5836 :optupdate: updating working directory is needed or not
5822 :optupdate: updating working directory is needed or not
5837 :checkout: update destination revision (or None to default destination)
5823 :checkout: update destination revision (or None to default destination)
5838 :brev: a name, which might be a bookmark to be activated after updating
5824 :brev: a name, which might be a bookmark to be activated after updating
5839 """
5825 """
5840 if modheads == 0:
5826 if modheads == 0:
5841 return
5827 return
5842 if optupdate:
5828 if optupdate:
5843 try:
5829 try:
5844 return hg.updatetotally(ui, repo, checkout, brev)
5830 return hg.updatetotally(ui, repo, checkout, brev)
5845 except error.UpdateAbort as inst:
5831 except error.UpdateAbort as inst:
5846 msg = _("not updating: %s") % str(inst)
5832 msg = _("not updating: %s") % str(inst)
5847 hint = inst.hint
5833 hint = inst.hint
5848 raise error.UpdateAbort(msg, hint=hint)
5834 raise error.UpdateAbort(msg, hint=hint)
5849 if modheads > 1:
5835 if modheads > 1:
5850 currentbranchheads = len(repo.branchheads())
5836 currentbranchheads = len(repo.branchheads())
5851 if currentbranchheads == modheads:
5837 if currentbranchheads == modheads:
5852 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5838 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5853 elif currentbranchheads > 1:
5839 elif currentbranchheads > 1:
5854 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5840 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5855 "merge)\n"))
5841 "merge)\n"))
5856 else:
5842 else:
5857 ui.status(_("(run 'hg heads' to see heads)\n"))
5843 ui.status(_("(run 'hg heads' to see heads)\n"))
5858 else:
5844 else:
5859 ui.status(_("(run 'hg update' to get a working copy)\n"))
5845 ui.status(_("(run 'hg update' to get a working copy)\n"))
5860
5846
5861 @command('^pull',
5847 @command('^pull',
5862 [('u', 'update', None,
5848 [('u', 'update', None,
5863 _('update to new branch head if changesets were pulled')),
5849 _('update to new branch head if changesets were pulled')),
5864 ('f', 'force', None, _('run even when remote repository is unrelated')),
5850 ('f', 'force', None, _('run even when remote repository is unrelated')),
5865 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5851 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5866 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5852 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5867 ('b', 'branch', [], _('a specific branch you would like to pull'),
5853 ('b', 'branch', [], _('a specific branch you would like to pull'),
5868 _('BRANCH')),
5854 _('BRANCH')),
5869 ] + remoteopts,
5855 ] + remoteopts,
5870 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5856 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5871 def pull(ui, repo, source="default", **opts):
5857 def pull(ui, repo, source="default", **opts):
5872 """pull changes from the specified source
5858 """pull changes from the specified source
5873
5859
5874 Pull changes from a remote repository to a local one.
5860 Pull changes from a remote repository to a local one.
5875
5861
5876 This finds all changes from the repository at the specified path
5862 This finds all changes from the repository at the specified path
5877 or URL and adds them to a local repository (the current one unless
5863 or URL and adds them to a local repository (the current one unless
5878 -R is specified). By default, this does not update the copy of the
5864 -R is specified). By default, this does not update the copy of the
5879 project in the working directory.
5865 project in the working directory.
5880
5866
5881 Use :hg:`incoming` if you want to see what would have been added
5867 Use :hg:`incoming` if you want to see what would have been added
5882 by a pull at the time you issued this command. If you then decide
5868 by a pull at the time you issued this command. If you then decide
5883 to add those changes to the repository, you should use :hg:`pull
5869 to add those changes to the repository, you should use :hg:`pull
5884 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5870 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5885
5871
5886 If SOURCE is omitted, the 'default' path will be used.
5872 If SOURCE is omitted, the 'default' path will be used.
5887 See :hg:`help urls` for more information.
5873 See :hg:`help urls` for more information.
5888
5874
5889 Specifying bookmark as ``.`` is equivalent to specifying the active
5875 Specifying bookmark as ``.`` is equivalent to specifying the active
5890 bookmark's name.
5876 bookmark's name.
5891
5877
5892 Returns 0 on success, 1 if an update had unresolved files.
5878 Returns 0 on success, 1 if an update had unresolved files.
5893 """
5879 """
5894 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5880 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5895 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5881 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5896 other = hg.peer(repo, opts, source)
5882 other = hg.peer(repo, opts, source)
5897 try:
5883 try:
5898 revs, checkout = hg.addbranchrevs(repo, other, branches,
5884 revs, checkout = hg.addbranchrevs(repo, other, branches,
5899 opts.get('rev'))
5885 opts.get('rev'))
5900
5886
5901
5887
5902 pullopargs = {}
5888 pullopargs = {}
5903 if opts.get('bookmark'):
5889 if opts.get('bookmark'):
5904 if not revs:
5890 if not revs:
5905 revs = []
5891 revs = []
5906 # The list of bookmark used here is not the one used to actually
5892 # The list of bookmark used here is not the one used to actually
5907 # update the bookmark name. This can result in the revision pulled
5893 # update the bookmark name. This can result in the revision pulled
5908 # not ending up with the name of the bookmark because of a race
5894 # not ending up with the name of the bookmark because of a race
5909 # condition on the server. (See issue 4689 for details)
5895 # condition on the server. (See issue 4689 for details)
5910 remotebookmarks = other.listkeys('bookmarks')
5896 remotebookmarks = other.listkeys('bookmarks')
5911 pullopargs['remotebookmarks'] = remotebookmarks
5897 pullopargs['remotebookmarks'] = remotebookmarks
5912 for b in opts['bookmark']:
5898 for b in opts['bookmark']:
5913 b = repo._bookmarks.expandname(b)
5899 b = repo._bookmarks.expandname(b)
5914 if b not in remotebookmarks:
5900 if b not in remotebookmarks:
5915 raise error.Abort(_('remote bookmark %s not found!') % b)
5901 raise error.Abort(_('remote bookmark %s not found!') % b)
5916 revs.append(remotebookmarks[b])
5902 revs.append(remotebookmarks[b])
5917
5903
5918 if revs:
5904 if revs:
5919 try:
5905 try:
5920 # When 'rev' is a bookmark name, we cannot guarantee that it
5906 # When 'rev' is a bookmark name, we cannot guarantee that it
5921 # will be updated with that name because of a race condition
5907 # will be updated with that name because of a race condition
5922 # server side. (See issue 4689 for details)
5908 # server side. (See issue 4689 for details)
5923 oldrevs = revs
5909 oldrevs = revs
5924 revs = [] # actually, nodes
5910 revs = [] # actually, nodes
5925 for r in oldrevs:
5911 for r in oldrevs:
5926 node = other.lookup(r)
5912 node = other.lookup(r)
5927 revs.append(node)
5913 revs.append(node)
5928 if r == checkout:
5914 if r == checkout:
5929 checkout = node
5915 checkout = node
5930 except error.CapabilityError:
5916 except error.CapabilityError:
5931 err = _("other repository doesn't support revision lookup, "
5917 err = _("other repository doesn't support revision lookup, "
5932 "so a rev cannot be specified.")
5918 "so a rev cannot be specified.")
5933 raise error.Abort(err)
5919 raise error.Abort(err)
5934
5920
5935 pullopargs.update(opts.get('opargs', {}))
5921 pullopargs.update(opts.get('opargs', {}))
5936 modheads = exchange.pull(repo, other, heads=revs,
5922 modheads = exchange.pull(repo, other, heads=revs,
5937 force=opts.get('force'),
5923 force=opts.get('force'),
5938 bookmarks=opts.get('bookmark', ()),
5924 bookmarks=opts.get('bookmark', ()),
5939 opargs=pullopargs).cgresult
5925 opargs=pullopargs).cgresult
5940
5926
5941 # brev is a name, which might be a bookmark to be activated at
5927 # brev is a name, which might be a bookmark to be activated at
5942 # the end of the update. In other words, it is an explicit
5928 # the end of the update. In other words, it is an explicit
5943 # destination of the update
5929 # destination of the update
5944 brev = None
5930 brev = None
5945
5931
5946 if checkout:
5932 if checkout:
5947 checkout = str(repo.changelog.rev(checkout))
5933 checkout = str(repo.changelog.rev(checkout))
5948
5934
5949 # order below depends on implementation of
5935 # order below depends on implementation of
5950 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5936 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5951 # because 'checkout' is determined without it.
5937 # because 'checkout' is determined without it.
5952 if opts.get('rev'):
5938 if opts.get('rev'):
5953 brev = opts['rev'][0]
5939 brev = opts['rev'][0]
5954 elif opts.get('branch'):
5940 elif opts.get('branch'):
5955 brev = opts['branch'][0]
5941 brev = opts['branch'][0]
5956 else:
5942 else:
5957 brev = branches[0]
5943 brev = branches[0]
5958 repo._subtoppath = source
5944 repo._subtoppath = source
5959 try:
5945 try:
5960 ret = postincoming(ui, repo, modheads, opts.get('update'),
5946 ret = postincoming(ui, repo, modheads, opts.get('update'),
5961 checkout, brev)
5947 checkout, brev)
5962
5948
5963 finally:
5949 finally:
5964 del repo._subtoppath
5950 del repo._subtoppath
5965
5951
5966 finally:
5952 finally:
5967 other.close()
5953 other.close()
5968 return ret
5954 return ret
5969
5955
5970 @command('^push',
5956 @command('^push',
5971 [('f', 'force', None, _('force push')),
5957 [('f', 'force', None, _('force push')),
5972 ('r', 'rev', [],
5958 ('r', 'rev', [],
5973 _('a changeset intended to be included in the destination'),
5959 _('a changeset intended to be included in the destination'),
5974 _('REV')),
5960 _('REV')),
5975 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5961 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5976 ('b', 'branch', [],
5962 ('b', 'branch', [],
5977 _('a specific branch you would like to push'), _('BRANCH')),
5963 _('a specific branch you would like to push'), _('BRANCH')),
5978 ('', 'new-branch', False, _('allow pushing a new branch')),
5964 ('', 'new-branch', False, _('allow pushing a new branch')),
5979 ] + remoteopts,
5965 ] + remoteopts,
5980 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5966 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5981 def push(ui, repo, dest=None, **opts):
5967 def push(ui, repo, dest=None, **opts):
5982 """push changes to the specified destination
5968 """push changes to the specified destination
5983
5969
5984 Push changesets from the local repository to the specified
5970 Push changesets from the local repository to the specified
5985 destination.
5971 destination.
5986
5972
5987 This operation is symmetrical to pull: it is identical to a pull
5973 This operation is symmetrical to pull: it is identical to a pull
5988 in the destination repository from the current one.
5974 in the destination repository from the current one.
5989
5975
5990 By default, push will not allow creation of new heads at the
5976 By default, push will not allow creation of new heads at the
5991 destination, since multiple heads would make it unclear which head
5977 destination, since multiple heads would make it unclear which head
5992 to use. In this situation, it is recommended to pull and merge
5978 to use. In this situation, it is recommended to pull and merge
5993 before pushing.
5979 before pushing.
5994
5980
5995 Use --new-branch if you want to allow push to create a new named
5981 Use --new-branch if you want to allow push to create a new named
5996 branch that is not present at the destination. This allows you to
5982 branch that is not present at the destination. This allows you to
5997 only create a new branch without forcing other changes.
5983 only create a new branch without forcing other changes.
5998
5984
5999 .. note::
5985 .. note::
6000
5986
6001 Extra care should be taken with the -f/--force option,
5987 Extra care should be taken with the -f/--force option,
6002 which will push all new heads on all branches, an action which will
5988 which will push all new heads on all branches, an action which will
6003 almost always cause confusion for collaborators.
5989 almost always cause confusion for collaborators.
6004
5990
6005 If -r/--rev is used, the specified revision and all its ancestors
5991 If -r/--rev is used, the specified revision and all its ancestors
6006 will be pushed to the remote repository.
5992 will be pushed to the remote repository.
6007
5993
6008 If -B/--bookmark is used, the specified bookmarked revision, its
5994 If -B/--bookmark is used, the specified bookmarked revision, its
6009 ancestors, and the bookmark will be pushed to the remote
5995 ancestors, and the bookmark will be pushed to the remote
6010 repository. Specifying ``.`` is equivalent to specifying the active
5996 repository. Specifying ``.`` is equivalent to specifying the active
6011 bookmark's name.
5997 bookmark's name.
6012
5998
6013 Please see :hg:`help urls` for important details about ``ssh://``
5999 Please see :hg:`help urls` for important details about ``ssh://``
6014 URLs. If DESTINATION is omitted, a default path will be used.
6000 URLs. If DESTINATION is omitted, a default path will be used.
6015
6001
6016 Returns 0 if push was successful, 1 if nothing to push.
6002 Returns 0 if push was successful, 1 if nothing to push.
6017 """
6003 """
6018
6004
6019 if opts.get('bookmark'):
6005 if opts.get('bookmark'):
6020 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
6006 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
6021 for b in opts['bookmark']:
6007 for b in opts['bookmark']:
6022 # translate -B options to -r so changesets get pushed
6008 # translate -B options to -r so changesets get pushed
6023 b = repo._bookmarks.expandname(b)
6009 b = repo._bookmarks.expandname(b)
6024 if b in repo._bookmarks:
6010 if b in repo._bookmarks:
6025 opts.setdefault('rev', []).append(b)
6011 opts.setdefault('rev', []).append(b)
6026 else:
6012 else:
6027 # if we try to push a deleted bookmark, translate it to null
6013 # if we try to push a deleted bookmark, translate it to null
6028 # this lets simultaneous -r, -b options continue working
6014 # this lets simultaneous -r, -b options continue working
6029 opts.setdefault('rev', []).append("null")
6015 opts.setdefault('rev', []).append("null")
6030
6016
6031 path = ui.paths.getpath(dest, default=('default-push', 'default'))
6017 path = ui.paths.getpath(dest, default=('default-push', 'default'))
6032 if not path:
6018 if not path:
6033 raise error.Abort(_('default repository not configured!'),
6019 raise error.Abort(_('default repository not configured!'),
6034 hint=_("see 'hg help config.paths'"))
6020 hint=_("see 'hg help config.paths'"))
6035 dest = path.pushloc or path.loc
6021 dest = path.pushloc or path.loc
6036 branches = (path.branch, opts.get('branch') or [])
6022 branches = (path.branch, opts.get('branch') or [])
6037 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
6023 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
6038 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
6024 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
6039 other = hg.peer(repo, opts, dest)
6025 other = hg.peer(repo, opts, dest)
6040
6026
6041 if revs:
6027 if revs:
6042 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
6028 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
6043 if not revs:
6029 if not revs:
6044 raise error.Abort(_("specified revisions evaluate to an empty set"),
6030 raise error.Abort(_("specified revisions evaluate to an empty set"),
6045 hint=_("use different revision arguments"))
6031 hint=_("use different revision arguments"))
6046 elif path.pushrev:
6032 elif path.pushrev:
6047 # It doesn't make any sense to specify ancestor revisions. So limit
6033 # It doesn't make any sense to specify ancestor revisions. So limit
6048 # to DAG heads to make discovery simpler.
6034 # to DAG heads to make discovery simpler.
6049 expr = revset.formatspec('heads(%r)', path.pushrev)
6035 expr = revset.formatspec('heads(%r)', path.pushrev)
6050 revs = scmutil.revrange(repo, [expr])
6036 revs = scmutil.revrange(repo, [expr])
6051 revs = [repo[rev].node() for rev in revs]
6037 revs = [repo[rev].node() for rev in revs]
6052 if not revs:
6038 if not revs:
6053 raise error.Abort(_('default push revset for path evaluates to an '
6039 raise error.Abort(_('default push revset for path evaluates to an '
6054 'empty set'))
6040 'empty set'))
6055
6041
6056 repo._subtoppath = dest
6042 repo._subtoppath = dest
6057 try:
6043 try:
6058 # push subrepos depth-first for coherent ordering
6044 # push subrepos depth-first for coherent ordering
6059 c = repo['']
6045 c = repo['']
6060 subs = c.substate # only repos that are committed
6046 subs = c.substate # only repos that are committed
6061 for s in sorted(subs):
6047 for s in sorted(subs):
6062 result = c.sub(s).push(opts)
6048 result = c.sub(s).push(opts)
6063 if result == 0:
6049 if result == 0:
6064 return not result
6050 return not result
6065 finally:
6051 finally:
6066 del repo._subtoppath
6052 del repo._subtoppath
6067 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
6053 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
6068 newbranch=opts.get('new_branch'),
6054 newbranch=opts.get('new_branch'),
6069 bookmarks=opts.get('bookmark', ()),
6055 bookmarks=opts.get('bookmark', ()),
6070 opargs=opts.get('opargs'))
6056 opargs=opts.get('opargs'))
6071
6057
6072 result = not pushop.cgresult
6058 result = not pushop.cgresult
6073
6059
6074 if pushop.bkresult is not None:
6060 if pushop.bkresult is not None:
6075 if pushop.bkresult == 2:
6061 if pushop.bkresult == 2:
6076 result = 2
6062 result = 2
6077 elif not result and pushop.bkresult:
6063 elif not result and pushop.bkresult:
6078 result = 2
6064 result = 2
6079
6065
6080 return result
6066 return result
6081
6067
6082 @command('recover', [])
6068 @command('recover', [])
6083 def recover(ui, repo):
6069 def recover(ui, repo):
6084 """roll back an interrupted transaction
6070 """roll back an interrupted transaction
6085
6071
6086 Recover from an interrupted commit or pull.
6072 Recover from an interrupted commit or pull.
6087
6073
6088 This command tries to fix the repository status after an
6074 This command tries to fix the repository status after an
6089 interrupted operation. It should only be necessary when Mercurial
6075 interrupted operation. It should only be necessary when Mercurial
6090 suggests it.
6076 suggests it.
6091
6077
6092 Returns 0 if successful, 1 if nothing to recover or verify fails.
6078 Returns 0 if successful, 1 if nothing to recover or verify fails.
6093 """
6079 """
6094 if repo.recover():
6080 if repo.recover():
6095 return hg.verify(repo)
6081 return hg.verify(repo)
6096 return 1
6082 return 1
6097
6083
6098 @command('^remove|rm',
6084 @command('^remove|rm',
6099 [('A', 'after', None, _('record delete for missing files')),
6085 [('A', 'after', None, _('record delete for missing files')),
6100 ('f', 'force', None,
6086 ('f', 'force', None,
6101 _('forget added files, delete modified files')),
6087 _('forget added files, delete modified files')),
6102 ] + subrepoopts + walkopts,
6088 ] + subrepoopts + walkopts,
6103 _('[OPTION]... FILE...'),
6089 _('[OPTION]... FILE...'),
6104 inferrepo=True)
6090 inferrepo=True)
6105 def remove(ui, repo, *pats, **opts):
6091 def remove(ui, repo, *pats, **opts):
6106 """remove the specified files on the next commit
6092 """remove the specified files on the next commit
6107
6093
6108 Schedule the indicated files for removal from the current branch.
6094 Schedule the indicated files for removal from the current branch.
6109
6095
6110 This command schedules the files to be removed at the next commit.
6096 This command schedules the files to be removed at the next commit.
6111 To undo a remove before that, see :hg:`revert`. To undo added
6097 To undo a remove before that, see :hg:`revert`. To undo added
6112 files, see :hg:`forget`.
6098 files, see :hg:`forget`.
6113
6099
6114 .. container:: verbose
6100 .. container:: verbose
6115
6101
6116 -A/--after can be used to remove only files that have already
6102 -A/--after can be used to remove only files that have already
6117 been deleted, -f/--force can be used to force deletion, and -Af
6103 been deleted, -f/--force can be used to force deletion, and -Af
6118 can be used to remove files from the next revision without
6104 can be used to remove files from the next revision without
6119 deleting them from the working directory.
6105 deleting them from the working directory.
6120
6106
6121 The following table details the behavior of remove for different
6107 The following table details the behavior of remove for different
6122 file states (columns) and option combinations (rows). The file
6108 file states (columns) and option combinations (rows). The file
6123 states are Added [A], Clean [C], Modified [M] and Missing [!]
6109 states are Added [A], Clean [C], Modified [M] and Missing [!]
6124 (as reported by :hg:`status`). The actions are Warn, Remove
6110 (as reported by :hg:`status`). The actions are Warn, Remove
6125 (from branch) and Delete (from disk):
6111 (from branch) and Delete (from disk):
6126
6112
6127 ========= == == == ==
6113 ========= == == == ==
6128 opt/state A C M !
6114 opt/state A C M !
6129 ========= == == == ==
6115 ========= == == == ==
6130 none W RD W R
6116 none W RD W R
6131 -f R RD RD R
6117 -f R RD RD R
6132 -A W W W R
6118 -A W W W R
6133 -Af R R R R
6119 -Af R R R R
6134 ========= == == == ==
6120 ========= == == == ==
6135
6121
6136 .. note::
6122 .. note::
6137
6123
6138 :hg:`remove` never deletes files in Added [A] state from the
6124 :hg:`remove` never deletes files in Added [A] state from the
6139 working directory, not even if ``--force`` is specified.
6125 working directory, not even if ``--force`` is specified.
6140
6126
6141 Returns 0 on success, 1 if any warnings encountered.
6127 Returns 0 on success, 1 if any warnings encountered.
6142 """
6128 """
6143
6129
6144 after, force = opts.get('after'), opts.get('force')
6130 after, force = opts.get('after'), opts.get('force')
6145 if not pats and not after:
6131 if not pats and not after:
6146 raise error.Abort(_('no files specified'))
6132 raise error.Abort(_('no files specified'))
6147
6133
6148 m = scmutil.match(repo[None], pats, opts)
6134 m = scmutil.match(repo[None], pats, opts)
6149 subrepos = opts.get('subrepos')
6135 subrepos = opts.get('subrepos')
6150 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6136 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6151
6137
6152 @command('rename|move|mv',
6138 @command('rename|move|mv',
6153 [('A', 'after', None, _('record a rename that has already occurred')),
6139 [('A', 'after', None, _('record a rename that has already occurred')),
6154 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6140 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6155 ] + walkopts + dryrunopts,
6141 ] + walkopts + dryrunopts,
6156 _('[OPTION]... SOURCE... DEST'))
6142 _('[OPTION]... SOURCE... DEST'))
6157 def rename(ui, repo, *pats, **opts):
6143 def rename(ui, repo, *pats, **opts):
6158 """rename files; equivalent of copy + remove
6144 """rename files; equivalent of copy + remove
6159
6145
6160 Mark dest as copies of sources; mark sources for deletion. If dest
6146 Mark dest as copies of sources; mark sources for deletion. If dest
6161 is a directory, copies are put in that directory. If dest is a
6147 is a directory, copies are put in that directory. If dest is a
6162 file, there can only be one source.
6148 file, there can only be one source.
6163
6149
6164 By default, this command copies the contents of files as they
6150 By default, this command copies the contents of files as they
6165 exist in the working directory. If invoked with -A/--after, the
6151 exist in the working directory. If invoked with -A/--after, the
6166 operation is recorded, but no copying is performed.
6152 operation is recorded, but no copying is performed.
6167
6153
6168 This command takes effect at the next commit. To undo a rename
6154 This command takes effect at the next commit. To undo a rename
6169 before that, see :hg:`revert`.
6155 before that, see :hg:`revert`.
6170
6156
6171 Returns 0 on success, 1 if errors are encountered.
6157 Returns 0 on success, 1 if errors are encountered.
6172 """
6158 """
6173 with repo.wlock(False):
6159 with repo.wlock(False):
6174 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6160 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6175
6161
6176 @command('resolve',
6162 @command('resolve',
6177 [('a', 'all', None, _('select all unresolved files')),
6163 [('a', 'all', None, _('select all unresolved files')),
6178 ('l', 'list', None, _('list state of files needing merge')),
6164 ('l', 'list', None, _('list state of files needing merge')),
6179 ('m', 'mark', None, _('mark files as resolved')),
6165 ('m', 'mark', None, _('mark files as resolved')),
6180 ('u', 'unmark', None, _('mark files as unresolved')),
6166 ('u', 'unmark', None, _('mark files as unresolved')),
6181 ('n', 'no-status', None, _('hide status prefix'))]
6167 ('n', 'no-status', None, _('hide status prefix'))]
6182 + mergetoolopts + walkopts + formatteropts,
6168 + mergetoolopts + walkopts + formatteropts,
6183 _('[OPTION]... [FILE]...'),
6169 _('[OPTION]... [FILE]...'),
6184 inferrepo=True)
6170 inferrepo=True)
6185 def resolve(ui, repo, *pats, **opts):
6171 def resolve(ui, repo, *pats, **opts):
6186 """redo merges or set/view the merge status of files
6172 """redo merges or set/view the merge status of files
6187
6173
6188 Merges with unresolved conflicts are often the result of
6174 Merges with unresolved conflicts are often the result of
6189 non-interactive merging using the ``internal:merge`` configuration
6175 non-interactive merging using the ``internal:merge`` configuration
6190 setting, or a command-line merge tool like ``diff3``. The resolve
6176 setting, or a command-line merge tool like ``diff3``. The resolve
6191 command is used to manage the files involved in a merge, after
6177 command is used to manage the files involved in a merge, after
6192 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6178 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6193 working directory must have two parents). See :hg:`help
6179 working directory must have two parents). See :hg:`help
6194 merge-tools` for information on configuring merge tools.
6180 merge-tools` for information on configuring merge tools.
6195
6181
6196 The resolve command can be used in the following ways:
6182 The resolve command can be used in the following ways:
6197
6183
6198 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6184 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6199 files, discarding any previous merge attempts. Re-merging is not
6185 files, discarding any previous merge attempts. Re-merging is not
6200 performed for files already marked as resolved. Use ``--all/-a``
6186 performed for files already marked as resolved. Use ``--all/-a``
6201 to select all unresolved files. ``--tool`` can be used to specify
6187 to select all unresolved files. ``--tool`` can be used to specify
6202 the merge tool used for the given files. It overrides the HGMERGE
6188 the merge tool used for the given files. It overrides the HGMERGE
6203 environment variable and your configuration files. Previous file
6189 environment variable and your configuration files. Previous file
6204 contents are saved with a ``.orig`` suffix.
6190 contents are saved with a ``.orig`` suffix.
6205
6191
6206 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6192 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6207 (e.g. after having manually fixed-up the files). The default is
6193 (e.g. after having manually fixed-up the files). The default is
6208 to mark all unresolved files.
6194 to mark all unresolved files.
6209
6195
6210 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6196 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6211 default is to mark all resolved files.
6197 default is to mark all resolved files.
6212
6198
6213 - :hg:`resolve -l`: list files which had or still have conflicts.
6199 - :hg:`resolve -l`: list files which had or still have conflicts.
6214 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6200 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6215
6201
6216 .. note::
6202 .. note::
6217
6203
6218 Mercurial will not let you commit files with unresolved merge
6204 Mercurial will not let you commit files with unresolved merge
6219 conflicts. You must use :hg:`resolve -m ...` before you can
6205 conflicts. You must use :hg:`resolve -m ...` before you can
6220 commit after a conflicting merge.
6206 commit after a conflicting merge.
6221
6207
6222 Returns 0 on success, 1 if any files fail a resolve attempt.
6208 Returns 0 on success, 1 if any files fail a resolve attempt.
6223 """
6209 """
6224
6210
6225 flaglist = 'all mark unmark list no_status'.split()
6211 flaglist = 'all mark unmark list no_status'.split()
6226 all, mark, unmark, show, nostatus = \
6212 all, mark, unmark, show, nostatus = \
6227 [opts.get(o) for o in flaglist]
6213 [opts.get(o) for o in flaglist]
6228
6214
6229 if (show and (mark or unmark)) or (mark and unmark):
6215 if (show and (mark or unmark)) or (mark and unmark):
6230 raise error.Abort(_("too many options specified"))
6216 raise error.Abort(_("too many options specified"))
6231 if pats and all:
6217 if pats and all:
6232 raise error.Abort(_("can't specify --all and patterns"))
6218 raise error.Abort(_("can't specify --all and patterns"))
6233 if not (all or pats or show or mark or unmark):
6219 if not (all or pats or show or mark or unmark):
6234 raise error.Abort(_('no files or directories specified'),
6220 raise error.Abort(_('no files or directories specified'),
6235 hint=('use --all to re-merge all unresolved files'))
6221 hint=('use --all to re-merge all unresolved files'))
6236
6222
6237 if show:
6223 if show:
6238 fm = ui.formatter('resolve', opts)
6224 fm = ui.formatter('resolve', opts)
6239 ms = mergemod.mergestate.read(repo)
6225 ms = mergemod.mergestate.read(repo)
6240 m = scmutil.match(repo[None], pats, opts)
6226 m = scmutil.match(repo[None], pats, opts)
6241 for f in ms:
6227 for f in ms:
6242 if not m(f):
6228 if not m(f):
6243 continue
6229 continue
6244 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6230 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6245 'd': 'driverresolved'}[ms[f]]
6231 'd': 'driverresolved'}[ms[f]]
6246 fm.startitem()
6232 fm.startitem()
6247 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6233 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6248 fm.write('path', '%s\n', f, label=l)
6234 fm.write('path', '%s\n', f, label=l)
6249 fm.end()
6235 fm.end()
6250 return 0
6236 return 0
6251
6237
6252 with repo.wlock():
6238 with repo.wlock():
6253 ms = mergemod.mergestate.read(repo)
6239 ms = mergemod.mergestate.read(repo)
6254
6240
6255 if not (ms.active() or repo.dirstate.p2() != nullid):
6241 if not (ms.active() or repo.dirstate.p2() != nullid):
6256 raise error.Abort(
6242 raise error.Abort(
6257 _('resolve command not applicable when not merging'))
6243 _('resolve command not applicable when not merging'))
6258
6244
6259 wctx = repo[None]
6245 wctx = repo[None]
6260
6246
6261 if ms.mergedriver and ms.mdstate() == 'u':
6247 if ms.mergedriver and ms.mdstate() == 'u':
6262 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6248 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6263 ms.commit()
6249 ms.commit()
6264 # allow mark and unmark to go through
6250 # allow mark and unmark to go through
6265 if not mark and not unmark and not proceed:
6251 if not mark and not unmark and not proceed:
6266 return 1
6252 return 1
6267
6253
6268 m = scmutil.match(wctx, pats, opts)
6254 m = scmutil.match(wctx, pats, opts)
6269 ret = 0
6255 ret = 0
6270 didwork = False
6256 didwork = False
6271 runconclude = False
6257 runconclude = False
6272
6258
6273 tocomplete = []
6259 tocomplete = []
6274 for f in ms:
6260 for f in ms:
6275 if not m(f):
6261 if not m(f):
6276 continue
6262 continue
6277
6263
6278 didwork = True
6264 didwork = True
6279
6265
6280 # don't let driver-resolved files be marked, and run the conclude
6266 # don't let driver-resolved files be marked, and run the conclude
6281 # step if asked to resolve
6267 # step if asked to resolve
6282 if ms[f] == "d":
6268 if ms[f] == "d":
6283 exact = m.exact(f)
6269 exact = m.exact(f)
6284 if mark:
6270 if mark:
6285 if exact:
6271 if exact:
6286 ui.warn(_('not marking %s as it is driver-resolved\n')
6272 ui.warn(_('not marking %s as it is driver-resolved\n')
6287 % f)
6273 % f)
6288 elif unmark:
6274 elif unmark:
6289 if exact:
6275 if exact:
6290 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6276 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6291 % f)
6277 % f)
6292 else:
6278 else:
6293 runconclude = True
6279 runconclude = True
6294 continue
6280 continue
6295
6281
6296 if mark:
6282 if mark:
6297 ms.mark(f, "r")
6283 ms.mark(f, "r")
6298 elif unmark:
6284 elif unmark:
6299 ms.mark(f, "u")
6285 ms.mark(f, "u")
6300 else:
6286 else:
6301 # backup pre-resolve (merge uses .orig for its own purposes)
6287 # backup pre-resolve (merge uses .orig for its own purposes)
6302 a = repo.wjoin(f)
6288 a = repo.wjoin(f)
6303 try:
6289 try:
6304 util.copyfile(a, a + ".resolve")
6290 util.copyfile(a, a + ".resolve")
6305 except (IOError, OSError) as inst:
6291 except (IOError, OSError) as inst:
6306 if inst.errno != errno.ENOENT:
6292 if inst.errno != errno.ENOENT:
6307 raise
6293 raise
6308
6294
6309 try:
6295 try:
6310 # preresolve file
6296 # preresolve file
6311 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6297 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6312 'resolve')
6298 'resolve')
6313 complete, r = ms.preresolve(f, wctx)
6299 complete, r = ms.preresolve(f, wctx)
6314 if not complete:
6300 if not complete:
6315 tocomplete.append(f)
6301 tocomplete.append(f)
6316 elif r:
6302 elif r:
6317 ret = 1
6303 ret = 1
6318 finally:
6304 finally:
6319 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6305 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6320 ms.commit()
6306 ms.commit()
6321
6307
6322 # replace filemerge's .orig file with our resolve file, but only
6308 # replace filemerge's .orig file with our resolve file, but only
6323 # for merges that are complete
6309 # for merges that are complete
6324 if complete:
6310 if complete:
6325 try:
6311 try:
6326 util.rename(a + ".resolve",
6312 util.rename(a + ".resolve",
6327 scmutil.origpath(ui, repo, a))
6313 scmutil.origpath(ui, repo, a))
6328 except OSError as inst:
6314 except OSError as inst:
6329 if inst.errno != errno.ENOENT:
6315 if inst.errno != errno.ENOENT:
6330 raise
6316 raise
6331
6317
6332 for f in tocomplete:
6318 for f in tocomplete:
6333 try:
6319 try:
6334 # resolve file
6320 # resolve file
6335 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6321 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6336 'resolve')
6322 'resolve')
6337 r = ms.resolve(f, wctx)
6323 r = ms.resolve(f, wctx)
6338 if r:
6324 if r:
6339 ret = 1
6325 ret = 1
6340 finally:
6326 finally:
6341 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6327 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6342 ms.commit()
6328 ms.commit()
6343
6329
6344 # replace filemerge's .orig file with our resolve file
6330 # replace filemerge's .orig file with our resolve file
6345 a = repo.wjoin(f)
6331 a = repo.wjoin(f)
6346 try:
6332 try:
6347 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6333 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6348 except OSError as inst:
6334 except OSError as inst:
6349 if inst.errno != errno.ENOENT:
6335 if inst.errno != errno.ENOENT:
6350 raise
6336 raise
6351
6337
6352 ms.commit()
6338 ms.commit()
6353 ms.recordactions()
6339 ms.recordactions()
6354
6340
6355 if not didwork and pats:
6341 if not didwork and pats:
6356 hint = None
6342 hint = None
6357 if not any([p for p in pats if p.find(':') >= 0]):
6343 if not any([p for p in pats if p.find(':') >= 0]):
6358 pats = ['path:%s' % p for p in pats]
6344 pats = ['path:%s' % p for p in pats]
6359 m = scmutil.match(wctx, pats, opts)
6345 m = scmutil.match(wctx, pats, opts)
6360 for f in ms:
6346 for f in ms:
6361 if not m(f):
6347 if not m(f):
6362 continue
6348 continue
6363 flags = ''.join(['-%s ' % o[0] for o in flaglist
6349 flags = ''.join(['-%s ' % o[0] for o in flaglist
6364 if opts.get(o)])
6350 if opts.get(o)])
6365 hint = _("(try: hg resolve %s%s)\n") % (
6351 hint = _("(try: hg resolve %s%s)\n") % (
6366 flags,
6352 flags,
6367 ' '.join(pats))
6353 ' '.join(pats))
6368 break
6354 break
6369 ui.warn(_("arguments do not match paths that need resolving\n"))
6355 ui.warn(_("arguments do not match paths that need resolving\n"))
6370 if hint:
6356 if hint:
6371 ui.warn(hint)
6357 ui.warn(hint)
6372 elif ms.mergedriver and ms.mdstate() != 's':
6358 elif ms.mergedriver and ms.mdstate() != 's':
6373 # run conclude step when either a driver-resolved file is requested
6359 # run conclude step when either a driver-resolved file is requested
6374 # or there are no driver-resolved files
6360 # or there are no driver-resolved files
6375 # we can't use 'ret' to determine whether any files are unresolved
6361 # we can't use 'ret' to determine whether any files are unresolved
6376 # because we might not have tried to resolve some
6362 # because we might not have tried to resolve some
6377 if ((runconclude or not list(ms.driverresolved()))
6363 if ((runconclude or not list(ms.driverresolved()))
6378 and not list(ms.unresolved())):
6364 and not list(ms.unresolved())):
6379 proceed = mergemod.driverconclude(repo, ms, wctx)
6365 proceed = mergemod.driverconclude(repo, ms, wctx)
6380 ms.commit()
6366 ms.commit()
6381 if not proceed:
6367 if not proceed:
6382 return 1
6368 return 1
6383
6369
6384 # Nudge users into finishing an unfinished operation
6370 # Nudge users into finishing an unfinished operation
6385 unresolvedf = list(ms.unresolved())
6371 unresolvedf = list(ms.unresolved())
6386 driverresolvedf = list(ms.driverresolved())
6372 driverresolvedf = list(ms.driverresolved())
6387 if not unresolvedf and not driverresolvedf:
6373 if not unresolvedf and not driverresolvedf:
6388 ui.status(_('(no more unresolved files)\n'))
6374 ui.status(_('(no more unresolved files)\n'))
6389 cmdutil.checkafterresolved(repo)
6375 cmdutil.checkafterresolved(repo)
6390 elif not unresolvedf:
6376 elif not unresolvedf:
6391 ui.status(_('(no more unresolved files -- '
6377 ui.status(_('(no more unresolved files -- '
6392 'run "hg resolve --all" to conclude)\n'))
6378 'run "hg resolve --all" to conclude)\n'))
6393
6379
6394 return ret
6380 return ret
6395
6381
6396 @command('revert',
6382 @command('revert',
6397 [('a', 'all', None, _('revert all changes when no arguments given')),
6383 [('a', 'all', None, _('revert all changes when no arguments given')),
6398 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6384 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6399 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6385 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6400 ('C', 'no-backup', None, _('do not save backup copies of files')),
6386 ('C', 'no-backup', None, _('do not save backup copies of files')),
6401 ('i', 'interactive', None,
6387 ('i', 'interactive', None,
6402 _('interactively select the changes (EXPERIMENTAL)')),
6388 _('interactively select the changes (EXPERIMENTAL)')),
6403 ] + walkopts + dryrunopts,
6389 ] + walkopts + dryrunopts,
6404 _('[OPTION]... [-r REV] [NAME]...'))
6390 _('[OPTION]... [-r REV] [NAME]...'))
6405 def revert(ui, repo, *pats, **opts):
6391 def revert(ui, repo, *pats, **opts):
6406 """restore files to their checkout state
6392 """restore files to their checkout state
6407
6393
6408 .. note::
6394 .. note::
6409
6395
6410 To check out earlier revisions, you should use :hg:`update REV`.
6396 To check out earlier revisions, you should use :hg:`update REV`.
6411 To cancel an uncommitted merge (and lose your changes),
6397 To cancel an uncommitted merge (and lose your changes),
6412 use :hg:`update --clean .`.
6398 use :hg:`update --clean .`.
6413
6399
6414 With no revision specified, revert the specified files or directories
6400 With no revision specified, revert the specified files or directories
6415 to the contents they had in the parent of the working directory.
6401 to the contents they had in the parent of the working directory.
6416 This restores the contents of files to an unmodified
6402 This restores the contents of files to an unmodified
6417 state and unschedules adds, removes, copies, and renames. If the
6403 state and unschedules adds, removes, copies, and renames. If the
6418 working directory has two parents, you must explicitly specify a
6404 working directory has two parents, you must explicitly specify a
6419 revision.
6405 revision.
6420
6406
6421 Using the -r/--rev or -d/--date options, revert the given files or
6407 Using the -r/--rev or -d/--date options, revert the given files or
6422 directories to their states as of a specific revision. Because
6408 directories to their states as of a specific revision. Because
6423 revert does not change the working directory parents, this will
6409 revert does not change the working directory parents, this will
6424 cause these files to appear modified. This can be helpful to "back
6410 cause these files to appear modified. This can be helpful to "back
6425 out" some or all of an earlier change. See :hg:`backout` for a
6411 out" some or all of an earlier change. See :hg:`backout` for a
6426 related method.
6412 related method.
6427
6413
6428 Modified files are saved with a .orig suffix before reverting.
6414 Modified files are saved with a .orig suffix before reverting.
6429 To disable these backups, use --no-backup. It is possible to store
6415 To disable these backups, use --no-backup. It is possible to store
6430 the backup files in a custom directory relative to the root of the
6416 the backup files in a custom directory relative to the root of the
6431 repository by setting the ``ui.origbackuppath`` configuration
6417 repository by setting the ``ui.origbackuppath`` configuration
6432 option.
6418 option.
6433
6419
6434 See :hg:`help dates` for a list of formats valid for -d/--date.
6420 See :hg:`help dates` for a list of formats valid for -d/--date.
6435
6421
6436 See :hg:`help backout` for a way to reverse the effect of an
6422 See :hg:`help backout` for a way to reverse the effect of an
6437 earlier changeset.
6423 earlier changeset.
6438
6424
6439 Returns 0 on success.
6425 Returns 0 on success.
6440 """
6426 """
6441
6427
6442 if opts.get("date"):
6428 if opts.get("date"):
6443 if opts.get("rev"):
6429 if opts.get("rev"):
6444 raise error.Abort(_("you can't specify a revision and a date"))
6430 raise error.Abort(_("you can't specify a revision and a date"))
6445 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6431 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6446
6432
6447 parent, p2 = repo.dirstate.parents()
6433 parent, p2 = repo.dirstate.parents()
6448 if not opts.get('rev') and p2 != nullid:
6434 if not opts.get('rev') and p2 != nullid:
6449 # revert after merge is a trap for new users (issue2915)
6435 # revert after merge is a trap for new users (issue2915)
6450 raise error.Abort(_('uncommitted merge with no revision specified'),
6436 raise error.Abort(_('uncommitted merge with no revision specified'),
6451 hint=_("use 'hg update' or see 'hg help revert'"))
6437 hint=_("use 'hg update' or see 'hg help revert'"))
6452
6438
6453 ctx = scmutil.revsingle(repo, opts.get('rev'))
6439 ctx = scmutil.revsingle(repo, opts.get('rev'))
6454
6440
6455 if (not (pats or opts.get('include') or opts.get('exclude') or
6441 if (not (pats or opts.get('include') or opts.get('exclude') or
6456 opts.get('all') or opts.get('interactive'))):
6442 opts.get('all') or opts.get('interactive'))):
6457 msg = _("no files or directories specified")
6443 msg = _("no files or directories specified")
6458 if p2 != nullid:
6444 if p2 != nullid:
6459 hint = _("uncommitted merge, use --all to discard all changes,"
6445 hint = _("uncommitted merge, use --all to discard all changes,"
6460 " or 'hg update -C .' to abort the merge")
6446 " or 'hg update -C .' to abort the merge")
6461 raise error.Abort(msg, hint=hint)
6447 raise error.Abort(msg, hint=hint)
6462 dirty = any(repo.status())
6448 dirty = any(repo.status())
6463 node = ctx.node()
6449 node = ctx.node()
6464 if node != parent:
6450 if node != parent:
6465 if dirty:
6451 if dirty:
6466 hint = _("uncommitted changes, use --all to discard all"
6452 hint = _("uncommitted changes, use --all to discard all"
6467 " changes, or 'hg update %s' to update") % ctx.rev()
6453 " changes, or 'hg update %s' to update") % ctx.rev()
6468 else:
6454 else:
6469 hint = _("use --all to revert all files,"
6455 hint = _("use --all to revert all files,"
6470 " or 'hg update %s' to update") % ctx.rev()
6456 " or 'hg update %s' to update") % ctx.rev()
6471 elif dirty:
6457 elif dirty:
6472 hint = _("uncommitted changes, use --all to discard all changes")
6458 hint = _("uncommitted changes, use --all to discard all changes")
6473 else:
6459 else:
6474 hint = _("use --all to revert all files")
6460 hint = _("use --all to revert all files")
6475 raise error.Abort(msg, hint=hint)
6461 raise error.Abort(msg, hint=hint)
6476
6462
6477 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6463 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6478
6464
6479 @command('rollback', dryrunopts +
6465 @command('rollback', dryrunopts +
6480 [('f', 'force', False, _('ignore safety measures'))])
6466 [('f', 'force', False, _('ignore safety measures'))])
6481 def rollback(ui, repo, **opts):
6467 def rollback(ui, repo, **opts):
6482 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6468 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6483
6469
6484 Please use :hg:`commit --amend` instead of rollback to correct
6470 Please use :hg:`commit --amend` instead of rollback to correct
6485 mistakes in the last commit.
6471 mistakes in the last commit.
6486
6472
6487 This command should be used with care. There is only one level of
6473 This command should be used with care. There is only one level of
6488 rollback, and there is no way to undo a rollback. It will also
6474 rollback, and there is no way to undo a rollback. It will also
6489 restore the dirstate at the time of the last transaction, losing
6475 restore the dirstate at the time of the last transaction, losing
6490 any dirstate changes since that time. This command does not alter
6476 any dirstate changes since that time. This command does not alter
6491 the working directory.
6477 the working directory.
6492
6478
6493 Transactions are used to encapsulate the effects of all commands
6479 Transactions are used to encapsulate the effects of all commands
6494 that create new changesets or propagate existing changesets into a
6480 that create new changesets or propagate existing changesets into a
6495 repository.
6481 repository.
6496
6482
6497 .. container:: verbose
6483 .. container:: verbose
6498
6484
6499 For example, the following commands are transactional, and their
6485 For example, the following commands are transactional, and their
6500 effects can be rolled back:
6486 effects can be rolled back:
6501
6487
6502 - commit
6488 - commit
6503 - import
6489 - import
6504 - pull
6490 - pull
6505 - push (with this repository as the destination)
6491 - push (with this repository as the destination)
6506 - unbundle
6492 - unbundle
6507
6493
6508 To avoid permanent data loss, rollback will refuse to rollback a
6494 To avoid permanent data loss, rollback will refuse to rollback a
6509 commit transaction if it isn't checked out. Use --force to
6495 commit transaction if it isn't checked out. Use --force to
6510 override this protection.
6496 override this protection.
6511
6497
6512 The rollback command can be entirely disabled by setting the
6498 The rollback command can be entirely disabled by setting the
6513 ``ui.rollback`` configuration setting to false. If you're here
6499 ``ui.rollback`` configuration setting to false. If you're here
6514 because you want to use rollback and it's disabled, you can
6500 because you want to use rollback and it's disabled, you can
6515 re-enable the command by setting ``ui.rollback`` to true.
6501 re-enable the command by setting ``ui.rollback`` to true.
6516
6502
6517 This command is not intended for use on public repositories. Once
6503 This command is not intended for use on public repositories. Once
6518 changes are visible for pull by other users, rolling a transaction
6504 changes are visible for pull by other users, rolling a transaction
6519 back locally is ineffective (someone else may already have pulled
6505 back locally is ineffective (someone else may already have pulled
6520 the changes). Furthermore, a race is possible with readers of the
6506 the changes). Furthermore, a race is possible with readers of the
6521 repository; for example an in-progress pull from the repository
6507 repository; for example an in-progress pull from the repository
6522 may fail if a rollback is performed.
6508 may fail if a rollback is performed.
6523
6509
6524 Returns 0 on success, 1 if no rollback data is available.
6510 Returns 0 on success, 1 if no rollback data is available.
6525 """
6511 """
6526 if not ui.configbool('ui', 'rollback', True):
6512 if not ui.configbool('ui', 'rollback', True):
6527 raise error.Abort(_('rollback is disabled because it is unsafe'),
6513 raise error.Abort(_('rollback is disabled because it is unsafe'),
6528 hint=('see `hg help -v rollback` for information'))
6514 hint=('see `hg help -v rollback` for information'))
6529 return repo.rollback(dryrun=opts.get('dry_run'),
6515 return repo.rollback(dryrun=opts.get('dry_run'),
6530 force=opts.get('force'))
6516 force=opts.get('force'))
6531
6517
6532 @command('root', [])
6518 @command('root', [])
6533 def root(ui, repo):
6519 def root(ui, repo):
6534 """print the root (top) of the current working directory
6520 """print the root (top) of the current working directory
6535
6521
6536 Print the root directory of the current repository.
6522 Print the root directory of the current repository.
6537
6523
6538 Returns 0 on success.
6524 Returns 0 on success.
6539 """
6525 """
6540 ui.write(repo.root + "\n")
6526 ui.write(repo.root + "\n")
6541
6527
6542 @command('^serve',
6528 @command('^serve',
6543 [('A', 'accesslog', '', _('name of access log file to write to'),
6529 [('A', 'accesslog', '', _('name of access log file to write to'),
6544 _('FILE')),
6530 _('FILE')),
6545 ('d', 'daemon', None, _('run server in background')),
6531 ('d', 'daemon', None, _('run server in background')),
6546 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6532 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6547 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6533 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6548 # use string type, then we can check if something was passed
6534 # use string type, then we can check if something was passed
6549 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6535 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6550 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6536 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6551 _('ADDR')),
6537 _('ADDR')),
6552 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6538 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6553 _('PREFIX')),
6539 _('PREFIX')),
6554 ('n', 'name', '',
6540 ('n', 'name', '',
6555 _('name to show in web pages (default: working directory)'), _('NAME')),
6541 _('name to show in web pages (default: working directory)'), _('NAME')),
6556 ('', 'web-conf', '',
6542 ('', 'web-conf', '',
6557 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6543 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6558 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6544 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6559 _('FILE')),
6545 _('FILE')),
6560 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6546 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6561 ('', 'stdio', None, _('for remote clients')),
6547 ('', 'stdio', None, _('for remote clients')),
6562 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6548 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6563 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6549 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6564 ('', 'style', '', _('template style to use'), _('STYLE')),
6550 ('', 'style', '', _('template style to use'), _('STYLE')),
6565 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6551 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6566 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6552 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6567 _('[OPTION]...'),
6553 _('[OPTION]...'),
6568 optionalrepo=True)
6554 optionalrepo=True)
6569 def serve(ui, repo, **opts):
6555 def serve(ui, repo, **opts):
6570 """start stand-alone webserver
6556 """start stand-alone webserver
6571
6557
6572 Start a local HTTP repository browser and pull server. You can use
6558 Start a local HTTP repository browser and pull server. You can use
6573 this for ad-hoc sharing and browsing of repositories. It is
6559 this for ad-hoc sharing and browsing of repositories. It is
6574 recommended to use a real web server to serve a repository for
6560 recommended to use a real web server to serve a repository for
6575 longer periods of time.
6561 longer periods of time.
6576
6562
6577 Please note that the server does not implement access control.
6563 Please note that the server does not implement access control.
6578 This means that, by default, anybody can read from the server and
6564 This means that, by default, anybody can read from the server and
6579 nobody can write to it by default. Set the ``web.allow_push``
6565 nobody can write to it by default. Set the ``web.allow_push``
6580 option to ``*`` to allow everybody to push to the server. You
6566 option to ``*`` to allow everybody to push to the server. You
6581 should use a real web server if you need to authenticate users.
6567 should use a real web server if you need to authenticate users.
6582
6568
6583 By default, the server logs accesses to stdout and errors to
6569 By default, the server logs accesses to stdout and errors to
6584 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6570 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6585 files.
6571 files.
6586
6572
6587 To have the server choose a free port number to listen on, specify
6573 To have the server choose a free port number to listen on, specify
6588 a port number of 0; in this case, the server will print the port
6574 a port number of 0; in this case, the server will print the port
6589 number it uses.
6575 number it uses.
6590
6576
6591 Returns 0 on success.
6577 Returns 0 on success.
6592 """
6578 """
6593
6579
6594 if opts["stdio"] and opts["cmdserver"]:
6580 if opts["stdio"] and opts["cmdserver"]:
6595 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6581 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6596
6582
6597 if opts["stdio"]:
6583 if opts["stdio"]:
6598 if repo is None:
6584 if repo is None:
6599 raise error.RepoError(_("there is no Mercurial repository here"
6585 raise error.RepoError(_("there is no Mercurial repository here"
6600 " (.hg not found)"))
6586 " (.hg not found)"))
6601 s = sshserver.sshserver(ui, repo)
6587 s = sshserver.sshserver(ui, repo)
6602 s.serve_forever()
6588 s.serve_forever()
6603
6589
6604 if opts["cmdserver"]:
6590 if opts["cmdserver"]:
6605 service = commandserver.createservice(ui, repo, opts)
6591 service = commandserver.createservice(ui, repo, opts)
6606 else:
6592 else:
6607 service = hgweb.createservice(ui, repo, opts)
6593 service = hgweb.createservice(ui, repo, opts)
6608 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6594 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6609
6595
6610 @command('^status|st',
6596 @command('^status|st',
6611 [('A', 'all', None, _('show status of all files')),
6597 [('A', 'all', None, _('show status of all files')),
6612 ('m', 'modified', None, _('show only modified files')),
6598 ('m', 'modified', None, _('show only modified files')),
6613 ('a', 'added', None, _('show only added files')),
6599 ('a', 'added', None, _('show only added files')),
6614 ('r', 'removed', None, _('show only removed files')),
6600 ('r', 'removed', None, _('show only removed files')),
6615 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6601 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6616 ('c', 'clean', None, _('show only files without changes')),
6602 ('c', 'clean', None, _('show only files without changes')),
6617 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6603 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6618 ('i', 'ignored', None, _('show only ignored files')),
6604 ('i', 'ignored', None, _('show only ignored files')),
6619 ('n', 'no-status', None, _('hide status prefix')),
6605 ('n', 'no-status', None, _('hide status prefix')),
6620 ('C', 'copies', None, _('show source of copied files')),
6606 ('C', 'copies', None, _('show source of copied files')),
6621 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6607 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6622 ('', 'rev', [], _('show difference from revision'), _('REV')),
6608 ('', 'rev', [], _('show difference from revision'), _('REV')),
6623 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6609 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6624 ] + walkopts + subrepoopts + formatteropts,
6610 ] + walkopts + subrepoopts + formatteropts,
6625 _('[OPTION]... [FILE]...'),
6611 _('[OPTION]... [FILE]...'),
6626 inferrepo=True)
6612 inferrepo=True)
6627 def status(ui, repo, *pats, **opts):
6613 def status(ui, repo, *pats, **opts):
6628 """show changed files in the working directory
6614 """show changed files in the working directory
6629
6615
6630 Show status of files in the repository. If names are given, only
6616 Show status of files in the repository. If names are given, only
6631 files that match are shown. Files that are clean or ignored or
6617 files that match are shown. Files that are clean or ignored or
6632 the source of a copy/move operation, are not listed unless
6618 the source of a copy/move operation, are not listed unless
6633 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6619 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6634 Unless options described with "show only ..." are given, the
6620 Unless options described with "show only ..." are given, the
6635 options -mardu are used.
6621 options -mardu are used.
6636
6622
6637 Option -q/--quiet hides untracked (unknown and ignored) files
6623 Option -q/--quiet hides untracked (unknown and ignored) files
6638 unless explicitly requested with -u/--unknown or -i/--ignored.
6624 unless explicitly requested with -u/--unknown or -i/--ignored.
6639
6625
6640 .. note::
6626 .. note::
6641
6627
6642 :hg:`status` may appear to disagree with diff if permissions have
6628 :hg:`status` may appear to disagree with diff if permissions have
6643 changed or a merge has occurred. The standard diff format does
6629 changed or a merge has occurred. The standard diff format does
6644 not report permission changes and diff only reports changes
6630 not report permission changes and diff only reports changes
6645 relative to one merge parent.
6631 relative to one merge parent.
6646
6632
6647 If one revision is given, it is used as the base revision.
6633 If one revision is given, it is used as the base revision.
6648 If two revisions are given, the differences between them are
6634 If two revisions are given, the differences between them are
6649 shown. The --change option can also be used as a shortcut to list
6635 shown. The --change option can also be used as a shortcut to list
6650 the changed files of a revision from its first parent.
6636 the changed files of a revision from its first parent.
6651
6637
6652 The codes used to show the status of files are::
6638 The codes used to show the status of files are::
6653
6639
6654 M = modified
6640 M = modified
6655 A = added
6641 A = added
6656 R = removed
6642 R = removed
6657 C = clean
6643 C = clean
6658 ! = missing (deleted by non-hg command, but still tracked)
6644 ! = missing (deleted by non-hg command, but still tracked)
6659 ? = not tracked
6645 ? = not tracked
6660 I = ignored
6646 I = ignored
6661 = origin of the previous file (with --copies)
6647 = origin of the previous file (with --copies)
6662
6648
6663 .. container:: verbose
6649 .. container:: verbose
6664
6650
6665 Examples:
6651 Examples:
6666
6652
6667 - show changes in the working directory relative to a
6653 - show changes in the working directory relative to a
6668 changeset::
6654 changeset::
6669
6655
6670 hg status --rev 9353
6656 hg status --rev 9353
6671
6657
6672 - show changes in the working directory relative to the
6658 - show changes in the working directory relative to the
6673 current directory (see :hg:`help patterns` for more information)::
6659 current directory (see :hg:`help patterns` for more information)::
6674
6660
6675 hg status re:
6661 hg status re:
6676
6662
6677 - show all changes including copies in an existing changeset::
6663 - show all changes including copies in an existing changeset::
6678
6664
6679 hg status --copies --change 9353
6665 hg status --copies --change 9353
6680
6666
6681 - get a NUL separated list of added files, suitable for xargs::
6667 - get a NUL separated list of added files, suitable for xargs::
6682
6668
6683 hg status -an0
6669 hg status -an0
6684
6670
6685 Returns 0 on success.
6671 Returns 0 on success.
6686 """
6672 """
6687
6673
6688 revs = opts.get('rev')
6674 revs = opts.get('rev')
6689 change = opts.get('change')
6675 change = opts.get('change')
6690
6676
6691 if revs and change:
6677 if revs and change:
6692 msg = _('cannot specify --rev and --change at the same time')
6678 msg = _('cannot specify --rev and --change at the same time')
6693 raise error.Abort(msg)
6679 raise error.Abort(msg)
6694 elif change:
6680 elif change:
6695 node2 = scmutil.revsingle(repo, change, None).node()
6681 node2 = scmutil.revsingle(repo, change, None).node()
6696 node1 = repo[node2].p1().node()
6682 node1 = repo[node2].p1().node()
6697 else:
6683 else:
6698 node1, node2 = scmutil.revpair(repo, revs)
6684 node1, node2 = scmutil.revpair(repo, revs)
6699
6685
6700 if pats:
6686 if pats:
6701 cwd = repo.getcwd()
6687 cwd = repo.getcwd()
6702 else:
6688 else:
6703 cwd = ''
6689 cwd = ''
6704
6690
6705 if opts.get('print0'):
6691 if opts.get('print0'):
6706 end = '\0'
6692 end = '\0'
6707 else:
6693 else:
6708 end = '\n'
6694 end = '\n'
6709 copy = {}
6695 copy = {}
6710 states = 'modified added removed deleted unknown ignored clean'.split()
6696 states = 'modified added removed deleted unknown ignored clean'.split()
6711 show = [k for k in states if opts.get(k)]
6697 show = [k for k in states if opts.get(k)]
6712 if opts.get('all'):
6698 if opts.get('all'):
6713 show += ui.quiet and (states[:4] + ['clean']) or states
6699 show += ui.quiet and (states[:4] + ['clean']) or states
6714 if not show:
6700 if not show:
6715 if ui.quiet:
6701 if ui.quiet:
6716 show = states[:4]
6702 show = states[:4]
6717 else:
6703 else:
6718 show = states[:5]
6704 show = states[:5]
6719
6705
6720 m = scmutil.match(repo[node2], pats, opts)
6706 m = scmutil.match(repo[node2], pats, opts)
6721 stat = repo.status(node1, node2, m,
6707 stat = repo.status(node1, node2, m,
6722 'ignored' in show, 'clean' in show, 'unknown' in show,
6708 'ignored' in show, 'clean' in show, 'unknown' in show,
6723 opts.get('subrepos'))
6709 opts.get('subrepos'))
6724 changestates = zip(states, 'MAR!?IC', stat)
6710 changestates = zip(states, 'MAR!?IC', stat)
6725
6711
6726 if (opts.get('all') or opts.get('copies')
6712 if (opts.get('all') or opts.get('copies')
6727 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6713 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6728 copy = copies.pathcopies(repo[node1], repo[node2], m)
6714 copy = copies.pathcopies(repo[node1], repo[node2], m)
6729
6715
6730 fm = ui.formatter('status', opts)
6716 fm = ui.formatter('status', opts)
6731 fmt = '%s' + end
6717 fmt = '%s' + end
6732 showchar = not opts.get('no_status')
6718 showchar = not opts.get('no_status')
6733
6719
6734 for state, char, files in changestates:
6720 for state, char, files in changestates:
6735 if state in show:
6721 if state in show:
6736 label = 'status.' + state
6722 label = 'status.' + state
6737 for f in files:
6723 for f in files:
6738 fm.startitem()
6724 fm.startitem()
6739 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6725 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6740 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6726 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6741 if f in copy:
6727 if f in copy:
6742 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6728 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6743 label='status.copied')
6729 label='status.copied')
6744 fm.end()
6730 fm.end()
6745
6731
6746 @command('^summary|sum',
6732 @command('^summary|sum',
6747 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6733 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6748 def summary(ui, repo, **opts):
6734 def summary(ui, repo, **opts):
6749 """summarize working directory state
6735 """summarize working directory state
6750
6736
6751 This generates a brief summary of the working directory state,
6737 This generates a brief summary of the working directory state,
6752 including parents, branch, commit status, phase and available updates.
6738 including parents, branch, commit status, phase and available updates.
6753
6739
6754 With the --remote option, this will check the default paths for
6740 With the --remote option, this will check the default paths for
6755 incoming and outgoing changes. This can be time-consuming.
6741 incoming and outgoing changes. This can be time-consuming.
6756
6742
6757 Returns 0 on success.
6743 Returns 0 on success.
6758 """
6744 """
6759
6745
6760 ctx = repo[None]
6746 ctx = repo[None]
6761 parents = ctx.parents()
6747 parents = ctx.parents()
6762 pnode = parents[0].node()
6748 pnode = parents[0].node()
6763 marks = []
6749 marks = []
6764
6750
6765 ms = None
6751 ms = None
6766 try:
6752 try:
6767 ms = mergemod.mergestate.read(repo)
6753 ms = mergemod.mergestate.read(repo)
6768 except error.UnsupportedMergeRecords as e:
6754 except error.UnsupportedMergeRecords as e:
6769 s = ' '.join(e.recordtypes)
6755 s = ' '.join(e.recordtypes)
6770 ui.warn(
6756 ui.warn(
6771 _('warning: merge state has unsupported record types: %s\n') % s)
6757 _('warning: merge state has unsupported record types: %s\n') % s)
6772 unresolved = 0
6758 unresolved = 0
6773 else:
6759 else:
6774 unresolved = [f for f in ms if ms[f] == 'u']
6760 unresolved = [f for f in ms if ms[f] == 'u']
6775
6761
6776 for p in parents:
6762 for p in parents:
6777 # label with log.changeset (instead of log.parent) since this
6763 # label with log.changeset (instead of log.parent) since this
6778 # shows a working directory parent *changeset*:
6764 # shows a working directory parent *changeset*:
6779 # i18n: column positioning for "hg summary"
6765 # i18n: column positioning for "hg summary"
6780 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6766 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6781 label='log.changeset changeset.%s' % p.phasestr())
6767 label='log.changeset changeset.%s' % p.phasestr())
6782 ui.write(' '.join(p.tags()), label='log.tag')
6768 ui.write(' '.join(p.tags()), label='log.tag')
6783 if p.bookmarks():
6769 if p.bookmarks():
6784 marks.extend(p.bookmarks())
6770 marks.extend(p.bookmarks())
6785 if p.rev() == -1:
6771 if p.rev() == -1:
6786 if not len(repo):
6772 if not len(repo):
6787 ui.write(_(' (empty repository)'))
6773 ui.write(_(' (empty repository)'))
6788 else:
6774 else:
6789 ui.write(_(' (no revision checked out)'))
6775 ui.write(_(' (no revision checked out)'))
6790 ui.write('\n')
6776 ui.write('\n')
6791 if p.description():
6777 if p.description():
6792 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6778 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6793 label='log.summary')
6779 label='log.summary')
6794
6780
6795 branch = ctx.branch()
6781 branch = ctx.branch()
6796 bheads = repo.branchheads(branch)
6782 bheads = repo.branchheads(branch)
6797 # i18n: column positioning for "hg summary"
6783 # i18n: column positioning for "hg summary"
6798 m = _('branch: %s\n') % branch
6784 m = _('branch: %s\n') % branch
6799 if branch != 'default':
6785 if branch != 'default':
6800 ui.write(m, label='log.branch')
6786 ui.write(m, label='log.branch')
6801 else:
6787 else:
6802 ui.status(m, label='log.branch')
6788 ui.status(m, label='log.branch')
6803
6789
6804 if marks:
6790 if marks:
6805 active = repo._activebookmark
6791 active = repo._activebookmark
6806 # i18n: column positioning for "hg summary"
6792 # i18n: column positioning for "hg summary"
6807 ui.write(_('bookmarks:'), label='log.bookmark')
6793 ui.write(_('bookmarks:'), label='log.bookmark')
6808 if active is not None:
6794 if active is not None:
6809 if active in marks:
6795 if active in marks:
6810 ui.write(' *' + active, label=activebookmarklabel)
6796 ui.write(' *' + active, label=activebookmarklabel)
6811 marks.remove(active)
6797 marks.remove(active)
6812 else:
6798 else:
6813 ui.write(' [%s]' % active, label=activebookmarklabel)
6799 ui.write(' [%s]' % active, label=activebookmarklabel)
6814 for m in marks:
6800 for m in marks:
6815 ui.write(' ' + m, label='log.bookmark')
6801 ui.write(' ' + m, label='log.bookmark')
6816 ui.write('\n', label='log.bookmark')
6802 ui.write('\n', label='log.bookmark')
6817
6803
6818 status = repo.status(unknown=True)
6804 status = repo.status(unknown=True)
6819
6805
6820 c = repo.dirstate.copies()
6806 c = repo.dirstate.copies()
6821 copied, renamed = [], []
6807 copied, renamed = [], []
6822 for d, s in c.iteritems():
6808 for d, s in c.iteritems():
6823 if s in status.removed:
6809 if s in status.removed:
6824 status.removed.remove(s)
6810 status.removed.remove(s)
6825 renamed.append(d)
6811 renamed.append(d)
6826 else:
6812 else:
6827 copied.append(d)
6813 copied.append(d)
6828 if d in status.added:
6814 if d in status.added:
6829 status.added.remove(d)
6815 status.added.remove(d)
6830
6816
6831 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6817 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6832
6818
6833 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6819 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6834 (ui.label(_('%d added'), 'status.added'), status.added),
6820 (ui.label(_('%d added'), 'status.added'), status.added),
6835 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6821 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6836 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6822 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6837 (ui.label(_('%d copied'), 'status.copied'), copied),
6823 (ui.label(_('%d copied'), 'status.copied'), copied),
6838 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6824 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6839 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6825 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6840 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6826 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6841 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6827 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6842 t = []
6828 t = []
6843 for l, s in labels:
6829 for l, s in labels:
6844 if s:
6830 if s:
6845 t.append(l % len(s))
6831 t.append(l % len(s))
6846
6832
6847 t = ', '.join(t)
6833 t = ', '.join(t)
6848 cleanworkdir = False
6834 cleanworkdir = False
6849
6835
6850 if repo.vfs.exists('graftstate'):
6836 if repo.vfs.exists('graftstate'):
6851 t += _(' (graft in progress)')
6837 t += _(' (graft in progress)')
6852 if repo.vfs.exists('updatestate'):
6838 if repo.vfs.exists('updatestate'):
6853 t += _(' (interrupted update)')
6839 t += _(' (interrupted update)')
6854 elif len(parents) > 1:
6840 elif len(parents) > 1:
6855 t += _(' (merge)')
6841 t += _(' (merge)')
6856 elif branch != parents[0].branch():
6842 elif branch != parents[0].branch():
6857 t += _(' (new branch)')
6843 t += _(' (new branch)')
6858 elif (parents[0].closesbranch() and
6844 elif (parents[0].closesbranch() and
6859 pnode in repo.branchheads(branch, closed=True)):
6845 pnode in repo.branchheads(branch, closed=True)):
6860 t += _(' (head closed)')
6846 t += _(' (head closed)')
6861 elif not (status.modified or status.added or status.removed or renamed or
6847 elif not (status.modified or status.added or status.removed or renamed or
6862 copied or subs):
6848 copied or subs):
6863 t += _(' (clean)')
6849 t += _(' (clean)')
6864 cleanworkdir = True
6850 cleanworkdir = True
6865 elif pnode not in bheads:
6851 elif pnode not in bheads:
6866 t += _(' (new branch head)')
6852 t += _(' (new branch head)')
6867
6853
6868 if parents:
6854 if parents:
6869 pendingphase = max(p.phase() for p in parents)
6855 pendingphase = max(p.phase() for p in parents)
6870 else:
6856 else:
6871 pendingphase = phases.public
6857 pendingphase = phases.public
6872
6858
6873 if pendingphase > phases.newcommitphase(ui):
6859 if pendingphase > phases.newcommitphase(ui):
6874 t += ' (%s)' % phases.phasenames[pendingphase]
6860 t += ' (%s)' % phases.phasenames[pendingphase]
6875
6861
6876 if cleanworkdir:
6862 if cleanworkdir:
6877 # i18n: column positioning for "hg summary"
6863 # i18n: column positioning for "hg summary"
6878 ui.status(_('commit: %s\n') % t.strip())
6864 ui.status(_('commit: %s\n') % t.strip())
6879 else:
6865 else:
6880 # i18n: column positioning for "hg summary"
6866 # i18n: column positioning for "hg summary"
6881 ui.write(_('commit: %s\n') % t.strip())
6867 ui.write(_('commit: %s\n') % t.strip())
6882
6868
6883 # all ancestors of branch heads - all ancestors of parent = new csets
6869 # all ancestors of branch heads - all ancestors of parent = new csets
6884 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6870 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6885 bheads))
6871 bheads))
6886
6872
6887 if new == 0:
6873 if new == 0:
6888 # i18n: column positioning for "hg summary"
6874 # i18n: column positioning for "hg summary"
6889 ui.status(_('update: (current)\n'))
6875 ui.status(_('update: (current)\n'))
6890 elif pnode not in bheads:
6876 elif pnode not in bheads:
6891 # i18n: column positioning for "hg summary"
6877 # i18n: column positioning for "hg summary"
6892 ui.write(_('update: %d new changesets (update)\n') % new)
6878 ui.write(_('update: %d new changesets (update)\n') % new)
6893 else:
6879 else:
6894 # i18n: column positioning for "hg summary"
6880 # i18n: column positioning for "hg summary"
6895 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6881 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6896 (new, len(bheads)))
6882 (new, len(bheads)))
6897
6883
6898 t = []
6884 t = []
6899 draft = len(repo.revs('draft()'))
6885 draft = len(repo.revs('draft()'))
6900 if draft:
6886 if draft:
6901 t.append(_('%d draft') % draft)
6887 t.append(_('%d draft') % draft)
6902 secret = len(repo.revs('secret()'))
6888 secret = len(repo.revs('secret()'))
6903 if secret:
6889 if secret:
6904 t.append(_('%d secret') % secret)
6890 t.append(_('%d secret') % secret)
6905
6891
6906 if draft or secret:
6892 if draft or secret:
6907 ui.status(_('phases: %s\n') % ', '.join(t))
6893 ui.status(_('phases: %s\n') % ', '.join(t))
6908
6894
6909 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6895 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6910 for trouble in ("unstable", "divergent", "bumped"):
6896 for trouble in ("unstable", "divergent", "bumped"):
6911 numtrouble = len(repo.revs(trouble + "()"))
6897 numtrouble = len(repo.revs(trouble + "()"))
6912 # We write all the possibilities to ease translation
6898 # We write all the possibilities to ease translation
6913 troublemsg = {
6899 troublemsg = {
6914 "unstable": _("unstable: %d changesets"),
6900 "unstable": _("unstable: %d changesets"),
6915 "divergent": _("divergent: %d changesets"),
6901 "divergent": _("divergent: %d changesets"),
6916 "bumped": _("bumped: %d changesets"),
6902 "bumped": _("bumped: %d changesets"),
6917 }
6903 }
6918 if numtrouble > 0:
6904 if numtrouble > 0:
6919 ui.status(troublemsg[trouble] % numtrouble + "\n")
6905 ui.status(troublemsg[trouble] % numtrouble + "\n")
6920
6906
6921 cmdutil.summaryhooks(ui, repo)
6907 cmdutil.summaryhooks(ui, repo)
6922
6908
6923 if opts.get('remote'):
6909 if opts.get('remote'):
6924 needsincoming, needsoutgoing = True, True
6910 needsincoming, needsoutgoing = True, True
6925 else:
6911 else:
6926 needsincoming, needsoutgoing = False, False
6912 needsincoming, needsoutgoing = False, False
6927 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6913 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6928 if i:
6914 if i:
6929 needsincoming = True
6915 needsincoming = True
6930 if o:
6916 if o:
6931 needsoutgoing = True
6917 needsoutgoing = True
6932 if not needsincoming and not needsoutgoing:
6918 if not needsincoming and not needsoutgoing:
6933 return
6919 return
6934
6920
6935 def getincoming():
6921 def getincoming():
6936 source, branches = hg.parseurl(ui.expandpath('default'))
6922 source, branches = hg.parseurl(ui.expandpath('default'))
6937 sbranch = branches[0]
6923 sbranch = branches[0]
6938 try:
6924 try:
6939 other = hg.peer(repo, {}, source)
6925 other = hg.peer(repo, {}, source)
6940 except error.RepoError:
6926 except error.RepoError:
6941 if opts.get('remote'):
6927 if opts.get('remote'):
6942 raise
6928 raise
6943 return source, sbranch, None, None, None
6929 return source, sbranch, None, None, None
6944 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6930 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6945 if revs:
6931 if revs:
6946 revs = [other.lookup(rev) for rev in revs]
6932 revs = [other.lookup(rev) for rev in revs]
6947 ui.debug('comparing with %s\n' % util.hidepassword(source))
6933 ui.debug('comparing with %s\n' % util.hidepassword(source))
6948 repo.ui.pushbuffer()
6934 repo.ui.pushbuffer()
6949 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6935 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6950 repo.ui.popbuffer()
6936 repo.ui.popbuffer()
6951 return source, sbranch, other, commoninc, commoninc[1]
6937 return source, sbranch, other, commoninc, commoninc[1]
6952
6938
6953 if needsincoming:
6939 if needsincoming:
6954 source, sbranch, sother, commoninc, incoming = getincoming()
6940 source, sbranch, sother, commoninc, incoming = getincoming()
6955 else:
6941 else:
6956 source = sbranch = sother = commoninc = incoming = None
6942 source = sbranch = sother = commoninc = incoming = None
6957
6943
6958 def getoutgoing():
6944 def getoutgoing():
6959 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6945 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6960 dbranch = branches[0]
6946 dbranch = branches[0]
6961 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6947 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6962 if source != dest:
6948 if source != dest:
6963 try:
6949 try:
6964 dother = hg.peer(repo, {}, dest)
6950 dother = hg.peer(repo, {}, dest)
6965 except error.RepoError:
6951 except error.RepoError:
6966 if opts.get('remote'):
6952 if opts.get('remote'):
6967 raise
6953 raise
6968 return dest, dbranch, None, None
6954 return dest, dbranch, None, None
6969 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6955 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6970 elif sother is None:
6956 elif sother is None:
6971 # there is no explicit destination peer, but source one is invalid
6957 # there is no explicit destination peer, but source one is invalid
6972 return dest, dbranch, None, None
6958 return dest, dbranch, None, None
6973 else:
6959 else:
6974 dother = sother
6960 dother = sother
6975 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6961 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6976 common = None
6962 common = None
6977 else:
6963 else:
6978 common = commoninc
6964 common = commoninc
6979 if revs:
6965 if revs:
6980 revs = [repo.lookup(rev) for rev in revs]
6966 revs = [repo.lookup(rev) for rev in revs]
6981 repo.ui.pushbuffer()
6967 repo.ui.pushbuffer()
6982 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6968 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6983 commoninc=common)
6969 commoninc=common)
6984 repo.ui.popbuffer()
6970 repo.ui.popbuffer()
6985 return dest, dbranch, dother, outgoing
6971 return dest, dbranch, dother, outgoing
6986
6972
6987 if needsoutgoing:
6973 if needsoutgoing:
6988 dest, dbranch, dother, outgoing = getoutgoing()
6974 dest, dbranch, dother, outgoing = getoutgoing()
6989 else:
6975 else:
6990 dest = dbranch = dother = outgoing = None
6976 dest = dbranch = dother = outgoing = None
6991
6977
6992 if opts.get('remote'):
6978 if opts.get('remote'):
6993 t = []
6979 t = []
6994 if incoming:
6980 if incoming:
6995 t.append(_('1 or more incoming'))
6981 t.append(_('1 or more incoming'))
6996 o = outgoing.missing
6982 o = outgoing.missing
6997 if o:
6983 if o:
6998 t.append(_('%d outgoing') % len(o))
6984 t.append(_('%d outgoing') % len(o))
6999 other = dother or sother
6985 other = dother or sother
7000 if 'bookmarks' in other.listkeys('namespaces'):
6986 if 'bookmarks' in other.listkeys('namespaces'):
7001 counts = bookmarks.summary(repo, other)
6987 counts = bookmarks.summary(repo, other)
7002 if counts[0] > 0:
6988 if counts[0] > 0:
7003 t.append(_('%d incoming bookmarks') % counts[0])
6989 t.append(_('%d incoming bookmarks') % counts[0])
7004 if counts[1] > 0:
6990 if counts[1] > 0:
7005 t.append(_('%d outgoing bookmarks') % counts[1])
6991 t.append(_('%d outgoing bookmarks') % counts[1])
7006
6992
7007 if t:
6993 if t:
7008 # i18n: column positioning for "hg summary"
6994 # i18n: column positioning for "hg summary"
7009 ui.write(_('remote: %s\n') % (', '.join(t)))
6995 ui.write(_('remote: %s\n') % (', '.join(t)))
7010 else:
6996 else:
7011 # i18n: column positioning for "hg summary"
6997 # i18n: column positioning for "hg summary"
7012 ui.status(_('remote: (synced)\n'))
6998 ui.status(_('remote: (synced)\n'))
7013
6999
7014 cmdutil.summaryremotehooks(ui, repo, opts,
7000 cmdutil.summaryremotehooks(ui, repo, opts,
7015 ((source, sbranch, sother, commoninc),
7001 ((source, sbranch, sother, commoninc),
7016 (dest, dbranch, dother, outgoing)))
7002 (dest, dbranch, dother, outgoing)))
7017
7003
7018 @command('tag',
7004 @command('tag',
7019 [('f', 'force', None, _('force tag')),
7005 [('f', 'force', None, _('force tag')),
7020 ('l', 'local', None, _('make the tag local')),
7006 ('l', 'local', None, _('make the tag local')),
7021 ('r', 'rev', '', _('revision to tag'), _('REV')),
7007 ('r', 'rev', '', _('revision to tag'), _('REV')),
7022 ('', 'remove', None, _('remove a tag')),
7008 ('', 'remove', None, _('remove a tag')),
7023 # -l/--local is already there, commitopts cannot be used
7009 # -l/--local is already there, commitopts cannot be used
7024 ('e', 'edit', None, _('invoke editor on commit messages')),
7010 ('e', 'edit', None, _('invoke editor on commit messages')),
7025 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
7011 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
7026 ] + commitopts2,
7012 ] + commitopts2,
7027 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
7013 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
7028 def tag(ui, repo, name1, *names, **opts):
7014 def tag(ui, repo, name1, *names, **opts):
7029 """add one or more tags for the current or given revision
7015 """add one or more tags for the current or given revision
7030
7016
7031 Name a particular revision using <name>.
7017 Name a particular revision using <name>.
7032
7018
7033 Tags are used to name particular revisions of the repository and are
7019 Tags are used to name particular revisions of the repository and are
7034 very useful to compare different revisions, to go back to significant
7020 very useful to compare different revisions, to go back to significant
7035 earlier versions or to mark branch points as releases, etc. Changing
7021 earlier versions or to mark branch points as releases, etc. Changing
7036 an existing tag is normally disallowed; use -f/--force to override.
7022 an existing tag is normally disallowed; use -f/--force to override.
7037
7023
7038 If no revision is given, the parent of the working directory is
7024 If no revision is given, the parent of the working directory is
7039 used.
7025 used.
7040
7026
7041 To facilitate version control, distribution, and merging of tags,
7027 To facilitate version control, distribution, and merging of tags,
7042 they are stored as a file named ".hgtags" which is managed similarly
7028 they are stored as a file named ".hgtags" which is managed similarly
7043 to other project files and can be hand-edited if necessary. This
7029 to other project files and can be hand-edited if necessary. This
7044 also means that tagging creates a new commit. The file
7030 also means that tagging creates a new commit. The file
7045 ".hg/localtags" is used for local tags (not shared among
7031 ".hg/localtags" is used for local tags (not shared among
7046 repositories).
7032 repositories).
7047
7033
7048 Tag commits are usually made at the head of a branch. If the parent
7034 Tag commits are usually made at the head of a branch. If the parent
7049 of the working directory is not a branch head, :hg:`tag` aborts; use
7035 of the working directory is not a branch head, :hg:`tag` aborts; use
7050 -f/--force to force the tag commit to be based on a non-head
7036 -f/--force to force the tag commit to be based on a non-head
7051 changeset.
7037 changeset.
7052
7038
7053 See :hg:`help dates` for a list of formats valid for -d/--date.
7039 See :hg:`help dates` for a list of formats valid for -d/--date.
7054
7040
7055 Since tag names have priority over branch names during revision
7041 Since tag names have priority over branch names during revision
7056 lookup, using an existing branch name as a tag name is discouraged.
7042 lookup, using an existing branch name as a tag name is discouraged.
7057
7043
7058 Returns 0 on success.
7044 Returns 0 on success.
7059 """
7045 """
7060 wlock = lock = None
7046 wlock = lock = None
7061 try:
7047 try:
7062 wlock = repo.wlock()
7048 wlock = repo.wlock()
7063 lock = repo.lock()
7049 lock = repo.lock()
7064 rev_ = "."
7050 rev_ = "."
7065 names = [t.strip() for t in (name1,) + names]
7051 names = [t.strip() for t in (name1,) + names]
7066 if len(names) != len(set(names)):
7052 if len(names) != len(set(names)):
7067 raise error.Abort(_('tag names must be unique'))
7053 raise error.Abort(_('tag names must be unique'))
7068 for n in names:
7054 for n in names:
7069 scmutil.checknewlabel(repo, n, 'tag')
7055 scmutil.checknewlabel(repo, n, 'tag')
7070 if not n:
7056 if not n:
7071 raise error.Abort(_('tag names cannot consist entirely of '
7057 raise error.Abort(_('tag names cannot consist entirely of '
7072 'whitespace'))
7058 'whitespace'))
7073 if opts.get('rev') and opts.get('remove'):
7059 if opts.get('rev') and opts.get('remove'):
7074 raise error.Abort(_("--rev and --remove are incompatible"))
7060 raise error.Abort(_("--rev and --remove are incompatible"))
7075 if opts.get('rev'):
7061 if opts.get('rev'):
7076 rev_ = opts['rev']
7062 rev_ = opts['rev']
7077 message = opts.get('message')
7063 message = opts.get('message')
7078 if opts.get('remove'):
7064 if opts.get('remove'):
7079 if opts.get('local'):
7065 if opts.get('local'):
7080 expectedtype = 'local'
7066 expectedtype = 'local'
7081 else:
7067 else:
7082 expectedtype = 'global'
7068 expectedtype = 'global'
7083
7069
7084 for n in names:
7070 for n in names:
7085 if not repo.tagtype(n):
7071 if not repo.tagtype(n):
7086 raise error.Abort(_("tag '%s' does not exist") % n)
7072 raise error.Abort(_("tag '%s' does not exist") % n)
7087 if repo.tagtype(n) != expectedtype:
7073 if repo.tagtype(n) != expectedtype:
7088 if expectedtype == 'global':
7074 if expectedtype == 'global':
7089 raise error.Abort(_("tag '%s' is not a global tag") % n)
7075 raise error.Abort(_("tag '%s' is not a global tag") % n)
7090 else:
7076 else:
7091 raise error.Abort(_("tag '%s' is not a local tag") % n)
7077 raise error.Abort(_("tag '%s' is not a local tag") % n)
7092 rev_ = 'null'
7078 rev_ = 'null'
7093 if not message:
7079 if not message:
7094 # we don't translate commit messages
7080 # we don't translate commit messages
7095 message = 'Removed tag %s' % ', '.join(names)
7081 message = 'Removed tag %s' % ', '.join(names)
7096 elif not opts.get('force'):
7082 elif not opts.get('force'):
7097 for n in names:
7083 for n in names:
7098 if n in repo.tags():
7084 if n in repo.tags():
7099 raise error.Abort(_("tag '%s' already exists "
7085 raise error.Abort(_("tag '%s' already exists "
7100 "(use -f to force)") % n)
7086 "(use -f to force)") % n)
7101 if not opts.get('local'):
7087 if not opts.get('local'):
7102 p1, p2 = repo.dirstate.parents()
7088 p1, p2 = repo.dirstate.parents()
7103 if p2 != nullid:
7089 if p2 != nullid:
7104 raise error.Abort(_('uncommitted merge'))
7090 raise error.Abort(_('uncommitted merge'))
7105 bheads = repo.branchheads()
7091 bheads = repo.branchheads()
7106 if not opts.get('force') and bheads and p1 not in bheads:
7092 if not opts.get('force') and bheads and p1 not in bheads:
7107 raise error.Abort(_('not at a branch head (use -f to force)'))
7093 raise error.Abort(_('not at a branch head (use -f to force)'))
7108 r = scmutil.revsingle(repo, rev_).node()
7094 r = scmutil.revsingle(repo, rev_).node()
7109
7095
7110 if not message:
7096 if not message:
7111 # we don't translate commit messages
7097 # we don't translate commit messages
7112 message = ('Added tag %s for changeset %s' %
7098 message = ('Added tag %s for changeset %s' %
7113 (', '.join(names), short(r)))
7099 (', '.join(names), short(r)))
7114
7100
7115 date = opts.get('date')
7101 date = opts.get('date')
7116 if date:
7102 if date:
7117 date = util.parsedate(date)
7103 date = util.parsedate(date)
7118
7104
7119 if opts.get('remove'):
7105 if opts.get('remove'):
7120 editform = 'tag.remove'
7106 editform = 'tag.remove'
7121 else:
7107 else:
7122 editform = 'tag.add'
7108 editform = 'tag.add'
7123 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7109 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7124
7110
7125 # don't allow tagging the null rev
7111 # don't allow tagging the null rev
7126 if (not opts.get('remove') and
7112 if (not opts.get('remove') and
7127 scmutil.revsingle(repo, rev_).rev() == nullrev):
7113 scmutil.revsingle(repo, rev_).rev() == nullrev):
7128 raise error.Abort(_("cannot tag null revision"))
7114 raise error.Abort(_("cannot tag null revision"))
7129
7115
7130 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7116 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7131 editor=editor)
7117 editor=editor)
7132 finally:
7118 finally:
7133 release(lock, wlock)
7119 release(lock, wlock)
7134
7120
7135 @command('tags', formatteropts, '')
7121 @command('tags', formatteropts, '')
7136 def tags(ui, repo, **opts):
7122 def tags(ui, repo, **opts):
7137 """list repository tags
7123 """list repository tags
7138
7124
7139 This lists both regular and local tags. When the -v/--verbose
7125 This lists both regular and local tags. When the -v/--verbose
7140 switch is used, a third column "local" is printed for local tags.
7126 switch is used, a third column "local" is printed for local tags.
7141 When the -q/--quiet switch is used, only the tag name is printed.
7127 When the -q/--quiet switch is used, only the tag name is printed.
7142
7128
7143 Returns 0 on success.
7129 Returns 0 on success.
7144 """
7130 """
7145
7131
7146 fm = ui.formatter('tags', opts)
7132 fm = ui.formatter('tags', opts)
7147 hexfunc = fm.hexfunc
7133 hexfunc = fm.hexfunc
7148 tagtype = ""
7134 tagtype = ""
7149
7135
7150 for t, n in reversed(repo.tagslist()):
7136 for t, n in reversed(repo.tagslist()):
7151 hn = hexfunc(n)
7137 hn = hexfunc(n)
7152 label = 'tags.normal'
7138 label = 'tags.normal'
7153 tagtype = ''
7139 tagtype = ''
7154 if repo.tagtype(t) == 'local':
7140 if repo.tagtype(t) == 'local':
7155 label = 'tags.local'
7141 label = 'tags.local'
7156 tagtype = 'local'
7142 tagtype = 'local'
7157
7143
7158 fm.startitem()
7144 fm.startitem()
7159 fm.write('tag', '%s', t, label=label)
7145 fm.write('tag', '%s', t, label=label)
7160 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7146 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7161 fm.condwrite(not ui.quiet, 'rev node', fmt,
7147 fm.condwrite(not ui.quiet, 'rev node', fmt,
7162 repo.changelog.rev(n), hn, label=label)
7148 repo.changelog.rev(n), hn, label=label)
7163 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7149 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7164 tagtype, label=label)
7150 tagtype, label=label)
7165 fm.plain('\n')
7151 fm.plain('\n')
7166 fm.end()
7152 fm.end()
7167
7153
7168 @command('tip',
7154 @command('tip',
7169 [('p', 'patch', None, _('show patch')),
7155 [('p', 'patch', None, _('show patch')),
7170 ('g', 'git', None, _('use git extended diff format')),
7156 ('g', 'git', None, _('use git extended diff format')),
7171 ] + templateopts,
7157 ] + templateopts,
7172 _('[-p] [-g]'))
7158 _('[-p] [-g]'))
7173 def tip(ui, repo, **opts):
7159 def tip(ui, repo, **opts):
7174 """show the tip revision (DEPRECATED)
7160 """show the tip revision (DEPRECATED)
7175
7161
7176 The tip revision (usually just called the tip) is the changeset
7162 The tip revision (usually just called the tip) is the changeset
7177 most recently added to the repository (and therefore the most
7163 most recently added to the repository (and therefore the most
7178 recently changed head).
7164 recently changed head).
7179
7165
7180 If you have just made a commit, that commit will be the tip. If
7166 If you have just made a commit, that commit will be the tip. If
7181 you have just pulled changes from another repository, the tip of
7167 you have just pulled changes from another repository, the tip of
7182 that repository becomes the current tip. The "tip" tag is special
7168 that repository becomes the current tip. The "tip" tag is special
7183 and cannot be renamed or assigned to a different changeset.
7169 and cannot be renamed or assigned to a different changeset.
7184
7170
7185 This command is deprecated, please use :hg:`heads` instead.
7171 This command is deprecated, please use :hg:`heads` instead.
7186
7172
7187 Returns 0 on success.
7173 Returns 0 on success.
7188 """
7174 """
7189 displayer = cmdutil.show_changeset(ui, repo, opts)
7175 displayer = cmdutil.show_changeset(ui, repo, opts)
7190 displayer.show(repo['tip'])
7176 displayer.show(repo['tip'])
7191 displayer.close()
7177 displayer.close()
7192
7178
7193 @command('unbundle',
7179 @command('unbundle',
7194 [('u', 'update', None,
7180 [('u', 'update', None,
7195 _('update to new branch head if changesets were unbundled'))],
7181 _('update to new branch head if changesets were unbundled'))],
7196 _('[-u] FILE...'))
7182 _('[-u] FILE...'))
7197 def unbundle(ui, repo, fname1, *fnames, **opts):
7183 def unbundle(ui, repo, fname1, *fnames, **opts):
7198 """apply one or more changegroup files
7184 """apply one or more changegroup files
7199
7185
7200 Apply one or more compressed changegroup files generated by the
7186 Apply one or more compressed changegroup files generated by the
7201 bundle command.
7187 bundle command.
7202
7188
7203 Returns 0 on success, 1 if an update has unresolved files.
7189 Returns 0 on success, 1 if an update has unresolved files.
7204 """
7190 """
7205 fnames = (fname1,) + fnames
7191 fnames = (fname1,) + fnames
7206
7192
7207 with repo.lock():
7193 with repo.lock():
7208 for fname in fnames:
7194 for fname in fnames:
7209 f = hg.openpath(ui, fname)
7195 f = hg.openpath(ui, fname)
7210 gen = exchange.readbundle(ui, f, fname)
7196 gen = exchange.readbundle(ui, f, fname)
7211 if isinstance(gen, bundle2.unbundle20):
7197 if isinstance(gen, bundle2.unbundle20):
7212 tr = repo.transaction('unbundle')
7198 tr = repo.transaction('unbundle')
7213 try:
7199 try:
7214 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7200 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7215 url='bundle:' + fname)
7201 url='bundle:' + fname)
7216 tr.close()
7202 tr.close()
7217 except error.BundleUnknownFeatureError as exc:
7203 except error.BundleUnknownFeatureError as exc:
7218 raise error.Abort(_('%s: unknown bundle feature, %s')
7204 raise error.Abort(_('%s: unknown bundle feature, %s')
7219 % (fname, exc),
7205 % (fname, exc),
7220 hint=_("see https://mercurial-scm.org/"
7206 hint=_("see https://mercurial-scm.org/"
7221 "wiki/BundleFeature for more "
7207 "wiki/BundleFeature for more "
7222 "information"))
7208 "information"))
7223 finally:
7209 finally:
7224 if tr:
7210 if tr:
7225 tr.release()
7211 tr.release()
7226 changes = [r.get('return', 0)
7212 changes = [r.get('return', 0)
7227 for r in op.records['changegroup']]
7213 for r in op.records['changegroup']]
7228 modheads = changegroup.combineresults(changes)
7214 modheads = changegroup.combineresults(changes)
7229 elif isinstance(gen, streamclone.streamcloneapplier):
7215 elif isinstance(gen, streamclone.streamcloneapplier):
7230 raise error.Abort(
7216 raise error.Abort(
7231 _('packed bundles cannot be applied with '
7217 _('packed bundles cannot be applied with '
7232 '"hg unbundle"'),
7218 '"hg unbundle"'),
7233 hint=_('use "hg debugapplystreamclonebundle"'))
7219 hint=_('use "hg debugapplystreamclonebundle"'))
7234 else:
7220 else:
7235 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7221 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7236
7222
7237 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7223 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7238
7224
7239 @command('^update|up|checkout|co',
7225 @command('^update|up|checkout|co',
7240 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7226 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7241 ('c', 'check', None, _('require clean working directory')),
7227 ('c', 'check', None, _('require clean working directory')),
7242 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7228 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7243 ('r', 'rev', '', _('revision'), _('REV'))
7229 ('r', 'rev', '', _('revision'), _('REV'))
7244 ] + mergetoolopts,
7230 ] + mergetoolopts,
7245 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7231 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7246 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7232 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7247 tool=None):
7233 tool=None):
7248 """update working directory (or switch revisions)
7234 """update working directory (or switch revisions)
7249
7235
7250 Update the repository's working directory to the specified
7236 Update the repository's working directory to the specified
7251 changeset. If no changeset is specified, update to the tip of the
7237 changeset. If no changeset is specified, update to the tip of the
7252 current named branch and move the active bookmark (see :hg:`help
7238 current named branch and move the active bookmark (see :hg:`help
7253 bookmarks`).
7239 bookmarks`).
7254
7240
7255 Update sets the working directory's parent revision to the specified
7241 Update sets the working directory's parent revision to the specified
7256 changeset (see :hg:`help parents`).
7242 changeset (see :hg:`help parents`).
7257
7243
7258 If the changeset is not a descendant or ancestor of the working
7244 If the changeset is not a descendant or ancestor of the working
7259 directory's parent, the update is aborted. With the -c/--check
7245 directory's parent, the update is aborted. With the -c/--check
7260 option, the working directory is checked for uncommitted changes; if
7246 option, the working directory is checked for uncommitted changes; if
7261 none are found, the working directory is updated to the specified
7247 none are found, the working directory is updated to the specified
7262 changeset.
7248 changeset.
7263
7249
7264 .. container:: verbose
7250 .. container:: verbose
7265
7251
7266 The following rules apply when the working directory contains
7252 The following rules apply when the working directory contains
7267 uncommitted changes:
7253 uncommitted changes:
7268
7254
7269 1. If neither -c/--check nor -C/--clean is specified, and if
7255 1. If neither -c/--check nor -C/--clean is specified, and if
7270 the requested changeset is an ancestor or descendant of
7256 the requested changeset is an ancestor or descendant of
7271 the working directory's parent, the uncommitted changes
7257 the working directory's parent, the uncommitted changes
7272 are merged into the requested changeset and the merged
7258 are merged into the requested changeset and the merged
7273 result is left uncommitted. If the requested changeset is
7259 result is left uncommitted. If the requested changeset is
7274 not an ancestor or descendant (that is, it is on another
7260 not an ancestor or descendant (that is, it is on another
7275 branch), the update is aborted and the uncommitted changes
7261 branch), the update is aborted and the uncommitted changes
7276 are preserved.
7262 are preserved.
7277
7263
7278 2. With the -c/--check option, the update is aborted and the
7264 2. With the -c/--check option, the update is aborted and the
7279 uncommitted changes are preserved.
7265 uncommitted changes are preserved.
7280
7266
7281 3. With the -C/--clean option, uncommitted changes are discarded and
7267 3. With the -C/--clean option, uncommitted changes are discarded and
7282 the working directory is updated to the requested changeset.
7268 the working directory is updated to the requested changeset.
7283
7269
7284 To cancel an uncommitted merge (and lose your changes), use
7270 To cancel an uncommitted merge (and lose your changes), use
7285 :hg:`update --clean .`.
7271 :hg:`update --clean .`.
7286
7272
7287 Use null as the changeset to remove the working directory (like
7273 Use null as the changeset to remove the working directory (like
7288 :hg:`clone -U`).
7274 :hg:`clone -U`).
7289
7275
7290 If you want to revert just one file to an older revision, use
7276 If you want to revert just one file to an older revision, use
7291 :hg:`revert [-r REV] NAME`.
7277 :hg:`revert [-r REV] NAME`.
7292
7278
7293 See :hg:`help dates` for a list of formats valid for -d/--date.
7279 See :hg:`help dates` for a list of formats valid for -d/--date.
7294
7280
7295 Returns 0 on success, 1 if there are unresolved files.
7281 Returns 0 on success, 1 if there are unresolved files.
7296 """
7282 """
7297 if rev and node:
7283 if rev and node:
7298 raise error.Abort(_("please specify just one revision"))
7284 raise error.Abort(_("please specify just one revision"))
7299
7285
7300 if rev is None or rev == '':
7286 if rev is None or rev == '':
7301 rev = node
7287 rev = node
7302
7288
7303 if date and rev is not None:
7289 if date and rev is not None:
7304 raise error.Abort(_("you can't specify a revision and a date"))
7290 raise error.Abort(_("you can't specify a revision and a date"))
7305
7291
7306 if check and clean:
7292 if check and clean:
7307 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7293 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7308
7294
7309 with repo.wlock():
7295 with repo.wlock():
7310 cmdutil.clearunfinished(repo)
7296 cmdutil.clearunfinished(repo)
7311
7297
7312 if date:
7298 if date:
7313 rev = cmdutil.finddate(ui, repo, date)
7299 rev = cmdutil.finddate(ui, repo, date)
7314
7300
7315 # if we defined a bookmark, we have to remember the original name
7301 # if we defined a bookmark, we have to remember the original name
7316 brev = rev
7302 brev = rev
7317 rev = scmutil.revsingle(repo, rev, rev).rev()
7303 rev = scmutil.revsingle(repo, rev, rev).rev()
7318
7304
7319 if check:
7305 if check:
7320 cmdutil.bailifchanged(repo, merge=False)
7306 cmdutil.bailifchanged(repo, merge=False)
7321
7307
7322 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7308 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7323
7309
7324 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7310 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7325
7311
7326 @command('verify', [])
7312 @command('verify', [])
7327 def verify(ui, repo):
7313 def verify(ui, repo):
7328 """verify the integrity of the repository
7314 """verify the integrity of the repository
7329
7315
7330 Verify the integrity of the current repository.
7316 Verify the integrity of the current repository.
7331
7317
7332 This will perform an extensive check of the repository's
7318 This will perform an extensive check of the repository's
7333 integrity, validating the hashes and checksums of each entry in
7319 integrity, validating the hashes and checksums of each entry in
7334 the changelog, manifest, and tracked files, as well as the
7320 the changelog, manifest, and tracked files, as well as the
7335 integrity of their crosslinks and indices.
7321 integrity of their crosslinks and indices.
7336
7322
7337 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7323 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7338 for more information about recovery from corruption of the
7324 for more information about recovery from corruption of the
7339 repository.
7325 repository.
7340
7326
7341 Returns 0 on success, 1 if errors are encountered.
7327 Returns 0 on success, 1 if errors are encountered.
7342 """
7328 """
7343 return hg.verify(repo)
7329 return hg.verify(repo)
7344
7330
7345 @command('version', [] + formatteropts, norepo=True)
7331 @command('version', [] + formatteropts, norepo=True)
7346 def version_(ui, **opts):
7332 def version_(ui, **opts):
7347 """output version and copyright information"""
7333 """output version and copyright information"""
7348 fm = ui.formatter("version", opts)
7334 fm = ui.formatter("version", opts)
7349 fm.startitem()
7335 fm.startitem()
7350 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7336 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7351 util.version())
7337 util.version())
7352 license = _(
7338 license = _(
7353 "(see https://mercurial-scm.org for more information)\n"
7339 "(see https://mercurial-scm.org for more information)\n"
7354 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7340 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7355 "This is free software; see the source for copying conditions. "
7341 "This is free software; see the source for copying conditions. "
7356 "There is NO\nwarranty; "
7342 "There is NO\nwarranty; "
7357 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7343 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7358 )
7344 )
7359 if not ui.quiet:
7345 if not ui.quiet:
7360 fm.plain(license)
7346 fm.plain(license)
7361
7347
7362 if ui.verbose:
7348 if ui.verbose:
7363 fm.plain(_("\nEnabled extensions:\n\n"))
7349 fm.plain(_("\nEnabled extensions:\n\n"))
7364 # format names and versions into columns
7350 # format names and versions into columns
7365 names = []
7351 names = []
7366 vers = []
7352 vers = []
7367 isinternals = []
7353 isinternals = []
7368 for name, module in extensions.extensions():
7354 for name, module in extensions.extensions():
7369 names.append(name)
7355 names.append(name)
7370 vers.append(extensions.moduleversion(module) or None)
7356 vers.append(extensions.moduleversion(module) or None)
7371 isinternals.append(extensions.ismoduleinternal(module))
7357 isinternals.append(extensions.ismoduleinternal(module))
7372 fn = fm.nested("extensions")
7358 fn = fm.nested("extensions")
7373 if names:
7359 if names:
7374 namefmt = " %%-%ds " % max(len(n) for n in names)
7360 namefmt = " %%-%ds " % max(len(n) for n in names)
7375 places = [_("external"), _("internal")]
7361 places = [_("external"), _("internal")]
7376 for n, v, p in zip(names, vers, isinternals):
7362 for n, v, p in zip(names, vers, isinternals):
7377 fn.startitem()
7363 fn.startitem()
7378 fn.condwrite(ui.verbose, "name", namefmt, n)
7364 fn.condwrite(ui.verbose, "name", namefmt, n)
7379 if ui.verbose:
7365 if ui.verbose:
7380 fn.plain("%s " % places[p])
7366 fn.plain("%s " % places[p])
7381 fn.data(bundled=p)
7367 fn.data(bundled=p)
7382 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7368 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7383 if ui.verbose:
7369 if ui.verbose:
7384 fn.plain("\n")
7370 fn.plain("\n")
7385 fn.end()
7371 fn.end()
7386 fm.end()
7372 fm.end()
7387
7373
7388 def loadcmdtable(ui, name, cmdtable):
7374 def loadcmdtable(ui, name, cmdtable):
7389 """Load command functions from specified cmdtable
7375 """Load command functions from specified cmdtable
7390 """
7376 """
7391 overrides = [cmd for cmd in cmdtable if cmd in table]
7377 overrides = [cmd for cmd in cmdtable if cmd in table]
7392 if overrides:
7378 if overrides:
7393 ui.warn(_("extension '%s' overrides commands: %s\n")
7379 ui.warn(_("extension '%s' overrides commands: %s\n")
7394 % (name, " ".join(overrides)))
7380 % (name, " ".join(overrides)))
7395 table.update(cmdtable)
7381 table.update(cmdtable)
@@ -1,268 +1,281 b''
1 # changelog bisection for mercurial
1 # changelog bisection for mercurial
2 #
2 #
3 # Copyright 2007 Matt Mackall
3 # Copyright 2007 Matt Mackall
4 # Copyright 2005, 2006 Benoit Boissinot <benoit.boissinot@ens-lyon.org>
4 # Copyright 2005, 2006 Benoit Boissinot <benoit.boissinot@ens-lyon.org>
5 #
5 #
6 # Inspired by git bisect, extension skeleton taken from mq.py.
6 # Inspired by git bisect, extension skeleton taken from mq.py.
7 #
7 #
8 # This software may be used and distributed according to the terms of the
8 # This software may be used and distributed according to the terms of the
9 # GNU General Public License version 2 or any later version.
9 # GNU General Public License version 2 or any later version.
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12
12
13 import collections
13 import collections
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 hex,
17 hex,
18 short,
18 short,
19 )
19 )
20 from . import (
20 from . import (
21 error,
21 error,
22 )
22 )
23
23
24 def bisect(changelog, state):
24 def bisect(changelog, state):
25 """find the next node (if any) for testing during a bisect search.
25 """find the next node (if any) for testing during a bisect search.
26 returns a (nodes, number, good) tuple.
26 returns a (nodes, number, good) tuple.
27
27
28 'nodes' is the final result of the bisect if 'number' is 0.
28 'nodes' is the final result of the bisect if 'number' is 0.
29 Otherwise 'number' indicates the remaining possible candidates for
29 Otherwise 'number' indicates the remaining possible candidates for
30 the search and 'nodes' contains the next bisect target.
30 the search and 'nodes' contains the next bisect target.
31 'good' is True if bisect is searching for a first good changeset, False
31 'good' is True if bisect is searching for a first good changeset, False
32 if searching for a first bad one.
32 if searching for a first bad one.
33 """
33 """
34
34
35 clparents = changelog.parentrevs
35 clparents = changelog.parentrevs
36 skip = set([changelog.rev(n) for n in state['skip']])
36 skip = set([changelog.rev(n) for n in state['skip']])
37
37
38 def buildancestors(bad, good):
38 def buildancestors(bad, good):
39 # only the earliest bad revision matters
39 # only the earliest bad revision matters
40 badrev = min([changelog.rev(n) for n in bad])
40 badrev = min([changelog.rev(n) for n in bad])
41 goodrevs = [changelog.rev(n) for n in good]
41 goodrevs = [changelog.rev(n) for n in good]
42 goodrev = min(goodrevs)
42 goodrev = min(goodrevs)
43 # build visit array
43 # build visit array
44 ancestors = [None] * (len(changelog) + 1) # an extra for [-1]
44 ancestors = [None] * (len(changelog) + 1) # an extra for [-1]
45
45
46 # set nodes descended from goodrevs
46 # set nodes descended from goodrevs
47 for rev in goodrevs:
47 for rev in goodrevs:
48 ancestors[rev] = []
48 ancestors[rev] = []
49 for rev in changelog.revs(goodrev + 1):
49 for rev in changelog.revs(goodrev + 1):
50 for prev in clparents(rev):
50 for prev in clparents(rev):
51 if ancestors[prev] == []:
51 if ancestors[prev] == []:
52 ancestors[rev] = []
52 ancestors[rev] = []
53
53
54 # clear good revs from array
54 # clear good revs from array
55 for rev in goodrevs:
55 for rev in goodrevs:
56 ancestors[rev] = None
56 ancestors[rev] = None
57 for rev in changelog.revs(len(changelog), goodrev):
57 for rev in changelog.revs(len(changelog), goodrev):
58 if ancestors[rev] is None:
58 if ancestors[rev] is None:
59 for prev in clparents(rev):
59 for prev in clparents(rev):
60 ancestors[prev] = None
60 ancestors[prev] = None
61
61
62 if ancestors[badrev] is None:
62 if ancestors[badrev] is None:
63 return badrev, None
63 return badrev, None
64 return badrev, ancestors
64 return badrev, ancestors
65
65
66 good = False
66 good = False
67 badrev, ancestors = buildancestors(state['bad'], state['good'])
67 badrev, ancestors = buildancestors(state['bad'], state['good'])
68 if not ancestors: # looking for bad to good transition?
68 if not ancestors: # looking for bad to good transition?
69 good = True
69 good = True
70 badrev, ancestors = buildancestors(state['good'], state['bad'])
70 badrev, ancestors = buildancestors(state['good'], state['bad'])
71 bad = changelog.node(badrev)
71 bad = changelog.node(badrev)
72 if not ancestors: # now we're confused
72 if not ancestors: # now we're confused
73 if (len(state['bad']) == 1 and len(state['good']) == 1 and
73 if (len(state['bad']) == 1 and len(state['good']) == 1 and
74 state['bad'] != state['good']):
74 state['bad'] != state['good']):
75 raise error.Abort(_("starting revisions are not directly related"))
75 raise error.Abort(_("starting revisions are not directly related"))
76 raise error.Abort(_("inconsistent state, %s:%s is good and bad")
76 raise error.Abort(_("inconsistent state, %s:%s is good and bad")
77 % (badrev, short(bad)))
77 % (badrev, short(bad)))
78
78
79 # build children dict
79 # build children dict
80 children = {}
80 children = {}
81 visit = collections.deque([badrev])
81 visit = collections.deque([badrev])
82 candidates = []
82 candidates = []
83 while visit:
83 while visit:
84 rev = visit.popleft()
84 rev = visit.popleft()
85 if ancestors[rev] == []:
85 if ancestors[rev] == []:
86 candidates.append(rev)
86 candidates.append(rev)
87 for prev in clparents(rev):
87 for prev in clparents(rev):
88 if prev != -1:
88 if prev != -1:
89 if prev in children:
89 if prev in children:
90 children[prev].append(rev)
90 children[prev].append(rev)
91 else:
91 else:
92 children[prev] = [rev]
92 children[prev] = [rev]
93 visit.append(prev)
93 visit.append(prev)
94
94
95 candidates.sort()
95 candidates.sort()
96 # have we narrowed it down to one entry?
96 # have we narrowed it down to one entry?
97 # or have all other possible candidates besides 'bad' have been skipped?
97 # or have all other possible candidates besides 'bad' have been skipped?
98 tot = len(candidates)
98 tot = len(candidates)
99 unskipped = [c for c in candidates if (c not in skip) and (c != badrev)]
99 unskipped = [c for c in candidates if (c not in skip) and (c != badrev)]
100 if tot == 1 or not unskipped:
100 if tot == 1 or not unskipped:
101 return ([changelog.node(rev) for rev in candidates], 0, good)
101 return ([changelog.node(rev) for rev in candidates], 0, good)
102 perfect = tot // 2
102 perfect = tot // 2
103
103
104 # find the best node to test
104 # find the best node to test
105 best_rev = None
105 best_rev = None
106 best_len = -1
106 best_len = -1
107 poison = set()
107 poison = set()
108 for rev in candidates:
108 for rev in candidates:
109 if rev in poison:
109 if rev in poison:
110 # poison children
110 # poison children
111 poison.update(children.get(rev, []))
111 poison.update(children.get(rev, []))
112 continue
112 continue
113
113
114 a = ancestors[rev] or [rev]
114 a = ancestors[rev] or [rev]
115 ancestors[rev] = None
115 ancestors[rev] = None
116
116
117 x = len(a) # number of ancestors
117 x = len(a) # number of ancestors
118 y = tot - x # number of non-ancestors
118 y = tot - x # number of non-ancestors
119 value = min(x, y) # how good is this test?
119 value = min(x, y) # how good is this test?
120 if value > best_len and rev not in skip:
120 if value > best_len and rev not in skip:
121 best_len = value
121 best_len = value
122 best_rev = rev
122 best_rev = rev
123 if value == perfect: # found a perfect candidate? quit early
123 if value == perfect: # found a perfect candidate? quit early
124 break
124 break
125
125
126 if y < perfect and rev not in skip: # all downhill from here?
126 if y < perfect and rev not in skip: # all downhill from here?
127 # poison children
127 # poison children
128 poison.update(children.get(rev, []))
128 poison.update(children.get(rev, []))
129 continue
129 continue
130
130
131 for c in children.get(rev, []):
131 for c in children.get(rev, []):
132 if ancestors[c]:
132 if ancestors[c]:
133 ancestors[c] = list(set(ancestors[c] + a))
133 ancestors[c] = list(set(ancestors[c] + a))
134 else:
134 else:
135 ancestors[c] = a + [c]
135 ancestors[c] = a + [c]
136
136
137 assert best_rev is not None
137 assert best_rev is not None
138 best_node = changelog.node(best_rev)
138 best_node = changelog.node(best_rev)
139
139
140 return ([best_node], tot, good)
140 return ([best_node], tot, good)
141
141
142 def extendrange(repo, state, nodes, good):
143 # bisect is incomplete when it ends on a merge node and
144 # one of the parent was not checked.
145 parents = repo[nodes[0]].parents()
146 if len(parents) > 1:
147 if good:
148 side = state['bad']
149 else:
150 side = state['good']
151 num = len(set(i.node() for i in parents) & set(side))
152 if num == 1:
153 return parents[0].ancestor(parents[1])
154 return None
142
155
143 def load_state(repo):
156 def load_state(repo):
144 state = {'current': [], 'good': [], 'bad': [], 'skip': []}
157 state = {'current': [], 'good': [], 'bad': [], 'skip': []}
145 for l in repo.vfs.tryreadlines("bisect.state"):
158 for l in repo.vfs.tryreadlines("bisect.state"):
146 kind, node = l[:-1].split()
159 kind, node = l[:-1].split()
147 node = repo.lookup(node)
160 node = repo.lookup(node)
148 if kind not in state:
161 if kind not in state:
149 raise error.Abort(_("unknown bisect kind %s") % kind)
162 raise error.Abort(_("unknown bisect kind %s") % kind)
150 state[kind].append(node)
163 state[kind].append(node)
151 return state
164 return state
152
165
153
166
154 def save_state(repo, state):
167 def save_state(repo, state):
155 f = repo.vfs("bisect.state", "w", atomictemp=True)
168 f = repo.vfs("bisect.state", "w", atomictemp=True)
156 with repo.wlock():
169 with repo.wlock():
157 for kind in sorted(state):
170 for kind in sorted(state):
158 for node in state[kind]:
171 for node in state[kind]:
159 f.write("%s %s\n" % (kind, hex(node)))
172 f.write("%s %s\n" % (kind, hex(node)))
160 f.close()
173 f.close()
161
174
162 def resetstate(repo):
175 def resetstate(repo):
163 """remove any bisect state from the repository"""
176 """remove any bisect state from the repository"""
164 if repo.vfs.exists("bisect.state"):
177 if repo.vfs.exists("bisect.state"):
165 repo.vfs.unlink("bisect.state")
178 repo.vfs.unlink("bisect.state")
166
179
167 def get(repo, status):
180 def get(repo, status):
168 """
181 """
169 Return a list of revision(s) that match the given status:
182 Return a list of revision(s) that match the given status:
170
183
171 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
184 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
172 - ``goods``, ``bads`` : csets topologically good/bad
185 - ``goods``, ``bads`` : csets topologically good/bad
173 - ``range`` : csets taking part in the bisection
186 - ``range`` : csets taking part in the bisection
174 - ``pruned`` : csets that are goods, bads or skipped
187 - ``pruned`` : csets that are goods, bads or skipped
175 - ``untested`` : csets whose fate is yet unknown
188 - ``untested`` : csets whose fate is yet unknown
176 - ``ignored`` : csets ignored due to DAG topology
189 - ``ignored`` : csets ignored due to DAG topology
177 - ``current`` : the cset currently being bisected
190 - ``current`` : the cset currently being bisected
178 """
191 """
179 state = load_state(repo)
192 state = load_state(repo)
180 if status in ('good', 'bad', 'skip', 'current'):
193 if status in ('good', 'bad', 'skip', 'current'):
181 return map(repo.changelog.rev, state[status])
194 return map(repo.changelog.rev, state[status])
182 else:
195 else:
183 # In the following sets, we do *not* call 'bisect()' with more
196 # In the following sets, we do *not* call 'bisect()' with more
184 # than one level of recursion, because that can be very, very
197 # than one level of recursion, because that can be very, very
185 # time consuming. Instead, we always develop the expression as
198 # time consuming. Instead, we always develop the expression as
186 # much as possible.
199 # much as possible.
187
200
188 # 'range' is all csets that make the bisection:
201 # 'range' is all csets that make the bisection:
189 # - have a good ancestor and a bad descendant, or conversely
202 # - have a good ancestor and a bad descendant, or conversely
190 # that's because the bisection can go either way
203 # that's because the bisection can go either way
191 range = '( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
204 range = '( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
192
205
193 _t = repo.revs('bisect(good)::bisect(bad)')
206 _t = repo.revs('bisect(good)::bisect(bad)')
194 # The sets of topologically good or bad csets
207 # The sets of topologically good or bad csets
195 if len(_t) == 0:
208 if len(_t) == 0:
196 # Goods are topologically after bads
209 # Goods are topologically after bads
197 goods = 'bisect(good)::' # Pruned good csets
210 goods = 'bisect(good)::' # Pruned good csets
198 bads = '::bisect(bad)' # Pruned bad csets
211 bads = '::bisect(bad)' # Pruned bad csets
199 else:
212 else:
200 # Goods are topologically before bads
213 # Goods are topologically before bads
201 goods = '::bisect(good)' # Pruned good csets
214 goods = '::bisect(good)' # Pruned good csets
202 bads = 'bisect(bad)::' # Pruned bad csets
215 bads = 'bisect(bad)::' # Pruned bad csets
203
216
204 # 'pruned' is all csets whose fate is already known: good, bad, skip
217 # 'pruned' is all csets whose fate is already known: good, bad, skip
205 skips = 'bisect(skip)' # Pruned skipped csets
218 skips = 'bisect(skip)' # Pruned skipped csets
206 pruned = '( (%s) | (%s) | (%s) )' % (goods, bads, skips)
219 pruned = '( (%s) | (%s) | (%s) )' % (goods, bads, skips)
207
220
208 # 'untested' is all cset that are- in 'range', but not in 'pruned'
221 # 'untested' is all cset that are- in 'range', but not in 'pruned'
209 untested = '( (%s) - (%s) )' % (range, pruned)
222 untested = '( (%s) - (%s) )' % (range, pruned)
210
223
211 # 'ignored' is all csets that were not used during the bisection
224 # 'ignored' is all csets that were not used during the bisection
212 # due to DAG topology, but may however have had an impact.
225 # due to DAG topology, but may however have had an impact.
213 # E.g., a branch merged between bads and goods, but whose branch-
226 # E.g., a branch merged between bads and goods, but whose branch-
214 # point is out-side of the range.
227 # point is out-side of the range.
215 iba = '::bisect(bad) - ::bisect(good)' # Ignored bads' ancestors
228 iba = '::bisect(bad) - ::bisect(good)' # Ignored bads' ancestors
216 iga = '::bisect(good) - ::bisect(bad)' # Ignored goods' ancestors
229 iga = '::bisect(good) - ::bisect(bad)' # Ignored goods' ancestors
217 ignored = '( ( (%s) | (%s) ) - (%s) )' % (iba, iga, range)
230 ignored = '( ( (%s) | (%s) ) - (%s) )' % (iba, iga, range)
218
231
219 if status == 'range':
232 if status == 'range':
220 return repo.revs(range)
233 return repo.revs(range)
221 elif status == 'pruned':
234 elif status == 'pruned':
222 return repo.revs(pruned)
235 return repo.revs(pruned)
223 elif status == 'untested':
236 elif status == 'untested':
224 return repo.revs(untested)
237 return repo.revs(untested)
225 elif status == 'ignored':
238 elif status == 'ignored':
226 return repo.revs(ignored)
239 return repo.revs(ignored)
227 elif status == "goods":
240 elif status == "goods":
228 return repo.revs(goods)
241 return repo.revs(goods)
229 elif status == "bads":
242 elif status == "bads":
230 return repo.revs(bads)
243 return repo.revs(bads)
231 else:
244 else:
232 raise error.ParseError(_('invalid bisect state'))
245 raise error.ParseError(_('invalid bisect state'))
233
246
234 def label(repo, node):
247 def label(repo, node):
235 rev = repo.changelog.rev(node)
248 rev = repo.changelog.rev(node)
236
249
237 # Try explicit sets
250 # Try explicit sets
238 if rev in get(repo, 'good'):
251 if rev in get(repo, 'good'):
239 # i18n: bisect changeset status
252 # i18n: bisect changeset status
240 return _('good')
253 return _('good')
241 if rev in get(repo, 'bad'):
254 if rev in get(repo, 'bad'):
242 # i18n: bisect changeset status
255 # i18n: bisect changeset status
243 return _('bad')
256 return _('bad')
244 if rev in get(repo, 'skip'):
257 if rev in get(repo, 'skip'):
245 # i18n: bisect changeset status
258 # i18n: bisect changeset status
246 return _('skipped')
259 return _('skipped')
247 if rev in get(repo, 'untested') or rev in get(repo, 'current'):
260 if rev in get(repo, 'untested') or rev in get(repo, 'current'):
248 # i18n: bisect changeset status
261 # i18n: bisect changeset status
249 return _('untested')
262 return _('untested')
250 if rev in get(repo, 'ignored'):
263 if rev in get(repo, 'ignored'):
251 # i18n: bisect changeset status
264 # i18n: bisect changeset status
252 return _('ignored')
265 return _('ignored')
253
266
254 # Try implicit sets
267 # Try implicit sets
255 if rev in get(repo, 'goods'):
268 if rev in get(repo, 'goods'):
256 # i18n: bisect changeset status
269 # i18n: bisect changeset status
257 return _('good (implicit)')
270 return _('good (implicit)')
258 if rev in get(repo, 'bads'):
271 if rev in get(repo, 'bads'):
259 # i18n: bisect changeset status
272 # i18n: bisect changeset status
260 return _('bad (implicit)')
273 return _('bad (implicit)')
261
274
262 return None
275 return None
263
276
264 def shortlabel(label):
277 def shortlabel(label):
265 if label:
278 if label:
266 return label[0].upper()
279 return label[0].upper()
267
280
268 return None
281 return None
General Comments 0
You need to be logged in to leave comments. Login now