##// END OF EJS Templates
commit: return 1 for interactive commit with no changes (issue5397)...
Philippe Pepiot -
r30157:df224038 default
parent child Browse files
Show More
@@ -1,7346 +1,7348 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 # backward compatibility
838 # backward compatibility
839 if rev in "good bad reset init".split():
839 if rev in "good bad reset init".split():
840 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
840 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
841 cmd, rev, extra = rev, extra, None
841 cmd, rev, extra = rev, extra, None
842 if cmd == "good":
842 if cmd == "good":
843 good = True
843 good = True
844 elif cmd == "bad":
844 elif cmd == "bad":
845 bad = True
845 bad = True
846 else:
846 else:
847 reset = True
847 reset = True
848 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
848 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
849 raise error.Abort(_('incompatible arguments'))
849 raise error.Abort(_('incompatible arguments'))
850
850
851 cmdutil.checkunfinished(repo)
851 cmdutil.checkunfinished(repo)
852
852
853 if reset:
853 if reset:
854 hbisect.resetstate(repo)
854 hbisect.resetstate(repo)
855 return
855 return
856
856
857 state = hbisect.load_state(repo)
857 state = hbisect.load_state(repo)
858
858
859 # update state
859 # update state
860 if good or bad or skip:
860 if good or bad or skip:
861 if rev:
861 if rev:
862 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
862 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
863 else:
863 else:
864 nodes = [repo.lookup('.')]
864 nodes = [repo.lookup('.')]
865 if good:
865 if good:
866 state['good'] += nodes
866 state['good'] += nodes
867 elif bad:
867 elif bad:
868 state['bad'] += nodes
868 state['bad'] += nodes
869 elif skip:
869 elif skip:
870 state['skip'] += nodes
870 state['skip'] += nodes
871 hbisect.save_state(repo, state)
871 hbisect.save_state(repo, state)
872 if not (state['good'] and state['bad']):
872 if not (state['good'] and state['bad']):
873 return
873 return
874
874
875 def mayupdate(repo, node, show_stats=True):
875 def mayupdate(repo, node, show_stats=True):
876 """common used update sequence"""
876 """common used update sequence"""
877 if noupdate:
877 if noupdate:
878 return
878 return
879 cmdutil.bailifchanged(repo)
879 cmdutil.bailifchanged(repo)
880 return hg.clean(repo, node, show_stats=show_stats)
880 return hg.clean(repo, node, show_stats=show_stats)
881
881
882 displayer = cmdutil.show_changeset(ui, repo, {})
882 displayer = cmdutil.show_changeset(ui, repo, {})
883
883
884 if command:
884 if command:
885 changesets = 1
885 changesets = 1
886 if noupdate:
886 if noupdate:
887 try:
887 try:
888 node = state['current'][0]
888 node = state['current'][0]
889 except LookupError:
889 except LookupError:
890 raise error.Abort(_('current bisect revision is unknown - '
890 raise error.Abort(_('current bisect revision is unknown - '
891 'start a new bisect to fix'))
891 'start a new bisect to fix'))
892 else:
892 else:
893 node, p2 = repo.dirstate.parents()
893 node, p2 = repo.dirstate.parents()
894 if p2 != nullid:
894 if p2 != nullid:
895 raise error.Abort(_('current bisect revision is a merge'))
895 raise error.Abort(_('current bisect revision is a merge'))
896 if rev:
896 if rev:
897 node = repo[scmutil.revsingle(repo, rev, node)].node()
897 node = repo[scmutil.revsingle(repo, rev, node)].node()
898 try:
898 try:
899 while changesets:
899 while changesets:
900 # update state
900 # update state
901 state['current'] = [node]
901 state['current'] = [node]
902 hbisect.save_state(repo, state)
902 hbisect.save_state(repo, state)
903 status = ui.system(command, environ={'HG_NODE': hex(node)})
903 status = ui.system(command, environ={'HG_NODE': hex(node)})
904 if status == 125:
904 if status == 125:
905 transition = "skip"
905 transition = "skip"
906 elif status == 0:
906 elif status == 0:
907 transition = "good"
907 transition = "good"
908 # status < 0 means process was killed
908 # status < 0 means process was killed
909 elif status == 127:
909 elif status == 127:
910 raise error.Abort(_("failed to execute %s") % command)
910 raise error.Abort(_("failed to execute %s") % command)
911 elif status < 0:
911 elif status < 0:
912 raise error.Abort(_("%s killed") % command)
912 raise error.Abort(_("%s killed") % command)
913 else:
913 else:
914 transition = "bad"
914 transition = "bad"
915 state[transition].append(node)
915 state[transition].append(node)
916 ctx = repo[node]
916 ctx = repo[node]
917 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
917 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
918 hbisect.checkstate(state)
918 hbisect.checkstate(state)
919 # bisect
919 # bisect
920 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
920 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
921 # update to next check
921 # update to next check
922 node = nodes[0]
922 node = nodes[0]
923 mayupdate(repo, node, show_stats=False)
923 mayupdate(repo, node, show_stats=False)
924 finally:
924 finally:
925 state['current'] = [node]
925 state['current'] = [node]
926 hbisect.save_state(repo, state)
926 hbisect.save_state(repo, state)
927 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
927 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
928 return
928 return
929
929
930 hbisect.checkstate(state)
930 hbisect.checkstate(state)
931
931
932 # actually bisect
932 # actually bisect
933 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
933 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
934 if extend:
934 if extend:
935 if not changesets:
935 if not changesets:
936 extendnode = hbisect.extendrange(repo, state, nodes, good)
936 extendnode = hbisect.extendrange(repo, state, nodes, good)
937 if extendnode is not None:
937 if extendnode is not None:
938 ui.write(_("Extending search to changeset %d:%s\n")
938 ui.write(_("Extending search to changeset %d:%s\n")
939 % (extendnode.rev(), extendnode))
939 % (extendnode.rev(), extendnode))
940 state['current'] = [extendnode.node()]
940 state['current'] = [extendnode.node()]
941 hbisect.save_state(repo, state)
941 hbisect.save_state(repo, state)
942 return mayupdate(repo, extendnode.node())
942 return mayupdate(repo, extendnode.node())
943 raise error.Abort(_("nothing to extend"))
943 raise error.Abort(_("nothing to extend"))
944
944
945 if changesets == 0:
945 if changesets == 0:
946 hbisect.printresult(ui, repo, state, displayer, nodes, good)
946 hbisect.printresult(ui, repo, state, displayer, nodes, good)
947 else:
947 else:
948 assert len(nodes) == 1 # only a single node can be tested next
948 assert len(nodes) == 1 # only a single node can be tested next
949 node = nodes[0]
949 node = nodes[0]
950 # compute the approximate number of remaining tests
950 # compute the approximate number of remaining tests
951 tests, size = 0, 2
951 tests, size = 0, 2
952 while size <= changesets:
952 while size <= changesets:
953 tests, size = tests + 1, size * 2
953 tests, size = tests + 1, size * 2
954 rev = repo.changelog.rev(node)
954 rev = repo.changelog.rev(node)
955 ui.write(_("Testing changeset %d:%s "
955 ui.write(_("Testing changeset %d:%s "
956 "(%d changesets remaining, ~%d tests)\n")
956 "(%d changesets remaining, ~%d tests)\n")
957 % (rev, short(node), changesets, tests))
957 % (rev, short(node), changesets, tests))
958 state['current'] = [node]
958 state['current'] = [node]
959 hbisect.save_state(repo, state)
959 hbisect.save_state(repo, state)
960 return mayupdate(repo, node)
960 return mayupdate(repo, node)
961
961
962 @command('bookmarks|bookmark',
962 @command('bookmarks|bookmark',
963 [('f', 'force', False, _('force')),
963 [('f', 'force', False, _('force')),
964 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
964 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
965 ('d', 'delete', False, _('delete a given bookmark')),
965 ('d', 'delete', False, _('delete a given bookmark')),
966 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
966 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
967 ('i', 'inactive', False, _('mark a bookmark inactive')),
967 ('i', 'inactive', False, _('mark a bookmark inactive')),
968 ] + formatteropts,
968 ] + formatteropts,
969 _('hg bookmarks [OPTIONS]... [NAME]...'))
969 _('hg bookmarks [OPTIONS]... [NAME]...'))
970 def bookmark(ui, repo, *names, **opts):
970 def bookmark(ui, repo, *names, **opts):
971 '''create a new bookmark or list existing bookmarks
971 '''create a new bookmark or list existing bookmarks
972
972
973 Bookmarks are labels on changesets to help track lines of development.
973 Bookmarks are labels on changesets to help track lines of development.
974 Bookmarks are unversioned and can be moved, renamed and deleted.
974 Bookmarks are unversioned and can be moved, renamed and deleted.
975 Deleting or moving a bookmark has no effect on the associated changesets.
975 Deleting or moving a bookmark has no effect on the associated changesets.
976
976
977 Creating or updating to a bookmark causes it to be marked as 'active'.
977 Creating or updating to a bookmark causes it to be marked as 'active'.
978 The active bookmark is indicated with a '*'.
978 The active bookmark is indicated with a '*'.
979 When a commit is made, the active bookmark will advance to the new commit.
979 When a commit is made, the active bookmark will advance to the new commit.
980 A plain :hg:`update` will also advance an active bookmark, if possible.
980 A plain :hg:`update` will also advance an active bookmark, if possible.
981 Updating away from a bookmark will cause it to be deactivated.
981 Updating away from a bookmark will cause it to be deactivated.
982
982
983 Bookmarks can be pushed and pulled between repositories (see
983 Bookmarks can be pushed and pulled between repositories (see
984 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
984 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
985 diverged, a new 'divergent bookmark' of the form 'name@path' will
985 diverged, a new 'divergent bookmark' of the form 'name@path' will
986 be created. Using :hg:`merge` will resolve the divergence.
986 be created. Using :hg:`merge` will resolve the divergence.
987
987
988 A bookmark named '@' has the special property that :hg:`clone` will
988 A bookmark named '@' has the special property that :hg:`clone` will
989 check it out by default if it exists.
989 check it out by default if it exists.
990
990
991 .. container:: verbose
991 .. container:: verbose
992
992
993 Examples:
993 Examples:
994
994
995 - create an active bookmark for a new line of development::
995 - create an active bookmark for a new line of development::
996
996
997 hg book new-feature
997 hg book new-feature
998
998
999 - create an inactive bookmark as a place marker::
999 - create an inactive bookmark as a place marker::
1000
1000
1001 hg book -i reviewed
1001 hg book -i reviewed
1002
1002
1003 - create an inactive bookmark on another changeset::
1003 - create an inactive bookmark on another changeset::
1004
1004
1005 hg book -r .^ tested
1005 hg book -r .^ tested
1006
1006
1007 - rename bookmark turkey to dinner::
1007 - rename bookmark turkey to dinner::
1008
1008
1009 hg book -m turkey dinner
1009 hg book -m turkey dinner
1010
1010
1011 - move the '@' bookmark from another branch::
1011 - move the '@' bookmark from another branch::
1012
1012
1013 hg book -f @
1013 hg book -f @
1014 '''
1014 '''
1015 force = opts.get('force')
1015 force = opts.get('force')
1016 rev = opts.get('rev')
1016 rev = opts.get('rev')
1017 delete = opts.get('delete')
1017 delete = opts.get('delete')
1018 rename = opts.get('rename')
1018 rename = opts.get('rename')
1019 inactive = opts.get('inactive')
1019 inactive = opts.get('inactive')
1020
1020
1021 def checkformat(mark):
1021 def checkformat(mark):
1022 mark = mark.strip()
1022 mark = mark.strip()
1023 if not mark:
1023 if not mark:
1024 raise error.Abort(_("bookmark names cannot consist entirely of "
1024 raise error.Abort(_("bookmark names cannot consist entirely of "
1025 "whitespace"))
1025 "whitespace"))
1026 scmutil.checknewlabel(repo, mark, 'bookmark')
1026 scmutil.checknewlabel(repo, mark, 'bookmark')
1027 return mark
1027 return mark
1028
1028
1029 def checkconflict(repo, mark, cur, force=False, target=None):
1029 def checkconflict(repo, mark, cur, force=False, target=None):
1030 if mark in marks and not force:
1030 if mark in marks and not force:
1031 if target:
1031 if target:
1032 if marks[mark] == target and target == cur:
1032 if marks[mark] == target and target == cur:
1033 # re-activating a bookmark
1033 # re-activating a bookmark
1034 return
1034 return
1035 anc = repo.changelog.ancestors([repo[target].rev()])
1035 anc = repo.changelog.ancestors([repo[target].rev()])
1036 bmctx = repo[marks[mark]]
1036 bmctx = repo[marks[mark]]
1037 divs = [repo[b].node() for b in marks
1037 divs = [repo[b].node() for b in marks
1038 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1038 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1039
1039
1040 # allow resolving a single divergent bookmark even if moving
1040 # allow resolving a single divergent bookmark even if moving
1041 # the bookmark across branches when a revision is specified
1041 # the bookmark across branches when a revision is specified
1042 # that contains a divergent bookmark
1042 # that contains a divergent bookmark
1043 if bmctx.rev() not in anc and target in divs:
1043 if bmctx.rev() not in anc and target in divs:
1044 bookmarks.deletedivergent(repo, [target], mark)
1044 bookmarks.deletedivergent(repo, [target], mark)
1045 return
1045 return
1046
1046
1047 deletefrom = [b for b in divs
1047 deletefrom = [b for b in divs
1048 if repo[b].rev() in anc or b == target]
1048 if repo[b].rev() in anc or b == target]
1049 bookmarks.deletedivergent(repo, deletefrom, mark)
1049 bookmarks.deletedivergent(repo, deletefrom, mark)
1050 if bookmarks.validdest(repo, bmctx, repo[target]):
1050 if bookmarks.validdest(repo, bmctx, repo[target]):
1051 ui.status(_("moving bookmark '%s' forward from %s\n") %
1051 ui.status(_("moving bookmark '%s' forward from %s\n") %
1052 (mark, short(bmctx.node())))
1052 (mark, short(bmctx.node())))
1053 return
1053 return
1054 raise error.Abort(_("bookmark '%s' already exists "
1054 raise error.Abort(_("bookmark '%s' already exists "
1055 "(use -f to force)") % mark)
1055 "(use -f to force)") % mark)
1056 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1056 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1057 and not force):
1057 and not force):
1058 raise error.Abort(
1058 raise error.Abort(
1059 _("a bookmark cannot have the name of an existing branch"))
1059 _("a bookmark cannot have the name of an existing branch"))
1060
1060
1061 if delete and rename:
1061 if delete and rename:
1062 raise error.Abort(_("--delete and --rename are incompatible"))
1062 raise error.Abort(_("--delete and --rename are incompatible"))
1063 if delete and rev:
1063 if delete and rev:
1064 raise error.Abort(_("--rev is incompatible with --delete"))
1064 raise error.Abort(_("--rev is incompatible with --delete"))
1065 if rename and rev:
1065 if rename and rev:
1066 raise error.Abort(_("--rev is incompatible with --rename"))
1066 raise error.Abort(_("--rev is incompatible with --rename"))
1067 if not names and (delete or rev):
1067 if not names and (delete or rev):
1068 raise error.Abort(_("bookmark name required"))
1068 raise error.Abort(_("bookmark name required"))
1069
1069
1070 if delete or rename or names or inactive:
1070 if delete or rename or names or inactive:
1071 wlock = lock = tr = None
1071 wlock = lock = tr = None
1072 try:
1072 try:
1073 wlock = repo.wlock()
1073 wlock = repo.wlock()
1074 lock = repo.lock()
1074 lock = repo.lock()
1075 cur = repo.changectx('.').node()
1075 cur = repo.changectx('.').node()
1076 marks = repo._bookmarks
1076 marks = repo._bookmarks
1077 if delete:
1077 if delete:
1078 tr = repo.transaction('bookmark')
1078 tr = repo.transaction('bookmark')
1079 for mark in names:
1079 for mark in names:
1080 if mark not in marks:
1080 if mark not in marks:
1081 raise error.Abort(_("bookmark '%s' does not exist") %
1081 raise error.Abort(_("bookmark '%s' does not exist") %
1082 mark)
1082 mark)
1083 if mark == repo._activebookmark:
1083 if mark == repo._activebookmark:
1084 bookmarks.deactivate(repo)
1084 bookmarks.deactivate(repo)
1085 del marks[mark]
1085 del marks[mark]
1086
1086
1087 elif rename:
1087 elif rename:
1088 tr = repo.transaction('bookmark')
1088 tr = repo.transaction('bookmark')
1089 if not names:
1089 if not names:
1090 raise error.Abort(_("new bookmark name required"))
1090 raise error.Abort(_("new bookmark name required"))
1091 elif len(names) > 1:
1091 elif len(names) > 1:
1092 raise error.Abort(_("only one new bookmark name allowed"))
1092 raise error.Abort(_("only one new bookmark name allowed"))
1093 mark = checkformat(names[0])
1093 mark = checkformat(names[0])
1094 if rename not in marks:
1094 if rename not in marks:
1095 raise error.Abort(_("bookmark '%s' does not exist")
1095 raise error.Abort(_("bookmark '%s' does not exist")
1096 % rename)
1096 % rename)
1097 checkconflict(repo, mark, cur, force)
1097 checkconflict(repo, mark, cur, force)
1098 marks[mark] = marks[rename]
1098 marks[mark] = marks[rename]
1099 if repo._activebookmark == rename and not inactive:
1099 if repo._activebookmark == rename and not inactive:
1100 bookmarks.activate(repo, mark)
1100 bookmarks.activate(repo, mark)
1101 del marks[rename]
1101 del marks[rename]
1102 elif names:
1102 elif names:
1103 tr = repo.transaction('bookmark')
1103 tr = repo.transaction('bookmark')
1104 newact = None
1104 newact = None
1105 for mark in names:
1105 for mark in names:
1106 mark = checkformat(mark)
1106 mark = checkformat(mark)
1107 if newact is None:
1107 if newact is None:
1108 newact = mark
1108 newact = mark
1109 if inactive and mark == repo._activebookmark:
1109 if inactive and mark == repo._activebookmark:
1110 bookmarks.deactivate(repo)
1110 bookmarks.deactivate(repo)
1111 return
1111 return
1112 tgt = cur
1112 tgt = cur
1113 if rev:
1113 if rev:
1114 tgt = scmutil.revsingle(repo, rev).node()
1114 tgt = scmutil.revsingle(repo, rev).node()
1115 checkconflict(repo, mark, cur, force, tgt)
1115 checkconflict(repo, mark, cur, force, tgt)
1116 marks[mark] = tgt
1116 marks[mark] = tgt
1117 if not inactive and cur == marks[newact] and not rev:
1117 if not inactive and cur == marks[newact] and not rev:
1118 bookmarks.activate(repo, newact)
1118 bookmarks.activate(repo, newact)
1119 elif cur != tgt and newact == repo._activebookmark:
1119 elif cur != tgt and newact == repo._activebookmark:
1120 bookmarks.deactivate(repo)
1120 bookmarks.deactivate(repo)
1121 elif inactive:
1121 elif inactive:
1122 if len(marks) == 0:
1122 if len(marks) == 0:
1123 ui.status(_("no bookmarks set\n"))
1123 ui.status(_("no bookmarks set\n"))
1124 elif not repo._activebookmark:
1124 elif not repo._activebookmark:
1125 ui.status(_("no active bookmark\n"))
1125 ui.status(_("no active bookmark\n"))
1126 else:
1126 else:
1127 bookmarks.deactivate(repo)
1127 bookmarks.deactivate(repo)
1128 if tr is not None:
1128 if tr is not None:
1129 marks.recordchange(tr)
1129 marks.recordchange(tr)
1130 tr.close()
1130 tr.close()
1131 finally:
1131 finally:
1132 lockmod.release(tr, lock, wlock)
1132 lockmod.release(tr, lock, wlock)
1133 else: # show bookmarks
1133 else: # show bookmarks
1134 fm = ui.formatter('bookmarks', opts)
1134 fm = ui.formatter('bookmarks', opts)
1135 hexfn = fm.hexfunc
1135 hexfn = fm.hexfunc
1136 marks = repo._bookmarks
1136 marks = repo._bookmarks
1137 if len(marks) == 0 and fm.isplain():
1137 if len(marks) == 0 and fm.isplain():
1138 ui.status(_("no bookmarks set\n"))
1138 ui.status(_("no bookmarks set\n"))
1139 for bmark, n in sorted(marks.iteritems()):
1139 for bmark, n in sorted(marks.iteritems()):
1140 active = repo._activebookmark
1140 active = repo._activebookmark
1141 if bmark == active:
1141 if bmark == active:
1142 prefix, label = '*', activebookmarklabel
1142 prefix, label = '*', activebookmarklabel
1143 else:
1143 else:
1144 prefix, label = ' ', ''
1144 prefix, label = ' ', ''
1145
1145
1146 fm.startitem()
1146 fm.startitem()
1147 if not ui.quiet:
1147 if not ui.quiet:
1148 fm.plain(' %s ' % prefix, label=label)
1148 fm.plain(' %s ' % prefix, label=label)
1149 fm.write('bookmark', '%s', bmark, label=label)
1149 fm.write('bookmark', '%s', bmark, label=label)
1150 pad = " " * (25 - encoding.colwidth(bmark))
1150 pad = " " * (25 - encoding.colwidth(bmark))
1151 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1151 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1152 repo.changelog.rev(n), hexfn(n), label=label)
1152 repo.changelog.rev(n), hexfn(n), label=label)
1153 fm.data(active=(bmark == active))
1153 fm.data(active=(bmark == active))
1154 fm.plain('\n')
1154 fm.plain('\n')
1155 fm.end()
1155 fm.end()
1156
1156
1157 @command('branch',
1157 @command('branch',
1158 [('f', 'force', None,
1158 [('f', 'force', None,
1159 _('set branch name even if it shadows an existing branch')),
1159 _('set branch name even if it shadows an existing branch')),
1160 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1160 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1161 _('[-fC] [NAME]'))
1161 _('[-fC] [NAME]'))
1162 def branch(ui, repo, label=None, **opts):
1162 def branch(ui, repo, label=None, **opts):
1163 """set or show the current branch name
1163 """set or show the current branch name
1164
1164
1165 .. note::
1165 .. note::
1166
1166
1167 Branch names are permanent and global. Use :hg:`bookmark` to create a
1167 Branch names are permanent and global. Use :hg:`bookmark` to create a
1168 light-weight bookmark instead. See :hg:`help glossary` for more
1168 light-weight bookmark instead. See :hg:`help glossary` for more
1169 information about named branches and bookmarks.
1169 information about named branches and bookmarks.
1170
1170
1171 With no argument, show the current branch name. With one argument,
1171 With no argument, show the current branch name. With one argument,
1172 set the working directory branch name (the branch will not exist
1172 set the working directory branch name (the branch will not exist
1173 in the repository until the next commit). Standard practice
1173 in the repository until the next commit). Standard practice
1174 recommends that primary development take place on the 'default'
1174 recommends that primary development take place on the 'default'
1175 branch.
1175 branch.
1176
1176
1177 Unless -f/--force is specified, branch will not let you set a
1177 Unless -f/--force is specified, branch will not let you set a
1178 branch name that already exists.
1178 branch name that already exists.
1179
1179
1180 Use -C/--clean to reset the working directory branch to that of
1180 Use -C/--clean to reset the working directory branch to that of
1181 the parent of the working directory, negating a previous branch
1181 the parent of the working directory, negating a previous branch
1182 change.
1182 change.
1183
1183
1184 Use the command :hg:`update` to switch to an existing branch. Use
1184 Use the command :hg:`update` to switch to an existing branch. Use
1185 :hg:`commit --close-branch` to mark this branch head as closed.
1185 :hg:`commit --close-branch` to mark this branch head as closed.
1186 When all heads of a branch are closed, the branch will be
1186 When all heads of a branch are closed, the branch will be
1187 considered closed.
1187 considered closed.
1188
1188
1189 Returns 0 on success.
1189 Returns 0 on success.
1190 """
1190 """
1191 if label:
1191 if label:
1192 label = label.strip()
1192 label = label.strip()
1193
1193
1194 if not opts.get('clean') and not label:
1194 if not opts.get('clean') and not label:
1195 ui.write("%s\n" % repo.dirstate.branch())
1195 ui.write("%s\n" % repo.dirstate.branch())
1196 return
1196 return
1197
1197
1198 with repo.wlock():
1198 with repo.wlock():
1199 if opts.get('clean'):
1199 if opts.get('clean'):
1200 label = repo[None].p1().branch()
1200 label = repo[None].p1().branch()
1201 repo.dirstate.setbranch(label)
1201 repo.dirstate.setbranch(label)
1202 ui.status(_('reset working directory to branch %s\n') % label)
1202 ui.status(_('reset working directory to branch %s\n') % label)
1203 elif label:
1203 elif label:
1204 if not opts.get('force') and label in repo.branchmap():
1204 if not opts.get('force') and label in repo.branchmap():
1205 if label not in [p.branch() for p in repo[None].parents()]:
1205 if label not in [p.branch() for p in repo[None].parents()]:
1206 raise error.Abort(_('a branch of the same name already'
1206 raise error.Abort(_('a branch of the same name already'
1207 ' exists'),
1207 ' exists'),
1208 # i18n: "it" refers to an existing branch
1208 # i18n: "it" refers to an existing branch
1209 hint=_("use 'hg update' to switch to it"))
1209 hint=_("use 'hg update' to switch to it"))
1210 scmutil.checknewlabel(repo, label, 'branch')
1210 scmutil.checknewlabel(repo, label, 'branch')
1211 repo.dirstate.setbranch(label)
1211 repo.dirstate.setbranch(label)
1212 ui.status(_('marked working directory as branch %s\n') % label)
1212 ui.status(_('marked working directory as branch %s\n') % label)
1213
1213
1214 # find any open named branches aside from default
1214 # find any open named branches aside from default
1215 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1215 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1216 if n != "default" and not c]
1216 if n != "default" and not c]
1217 if not others:
1217 if not others:
1218 ui.status(_('(branches are permanent and global, '
1218 ui.status(_('(branches are permanent and global, '
1219 'did you want a bookmark?)\n'))
1219 'did you want a bookmark?)\n'))
1220
1220
1221 @command('branches',
1221 @command('branches',
1222 [('a', 'active', False,
1222 [('a', 'active', False,
1223 _('show only branches that have unmerged heads (DEPRECATED)')),
1223 _('show only branches that have unmerged heads (DEPRECATED)')),
1224 ('c', 'closed', False, _('show normal and closed branches')),
1224 ('c', 'closed', False, _('show normal and closed branches')),
1225 ] + formatteropts,
1225 ] + formatteropts,
1226 _('[-c]'))
1226 _('[-c]'))
1227 def branches(ui, repo, active=False, closed=False, **opts):
1227 def branches(ui, repo, active=False, closed=False, **opts):
1228 """list repository named branches
1228 """list repository named branches
1229
1229
1230 List the repository's named branches, indicating which ones are
1230 List the repository's named branches, indicating which ones are
1231 inactive. If -c/--closed is specified, also list branches which have
1231 inactive. If -c/--closed is specified, also list branches which have
1232 been marked closed (see :hg:`commit --close-branch`).
1232 been marked closed (see :hg:`commit --close-branch`).
1233
1233
1234 Use the command :hg:`update` to switch to an existing branch.
1234 Use the command :hg:`update` to switch to an existing branch.
1235
1235
1236 Returns 0.
1236 Returns 0.
1237 """
1237 """
1238
1238
1239 fm = ui.formatter('branches', opts)
1239 fm = ui.formatter('branches', opts)
1240 hexfunc = fm.hexfunc
1240 hexfunc = fm.hexfunc
1241
1241
1242 allheads = set(repo.heads())
1242 allheads = set(repo.heads())
1243 branches = []
1243 branches = []
1244 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1244 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1245 isactive = not isclosed and bool(set(heads) & allheads)
1245 isactive = not isclosed and bool(set(heads) & allheads)
1246 branches.append((tag, repo[tip], isactive, not isclosed))
1246 branches.append((tag, repo[tip], isactive, not isclosed))
1247 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1247 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1248 reverse=True)
1248 reverse=True)
1249
1249
1250 for tag, ctx, isactive, isopen in branches:
1250 for tag, ctx, isactive, isopen in branches:
1251 if active and not isactive:
1251 if active and not isactive:
1252 continue
1252 continue
1253 if isactive:
1253 if isactive:
1254 label = 'branches.active'
1254 label = 'branches.active'
1255 notice = ''
1255 notice = ''
1256 elif not isopen:
1256 elif not isopen:
1257 if not closed:
1257 if not closed:
1258 continue
1258 continue
1259 label = 'branches.closed'
1259 label = 'branches.closed'
1260 notice = _(' (closed)')
1260 notice = _(' (closed)')
1261 else:
1261 else:
1262 label = 'branches.inactive'
1262 label = 'branches.inactive'
1263 notice = _(' (inactive)')
1263 notice = _(' (inactive)')
1264 current = (tag == repo.dirstate.branch())
1264 current = (tag == repo.dirstate.branch())
1265 if current:
1265 if current:
1266 label = 'branches.current'
1266 label = 'branches.current'
1267
1267
1268 fm.startitem()
1268 fm.startitem()
1269 fm.write('branch', '%s', tag, label=label)
1269 fm.write('branch', '%s', tag, label=label)
1270 rev = ctx.rev()
1270 rev = ctx.rev()
1271 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1271 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1272 fmt = ' ' * padsize + ' %d:%s'
1272 fmt = ' ' * padsize + ' %d:%s'
1273 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1273 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1274 label='log.changeset changeset.%s' % ctx.phasestr())
1274 label='log.changeset changeset.%s' % ctx.phasestr())
1275 fm.data(active=isactive, closed=not isopen, current=current)
1275 fm.data(active=isactive, closed=not isopen, current=current)
1276 if not ui.quiet:
1276 if not ui.quiet:
1277 fm.plain(notice)
1277 fm.plain(notice)
1278 fm.plain('\n')
1278 fm.plain('\n')
1279 fm.end()
1279 fm.end()
1280
1280
1281 @command('bundle',
1281 @command('bundle',
1282 [('f', 'force', None, _('run even when the destination is unrelated')),
1282 [('f', 'force', None, _('run even when the destination is unrelated')),
1283 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1283 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1284 _('REV')),
1284 _('REV')),
1285 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1285 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1286 _('BRANCH')),
1286 _('BRANCH')),
1287 ('', 'base', [],
1287 ('', 'base', [],
1288 _('a base changeset assumed to be available at the destination'),
1288 _('a base changeset assumed to be available at the destination'),
1289 _('REV')),
1289 _('REV')),
1290 ('a', 'all', None, _('bundle all changesets in the repository')),
1290 ('a', 'all', None, _('bundle all changesets in the repository')),
1291 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1291 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1292 ] + remoteopts,
1292 ] + remoteopts,
1293 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1293 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1294 def bundle(ui, repo, fname, dest=None, **opts):
1294 def bundle(ui, repo, fname, dest=None, **opts):
1295 """create a changegroup file
1295 """create a changegroup file
1296
1296
1297 Generate a changegroup file collecting changesets to be added
1297 Generate a changegroup file collecting changesets to be added
1298 to a repository.
1298 to a repository.
1299
1299
1300 To create a bundle containing all changesets, use -a/--all
1300 To create a bundle containing all changesets, use -a/--all
1301 (or --base null). Otherwise, hg assumes the destination will have
1301 (or --base null). Otherwise, hg assumes the destination will have
1302 all the nodes you specify with --base parameters. Otherwise, hg
1302 all the nodes you specify with --base parameters. Otherwise, hg
1303 will assume the repository has all the nodes in destination, or
1303 will assume the repository has all the nodes in destination, or
1304 default-push/default if no destination is specified.
1304 default-push/default if no destination is specified.
1305
1305
1306 You can change bundle format with the -t/--type option. You can
1306 You can change bundle format with the -t/--type option. You can
1307 specify a compression, a bundle version or both using a dash
1307 specify a compression, a bundle version or both using a dash
1308 (comp-version). The available compression methods are: none, bzip2,
1308 (comp-version). The available compression methods are: none, bzip2,
1309 and gzip (by default, bundles are compressed using bzip2). The
1309 and gzip (by default, bundles are compressed using bzip2). The
1310 available formats are: v1, v2 (default to most suitable).
1310 available formats are: v1, v2 (default to most suitable).
1311
1311
1312 The bundle file can then be transferred using conventional means
1312 The bundle file can then be transferred using conventional means
1313 and applied to another repository with the unbundle or pull
1313 and applied to another repository with the unbundle or pull
1314 command. This is useful when direct push and pull are not
1314 command. This is useful when direct push and pull are not
1315 available or when exporting an entire repository is undesirable.
1315 available or when exporting an entire repository is undesirable.
1316
1316
1317 Applying bundles preserves all changeset contents including
1317 Applying bundles preserves all changeset contents including
1318 permissions, copy/rename information, and revision history.
1318 permissions, copy/rename information, and revision history.
1319
1319
1320 Returns 0 on success, 1 if no changes found.
1320 Returns 0 on success, 1 if no changes found.
1321 """
1321 """
1322 revs = None
1322 revs = None
1323 if 'rev' in opts:
1323 if 'rev' in opts:
1324 revstrings = opts['rev']
1324 revstrings = opts['rev']
1325 revs = scmutil.revrange(repo, revstrings)
1325 revs = scmutil.revrange(repo, revstrings)
1326 if revstrings and not revs:
1326 if revstrings and not revs:
1327 raise error.Abort(_('no commits to bundle'))
1327 raise error.Abort(_('no commits to bundle'))
1328
1328
1329 bundletype = opts.get('type', 'bzip2').lower()
1329 bundletype = opts.get('type', 'bzip2').lower()
1330 try:
1330 try:
1331 bcompression, cgversion, params = exchange.parsebundlespec(
1331 bcompression, cgversion, params = exchange.parsebundlespec(
1332 repo, bundletype, strict=False)
1332 repo, bundletype, strict=False)
1333 except error.UnsupportedBundleSpecification as e:
1333 except error.UnsupportedBundleSpecification as e:
1334 raise error.Abort(str(e),
1334 raise error.Abort(str(e),
1335 hint=_("see 'hg help bundle' for supported "
1335 hint=_("see 'hg help bundle' for supported "
1336 "values for --type"))
1336 "values for --type"))
1337
1337
1338 # Packed bundles are a pseudo bundle format for now.
1338 # Packed bundles are a pseudo bundle format for now.
1339 if cgversion == 's1':
1339 if cgversion == 's1':
1340 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1340 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1341 hint=_("use 'hg debugcreatestreamclonebundle'"))
1341 hint=_("use 'hg debugcreatestreamclonebundle'"))
1342
1342
1343 if opts.get('all'):
1343 if opts.get('all'):
1344 if dest:
1344 if dest:
1345 raise error.Abort(_("--all is incompatible with specifying "
1345 raise error.Abort(_("--all is incompatible with specifying "
1346 "a destination"))
1346 "a destination"))
1347 if opts.get('base'):
1347 if opts.get('base'):
1348 ui.warn(_("ignoring --base because --all was specified\n"))
1348 ui.warn(_("ignoring --base because --all was specified\n"))
1349 base = ['null']
1349 base = ['null']
1350 else:
1350 else:
1351 base = scmutil.revrange(repo, opts.get('base'))
1351 base = scmutil.revrange(repo, opts.get('base'))
1352 # TODO: get desired bundlecaps from command line.
1352 # TODO: get desired bundlecaps from command line.
1353 bundlecaps = None
1353 bundlecaps = None
1354 if cgversion not in changegroup.supportedoutgoingversions(repo):
1354 if cgversion not in changegroup.supportedoutgoingversions(repo):
1355 raise error.Abort(_("repository does not support bundle version %s") %
1355 raise error.Abort(_("repository does not support bundle version %s") %
1356 cgversion)
1356 cgversion)
1357
1357
1358 if base:
1358 if base:
1359 if dest:
1359 if dest:
1360 raise error.Abort(_("--base is incompatible with specifying "
1360 raise error.Abort(_("--base is incompatible with specifying "
1361 "a destination"))
1361 "a destination"))
1362 common = [repo.lookup(rev) for rev in base]
1362 common = [repo.lookup(rev) for rev in base]
1363 heads = revs and map(repo.lookup, revs) or None
1363 heads = revs and map(repo.lookup, revs) or None
1364 outgoing = discovery.outgoing(repo, common, heads)
1364 outgoing = discovery.outgoing(repo, common, heads)
1365 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1365 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1366 bundlecaps=bundlecaps,
1366 bundlecaps=bundlecaps,
1367 version=cgversion)
1367 version=cgversion)
1368 outgoing = None
1368 outgoing = None
1369 else:
1369 else:
1370 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1370 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1371 dest, branches = hg.parseurl(dest, opts.get('branch'))
1371 dest, branches = hg.parseurl(dest, opts.get('branch'))
1372 other = hg.peer(repo, opts, dest)
1372 other = hg.peer(repo, opts, dest)
1373 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1373 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1374 heads = revs and map(repo.lookup, revs) or revs
1374 heads = revs and map(repo.lookup, revs) or revs
1375 outgoing = discovery.findcommonoutgoing(repo, other,
1375 outgoing = discovery.findcommonoutgoing(repo, other,
1376 onlyheads=heads,
1376 onlyheads=heads,
1377 force=opts.get('force'),
1377 force=opts.get('force'),
1378 portable=True)
1378 portable=True)
1379 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1379 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1380 bundlecaps, version=cgversion)
1380 bundlecaps, version=cgversion)
1381 if not cg:
1381 if not cg:
1382 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1382 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1383 return 1
1383 return 1
1384
1384
1385 if cgversion == '01': #bundle1
1385 if cgversion == '01': #bundle1
1386 if bcompression is None:
1386 if bcompression is None:
1387 bcompression = 'UN'
1387 bcompression = 'UN'
1388 bversion = 'HG10' + bcompression
1388 bversion = 'HG10' + bcompression
1389 bcompression = None
1389 bcompression = None
1390 else:
1390 else:
1391 assert cgversion == '02'
1391 assert cgversion == '02'
1392 bversion = 'HG20'
1392 bversion = 'HG20'
1393
1393
1394 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1394 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1395
1395
1396 @command('cat',
1396 @command('cat',
1397 [('o', 'output', '',
1397 [('o', 'output', '',
1398 _('print output to file with formatted name'), _('FORMAT')),
1398 _('print output to file with formatted name'), _('FORMAT')),
1399 ('r', 'rev', '', _('print the given revision'), _('REV')),
1399 ('r', 'rev', '', _('print the given revision'), _('REV')),
1400 ('', 'decode', None, _('apply any matching decode filter')),
1400 ('', 'decode', None, _('apply any matching decode filter')),
1401 ] + walkopts,
1401 ] + walkopts,
1402 _('[OPTION]... FILE...'),
1402 _('[OPTION]... FILE...'),
1403 inferrepo=True)
1403 inferrepo=True)
1404 def cat(ui, repo, file1, *pats, **opts):
1404 def cat(ui, repo, file1, *pats, **opts):
1405 """output the current or given revision of files
1405 """output the current or given revision of files
1406
1406
1407 Print the specified files as they were at the given revision. If
1407 Print the specified files as they were at the given revision. If
1408 no revision is given, the parent of the working directory is used.
1408 no revision is given, the parent of the working directory is used.
1409
1409
1410 Output may be to a file, in which case the name of the file is
1410 Output may be to a file, in which case the name of the file is
1411 given using a format string. The formatting rules as follows:
1411 given using a format string. The formatting rules as follows:
1412
1412
1413 :``%%``: literal "%" character
1413 :``%%``: literal "%" character
1414 :``%s``: basename of file being printed
1414 :``%s``: basename of file being printed
1415 :``%d``: dirname of file being printed, or '.' if in repository root
1415 :``%d``: dirname of file being printed, or '.' if in repository root
1416 :``%p``: root-relative path name of file being printed
1416 :``%p``: root-relative path name of file being printed
1417 :``%H``: changeset hash (40 hexadecimal digits)
1417 :``%H``: changeset hash (40 hexadecimal digits)
1418 :``%R``: changeset revision number
1418 :``%R``: changeset revision number
1419 :``%h``: short-form changeset hash (12 hexadecimal digits)
1419 :``%h``: short-form changeset hash (12 hexadecimal digits)
1420 :``%r``: zero-padded changeset revision number
1420 :``%r``: zero-padded changeset revision number
1421 :``%b``: basename of the exporting repository
1421 :``%b``: basename of the exporting repository
1422
1422
1423 Returns 0 on success.
1423 Returns 0 on success.
1424 """
1424 """
1425 ctx = scmutil.revsingle(repo, opts.get('rev'))
1425 ctx = scmutil.revsingle(repo, opts.get('rev'))
1426 m = scmutil.match(ctx, (file1,) + pats, opts)
1426 m = scmutil.match(ctx, (file1,) + pats, opts)
1427
1427
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1429
1429
1430 @command('^clone',
1430 @command('^clone',
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1432 'directory (only a repository)')),
1432 'directory (only a repository)')),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1434 _('REV')),
1434 _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1439 ] + remoteopts,
1439 ] + remoteopts,
1440 _('[OPTION]... SOURCE [DEST]'),
1440 _('[OPTION]... SOURCE [DEST]'),
1441 norepo=True)
1441 norepo=True)
1442 def clone(ui, source, dest=None, **opts):
1442 def clone(ui, source, dest=None, **opts):
1443 """make a copy of an existing repository
1443 """make a copy of an existing repository
1444
1444
1445 Create a copy of an existing repository in a new directory.
1445 Create a copy of an existing repository in a new directory.
1446
1446
1447 If no destination directory name is specified, it defaults to the
1447 If no destination directory name is specified, it defaults to the
1448 basename of the source.
1448 basename of the source.
1449
1449
1450 The location of the source is added to the new repository's
1450 The location of the source is added to the new repository's
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1452
1452
1453 Only local paths and ``ssh://`` URLs are supported as
1453 Only local paths and ``ssh://`` URLs are supported as
1454 destinations. For ``ssh://`` destinations, no working directory or
1454 destinations. For ``ssh://`` destinations, no working directory or
1455 ``.hg/hgrc`` will be created on the remote side.
1455 ``.hg/hgrc`` will be created on the remote side.
1456
1456
1457 If the source repository has a bookmark called '@' set, that
1457 If the source repository has a bookmark called '@' set, that
1458 revision will be checked out in the new repository by default.
1458 revision will be checked out in the new repository by default.
1459
1459
1460 To check out a particular version, use -u/--update, or
1460 To check out a particular version, use -u/--update, or
1461 -U/--noupdate to create a clone with no working directory.
1461 -U/--noupdate to create a clone with no working directory.
1462
1462
1463 To pull only a subset of changesets, specify one or more revisions
1463 To pull only a subset of changesets, specify one or more revisions
1464 identifiers with -r/--rev or branches with -b/--branch. The
1464 identifiers with -r/--rev or branches with -b/--branch. The
1465 resulting clone will contain only the specified changesets and
1465 resulting clone will contain only the specified changesets and
1466 their ancestors. These options (or 'clone src#rev dest') imply
1466 their ancestors. These options (or 'clone src#rev dest') imply
1467 --pull, even for local source repositories.
1467 --pull, even for local source repositories.
1468
1468
1469 .. note::
1469 .. note::
1470
1470
1471 Specifying a tag will include the tagged changeset but not the
1471 Specifying a tag will include the tagged changeset but not the
1472 changeset containing the tag.
1472 changeset containing the tag.
1473
1473
1474 .. container:: verbose
1474 .. container:: verbose
1475
1475
1476 For efficiency, hardlinks are used for cloning whenever the
1476 For efficiency, hardlinks are used for cloning whenever the
1477 source and destination are on the same filesystem (note this
1477 source and destination are on the same filesystem (note this
1478 applies only to the repository data, not to the working
1478 applies only to the repository data, not to the working
1479 directory). Some filesystems, such as AFS, implement hardlinking
1479 directory). Some filesystems, such as AFS, implement hardlinking
1480 incorrectly, but do not report errors. In these cases, use the
1480 incorrectly, but do not report errors. In these cases, use the
1481 --pull option to avoid hardlinking.
1481 --pull option to avoid hardlinking.
1482
1482
1483 In some cases, you can clone repositories and the working
1483 In some cases, you can clone repositories and the working
1484 directory using full hardlinks with ::
1484 directory using full hardlinks with ::
1485
1485
1486 $ cp -al REPO REPOCLONE
1486 $ cp -al REPO REPOCLONE
1487
1487
1488 This is the fastest way to clone, but it is not always safe. The
1488 This is the fastest way to clone, but it is not always safe. The
1489 operation is not atomic (making sure REPO is not modified during
1489 operation is not atomic (making sure REPO is not modified during
1490 the operation is up to you) and you have to make sure your
1490 the operation is up to you) and you have to make sure your
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1492 so). Also, this is not compatible with certain extensions that
1492 so). Also, this is not compatible with certain extensions that
1493 place their metadata under the .hg directory, such as mq.
1493 place their metadata under the .hg directory, such as mq.
1494
1494
1495 Mercurial will update the working directory to the first applicable
1495 Mercurial will update the working directory to the first applicable
1496 revision from this list:
1496 revision from this list:
1497
1497
1498 a) null if -U or the source repository has no changesets
1498 a) null if -U or the source repository has no changesets
1499 b) if -u . and the source repository is local, the first parent of
1499 b) if -u . and the source repository is local, the first parent of
1500 the source repository's working directory
1500 the source repository's working directory
1501 c) the changeset specified with -u (if a branch name, this means the
1501 c) the changeset specified with -u (if a branch name, this means the
1502 latest head of that branch)
1502 latest head of that branch)
1503 d) the changeset specified with -r
1503 d) the changeset specified with -r
1504 e) the tipmost head specified with -b
1504 e) the tipmost head specified with -b
1505 f) the tipmost head specified with the url#branch source syntax
1505 f) the tipmost head specified with the url#branch source syntax
1506 g) the revision marked with the '@' bookmark, if present
1506 g) the revision marked with the '@' bookmark, if present
1507 h) the tipmost head of the default branch
1507 h) the tipmost head of the default branch
1508 i) tip
1508 i) tip
1509
1509
1510 When cloning from servers that support it, Mercurial may fetch
1510 When cloning from servers that support it, Mercurial may fetch
1511 pre-generated data from a server-advertised URL. When this is done,
1511 pre-generated data from a server-advertised URL. When this is done,
1512 hooks operating on incoming changesets and changegroups may fire twice,
1512 hooks operating on incoming changesets and changegroups may fire twice,
1513 once for the bundle fetched from the URL and another for any additional
1513 once for the bundle fetched from the URL and another for any additional
1514 data not fetched from this URL. In addition, if an error occurs, the
1514 data not fetched from this URL. In addition, if an error occurs, the
1515 repository may be rolled back to a partial clone. This behavior may
1515 repository may be rolled back to a partial clone. This behavior may
1516 change in future releases. See :hg:`help -e clonebundles` for more.
1516 change in future releases. See :hg:`help -e clonebundles` for more.
1517
1517
1518 Examples:
1518 Examples:
1519
1519
1520 - clone a remote repository to a new directory named hg/::
1520 - clone a remote repository to a new directory named hg/::
1521
1521
1522 hg clone http://selenic.com/hg
1522 hg clone http://selenic.com/hg
1523
1523
1524 - create a lightweight local clone::
1524 - create a lightweight local clone::
1525
1525
1526 hg clone project/ project-feature/
1526 hg clone project/ project-feature/
1527
1527
1528 - clone from an absolute path on an ssh server (note double-slash)::
1528 - clone from an absolute path on an ssh server (note double-slash)::
1529
1529
1530 hg clone ssh://user@server//home/projects/alpha/
1530 hg clone ssh://user@server//home/projects/alpha/
1531
1531
1532 - do a high-speed clone over a LAN while checking out a
1532 - do a high-speed clone over a LAN while checking out a
1533 specified version::
1533 specified version::
1534
1534
1535 hg clone --uncompressed http://server/repo -u 1.5
1535 hg clone --uncompressed http://server/repo -u 1.5
1536
1536
1537 - create a repository without changesets after a particular revision::
1537 - create a repository without changesets after a particular revision::
1538
1538
1539 hg clone -r 04e544 experimental/ good/
1539 hg clone -r 04e544 experimental/ good/
1540
1540
1541 - clone (and track) a particular named branch::
1541 - clone (and track) a particular named branch::
1542
1542
1543 hg clone http://selenic.com/hg#stable
1543 hg clone http://selenic.com/hg#stable
1544
1544
1545 See :hg:`help urls` for details on specifying URLs.
1545 See :hg:`help urls` for details on specifying URLs.
1546
1546
1547 Returns 0 on success.
1547 Returns 0 on success.
1548 """
1548 """
1549 if opts.get('noupdate') and opts.get('updaterev'):
1549 if opts.get('noupdate') and opts.get('updaterev'):
1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1551
1551
1552 r = hg.clone(ui, opts, source, dest,
1552 r = hg.clone(ui, opts, source, dest,
1553 pull=opts.get('pull'),
1553 pull=opts.get('pull'),
1554 stream=opts.get('uncompressed'),
1554 stream=opts.get('uncompressed'),
1555 rev=opts.get('rev'),
1555 rev=opts.get('rev'),
1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1557 branch=opts.get('branch'),
1557 branch=opts.get('branch'),
1558 shareopts=opts.get('shareopts'))
1558 shareopts=opts.get('shareopts'))
1559
1559
1560 return r is None
1560 return r is None
1561
1561
1562 @command('^commit|ci',
1562 @command('^commit|ci',
1563 [('A', 'addremove', None,
1563 [('A', 'addremove', None,
1564 _('mark new/missing files as added/removed before committing')),
1564 _('mark new/missing files as added/removed before committing')),
1565 ('', 'close-branch', None,
1565 ('', 'close-branch', None,
1566 _('mark a branch head as closed')),
1566 _('mark a branch head as closed')),
1567 ('', 'amend', None, _('amend the parent of the working directory')),
1567 ('', 'amend', None, _('amend the parent of the working directory')),
1568 ('s', 'secret', None, _('use the secret phase for committing')),
1568 ('s', 'secret', None, _('use the secret phase for committing')),
1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1570 ('i', 'interactive', None, _('use interactive mode')),
1570 ('i', 'interactive', None, _('use interactive mode')),
1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1572 _('[OPTION]... [FILE]...'),
1572 _('[OPTION]... [FILE]...'),
1573 inferrepo=True)
1573 inferrepo=True)
1574 def commit(ui, repo, *pats, **opts):
1574 def commit(ui, repo, *pats, **opts):
1575 """commit the specified files or all outstanding changes
1575 """commit the specified files or all outstanding changes
1576
1576
1577 Commit changes to the given files into the repository. Unlike a
1577 Commit changes to the given files into the repository. Unlike a
1578 centralized SCM, this operation is a local operation. See
1578 centralized SCM, this operation is a local operation. See
1579 :hg:`push` for a way to actively distribute your changes.
1579 :hg:`push` for a way to actively distribute your changes.
1580
1580
1581 If a list of files is omitted, all changes reported by :hg:`status`
1581 If a list of files is omitted, all changes reported by :hg:`status`
1582 will be committed.
1582 will be committed.
1583
1583
1584 If you are committing the result of a merge, do not provide any
1584 If you are committing the result of a merge, do not provide any
1585 filenames or -I/-X filters.
1585 filenames or -I/-X filters.
1586
1586
1587 If no commit message is specified, Mercurial starts your
1587 If no commit message is specified, Mercurial starts your
1588 configured editor where you can enter a message. In case your
1588 configured editor where you can enter a message. In case your
1589 commit fails, you will find a backup of your message in
1589 commit fails, you will find a backup of your message in
1590 ``.hg/last-message.txt``.
1590 ``.hg/last-message.txt``.
1591
1591
1592 The --close-branch flag can be used to mark the current branch
1592 The --close-branch flag can be used to mark the current branch
1593 head closed. When all heads of a branch are closed, the branch
1593 head closed. When all heads of a branch are closed, the branch
1594 will be considered closed and no longer listed.
1594 will be considered closed and no longer listed.
1595
1595
1596 The --amend flag can be used to amend the parent of the
1596 The --amend flag can be used to amend the parent of the
1597 working directory with a new commit that contains the changes
1597 working directory with a new commit that contains the changes
1598 in the parent in addition to those currently reported by :hg:`status`,
1598 in the parent in addition to those currently reported by :hg:`status`,
1599 if there are any. The old commit is stored in a backup bundle in
1599 if there are any. The old commit is stored in a backup bundle in
1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1601 on how to restore it).
1601 on how to restore it).
1602
1602
1603 Message, user and date are taken from the amended commit unless
1603 Message, user and date are taken from the amended commit unless
1604 specified. When a message isn't specified on the command line,
1604 specified. When a message isn't specified on the command line,
1605 the editor will open with the message of the amended commit.
1605 the editor will open with the message of the amended commit.
1606
1606
1607 It is not possible to amend public changesets (see :hg:`help phases`)
1607 It is not possible to amend public changesets (see :hg:`help phases`)
1608 or changesets that have children.
1608 or changesets that have children.
1609
1609
1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1611
1611
1612 Returns 0 on success, 1 if nothing changed.
1612 Returns 0 on success, 1 if nothing changed.
1613
1613
1614 .. container:: verbose
1614 .. container:: verbose
1615
1615
1616 Examples:
1616 Examples:
1617
1617
1618 - commit all files ending in .py::
1618 - commit all files ending in .py::
1619
1619
1620 hg commit --include "set:**.py"
1620 hg commit --include "set:**.py"
1621
1621
1622 - commit all non-binary files::
1622 - commit all non-binary files::
1623
1623
1624 hg commit --exclude "set:binary()"
1624 hg commit --exclude "set:binary()"
1625
1625
1626 - amend the current commit and set the date to now::
1626 - amend the current commit and set the date to now::
1627
1627
1628 hg commit --amend --date now
1628 hg commit --amend --date now
1629 """
1629 """
1630 wlock = lock = None
1630 wlock = lock = None
1631 try:
1631 try:
1632 wlock = repo.wlock()
1632 wlock = repo.wlock()
1633 lock = repo.lock()
1633 lock = repo.lock()
1634 return _docommit(ui, repo, *pats, **opts)
1634 return _docommit(ui, repo, *pats, **opts)
1635 finally:
1635 finally:
1636 release(lock, wlock)
1636 release(lock, wlock)
1637
1637
1638 def _docommit(ui, repo, *pats, **opts):
1638 def _docommit(ui, repo, *pats, **opts):
1639 if opts.get('interactive'):
1639 if opts.get('interactive'):
1640 opts.pop('interactive')
1640 opts.pop('interactive')
1641 cmdutil.dorecord(ui, repo, commit, None, False,
1641 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1642 cmdutil.recordfilter, *pats, **opts)
1642 cmdutil.recordfilter, *pats, **opts)
1643 return
1643 # ret can be 0 (no changes to record) or the value returned by
1644 # commit(), 1 if nothing changed or None on success.
1645 return 1 if ret == 0 else ret
1644
1646
1645 if opts.get('subrepos'):
1647 if opts.get('subrepos'):
1646 if opts.get('amend'):
1648 if opts.get('amend'):
1647 raise error.Abort(_('cannot amend with --subrepos'))
1649 raise error.Abort(_('cannot amend with --subrepos'))
1648 # Let --subrepos on the command line override config setting.
1650 # Let --subrepos on the command line override config setting.
1649 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1651 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1650
1652
1651 cmdutil.checkunfinished(repo, commit=True)
1653 cmdutil.checkunfinished(repo, commit=True)
1652
1654
1653 branch = repo[None].branch()
1655 branch = repo[None].branch()
1654 bheads = repo.branchheads(branch)
1656 bheads = repo.branchheads(branch)
1655
1657
1656 extra = {}
1658 extra = {}
1657 if opts.get('close_branch'):
1659 if opts.get('close_branch'):
1658 extra['close'] = 1
1660 extra['close'] = 1
1659
1661
1660 if not bheads:
1662 if not bheads:
1661 raise error.Abort(_('can only close branch heads'))
1663 raise error.Abort(_('can only close branch heads'))
1662 elif opts.get('amend'):
1664 elif opts.get('amend'):
1663 if repo[None].parents()[0].p1().branch() != branch and \
1665 if repo[None].parents()[0].p1().branch() != branch and \
1664 repo[None].parents()[0].p2().branch() != branch:
1666 repo[None].parents()[0].p2().branch() != branch:
1665 raise error.Abort(_('can only close branch heads'))
1667 raise error.Abort(_('can only close branch heads'))
1666
1668
1667 if opts.get('amend'):
1669 if opts.get('amend'):
1668 if ui.configbool('ui', 'commitsubrepos'):
1670 if ui.configbool('ui', 'commitsubrepos'):
1669 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1671 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1670
1672
1671 old = repo['.']
1673 old = repo['.']
1672 if not old.mutable():
1674 if not old.mutable():
1673 raise error.Abort(_('cannot amend public changesets'))
1675 raise error.Abort(_('cannot amend public changesets'))
1674 if len(repo[None].parents()) > 1:
1676 if len(repo[None].parents()) > 1:
1675 raise error.Abort(_('cannot amend while merging'))
1677 raise error.Abort(_('cannot amend while merging'))
1676 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1678 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1677 if not allowunstable and old.children():
1679 if not allowunstable and old.children():
1678 raise error.Abort(_('cannot amend changeset with children'))
1680 raise error.Abort(_('cannot amend changeset with children'))
1679
1681
1680 # Currently histedit gets confused if an amend happens while histedit
1682 # Currently histedit gets confused if an amend happens while histedit
1681 # is in progress. Since we have a checkunfinished command, we are
1683 # is in progress. Since we have a checkunfinished command, we are
1682 # temporarily honoring it.
1684 # temporarily honoring it.
1683 #
1685 #
1684 # Note: eventually this guard will be removed. Please do not expect
1686 # Note: eventually this guard will be removed. Please do not expect
1685 # this behavior to remain.
1687 # this behavior to remain.
1686 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1688 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1687 cmdutil.checkunfinished(repo)
1689 cmdutil.checkunfinished(repo)
1688
1690
1689 # commitfunc is used only for temporary amend commit by cmdutil.amend
1691 # commitfunc is used only for temporary amend commit by cmdutil.amend
1690 def commitfunc(ui, repo, message, match, opts):
1692 def commitfunc(ui, repo, message, match, opts):
1691 return repo.commit(message,
1693 return repo.commit(message,
1692 opts.get('user') or old.user(),
1694 opts.get('user') or old.user(),
1693 opts.get('date') or old.date(),
1695 opts.get('date') or old.date(),
1694 match,
1696 match,
1695 extra=extra)
1697 extra=extra)
1696
1698
1697 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1699 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1698 if node == old.node():
1700 if node == old.node():
1699 ui.status(_("nothing changed\n"))
1701 ui.status(_("nothing changed\n"))
1700 return 1
1702 return 1
1701 else:
1703 else:
1702 def commitfunc(ui, repo, message, match, opts):
1704 def commitfunc(ui, repo, message, match, opts):
1703 backup = ui.backupconfig('phases', 'new-commit')
1705 backup = ui.backupconfig('phases', 'new-commit')
1704 baseui = repo.baseui
1706 baseui = repo.baseui
1705 basebackup = baseui.backupconfig('phases', 'new-commit')
1707 basebackup = baseui.backupconfig('phases', 'new-commit')
1706 try:
1708 try:
1707 if opts.get('secret'):
1709 if opts.get('secret'):
1708 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1710 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1709 # Propagate to subrepos
1711 # Propagate to subrepos
1710 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1712 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1711
1713
1712 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1714 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1713 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1715 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1714 return repo.commit(message, opts.get('user'), opts.get('date'),
1716 return repo.commit(message, opts.get('user'), opts.get('date'),
1715 match,
1717 match,
1716 editor=editor,
1718 editor=editor,
1717 extra=extra)
1719 extra=extra)
1718 finally:
1720 finally:
1719 ui.restoreconfig(backup)
1721 ui.restoreconfig(backup)
1720 repo.baseui.restoreconfig(basebackup)
1722 repo.baseui.restoreconfig(basebackup)
1721
1723
1722
1724
1723 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1725 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1724
1726
1725 if not node:
1727 if not node:
1726 stat = cmdutil.postcommitstatus(repo, pats, opts)
1728 stat = cmdutil.postcommitstatus(repo, pats, opts)
1727 if stat[3]:
1729 if stat[3]:
1728 ui.status(_("nothing changed (%d missing files, see "
1730 ui.status(_("nothing changed (%d missing files, see "
1729 "'hg status')\n") % len(stat[3]))
1731 "'hg status')\n") % len(stat[3]))
1730 else:
1732 else:
1731 ui.status(_("nothing changed\n"))
1733 ui.status(_("nothing changed\n"))
1732 return 1
1734 return 1
1733
1735
1734 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1736 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1735
1737
1736 @command('config|showconfig|debugconfig',
1738 @command('config|showconfig|debugconfig',
1737 [('u', 'untrusted', None, _('show untrusted configuration options')),
1739 [('u', 'untrusted', None, _('show untrusted configuration options')),
1738 ('e', 'edit', None, _('edit user config')),
1740 ('e', 'edit', None, _('edit user config')),
1739 ('l', 'local', None, _('edit repository config')),
1741 ('l', 'local', None, _('edit repository config')),
1740 ('g', 'global', None, _('edit global config'))] + formatteropts,
1742 ('g', 'global', None, _('edit global config'))] + formatteropts,
1741 _('[-u] [NAME]...'),
1743 _('[-u] [NAME]...'),
1742 optionalrepo=True)
1744 optionalrepo=True)
1743 def config(ui, repo, *values, **opts):
1745 def config(ui, repo, *values, **opts):
1744 """show combined config settings from all hgrc files
1746 """show combined config settings from all hgrc files
1745
1747
1746 With no arguments, print names and values of all config items.
1748 With no arguments, print names and values of all config items.
1747
1749
1748 With one argument of the form section.name, print just the value
1750 With one argument of the form section.name, print just the value
1749 of that config item.
1751 of that config item.
1750
1752
1751 With multiple arguments, print names and values of all config
1753 With multiple arguments, print names and values of all config
1752 items with matching section names.
1754 items with matching section names.
1753
1755
1754 With --edit, start an editor on the user-level config file. With
1756 With --edit, start an editor on the user-level config file. With
1755 --global, edit the system-wide config file. With --local, edit the
1757 --global, edit the system-wide config file. With --local, edit the
1756 repository-level config file.
1758 repository-level config file.
1757
1759
1758 With --debug, the source (filename and line number) is printed
1760 With --debug, the source (filename and line number) is printed
1759 for each config item.
1761 for each config item.
1760
1762
1761 See :hg:`help config` for more information about config files.
1763 See :hg:`help config` for more information about config files.
1762
1764
1763 Returns 0 on success, 1 if NAME does not exist.
1765 Returns 0 on success, 1 if NAME does not exist.
1764
1766
1765 """
1767 """
1766
1768
1767 if opts.get('edit') or opts.get('local') or opts.get('global'):
1769 if opts.get('edit') or opts.get('local') or opts.get('global'):
1768 if opts.get('local') and opts.get('global'):
1770 if opts.get('local') and opts.get('global'):
1769 raise error.Abort(_("can't use --local and --global together"))
1771 raise error.Abort(_("can't use --local and --global together"))
1770
1772
1771 if opts.get('local'):
1773 if opts.get('local'):
1772 if not repo:
1774 if not repo:
1773 raise error.Abort(_("can't use --local outside a repository"))
1775 raise error.Abort(_("can't use --local outside a repository"))
1774 paths = [repo.join('hgrc')]
1776 paths = [repo.join('hgrc')]
1775 elif opts.get('global'):
1777 elif opts.get('global'):
1776 paths = scmutil.systemrcpath()
1778 paths = scmutil.systemrcpath()
1777 else:
1779 else:
1778 paths = scmutil.userrcpath()
1780 paths = scmutil.userrcpath()
1779
1781
1780 for f in paths:
1782 for f in paths:
1781 if os.path.exists(f):
1783 if os.path.exists(f):
1782 break
1784 break
1783 else:
1785 else:
1784 if opts.get('global'):
1786 if opts.get('global'):
1785 samplehgrc = uimod.samplehgrcs['global']
1787 samplehgrc = uimod.samplehgrcs['global']
1786 elif opts.get('local'):
1788 elif opts.get('local'):
1787 samplehgrc = uimod.samplehgrcs['local']
1789 samplehgrc = uimod.samplehgrcs['local']
1788 else:
1790 else:
1789 samplehgrc = uimod.samplehgrcs['user']
1791 samplehgrc = uimod.samplehgrcs['user']
1790
1792
1791 f = paths[0]
1793 f = paths[0]
1792 fp = open(f, "w")
1794 fp = open(f, "w")
1793 fp.write(samplehgrc)
1795 fp.write(samplehgrc)
1794 fp.close()
1796 fp.close()
1795
1797
1796 editor = ui.geteditor()
1798 editor = ui.geteditor()
1797 ui.system("%s \"%s\"" % (editor, f),
1799 ui.system("%s \"%s\"" % (editor, f),
1798 onerr=error.Abort, errprefix=_("edit failed"))
1800 onerr=error.Abort, errprefix=_("edit failed"))
1799 return
1801 return
1800
1802
1801 fm = ui.formatter('config', opts)
1803 fm = ui.formatter('config', opts)
1802 for f in scmutil.rcpath():
1804 for f in scmutil.rcpath():
1803 ui.debug('read config from: %s\n' % f)
1805 ui.debug('read config from: %s\n' % f)
1804 untrusted = bool(opts.get('untrusted'))
1806 untrusted = bool(opts.get('untrusted'))
1805 if values:
1807 if values:
1806 sections = [v for v in values if '.' not in v]
1808 sections = [v for v in values if '.' not in v]
1807 items = [v for v in values if '.' in v]
1809 items = [v for v in values if '.' in v]
1808 if len(items) > 1 or items and sections:
1810 if len(items) > 1 or items and sections:
1809 raise error.Abort(_('only one config item permitted'))
1811 raise error.Abort(_('only one config item permitted'))
1810 matched = False
1812 matched = False
1811 for section, name, value in ui.walkconfig(untrusted=untrusted):
1813 for section, name, value in ui.walkconfig(untrusted=untrusted):
1812 value = str(value)
1814 value = str(value)
1813 if fm.isplain():
1815 if fm.isplain():
1814 value = value.replace('\n', '\\n')
1816 value = value.replace('\n', '\\n')
1815 entryname = section + '.' + name
1817 entryname = section + '.' + name
1816 if values:
1818 if values:
1817 for v in values:
1819 for v in values:
1818 if v == section:
1820 if v == section:
1819 fm.startitem()
1821 fm.startitem()
1820 fm.condwrite(ui.debugflag, 'source', '%s: ',
1822 fm.condwrite(ui.debugflag, 'source', '%s: ',
1821 ui.configsource(section, name, untrusted))
1823 ui.configsource(section, name, untrusted))
1822 fm.write('name value', '%s=%s\n', entryname, value)
1824 fm.write('name value', '%s=%s\n', entryname, value)
1823 matched = True
1825 matched = True
1824 elif v == entryname:
1826 elif v == entryname:
1825 fm.startitem()
1827 fm.startitem()
1826 fm.condwrite(ui.debugflag, 'source', '%s: ',
1828 fm.condwrite(ui.debugflag, 'source', '%s: ',
1827 ui.configsource(section, name, untrusted))
1829 ui.configsource(section, name, untrusted))
1828 fm.write('value', '%s\n', value)
1830 fm.write('value', '%s\n', value)
1829 fm.data(name=entryname)
1831 fm.data(name=entryname)
1830 matched = True
1832 matched = True
1831 else:
1833 else:
1832 fm.startitem()
1834 fm.startitem()
1833 fm.condwrite(ui.debugflag, 'source', '%s: ',
1835 fm.condwrite(ui.debugflag, 'source', '%s: ',
1834 ui.configsource(section, name, untrusted))
1836 ui.configsource(section, name, untrusted))
1835 fm.write('name value', '%s=%s\n', entryname, value)
1837 fm.write('name value', '%s=%s\n', entryname, value)
1836 matched = True
1838 matched = True
1837 fm.end()
1839 fm.end()
1838 if matched:
1840 if matched:
1839 return 0
1841 return 0
1840 return 1
1842 return 1
1841
1843
1842 @command('copy|cp',
1844 @command('copy|cp',
1843 [('A', 'after', None, _('record a copy that has already occurred')),
1845 [('A', 'after', None, _('record a copy that has already occurred')),
1844 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1846 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1845 ] + walkopts + dryrunopts,
1847 ] + walkopts + dryrunopts,
1846 _('[OPTION]... [SOURCE]... DEST'))
1848 _('[OPTION]... [SOURCE]... DEST'))
1847 def copy(ui, repo, *pats, **opts):
1849 def copy(ui, repo, *pats, **opts):
1848 """mark files as copied for the next commit
1850 """mark files as copied for the next commit
1849
1851
1850 Mark dest as having copies of source files. If dest is a
1852 Mark dest as having copies of source files. If dest is a
1851 directory, copies are put in that directory. If dest is a file,
1853 directory, copies are put in that directory. If dest is a file,
1852 the source must be a single file.
1854 the source must be a single file.
1853
1855
1854 By default, this command copies the contents of files as they
1856 By default, this command copies the contents of files as they
1855 exist in the working directory. If invoked with -A/--after, the
1857 exist in the working directory. If invoked with -A/--after, the
1856 operation is recorded, but no copying is performed.
1858 operation is recorded, but no copying is performed.
1857
1859
1858 This command takes effect with the next commit. To undo a copy
1860 This command takes effect with the next commit. To undo a copy
1859 before that, see :hg:`revert`.
1861 before that, see :hg:`revert`.
1860
1862
1861 Returns 0 on success, 1 if errors are encountered.
1863 Returns 0 on success, 1 if errors are encountered.
1862 """
1864 """
1863 with repo.wlock(False):
1865 with repo.wlock(False):
1864 return cmdutil.copy(ui, repo, pats, opts)
1866 return cmdutil.copy(ui, repo, pats, opts)
1865
1867
1866 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1868 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1867 def debugancestor(ui, repo, *args):
1869 def debugancestor(ui, repo, *args):
1868 """find the ancestor revision of two revisions in a given index"""
1870 """find the ancestor revision of two revisions in a given index"""
1869 if len(args) == 3:
1871 if len(args) == 3:
1870 index, rev1, rev2 = args
1872 index, rev1, rev2 = args
1871 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1873 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1872 lookup = r.lookup
1874 lookup = r.lookup
1873 elif len(args) == 2:
1875 elif len(args) == 2:
1874 if not repo:
1876 if not repo:
1875 raise error.Abort(_("there is no Mercurial repository here "
1877 raise error.Abort(_("there is no Mercurial repository here "
1876 "(.hg not found)"))
1878 "(.hg not found)"))
1877 rev1, rev2 = args
1879 rev1, rev2 = args
1878 r = repo.changelog
1880 r = repo.changelog
1879 lookup = repo.lookup
1881 lookup = repo.lookup
1880 else:
1882 else:
1881 raise error.Abort(_('either two or three arguments required'))
1883 raise error.Abort(_('either two or three arguments required'))
1882 a = r.ancestor(lookup(rev1), lookup(rev2))
1884 a = r.ancestor(lookup(rev1), lookup(rev2))
1883 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1885 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1884
1886
1885 @command('debugbuilddag',
1887 @command('debugbuilddag',
1886 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1888 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1887 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1889 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1888 ('n', 'new-file', None, _('add new file at each rev'))],
1890 ('n', 'new-file', None, _('add new file at each rev'))],
1889 _('[OPTION]... [TEXT]'))
1891 _('[OPTION]... [TEXT]'))
1890 def debugbuilddag(ui, repo, text=None,
1892 def debugbuilddag(ui, repo, text=None,
1891 mergeable_file=False,
1893 mergeable_file=False,
1892 overwritten_file=False,
1894 overwritten_file=False,
1893 new_file=False):
1895 new_file=False):
1894 """builds a repo with a given DAG from scratch in the current empty repo
1896 """builds a repo with a given DAG from scratch in the current empty repo
1895
1897
1896 The description of the DAG is read from stdin if not given on the
1898 The description of the DAG is read from stdin if not given on the
1897 command line.
1899 command line.
1898
1900
1899 Elements:
1901 Elements:
1900
1902
1901 - "+n" is a linear run of n nodes based on the current default parent
1903 - "+n" is a linear run of n nodes based on the current default parent
1902 - "." is a single node based on the current default parent
1904 - "." is a single node based on the current default parent
1903 - "$" resets the default parent to null (implied at the start);
1905 - "$" resets the default parent to null (implied at the start);
1904 otherwise the default parent is always the last node created
1906 otherwise the default parent is always the last node created
1905 - "<p" sets the default parent to the backref p
1907 - "<p" sets the default parent to the backref p
1906 - "*p" is a fork at parent p, which is a backref
1908 - "*p" is a fork at parent p, which is a backref
1907 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1909 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1908 - "/p2" is a merge of the preceding node and p2
1910 - "/p2" is a merge of the preceding node and p2
1909 - ":tag" defines a local tag for the preceding node
1911 - ":tag" defines a local tag for the preceding node
1910 - "@branch" sets the named branch for subsequent nodes
1912 - "@branch" sets the named branch for subsequent nodes
1911 - "#...\\n" is a comment up to the end of the line
1913 - "#...\\n" is a comment up to the end of the line
1912
1914
1913 Whitespace between the above elements is ignored.
1915 Whitespace between the above elements is ignored.
1914
1916
1915 A backref is either
1917 A backref is either
1916
1918
1917 - a number n, which references the node curr-n, where curr is the current
1919 - a number n, which references the node curr-n, where curr is the current
1918 node, or
1920 node, or
1919 - the name of a local tag you placed earlier using ":tag", or
1921 - the name of a local tag you placed earlier using ":tag", or
1920 - empty to denote the default parent.
1922 - empty to denote the default parent.
1921
1923
1922 All string valued-elements are either strictly alphanumeric, or must
1924 All string valued-elements are either strictly alphanumeric, or must
1923 be enclosed in double quotes ("..."), with "\\" as escape character.
1925 be enclosed in double quotes ("..."), with "\\" as escape character.
1924 """
1926 """
1925
1927
1926 if text is None:
1928 if text is None:
1927 ui.status(_("reading DAG from stdin\n"))
1929 ui.status(_("reading DAG from stdin\n"))
1928 text = ui.fin.read()
1930 text = ui.fin.read()
1929
1931
1930 cl = repo.changelog
1932 cl = repo.changelog
1931 if len(cl) > 0:
1933 if len(cl) > 0:
1932 raise error.Abort(_('repository is not empty'))
1934 raise error.Abort(_('repository is not empty'))
1933
1935
1934 # determine number of revs in DAG
1936 # determine number of revs in DAG
1935 total = 0
1937 total = 0
1936 for type, data in dagparser.parsedag(text):
1938 for type, data in dagparser.parsedag(text):
1937 if type == 'n':
1939 if type == 'n':
1938 total += 1
1940 total += 1
1939
1941
1940 if mergeable_file:
1942 if mergeable_file:
1941 linesperrev = 2
1943 linesperrev = 2
1942 # make a file with k lines per rev
1944 # make a file with k lines per rev
1943 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1945 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1944 initialmergedlines.append("")
1946 initialmergedlines.append("")
1945
1947
1946 tags = []
1948 tags = []
1947
1949
1948 wlock = lock = tr = None
1950 wlock = lock = tr = None
1949 try:
1951 try:
1950 wlock = repo.wlock()
1952 wlock = repo.wlock()
1951 lock = repo.lock()
1953 lock = repo.lock()
1952 tr = repo.transaction("builddag")
1954 tr = repo.transaction("builddag")
1953
1955
1954 at = -1
1956 at = -1
1955 atbranch = 'default'
1957 atbranch = 'default'
1956 nodeids = []
1958 nodeids = []
1957 id = 0
1959 id = 0
1958 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1960 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1959 for type, data in dagparser.parsedag(text):
1961 for type, data in dagparser.parsedag(text):
1960 if type == 'n':
1962 if type == 'n':
1961 ui.note(('node %s\n' % str(data)))
1963 ui.note(('node %s\n' % str(data)))
1962 id, ps = data
1964 id, ps = data
1963
1965
1964 files = []
1966 files = []
1965 fctxs = {}
1967 fctxs = {}
1966
1968
1967 p2 = None
1969 p2 = None
1968 if mergeable_file:
1970 if mergeable_file:
1969 fn = "mf"
1971 fn = "mf"
1970 p1 = repo[ps[0]]
1972 p1 = repo[ps[0]]
1971 if len(ps) > 1:
1973 if len(ps) > 1:
1972 p2 = repo[ps[1]]
1974 p2 = repo[ps[1]]
1973 pa = p1.ancestor(p2)
1975 pa = p1.ancestor(p2)
1974 base, local, other = [x[fn].data() for x in (pa, p1,
1976 base, local, other = [x[fn].data() for x in (pa, p1,
1975 p2)]
1977 p2)]
1976 m3 = simplemerge.Merge3Text(base, local, other)
1978 m3 = simplemerge.Merge3Text(base, local, other)
1977 ml = [l.strip() for l in m3.merge_lines()]
1979 ml = [l.strip() for l in m3.merge_lines()]
1978 ml.append("")
1980 ml.append("")
1979 elif at > 0:
1981 elif at > 0:
1980 ml = p1[fn].data().split("\n")
1982 ml = p1[fn].data().split("\n")
1981 else:
1983 else:
1982 ml = initialmergedlines
1984 ml = initialmergedlines
1983 ml[id * linesperrev] += " r%i" % id
1985 ml[id * linesperrev] += " r%i" % id
1984 mergedtext = "\n".join(ml)
1986 mergedtext = "\n".join(ml)
1985 files.append(fn)
1987 files.append(fn)
1986 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1988 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1987
1989
1988 if overwritten_file:
1990 if overwritten_file:
1989 fn = "of"
1991 fn = "of"
1990 files.append(fn)
1992 files.append(fn)
1991 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1993 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1992
1994
1993 if new_file:
1995 if new_file:
1994 fn = "nf%i" % id
1996 fn = "nf%i" % id
1995 files.append(fn)
1997 files.append(fn)
1996 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1998 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1997 if len(ps) > 1:
1999 if len(ps) > 1:
1998 if not p2:
2000 if not p2:
1999 p2 = repo[ps[1]]
2001 p2 = repo[ps[1]]
2000 for fn in p2:
2002 for fn in p2:
2001 if fn.startswith("nf"):
2003 if fn.startswith("nf"):
2002 files.append(fn)
2004 files.append(fn)
2003 fctxs[fn] = p2[fn]
2005 fctxs[fn] = p2[fn]
2004
2006
2005 def fctxfn(repo, cx, path):
2007 def fctxfn(repo, cx, path):
2006 return fctxs.get(path)
2008 return fctxs.get(path)
2007
2009
2008 if len(ps) == 0 or ps[0] < 0:
2010 if len(ps) == 0 or ps[0] < 0:
2009 pars = [None, None]
2011 pars = [None, None]
2010 elif len(ps) == 1:
2012 elif len(ps) == 1:
2011 pars = [nodeids[ps[0]], None]
2013 pars = [nodeids[ps[0]], None]
2012 else:
2014 else:
2013 pars = [nodeids[p] for p in ps]
2015 pars = [nodeids[p] for p in ps]
2014 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2016 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2015 date=(id, 0),
2017 date=(id, 0),
2016 user="debugbuilddag",
2018 user="debugbuilddag",
2017 extra={'branch': atbranch})
2019 extra={'branch': atbranch})
2018 nodeid = repo.commitctx(cx)
2020 nodeid = repo.commitctx(cx)
2019 nodeids.append(nodeid)
2021 nodeids.append(nodeid)
2020 at = id
2022 at = id
2021 elif type == 'l':
2023 elif type == 'l':
2022 id, name = data
2024 id, name = data
2023 ui.note(('tag %s\n' % name))
2025 ui.note(('tag %s\n' % name))
2024 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2026 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2025 elif type == 'a':
2027 elif type == 'a':
2026 ui.note(('branch %s\n' % data))
2028 ui.note(('branch %s\n' % data))
2027 atbranch = data
2029 atbranch = data
2028 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2030 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2029 tr.close()
2031 tr.close()
2030
2032
2031 if tags:
2033 if tags:
2032 repo.vfs.write("localtags", "".join(tags))
2034 repo.vfs.write("localtags", "".join(tags))
2033 finally:
2035 finally:
2034 ui.progress(_('building'), None)
2036 ui.progress(_('building'), None)
2035 release(tr, lock, wlock)
2037 release(tr, lock, wlock)
2036
2038
2037 @command('debugbundle',
2039 @command('debugbundle',
2038 [('a', 'all', None, _('show all details')),
2040 [('a', 'all', None, _('show all details')),
2039 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2041 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2040 _('FILE'),
2042 _('FILE'),
2041 norepo=True)
2043 norepo=True)
2042 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2044 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2043 """lists the contents of a bundle"""
2045 """lists the contents of a bundle"""
2044 with hg.openpath(ui, bundlepath) as f:
2046 with hg.openpath(ui, bundlepath) as f:
2045 if spec:
2047 if spec:
2046 spec = exchange.getbundlespec(ui, f)
2048 spec = exchange.getbundlespec(ui, f)
2047 ui.write('%s\n' % spec)
2049 ui.write('%s\n' % spec)
2048 return
2050 return
2049
2051
2050 gen = exchange.readbundle(ui, f, bundlepath)
2052 gen = exchange.readbundle(ui, f, bundlepath)
2051 if isinstance(gen, bundle2.unbundle20):
2053 if isinstance(gen, bundle2.unbundle20):
2052 return _debugbundle2(ui, gen, all=all, **opts)
2054 return _debugbundle2(ui, gen, all=all, **opts)
2053 _debugchangegroup(ui, gen, all=all, **opts)
2055 _debugchangegroup(ui, gen, all=all, **opts)
2054
2056
2055 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2057 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2056 indent_string = ' ' * indent
2058 indent_string = ' ' * indent
2057 if all:
2059 if all:
2058 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2060 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2059 % indent_string)
2061 % indent_string)
2060
2062
2061 def showchunks(named):
2063 def showchunks(named):
2062 ui.write("\n%s%s\n" % (indent_string, named))
2064 ui.write("\n%s%s\n" % (indent_string, named))
2063 chain = None
2065 chain = None
2064 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2066 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2065 node = chunkdata['node']
2067 node = chunkdata['node']
2066 p1 = chunkdata['p1']
2068 p1 = chunkdata['p1']
2067 p2 = chunkdata['p2']
2069 p2 = chunkdata['p2']
2068 cs = chunkdata['cs']
2070 cs = chunkdata['cs']
2069 deltabase = chunkdata['deltabase']
2071 deltabase = chunkdata['deltabase']
2070 delta = chunkdata['delta']
2072 delta = chunkdata['delta']
2071 ui.write("%s%s %s %s %s %s %s\n" %
2073 ui.write("%s%s %s %s %s %s %s\n" %
2072 (indent_string, hex(node), hex(p1), hex(p2),
2074 (indent_string, hex(node), hex(p1), hex(p2),
2073 hex(cs), hex(deltabase), len(delta)))
2075 hex(cs), hex(deltabase), len(delta)))
2074 chain = node
2076 chain = node
2075
2077
2076 chunkdata = gen.changelogheader()
2078 chunkdata = gen.changelogheader()
2077 showchunks("changelog")
2079 showchunks("changelog")
2078 chunkdata = gen.manifestheader()
2080 chunkdata = gen.manifestheader()
2079 showchunks("manifest")
2081 showchunks("manifest")
2080 for chunkdata in iter(gen.filelogheader, {}):
2082 for chunkdata in iter(gen.filelogheader, {}):
2081 fname = chunkdata['filename']
2083 fname = chunkdata['filename']
2082 showchunks(fname)
2084 showchunks(fname)
2083 else:
2085 else:
2084 if isinstance(gen, bundle2.unbundle20):
2086 if isinstance(gen, bundle2.unbundle20):
2085 raise error.Abort(_('use debugbundle2 for this file'))
2087 raise error.Abort(_('use debugbundle2 for this file'))
2086 chunkdata = gen.changelogheader()
2088 chunkdata = gen.changelogheader()
2087 chain = None
2089 chain = None
2088 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2090 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2089 node = chunkdata['node']
2091 node = chunkdata['node']
2090 ui.write("%s%s\n" % (indent_string, hex(node)))
2092 ui.write("%s%s\n" % (indent_string, hex(node)))
2091 chain = node
2093 chain = node
2092
2094
2093 def _debugbundle2(ui, gen, all=None, **opts):
2095 def _debugbundle2(ui, gen, all=None, **opts):
2094 """lists the contents of a bundle2"""
2096 """lists the contents of a bundle2"""
2095 if not isinstance(gen, bundle2.unbundle20):
2097 if not isinstance(gen, bundle2.unbundle20):
2096 raise error.Abort(_('not a bundle2 file'))
2098 raise error.Abort(_('not a bundle2 file'))
2097 ui.write(('Stream params: %s\n' % repr(gen.params)))
2099 ui.write(('Stream params: %s\n' % repr(gen.params)))
2098 for part in gen.iterparts():
2100 for part in gen.iterparts():
2099 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2101 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2100 if part.type == 'changegroup':
2102 if part.type == 'changegroup':
2101 version = part.params.get('version', '01')
2103 version = part.params.get('version', '01')
2102 cg = changegroup.getunbundler(version, part, 'UN')
2104 cg = changegroup.getunbundler(version, part, 'UN')
2103 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2105 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2104
2106
2105 @command('debugcreatestreamclonebundle', [], 'FILE')
2107 @command('debugcreatestreamclonebundle', [], 'FILE')
2106 def debugcreatestreamclonebundle(ui, repo, fname):
2108 def debugcreatestreamclonebundle(ui, repo, fname):
2107 """create a stream clone bundle file
2109 """create a stream clone bundle file
2108
2110
2109 Stream bundles are special bundles that are essentially archives of
2111 Stream bundles are special bundles that are essentially archives of
2110 revlog files. They are commonly used for cloning very quickly.
2112 revlog files. They are commonly used for cloning very quickly.
2111 """
2113 """
2112 requirements, gen = streamclone.generatebundlev1(repo)
2114 requirements, gen = streamclone.generatebundlev1(repo)
2113 changegroup.writechunks(ui, gen, fname)
2115 changegroup.writechunks(ui, gen, fname)
2114
2116
2115 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2117 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2116
2118
2117 @command('debugapplystreamclonebundle', [], 'FILE')
2119 @command('debugapplystreamclonebundle', [], 'FILE')
2118 def debugapplystreamclonebundle(ui, repo, fname):
2120 def debugapplystreamclonebundle(ui, repo, fname):
2119 """apply a stream clone bundle file"""
2121 """apply a stream clone bundle file"""
2120 f = hg.openpath(ui, fname)
2122 f = hg.openpath(ui, fname)
2121 gen = exchange.readbundle(ui, f, fname)
2123 gen = exchange.readbundle(ui, f, fname)
2122 gen.apply(repo)
2124 gen.apply(repo)
2123
2125
2124 @command('debugcheckstate', [], '')
2126 @command('debugcheckstate', [], '')
2125 def debugcheckstate(ui, repo):
2127 def debugcheckstate(ui, repo):
2126 """validate the correctness of the current dirstate"""
2128 """validate the correctness of the current dirstate"""
2127 parent1, parent2 = repo.dirstate.parents()
2129 parent1, parent2 = repo.dirstate.parents()
2128 m1 = repo[parent1].manifest()
2130 m1 = repo[parent1].manifest()
2129 m2 = repo[parent2].manifest()
2131 m2 = repo[parent2].manifest()
2130 errors = 0
2132 errors = 0
2131 for f in repo.dirstate:
2133 for f in repo.dirstate:
2132 state = repo.dirstate[f]
2134 state = repo.dirstate[f]
2133 if state in "nr" and f not in m1:
2135 if state in "nr" and f not in m1:
2134 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2136 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2135 errors += 1
2137 errors += 1
2136 if state in "a" and f in m1:
2138 if state in "a" and f in m1:
2137 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2139 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2138 errors += 1
2140 errors += 1
2139 if state in "m" and f not in m1 and f not in m2:
2141 if state in "m" and f not in m1 and f not in m2:
2140 ui.warn(_("%s in state %s, but not in either manifest\n") %
2142 ui.warn(_("%s in state %s, but not in either manifest\n") %
2141 (f, state))
2143 (f, state))
2142 errors += 1
2144 errors += 1
2143 for f in m1:
2145 for f in m1:
2144 state = repo.dirstate[f]
2146 state = repo.dirstate[f]
2145 if state not in "nrm":
2147 if state not in "nrm":
2146 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2148 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2147 errors += 1
2149 errors += 1
2148 if errors:
2150 if errors:
2149 error = _(".hg/dirstate inconsistent with current parent's manifest")
2151 error = _(".hg/dirstate inconsistent with current parent's manifest")
2150 raise error.Abort(error)
2152 raise error.Abort(error)
2151
2153
2152 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2154 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2153 def debugcommands(ui, cmd='', *args):
2155 def debugcommands(ui, cmd='', *args):
2154 """list all available commands and options"""
2156 """list all available commands and options"""
2155 for cmd, vals in sorted(table.iteritems()):
2157 for cmd, vals in sorted(table.iteritems()):
2156 cmd = cmd.split('|')[0].strip('^')
2158 cmd = cmd.split('|')[0].strip('^')
2157 opts = ', '.join([i[1] for i in vals[1]])
2159 opts = ', '.join([i[1] for i in vals[1]])
2158 ui.write('%s: %s\n' % (cmd, opts))
2160 ui.write('%s: %s\n' % (cmd, opts))
2159
2161
2160 @command('debugcomplete',
2162 @command('debugcomplete',
2161 [('o', 'options', None, _('show the command options'))],
2163 [('o', 'options', None, _('show the command options'))],
2162 _('[-o] CMD'),
2164 _('[-o] CMD'),
2163 norepo=True)
2165 norepo=True)
2164 def debugcomplete(ui, cmd='', **opts):
2166 def debugcomplete(ui, cmd='', **opts):
2165 """returns the completion list associated with the given command"""
2167 """returns the completion list associated with the given command"""
2166
2168
2167 if opts.get('options'):
2169 if opts.get('options'):
2168 options = []
2170 options = []
2169 otables = [globalopts]
2171 otables = [globalopts]
2170 if cmd:
2172 if cmd:
2171 aliases, entry = cmdutil.findcmd(cmd, table, False)
2173 aliases, entry = cmdutil.findcmd(cmd, table, False)
2172 otables.append(entry[1])
2174 otables.append(entry[1])
2173 for t in otables:
2175 for t in otables:
2174 for o in t:
2176 for o in t:
2175 if "(DEPRECATED)" in o[3]:
2177 if "(DEPRECATED)" in o[3]:
2176 continue
2178 continue
2177 if o[0]:
2179 if o[0]:
2178 options.append('-%s' % o[0])
2180 options.append('-%s' % o[0])
2179 options.append('--%s' % o[1])
2181 options.append('--%s' % o[1])
2180 ui.write("%s\n" % "\n".join(options))
2182 ui.write("%s\n" % "\n".join(options))
2181 return
2183 return
2182
2184
2183 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2185 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2184 if ui.verbose:
2186 if ui.verbose:
2185 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2187 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2186 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2188 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2187
2189
2188 @command('debugdag',
2190 @command('debugdag',
2189 [('t', 'tags', None, _('use tags as labels')),
2191 [('t', 'tags', None, _('use tags as labels')),
2190 ('b', 'branches', None, _('annotate with branch names')),
2192 ('b', 'branches', None, _('annotate with branch names')),
2191 ('', 'dots', None, _('use dots for runs')),
2193 ('', 'dots', None, _('use dots for runs')),
2192 ('s', 'spaces', None, _('separate elements by spaces'))],
2194 ('s', 'spaces', None, _('separate elements by spaces'))],
2193 _('[OPTION]... [FILE [REV]...]'),
2195 _('[OPTION]... [FILE [REV]...]'),
2194 optionalrepo=True)
2196 optionalrepo=True)
2195 def debugdag(ui, repo, file_=None, *revs, **opts):
2197 def debugdag(ui, repo, file_=None, *revs, **opts):
2196 """format the changelog or an index DAG as a concise textual description
2198 """format the changelog or an index DAG as a concise textual description
2197
2199
2198 If you pass a revlog index, the revlog's DAG is emitted. If you list
2200 If you pass a revlog index, the revlog's DAG is emitted. If you list
2199 revision numbers, they get labeled in the output as rN.
2201 revision numbers, they get labeled in the output as rN.
2200
2202
2201 Otherwise, the changelog DAG of the current repo is emitted.
2203 Otherwise, the changelog DAG of the current repo is emitted.
2202 """
2204 """
2203 spaces = opts.get('spaces')
2205 spaces = opts.get('spaces')
2204 dots = opts.get('dots')
2206 dots = opts.get('dots')
2205 if file_:
2207 if file_:
2206 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2208 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2207 revs = set((int(r) for r in revs))
2209 revs = set((int(r) for r in revs))
2208 def events():
2210 def events():
2209 for r in rlog:
2211 for r in rlog:
2210 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2212 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2211 if p != -1))
2213 if p != -1))
2212 if r in revs:
2214 if r in revs:
2213 yield 'l', (r, "r%i" % r)
2215 yield 'l', (r, "r%i" % r)
2214 elif repo:
2216 elif repo:
2215 cl = repo.changelog
2217 cl = repo.changelog
2216 tags = opts.get('tags')
2218 tags = opts.get('tags')
2217 branches = opts.get('branches')
2219 branches = opts.get('branches')
2218 if tags:
2220 if tags:
2219 labels = {}
2221 labels = {}
2220 for l, n in repo.tags().items():
2222 for l, n in repo.tags().items():
2221 labels.setdefault(cl.rev(n), []).append(l)
2223 labels.setdefault(cl.rev(n), []).append(l)
2222 def events():
2224 def events():
2223 b = "default"
2225 b = "default"
2224 for r in cl:
2226 for r in cl:
2225 if branches:
2227 if branches:
2226 newb = cl.read(cl.node(r))[5]['branch']
2228 newb = cl.read(cl.node(r))[5]['branch']
2227 if newb != b:
2229 if newb != b:
2228 yield 'a', newb
2230 yield 'a', newb
2229 b = newb
2231 b = newb
2230 yield 'n', (r, list(p for p in cl.parentrevs(r)
2232 yield 'n', (r, list(p for p in cl.parentrevs(r)
2231 if p != -1))
2233 if p != -1))
2232 if tags:
2234 if tags:
2233 ls = labels.get(r)
2235 ls = labels.get(r)
2234 if ls:
2236 if ls:
2235 for l in ls:
2237 for l in ls:
2236 yield 'l', (r, l)
2238 yield 'l', (r, l)
2237 else:
2239 else:
2238 raise error.Abort(_('need repo for changelog dag'))
2240 raise error.Abort(_('need repo for changelog dag'))
2239
2241
2240 for line in dagparser.dagtextlines(events(),
2242 for line in dagparser.dagtextlines(events(),
2241 addspaces=spaces,
2243 addspaces=spaces,
2242 wraplabels=True,
2244 wraplabels=True,
2243 wrapannotations=True,
2245 wrapannotations=True,
2244 wrapnonlinear=dots,
2246 wrapnonlinear=dots,
2245 usedots=dots,
2247 usedots=dots,
2246 maxlinewidth=70):
2248 maxlinewidth=70):
2247 ui.write(line)
2249 ui.write(line)
2248 ui.write("\n")
2250 ui.write("\n")
2249
2251
2250 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2252 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2251 def debugdata(ui, repo, file_, rev=None, **opts):
2253 def debugdata(ui, repo, file_, rev=None, **opts):
2252 """dump the contents of a data file revision"""
2254 """dump the contents of a data file revision"""
2253 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2255 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2254 if rev is not None:
2256 if rev is not None:
2255 raise error.CommandError('debugdata', _('invalid arguments'))
2257 raise error.CommandError('debugdata', _('invalid arguments'))
2256 file_, rev = None, file_
2258 file_, rev = None, file_
2257 elif rev is None:
2259 elif rev is None:
2258 raise error.CommandError('debugdata', _('invalid arguments'))
2260 raise error.CommandError('debugdata', _('invalid arguments'))
2259 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2261 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2260 try:
2262 try:
2261 ui.write(r.revision(r.lookup(rev)))
2263 ui.write(r.revision(r.lookup(rev)))
2262 except KeyError:
2264 except KeyError:
2263 raise error.Abort(_('invalid revision identifier %s') % rev)
2265 raise error.Abort(_('invalid revision identifier %s') % rev)
2264
2266
2265 @command('debugdate',
2267 @command('debugdate',
2266 [('e', 'extended', None, _('try extended date formats'))],
2268 [('e', 'extended', None, _('try extended date formats'))],
2267 _('[-e] DATE [RANGE]'),
2269 _('[-e] DATE [RANGE]'),
2268 norepo=True, optionalrepo=True)
2270 norepo=True, optionalrepo=True)
2269 def debugdate(ui, date, range=None, **opts):
2271 def debugdate(ui, date, range=None, **opts):
2270 """parse and display a date"""
2272 """parse and display a date"""
2271 if opts["extended"]:
2273 if opts["extended"]:
2272 d = util.parsedate(date, util.extendeddateformats)
2274 d = util.parsedate(date, util.extendeddateformats)
2273 else:
2275 else:
2274 d = util.parsedate(date)
2276 d = util.parsedate(date)
2275 ui.write(("internal: %s %s\n") % d)
2277 ui.write(("internal: %s %s\n") % d)
2276 ui.write(("standard: %s\n") % util.datestr(d))
2278 ui.write(("standard: %s\n") % util.datestr(d))
2277 if range:
2279 if range:
2278 m = util.matchdate(range)
2280 m = util.matchdate(range)
2279 ui.write(("match: %s\n") % m(d[0]))
2281 ui.write(("match: %s\n") % m(d[0]))
2280
2282
2281 @command('debugdiscovery',
2283 @command('debugdiscovery',
2282 [('', 'old', None, _('use old-style discovery')),
2284 [('', 'old', None, _('use old-style discovery')),
2283 ('', 'nonheads', None,
2285 ('', 'nonheads', None,
2284 _('use old-style discovery with non-heads included')),
2286 _('use old-style discovery with non-heads included')),
2285 ] + remoteopts,
2287 ] + remoteopts,
2286 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2288 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2287 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2289 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2288 """runs the changeset discovery protocol in isolation"""
2290 """runs the changeset discovery protocol in isolation"""
2289 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2291 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2290 opts.get('branch'))
2292 opts.get('branch'))
2291 remote = hg.peer(repo, opts, remoteurl)
2293 remote = hg.peer(repo, opts, remoteurl)
2292 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2294 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2293
2295
2294 # make sure tests are repeatable
2296 # make sure tests are repeatable
2295 random.seed(12323)
2297 random.seed(12323)
2296
2298
2297 def doit(localheads, remoteheads, remote=remote):
2299 def doit(localheads, remoteheads, remote=remote):
2298 if opts.get('old'):
2300 if opts.get('old'):
2299 if localheads:
2301 if localheads:
2300 raise error.Abort('cannot use localheads with old style '
2302 raise error.Abort('cannot use localheads with old style '
2301 'discovery')
2303 'discovery')
2302 if not util.safehasattr(remote, 'branches'):
2304 if not util.safehasattr(remote, 'branches'):
2303 # enable in-client legacy support
2305 # enable in-client legacy support
2304 remote = localrepo.locallegacypeer(remote.local())
2306 remote = localrepo.locallegacypeer(remote.local())
2305 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2307 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2306 force=True)
2308 force=True)
2307 common = set(common)
2309 common = set(common)
2308 if not opts.get('nonheads'):
2310 if not opts.get('nonheads'):
2309 ui.write(("unpruned common: %s\n") %
2311 ui.write(("unpruned common: %s\n") %
2310 " ".join(sorted(short(n) for n in common)))
2312 " ".join(sorted(short(n) for n in common)))
2311 dag = dagutil.revlogdag(repo.changelog)
2313 dag = dagutil.revlogdag(repo.changelog)
2312 all = dag.ancestorset(dag.internalizeall(common))
2314 all = dag.ancestorset(dag.internalizeall(common))
2313 common = dag.externalizeall(dag.headsetofconnecteds(all))
2315 common = dag.externalizeall(dag.headsetofconnecteds(all))
2314 else:
2316 else:
2315 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2317 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2316 common = set(common)
2318 common = set(common)
2317 rheads = set(hds)
2319 rheads = set(hds)
2318 lheads = set(repo.heads())
2320 lheads = set(repo.heads())
2319 ui.write(("common heads: %s\n") %
2321 ui.write(("common heads: %s\n") %
2320 " ".join(sorted(short(n) for n in common)))
2322 " ".join(sorted(short(n) for n in common)))
2321 if lheads <= common:
2323 if lheads <= common:
2322 ui.write(("local is subset\n"))
2324 ui.write(("local is subset\n"))
2323 elif rheads <= common:
2325 elif rheads <= common:
2324 ui.write(("remote is subset\n"))
2326 ui.write(("remote is subset\n"))
2325
2327
2326 serverlogs = opts.get('serverlog')
2328 serverlogs = opts.get('serverlog')
2327 if serverlogs:
2329 if serverlogs:
2328 for filename in serverlogs:
2330 for filename in serverlogs:
2329 with open(filename, 'r') as logfile:
2331 with open(filename, 'r') as logfile:
2330 line = logfile.readline()
2332 line = logfile.readline()
2331 while line:
2333 while line:
2332 parts = line.strip().split(';')
2334 parts = line.strip().split(';')
2333 op = parts[1]
2335 op = parts[1]
2334 if op == 'cg':
2336 if op == 'cg':
2335 pass
2337 pass
2336 elif op == 'cgss':
2338 elif op == 'cgss':
2337 doit(parts[2].split(' '), parts[3].split(' '))
2339 doit(parts[2].split(' '), parts[3].split(' '))
2338 elif op == 'unb':
2340 elif op == 'unb':
2339 doit(parts[3].split(' '), parts[2].split(' '))
2341 doit(parts[3].split(' '), parts[2].split(' '))
2340 line = logfile.readline()
2342 line = logfile.readline()
2341 else:
2343 else:
2342 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2344 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2343 opts.get('remote_head'))
2345 opts.get('remote_head'))
2344 localrevs = opts.get('local_head')
2346 localrevs = opts.get('local_head')
2345 doit(localrevs, remoterevs)
2347 doit(localrevs, remoterevs)
2346
2348
2347 @command('debugextensions', formatteropts, [], norepo=True)
2349 @command('debugextensions', formatteropts, [], norepo=True)
2348 def debugextensions(ui, **opts):
2350 def debugextensions(ui, **opts):
2349 '''show information about active extensions'''
2351 '''show information about active extensions'''
2350 exts = extensions.extensions(ui)
2352 exts = extensions.extensions(ui)
2351 hgver = util.version()
2353 hgver = util.version()
2352 fm = ui.formatter('debugextensions', opts)
2354 fm = ui.formatter('debugextensions', opts)
2353 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2355 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2354 isinternal = extensions.ismoduleinternal(extmod)
2356 isinternal = extensions.ismoduleinternal(extmod)
2355 extsource = extmod.__file__
2357 extsource = extmod.__file__
2356 if isinternal:
2358 if isinternal:
2357 exttestedwith = [] # never expose magic string to users
2359 exttestedwith = [] # never expose magic string to users
2358 else:
2360 else:
2359 exttestedwith = getattr(extmod, 'testedwith', '').split()
2361 exttestedwith = getattr(extmod, 'testedwith', '').split()
2360 extbuglink = getattr(extmod, 'buglink', None)
2362 extbuglink = getattr(extmod, 'buglink', None)
2361
2363
2362 fm.startitem()
2364 fm.startitem()
2363
2365
2364 if ui.quiet or ui.verbose:
2366 if ui.quiet or ui.verbose:
2365 fm.write('name', '%s\n', extname)
2367 fm.write('name', '%s\n', extname)
2366 else:
2368 else:
2367 fm.write('name', '%s', extname)
2369 fm.write('name', '%s', extname)
2368 if isinternal or hgver in exttestedwith:
2370 if isinternal or hgver in exttestedwith:
2369 fm.plain('\n')
2371 fm.plain('\n')
2370 elif not exttestedwith:
2372 elif not exttestedwith:
2371 fm.plain(_(' (untested!)\n'))
2373 fm.plain(_(' (untested!)\n'))
2372 else:
2374 else:
2373 lasttestedversion = exttestedwith[-1]
2375 lasttestedversion = exttestedwith[-1]
2374 fm.plain(' (%s!)\n' % lasttestedversion)
2376 fm.plain(' (%s!)\n' % lasttestedversion)
2375
2377
2376 fm.condwrite(ui.verbose and extsource, 'source',
2378 fm.condwrite(ui.verbose and extsource, 'source',
2377 _(' location: %s\n'), extsource or "")
2379 _(' location: %s\n'), extsource or "")
2378
2380
2379 if ui.verbose:
2381 if ui.verbose:
2380 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2382 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2381 fm.data(bundled=isinternal)
2383 fm.data(bundled=isinternal)
2382
2384
2383 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2385 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2384 _(' tested with: %s\n'),
2386 _(' tested with: %s\n'),
2385 fm.formatlist(exttestedwith, name='ver'))
2387 fm.formatlist(exttestedwith, name='ver'))
2386
2388
2387 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2389 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2388 _(' bug reporting: %s\n'), extbuglink or "")
2390 _(' bug reporting: %s\n'), extbuglink or "")
2389
2391
2390 fm.end()
2392 fm.end()
2391
2393
2392 @command('debugfileset',
2394 @command('debugfileset',
2393 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2395 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2394 _('[-r REV] FILESPEC'))
2396 _('[-r REV] FILESPEC'))
2395 def debugfileset(ui, repo, expr, **opts):
2397 def debugfileset(ui, repo, expr, **opts):
2396 '''parse and apply a fileset specification'''
2398 '''parse and apply a fileset specification'''
2397 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2399 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2398 if ui.verbose:
2400 if ui.verbose:
2399 tree = fileset.parse(expr)
2401 tree = fileset.parse(expr)
2400 ui.note(fileset.prettyformat(tree), "\n")
2402 ui.note(fileset.prettyformat(tree), "\n")
2401
2403
2402 for f in ctx.getfileset(expr):
2404 for f in ctx.getfileset(expr):
2403 ui.write("%s\n" % f)
2405 ui.write("%s\n" % f)
2404
2406
2405 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2407 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2406 def debugfsinfo(ui, path="."):
2408 def debugfsinfo(ui, path="."):
2407 """show information detected about current filesystem"""
2409 """show information detected about current filesystem"""
2408 util.writefile('.debugfsinfo', '')
2410 util.writefile('.debugfsinfo', '')
2409 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2411 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2410 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2412 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2411 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2413 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2412 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2414 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2413 and 'yes' or 'no'))
2415 and 'yes' or 'no'))
2414 os.unlink('.debugfsinfo')
2416 os.unlink('.debugfsinfo')
2415
2417
2416 @command('debuggetbundle',
2418 @command('debuggetbundle',
2417 [('H', 'head', [], _('id of head node'), _('ID')),
2419 [('H', 'head', [], _('id of head node'), _('ID')),
2418 ('C', 'common', [], _('id of common node'), _('ID')),
2420 ('C', 'common', [], _('id of common node'), _('ID')),
2419 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2421 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2420 _('REPO FILE [-H|-C ID]...'),
2422 _('REPO FILE [-H|-C ID]...'),
2421 norepo=True)
2423 norepo=True)
2422 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2424 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2423 """retrieves a bundle from a repo
2425 """retrieves a bundle from a repo
2424
2426
2425 Every ID must be a full-length hex node id string. Saves the bundle to the
2427 Every ID must be a full-length hex node id string. Saves the bundle to the
2426 given file.
2428 given file.
2427 """
2429 """
2428 repo = hg.peer(ui, opts, repopath)
2430 repo = hg.peer(ui, opts, repopath)
2429 if not repo.capable('getbundle'):
2431 if not repo.capable('getbundle'):
2430 raise error.Abort("getbundle() not supported by target repository")
2432 raise error.Abort("getbundle() not supported by target repository")
2431 args = {}
2433 args = {}
2432 if common:
2434 if common:
2433 args['common'] = [bin(s) for s in common]
2435 args['common'] = [bin(s) for s in common]
2434 if head:
2436 if head:
2435 args['heads'] = [bin(s) for s in head]
2437 args['heads'] = [bin(s) for s in head]
2436 # TODO: get desired bundlecaps from command line.
2438 # TODO: get desired bundlecaps from command line.
2437 args['bundlecaps'] = None
2439 args['bundlecaps'] = None
2438 bundle = repo.getbundle('debug', **args)
2440 bundle = repo.getbundle('debug', **args)
2439
2441
2440 bundletype = opts.get('type', 'bzip2').lower()
2442 bundletype = opts.get('type', 'bzip2').lower()
2441 btypes = {'none': 'HG10UN',
2443 btypes = {'none': 'HG10UN',
2442 'bzip2': 'HG10BZ',
2444 'bzip2': 'HG10BZ',
2443 'gzip': 'HG10GZ',
2445 'gzip': 'HG10GZ',
2444 'bundle2': 'HG20'}
2446 'bundle2': 'HG20'}
2445 bundletype = btypes.get(bundletype)
2447 bundletype = btypes.get(bundletype)
2446 if bundletype not in bundle2.bundletypes:
2448 if bundletype not in bundle2.bundletypes:
2447 raise error.Abort(_('unknown bundle type specified with --type'))
2449 raise error.Abort(_('unknown bundle type specified with --type'))
2448 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2450 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2449
2451
2450 @command('debugignore', [], '[FILE]')
2452 @command('debugignore', [], '[FILE]')
2451 def debugignore(ui, repo, *files, **opts):
2453 def debugignore(ui, repo, *files, **opts):
2452 """display the combined ignore pattern and information about ignored files
2454 """display the combined ignore pattern and information about ignored files
2453
2455
2454 With no argument display the combined ignore pattern.
2456 With no argument display the combined ignore pattern.
2455
2457
2456 Given space separated file names, shows if the given file is ignored and
2458 Given space separated file names, shows if the given file is ignored and
2457 if so, show the ignore rule (file and line number) that matched it.
2459 if so, show the ignore rule (file and line number) that matched it.
2458 """
2460 """
2459 ignore = repo.dirstate._ignore
2461 ignore = repo.dirstate._ignore
2460 if not files:
2462 if not files:
2461 # Show all the patterns
2463 # Show all the patterns
2462 includepat = getattr(ignore, 'includepat', None)
2464 includepat = getattr(ignore, 'includepat', None)
2463 if includepat is not None:
2465 if includepat is not None:
2464 ui.write("%s\n" % includepat)
2466 ui.write("%s\n" % includepat)
2465 else:
2467 else:
2466 raise error.Abort(_("no ignore patterns found"))
2468 raise error.Abort(_("no ignore patterns found"))
2467 else:
2469 else:
2468 for f in files:
2470 for f in files:
2469 nf = util.normpath(f)
2471 nf = util.normpath(f)
2470 ignored = None
2472 ignored = None
2471 ignoredata = None
2473 ignoredata = None
2472 if nf != '.':
2474 if nf != '.':
2473 if ignore(nf):
2475 if ignore(nf):
2474 ignored = nf
2476 ignored = nf
2475 ignoredata = repo.dirstate._ignorefileandline(nf)
2477 ignoredata = repo.dirstate._ignorefileandline(nf)
2476 else:
2478 else:
2477 for p in util.finddirs(nf):
2479 for p in util.finddirs(nf):
2478 if ignore(p):
2480 if ignore(p):
2479 ignored = p
2481 ignored = p
2480 ignoredata = repo.dirstate._ignorefileandline(p)
2482 ignoredata = repo.dirstate._ignorefileandline(p)
2481 break
2483 break
2482 if ignored:
2484 if ignored:
2483 if ignored == nf:
2485 if ignored == nf:
2484 ui.write(_("%s is ignored\n") % f)
2486 ui.write(_("%s is ignored\n") % f)
2485 else:
2487 else:
2486 ui.write(_("%s is ignored because of "
2488 ui.write(_("%s is ignored because of "
2487 "containing folder %s\n")
2489 "containing folder %s\n")
2488 % (f, ignored))
2490 % (f, ignored))
2489 ignorefile, lineno, line = ignoredata
2491 ignorefile, lineno, line = ignoredata
2490 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2492 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2491 % (ignorefile, lineno, line))
2493 % (ignorefile, lineno, line))
2492 else:
2494 else:
2493 ui.write(_("%s is not ignored\n") % f)
2495 ui.write(_("%s is not ignored\n") % f)
2494
2496
2495 @command('debugindex', debugrevlogopts +
2497 @command('debugindex', debugrevlogopts +
2496 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2498 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2497 _('[-f FORMAT] -c|-m|FILE'),
2499 _('[-f FORMAT] -c|-m|FILE'),
2498 optionalrepo=True)
2500 optionalrepo=True)
2499 def debugindex(ui, repo, file_=None, **opts):
2501 def debugindex(ui, repo, file_=None, **opts):
2500 """dump the contents of an index file"""
2502 """dump the contents of an index file"""
2501 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2503 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2502 format = opts.get('format', 0)
2504 format = opts.get('format', 0)
2503 if format not in (0, 1):
2505 if format not in (0, 1):
2504 raise error.Abort(_("unknown format %d") % format)
2506 raise error.Abort(_("unknown format %d") % format)
2505
2507
2506 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2508 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2507 if generaldelta:
2509 if generaldelta:
2508 basehdr = ' delta'
2510 basehdr = ' delta'
2509 else:
2511 else:
2510 basehdr = ' base'
2512 basehdr = ' base'
2511
2513
2512 if ui.debugflag:
2514 if ui.debugflag:
2513 shortfn = hex
2515 shortfn = hex
2514 else:
2516 else:
2515 shortfn = short
2517 shortfn = short
2516
2518
2517 # There might not be anything in r, so have a sane default
2519 # There might not be anything in r, so have a sane default
2518 idlen = 12
2520 idlen = 12
2519 for i in r:
2521 for i in r:
2520 idlen = len(shortfn(r.node(i)))
2522 idlen = len(shortfn(r.node(i)))
2521 break
2523 break
2522
2524
2523 if format == 0:
2525 if format == 0:
2524 ui.write((" rev offset length " + basehdr + " linkrev"
2526 ui.write((" rev offset length " + basehdr + " linkrev"
2525 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2527 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2526 elif format == 1:
2528 elif format == 1:
2527 ui.write((" rev flag offset length"
2529 ui.write((" rev flag offset length"
2528 " size " + basehdr + " link p1 p2"
2530 " size " + basehdr + " link p1 p2"
2529 " %s\n") % "nodeid".rjust(idlen))
2531 " %s\n") % "nodeid".rjust(idlen))
2530
2532
2531 for i in r:
2533 for i in r:
2532 node = r.node(i)
2534 node = r.node(i)
2533 if generaldelta:
2535 if generaldelta:
2534 base = r.deltaparent(i)
2536 base = r.deltaparent(i)
2535 else:
2537 else:
2536 base = r.chainbase(i)
2538 base = r.chainbase(i)
2537 if format == 0:
2539 if format == 0:
2538 try:
2540 try:
2539 pp = r.parents(node)
2541 pp = r.parents(node)
2540 except Exception:
2542 except Exception:
2541 pp = [nullid, nullid]
2543 pp = [nullid, nullid]
2542 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2544 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2543 i, r.start(i), r.length(i), base, r.linkrev(i),
2545 i, r.start(i), r.length(i), base, r.linkrev(i),
2544 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2546 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2545 elif format == 1:
2547 elif format == 1:
2546 pr = r.parentrevs(i)
2548 pr = r.parentrevs(i)
2547 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2549 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2548 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2550 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2549 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2551 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2550
2552
2551 @command('debugindexdot', debugrevlogopts,
2553 @command('debugindexdot', debugrevlogopts,
2552 _('-c|-m|FILE'), optionalrepo=True)
2554 _('-c|-m|FILE'), optionalrepo=True)
2553 def debugindexdot(ui, repo, file_=None, **opts):
2555 def debugindexdot(ui, repo, file_=None, **opts):
2554 """dump an index DAG as a graphviz dot file"""
2556 """dump an index DAG as a graphviz dot file"""
2555 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2557 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2556 ui.write(("digraph G {\n"))
2558 ui.write(("digraph G {\n"))
2557 for i in r:
2559 for i in r:
2558 node = r.node(i)
2560 node = r.node(i)
2559 pp = r.parents(node)
2561 pp = r.parents(node)
2560 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2562 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2561 if pp[1] != nullid:
2563 if pp[1] != nullid:
2562 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2564 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2563 ui.write("}\n")
2565 ui.write("}\n")
2564
2566
2565 @command('debugdeltachain',
2567 @command('debugdeltachain',
2566 debugrevlogopts + formatteropts,
2568 debugrevlogopts + formatteropts,
2567 _('-c|-m|FILE'),
2569 _('-c|-m|FILE'),
2568 optionalrepo=True)
2570 optionalrepo=True)
2569 def debugdeltachain(ui, repo, file_=None, **opts):
2571 def debugdeltachain(ui, repo, file_=None, **opts):
2570 """dump information about delta chains in a revlog
2572 """dump information about delta chains in a revlog
2571
2573
2572 Output can be templatized. Available template keywords are:
2574 Output can be templatized. Available template keywords are:
2573
2575
2574 :``rev``: revision number
2576 :``rev``: revision number
2575 :``chainid``: delta chain identifier (numbered by unique base)
2577 :``chainid``: delta chain identifier (numbered by unique base)
2576 :``chainlen``: delta chain length to this revision
2578 :``chainlen``: delta chain length to this revision
2577 :``prevrev``: previous revision in delta chain
2579 :``prevrev``: previous revision in delta chain
2578 :``deltatype``: role of delta / how it was computed
2580 :``deltatype``: role of delta / how it was computed
2579 :``compsize``: compressed size of revision
2581 :``compsize``: compressed size of revision
2580 :``uncompsize``: uncompressed size of revision
2582 :``uncompsize``: uncompressed size of revision
2581 :``chainsize``: total size of compressed revisions in chain
2583 :``chainsize``: total size of compressed revisions in chain
2582 :``chainratio``: total chain size divided by uncompressed revision size
2584 :``chainratio``: total chain size divided by uncompressed revision size
2583 (new delta chains typically start at ratio 2.00)
2585 (new delta chains typically start at ratio 2.00)
2584 :``lindist``: linear distance from base revision in delta chain to end
2586 :``lindist``: linear distance from base revision in delta chain to end
2585 of this revision
2587 of this revision
2586 :``extradist``: total size of revisions not part of this delta chain from
2588 :``extradist``: total size of revisions not part of this delta chain from
2587 base of delta chain to end of this revision; a measurement
2589 base of delta chain to end of this revision; a measurement
2588 of how much extra data we need to read/seek across to read
2590 of how much extra data we need to read/seek across to read
2589 the delta chain for this revision
2591 the delta chain for this revision
2590 :``extraratio``: extradist divided by chainsize; another representation of
2592 :``extraratio``: extradist divided by chainsize; another representation of
2591 how much unrelated data is needed to load this delta chain
2593 how much unrelated data is needed to load this delta chain
2592 """
2594 """
2593 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2595 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2594 index = r.index
2596 index = r.index
2595 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2597 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2596
2598
2597 def revinfo(rev):
2599 def revinfo(rev):
2598 e = index[rev]
2600 e = index[rev]
2599 compsize = e[1]
2601 compsize = e[1]
2600 uncompsize = e[2]
2602 uncompsize = e[2]
2601 chainsize = 0
2603 chainsize = 0
2602
2604
2603 if generaldelta:
2605 if generaldelta:
2604 if e[3] == e[5]:
2606 if e[3] == e[5]:
2605 deltatype = 'p1'
2607 deltatype = 'p1'
2606 elif e[3] == e[6]:
2608 elif e[3] == e[6]:
2607 deltatype = 'p2'
2609 deltatype = 'p2'
2608 elif e[3] == rev - 1:
2610 elif e[3] == rev - 1:
2609 deltatype = 'prev'
2611 deltatype = 'prev'
2610 elif e[3] == rev:
2612 elif e[3] == rev:
2611 deltatype = 'base'
2613 deltatype = 'base'
2612 else:
2614 else:
2613 deltatype = 'other'
2615 deltatype = 'other'
2614 else:
2616 else:
2615 if e[3] == rev:
2617 if e[3] == rev:
2616 deltatype = 'base'
2618 deltatype = 'base'
2617 else:
2619 else:
2618 deltatype = 'prev'
2620 deltatype = 'prev'
2619
2621
2620 chain = r._deltachain(rev)[0]
2622 chain = r._deltachain(rev)[0]
2621 for iterrev in chain:
2623 for iterrev in chain:
2622 e = index[iterrev]
2624 e = index[iterrev]
2623 chainsize += e[1]
2625 chainsize += e[1]
2624
2626
2625 return compsize, uncompsize, deltatype, chain, chainsize
2627 return compsize, uncompsize, deltatype, chain, chainsize
2626
2628
2627 fm = ui.formatter('debugdeltachain', opts)
2629 fm = ui.formatter('debugdeltachain', opts)
2628
2630
2629 fm.plain(' rev chain# chainlen prev delta '
2631 fm.plain(' rev chain# chainlen prev delta '
2630 'size rawsize chainsize ratio lindist extradist '
2632 'size rawsize chainsize ratio lindist extradist '
2631 'extraratio\n')
2633 'extraratio\n')
2632
2634
2633 chainbases = {}
2635 chainbases = {}
2634 for rev in r:
2636 for rev in r:
2635 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2637 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2636 chainbase = chain[0]
2638 chainbase = chain[0]
2637 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2639 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2638 basestart = r.start(chainbase)
2640 basestart = r.start(chainbase)
2639 revstart = r.start(rev)
2641 revstart = r.start(rev)
2640 lineardist = revstart + comp - basestart
2642 lineardist = revstart + comp - basestart
2641 extradist = lineardist - chainsize
2643 extradist = lineardist - chainsize
2642 try:
2644 try:
2643 prevrev = chain[-2]
2645 prevrev = chain[-2]
2644 except IndexError:
2646 except IndexError:
2645 prevrev = -1
2647 prevrev = -1
2646
2648
2647 chainratio = float(chainsize) / float(uncomp)
2649 chainratio = float(chainsize) / float(uncomp)
2648 extraratio = float(extradist) / float(chainsize)
2650 extraratio = float(extradist) / float(chainsize)
2649
2651
2650 fm.startitem()
2652 fm.startitem()
2651 fm.write('rev chainid chainlen prevrev deltatype compsize '
2653 fm.write('rev chainid chainlen prevrev deltatype compsize '
2652 'uncompsize chainsize chainratio lindist extradist '
2654 'uncompsize chainsize chainratio lindist extradist '
2653 'extraratio',
2655 'extraratio',
2654 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2656 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2655 rev, chainid, len(chain), prevrev, deltatype, comp,
2657 rev, chainid, len(chain), prevrev, deltatype, comp,
2656 uncomp, chainsize, chainratio, lineardist, extradist,
2658 uncomp, chainsize, chainratio, lineardist, extradist,
2657 extraratio,
2659 extraratio,
2658 rev=rev, chainid=chainid, chainlen=len(chain),
2660 rev=rev, chainid=chainid, chainlen=len(chain),
2659 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2661 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2660 uncompsize=uncomp, chainsize=chainsize,
2662 uncompsize=uncomp, chainsize=chainsize,
2661 chainratio=chainratio, lindist=lineardist,
2663 chainratio=chainratio, lindist=lineardist,
2662 extradist=extradist, extraratio=extraratio)
2664 extradist=extradist, extraratio=extraratio)
2663
2665
2664 fm.end()
2666 fm.end()
2665
2667
2666 @command('debuginstall', [] + formatteropts, '', norepo=True)
2668 @command('debuginstall', [] + formatteropts, '', norepo=True)
2667 def debuginstall(ui, **opts):
2669 def debuginstall(ui, **opts):
2668 '''test Mercurial installation
2670 '''test Mercurial installation
2669
2671
2670 Returns 0 on success.
2672 Returns 0 on success.
2671 '''
2673 '''
2672
2674
2673 def writetemp(contents):
2675 def writetemp(contents):
2674 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2676 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2675 f = os.fdopen(fd, "wb")
2677 f = os.fdopen(fd, "wb")
2676 f.write(contents)
2678 f.write(contents)
2677 f.close()
2679 f.close()
2678 return name
2680 return name
2679
2681
2680 problems = 0
2682 problems = 0
2681
2683
2682 fm = ui.formatter('debuginstall', opts)
2684 fm = ui.formatter('debuginstall', opts)
2683 fm.startitem()
2685 fm.startitem()
2684
2686
2685 # encoding
2687 # encoding
2686 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2688 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2687 err = None
2689 err = None
2688 try:
2690 try:
2689 encoding.fromlocal("test")
2691 encoding.fromlocal("test")
2690 except error.Abort as inst:
2692 except error.Abort as inst:
2691 err = inst
2693 err = inst
2692 problems += 1
2694 problems += 1
2693 fm.condwrite(err, 'encodingerror', _(" %s\n"
2695 fm.condwrite(err, 'encodingerror', _(" %s\n"
2694 " (check that your locale is properly set)\n"), err)
2696 " (check that your locale is properly set)\n"), err)
2695
2697
2696 # Python
2698 # Python
2697 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2699 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2698 sys.executable)
2700 sys.executable)
2699 fm.write('pythonver', _("checking Python version (%s)\n"),
2701 fm.write('pythonver', _("checking Python version (%s)\n"),
2700 ("%s.%s.%s" % sys.version_info[:3]))
2702 ("%s.%s.%s" % sys.version_info[:3]))
2701 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2703 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2702 os.path.dirname(os.__file__))
2704 os.path.dirname(os.__file__))
2703
2705
2704 # hg version
2706 # hg version
2705 hgver = util.version()
2707 hgver = util.version()
2706 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2708 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2707 hgver.split('+')[0])
2709 hgver.split('+')[0])
2708 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2710 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2709 '+'.join(hgver.split('+')[1:]))
2711 '+'.join(hgver.split('+')[1:]))
2710
2712
2711 # compiled modules
2713 # compiled modules
2712 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2714 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2713 policy.policy)
2715 policy.policy)
2714 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2716 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2715 os.path.dirname(__file__))
2717 os.path.dirname(__file__))
2716
2718
2717 err = None
2719 err = None
2718 try:
2720 try:
2719 from . import (
2721 from . import (
2720 base85,
2722 base85,
2721 bdiff,
2723 bdiff,
2722 mpatch,
2724 mpatch,
2723 osutil,
2725 osutil,
2724 )
2726 )
2725 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2727 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2726 except Exception as inst:
2728 except Exception as inst:
2727 err = inst
2729 err = inst
2728 problems += 1
2730 problems += 1
2729 fm.condwrite(err, 'extensionserror', " %s\n", err)
2731 fm.condwrite(err, 'extensionserror', " %s\n", err)
2730
2732
2731 # templates
2733 # templates
2732 p = templater.templatepaths()
2734 p = templater.templatepaths()
2733 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2735 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2734 fm.condwrite(not p, '', _(" no template directories found\n"))
2736 fm.condwrite(not p, '', _(" no template directories found\n"))
2735 if p:
2737 if p:
2736 m = templater.templatepath("map-cmdline.default")
2738 m = templater.templatepath("map-cmdline.default")
2737 if m:
2739 if m:
2738 # template found, check if it is working
2740 # template found, check if it is working
2739 err = None
2741 err = None
2740 try:
2742 try:
2741 templater.templater.frommapfile(m)
2743 templater.templater.frommapfile(m)
2742 except Exception as inst:
2744 except Exception as inst:
2743 err = inst
2745 err = inst
2744 p = None
2746 p = None
2745 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2747 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2746 else:
2748 else:
2747 p = None
2749 p = None
2748 fm.condwrite(p, 'defaulttemplate',
2750 fm.condwrite(p, 'defaulttemplate',
2749 _("checking default template (%s)\n"), m)
2751 _("checking default template (%s)\n"), m)
2750 fm.condwrite(not m, 'defaulttemplatenotfound',
2752 fm.condwrite(not m, 'defaulttemplatenotfound',
2751 _(" template '%s' not found\n"), "default")
2753 _(" template '%s' not found\n"), "default")
2752 if not p:
2754 if not p:
2753 problems += 1
2755 problems += 1
2754 fm.condwrite(not p, '',
2756 fm.condwrite(not p, '',
2755 _(" (templates seem to have been installed incorrectly)\n"))
2757 _(" (templates seem to have been installed incorrectly)\n"))
2756
2758
2757 # editor
2759 # editor
2758 editor = ui.geteditor()
2760 editor = ui.geteditor()
2759 editor = util.expandpath(editor)
2761 editor = util.expandpath(editor)
2760 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2762 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2761 cmdpath = util.findexe(shlex.split(editor)[0])
2763 cmdpath = util.findexe(shlex.split(editor)[0])
2762 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2764 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2763 _(" No commit editor set and can't find %s in PATH\n"
2765 _(" No commit editor set and can't find %s in PATH\n"
2764 " (specify a commit editor in your configuration"
2766 " (specify a commit editor in your configuration"
2765 " file)\n"), not cmdpath and editor == 'vi' and editor)
2767 " file)\n"), not cmdpath and editor == 'vi' and editor)
2766 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2768 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2767 _(" Can't find editor '%s' in PATH\n"
2769 _(" Can't find editor '%s' in PATH\n"
2768 " (specify a commit editor in your configuration"
2770 " (specify a commit editor in your configuration"
2769 " file)\n"), not cmdpath and editor)
2771 " file)\n"), not cmdpath and editor)
2770 if not cmdpath and editor != 'vi':
2772 if not cmdpath and editor != 'vi':
2771 problems += 1
2773 problems += 1
2772
2774
2773 # check username
2775 # check username
2774 username = None
2776 username = None
2775 err = None
2777 err = None
2776 try:
2778 try:
2777 username = ui.username()
2779 username = ui.username()
2778 except error.Abort as e:
2780 except error.Abort as e:
2779 err = e
2781 err = e
2780 problems += 1
2782 problems += 1
2781
2783
2782 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2784 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2783 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2785 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2784 " (specify a username in your configuration file)\n"), err)
2786 " (specify a username in your configuration file)\n"), err)
2785
2787
2786 fm.condwrite(not problems, '',
2788 fm.condwrite(not problems, '',
2787 _("no problems detected\n"))
2789 _("no problems detected\n"))
2788 if not problems:
2790 if not problems:
2789 fm.data(problems=problems)
2791 fm.data(problems=problems)
2790 fm.condwrite(problems, 'problems',
2792 fm.condwrite(problems, 'problems',
2791 _("%d problems detected,"
2793 _("%d problems detected,"
2792 " please check your install!\n"), problems)
2794 " please check your install!\n"), problems)
2793 fm.end()
2795 fm.end()
2794
2796
2795 return problems
2797 return problems
2796
2798
2797 @command('debugknown', [], _('REPO ID...'), norepo=True)
2799 @command('debugknown', [], _('REPO ID...'), norepo=True)
2798 def debugknown(ui, repopath, *ids, **opts):
2800 def debugknown(ui, repopath, *ids, **opts):
2799 """test whether node ids are known to a repo
2801 """test whether node ids are known to a repo
2800
2802
2801 Every ID must be a full-length hex node id string. Returns a list of 0s
2803 Every ID must be a full-length hex node id string. Returns a list of 0s
2802 and 1s indicating unknown/known.
2804 and 1s indicating unknown/known.
2803 """
2805 """
2804 repo = hg.peer(ui, opts, repopath)
2806 repo = hg.peer(ui, opts, repopath)
2805 if not repo.capable('known'):
2807 if not repo.capable('known'):
2806 raise error.Abort("known() not supported by target repository")
2808 raise error.Abort("known() not supported by target repository")
2807 flags = repo.known([bin(s) for s in ids])
2809 flags = repo.known([bin(s) for s in ids])
2808 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2810 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2809
2811
2810 @command('debuglabelcomplete', [], _('LABEL...'))
2812 @command('debuglabelcomplete', [], _('LABEL...'))
2811 def debuglabelcomplete(ui, repo, *args):
2813 def debuglabelcomplete(ui, repo, *args):
2812 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2814 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2813 debugnamecomplete(ui, repo, *args)
2815 debugnamecomplete(ui, repo, *args)
2814
2816
2815 @command('debugmergestate', [], '')
2817 @command('debugmergestate', [], '')
2816 def debugmergestate(ui, repo, *args):
2818 def debugmergestate(ui, repo, *args):
2817 """print merge state
2819 """print merge state
2818
2820
2819 Use --verbose to print out information about whether v1 or v2 merge state
2821 Use --verbose to print out information about whether v1 or v2 merge state
2820 was chosen."""
2822 was chosen."""
2821 def _hashornull(h):
2823 def _hashornull(h):
2822 if h == nullhex:
2824 if h == nullhex:
2823 return 'null'
2825 return 'null'
2824 else:
2826 else:
2825 return h
2827 return h
2826
2828
2827 def printrecords(version):
2829 def printrecords(version):
2828 ui.write(('* version %s records\n') % version)
2830 ui.write(('* version %s records\n') % version)
2829 if version == 1:
2831 if version == 1:
2830 records = v1records
2832 records = v1records
2831 else:
2833 else:
2832 records = v2records
2834 records = v2records
2833
2835
2834 for rtype, record in records:
2836 for rtype, record in records:
2835 # pretty print some record types
2837 # pretty print some record types
2836 if rtype == 'L':
2838 if rtype == 'L':
2837 ui.write(('local: %s\n') % record)
2839 ui.write(('local: %s\n') % record)
2838 elif rtype == 'O':
2840 elif rtype == 'O':
2839 ui.write(('other: %s\n') % record)
2841 ui.write(('other: %s\n') % record)
2840 elif rtype == 'm':
2842 elif rtype == 'm':
2841 driver, mdstate = record.split('\0', 1)
2843 driver, mdstate = record.split('\0', 1)
2842 ui.write(('merge driver: %s (state "%s")\n')
2844 ui.write(('merge driver: %s (state "%s")\n')
2843 % (driver, mdstate))
2845 % (driver, mdstate))
2844 elif rtype in 'FDC':
2846 elif rtype in 'FDC':
2845 r = record.split('\0')
2847 r = record.split('\0')
2846 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2848 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2847 if version == 1:
2849 if version == 1:
2848 onode = 'not stored in v1 format'
2850 onode = 'not stored in v1 format'
2849 flags = r[7]
2851 flags = r[7]
2850 else:
2852 else:
2851 onode, flags = r[7:9]
2853 onode, flags = r[7:9]
2852 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2854 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2853 % (f, rtype, state, _hashornull(hash)))
2855 % (f, rtype, state, _hashornull(hash)))
2854 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2856 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2855 ui.write((' ancestor path: %s (node %s)\n')
2857 ui.write((' ancestor path: %s (node %s)\n')
2856 % (afile, _hashornull(anode)))
2858 % (afile, _hashornull(anode)))
2857 ui.write((' other path: %s (node %s)\n')
2859 ui.write((' other path: %s (node %s)\n')
2858 % (ofile, _hashornull(onode)))
2860 % (ofile, _hashornull(onode)))
2859 elif rtype == 'f':
2861 elif rtype == 'f':
2860 filename, rawextras = record.split('\0', 1)
2862 filename, rawextras = record.split('\0', 1)
2861 extras = rawextras.split('\0')
2863 extras = rawextras.split('\0')
2862 i = 0
2864 i = 0
2863 extrastrings = []
2865 extrastrings = []
2864 while i < len(extras):
2866 while i < len(extras):
2865 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2867 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2866 i += 2
2868 i += 2
2867
2869
2868 ui.write(('file extras: %s (%s)\n')
2870 ui.write(('file extras: %s (%s)\n')
2869 % (filename, ', '.join(extrastrings)))
2871 % (filename, ', '.join(extrastrings)))
2870 elif rtype == 'l':
2872 elif rtype == 'l':
2871 labels = record.split('\0', 2)
2873 labels = record.split('\0', 2)
2872 labels = [l for l in labels if len(l) > 0]
2874 labels = [l for l in labels if len(l) > 0]
2873 ui.write(('labels:\n'))
2875 ui.write(('labels:\n'))
2874 ui.write((' local: %s\n' % labels[0]))
2876 ui.write((' local: %s\n' % labels[0]))
2875 ui.write((' other: %s\n' % labels[1]))
2877 ui.write((' other: %s\n' % labels[1]))
2876 if len(labels) > 2:
2878 if len(labels) > 2:
2877 ui.write((' base: %s\n' % labels[2]))
2879 ui.write((' base: %s\n' % labels[2]))
2878 else:
2880 else:
2879 ui.write(('unrecognized entry: %s\t%s\n')
2881 ui.write(('unrecognized entry: %s\t%s\n')
2880 % (rtype, record.replace('\0', '\t')))
2882 % (rtype, record.replace('\0', '\t')))
2881
2883
2882 # Avoid mergestate.read() since it may raise an exception for unsupported
2884 # Avoid mergestate.read() since it may raise an exception for unsupported
2883 # merge state records. We shouldn't be doing this, but this is OK since this
2885 # merge state records. We shouldn't be doing this, but this is OK since this
2884 # command is pretty low-level.
2886 # command is pretty low-level.
2885 ms = mergemod.mergestate(repo)
2887 ms = mergemod.mergestate(repo)
2886
2888
2887 # sort so that reasonable information is on top
2889 # sort so that reasonable information is on top
2888 v1records = ms._readrecordsv1()
2890 v1records = ms._readrecordsv1()
2889 v2records = ms._readrecordsv2()
2891 v2records = ms._readrecordsv2()
2890 order = 'LOml'
2892 order = 'LOml'
2891 def key(r):
2893 def key(r):
2892 idx = order.find(r[0])
2894 idx = order.find(r[0])
2893 if idx == -1:
2895 if idx == -1:
2894 return (1, r[1])
2896 return (1, r[1])
2895 else:
2897 else:
2896 return (0, idx)
2898 return (0, idx)
2897 v1records.sort(key=key)
2899 v1records.sort(key=key)
2898 v2records.sort(key=key)
2900 v2records.sort(key=key)
2899
2901
2900 if not v1records and not v2records:
2902 if not v1records and not v2records:
2901 ui.write(('no merge state found\n'))
2903 ui.write(('no merge state found\n'))
2902 elif not v2records:
2904 elif not v2records:
2903 ui.note(('no version 2 merge state\n'))
2905 ui.note(('no version 2 merge state\n'))
2904 printrecords(1)
2906 printrecords(1)
2905 elif ms._v1v2match(v1records, v2records):
2907 elif ms._v1v2match(v1records, v2records):
2906 ui.note(('v1 and v2 states match: using v2\n'))
2908 ui.note(('v1 and v2 states match: using v2\n'))
2907 printrecords(2)
2909 printrecords(2)
2908 else:
2910 else:
2909 ui.note(('v1 and v2 states mismatch: using v1\n'))
2911 ui.note(('v1 and v2 states mismatch: using v1\n'))
2910 printrecords(1)
2912 printrecords(1)
2911 if ui.verbose:
2913 if ui.verbose:
2912 printrecords(2)
2914 printrecords(2)
2913
2915
2914 @command('debugnamecomplete', [], _('NAME...'))
2916 @command('debugnamecomplete', [], _('NAME...'))
2915 def debugnamecomplete(ui, repo, *args):
2917 def debugnamecomplete(ui, repo, *args):
2916 '''complete "names" - tags, open branch names, bookmark names'''
2918 '''complete "names" - tags, open branch names, bookmark names'''
2917
2919
2918 names = set()
2920 names = set()
2919 # since we previously only listed open branches, we will handle that
2921 # since we previously only listed open branches, we will handle that
2920 # specially (after this for loop)
2922 # specially (after this for loop)
2921 for name, ns in repo.names.iteritems():
2923 for name, ns in repo.names.iteritems():
2922 if name != 'branches':
2924 if name != 'branches':
2923 names.update(ns.listnames(repo))
2925 names.update(ns.listnames(repo))
2924 names.update(tag for (tag, heads, tip, closed)
2926 names.update(tag for (tag, heads, tip, closed)
2925 in repo.branchmap().iterbranches() if not closed)
2927 in repo.branchmap().iterbranches() if not closed)
2926 completions = set()
2928 completions = set()
2927 if not args:
2929 if not args:
2928 args = ['']
2930 args = ['']
2929 for a in args:
2931 for a in args:
2930 completions.update(n for n in names if n.startswith(a))
2932 completions.update(n for n in names if n.startswith(a))
2931 ui.write('\n'.join(sorted(completions)))
2933 ui.write('\n'.join(sorted(completions)))
2932 ui.write('\n')
2934 ui.write('\n')
2933
2935
2934 @command('debuglocks',
2936 @command('debuglocks',
2935 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2937 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2936 ('W', 'force-wlock', None,
2938 ('W', 'force-wlock', None,
2937 _('free the working state lock (DANGEROUS)'))],
2939 _('free the working state lock (DANGEROUS)'))],
2938 _('[OPTION]...'))
2940 _('[OPTION]...'))
2939 def debuglocks(ui, repo, **opts):
2941 def debuglocks(ui, repo, **opts):
2940 """show or modify state of locks
2942 """show or modify state of locks
2941
2943
2942 By default, this command will show which locks are held. This
2944 By default, this command will show which locks are held. This
2943 includes the user and process holding the lock, the amount of time
2945 includes the user and process holding the lock, the amount of time
2944 the lock has been held, and the machine name where the process is
2946 the lock has been held, and the machine name where the process is
2945 running if it's not local.
2947 running if it's not local.
2946
2948
2947 Locks protect the integrity of Mercurial's data, so should be
2949 Locks protect the integrity of Mercurial's data, so should be
2948 treated with care. System crashes or other interruptions may cause
2950 treated with care. System crashes or other interruptions may cause
2949 locks to not be properly released, though Mercurial will usually
2951 locks to not be properly released, though Mercurial will usually
2950 detect and remove such stale locks automatically.
2952 detect and remove such stale locks automatically.
2951
2953
2952 However, detecting stale locks may not always be possible (for
2954 However, detecting stale locks may not always be possible (for
2953 instance, on a shared filesystem). Removing locks may also be
2955 instance, on a shared filesystem). Removing locks may also be
2954 blocked by filesystem permissions.
2956 blocked by filesystem permissions.
2955
2957
2956 Returns 0 if no locks are held.
2958 Returns 0 if no locks are held.
2957
2959
2958 """
2960 """
2959
2961
2960 if opts.get('force_lock'):
2962 if opts.get('force_lock'):
2961 repo.svfs.unlink('lock')
2963 repo.svfs.unlink('lock')
2962 if opts.get('force_wlock'):
2964 if opts.get('force_wlock'):
2963 repo.vfs.unlink('wlock')
2965 repo.vfs.unlink('wlock')
2964 if opts.get('force_lock') or opts.get('force_lock'):
2966 if opts.get('force_lock') or opts.get('force_lock'):
2965 return 0
2967 return 0
2966
2968
2967 now = time.time()
2969 now = time.time()
2968 held = 0
2970 held = 0
2969
2971
2970 def report(vfs, name, method):
2972 def report(vfs, name, method):
2971 # this causes stale locks to get reaped for more accurate reporting
2973 # this causes stale locks to get reaped for more accurate reporting
2972 try:
2974 try:
2973 l = method(False)
2975 l = method(False)
2974 except error.LockHeld:
2976 except error.LockHeld:
2975 l = None
2977 l = None
2976
2978
2977 if l:
2979 if l:
2978 l.release()
2980 l.release()
2979 else:
2981 else:
2980 try:
2982 try:
2981 stat = vfs.lstat(name)
2983 stat = vfs.lstat(name)
2982 age = now - stat.st_mtime
2984 age = now - stat.st_mtime
2983 user = util.username(stat.st_uid)
2985 user = util.username(stat.st_uid)
2984 locker = vfs.readlock(name)
2986 locker = vfs.readlock(name)
2985 if ":" in locker:
2987 if ":" in locker:
2986 host, pid = locker.split(':')
2988 host, pid = locker.split(':')
2987 if host == socket.gethostname():
2989 if host == socket.gethostname():
2988 locker = 'user %s, process %s' % (user, pid)
2990 locker = 'user %s, process %s' % (user, pid)
2989 else:
2991 else:
2990 locker = 'user %s, process %s, host %s' \
2992 locker = 'user %s, process %s, host %s' \
2991 % (user, pid, host)
2993 % (user, pid, host)
2992 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
2994 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
2993 return 1
2995 return 1
2994 except OSError as e:
2996 except OSError as e:
2995 if e.errno != errno.ENOENT:
2997 if e.errno != errno.ENOENT:
2996 raise
2998 raise
2997
2999
2998 ui.write(("%-6s free\n") % (name + ":"))
3000 ui.write(("%-6s free\n") % (name + ":"))
2999 return 0
3001 return 0
3000
3002
3001 held += report(repo.svfs, "lock", repo.lock)
3003 held += report(repo.svfs, "lock", repo.lock)
3002 held += report(repo.vfs, "wlock", repo.wlock)
3004 held += report(repo.vfs, "wlock", repo.wlock)
3003
3005
3004 return held
3006 return held
3005
3007
3006 @command('debugobsolete',
3008 @command('debugobsolete',
3007 [('', 'flags', 0, _('markers flag')),
3009 [('', 'flags', 0, _('markers flag')),
3008 ('', 'record-parents', False,
3010 ('', 'record-parents', False,
3009 _('record parent information for the precursor')),
3011 _('record parent information for the precursor')),
3010 ('r', 'rev', [], _('display markers relevant to REV')),
3012 ('r', 'rev', [], _('display markers relevant to REV')),
3011 ('', 'index', False, _('display index of the marker')),
3013 ('', 'index', False, _('display index of the marker')),
3012 ('', 'delete', [], _('delete markers specified by indices')),
3014 ('', 'delete', [], _('delete markers specified by indices')),
3013 ] + commitopts2 + formatteropts,
3015 ] + commitopts2 + formatteropts,
3014 _('[OBSOLETED [REPLACEMENT ...]]'))
3016 _('[OBSOLETED [REPLACEMENT ...]]'))
3015 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3017 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3016 """create arbitrary obsolete marker
3018 """create arbitrary obsolete marker
3017
3019
3018 With no arguments, displays the list of obsolescence markers."""
3020 With no arguments, displays the list of obsolescence markers."""
3019
3021
3020 def parsenodeid(s):
3022 def parsenodeid(s):
3021 try:
3023 try:
3022 # We do not use revsingle/revrange functions here to accept
3024 # We do not use revsingle/revrange functions here to accept
3023 # arbitrary node identifiers, possibly not present in the
3025 # arbitrary node identifiers, possibly not present in the
3024 # local repository.
3026 # local repository.
3025 n = bin(s)
3027 n = bin(s)
3026 if len(n) != len(nullid):
3028 if len(n) != len(nullid):
3027 raise TypeError()
3029 raise TypeError()
3028 return n
3030 return n
3029 except TypeError:
3031 except TypeError:
3030 raise error.Abort('changeset references must be full hexadecimal '
3032 raise error.Abort('changeset references must be full hexadecimal '
3031 'node identifiers')
3033 'node identifiers')
3032
3034
3033 if opts.get('delete'):
3035 if opts.get('delete'):
3034 indices = []
3036 indices = []
3035 for v in opts.get('delete'):
3037 for v in opts.get('delete'):
3036 try:
3038 try:
3037 indices.append(int(v))
3039 indices.append(int(v))
3038 except ValueError:
3040 except ValueError:
3039 raise error.Abort(_('invalid index value: %r') % v,
3041 raise error.Abort(_('invalid index value: %r') % v,
3040 hint=_('use integers for indices'))
3042 hint=_('use integers for indices'))
3041
3043
3042 if repo.currenttransaction():
3044 if repo.currenttransaction():
3043 raise error.Abort(_('cannot delete obsmarkers in the middle '
3045 raise error.Abort(_('cannot delete obsmarkers in the middle '
3044 'of transaction.'))
3046 'of transaction.'))
3045
3047
3046 with repo.lock():
3048 with repo.lock():
3047 n = repair.deleteobsmarkers(repo.obsstore, indices)
3049 n = repair.deleteobsmarkers(repo.obsstore, indices)
3048 ui.write(_('deleted %i obsolescense markers\n') % n)
3050 ui.write(_('deleted %i obsolescense markers\n') % n)
3049
3051
3050 return
3052 return
3051
3053
3052 if precursor is not None:
3054 if precursor is not None:
3053 if opts['rev']:
3055 if opts['rev']:
3054 raise error.Abort('cannot select revision when creating marker')
3056 raise error.Abort('cannot select revision when creating marker')
3055 metadata = {}
3057 metadata = {}
3056 metadata['user'] = opts['user'] or ui.username()
3058 metadata['user'] = opts['user'] or ui.username()
3057 succs = tuple(parsenodeid(succ) for succ in successors)
3059 succs = tuple(parsenodeid(succ) for succ in successors)
3058 l = repo.lock()
3060 l = repo.lock()
3059 try:
3061 try:
3060 tr = repo.transaction('debugobsolete')
3062 tr = repo.transaction('debugobsolete')
3061 try:
3063 try:
3062 date = opts.get('date')
3064 date = opts.get('date')
3063 if date:
3065 if date:
3064 date = util.parsedate(date)
3066 date = util.parsedate(date)
3065 else:
3067 else:
3066 date = None
3068 date = None
3067 prec = parsenodeid(precursor)
3069 prec = parsenodeid(precursor)
3068 parents = None
3070 parents = None
3069 if opts['record_parents']:
3071 if opts['record_parents']:
3070 if prec not in repo.unfiltered():
3072 if prec not in repo.unfiltered():
3071 raise error.Abort('cannot used --record-parents on '
3073 raise error.Abort('cannot used --record-parents on '
3072 'unknown changesets')
3074 'unknown changesets')
3073 parents = repo.unfiltered()[prec].parents()
3075 parents = repo.unfiltered()[prec].parents()
3074 parents = tuple(p.node() for p in parents)
3076 parents = tuple(p.node() for p in parents)
3075 repo.obsstore.create(tr, prec, succs, opts['flags'],
3077 repo.obsstore.create(tr, prec, succs, opts['flags'],
3076 parents=parents, date=date,
3078 parents=parents, date=date,
3077 metadata=metadata)
3079 metadata=metadata)
3078 tr.close()
3080 tr.close()
3079 except ValueError as exc:
3081 except ValueError as exc:
3080 raise error.Abort(_('bad obsmarker input: %s') % exc)
3082 raise error.Abort(_('bad obsmarker input: %s') % exc)
3081 finally:
3083 finally:
3082 tr.release()
3084 tr.release()
3083 finally:
3085 finally:
3084 l.release()
3086 l.release()
3085 else:
3087 else:
3086 if opts['rev']:
3088 if opts['rev']:
3087 revs = scmutil.revrange(repo, opts['rev'])
3089 revs = scmutil.revrange(repo, opts['rev'])
3088 nodes = [repo[r].node() for r in revs]
3090 nodes = [repo[r].node() for r in revs]
3089 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3091 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3090 markers.sort(key=lambda x: x._data)
3092 markers.sort(key=lambda x: x._data)
3091 else:
3093 else:
3092 markers = obsolete.getmarkers(repo)
3094 markers = obsolete.getmarkers(repo)
3093
3095
3094 markerstoiter = markers
3096 markerstoiter = markers
3095 isrelevant = lambda m: True
3097 isrelevant = lambda m: True
3096 if opts.get('rev') and opts.get('index'):
3098 if opts.get('rev') and opts.get('index'):
3097 markerstoiter = obsolete.getmarkers(repo)
3099 markerstoiter = obsolete.getmarkers(repo)
3098 markerset = set(markers)
3100 markerset = set(markers)
3099 isrelevant = lambda m: m in markerset
3101 isrelevant = lambda m: m in markerset
3100
3102
3101 fm = ui.formatter('debugobsolete', opts)
3103 fm = ui.formatter('debugobsolete', opts)
3102 for i, m in enumerate(markerstoiter):
3104 for i, m in enumerate(markerstoiter):
3103 if not isrelevant(m):
3105 if not isrelevant(m):
3104 # marker can be irrelevant when we're iterating over a set
3106 # marker can be irrelevant when we're iterating over a set
3105 # of markers (markerstoiter) which is bigger than the set
3107 # of markers (markerstoiter) which is bigger than the set
3106 # of markers we want to display (markers)
3108 # of markers we want to display (markers)
3107 # this can happen if both --index and --rev options are
3109 # this can happen if both --index and --rev options are
3108 # provided and thus we need to iterate over all of the markers
3110 # provided and thus we need to iterate over all of the markers
3109 # to get the correct indices, but only display the ones that
3111 # to get the correct indices, but only display the ones that
3110 # are relevant to --rev value
3112 # are relevant to --rev value
3111 continue
3113 continue
3112 fm.startitem()
3114 fm.startitem()
3113 ind = i if opts.get('index') else None
3115 ind = i if opts.get('index') else None
3114 cmdutil.showmarker(fm, m, index=ind)
3116 cmdutil.showmarker(fm, m, index=ind)
3115 fm.end()
3117 fm.end()
3116
3118
3117 @command('debugpathcomplete',
3119 @command('debugpathcomplete',
3118 [('f', 'full', None, _('complete an entire path')),
3120 [('f', 'full', None, _('complete an entire path')),
3119 ('n', 'normal', None, _('show only normal files')),
3121 ('n', 'normal', None, _('show only normal files')),
3120 ('a', 'added', None, _('show only added files')),
3122 ('a', 'added', None, _('show only added files')),
3121 ('r', 'removed', None, _('show only removed files'))],
3123 ('r', 'removed', None, _('show only removed files'))],
3122 _('FILESPEC...'))
3124 _('FILESPEC...'))
3123 def debugpathcomplete(ui, repo, *specs, **opts):
3125 def debugpathcomplete(ui, repo, *specs, **opts):
3124 '''complete part or all of a tracked path
3126 '''complete part or all of a tracked path
3125
3127
3126 This command supports shells that offer path name completion. It
3128 This command supports shells that offer path name completion. It
3127 currently completes only files already known to the dirstate.
3129 currently completes only files already known to the dirstate.
3128
3130
3129 Completion extends only to the next path segment unless
3131 Completion extends only to the next path segment unless
3130 --full is specified, in which case entire paths are used.'''
3132 --full is specified, in which case entire paths are used.'''
3131
3133
3132 def complete(path, acceptable):
3134 def complete(path, acceptable):
3133 dirstate = repo.dirstate
3135 dirstate = repo.dirstate
3134 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3136 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3135 rootdir = repo.root + os.sep
3137 rootdir = repo.root + os.sep
3136 if spec != repo.root and not spec.startswith(rootdir):
3138 if spec != repo.root and not spec.startswith(rootdir):
3137 return [], []
3139 return [], []
3138 if os.path.isdir(spec):
3140 if os.path.isdir(spec):
3139 spec += '/'
3141 spec += '/'
3140 spec = spec[len(rootdir):]
3142 spec = spec[len(rootdir):]
3141 fixpaths = os.sep != '/'
3143 fixpaths = os.sep != '/'
3142 if fixpaths:
3144 if fixpaths:
3143 spec = spec.replace(os.sep, '/')
3145 spec = spec.replace(os.sep, '/')
3144 speclen = len(spec)
3146 speclen = len(spec)
3145 fullpaths = opts['full']
3147 fullpaths = opts['full']
3146 files, dirs = set(), set()
3148 files, dirs = set(), set()
3147 adddir, addfile = dirs.add, files.add
3149 adddir, addfile = dirs.add, files.add
3148 for f, st in dirstate.iteritems():
3150 for f, st in dirstate.iteritems():
3149 if f.startswith(spec) and st[0] in acceptable:
3151 if f.startswith(spec) and st[0] in acceptable:
3150 if fixpaths:
3152 if fixpaths:
3151 f = f.replace('/', os.sep)
3153 f = f.replace('/', os.sep)
3152 if fullpaths:
3154 if fullpaths:
3153 addfile(f)
3155 addfile(f)
3154 continue
3156 continue
3155 s = f.find(os.sep, speclen)
3157 s = f.find(os.sep, speclen)
3156 if s >= 0:
3158 if s >= 0:
3157 adddir(f[:s])
3159 adddir(f[:s])
3158 else:
3160 else:
3159 addfile(f)
3161 addfile(f)
3160 return files, dirs
3162 return files, dirs
3161
3163
3162 acceptable = ''
3164 acceptable = ''
3163 if opts['normal']:
3165 if opts['normal']:
3164 acceptable += 'nm'
3166 acceptable += 'nm'
3165 if opts['added']:
3167 if opts['added']:
3166 acceptable += 'a'
3168 acceptable += 'a'
3167 if opts['removed']:
3169 if opts['removed']:
3168 acceptable += 'r'
3170 acceptable += 'r'
3169 cwd = repo.getcwd()
3171 cwd = repo.getcwd()
3170 if not specs:
3172 if not specs:
3171 specs = ['.']
3173 specs = ['.']
3172
3174
3173 files, dirs = set(), set()
3175 files, dirs = set(), set()
3174 for spec in specs:
3176 for spec in specs:
3175 f, d = complete(spec, acceptable or 'nmar')
3177 f, d = complete(spec, acceptable or 'nmar')
3176 files.update(f)
3178 files.update(f)
3177 dirs.update(d)
3179 dirs.update(d)
3178 files.update(dirs)
3180 files.update(dirs)
3179 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3181 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3180 ui.write('\n')
3182 ui.write('\n')
3181
3183
3182 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3184 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3183 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3185 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3184 '''access the pushkey key/value protocol
3186 '''access the pushkey key/value protocol
3185
3187
3186 With two args, list the keys in the given namespace.
3188 With two args, list the keys in the given namespace.
3187
3189
3188 With five args, set a key to new if it currently is set to old.
3190 With five args, set a key to new if it currently is set to old.
3189 Reports success or failure.
3191 Reports success or failure.
3190 '''
3192 '''
3191
3193
3192 target = hg.peer(ui, {}, repopath)
3194 target = hg.peer(ui, {}, repopath)
3193 if keyinfo:
3195 if keyinfo:
3194 key, old, new = keyinfo
3196 key, old, new = keyinfo
3195 r = target.pushkey(namespace, key, old, new)
3197 r = target.pushkey(namespace, key, old, new)
3196 ui.status(str(r) + '\n')
3198 ui.status(str(r) + '\n')
3197 return not r
3199 return not r
3198 else:
3200 else:
3199 for k, v in sorted(target.listkeys(namespace).iteritems()):
3201 for k, v in sorted(target.listkeys(namespace).iteritems()):
3200 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3202 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3201 v.encode('string-escape')))
3203 v.encode('string-escape')))
3202
3204
3203 @command('debugpvec', [], _('A B'))
3205 @command('debugpvec', [], _('A B'))
3204 def debugpvec(ui, repo, a, b=None):
3206 def debugpvec(ui, repo, a, b=None):
3205 ca = scmutil.revsingle(repo, a)
3207 ca = scmutil.revsingle(repo, a)
3206 cb = scmutil.revsingle(repo, b)
3208 cb = scmutil.revsingle(repo, b)
3207 pa = pvec.ctxpvec(ca)
3209 pa = pvec.ctxpvec(ca)
3208 pb = pvec.ctxpvec(cb)
3210 pb = pvec.ctxpvec(cb)
3209 if pa == pb:
3211 if pa == pb:
3210 rel = "="
3212 rel = "="
3211 elif pa > pb:
3213 elif pa > pb:
3212 rel = ">"
3214 rel = ">"
3213 elif pa < pb:
3215 elif pa < pb:
3214 rel = "<"
3216 rel = "<"
3215 elif pa | pb:
3217 elif pa | pb:
3216 rel = "|"
3218 rel = "|"
3217 ui.write(_("a: %s\n") % pa)
3219 ui.write(_("a: %s\n") % pa)
3218 ui.write(_("b: %s\n") % pb)
3220 ui.write(_("b: %s\n") % pb)
3219 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3221 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3220 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3222 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3221 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3223 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3222 pa.distance(pb), rel))
3224 pa.distance(pb), rel))
3223
3225
3224 @command('debugrebuilddirstate|debugrebuildstate',
3226 @command('debugrebuilddirstate|debugrebuildstate',
3225 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3227 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3226 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3228 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3227 'the working copy parent')),
3229 'the working copy parent')),
3228 ],
3230 ],
3229 _('[-r REV]'))
3231 _('[-r REV]'))
3230 def debugrebuilddirstate(ui, repo, rev, **opts):
3232 def debugrebuilddirstate(ui, repo, rev, **opts):
3231 """rebuild the dirstate as it would look like for the given revision
3233 """rebuild the dirstate as it would look like for the given revision
3232
3234
3233 If no revision is specified the first current parent will be used.
3235 If no revision is specified the first current parent will be used.
3234
3236
3235 The dirstate will be set to the files of the given revision.
3237 The dirstate will be set to the files of the given revision.
3236 The actual working directory content or existing dirstate
3238 The actual working directory content or existing dirstate
3237 information such as adds or removes is not considered.
3239 information such as adds or removes is not considered.
3238
3240
3239 ``minimal`` will only rebuild the dirstate status for files that claim to be
3241 ``minimal`` will only rebuild the dirstate status for files that claim to be
3240 tracked but are not in the parent manifest, or that exist in the parent
3242 tracked but are not in the parent manifest, or that exist in the parent
3241 manifest but are not in the dirstate. It will not change adds, removes, or
3243 manifest but are not in the dirstate. It will not change adds, removes, or
3242 modified files that are in the working copy parent.
3244 modified files that are in the working copy parent.
3243
3245
3244 One use of this command is to make the next :hg:`status` invocation
3246 One use of this command is to make the next :hg:`status` invocation
3245 check the actual file content.
3247 check the actual file content.
3246 """
3248 """
3247 ctx = scmutil.revsingle(repo, rev)
3249 ctx = scmutil.revsingle(repo, rev)
3248 with repo.wlock():
3250 with repo.wlock():
3249 dirstate = repo.dirstate
3251 dirstate = repo.dirstate
3250 changedfiles = None
3252 changedfiles = None
3251 # See command doc for what minimal does.
3253 # See command doc for what minimal does.
3252 if opts.get('minimal'):
3254 if opts.get('minimal'):
3253 manifestfiles = set(ctx.manifest().keys())
3255 manifestfiles = set(ctx.manifest().keys())
3254 dirstatefiles = set(dirstate)
3256 dirstatefiles = set(dirstate)
3255 manifestonly = manifestfiles - dirstatefiles
3257 manifestonly = manifestfiles - dirstatefiles
3256 dsonly = dirstatefiles - manifestfiles
3258 dsonly = dirstatefiles - manifestfiles
3257 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3259 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3258 changedfiles = manifestonly | dsnotadded
3260 changedfiles = manifestonly | dsnotadded
3259
3261
3260 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3262 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3261
3263
3262 @command('debugrebuildfncache', [], '')
3264 @command('debugrebuildfncache', [], '')
3263 def debugrebuildfncache(ui, repo):
3265 def debugrebuildfncache(ui, repo):
3264 """rebuild the fncache file"""
3266 """rebuild the fncache file"""
3265 repair.rebuildfncache(ui, repo)
3267 repair.rebuildfncache(ui, repo)
3266
3268
3267 @command('debugrename',
3269 @command('debugrename',
3268 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3270 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3269 _('[-r REV] FILE'))
3271 _('[-r REV] FILE'))
3270 def debugrename(ui, repo, file1, *pats, **opts):
3272 def debugrename(ui, repo, file1, *pats, **opts):
3271 """dump rename information"""
3273 """dump rename information"""
3272
3274
3273 ctx = scmutil.revsingle(repo, opts.get('rev'))
3275 ctx = scmutil.revsingle(repo, opts.get('rev'))
3274 m = scmutil.match(ctx, (file1,) + pats, opts)
3276 m = scmutil.match(ctx, (file1,) + pats, opts)
3275 for abs in ctx.walk(m):
3277 for abs in ctx.walk(m):
3276 fctx = ctx[abs]
3278 fctx = ctx[abs]
3277 o = fctx.filelog().renamed(fctx.filenode())
3279 o = fctx.filelog().renamed(fctx.filenode())
3278 rel = m.rel(abs)
3280 rel = m.rel(abs)
3279 if o:
3281 if o:
3280 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3282 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3281 else:
3283 else:
3282 ui.write(_("%s not renamed\n") % rel)
3284 ui.write(_("%s not renamed\n") % rel)
3283
3285
3284 @command('debugrevlog', debugrevlogopts +
3286 @command('debugrevlog', debugrevlogopts +
3285 [('d', 'dump', False, _('dump index data'))],
3287 [('d', 'dump', False, _('dump index data'))],
3286 _('-c|-m|FILE'),
3288 _('-c|-m|FILE'),
3287 optionalrepo=True)
3289 optionalrepo=True)
3288 def debugrevlog(ui, repo, file_=None, **opts):
3290 def debugrevlog(ui, repo, file_=None, **opts):
3289 """show data and statistics about a revlog"""
3291 """show data and statistics about a revlog"""
3290 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3292 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3291
3293
3292 if opts.get("dump"):
3294 if opts.get("dump"):
3293 numrevs = len(r)
3295 numrevs = len(r)
3294 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3296 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3295 " rawsize totalsize compression heads chainlen\n"))
3297 " rawsize totalsize compression heads chainlen\n"))
3296 ts = 0
3298 ts = 0
3297 heads = set()
3299 heads = set()
3298
3300
3299 for rev in xrange(numrevs):
3301 for rev in xrange(numrevs):
3300 dbase = r.deltaparent(rev)
3302 dbase = r.deltaparent(rev)
3301 if dbase == -1:
3303 if dbase == -1:
3302 dbase = rev
3304 dbase = rev
3303 cbase = r.chainbase(rev)
3305 cbase = r.chainbase(rev)
3304 clen = r.chainlen(rev)
3306 clen = r.chainlen(rev)
3305 p1, p2 = r.parentrevs(rev)
3307 p1, p2 = r.parentrevs(rev)
3306 rs = r.rawsize(rev)
3308 rs = r.rawsize(rev)
3307 ts = ts + rs
3309 ts = ts + rs
3308 heads -= set(r.parentrevs(rev))
3310 heads -= set(r.parentrevs(rev))
3309 heads.add(rev)
3311 heads.add(rev)
3310 try:
3312 try:
3311 compression = ts / r.end(rev)
3313 compression = ts / r.end(rev)
3312 except ZeroDivisionError:
3314 except ZeroDivisionError:
3313 compression = 0
3315 compression = 0
3314 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3316 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3315 "%11d %5d %8d\n" %
3317 "%11d %5d %8d\n" %
3316 (rev, p1, p2, r.start(rev), r.end(rev),
3318 (rev, p1, p2, r.start(rev), r.end(rev),
3317 r.start(dbase), r.start(cbase),
3319 r.start(dbase), r.start(cbase),
3318 r.start(p1), r.start(p2),
3320 r.start(p1), r.start(p2),
3319 rs, ts, compression, len(heads), clen))
3321 rs, ts, compression, len(heads), clen))
3320 return 0
3322 return 0
3321
3323
3322 v = r.version
3324 v = r.version
3323 format = v & 0xFFFF
3325 format = v & 0xFFFF
3324 flags = []
3326 flags = []
3325 gdelta = False
3327 gdelta = False
3326 if v & revlog.REVLOGNGINLINEDATA:
3328 if v & revlog.REVLOGNGINLINEDATA:
3327 flags.append('inline')
3329 flags.append('inline')
3328 if v & revlog.REVLOGGENERALDELTA:
3330 if v & revlog.REVLOGGENERALDELTA:
3329 gdelta = True
3331 gdelta = True
3330 flags.append('generaldelta')
3332 flags.append('generaldelta')
3331 if not flags:
3333 if not flags:
3332 flags = ['(none)']
3334 flags = ['(none)']
3333
3335
3334 nummerges = 0
3336 nummerges = 0
3335 numfull = 0
3337 numfull = 0
3336 numprev = 0
3338 numprev = 0
3337 nump1 = 0
3339 nump1 = 0
3338 nump2 = 0
3340 nump2 = 0
3339 numother = 0
3341 numother = 0
3340 nump1prev = 0
3342 nump1prev = 0
3341 nump2prev = 0
3343 nump2prev = 0
3342 chainlengths = []
3344 chainlengths = []
3343
3345
3344 datasize = [None, 0, 0]
3346 datasize = [None, 0, 0]
3345 fullsize = [None, 0, 0]
3347 fullsize = [None, 0, 0]
3346 deltasize = [None, 0, 0]
3348 deltasize = [None, 0, 0]
3347
3349
3348 def addsize(size, l):
3350 def addsize(size, l):
3349 if l[0] is None or size < l[0]:
3351 if l[0] is None or size < l[0]:
3350 l[0] = size
3352 l[0] = size
3351 if size > l[1]:
3353 if size > l[1]:
3352 l[1] = size
3354 l[1] = size
3353 l[2] += size
3355 l[2] += size
3354
3356
3355 numrevs = len(r)
3357 numrevs = len(r)
3356 for rev in xrange(numrevs):
3358 for rev in xrange(numrevs):
3357 p1, p2 = r.parentrevs(rev)
3359 p1, p2 = r.parentrevs(rev)
3358 delta = r.deltaparent(rev)
3360 delta = r.deltaparent(rev)
3359 if format > 0:
3361 if format > 0:
3360 addsize(r.rawsize(rev), datasize)
3362 addsize(r.rawsize(rev), datasize)
3361 if p2 != nullrev:
3363 if p2 != nullrev:
3362 nummerges += 1
3364 nummerges += 1
3363 size = r.length(rev)
3365 size = r.length(rev)
3364 if delta == nullrev:
3366 if delta == nullrev:
3365 chainlengths.append(0)
3367 chainlengths.append(0)
3366 numfull += 1
3368 numfull += 1
3367 addsize(size, fullsize)
3369 addsize(size, fullsize)
3368 else:
3370 else:
3369 chainlengths.append(chainlengths[delta] + 1)
3371 chainlengths.append(chainlengths[delta] + 1)
3370 addsize(size, deltasize)
3372 addsize(size, deltasize)
3371 if delta == rev - 1:
3373 if delta == rev - 1:
3372 numprev += 1
3374 numprev += 1
3373 if delta == p1:
3375 if delta == p1:
3374 nump1prev += 1
3376 nump1prev += 1
3375 elif delta == p2:
3377 elif delta == p2:
3376 nump2prev += 1
3378 nump2prev += 1
3377 elif delta == p1:
3379 elif delta == p1:
3378 nump1 += 1
3380 nump1 += 1
3379 elif delta == p2:
3381 elif delta == p2:
3380 nump2 += 1
3382 nump2 += 1
3381 elif delta != nullrev:
3383 elif delta != nullrev:
3382 numother += 1
3384 numother += 1
3383
3385
3384 # Adjust size min value for empty cases
3386 # Adjust size min value for empty cases
3385 for size in (datasize, fullsize, deltasize):
3387 for size in (datasize, fullsize, deltasize):
3386 if size[0] is None:
3388 if size[0] is None:
3387 size[0] = 0
3389 size[0] = 0
3388
3390
3389 numdeltas = numrevs - numfull
3391 numdeltas = numrevs - numfull
3390 numoprev = numprev - nump1prev - nump2prev
3392 numoprev = numprev - nump1prev - nump2prev
3391 totalrawsize = datasize[2]
3393 totalrawsize = datasize[2]
3392 datasize[2] /= numrevs
3394 datasize[2] /= numrevs
3393 fulltotal = fullsize[2]
3395 fulltotal = fullsize[2]
3394 fullsize[2] /= numfull
3396 fullsize[2] /= numfull
3395 deltatotal = deltasize[2]
3397 deltatotal = deltasize[2]
3396 if numrevs - numfull > 0:
3398 if numrevs - numfull > 0:
3397 deltasize[2] /= numrevs - numfull
3399 deltasize[2] /= numrevs - numfull
3398 totalsize = fulltotal + deltatotal
3400 totalsize = fulltotal + deltatotal
3399 avgchainlen = sum(chainlengths) / numrevs
3401 avgchainlen = sum(chainlengths) / numrevs
3400 maxchainlen = max(chainlengths)
3402 maxchainlen = max(chainlengths)
3401 compratio = 1
3403 compratio = 1
3402 if totalsize:
3404 if totalsize:
3403 compratio = totalrawsize / totalsize
3405 compratio = totalrawsize / totalsize
3404
3406
3405 basedfmtstr = '%%%dd\n'
3407 basedfmtstr = '%%%dd\n'
3406 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3408 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3407
3409
3408 def dfmtstr(max):
3410 def dfmtstr(max):
3409 return basedfmtstr % len(str(max))
3411 return basedfmtstr % len(str(max))
3410 def pcfmtstr(max, padding=0):
3412 def pcfmtstr(max, padding=0):
3411 return basepcfmtstr % (len(str(max)), ' ' * padding)
3413 return basepcfmtstr % (len(str(max)), ' ' * padding)
3412
3414
3413 def pcfmt(value, total):
3415 def pcfmt(value, total):
3414 if total:
3416 if total:
3415 return (value, 100 * float(value) / total)
3417 return (value, 100 * float(value) / total)
3416 else:
3418 else:
3417 return value, 100.0
3419 return value, 100.0
3418
3420
3419 ui.write(('format : %d\n') % format)
3421 ui.write(('format : %d\n') % format)
3420 ui.write(('flags : %s\n') % ', '.join(flags))
3422 ui.write(('flags : %s\n') % ', '.join(flags))
3421
3423
3422 ui.write('\n')
3424 ui.write('\n')
3423 fmt = pcfmtstr(totalsize)
3425 fmt = pcfmtstr(totalsize)
3424 fmt2 = dfmtstr(totalsize)
3426 fmt2 = dfmtstr(totalsize)
3425 ui.write(('revisions : ') + fmt2 % numrevs)
3427 ui.write(('revisions : ') + fmt2 % numrevs)
3426 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3428 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3427 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3429 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3428 ui.write(('revisions : ') + fmt2 % numrevs)
3430 ui.write(('revisions : ') + fmt2 % numrevs)
3429 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3431 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3430 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3432 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3431 ui.write(('revision size : ') + fmt2 % totalsize)
3433 ui.write(('revision size : ') + fmt2 % totalsize)
3432 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3434 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3433 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3435 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3434
3436
3435 ui.write('\n')
3437 ui.write('\n')
3436 fmt = dfmtstr(max(avgchainlen, compratio))
3438 fmt = dfmtstr(max(avgchainlen, compratio))
3437 ui.write(('avg chain length : ') + fmt % avgchainlen)
3439 ui.write(('avg chain length : ') + fmt % avgchainlen)
3438 ui.write(('max chain length : ') + fmt % maxchainlen)
3440 ui.write(('max chain length : ') + fmt % maxchainlen)
3439 ui.write(('compression ratio : ') + fmt % compratio)
3441 ui.write(('compression ratio : ') + fmt % compratio)
3440
3442
3441 if format > 0:
3443 if format > 0:
3442 ui.write('\n')
3444 ui.write('\n')
3443 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3445 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3444 % tuple(datasize))
3446 % tuple(datasize))
3445 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3447 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3446 % tuple(fullsize))
3448 % tuple(fullsize))
3447 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3449 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3448 % tuple(deltasize))
3450 % tuple(deltasize))
3449
3451
3450 if numdeltas > 0:
3452 if numdeltas > 0:
3451 ui.write('\n')
3453 ui.write('\n')
3452 fmt = pcfmtstr(numdeltas)
3454 fmt = pcfmtstr(numdeltas)
3453 fmt2 = pcfmtstr(numdeltas, 4)
3455 fmt2 = pcfmtstr(numdeltas, 4)
3454 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3456 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3455 if numprev > 0:
3457 if numprev > 0:
3456 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3458 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3457 numprev))
3459 numprev))
3458 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3460 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3459 numprev))
3461 numprev))
3460 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3462 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3461 numprev))
3463 numprev))
3462 if gdelta:
3464 if gdelta:
3463 ui.write(('deltas against p1 : ')
3465 ui.write(('deltas against p1 : ')
3464 + fmt % pcfmt(nump1, numdeltas))
3466 + fmt % pcfmt(nump1, numdeltas))
3465 ui.write(('deltas against p2 : ')
3467 ui.write(('deltas against p2 : ')
3466 + fmt % pcfmt(nump2, numdeltas))
3468 + fmt % pcfmt(nump2, numdeltas))
3467 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3469 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3468 numdeltas))
3470 numdeltas))
3469
3471
3470 @command('debugrevspec',
3472 @command('debugrevspec',
3471 [('', 'optimize', None,
3473 [('', 'optimize', None,
3472 _('print parsed tree after optimizing (DEPRECATED)')),
3474 _('print parsed tree after optimizing (DEPRECATED)')),
3473 ('p', 'show-stage', [],
3475 ('p', 'show-stage', [],
3474 _('print parsed tree at the given stage'), _('NAME')),
3476 _('print parsed tree at the given stage'), _('NAME')),
3475 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3477 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3476 ('', 'verify-optimized', False, _('verify optimized result')),
3478 ('', 'verify-optimized', False, _('verify optimized result')),
3477 ],
3479 ],
3478 ('REVSPEC'))
3480 ('REVSPEC'))
3479 def debugrevspec(ui, repo, expr, **opts):
3481 def debugrevspec(ui, repo, expr, **opts):
3480 """parse and apply a revision specification
3482 """parse and apply a revision specification
3481
3483
3482 Use -p/--show-stage option to print the parsed tree at the given stages.
3484 Use -p/--show-stage option to print the parsed tree at the given stages.
3483 Use -p all to print tree at every stage.
3485 Use -p all to print tree at every stage.
3484
3486
3485 Use --verify-optimized to compare the optimized result with the unoptimized
3487 Use --verify-optimized to compare the optimized result with the unoptimized
3486 one. Returns 1 if the optimized result differs.
3488 one. Returns 1 if the optimized result differs.
3487 """
3489 """
3488 stages = [
3490 stages = [
3489 ('parsed', lambda tree: tree),
3491 ('parsed', lambda tree: tree),
3490 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3492 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3491 ('concatenated', revset.foldconcat),
3493 ('concatenated', revset.foldconcat),
3492 ('analyzed', revset.analyze),
3494 ('analyzed', revset.analyze),
3493 ('optimized', revset.optimize),
3495 ('optimized', revset.optimize),
3494 ]
3496 ]
3495 if opts['no_optimized']:
3497 if opts['no_optimized']:
3496 stages = stages[:-1]
3498 stages = stages[:-1]
3497 if opts['verify_optimized'] and opts['no_optimized']:
3499 if opts['verify_optimized'] and opts['no_optimized']:
3498 raise error.Abort(_('cannot use --verify-optimized with '
3500 raise error.Abort(_('cannot use --verify-optimized with '
3499 '--no-optimized'))
3501 '--no-optimized'))
3500 stagenames = set(n for n, f in stages)
3502 stagenames = set(n for n, f in stages)
3501
3503
3502 showalways = set()
3504 showalways = set()
3503 showchanged = set()
3505 showchanged = set()
3504 if ui.verbose and not opts['show_stage']:
3506 if ui.verbose and not opts['show_stage']:
3505 # show parsed tree by --verbose (deprecated)
3507 # show parsed tree by --verbose (deprecated)
3506 showalways.add('parsed')
3508 showalways.add('parsed')
3507 showchanged.update(['expanded', 'concatenated'])
3509 showchanged.update(['expanded', 'concatenated'])
3508 if opts['optimize']:
3510 if opts['optimize']:
3509 showalways.add('optimized')
3511 showalways.add('optimized')
3510 if opts['show_stage'] and opts['optimize']:
3512 if opts['show_stage'] and opts['optimize']:
3511 raise error.Abort(_('cannot use --optimize with --show-stage'))
3513 raise error.Abort(_('cannot use --optimize with --show-stage'))
3512 if opts['show_stage'] == ['all']:
3514 if opts['show_stage'] == ['all']:
3513 showalways.update(stagenames)
3515 showalways.update(stagenames)
3514 else:
3516 else:
3515 for n in opts['show_stage']:
3517 for n in opts['show_stage']:
3516 if n not in stagenames:
3518 if n not in stagenames:
3517 raise error.Abort(_('invalid stage name: %s') % n)
3519 raise error.Abort(_('invalid stage name: %s') % n)
3518 showalways.update(opts['show_stage'])
3520 showalways.update(opts['show_stage'])
3519
3521
3520 treebystage = {}
3522 treebystage = {}
3521 printedtree = None
3523 printedtree = None
3522 tree = revset.parse(expr, lookup=repo.__contains__)
3524 tree = revset.parse(expr, lookup=repo.__contains__)
3523 for n, f in stages:
3525 for n, f in stages:
3524 treebystage[n] = tree = f(tree)
3526 treebystage[n] = tree = f(tree)
3525 if n in showalways or (n in showchanged and tree != printedtree):
3527 if n in showalways or (n in showchanged and tree != printedtree):
3526 if opts['show_stage'] or n != 'parsed':
3528 if opts['show_stage'] or n != 'parsed':
3527 ui.write(("* %s:\n") % n)
3529 ui.write(("* %s:\n") % n)
3528 ui.write(revset.prettyformat(tree), "\n")
3530 ui.write(revset.prettyformat(tree), "\n")
3529 printedtree = tree
3531 printedtree = tree
3530
3532
3531 if opts['verify_optimized']:
3533 if opts['verify_optimized']:
3532 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3534 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3533 brevs = revset.makematcher(treebystage['optimized'])(repo)
3535 brevs = revset.makematcher(treebystage['optimized'])(repo)
3534 if ui.verbose:
3536 if ui.verbose:
3535 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3537 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3536 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3538 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3537 arevs = list(arevs)
3539 arevs = list(arevs)
3538 brevs = list(brevs)
3540 brevs = list(brevs)
3539 if arevs == brevs:
3541 if arevs == brevs:
3540 return 0
3542 return 0
3541 ui.write(('--- analyzed\n'), label='diff.file_a')
3543 ui.write(('--- analyzed\n'), label='diff.file_a')
3542 ui.write(('+++ optimized\n'), label='diff.file_b')
3544 ui.write(('+++ optimized\n'), label='diff.file_b')
3543 sm = difflib.SequenceMatcher(None, arevs, brevs)
3545 sm = difflib.SequenceMatcher(None, arevs, brevs)
3544 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3546 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3545 if tag in ('delete', 'replace'):
3547 if tag in ('delete', 'replace'):
3546 for c in arevs[alo:ahi]:
3548 for c in arevs[alo:ahi]:
3547 ui.write('-%s\n' % c, label='diff.deleted')
3549 ui.write('-%s\n' % c, label='diff.deleted')
3548 if tag in ('insert', 'replace'):
3550 if tag in ('insert', 'replace'):
3549 for c in brevs[blo:bhi]:
3551 for c in brevs[blo:bhi]:
3550 ui.write('+%s\n' % c, label='diff.inserted')
3552 ui.write('+%s\n' % c, label='diff.inserted')
3551 if tag == 'equal':
3553 if tag == 'equal':
3552 for c in arevs[alo:ahi]:
3554 for c in arevs[alo:ahi]:
3553 ui.write(' %s\n' % c)
3555 ui.write(' %s\n' % c)
3554 return 1
3556 return 1
3555
3557
3556 func = revset.makematcher(tree)
3558 func = revset.makematcher(tree)
3557 revs = func(repo)
3559 revs = func(repo)
3558 if ui.verbose:
3560 if ui.verbose:
3559 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3561 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3560 for c in revs:
3562 for c in revs:
3561 ui.write("%s\n" % c)
3563 ui.write("%s\n" % c)
3562
3564
3563 @command('debugsetparents', [], _('REV1 [REV2]'))
3565 @command('debugsetparents', [], _('REV1 [REV2]'))
3564 def debugsetparents(ui, repo, rev1, rev2=None):
3566 def debugsetparents(ui, repo, rev1, rev2=None):
3565 """manually set the parents of the current working directory
3567 """manually set the parents of the current working directory
3566
3568
3567 This is useful for writing repository conversion tools, but should
3569 This is useful for writing repository conversion tools, but should
3568 be used with care. For example, neither the working directory nor the
3570 be used with care. For example, neither the working directory nor the
3569 dirstate is updated, so file status may be incorrect after running this
3571 dirstate is updated, so file status may be incorrect after running this
3570 command.
3572 command.
3571
3573
3572 Returns 0 on success.
3574 Returns 0 on success.
3573 """
3575 """
3574
3576
3575 r1 = scmutil.revsingle(repo, rev1).node()
3577 r1 = scmutil.revsingle(repo, rev1).node()
3576 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3578 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3577
3579
3578 with repo.wlock():
3580 with repo.wlock():
3579 repo.setparents(r1, r2)
3581 repo.setparents(r1, r2)
3580
3582
3581 @command('debugdirstate|debugstate',
3583 @command('debugdirstate|debugstate',
3582 [('', 'nodates', None, _('do not display the saved mtime')),
3584 [('', 'nodates', None, _('do not display the saved mtime')),
3583 ('', 'datesort', None, _('sort by saved mtime'))],
3585 ('', 'datesort', None, _('sort by saved mtime'))],
3584 _('[OPTION]...'))
3586 _('[OPTION]...'))
3585 def debugstate(ui, repo, **opts):
3587 def debugstate(ui, repo, **opts):
3586 """show the contents of the current dirstate"""
3588 """show the contents of the current dirstate"""
3587
3589
3588 nodates = opts.get('nodates')
3590 nodates = opts.get('nodates')
3589 datesort = opts.get('datesort')
3591 datesort = opts.get('datesort')
3590
3592
3591 timestr = ""
3593 timestr = ""
3592 if datesort:
3594 if datesort:
3593 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3595 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3594 else:
3596 else:
3595 keyfunc = None # sort by filename
3597 keyfunc = None # sort by filename
3596 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3598 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3597 if ent[3] == -1:
3599 if ent[3] == -1:
3598 timestr = 'unset '
3600 timestr = 'unset '
3599 elif nodates:
3601 elif nodates:
3600 timestr = 'set '
3602 timestr = 'set '
3601 else:
3603 else:
3602 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3604 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3603 time.localtime(ent[3]))
3605 time.localtime(ent[3]))
3604 if ent[1] & 0o20000:
3606 if ent[1] & 0o20000:
3605 mode = 'lnk'
3607 mode = 'lnk'
3606 else:
3608 else:
3607 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3609 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3608 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3610 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3609 for f in repo.dirstate.copies():
3611 for f in repo.dirstate.copies():
3610 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3612 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3611
3613
3612 @command('debugsub',
3614 @command('debugsub',
3613 [('r', 'rev', '',
3615 [('r', 'rev', '',
3614 _('revision to check'), _('REV'))],
3616 _('revision to check'), _('REV'))],
3615 _('[-r REV] [REV]'))
3617 _('[-r REV] [REV]'))
3616 def debugsub(ui, repo, rev=None):
3618 def debugsub(ui, repo, rev=None):
3617 ctx = scmutil.revsingle(repo, rev, None)
3619 ctx = scmutil.revsingle(repo, rev, None)
3618 for k, v in sorted(ctx.substate.items()):
3620 for k, v in sorted(ctx.substate.items()):
3619 ui.write(('path %s\n') % k)
3621 ui.write(('path %s\n') % k)
3620 ui.write((' source %s\n') % v[0])
3622 ui.write((' source %s\n') % v[0])
3621 ui.write((' revision %s\n') % v[1])
3623 ui.write((' revision %s\n') % v[1])
3622
3624
3623 @command('debugsuccessorssets',
3625 @command('debugsuccessorssets',
3624 [],
3626 [],
3625 _('[REV]'))
3627 _('[REV]'))
3626 def debugsuccessorssets(ui, repo, *revs):
3628 def debugsuccessorssets(ui, repo, *revs):
3627 """show set of successors for revision
3629 """show set of successors for revision
3628
3630
3629 A successors set of changeset A is a consistent group of revisions that
3631 A successors set of changeset A is a consistent group of revisions that
3630 succeed A. It contains non-obsolete changesets only.
3632 succeed A. It contains non-obsolete changesets only.
3631
3633
3632 In most cases a changeset A has a single successors set containing a single
3634 In most cases a changeset A has a single successors set containing a single
3633 successor (changeset A replaced by A').
3635 successor (changeset A replaced by A').
3634
3636
3635 A changeset that is made obsolete with no successors are called "pruned".
3637 A changeset that is made obsolete with no successors are called "pruned".
3636 Such changesets have no successors sets at all.
3638 Such changesets have no successors sets at all.
3637
3639
3638 A changeset that has been "split" will have a successors set containing
3640 A changeset that has been "split" will have a successors set containing
3639 more than one successor.
3641 more than one successor.
3640
3642
3641 A changeset that has been rewritten in multiple different ways is called
3643 A changeset that has been rewritten in multiple different ways is called
3642 "divergent". Such changesets have multiple successor sets (each of which
3644 "divergent". Such changesets have multiple successor sets (each of which
3643 may also be split, i.e. have multiple successors).
3645 may also be split, i.e. have multiple successors).
3644
3646
3645 Results are displayed as follows::
3647 Results are displayed as follows::
3646
3648
3647 <rev1>
3649 <rev1>
3648 <successors-1A>
3650 <successors-1A>
3649 <rev2>
3651 <rev2>
3650 <successors-2A>
3652 <successors-2A>
3651 <successors-2B1> <successors-2B2> <successors-2B3>
3653 <successors-2B1> <successors-2B2> <successors-2B3>
3652
3654
3653 Here rev2 has two possible (i.e. divergent) successors sets. The first
3655 Here rev2 has two possible (i.e. divergent) successors sets. The first
3654 holds one element, whereas the second holds three (i.e. the changeset has
3656 holds one element, whereas the second holds three (i.e. the changeset has
3655 been split).
3657 been split).
3656 """
3658 """
3657 # passed to successorssets caching computation from one call to another
3659 # passed to successorssets caching computation from one call to another
3658 cache = {}
3660 cache = {}
3659 ctx2str = str
3661 ctx2str = str
3660 node2str = short
3662 node2str = short
3661 if ui.debug():
3663 if ui.debug():
3662 def ctx2str(ctx):
3664 def ctx2str(ctx):
3663 return ctx.hex()
3665 return ctx.hex()
3664 node2str = hex
3666 node2str = hex
3665 for rev in scmutil.revrange(repo, revs):
3667 for rev in scmutil.revrange(repo, revs):
3666 ctx = repo[rev]
3668 ctx = repo[rev]
3667 ui.write('%s\n'% ctx2str(ctx))
3669 ui.write('%s\n'% ctx2str(ctx))
3668 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3670 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3669 if succsset:
3671 if succsset:
3670 ui.write(' ')
3672 ui.write(' ')
3671 ui.write(node2str(succsset[0]))
3673 ui.write(node2str(succsset[0]))
3672 for node in succsset[1:]:
3674 for node in succsset[1:]:
3673 ui.write(' ')
3675 ui.write(' ')
3674 ui.write(node2str(node))
3676 ui.write(node2str(node))
3675 ui.write('\n')
3677 ui.write('\n')
3676
3678
3677 @command('debugtemplate',
3679 @command('debugtemplate',
3678 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3680 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3679 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3681 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3680 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3682 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3681 optionalrepo=True)
3683 optionalrepo=True)
3682 def debugtemplate(ui, repo, tmpl, **opts):
3684 def debugtemplate(ui, repo, tmpl, **opts):
3683 """parse and apply a template
3685 """parse and apply a template
3684
3686
3685 If -r/--rev is given, the template is processed as a log template and
3687 If -r/--rev is given, the template is processed as a log template and
3686 applied to the given changesets. Otherwise, it is processed as a generic
3688 applied to the given changesets. Otherwise, it is processed as a generic
3687 template.
3689 template.
3688
3690
3689 Use --verbose to print the parsed tree.
3691 Use --verbose to print the parsed tree.
3690 """
3692 """
3691 revs = None
3693 revs = None
3692 if opts['rev']:
3694 if opts['rev']:
3693 if repo is None:
3695 if repo is None:
3694 raise error.RepoError(_('there is no Mercurial repository here '
3696 raise error.RepoError(_('there is no Mercurial repository here '
3695 '(.hg not found)'))
3697 '(.hg not found)'))
3696 revs = scmutil.revrange(repo, opts['rev'])
3698 revs = scmutil.revrange(repo, opts['rev'])
3697
3699
3698 props = {}
3700 props = {}
3699 for d in opts['define']:
3701 for d in opts['define']:
3700 try:
3702 try:
3701 k, v = (e.strip() for e in d.split('=', 1))
3703 k, v = (e.strip() for e in d.split('=', 1))
3702 if not k:
3704 if not k:
3703 raise ValueError
3705 raise ValueError
3704 props[k] = v
3706 props[k] = v
3705 except ValueError:
3707 except ValueError:
3706 raise error.Abort(_('malformed keyword definition: %s') % d)
3708 raise error.Abort(_('malformed keyword definition: %s') % d)
3707
3709
3708 if ui.verbose:
3710 if ui.verbose:
3709 aliases = ui.configitems('templatealias')
3711 aliases = ui.configitems('templatealias')
3710 tree = templater.parse(tmpl)
3712 tree = templater.parse(tmpl)
3711 ui.note(templater.prettyformat(tree), '\n')
3713 ui.note(templater.prettyformat(tree), '\n')
3712 newtree = templater.expandaliases(tree, aliases)
3714 newtree = templater.expandaliases(tree, aliases)
3713 if newtree != tree:
3715 if newtree != tree:
3714 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3716 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3715
3717
3716 mapfile = None
3718 mapfile = None
3717 if revs is None:
3719 if revs is None:
3718 k = 'debugtemplate'
3720 k = 'debugtemplate'
3719 t = formatter.maketemplater(ui, k, tmpl)
3721 t = formatter.maketemplater(ui, k, tmpl)
3720 ui.write(templater.stringify(t(k, **props)))
3722 ui.write(templater.stringify(t(k, **props)))
3721 else:
3723 else:
3722 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3724 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3723 mapfile, buffered=False)
3725 mapfile, buffered=False)
3724 for r in revs:
3726 for r in revs:
3725 displayer.show(repo[r], **props)
3727 displayer.show(repo[r], **props)
3726 displayer.close()
3728 displayer.close()
3727
3729
3728 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3730 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3729 def debugwalk(ui, repo, *pats, **opts):
3731 def debugwalk(ui, repo, *pats, **opts):
3730 """show how files match on given patterns"""
3732 """show how files match on given patterns"""
3731 m = scmutil.match(repo[None], pats, opts)
3733 m = scmutil.match(repo[None], pats, opts)
3732 items = list(repo.walk(m))
3734 items = list(repo.walk(m))
3733 if not items:
3735 if not items:
3734 return
3736 return
3735 f = lambda fn: fn
3737 f = lambda fn: fn
3736 if ui.configbool('ui', 'slash') and os.sep != '/':
3738 if ui.configbool('ui', 'slash') and os.sep != '/':
3737 f = lambda fn: util.normpath(fn)
3739 f = lambda fn: util.normpath(fn)
3738 fmt = 'f %%-%ds %%-%ds %%s' % (
3740 fmt = 'f %%-%ds %%-%ds %%s' % (
3739 max([len(abs) for abs in items]),
3741 max([len(abs) for abs in items]),
3740 max([len(m.rel(abs)) for abs in items]))
3742 max([len(m.rel(abs)) for abs in items]))
3741 for abs in items:
3743 for abs in items:
3742 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3744 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3743 ui.write("%s\n" % line.rstrip())
3745 ui.write("%s\n" % line.rstrip())
3744
3746
3745 @command('debugwireargs',
3747 @command('debugwireargs',
3746 [('', 'three', '', 'three'),
3748 [('', 'three', '', 'three'),
3747 ('', 'four', '', 'four'),
3749 ('', 'four', '', 'four'),
3748 ('', 'five', '', 'five'),
3750 ('', 'five', '', 'five'),
3749 ] + remoteopts,
3751 ] + remoteopts,
3750 _('REPO [OPTIONS]... [ONE [TWO]]'),
3752 _('REPO [OPTIONS]... [ONE [TWO]]'),
3751 norepo=True)
3753 norepo=True)
3752 def debugwireargs(ui, repopath, *vals, **opts):
3754 def debugwireargs(ui, repopath, *vals, **opts):
3753 repo = hg.peer(ui, opts, repopath)
3755 repo = hg.peer(ui, opts, repopath)
3754 for opt in remoteopts:
3756 for opt in remoteopts:
3755 del opts[opt[1]]
3757 del opts[opt[1]]
3756 args = {}
3758 args = {}
3757 for k, v in opts.iteritems():
3759 for k, v in opts.iteritems():
3758 if v:
3760 if v:
3759 args[k] = v
3761 args[k] = v
3760 # run twice to check that we don't mess up the stream for the next command
3762 # run twice to check that we don't mess up the stream for the next command
3761 res1 = repo.debugwireargs(*vals, **args)
3763 res1 = repo.debugwireargs(*vals, **args)
3762 res2 = repo.debugwireargs(*vals, **args)
3764 res2 = repo.debugwireargs(*vals, **args)
3763 ui.write("%s\n" % res1)
3765 ui.write("%s\n" % res1)
3764 if res1 != res2:
3766 if res1 != res2:
3765 ui.warn("%s\n" % res2)
3767 ui.warn("%s\n" % res2)
3766
3768
3767 @command('^diff',
3769 @command('^diff',
3768 [('r', 'rev', [], _('revision'), _('REV')),
3770 [('r', 'rev', [], _('revision'), _('REV')),
3769 ('c', 'change', '', _('change made by revision'), _('REV'))
3771 ('c', 'change', '', _('change made by revision'), _('REV'))
3770 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3772 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3771 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3773 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3772 inferrepo=True)
3774 inferrepo=True)
3773 def diff(ui, repo, *pats, **opts):
3775 def diff(ui, repo, *pats, **opts):
3774 """diff repository (or selected files)
3776 """diff repository (or selected files)
3775
3777
3776 Show differences between revisions for the specified files.
3778 Show differences between revisions for the specified files.
3777
3779
3778 Differences between files are shown using the unified diff format.
3780 Differences between files are shown using the unified diff format.
3779
3781
3780 .. note::
3782 .. note::
3781
3783
3782 :hg:`diff` may generate unexpected results for merges, as it will
3784 :hg:`diff` may generate unexpected results for merges, as it will
3783 default to comparing against the working directory's first
3785 default to comparing against the working directory's first
3784 parent changeset if no revisions are specified.
3786 parent changeset if no revisions are specified.
3785
3787
3786 When two revision arguments are given, then changes are shown
3788 When two revision arguments are given, then changes are shown
3787 between those revisions. If only one revision is specified then
3789 between those revisions. If only one revision is specified then
3788 that revision is compared to the working directory, and, when no
3790 that revision is compared to the working directory, and, when no
3789 revisions are specified, the working directory files are compared
3791 revisions are specified, the working directory files are compared
3790 to its first parent.
3792 to its first parent.
3791
3793
3792 Alternatively you can specify -c/--change with a revision to see
3794 Alternatively you can specify -c/--change with a revision to see
3793 the changes in that changeset relative to its first parent.
3795 the changes in that changeset relative to its first parent.
3794
3796
3795 Without the -a/--text option, diff will avoid generating diffs of
3797 Without the -a/--text option, diff will avoid generating diffs of
3796 files it detects as binary. With -a, diff will generate a diff
3798 files it detects as binary. With -a, diff will generate a diff
3797 anyway, probably with undesirable results.
3799 anyway, probably with undesirable results.
3798
3800
3799 Use the -g/--git option to generate diffs in the git extended diff
3801 Use the -g/--git option to generate diffs in the git extended diff
3800 format. For more information, read :hg:`help diffs`.
3802 format. For more information, read :hg:`help diffs`.
3801
3803
3802 .. container:: verbose
3804 .. container:: verbose
3803
3805
3804 Examples:
3806 Examples:
3805
3807
3806 - compare a file in the current working directory to its parent::
3808 - compare a file in the current working directory to its parent::
3807
3809
3808 hg diff foo.c
3810 hg diff foo.c
3809
3811
3810 - compare two historical versions of a directory, with rename info::
3812 - compare two historical versions of a directory, with rename info::
3811
3813
3812 hg diff --git -r 1.0:1.2 lib/
3814 hg diff --git -r 1.0:1.2 lib/
3813
3815
3814 - get change stats relative to the last change on some date::
3816 - get change stats relative to the last change on some date::
3815
3817
3816 hg diff --stat -r "date('may 2')"
3818 hg diff --stat -r "date('may 2')"
3817
3819
3818 - diff all newly-added files that contain a keyword::
3820 - diff all newly-added files that contain a keyword::
3819
3821
3820 hg diff "set:added() and grep(GNU)"
3822 hg diff "set:added() and grep(GNU)"
3821
3823
3822 - compare a revision and its parents::
3824 - compare a revision and its parents::
3823
3825
3824 hg diff -c 9353 # compare against first parent
3826 hg diff -c 9353 # compare against first parent
3825 hg diff -r 9353^:9353 # same using revset syntax
3827 hg diff -r 9353^:9353 # same using revset syntax
3826 hg diff -r 9353^2:9353 # compare against the second parent
3828 hg diff -r 9353^2:9353 # compare against the second parent
3827
3829
3828 Returns 0 on success.
3830 Returns 0 on success.
3829 """
3831 """
3830
3832
3831 revs = opts.get('rev')
3833 revs = opts.get('rev')
3832 change = opts.get('change')
3834 change = opts.get('change')
3833 stat = opts.get('stat')
3835 stat = opts.get('stat')
3834 reverse = opts.get('reverse')
3836 reverse = opts.get('reverse')
3835
3837
3836 if revs and change:
3838 if revs and change:
3837 msg = _('cannot specify --rev and --change at the same time')
3839 msg = _('cannot specify --rev and --change at the same time')
3838 raise error.Abort(msg)
3840 raise error.Abort(msg)
3839 elif change:
3841 elif change:
3840 node2 = scmutil.revsingle(repo, change, None).node()
3842 node2 = scmutil.revsingle(repo, change, None).node()
3841 node1 = repo[node2].p1().node()
3843 node1 = repo[node2].p1().node()
3842 else:
3844 else:
3843 node1, node2 = scmutil.revpair(repo, revs)
3845 node1, node2 = scmutil.revpair(repo, revs)
3844
3846
3845 if reverse:
3847 if reverse:
3846 node1, node2 = node2, node1
3848 node1, node2 = node2, node1
3847
3849
3848 diffopts = patch.diffallopts(ui, opts)
3850 diffopts = patch.diffallopts(ui, opts)
3849 m = scmutil.match(repo[node2], pats, opts)
3851 m = scmutil.match(repo[node2], pats, opts)
3850 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3852 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3851 listsubrepos=opts.get('subrepos'),
3853 listsubrepos=opts.get('subrepos'),
3852 root=opts.get('root'))
3854 root=opts.get('root'))
3853
3855
3854 @command('^export',
3856 @command('^export',
3855 [('o', 'output', '',
3857 [('o', 'output', '',
3856 _('print output to file with formatted name'), _('FORMAT')),
3858 _('print output to file with formatted name'), _('FORMAT')),
3857 ('', 'switch-parent', None, _('diff against the second parent')),
3859 ('', 'switch-parent', None, _('diff against the second parent')),
3858 ('r', 'rev', [], _('revisions to export'), _('REV')),
3860 ('r', 'rev', [], _('revisions to export'), _('REV')),
3859 ] + diffopts,
3861 ] + diffopts,
3860 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3862 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3861 def export(ui, repo, *changesets, **opts):
3863 def export(ui, repo, *changesets, **opts):
3862 """dump the header and diffs for one or more changesets
3864 """dump the header and diffs for one or more changesets
3863
3865
3864 Print the changeset header and diffs for one or more revisions.
3866 Print the changeset header and diffs for one or more revisions.
3865 If no revision is given, the parent of the working directory is used.
3867 If no revision is given, the parent of the working directory is used.
3866
3868
3867 The information shown in the changeset header is: author, date,
3869 The information shown in the changeset header is: author, date,
3868 branch name (if non-default), changeset hash, parent(s) and commit
3870 branch name (if non-default), changeset hash, parent(s) and commit
3869 comment.
3871 comment.
3870
3872
3871 .. note::
3873 .. note::
3872
3874
3873 :hg:`export` may generate unexpected diff output for merge
3875 :hg:`export` may generate unexpected diff output for merge
3874 changesets, as it will compare the merge changeset against its
3876 changesets, as it will compare the merge changeset against its
3875 first parent only.
3877 first parent only.
3876
3878
3877 Output may be to a file, in which case the name of the file is
3879 Output may be to a file, in which case the name of the file is
3878 given using a format string. The formatting rules are as follows:
3880 given using a format string. The formatting rules are as follows:
3879
3881
3880 :``%%``: literal "%" character
3882 :``%%``: literal "%" character
3881 :``%H``: changeset hash (40 hexadecimal digits)
3883 :``%H``: changeset hash (40 hexadecimal digits)
3882 :``%N``: number of patches being generated
3884 :``%N``: number of patches being generated
3883 :``%R``: changeset revision number
3885 :``%R``: changeset revision number
3884 :``%b``: basename of the exporting repository
3886 :``%b``: basename of the exporting repository
3885 :``%h``: short-form changeset hash (12 hexadecimal digits)
3887 :``%h``: short-form changeset hash (12 hexadecimal digits)
3886 :``%m``: first line of the commit message (only alphanumeric characters)
3888 :``%m``: first line of the commit message (only alphanumeric characters)
3887 :``%n``: zero-padded sequence number, starting at 1
3889 :``%n``: zero-padded sequence number, starting at 1
3888 :``%r``: zero-padded changeset revision number
3890 :``%r``: zero-padded changeset revision number
3889
3891
3890 Without the -a/--text option, export will avoid generating diffs
3892 Without the -a/--text option, export will avoid generating diffs
3891 of files it detects as binary. With -a, export will generate a
3893 of files it detects as binary. With -a, export will generate a
3892 diff anyway, probably with undesirable results.
3894 diff anyway, probably with undesirable results.
3893
3895
3894 Use the -g/--git option to generate diffs in the git extended diff
3896 Use the -g/--git option to generate diffs in the git extended diff
3895 format. See :hg:`help diffs` for more information.
3897 format. See :hg:`help diffs` for more information.
3896
3898
3897 With the --switch-parent option, the diff will be against the
3899 With the --switch-parent option, the diff will be against the
3898 second parent. It can be useful to review a merge.
3900 second parent. It can be useful to review a merge.
3899
3901
3900 .. container:: verbose
3902 .. container:: verbose
3901
3903
3902 Examples:
3904 Examples:
3903
3905
3904 - use export and import to transplant a bugfix to the current
3906 - use export and import to transplant a bugfix to the current
3905 branch::
3907 branch::
3906
3908
3907 hg export -r 9353 | hg import -
3909 hg export -r 9353 | hg import -
3908
3910
3909 - export all the changesets between two revisions to a file with
3911 - export all the changesets between two revisions to a file with
3910 rename information::
3912 rename information::
3911
3913
3912 hg export --git -r 123:150 > changes.txt
3914 hg export --git -r 123:150 > changes.txt
3913
3915
3914 - split outgoing changes into a series of patches with
3916 - split outgoing changes into a series of patches with
3915 descriptive names::
3917 descriptive names::
3916
3918
3917 hg export -r "outgoing()" -o "%n-%m.patch"
3919 hg export -r "outgoing()" -o "%n-%m.patch"
3918
3920
3919 Returns 0 on success.
3921 Returns 0 on success.
3920 """
3922 """
3921 changesets += tuple(opts.get('rev', []))
3923 changesets += tuple(opts.get('rev', []))
3922 if not changesets:
3924 if not changesets:
3923 changesets = ['.']
3925 changesets = ['.']
3924 revs = scmutil.revrange(repo, changesets)
3926 revs = scmutil.revrange(repo, changesets)
3925 if not revs:
3927 if not revs:
3926 raise error.Abort(_("export requires at least one changeset"))
3928 raise error.Abort(_("export requires at least one changeset"))
3927 if len(revs) > 1:
3929 if len(revs) > 1:
3928 ui.note(_('exporting patches:\n'))
3930 ui.note(_('exporting patches:\n'))
3929 else:
3931 else:
3930 ui.note(_('exporting patch:\n'))
3932 ui.note(_('exporting patch:\n'))
3931 cmdutil.export(repo, revs, template=opts.get('output'),
3933 cmdutil.export(repo, revs, template=opts.get('output'),
3932 switch_parent=opts.get('switch_parent'),
3934 switch_parent=opts.get('switch_parent'),
3933 opts=patch.diffallopts(ui, opts))
3935 opts=patch.diffallopts(ui, opts))
3934
3936
3935 @command('files',
3937 @command('files',
3936 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3938 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3937 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3939 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3938 ] + walkopts + formatteropts + subrepoopts,
3940 ] + walkopts + formatteropts + subrepoopts,
3939 _('[OPTION]... [FILE]...'))
3941 _('[OPTION]... [FILE]...'))
3940 def files(ui, repo, *pats, **opts):
3942 def files(ui, repo, *pats, **opts):
3941 """list tracked files
3943 """list tracked files
3942
3944
3943 Print files under Mercurial control in the working directory or
3945 Print files under Mercurial control in the working directory or
3944 specified revision for given files (excluding removed files).
3946 specified revision for given files (excluding removed files).
3945 Files can be specified as filenames or filesets.
3947 Files can be specified as filenames or filesets.
3946
3948
3947 If no files are given to match, this command prints the names
3949 If no files are given to match, this command prints the names
3948 of all files under Mercurial control.
3950 of all files under Mercurial control.
3949
3951
3950 .. container:: verbose
3952 .. container:: verbose
3951
3953
3952 Examples:
3954 Examples:
3953
3955
3954 - list all files under the current directory::
3956 - list all files under the current directory::
3955
3957
3956 hg files .
3958 hg files .
3957
3959
3958 - shows sizes and flags for current revision::
3960 - shows sizes and flags for current revision::
3959
3961
3960 hg files -vr .
3962 hg files -vr .
3961
3963
3962 - list all files named README::
3964 - list all files named README::
3963
3965
3964 hg files -I "**/README"
3966 hg files -I "**/README"
3965
3967
3966 - list all binary files::
3968 - list all binary files::
3967
3969
3968 hg files "set:binary()"
3970 hg files "set:binary()"
3969
3971
3970 - find files containing a regular expression::
3972 - find files containing a regular expression::
3971
3973
3972 hg files "set:grep('bob')"
3974 hg files "set:grep('bob')"
3973
3975
3974 - search tracked file contents with xargs and grep::
3976 - search tracked file contents with xargs and grep::
3975
3977
3976 hg files -0 | xargs -0 grep foo
3978 hg files -0 | xargs -0 grep foo
3977
3979
3978 See :hg:`help patterns` and :hg:`help filesets` for more information
3980 See :hg:`help patterns` and :hg:`help filesets` for more information
3979 on specifying file patterns.
3981 on specifying file patterns.
3980
3982
3981 Returns 0 if a match is found, 1 otherwise.
3983 Returns 0 if a match is found, 1 otherwise.
3982
3984
3983 """
3985 """
3984 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3986 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3985
3987
3986 end = '\n'
3988 end = '\n'
3987 if opts.get('print0'):
3989 if opts.get('print0'):
3988 end = '\0'
3990 end = '\0'
3989 fmt = '%s' + end
3991 fmt = '%s' + end
3990
3992
3991 m = scmutil.match(ctx, pats, opts)
3993 m = scmutil.match(ctx, pats, opts)
3992 with ui.formatter('files', opts) as fm:
3994 with ui.formatter('files', opts) as fm:
3993 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3995 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3994
3996
3995 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3997 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3996 def forget(ui, repo, *pats, **opts):
3998 def forget(ui, repo, *pats, **opts):
3997 """forget the specified files on the next commit
3999 """forget the specified files on the next commit
3998
4000
3999 Mark the specified files so they will no longer be tracked
4001 Mark the specified files so they will no longer be tracked
4000 after the next commit.
4002 after the next commit.
4001
4003
4002 This only removes files from the current branch, not from the
4004 This only removes files from the current branch, not from the
4003 entire project history, and it does not delete them from the
4005 entire project history, and it does not delete them from the
4004 working directory.
4006 working directory.
4005
4007
4006 To delete the file from the working directory, see :hg:`remove`.
4008 To delete the file from the working directory, see :hg:`remove`.
4007
4009
4008 To undo a forget before the next commit, see :hg:`add`.
4010 To undo a forget before the next commit, see :hg:`add`.
4009
4011
4010 .. container:: verbose
4012 .. container:: verbose
4011
4013
4012 Examples:
4014 Examples:
4013
4015
4014 - forget newly-added binary files::
4016 - forget newly-added binary files::
4015
4017
4016 hg forget "set:added() and binary()"
4018 hg forget "set:added() and binary()"
4017
4019
4018 - forget files that would be excluded by .hgignore::
4020 - forget files that would be excluded by .hgignore::
4019
4021
4020 hg forget "set:hgignore()"
4022 hg forget "set:hgignore()"
4021
4023
4022 Returns 0 on success.
4024 Returns 0 on success.
4023 """
4025 """
4024
4026
4025 if not pats:
4027 if not pats:
4026 raise error.Abort(_('no files specified'))
4028 raise error.Abort(_('no files specified'))
4027
4029
4028 m = scmutil.match(repo[None], pats, opts)
4030 m = scmutil.match(repo[None], pats, opts)
4029 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4031 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4030 return rejected and 1 or 0
4032 return rejected and 1 or 0
4031
4033
4032 @command(
4034 @command(
4033 'graft',
4035 'graft',
4034 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4036 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4035 ('c', 'continue', False, _('resume interrupted graft')),
4037 ('c', 'continue', False, _('resume interrupted graft')),
4036 ('e', 'edit', False, _('invoke editor on commit messages')),
4038 ('e', 'edit', False, _('invoke editor on commit messages')),
4037 ('', 'log', None, _('append graft info to log message')),
4039 ('', 'log', None, _('append graft info to log message')),
4038 ('f', 'force', False, _('force graft')),
4040 ('f', 'force', False, _('force graft')),
4039 ('D', 'currentdate', False,
4041 ('D', 'currentdate', False,
4040 _('record the current date as commit date')),
4042 _('record the current date as commit date')),
4041 ('U', 'currentuser', False,
4043 ('U', 'currentuser', False,
4042 _('record the current user as committer'), _('DATE'))]
4044 _('record the current user as committer'), _('DATE'))]
4043 + commitopts2 + mergetoolopts + dryrunopts,
4045 + commitopts2 + mergetoolopts + dryrunopts,
4044 _('[OPTION]... [-r REV]... REV...'))
4046 _('[OPTION]... [-r REV]... REV...'))
4045 def graft(ui, repo, *revs, **opts):
4047 def graft(ui, repo, *revs, **opts):
4046 '''copy changes from other branches onto the current branch
4048 '''copy changes from other branches onto the current branch
4047
4049
4048 This command uses Mercurial's merge logic to copy individual
4050 This command uses Mercurial's merge logic to copy individual
4049 changes from other branches without merging branches in the
4051 changes from other branches without merging branches in the
4050 history graph. This is sometimes known as 'backporting' or
4052 history graph. This is sometimes known as 'backporting' or
4051 'cherry-picking'. By default, graft will copy user, date, and
4053 'cherry-picking'. By default, graft will copy user, date, and
4052 description from the source changesets.
4054 description from the source changesets.
4053
4055
4054 Changesets that are ancestors of the current revision, that have
4056 Changesets that are ancestors of the current revision, that have
4055 already been grafted, or that are merges will be skipped.
4057 already been grafted, or that are merges will be skipped.
4056
4058
4057 If --log is specified, log messages will have a comment appended
4059 If --log is specified, log messages will have a comment appended
4058 of the form::
4060 of the form::
4059
4061
4060 (grafted from CHANGESETHASH)
4062 (grafted from CHANGESETHASH)
4061
4063
4062 If --force is specified, revisions will be grafted even if they
4064 If --force is specified, revisions will be grafted even if they
4063 are already ancestors of or have been grafted to the destination.
4065 are already ancestors of or have been grafted to the destination.
4064 This is useful when the revisions have since been backed out.
4066 This is useful when the revisions have since been backed out.
4065
4067
4066 If a graft merge results in conflicts, the graft process is
4068 If a graft merge results in conflicts, the graft process is
4067 interrupted so that the current merge can be manually resolved.
4069 interrupted so that the current merge can be manually resolved.
4068 Once all conflicts are addressed, the graft process can be
4070 Once all conflicts are addressed, the graft process can be
4069 continued with the -c/--continue option.
4071 continued with the -c/--continue option.
4070
4072
4071 .. note::
4073 .. note::
4072
4074
4073 The -c/--continue option does not reapply earlier options, except
4075 The -c/--continue option does not reapply earlier options, except
4074 for --force.
4076 for --force.
4075
4077
4076 .. container:: verbose
4078 .. container:: verbose
4077
4079
4078 Examples:
4080 Examples:
4079
4081
4080 - copy a single change to the stable branch and edit its description::
4082 - copy a single change to the stable branch and edit its description::
4081
4083
4082 hg update stable
4084 hg update stable
4083 hg graft --edit 9393
4085 hg graft --edit 9393
4084
4086
4085 - graft a range of changesets with one exception, updating dates::
4087 - graft a range of changesets with one exception, updating dates::
4086
4088
4087 hg graft -D "2085::2093 and not 2091"
4089 hg graft -D "2085::2093 and not 2091"
4088
4090
4089 - continue a graft after resolving conflicts::
4091 - continue a graft after resolving conflicts::
4090
4092
4091 hg graft -c
4093 hg graft -c
4092
4094
4093 - show the source of a grafted changeset::
4095 - show the source of a grafted changeset::
4094
4096
4095 hg log --debug -r .
4097 hg log --debug -r .
4096
4098
4097 - show revisions sorted by date::
4099 - show revisions sorted by date::
4098
4100
4099 hg log -r "sort(all(), date)"
4101 hg log -r "sort(all(), date)"
4100
4102
4101 See :hg:`help revisions` and :hg:`help revsets` for more about
4103 See :hg:`help revisions` and :hg:`help revsets` for more about
4102 specifying revisions.
4104 specifying revisions.
4103
4105
4104 Returns 0 on successful completion.
4106 Returns 0 on successful completion.
4105 '''
4107 '''
4106 with repo.wlock():
4108 with repo.wlock():
4107 return _dograft(ui, repo, *revs, **opts)
4109 return _dograft(ui, repo, *revs, **opts)
4108
4110
4109 def _dograft(ui, repo, *revs, **opts):
4111 def _dograft(ui, repo, *revs, **opts):
4110 if revs and opts.get('rev'):
4112 if revs and opts.get('rev'):
4111 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4113 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4112 'revision ordering!\n'))
4114 'revision ordering!\n'))
4113
4115
4114 revs = list(revs)
4116 revs = list(revs)
4115 revs.extend(opts.get('rev'))
4117 revs.extend(opts.get('rev'))
4116
4118
4117 if not opts.get('user') and opts.get('currentuser'):
4119 if not opts.get('user') and opts.get('currentuser'):
4118 opts['user'] = ui.username()
4120 opts['user'] = ui.username()
4119 if not opts.get('date') and opts.get('currentdate'):
4121 if not opts.get('date') and opts.get('currentdate'):
4120 opts['date'] = "%d %d" % util.makedate()
4122 opts['date'] = "%d %d" % util.makedate()
4121
4123
4122 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4124 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4123
4125
4124 cont = False
4126 cont = False
4125 if opts.get('continue'):
4127 if opts.get('continue'):
4126 cont = True
4128 cont = True
4127 if revs:
4129 if revs:
4128 raise error.Abort(_("can't specify --continue and revisions"))
4130 raise error.Abort(_("can't specify --continue and revisions"))
4129 # read in unfinished revisions
4131 # read in unfinished revisions
4130 try:
4132 try:
4131 nodes = repo.vfs.read('graftstate').splitlines()
4133 nodes = repo.vfs.read('graftstate').splitlines()
4132 revs = [repo[node].rev() for node in nodes]
4134 revs = [repo[node].rev() for node in nodes]
4133 except IOError as inst:
4135 except IOError as inst:
4134 if inst.errno != errno.ENOENT:
4136 if inst.errno != errno.ENOENT:
4135 raise
4137 raise
4136 cmdutil.wrongtooltocontinue(repo, _('graft'))
4138 cmdutil.wrongtooltocontinue(repo, _('graft'))
4137 else:
4139 else:
4138 cmdutil.checkunfinished(repo)
4140 cmdutil.checkunfinished(repo)
4139 cmdutil.bailifchanged(repo)
4141 cmdutil.bailifchanged(repo)
4140 if not revs:
4142 if not revs:
4141 raise error.Abort(_('no revisions specified'))
4143 raise error.Abort(_('no revisions specified'))
4142 revs = scmutil.revrange(repo, revs)
4144 revs = scmutil.revrange(repo, revs)
4143
4145
4144 skipped = set()
4146 skipped = set()
4145 # check for merges
4147 # check for merges
4146 for rev in repo.revs('%ld and merge()', revs):
4148 for rev in repo.revs('%ld and merge()', revs):
4147 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4149 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4148 skipped.add(rev)
4150 skipped.add(rev)
4149 revs = [r for r in revs if r not in skipped]
4151 revs = [r for r in revs if r not in skipped]
4150 if not revs:
4152 if not revs:
4151 return -1
4153 return -1
4152
4154
4153 # Don't check in the --continue case, in effect retaining --force across
4155 # Don't check in the --continue case, in effect retaining --force across
4154 # --continues. That's because without --force, any revisions we decided to
4156 # --continues. That's because without --force, any revisions we decided to
4155 # skip would have been filtered out here, so they wouldn't have made their
4157 # skip would have been filtered out here, so they wouldn't have made their
4156 # way to the graftstate. With --force, any revisions we would have otherwise
4158 # way to the graftstate. With --force, any revisions we would have otherwise
4157 # skipped would not have been filtered out, and if they hadn't been applied
4159 # skipped would not have been filtered out, and if they hadn't been applied
4158 # already, they'd have been in the graftstate.
4160 # already, they'd have been in the graftstate.
4159 if not (cont or opts.get('force')):
4161 if not (cont or opts.get('force')):
4160 # check for ancestors of dest branch
4162 # check for ancestors of dest branch
4161 crev = repo['.'].rev()
4163 crev = repo['.'].rev()
4162 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4164 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4163 # XXX make this lazy in the future
4165 # XXX make this lazy in the future
4164 # don't mutate while iterating, create a copy
4166 # don't mutate while iterating, create a copy
4165 for rev in list(revs):
4167 for rev in list(revs):
4166 if rev in ancestors:
4168 if rev in ancestors:
4167 ui.warn(_('skipping ancestor revision %d:%s\n') %
4169 ui.warn(_('skipping ancestor revision %d:%s\n') %
4168 (rev, repo[rev]))
4170 (rev, repo[rev]))
4169 # XXX remove on list is slow
4171 # XXX remove on list is slow
4170 revs.remove(rev)
4172 revs.remove(rev)
4171 if not revs:
4173 if not revs:
4172 return -1
4174 return -1
4173
4175
4174 # analyze revs for earlier grafts
4176 # analyze revs for earlier grafts
4175 ids = {}
4177 ids = {}
4176 for ctx in repo.set("%ld", revs):
4178 for ctx in repo.set("%ld", revs):
4177 ids[ctx.hex()] = ctx.rev()
4179 ids[ctx.hex()] = ctx.rev()
4178 n = ctx.extra().get('source')
4180 n = ctx.extra().get('source')
4179 if n:
4181 if n:
4180 ids[n] = ctx.rev()
4182 ids[n] = ctx.rev()
4181
4183
4182 # check ancestors for earlier grafts
4184 # check ancestors for earlier grafts
4183 ui.debug('scanning for duplicate grafts\n')
4185 ui.debug('scanning for duplicate grafts\n')
4184
4186
4185 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4187 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4186 ctx = repo[rev]
4188 ctx = repo[rev]
4187 n = ctx.extra().get('source')
4189 n = ctx.extra().get('source')
4188 if n in ids:
4190 if n in ids:
4189 try:
4191 try:
4190 r = repo[n].rev()
4192 r = repo[n].rev()
4191 except error.RepoLookupError:
4193 except error.RepoLookupError:
4192 r = None
4194 r = None
4193 if r in revs:
4195 if r in revs:
4194 ui.warn(_('skipping revision %d:%s '
4196 ui.warn(_('skipping revision %d:%s '
4195 '(already grafted to %d:%s)\n')
4197 '(already grafted to %d:%s)\n')
4196 % (r, repo[r], rev, ctx))
4198 % (r, repo[r], rev, ctx))
4197 revs.remove(r)
4199 revs.remove(r)
4198 elif ids[n] in revs:
4200 elif ids[n] in revs:
4199 if r is None:
4201 if r is None:
4200 ui.warn(_('skipping already grafted revision %d:%s '
4202 ui.warn(_('skipping already grafted revision %d:%s '
4201 '(%d:%s also has unknown origin %s)\n')
4203 '(%d:%s also has unknown origin %s)\n')
4202 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4204 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4203 else:
4205 else:
4204 ui.warn(_('skipping already grafted revision %d:%s '
4206 ui.warn(_('skipping already grafted revision %d:%s '
4205 '(%d:%s also has origin %d:%s)\n')
4207 '(%d:%s also has origin %d:%s)\n')
4206 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4208 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4207 revs.remove(ids[n])
4209 revs.remove(ids[n])
4208 elif ctx.hex() in ids:
4210 elif ctx.hex() in ids:
4209 r = ids[ctx.hex()]
4211 r = ids[ctx.hex()]
4210 ui.warn(_('skipping already grafted revision %d:%s '
4212 ui.warn(_('skipping already grafted revision %d:%s '
4211 '(was grafted from %d:%s)\n') %
4213 '(was grafted from %d:%s)\n') %
4212 (r, repo[r], rev, ctx))
4214 (r, repo[r], rev, ctx))
4213 revs.remove(r)
4215 revs.remove(r)
4214 if not revs:
4216 if not revs:
4215 return -1
4217 return -1
4216
4218
4217 for pos, ctx in enumerate(repo.set("%ld", revs)):
4219 for pos, ctx in enumerate(repo.set("%ld", revs)):
4218 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4220 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4219 ctx.description().split('\n', 1)[0])
4221 ctx.description().split('\n', 1)[0])
4220 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4222 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4221 if names:
4223 if names:
4222 desc += ' (%s)' % ' '.join(names)
4224 desc += ' (%s)' % ' '.join(names)
4223 ui.status(_('grafting %s\n') % desc)
4225 ui.status(_('grafting %s\n') % desc)
4224 if opts.get('dry_run'):
4226 if opts.get('dry_run'):
4225 continue
4227 continue
4226
4228
4227 source = ctx.extra().get('source')
4229 source = ctx.extra().get('source')
4228 extra = {}
4230 extra = {}
4229 if source:
4231 if source:
4230 extra['source'] = source
4232 extra['source'] = source
4231 extra['intermediate-source'] = ctx.hex()
4233 extra['intermediate-source'] = ctx.hex()
4232 else:
4234 else:
4233 extra['source'] = ctx.hex()
4235 extra['source'] = ctx.hex()
4234 user = ctx.user()
4236 user = ctx.user()
4235 if opts.get('user'):
4237 if opts.get('user'):
4236 user = opts['user']
4238 user = opts['user']
4237 date = ctx.date()
4239 date = ctx.date()
4238 if opts.get('date'):
4240 if opts.get('date'):
4239 date = opts['date']
4241 date = opts['date']
4240 message = ctx.description()
4242 message = ctx.description()
4241 if opts.get('log'):
4243 if opts.get('log'):
4242 message += '\n(grafted from %s)' % ctx.hex()
4244 message += '\n(grafted from %s)' % ctx.hex()
4243
4245
4244 # we don't merge the first commit when continuing
4246 # we don't merge the first commit when continuing
4245 if not cont:
4247 if not cont:
4246 # perform the graft merge with p1(rev) as 'ancestor'
4248 # perform the graft merge with p1(rev) as 'ancestor'
4247 try:
4249 try:
4248 # ui.forcemerge is an internal variable, do not document
4250 # ui.forcemerge is an internal variable, do not document
4249 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4251 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4250 'graft')
4252 'graft')
4251 stats = mergemod.graft(repo, ctx, ctx.p1(),
4253 stats = mergemod.graft(repo, ctx, ctx.p1(),
4252 ['local', 'graft'])
4254 ['local', 'graft'])
4253 finally:
4255 finally:
4254 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4256 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4255 # report any conflicts
4257 # report any conflicts
4256 if stats and stats[3] > 0:
4258 if stats and stats[3] > 0:
4257 # write out state for --continue
4259 # write out state for --continue
4258 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4260 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4259 repo.vfs.write('graftstate', ''.join(nodelines))
4261 repo.vfs.write('graftstate', ''.join(nodelines))
4260 extra = ''
4262 extra = ''
4261 if opts.get('user'):
4263 if opts.get('user'):
4262 extra += ' --user %s' % util.shellquote(opts['user'])
4264 extra += ' --user %s' % util.shellquote(opts['user'])
4263 if opts.get('date'):
4265 if opts.get('date'):
4264 extra += ' --date %s' % util.shellquote(opts['date'])
4266 extra += ' --date %s' % util.shellquote(opts['date'])
4265 if opts.get('log'):
4267 if opts.get('log'):
4266 extra += ' --log'
4268 extra += ' --log'
4267 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4269 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4268 raise error.Abort(
4270 raise error.Abort(
4269 _("unresolved conflicts, can't continue"),
4271 _("unresolved conflicts, can't continue"),
4270 hint=hint)
4272 hint=hint)
4271 else:
4273 else:
4272 cont = False
4274 cont = False
4273
4275
4274 # commit
4276 # commit
4275 node = repo.commit(text=message, user=user,
4277 node = repo.commit(text=message, user=user,
4276 date=date, extra=extra, editor=editor)
4278 date=date, extra=extra, editor=editor)
4277 if node is None:
4279 if node is None:
4278 ui.warn(
4280 ui.warn(
4279 _('note: graft of %d:%s created no changes to commit\n') %
4281 _('note: graft of %d:%s created no changes to commit\n') %
4280 (ctx.rev(), ctx))
4282 (ctx.rev(), ctx))
4281
4283
4282 # remove state when we complete successfully
4284 # remove state when we complete successfully
4283 if not opts.get('dry_run'):
4285 if not opts.get('dry_run'):
4284 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4286 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4285
4287
4286 return 0
4288 return 0
4287
4289
4288 @command('grep',
4290 @command('grep',
4289 [('0', 'print0', None, _('end fields with NUL')),
4291 [('0', 'print0', None, _('end fields with NUL')),
4290 ('', 'all', None, _('print all revisions that match')),
4292 ('', 'all', None, _('print all revisions that match')),
4291 ('a', 'text', None, _('treat all files as text')),
4293 ('a', 'text', None, _('treat all files as text')),
4292 ('f', 'follow', None,
4294 ('f', 'follow', None,
4293 _('follow changeset history,'
4295 _('follow changeset history,'
4294 ' or file history across copies and renames')),
4296 ' or file history across copies and renames')),
4295 ('i', 'ignore-case', None, _('ignore case when matching')),
4297 ('i', 'ignore-case', None, _('ignore case when matching')),
4296 ('l', 'files-with-matches', None,
4298 ('l', 'files-with-matches', None,
4297 _('print only filenames and revisions that match')),
4299 _('print only filenames and revisions that match')),
4298 ('n', 'line-number', None, _('print matching line numbers')),
4300 ('n', 'line-number', None, _('print matching line numbers')),
4299 ('r', 'rev', [],
4301 ('r', 'rev', [],
4300 _('only search files changed within revision range'), _('REV')),
4302 _('only search files changed within revision range'), _('REV')),
4301 ('u', 'user', None, _('list the author (long with -v)')),
4303 ('u', 'user', None, _('list the author (long with -v)')),
4302 ('d', 'date', None, _('list the date (short with -q)')),
4304 ('d', 'date', None, _('list the date (short with -q)')),
4303 ] + formatteropts + walkopts,
4305 ] + formatteropts + walkopts,
4304 _('[OPTION]... PATTERN [FILE]...'),
4306 _('[OPTION]... PATTERN [FILE]...'),
4305 inferrepo=True)
4307 inferrepo=True)
4306 def grep(ui, repo, pattern, *pats, **opts):
4308 def grep(ui, repo, pattern, *pats, **opts):
4307 """search revision history for a pattern in specified files
4309 """search revision history for a pattern in specified files
4308
4310
4309 Search revision history for a regular expression in the specified
4311 Search revision history for a regular expression in the specified
4310 files or the entire project.
4312 files or the entire project.
4311
4313
4312 By default, grep prints the most recent revision number for each
4314 By default, grep prints the most recent revision number for each
4313 file in which it finds a match. To get it to print every revision
4315 file in which it finds a match. To get it to print every revision
4314 that contains a change in match status ("-" for a match that becomes
4316 that contains a change in match status ("-" for a match that becomes
4315 a non-match, or "+" for a non-match that becomes a match), use the
4317 a non-match, or "+" for a non-match that becomes a match), use the
4316 --all flag.
4318 --all flag.
4317
4319
4318 PATTERN can be any Python (roughly Perl-compatible) regular
4320 PATTERN can be any Python (roughly Perl-compatible) regular
4319 expression.
4321 expression.
4320
4322
4321 If no FILEs are specified (and -f/--follow isn't set), all files in
4323 If no FILEs are specified (and -f/--follow isn't set), all files in
4322 the repository are searched, including those that don't exist in the
4324 the repository are searched, including those that don't exist in the
4323 current branch or have been deleted in a prior changeset.
4325 current branch or have been deleted in a prior changeset.
4324
4326
4325 Returns 0 if a match is found, 1 otherwise.
4327 Returns 0 if a match is found, 1 otherwise.
4326 """
4328 """
4327 reflags = re.M
4329 reflags = re.M
4328 if opts.get('ignore_case'):
4330 if opts.get('ignore_case'):
4329 reflags |= re.I
4331 reflags |= re.I
4330 try:
4332 try:
4331 regexp = util.re.compile(pattern, reflags)
4333 regexp = util.re.compile(pattern, reflags)
4332 except re.error as inst:
4334 except re.error as inst:
4333 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4335 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4334 return 1
4336 return 1
4335 sep, eol = ':', '\n'
4337 sep, eol = ':', '\n'
4336 if opts.get('print0'):
4338 if opts.get('print0'):
4337 sep = eol = '\0'
4339 sep = eol = '\0'
4338
4340
4339 getfile = util.lrucachefunc(repo.file)
4341 getfile = util.lrucachefunc(repo.file)
4340
4342
4341 def matchlines(body):
4343 def matchlines(body):
4342 begin = 0
4344 begin = 0
4343 linenum = 0
4345 linenum = 0
4344 while begin < len(body):
4346 while begin < len(body):
4345 match = regexp.search(body, begin)
4347 match = regexp.search(body, begin)
4346 if not match:
4348 if not match:
4347 break
4349 break
4348 mstart, mend = match.span()
4350 mstart, mend = match.span()
4349 linenum += body.count('\n', begin, mstart) + 1
4351 linenum += body.count('\n', begin, mstart) + 1
4350 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4352 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4351 begin = body.find('\n', mend) + 1 or len(body) + 1
4353 begin = body.find('\n', mend) + 1 or len(body) + 1
4352 lend = begin - 1
4354 lend = begin - 1
4353 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4355 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4354
4356
4355 class linestate(object):
4357 class linestate(object):
4356 def __init__(self, line, linenum, colstart, colend):
4358 def __init__(self, line, linenum, colstart, colend):
4357 self.line = line
4359 self.line = line
4358 self.linenum = linenum
4360 self.linenum = linenum
4359 self.colstart = colstart
4361 self.colstart = colstart
4360 self.colend = colend
4362 self.colend = colend
4361
4363
4362 def __hash__(self):
4364 def __hash__(self):
4363 return hash((self.linenum, self.line))
4365 return hash((self.linenum, self.line))
4364
4366
4365 def __eq__(self, other):
4367 def __eq__(self, other):
4366 return self.line == other.line
4368 return self.line == other.line
4367
4369
4368 def findpos(self):
4370 def findpos(self):
4369 """Iterate all (start, end) indices of matches"""
4371 """Iterate all (start, end) indices of matches"""
4370 yield self.colstart, self.colend
4372 yield self.colstart, self.colend
4371 p = self.colend
4373 p = self.colend
4372 while p < len(self.line):
4374 while p < len(self.line):
4373 m = regexp.search(self.line, p)
4375 m = regexp.search(self.line, p)
4374 if not m:
4376 if not m:
4375 break
4377 break
4376 yield m.span()
4378 yield m.span()
4377 p = m.end()
4379 p = m.end()
4378
4380
4379 matches = {}
4381 matches = {}
4380 copies = {}
4382 copies = {}
4381 def grepbody(fn, rev, body):
4383 def grepbody(fn, rev, body):
4382 matches[rev].setdefault(fn, [])
4384 matches[rev].setdefault(fn, [])
4383 m = matches[rev][fn]
4385 m = matches[rev][fn]
4384 for lnum, cstart, cend, line in matchlines(body):
4386 for lnum, cstart, cend, line in matchlines(body):
4385 s = linestate(line, lnum, cstart, cend)
4387 s = linestate(line, lnum, cstart, cend)
4386 m.append(s)
4388 m.append(s)
4387
4389
4388 def difflinestates(a, b):
4390 def difflinestates(a, b):
4389 sm = difflib.SequenceMatcher(None, a, b)
4391 sm = difflib.SequenceMatcher(None, a, b)
4390 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4392 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4391 if tag == 'insert':
4393 if tag == 'insert':
4392 for i in xrange(blo, bhi):
4394 for i in xrange(blo, bhi):
4393 yield ('+', b[i])
4395 yield ('+', b[i])
4394 elif tag == 'delete':
4396 elif tag == 'delete':
4395 for i in xrange(alo, ahi):
4397 for i in xrange(alo, ahi):
4396 yield ('-', a[i])
4398 yield ('-', a[i])
4397 elif tag == 'replace':
4399 elif tag == 'replace':
4398 for i in xrange(alo, ahi):
4400 for i in xrange(alo, ahi):
4399 yield ('-', a[i])
4401 yield ('-', a[i])
4400 for i in xrange(blo, bhi):
4402 for i in xrange(blo, bhi):
4401 yield ('+', b[i])
4403 yield ('+', b[i])
4402
4404
4403 def display(fm, fn, ctx, pstates, states):
4405 def display(fm, fn, ctx, pstates, states):
4404 rev = ctx.rev()
4406 rev = ctx.rev()
4405 if fm.isplain():
4407 if fm.isplain():
4406 formatuser = ui.shortuser
4408 formatuser = ui.shortuser
4407 else:
4409 else:
4408 formatuser = str
4410 formatuser = str
4409 if ui.quiet:
4411 if ui.quiet:
4410 datefmt = '%Y-%m-%d'
4412 datefmt = '%Y-%m-%d'
4411 else:
4413 else:
4412 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4414 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4413 found = False
4415 found = False
4414 @util.cachefunc
4416 @util.cachefunc
4415 def binary():
4417 def binary():
4416 flog = getfile(fn)
4418 flog = getfile(fn)
4417 return util.binary(flog.read(ctx.filenode(fn)))
4419 return util.binary(flog.read(ctx.filenode(fn)))
4418
4420
4419 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4421 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4420 if opts.get('all'):
4422 if opts.get('all'):
4421 iter = difflinestates(pstates, states)
4423 iter = difflinestates(pstates, states)
4422 else:
4424 else:
4423 iter = [('', l) for l in states]
4425 iter = [('', l) for l in states]
4424 for change, l in iter:
4426 for change, l in iter:
4425 fm.startitem()
4427 fm.startitem()
4426 fm.data(node=fm.hexfunc(ctx.node()))
4428 fm.data(node=fm.hexfunc(ctx.node()))
4427 cols = [
4429 cols = [
4428 ('filename', fn, True),
4430 ('filename', fn, True),
4429 ('rev', rev, True),
4431 ('rev', rev, True),
4430 ('linenumber', l.linenum, opts.get('line_number')),
4432 ('linenumber', l.linenum, opts.get('line_number')),
4431 ]
4433 ]
4432 if opts.get('all'):
4434 if opts.get('all'):
4433 cols.append(('change', change, True))
4435 cols.append(('change', change, True))
4434 cols.extend([
4436 cols.extend([
4435 ('user', formatuser(ctx.user()), opts.get('user')),
4437 ('user', formatuser(ctx.user()), opts.get('user')),
4436 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4438 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4437 ])
4439 ])
4438 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4440 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4439 for name, data, cond in cols:
4441 for name, data, cond in cols:
4440 field = fieldnamemap.get(name, name)
4442 field = fieldnamemap.get(name, name)
4441 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4443 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4442 if cond and name != lastcol:
4444 if cond and name != lastcol:
4443 fm.plain(sep, label='grep.sep')
4445 fm.plain(sep, label='grep.sep')
4444 if not opts.get('files_with_matches'):
4446 if not opts.get('files_with_matches'):
4445 fm.plain(sep, label='grep.sep')
4447 fm.plain(sep, label='grep.sep')
4446 if not opts.get('text') and binary():
4448 if not opts.get('text') and binary():
4447 fm.plain(_(" Binary file matches"))
4449 fm.plain(_(" Binary file matches"))
4448 else:
4450 else:
4449 displaymatches(fm.nested('texts'), l)
4451 displaymatches(fm.nested('texts'), l)
4450 fm.plain(eol)
4452 fm.plain(eol)
4451 found = True
4453 found = True
4452 if opts.get('files_with_matches'):
4454 if opts.get('files_with_matches'):
4453 break
4455 break
4454 return found
4456 return found
4455
4457
4456 def displaymatches(fm, l):
4458 def displaymatches(fm, l):
4457 p = 0
4459 p = 0
4458 for s, e in l.findpos():
4460 for s, e in l.findpos():
4459 if p < s:
4461 if p < s:
4460 fm.startitem()
4462 fm.startitem()
4461 fm.write('text', '%s', l.line[p:s])
4463 fm.write('text', '%s', l.line[p:s])
4462 fm.data(matched=False)
4464 fm.data(matched=False)
4463 fm.startitem()
4465 fm.startitem()
4464 fm.write('text', '%s', l.line[s:e], label='grep.match')
4466 fm.write('text', '%s', l.line[s:e], label='grep.match')
4465 fm.data(matched=True)
4467 fm.data(matched=True)
4466 p = e
4468 p = e
4467 if p < len(l.line):
4469 if p < len(l.line):
4468 fm.startitem()
4470 fm.startitem()
4469 fm.write('text', '%s', l.line[p:])
4471 fm.write('text', '%s', l.line[p:])
4470 fm.data(matched=False)
4472 fm.data(matched=False)
4471 fm.end()
4473 fm.end()
4472
4474
4473 skip = {}
4475 skip = {}
4474 revfiles = {}
4476 revfiles = {}
4475 matchfn = scmutil.match(repo[None], pats, opts)
4477 matchfn = scmutil.match(repo[None], pats, opts)
4476 found = False
4478 found = False
4477 follow = opts.get('follow')
4479 follow = opts.get('follow')
4478
4480
4479 def prep(ctx, fns):
4481 def prep(ctx, fns):
4480 rev = ctx.rev()
4482 rev = ctx.rev()
4481 pctx = ctx.p1()
4483 pctx = ctx.p1()
4482 parent = pctx.rev()
4484 parent = pctx.rev()
4483 matches.setdefault(rev, {})
4485 matches.setdefault(rev, {})
4484 matches.setdefault(parent, {})
4486 matches.setdefault(parent, {})
4485 files = revfiles.setdefault(rev, [])
4487 files = revfiles.setdefault(rev, [])
4486 for fn in fns:
4488 for fn in fns:
4487 flog = getfile(fn)
4489 flog = getfile(fn)
4488 try:
4490 try:
4489 fnode = ctx.filenode(fn)
4491 fnode = ctx.filenode(fn)
4490 except error.LookupError:
4492 except error.LookupError:
4491 continue
4493 continue
4492
4494
4493 copied = flog.renamed(fnode)
4495 copied = flog.renamed(fnode)
4494 copy = follow and copied and copied[0]
4496 copy = follow and copied and copied[0]
4495 if copy:
4497 if copy:
4496 copies.setdefault(rev, {})[fn] = copy
4498 copies.setdefault(rev, {})[fn] = copy
4497 if fn in skip:
4499 if fn in skip:
4498 if copy:
4500 if copy:
4499 skip[copy] = True
4501 skip[copy] = True
4500 continue
4502 continue
4501 files.append(fn)
4503 files.append(fn)
4502
4504
4503 if fn not in matches[rev]:
4505 if fn not in matches[rev]:
4504 grepbody(fn, rev, flog.read(fnode))
4506 grepbody(fn, rev, flog.read(fnode))
4505
4507
4506 pfn = copy or fn
4508 pfn = copy or fn
4507 if pfn not in matches[parent]:
4509 if pfn not in matches[parent]:
4508 try:
4510 try:
4509 fnode = pctx.filenode(pfn)
4511 fnode = pctx.filenode(pfn)
4510 grepbody(pfn, parent, flog.read(fnode))
4512 grepbody(pfn, parent, flog.read(fnode))
4511 except error.LookupError:
4513 except error.LookupError:
4512 pass
4514 pass
4513
4515
4514 fm = ui.formatter('grep', opts)
4516 fm = ui.formatter('grep', opts)
4515 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4517 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4516 rev = ctx.rev()
4518 rev = ctx.rev()
4517 parent = ctx.p1().rev()
4519 parent = ctx.p1().rev()
4518 for fn in sorted(revfiles.get(rev, [])):
4520 for fn in sorted(revfiles.get(rev, [])):
4519 states = matches[rev][fn]
4521 states = matches[rev][fn]
4520 copy = copies.get(rev, {}).get(fn)
4522 copy = copies.get(rev, {}).get(fn)
4521 if fn in skip:
4523 if fn in skip:
4522 if copy:
4524 if copy:
4523 skip[copy] = True
4525 skip[copy] = True
4524 continue
4526 continue
4525 pstates = matches.get(parent, {}).get(copy or fn, [])
4527 pstates = matches.get(parent, {}).get(copy or fn, [])
4526 if pstates or states:
4528 if pstates or states:
4527 r = display(fm, fn, ctx, pstates, states)
4529 r = display(fm, fn, ctx, pstates, states)
4528 found = found or r
4530 found = found or r
4529 if r and not opts.get('all'):
4531 if r and not opts.get('all'):
4530 skip[fn] = True
4532 skip[fn] = True
4531 if copy:
4533 if copy:
4532 skip[copy] = True
4534 skip[copy] = True
4533 del matches[rev]
4535 del matches[rev]
4534 del revfiles[rev]
4536 del revfiles[rev]
4535 fm.end()
4537 fm.end()
4536
4538
4537 return not found
4539 return not found
4538
4540
4539 @command('heads',
4541 @command('heads',
4540 [('r', 'rev', '',
4542 [('r', 'rev', '',
4541 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4543 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4542 ('t', 'topo', False, _('show topological heads only')),
4544 ('t', 'topo', False, _('show topological heads only')),
4543 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4545 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4544 ('c', 'closed', False, _('show normal and closed branch heads')),
4546 ('c', 'closed', False, _('show normal and closed branch heads')),
4545 ] + templateopts,
4547 ] + templateopts,
4546 _('[-ct] [-r STARTREV] [REV]...'))
4548 _('[-ct] [-r STARTREV] [REV]...'))
4547 def heads(ui, repo, *branchrevs, **opts):
4549 def heads(ui, repo, *branchrevs, **opts):
4548 """show branch heads
4550 """show branch heads
4549
4551
4550 With no arguments, show all open branch heads in the repository.
4552 With no arguments, show all open branch heads in the repository.
4551 Branch heads are changesets that have no descendants on the
4553 Branch heads are changesets that have no descendants on the
4552 same branch. They are where development generally takes place and
4554 same branch. They are where development generally takes place and
4553 are the usual targets for update and merge operations.
4555 are the usual targets for update and merge operations.
4554
4556
4555 If one or more REVs are given, only open branch heads on the
4557 If one or more REVs are given, only open branch heads on the
4556 branches associated with the specified changesets are shown. This
4558 branches associated with the specified changesets are shown. This
4557 means that you can use :hg:`heads .` to see the heads on the
4559 means that you can use :hg:`heads .` to see the heads on the
4558 currently checked-out branch.
4560 currently checked-out branch.
4559
4561
4560 If -c/--closed is specified, also show branch heads marked closed
4562 If -c/--closed is specified, also show branch heads marked closed
4561 (see :hg:`commit --close-branch`).
4563 (see :hg:`commit --close-branch`).
4562
4564
4563 If STARTREV is specified, only those heads that are descendants of
4565 If STARTREV is specified, only those heads that are descendants of
4564 STARTREV will be displayed.
4566 STARTREV will be displayed.
4565
4567
4566 If -t/--topo is specified, named branch mechanics will be ignored and only
4568 If -t/--topo is specified, named branch mechanics will be ignored and only
4567 topological heads (changesets with no children) will be shown.
4569 topological heads (changesets with no children) will be shown.
4568
4570
4569 Returns 0 if matching heads are found, 1 if not.
4571 Returns 0 if matching heads are found, 1 if not.
4570 """
4572 """
4571
4573
4572 start = None
4574 start = None
4573 if 'rev' in opts:
4575 if 'rev' in opts:
4574 start = scmutil.revsingle(repo, opts['rev'], None).node()
4576 start = scmutil.revsingle(repo, opts['rev'], None).node()
4575
4577
4576 if opts.get('topo'):
4578 if opts.get('topo'):
4577 heads = [repo[h] for h in repo.heads(start)]
4579 heads = [repo[h] for h in repo.heads(start)]
4578 else:
4580 else:
4579 heads = []
4581 heads = []
4580 for branch in repo.branchmap():
4582 for branch in repo.branchmap():
4581 heads += repo.branchheads(branch, start, opts.get('closed'))
4583 heads += repo.branchheads(branch, start, opts.get('closed'))
4582 heads = [repo[h] for h in heads]
4584 heads = [repo[h] for h in heads]
4583
4585
4584 if branchrevs:
4586 if branchrevs:
4585 branches = set(repo[br].branch() for br in branchrevs)
4587 branches = set(repo[br].branch() for br in branchrevs)
4586 heads = [h for h in heads if h.branch() in branches]
4588 heads = [h for h in heads if h.branch() in branches]
4587
4589
4588 if opts.get('active') and branchrevs:
4590 if opts.get('active') and branchrevs:
4589 dagheads = repo.heads(start)
4591 dagheads = repo.heads(start)
4590 heads = [h for h in heads if h.node() in dagheads]
4592 heads = [h for h in heads if h.node() in dagheads]
4591
4593
4592 if branchrevs:
4594 if branchrevs:
4593 haveheads = set(h.branch() for h in heads)
4595 haveheads = set(h.branch() for h in heads)
4594 if branches - haveheads:
4596 if branches - haveheads:
4595 headless = ', '.join(b for b in branches - haveheads)
4597 headless = ', '.join(b for b in branches - haveheads)
4596 msg = _('no open branch heads found on branches %s')
4598 msg = _('no open branch heads found on branches %s')
4597 if opts.get('rev'):
4599 if opts.get('rev'):
4598 msg += _(' (started at %s)') % opts['rev']
4600 msg += _(' (started at %s)') % opts['rev']
4599 ui.warn((msg + '\n') % headless)
4601 ui.warn((msg + '\n') % headless)
4600
4602
4601 if not heads:
4603 if not heads:
4602 return 1
4604 return 1
4603
4605
4604 heads = sorted(heads, key=lambda x: -x.rev())
4606 heads = sorted(heads, key=lambda x: -x.rev())
4605 displayer = cmdutil.show_changeset(ui, repo, opts)
4607 displayer = cmdutil.show_changeset(ui, repo, opts)
4606 for ctx in heads:
4608 for ctx in heads:
4607 displayer.show(ctx)
4609 displayer.show(ctx)
4608 displayer.close()
4610 displayer.close()
4609
4611
4610 @command('help',
4612 @command('help',
4611 [('e', 'extension', None, _('show only help for extensions')),
4613 [('e', 'extension', None, _('show only help for extensions')),
4612 ('c', 'command', None, _('show only help for commands')),
4614 ('c', 'command', None, _('show only help for commands')),
4613 ('k', 'keyword', None, _('show topics matching keyword')),
4615 ('k', 'keyword', None, _('show topics matching keyword')),
4614 ('s', 'system', [], _('show help for specific platform(s)')),
4616 ('s', 'system', [], _('show help for specific platform(s)')),
4615 ],
4617 ],
4616 _('[-ecks] [TOPIC]'),
4618 _('[-ecks] [TOPIC]'),
4617 norepo=True)
4619 norepo=True)
4618 def help_(ui, name=None, **opts):
4620 def help_(ui, name=None, **opts):
4619 """show help for a given topic or a help overview
4621 """show help for a given topic or a help overview
4620
4622
4621 With no arguments, print a list of commands with short help messages.
4623 With no arguments, print a list of commands with short help messages.
4622
4624
4623 Given a topic, extension, or command name, print help for that
4625 Given a topic, extension, or command name, print help for that
4624 topic.
4626 topic.
4625
4627
4626 Returns 0 if successful.
4628 Returns 0 if successful.
4627 """
4629 """
4628
4630
4629 textwidth = ui.configint('ui', 'textwidth', 78)
4631 textwidth = ui.configint('ui', 'textwidth', 78)
4630 termwidth = ui.termwidth() - 2
4632 termwidth = ui.termwidth() - 2
4631 if textwidth <= 0 or termwidth < textwidth:
4633 if textwidth <= 0 or termwidth < textwidth:
4632 textwidth = termwidth
4634 textwidth = termwidth
4633
4635
4634 keep = opts.get('system') or []
4636 keep = opts.get('system') or []
4635 if len(keep) == 0:
4637 if len(keep) == 0:
4636 if sys.platform.startswith('win'):
4638 if sys.platform.startswith('win'):
4637 keep.append('windows')
4639 keep.append('windows')
4638 elif sys.platform == 'OpenVMS':
4640 elif sys.platform == 'OpenVMS':
4639 keep.append('vms')
4641 keep.append('vms')
4640 elif sys.platform == 'plan9':
4642 elif sys.platform == 'plan9':
4641 keep.append('plan9')
4643 keep.append('plan9')
4642 else:
4644 else:
4643 keep.append('unix')
4645 keep.append('unix')
4644 keep.append(sys.platform.lower())
4646 keep.append(sys.platform.lower())
4645 if ui.verbose:
4647 if ui.verbose:
4646 keep.append('verbose')
4648 keep.append('verbose')
4647
4649
4648 section = None
4650 section = None
4649 subtopic = None
4651 subtopic = None
4650 if name and '.' in name:
4652 if name and '.' in name:
4651 name, remaining = name.split('.', 1)
4653 name, remaining = name.split('.', 1)
4652 remaining = encoding.lower(remaining)
4654 remaining = encoding.lower(remaining)
4653 if '.' in remaining:
4655 if '.' in remaining:
4654 subtopic, section = remaining.split('.', 1)
4656 subtopic, section = remaining.split('.', 1)
4655 else:
4657 else:
4656 if name in help.subtopics:
4658 if name in help.subtopics:
4657 subtopic = remaining
4659 subtopic = remaining
4658 else:
4660 else:
4659 section = remaining
4661 section = remaining
4660
4662
4661 text = help.help_(ui, name, subtopic=subtopic, **opts)
4663 text = help.help_(ui, name, subtopic=subtopic, **opts)
4662
4664
4663 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4665 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4664 section=section)
4666 section=section)
4665
4667
4666 # We could have been given a weird ".foo" section without a name
4668 # We could have been given a weird ".foo" section without a name
4667 # to look for, or we could have simply failed to found "foo.bar"
4669 # to look for, or we could have simply failed to found "foo.bar"
4668 # because bar isn't a section of foo
4670 # because bar isn't a section of foo
4669 if section and not (formatted and name):
4671 if section and not (formatted and name):
4670 raise error.Abort(_("help section not found"))
4672 raise error.Abort(_("help section not found"))
4671
4673
4672 if 'verbose' in pruned:
4674 if 'verbose' in pruned:
4673 keep.append('omitted')
4675 keep.append('omitted')
4674 else:
4676 else:
4675 keep.append('notomitted')
4677 keep.append('notomitted')
4676 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4678 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4677 section=section)
4679 section=section)
4678 ui.write(formatted)
4680 ui.write(formatted)
4679
4681
4680
4682
4681 @command('identify|id',
4683 @command('identify|id',
4682 [('r', 'rev', '',
4684 [('r', 'rev', '',
4683 _('identify the specified revision'), _('REV')),
4685 _('identify the specified revision'), _('REV')),
4684 ('n', 'num', None, _('show local revision number')),
4686 ('n', 'num', None, _('show local revision number')),
4685 ('i', 'id', None, _('show global revision id')),
4687 ('i', 'id', None, _('show global revision id')),
4686 ('b', 'branch', None, _('show branch')),
4688 ('b', 'branch', None, _('show branch')),
4687 ('t', 'tags', None, _('show tags')),
4689 ('t', 'tags', None, _('show tags')),
4688 ('B', 'bookmarks', None, _('show bookmarks')),
4690 ('B', 'bookmarks', None, _('show bookmarks')),
4689 ] + remoteopts,
4691 ] + remoteopts,
4690 _('[-nibtB] [-r REV] [SOURCE]'),
4692 _('[-nibtB] [-r REV] [SOURCE]'),
4691 optionalrepo=True)
4693 optionalrepo=True)
4692 def identify(ui, repo, source=None, rev=None,
4694 def identify(ui, repo, source=None, rev=None,
4693 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4695 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4694 """identify the working directory or specified revision
4696 """identify the working directory or specified revision
4695
4697
4696 Print a summary identifying the repository state at REV using one or
4698 Print a summary identifying the repository state at REV using one or
4697 two parent hash identifiers, followed by a "+" if the working
4699 two parent hash identifiers, followed by a "+" if the working
4698 directory has uncommitted changes, the branch name (if not default),
4700 directory has uncommitted changes, the branch name (if not default),
4699 a list of tags, and a list of bookmarks.
4701 a list of tags, and a list of bookmarks.
4700
4702
4701 When REV is not given, print a summary of the current state of the
4703 When REV is not given, print a summary of the current state of the
4702 repository.
4704 repository.
4703
4705
4704 Specifying a path to a repository root or Mercurial bundle will
4706 Specifying a path to a repository root or Mercurial bundle will
4705 cause lookup to operate on that repository/bundle.
4707 cause lookup to operate on that repository/bundle.
4706
4708
4707 .. container:: verbose
4709 .. container:: verbose
4708
4710
4709 Examples:
4711 Examples:
4710
4712
4711 - generate a build identifier for the working directory::
4713 - generate a build identifier for the working directory::
4712
4714
4713 hg id --id > build-id.dat
4715 hg id --id > build-id.dat
4714
4716
4715 - find the revision corresponding to a tag::
4717 - find the revision corresponding to a tag::
4716
4718
4717 hg id -n -r 1.3
4719 hg id -n -r 1.3
4718
4720
4719 - check the most recent revision of a remote repository::
4721 - check the most recent revision of a remote repository::
4720
4722
4721 hg id -r tip http://selenic.com/hg/
4723 hg id -r tip http://selenic.com/hg/
4722
4724
4723 See :hg:`log` for generating more information about specific revisions,
4725 See :hg:`log` for generating more information about specific revisions,
4724 including full hash identifiers.
4726 including full hash identifiers.
4725
4727
4726 Returns 0 if successful.
4728 Returns 0 if successful.
4727 """
4729 """
4728
4730
4729 if not repo and not source:
4731 if not repo and not source:
4730 raise error.Abort(_("there is no Mercurial repository here "
4732 raise error.Abort(_("there is no Mercurial repository here "
4731 "(.hg not found)"))
4733 "(.hg not found)"))
4732
4734
4733 if ui.debugflag:
4735 if ui.debugflag:
4734 hexfunc = hex
4736 hexfunc = hex
4735 else:
4737 else:
4736 hexfunc = short
4738 hexfunc = short
4737 default = not (num or id or branch or tags or bookmarks)
4739 default = not (num or id or branch or tags or bookmarks)
4738 output = []
4740 output = []
4739 revs = []
4741 revs = []
4740
4742
4741 if source:
4743 if source:
4742 source, branches = hg.parseurl(ui.expandpath(source))
4744 source, branches = hg.parseurl(ui.expandpath(source))
4743 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4745 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4744 repo = peer.local()
4746 repo = peer.local()
4745 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4747 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4746
4748
4747 if not repo:
4749 if not repo:
4748 if num or branch or tags:
4750 if num or branch or tags:
4749 raise error.Abort(
4751 raise error.Abort(
4750 _("can't query remote revision number, branch, or tags"))
4752 _("can't query remote revision number, branch, or tags"))
4751 if not rev and revs:
4753 if not rev and revs:
4752 rev = revs[0]
4754 rev = revs[0]
4753 if not rev:
4755 if not rev:
4754 rev = "tip"
4756 rev = "tip"
4755
4757
4756 remoterev = peer.lookup(rev)
4758 remoterev = peer.lookup(rev)
4757 if default or id:
4759 if default or id:
4758 output = [hexfunc(remoterev)]
4760 output = [hexfunc(remoterev)]
4759
4761
4760 def getbms():
4762 def getbms():
4761 bms = []
4763 bms = []
4762
4764
4763 if 'bookmarks' in peer.listkeys('namespaces'):
4765 if 'bookmarks' in peer.listkeys('namespaces'):
4764 hexremoterev = hex(remoterev)
4766 hexremoterev = hex(remoterev)
4765 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4767 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4766 if bmr == hexremoterev]
4768 if bmr == hexremoterev]
4767
4769
4768 return sorted(bms)
4770 return sorted(bms)
4769
4771
4770 if bookmarks:
4772 if bookmarks:
4771 output.extend(getbms())
4773 output.extend(getbms())
4772 elif default and not ui.quiet:
4774 elif default and not ui.quiet:
4773 # multiple bookmarks for a single parent separated by '/'
4775 # multiple bookmarks for a single parent separated by '/'
4774 bm = '/'.join(getbms())
4776 bm = '/'.join(getbms())
4775 if bm:
4777 if bm:
4776 output.append(bm)
4778 output.append(bm)
4777 else:
4779 else:
4778 ctx = scmutil.revsingle(repo, rev, None)
4780 ctx = scmutil.revsingle(repo, rev, None)
4779
4781
4780 if ctx.rev() is None:
4782 if ctx.rev() is None:
4781 ctx = repo[None]
4783 ctx = repo[None]
4782 parents = ctx.parents()
4784 parents = ctx.parents()
4783 taglist = []
4785 taglist = []
4784 for p in parents:
4786 for p in parents:
4785 taglist.extend(p.tags())
4787 taglist.extend(p.tags())
4786
4788
4787 changed = ""
4789 changed = ""
4788 if default or id or num:
4790 if default or id or num:
4789 if (any(repo.status())
4791 if (any(repo.status())
4790 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4792 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4791 changed = '+'
4793 changed = '+'
4792 if default or id:
4794 if default or id:
4793 output = ["%s%s" %
4795 output = ["%s%s" %
4794 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4796 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4795 if num:
4797 if num:
4796 output.append("%s%s" %
4798 output.append("%s%s" %
4797 ('+'.join([str(p.rev()) for p in parents]), changed))
4799 ('+'.join([str(p.rev()) for p in parents]), changed))
4798 else:
4800 else:
4799 if default or id:
4801 if default or id:
4800 output = [hexfunc(ctx.node())]
4802 output = [hexfunc(ctx.node())]
4801 if num:
4803 if num:
4802 output.append(str(ctx.rev()))
4804 output.append(str(ctx.rev()))
4803 taglist = ctx.tags()
4805 taglist = ctx.tags()
4804
4806
4805 if default and not ui.quiet:
4807 if default and not ui.quiet:
4806 b = ctx.branch()
4808 b = ctx.branch()
4807 if b != 'default':
4809 if b != 'default':
4808 output.append("(%s)" % b)
4810 output.append("(%s)" % b)
4809
4811
4810 # multiple tags for a single parent separated by '/'
4812 # multiple tags for a single parent separated by '/'
4811 t = '/'.join(taglist)
4813 t = '/'.join(taglist)
4812 if t:
4814 if t:
4813 output.append(t)
4815 output.append(t)
4814
4816
4815 # multiple bookmarks for a single parent separated by '/'
4817 # multiple bookmarks for a single parent separated by '/'
4816 bm = '/'.join(ctx.bookmarks())
4818 bm = '/'.join(ctx.bookmarks())
4817 if bm:
4819 if bm:
4818 output.append(bm)
4820 output.append(bm)
4819 else:
4821 else:
4820 if branch:
4822 if branch:
4821 output.append(ctx.branch())
4823 output.append(ctx.branch())
4822
4824
4823 if tags:
4825 if tags:
4824 output.extend(taglist)
4826 output.extend(taglist)
4825
4827
4826 if bookmarks:
4828 if bookmarks:
4827 output.extend(ctx.bookmarks())
4829 output.extend(ctx.bookmarks())
4828
4830
4829 ui.write("%s\n" % ' '.join(output))
4831 ui.write("%s\n" % ' '.join(output))
4830
4832
4831 @command('import|patch',
4833 @command('import|patch',
4832 [('p', 'strip', 1,
4834 [('p', 'strip', 1,
4833 _('directory strip option for patch. This has the same '
4835 _('directory strip option for patch. This has the same '
4834 'meaning as the corresponding patch option'), _('NUM')),
4836 'meaning as the corresponding patch option'), _('NUM')),
4835 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4837 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4836 ('e', 'edit', False, _('invoke editor on commit messages')),
4838 ('e', 'edit', False, _('invoke editor on commit messages')),
4837 ('f', 'force', None,
4839 ('f', 'force', None,
4838 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4840 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4839 ('', 'no-commit', None,
4841 ('', 'no-commit', None,
4840 _("don't commit, just update the working directory")),
4842 _("don't commit, just update the working directory")),
4841 ('', 'bypass', None,
4843 ('', 'bypass', None,
4842 _("apply patch without touching the working directory")),
4844 _("apply patch without touching the working directory")),
4843 ('', 'partial', None,
4845 ('', 'partial', None,
4844 _('commit even if some hunks fail')),
4846 _('commit even if some hunks fail')),
4845 ('', 'exact', None,
4847 ('', 'exact', None,
4846 _('abort if patch would apply lossily')),
4848 _('abort if patch would apply lossily')),
4847 ('', 'prefix', '',
4849 ('', 'prefix', '',
4848 _('apply patch to subdirectory'), _('DIR')),
4850 _('apply patch to subdirectory'), _('DIR')),
4849 ('', 'import-branch', None,
4851 ('', 'import-branch', None,
4850 _('use any branch information in patch (implied by --exact)'))] +
4852 _('use any branch information in patch (implied by --exact)'))] +
4851 commitopts + commitopts2 + similarityopts,
4853 commitopts + commitopts2 + similarityopts,
4852 _('[OPTION]... PATCH...'))
4854 _('[OPTION]... PATCH...'))
4853 def import_(ui, repo, patch1=None, *patches, **opts):
4855 def import_(ui, repo, patch1=None, *patches, **opts):
4854 """import an ordered set of patches
4856 """import an ordered set of patches
4855
4857
4856 Import a list of patches and commit them individually (unless
4858 Import a list of patches and commit them individually (unless
4857 --no-commit is specified).
4859 --no-commit is specified).
4858
4860
4859 To read a patch from standard input, use "-" as the patch name. If
4861 To read a patch from standard input, use "-" as the patch name. If
4860 a URL is specified, the patch will be downloaded from there.
4862 a URL is specified, the patch will be downloaded from there.
4861
4863
4862 Import first applies changes to the working directory (unless
4864 Import first applies changes to the working directory (unless
4863 --bypass is specified), import will abort if there are outstanding
4865 --bypass is specified), import will abort if there are outstanding
4864 changes.
4866 changes.
4865
4867
4866 Use --bypass to apply and commit patches directly to the
4868 Use --bypass to apply and commit patches directly to the
4867 repository, without affecting the working directory. Without
4869 repository, without affecting the working directory. Without
4868 --exact, patches will be applied on top of the working directory
4870 --exact, patches will be applied on top of the working directory
4869 parent revision.
4871 parent revision.
4870
4872
4871 You can import a patch straight from a mail message. Even patches
4873 You can import a patch straight from a mail message. Even patches
4872 as attachments work (to use the body part, it must have type
4874 as attachments work (to use the body part, it must have type
4873 text/plain or text/x-patch). From and Subject headers of email
4875 text/plain or text/x-patch). From and Subject headers of email
4874 message are used as default committer and commit message. All
4876 message are used as default committer and commit message. All
4875 text/plain body parts before first diff are added to the commit
4877 text/plain body parts before first diff are added to the commit
4876 message.
4878 message.
4877
4879
4878 If the imported patch was generated by :hg:`export`, user and
4880 If the imported patch was generated by :hg:`export`, user and
4879 description from patch override values from message headers and
4881 description from patch override values from message headers and
4880 body. Values given on command line with -m/--message and -u/--user
4882 body. Values given on command line with -m/--message and -u/--user
4881 override these.
4883 override these.
4882
4884
4883 If --exact is specified, import will set the working directory to
4885 If --exact is specified, import will set the working directory to
4884 the parent of each patch before applying it, and will abort if the
4886 the parent of each patch before applying it, and will abort if the
4885 resulting changeset has a different ID than the one recorded in
4887 resulting changeset has a different ID than the one recorded in
4886 the patch. This will guard against various ways that portable
4888 the patch. This will guard against various ways that portable
4887 patch formats and mail systems might fail to transfer Mercurial
4889 patch formats and mail systems might fail to transfer Mercurial
4888 data or metadata. See :hg:`bundle` for lossless transmission.
4890 data or metadata. See :hg:`bundle` for lossless transmission.
4889
4891
4890 Use --partial to ensure a changeset will be created from the patch
4892 Use --partial to ensure a changeset will be created from the patch
4891 even if some hunks fail to apply. Hunks that fail to apply will be
4893 even if some hunks fail to apply. Hunks that fail to apply will be
4892 written to a <target-file>.rej file. Conflicts can then be resolved
4894 written to a <target-file>.rej file. Conflicts can then be resolved
4893 by hand before :hg:`commit --amend` is run to update the created
4895 by hand before :hg:`commit --amend` is run to update the created
4894 changeset. This flag exists to let people import patches that
4896 changeset. This flag exists to let people import patches that
4895 partially apply without losing the associated metadata (author,
4897 partially apply without losing the associated metadata (author,
4896 date, description, ...).
4898 date, description, ...).
4897
4899
4898 .. note::
4900 .. note::
4899
4901
4900 When no hunks apply cleanly, :hg:`import --partial` will create
4902 When no hunks apply cleanly, :hg:`import --partial` will create
4901 an empty changeset, importing only the patch metadata.
4903 an empty changeset, importing only the patch metadata.
4902
4904
4903 With -s/--similarity, hg will attempt to discover renames and
4905 With -s/--similarity, hg will attempt to discover renames and
4904 copies in the patch in the same way as :hg:`addremove`.
4906 copies in the patch in the same way as :hg:`addremove`.
4905
4907
4906 It is possible to use external patch programs to perform the patch
4908 It is possible to use external patch programs to perform the patch
4907 by setting the ``ui.patch`` configuration option. For the default
4909 by setting the ``ui.patch`` configuration option. For the default
4908 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4910 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4909 See :hg:`help config` for more information about configuration
4911 See :hg:`help config` for more information about configuration
4910 files and how to use these options.
4912 files and how to use these options.
4911
4913
4912 See :hg:`help dates` for a list of formats valid for -d/--date.
4914 See :hg:`help dates` for a list of formats valid for -d/--date.
4913
4915
4914 .. container:: verbose
4916 .. container:: verbose
4915
4917
4916 Examples:
4918 Examples:
4917
4919
4918 - import a traditional patch from a website and detect renames::
4920 - import a traditional patch from a website and detect renames::
4919
4921
4920 hg import -s 80 http://example.com/bugfix.patch
4922 hg import -s 80 http://example.com/bugfix.patch
4921
4923
4922 - import a changeset from an hgweb server::
4924 - import a changeset from an hgweb server::
4923
4925
4924 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4926 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4925
4927
4926 - import all the patches in an Unix-style mbox::
4928 - import all the patches in an Unix-style mbox::
4927
4929
4928 hg import incoming-patches.mbox
4930 hg import incoming-patches.mbox
4929
4931
4930 - attempt to exactly restore an exported changeset (not always
4932 - attempt to exactly restore an exported changeset (not always
4931 possible)::
4933 possible)::
4932
4934
4933 hg import --exact proposed-fix.patch
4935 hg import --exact proposed-fix.patch
4934
4936
4935 - use an external tool to apply a patch which is too fuzzy for
4937 - use an external tool to apply a patch which is too fuzzy for
4936 the default internal tool.
4938 the default internal tool.
4937
4939
4938 hg import --config ui.patch="patch --merge" fuzzy.patch
4940 hg import --config ui.patch="patch --merge" fuzzy.patch
4939
4941
4940 - change the default fuzzing from 2 to a less strict 7
4942 - change the default fuzzing from 2 to a less strict 7
4941
4943
4942 hg import --config ui.fuzz=7 fuzz.patch
4944 hg import --config ui.fuzz=7 fuzz.patch
4943
4945
4944 Returns 0 on success, 1 on partial success (see --partial).
4946 Returns 0 on success, 1 on partial success (see --partial).
4945 """
4947 """
4946
4948
4947 if not patch1:
4949 if not patch1:
4948 raise error.Abort(_('need at least one patch to import'))
4950 raise error.Abort(_('need at least one patch to import'))
4949
4951
4950 patches = (patch1,) + patches
4952 patches = (patch1,) + patches
4951
4953
4952 date = opts.get('date')
4954 date = opts.get('date')
4953 if date:
4955 if date:
4954 opts['date'] = util.parsedate(date)
4956 opts['date'] = util.parsedate(date)
4955
4957
4956 exact = opts.get('exact')
4958 exact = opts.get('exact')
4957 update = not opts.get('bypass')
4959 update = not opts.get('bypass')
4958 if not update and opts.get('no_commit'):
4960 if not update and opts.get('no_commit'):
4959 raise error.Abort(_('cannot use --no-commit with --bypass'))
4961 raise error.Abort(_('cannot use --no-commit with --bypass'))
4960 try:
4962 try:
4961 sim = float(opts.get('similarity') or 0)
4963 sim = float(opts.get('similarity') or 0)
4962 except ValueError:
4964 except ValueError:
4963 raise error.Abort(_('similarity must be a number'))
4965 raise error.Abort(_('similarity must be a number'))
4964 if sim < 0 or sim > 100:
4966 if sim < 0 or sim > 100:
4965 raise error.Abort(_('similarity must be between 0 and 100'))
4967 raise error.Abort(_('similarity must be between 0 and 100'))
4966 if sim and not update:
4968 if sim and not update:
4967 raise error.Abort(_('cannot use --similarity with --bypass'))
4969 raise error.Abort(_('cannot use --similarity with --bypass'))
4968 if exact:
4970 if exact:
4969 if opts.get('edit'):
4971 if opts.get('edit'):
4970 raise error.Abort(_('cannot use --exact with --edit'))
4972 raise error.Abort(_('cannot use --exact with --edit'))
4971 if opts.get('prefix'):
4973 if opts.get('prefix'):
4972 raise error.Abort(_('cannot use --exact with --prefix'))
4974 raise error.Abort(_('cannot use --exact with --prefix'))
4973
4975
4974 base = opts["base"]
4976 base = opts["base"]
4975 wlock = dsguard = lock = tr = None
4977 wlock = dsguard = lock = tr = None
4976 msgs = []
4978 msgs = []
4977 ret = 0
4979 ret = 0
4978
4980
4979
4981
4980 try:
4982 try:
4981 wlock = repo.wlock()
4983 wlock = repo.wlock()
4982
4984
4983 if update:
4985 if update:
4984 cmdutil.checkunfinished(repo)
4986 cmdutil.checkunfinished(repo)
4985 if (exact or not opts.get('force')):
4987 if (exact or not opts.get('force')):
4986 cmdutil.bailifchanged(repo)
4988 cmdutil.bailifchanged(repo)
4987
4989
4988 if not opts.get('no_commit'):
4990 if not opts.get('no_commit'):
4989 lock = repo.lock()
4991 lock = repo.lock()
4990 tr = repo.transaction('import')
4992 tr = repo.transaction('import')
4991 else:
4993 else:
4992 dsguard = cmdutil.dirstateguard(repo, 'import')
4994 dsguard = cmdutil.dirstateguard(repo, 'import')
4993 parents = repo[None].parents()
4995 parents = repo[None].parents()
4994 for patchurl in patches:
4996 for patchurl in patches:
4995 if patchurl == '-':
4997 if patchurl == '-':
4996 ui.status(_('applying patch from stdin\n'))
4998 ui.status(_('applying patch from stdin\n'))
4997 patchfile = ui.fin
4999 patchfile = ui.fin
4998 patchurl = 'stdin' # for error message
5000 patchurl = 'stdin' # for error message
4999 else:
5001 else:
5000 patchurl = os.path.join(base, patchurl)
5002 patchurl = os.path.join(base, patchurl)
5001 ui.status(_('applying %s\n') % patchurl)
5003 ui.status(_('applying %s\n') % patchurl)
5002 patchfile = hg.openpath(ui, patchurl)
5004 patchfile = hg.openpath(ui, patchurl)
5003
5005
5004 haspatch = False
5006 haspatch = False
5005 for hunk in patch.split(patchfile):
5007 for hunk in patch.split(patchfile):
5006 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
5008 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
5007 parents, opts,
5009 parents, opts,
5008 msgs, hg.clean)
5010 msgs, hg.clean)
5009 if msg:
5011 if msg:
5010 haspatch = True
5012 haspatch = True
5011 ui.note(msg + '\n')
5013 ui.note(msg + '\n')
5012 if update or exact:
5014 if update or exact:
5013 parents = repo[None].parents()
5015 parents = repo[None].parents()
5014 else:
5016 else:
5015 parents = [repo[node]]
5017 parents = [repo[node]]
5016 if rej:
5018 if rej:
5017 ui.write_err(_("patch applied partially\n"))
5019 ui.write_err(_("patch applied partially\n"))
5018 ui.write_err(_("(fix the .rej files and run "
5020 ui.write_err(_("(fix the .rej files and run "
5019 "`hg commit --amend`)\n"))
5021 "`hg commit --amend`)\n"))
5020 ret = 1
5022 ret = 1
5021 break
5023 break
5022
5024
5023 if not haspatch:
5025 if not haspatch:
5024 raise error.Abort(_('%s: no diffs found') % patchurl)
5026 raise error.Abort(_('%s: no diffs found') % patchurl)
5025
5027
5026 if tr:
5028 if tr:
5027 tr.close()
5029 tr.close()
5028 if msgs:
5030 if msgs:
5029 repo.savecommitmessage('\n* * *\n'.join(msgs))
5031 repo.savecommitmessage('\n* * *\n'.join(msgs))
5030 if dsguard:
5032 if dsguard:
5031 dsguard.close()
5033 dsguard.close()
5032 return ret
5034 return ret
5033 finally:
5035 finally:
5034 if tr:
5036 if tr:
5035 tr.release()
5037 tr.release()
5036 release(lock, dsguard, wlock)
5038 release(lock, dsguard, wlock)
5037
5039
5038 @command('incoming|in',
5040 @command('incoming|in',
5039 [('f', 'force', None,
5041 [('f', 'force', None,
5040 _('run even if remote repository is unrelated')),
5042 _('run even if remote repository is unrelated')),
5041 ('n', 'newest-first', None, _('show newest record first')),
5043 ('n', 'newest-first', None, _('show newest record first')),
5042 ('', 'bundle', '',
5044 ('', 'bundle', '',
5043 _('file to store the bundles into'), _('FILE')),
5045 _('file to store the bundles into'), _('FILE')),
5044 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5046 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5045 ('B', 'bookmarks', False, _("compare bookmarks")),
5047 ('B', 'bookmarks', False, _("compare bookmarks")),
5046 ('b', 'branch', [],
5048 ('b', 'branch', [],
5047 _('a specific branch you would like to pull'), _('BRANCH')),
5049 _('a specific branch you would like to pull'), _('BRANCH')),
5048 ] + logopts + remoteopts + subrepoopts,
5050 ] + logopts + remoteopts + subrepoopts,
5049 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
5051 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
5050 def incoming(ui, repo, source="default", **opts):
5052 def incoming(ui, repo, source="default", **opts):
5051 """show new changesets found in source
5053 """show new changesets found in source
5052
5054
5053 Show new changesets found in the specified path/URL or the default
5055 Show new changesets found in the specified path/URL or the default
5054 pull location. These are the changesets that would have been pulled
5056 pull location. These are the changesets that would have been pulled
5055 if a pull at the time you issued this command.
5057 if a pull at the time you issued this command.
5056
5058
5057 See pull for valid source format details.
5059 See pull for valid source format details.
5058
5060
5059 .. container:: verbose
5061 .. container:: verbose
5060
5062
5061 With -B/--bookmarks, the result of bookmark comparison between
5063 With -B/--bookmarks, the result of bookmark comparison between
5062 local and remote repositories is displayed. With -v/--verbose,
5064 local and remote repositories is displayed. With -v/--verbose,
5063 status is also displayed for each bookmark like below::
5065 status is also displayed for each bookmark like below::
5064
5066
5065 BM1 01234567890a added
5067 BM1 01234567890a added
5066 BM2 1234567890ab advanced
5068 BM2 1234567890ab advanced
5067 BM3 234567890abc diverged
5069 BM3 234567890abc diverged
5068 BM4 34567890abcd changed
5070 BM4 34567890abcd changed
5069
5071
5070 The action taken locally when pulling depends on the
5072 The action taken locally when pulling depends on the
5071 status of each bookmark:
5073 status of each bookmark:
5072
5074
5073 :``added``: pull will create it
5075 :``added``: pull will create it
5074 :``advanced``: pull will update it
5076 :``advanced``: pull will update it
5075 :``diverged``: pull will create a divergent bookmark
5077 :``diverged``: pull will create a divergent bookmark
5076 :``changed``: result depends on remote changesets
5078 :``changed``: result depends on remote changesets
5077
5079
5078 From the point of view of pulling behavior, bookmark
5080 From the point of view of pulling behavior, bookmark
5079 existing only in the remote repository are treated as ``added``,
5081 existing only in the remote repository are treated as ``added``,
5080 even if it is in fact locally deleted.
5082 even if it is in fact locally deleted.
5081
5083
5082 .. container:: verbose
5084 .. container:: verbose
5083
5085
5084 For remote repository, using --bundle avoids downloading the
5086 For remote repository, using --bundle avoids downloading the
5085 changesets twice if the incoming is followed by a pull.
5087 changesets twice if the incoming is followed by a pull.
5086
5088
5087 Examples:
5089 Examples:
5088
5090
5089 - show incoming changes with patches and full description::
5091 - show incoming changes with patches and full description::
5090
5092
5091 hg incoming -vp
5093 hg incoming -vp
5092
5094
5093 - show incoming changes excluding merges, store a bundle::
5095 - show incoming changes excluding merges, store a bundle::
5094
5096
5095 hg in -vpM --bundle incoming.hg
5097 hg in -vpM --bundle incoming.hg
5096 hg pull incoming.hg
5098 hg pull incoming.hg
5097
5099
5098 - briefly list changes inside a bundle::
5100 - briefly list changes inside a bundle::
5099
5101
5100 hg in changes.hg -T "{desc|firstline}\\n"
5102 hg in changes.hg -T "{desc|firstline}\\n"
5101
5103
5102 Returns 0 if there are incoming changes, 1 otherwise.
5104 Returns 0 if there are incoming changes, 1 otherwise.
5103 """
5105 """
5104 if opts.get('graph'):
5106 if opts.get('graph'):
5105 cmdutil.checkunsupportedgraphflags([], opts)
5107 cmdutil.checkunsupportedgraphflags([], opts)
5106 def display(other, chlist, displayer):
5108 def display(other, chlist, displayer):
5107 revdag = cmdutil.graphrevs(other, chlist, opts)
5109 revdag = cmdutil.graphrevs(other, chlist, opts)
5108 cmdutil.displaygraph(ui, repo, revdag, displayer,
5110 cmdutil.displaygraph(ui, repo, revdag, displayer,
5109 graphmod.asciiedges)
5111 graphmod.asciiedges)
5110
5112
5111 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5113 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5112 return 0
5114 return 0
5113
5115
5114 if opts.get('bundle') and opts.get('subrepos'):
5116 if opts.get('bundle') and opts.get('subrepos'):
5115 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5117 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5116
5118
5117 if opts.get('bookmarks'):
5119 if opts.get('bookmarks'):
5118 source, branches = hg.parseurl(ui.expandpath(source),
5120 source, branches = hg.parseurl(ui.expandpath(source),
5119 opts.get('branch'))
5121 opts.get('branch'))
5120 other = hg.peer(repo, opts, source)
5122 other = hg.peer(repo, opts, source)
5121 if 'bookmarks' not in other.listkeys('namespaces'):
5123 if 'bookmarks' not in other.listkeys('namespaces'):
5122 ui.warn(_("remote doesn't support bookmarks\n"))
5124 ui.warn(_("remote doesn't support bookmarks\n"))
5123 return 0
5125 return 0
5124 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5126 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5125 return bookmarks.incoming(ui, repo, other)
5127 return bookmarks.incoming(ui, repo, other)
5126
5128
5127 repo._subtoppath = ui.expandpath(source)
5129 repo._subtoppath = ui.expandpath(source)
5128 try:
5130 try:
5129 return hg.incoming(ui, repo, source, opts)
5131 return hg.incoming(ui, repo, source, opts)
5130 finally:
5132 finally:
5131 del repo._subtoppath
5133 del repo._subtoppath
5132
5134
5133
5135
5134 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5136 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5135 norepo=True)
5137 norepo=True)
5136 def init(ui, dest=".", **opts):
5138 def init(ui, dest=".", **opts):
5137 """create a new repository in the given directory
5139 """create a new repository in the given directory
5138
5140
5139 Initialize a new repository in the given directory. If the given
5141 Initialize a new repository in the given directory. If the given
5140 directory does not exist, it will be created.
5142 directory does not exist, it will be created.
5141
5143
5142 If no directory is given, the current directory is used.
5144 If no directory is given, the current directory is used.
5143
5145
5144 It is possible to specify an ``ssh://`` URL as the destination.
5146 It is possible to specify an ``ssh://`` URL as the destination.
5145 See :hg:`help urls` for more information.
5147 See :hg:`help urls` for more information.
5146
5148
5147 Returns 0 on success.
5149 Returns 0 on success.
5148 """
5150 """
5149 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5151 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5150
5152
5151 @command('locate',
5153 @command('locate',
5152 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5154 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5153 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5155 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5154 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5156 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5155 ] + walkopts,
5157 ] + walkopts,
5156 _('[OPTION]... [PATTERN]...'))
5158 _('[OPTION]... [PATTERN]...'))
5157 def locate(ui, repo, *pats, **opts):
5159 def locate(ui, repo, *pats, **opts):
5158 """locate files matching specific patterns (DEPRECATED)
5160 """locate files matching specific patterns (DEPRECATED)
5159
5161
5160 Print files under Mercurial control in the working directory whose
5162 Print files under Mercurial control in the working directory whose
5161 names match the given patterns.
5163 names match the given patterns.
5162
5164
5163 By default, this command searches all directories in the working
5165 By default, this command searches all directories in the working
5164 directory. To search just the current directory and its
5166 directory. To search just the current directory and its
5165 subdirectories, use "--include .".
5167 subdirectories, use "--include .".
5166
5168
5167 If no patterns are given to match, this command prints the names
5169 If no patterns are given to match, this command prints the names
5168 of all files under Mercurial control in the working directory.
5170 of all files under Mercurial control in the working directory.
5169
5171
5170 If you want to feed the output of this command into the "xargs"
5172 If you want to feed the output of this command into the "xargs"
5171 command, use the -0 option to both this command and "xargs". This
5173 command, use the -0 option to both this command and "xargs". This
5172 will avoid the problem of "xargs" treating single filenames that
5174 will avoid the problem of "xargs" treating single filenames that
5173 contain whitespace as multiple filenames.
5175 contain whitespace as multiple filenames.
5174
5176
5175 See :hg:`help files` for a more versatile command.
5177 See :hg:`help files` for a more versatile command.
5176
5178
5177 Returns 0 if a match is found, 1 otherwise.
5179 Returns 0 if a match is found, 1 otherwise.
5178 """
5180 """
5179 if opts.get('print0'):
5181 if opts.get('print0'):
5180 end = '\0'
5182 end = '\0'
5181 else:
5183 else:
5182 end = '\n'
5184 end = '\n'
5183 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5185 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5184
5186
5185 ret = 1
5187 ret = 1
5186 ctx = repo[rev]
5188 ctx = repo[rev]
5187 m = scmutil.match(ctx, pats, opts, default='relglob',
5189 m = scmutil.match(ctx, pats, opts, default='relglob',
5188 badfn=lambda x, y: False)
5190 badfn=lambda x, y: False)
5189
5191
5190 for abs in ctx.matches(m):
5192 for abs in ctx.matches(m):
5191 if opts.get('fullpath'):
5193 if opts.get('fullpath'):
5192 ui.write(repo.wjoin(abs), end)
5194 ui.write(repo.wjoin(abs), end)
5193 else:
5195 else:
5194 ui.write(((pats and m.rel(abs)) or abs), end)
5196 ui.write(((pats and m.rel(abs)) or abs), end)
5195 ret = 0
5197 ret = 0
5196
5198
5197 return ret
5199 return ret
5198
5200
5199 @command('^log|history',
5201 @command('^log|history',
5200 [('f', 'follow', None,
5202 [('f', 'follow', None,
5201 _('follow changeset history, or file history across copies and renames')),
5203 _('follow changeset history, or file history across copies and renames')),
5202 ('', 'follow-first', None,
5204 ('', 'follow-first', None,
5203 _('only follow the first parent of merge changesets (DEPRECATED)')),
5205 _('only follow the first parent of merge changesets (DEPRECATED)')),
5204 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5206 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5205 ('C', 'copies', None, _('show copied files')),
5207 ('C', 'copies', None, _('show copied files')),
5206 ('k', 'keyword', [],
5208 ('k', 'keyword', [],
5207 _('do case-insensitive search for a given text'), _('TEXT')),
5209 _('do case-insensitive search for a given text'), _('TEXT')),
5208 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5210 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5209 ('', 'removed', None, _('include revisions where files were removed')),
5211 ('', 'removed', None, _('include revisions where files were removed')),
5210 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5212 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5211 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5213 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5212 ('', 'only-branch', [],
5214 ('', 'only-branch', [],
5213 _('show only changesets within the given named branch (DEPRECATED)'),
5215 _('show only changesets within the given named branch (DEPRECATED)'),
5214 _('BRANCH')),
5216 _('BRANCH')),
5215 ('b', 'branch', [],
5217 ('b', 'branch', [],
5216 _('show changesets within the given named branch'), _('BRANCH')),
5218 _('show changesets within the given named branch'), _('BRANCH')),
5217 ('P', 'prune', [],
5219 ('P', 'prune', [],
5218 _('do not display revision or any of its ancestors'), _('REV')),
5220 _('do not display revision or any of its ancestors'), _('REV')),
5219 ] + logopts + walkopts,
5221 ] + logopts + walkopts,
5220 _('[OPTION]... [FILE]'),
5222 _('[OPTION]... [FILE]'),
5221 inferrepo=True)
5223 inferrepo=True)
5222 def log(ui, repo, *pats, **opts):
5224 def log(ui, repo, *pats, **opts):
5223 """show revision history of entire repository or files
5225 """show revision history of entire repository or files
5224
5226
5225 Print the revision history of the specified files or the entire
5227 Print the revision history of the specified files or the entire
5226 project.
5228 project.
5227
5229
5228 If no revision range is specified, the default is ``tip:0`` unless
5230 If no revision range is specified, the default is ``tip:0`` unless
5229 --follow is set, in which case the working directory parent is
5231 --follow is set, in which case the working directory parent is
5230 used as the starting revision.
5232 used as the starting revision.
5231
5233
5232 File history is shown without following rename or copy history of
5234 File history is shown without following rename or copy history of
5233 files. Use -f/--follow with a filename to follow history across
5235 files. Use -f/--follow with a filename to follow history across
5234 renames and copies. --follow without a filename will only show
5236 renames and copies. --follow without a filename will only show
5235 ancestors or descendants of the starting revision.
5237 ancestors or descendants of the starting revision.
5236
5238
5237 By default this command prints revision number and changeset id,
5239 By default this command prints revision number and changeset id,
5238 tags, non-trivial parents, user, date and time, and a summary for
5240 tags, non-trivial parents, user, date and time, and a summary for
5239 each commit. When the -v/--verbose switch is used, the list of
5241 each commit. When the -v/--verbose switch is used, the list of
5240 changed files and full commit message are shown.
5242 changed files and full commit message are shown.
5241
5243
5242 With --graph the revisions are shown as an ASCII art DAG with the most
5244 With --graph the revisions are shown as an ASCII art DAG with the most
5243 recent changeset at the top.
5245 recent changeset at the top.
5244 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5246 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5245 and '+' represents a fork where the changeset from the lines below is a
5247 and '+' represents a fork where the changeset from the lines below is a
5246 parent of the 'o' merge on the same line.
5248 parent of the 'o' merge on the same line.
5247
5249
5248 .. note::
5250 .. note::
5249
5251
5250 :hg:`log --patch` may generate unexpected diff output for merge
5252 :hg:`log --patch` may generate unexpected diff output for merge
5251 changesets, as it will only compare the merge changeset against
5253 changesets, as it will only compare the merge changeset against
5252 its first parent. Also, only files different from BOTH parents
5254 its first parent. Also, only files different from BOTH parents
5253 will appear in files:.
5255 will appear in files:.
5254
5256
5255 .. note::
5257 .. note::
5256
5258
5257 For performance reasons, :hg:`log FILE` may omit duplicate changes
5259 For performance reasons, :hg:`log FILE` may omit duplicate changes
5258 made on branches and will not show removals or mode changes. To
5260 made on branches and will not show removals or mode changes. To
5259 see all such changes, use the --removed switch.
5261 see all such changes, use the --removed switch.
5260
5262
5261 .. container:: verbose
5263 .. container:: verbose
5262
5264
5263 Some examples:
5265 Some examples:
5264
5266
5265 - changesets with full descriptions and file lists::
5267 - changesets with full descriptions and file lists::
5266
5268
5267 hg log -v
5269 hg log -v
5268
5270
5269 - changesets ancestral to the working directory::
5271 - changesets ancestral to the working directory::
5270
5272
5271 hg log -f
5273 hg log -f
5272
5274
5273 - last 10 commits on the current branch::
5275 - last 10 commits on the current branch::
5274
5276
5275 hg log -l 10 -b .
5277 hg log -l 10 -b .
5276
5278
5277 - changesets showing all modifications of a file, including removals::
5279 - changesets showing all modifications of a file, including removals::
5278
5280
5279 hg log --removed file.c
5281 hg log --removed file.c
5280
5282
5281 - all changesets that touch a directory, with diffs, excluding merges::
5283 - all changesets that touch a directory, with diffs, excluding merges::
5282
5284
5283 hg log -Mp lib/
5285 hg log -Mp lib/
5284
5286
5285 - all revision numbers that match a keyword::
5287 - all revision numbers that match a keyword::
5286
5288
5287 hg log -k bug --template "{rev}\\n"
5289 hg log -k bug --template "{rev}\\n"
5288
5290
5289 - the full hash identifier of the working directory parent::
5291 - the full hash identifier of the working directory parent::
5290
5292
5291 hg log -r . --template "{node}\\n"
5293 hg log -r . --template "{node}\\n"
5292
5294
5293 - list available log templates::
5295 - list available log templates::
5294
5296
5295 hg log -T list
5297 hg log -T list
5296
5298
5297 - check if a given changeset is included in a tagged release::
5299 - check if a given changeset is included in a tagged release::
5298
5300
5299 hg log -r "a21ccf and ancestor(1.9)"
5301 hg log -r "a21ccf and ancestor(1.9)"
5300
5302
5301 - find all changesets by some user in a date range::
5303 - find all changesets by some user in a date range::
5302
5304
5303 hg log -k alice -d "may 2008 to jul 2008"
5305 hg log -k alice -d "may 2008 to jul 2008"
5304
5306
5305 - summary of all changesets after the last tag::
5307 - summary of all changesets after the last tag::
5306
5308
5307 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5309 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5308
5310
5309 See :hg:`help dates` for a list of formats valid for -d/--date.
5311 See :hg:`help dates` for a list of formats valid for -d/--date.
5310
5312
5311 See :hg:`help revisions` and :hg:`help revsets` for more about
5313 See :hg:`help revisions` and :hg:`help revsets` for more about
5312 specifying and ordering revisions.
5314 specifying and ordering revisions.
5313
5315
5314 See :hg:`help templates` for more about pre-packaged styles and
5316 See :hg:`help templates` for more about pre-packaged styles and
5315 specifying custom templates.
5317 specifying custom templates.
5316
5318
5317 Returns 0 on success.
5319 Returns 0 on success.
5318
5320
5319 """
5321 """
5320 if opts.get('follow') and opts.get('rev'):
5322 if opts.get('follow') and opts.get('rev'):
5321 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5323 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5322 del opts['follow']
5324 del opts['follow']
5323
5325
5324 if opts.get('graph'):
5326 if opts.get('graph'):
5325 return cmdutil.graphlog(ui, repo, *pats, **opts)
5327 return cmdutil.graphlog(ui, repo, *pats, **opts)
5326
5328
5327 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5329 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5328 limit = cmdutil.loglimit(opts)
5330 limit = cmdutil.loglimit(opts)
5329 count = 0
5331 count = 0
5330
5332
5331 getrenamed = None
5333 getrenamed = None
5332 if opts.get('copies'):
5334 if opts.get('copies'):
5333 endrev = None
5335 endrev = None
5334 if opts.get('rev'):
5336 if opts.get('rev'):
5335 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5337 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5336 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5338 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5337
5339
5338 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5340 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5339 for rev in revs:
5341 for rev in revs:
5340 if count == limit:
5342 if count == limit:
5341 break
5343 break
5342 ctx = repo[rev]
5344 ctx = repo[rev]
5343 copies = None
5345 copies = None
5344 if getrenamed is not None and rev:
5346 if getrenamed is not None and rev:
5345 copies = []
5347 copies = []
5346 for fn in ctx.files():
5348 for fn in ctx.files():
5347 rename = getrenamed(fn, rev)
5349 rename = getrenamed(fn, rev)
5348 if rename:
5350 if rename:
5349 copies.append((fn, rename[0]))
5351 copies.append((fn, rename[0]))
5350 if filematcher:
5352 if filematcher:
5351 revmatchfn = filematcher(ctx.rev())
5353 revmatchfn = filematcher(ctx.rev())
5352 else:
5354 else:
5353 revmatchfn = None
5355 revmatchfn = None
5354 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5356 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5355 if displayer.flush(ctx):
5357 if displayer.flush(ctx):
5356 count += 1
5358 count += 1
5357
5359
5358 displayer.close()
5360 displayer.close()
5359
5361
5360 @command('manifest',
5362 @command('manifest',
5361 [('r', 'rev', '', _('revision to display'), _('REV')),
5363 [('r', 'rev', '', _('revision to display'), _('REV')),
5362 ('', 'all', False, _("list files from all revisions"))]
5364 ('', 'all', False, _("list files from all revisions"))]
5363 + formatteropts,
5365 + formatteropts,
5364 _('[-r REV]'))
5366 _('[-r REV]'))
5365 def manifest(ui, repo, node=None, rev=None, **opts):
5367 def manifest(ui, repo, node=None, rev=None, **opts):
5366 """output the current or given revision of the project manifest
5368 """output the current or given revision of the project manifest
5367
5369
5368 Print a list of version controlled files for the given revision.
5370 Print a list of version controlled files for the given revision.
5369 If no revision is given, the first parent of the working directory
5371 If no revision is given, the first parent of the working directory
5370 is used, or the null revision if no revision is checked out.
5372 is used, or the null revision if no revision is checked out.
5371
5373
5372 With -v, print file permissions, symlink and executable bits.
5374 With -v, print file permissions, symlink and executable bits.
5373 With --debug, print file revision hashes.
5375 With --debug, print file revision hashes.
5374
5376
5375 If option --all is specified, the list of all files from all revisions
5377 If option --all is specified, the list of all files from all revisions
5376 is printed. This includes deleted and renamed files.
5378 is printed. This includes deleted and renamed files.
5377
5379
5378 Returns 0 on success.
5380 Returns 0 on success.
5379 """
5381 """
5380
5382
5381 fm = ui.formatter('manifest', opts)
5383 fm = ui.formatter('manifest', opts)
5382
5384
5383 if opts.get('all'):
5385 if opts.get('all'):
5384 if rev or node:
5386 if rev or node:
5385 raise error.Abort(_("can't specify a revision with --all"))
5387 raise error.Abort(_("can't specify a revision with --all"))
5386
5388
5387 res = []
5389 res = []
5388 prefix = "data/"
5390 prefix = "data/"
5389 suffix = ".i"
5391 suffix = ".i"
5390 plen = len(prefix)
5392 plen = len(prefix)
5391 slen = len(suffix)
5393 slen = len(suffix)
5392 with repo.lock():
5394 with repo.lock():
5393 for fn, b, size in repo.store.datafiles():
5395 for fn, b, size in repo.store.datafiles():
5394 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5396 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5395 res.append(fn[plen:-slen])
5397 res.append(fn[plen:-slen])
5396 for f in res:
5398 for f in res:
5397 fm.startitem()
5399 fm.startitem()
5398 fm.write("path", '%s\n', f)
5400 fm.write("path", '%s\n', f)
5399 fm.end()
5401 fm.end()
5400 return
5402 return
5401
5403
5402 if rev and node:
5404 if rev and node:
5403 raise error.Abort(_("please specify just one revision"))
5405 raise error.Abort(_("please specify just one revision"))
5404
5406
5405 if not node:
5407 if not node:
5406 node = rev
5408 node = rev
5407
5409
5408 char = {'l': '@', 'x': '*', '': ''}
5410 char = {'l': '@', 'x': '*', '': ''}
5409 mode = {'l': '644', 'x': '755', '': '644'}
5411 mode = {'l': '644', 'x': '755', '': '644'}
5410 ctx = scmutil.revsingle(repo, node)
5412 ctx = scmutil.revsingle(repo, node)
5411 mf = ctx.manifest()
5413 mf = ctx.manifest()
5412 for f in ctx:
5414 for f in ctx:
5413 fm.startitem()
5415 fm.startitem()
5414 fl = ctx[f].flags()
5416 fl = ctx[f].flags()
5415 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5417 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5416 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5418 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5417 fm.write('path', '%s\n', f)
5419 fm.write('path', '%s\n', f)
5418 fm.end()
5420 fm.end()
5419
5421
5420 @command('^merge',
5422 @command('^merge',
5421 [('f', 'force', None,
5423 [('f', 'force', None,
5422 _('force a merge including outstanding changes (DEPRECATED)')),
5424 _('force a merge including outstanding changes (DEPRECATED)')),
5423 ('r', 'rev', '', _('revision to merge'), _('REV')),
5425 ('r', 'rev', '', _('revision to merge'), _('REV')),
5424 ('P', 'preview', None,
5426 ('P', 'preview', None,
5425 _('review revisions to merge (no merge is performed)'))
5427 _('review revisions to merge (no merge is performed)'))
5426 ] + mergetoolopts,
5428 ] + mergetoolopts,
5427 _('[-P] [[-r] REV]'))
5429 _('[-P] [[-r] REV]'))
5428 def merge(ui, repo, node=None, **opts):
5430 def merge(ui, repo, node=None, **opts):
5429 """merge another revision into working directory
5431 """merge another revision into working directory
5430
5432
5431 The current working directory is updated with all changes made in
5433 The current working directory is updated with all changes made in
5432 the requested revision since the last common predecessor revision.
5434 the requested revision since the last common predecessor revision.
5433
5435
5434 Files that changed between either parent are marked as changed for
5436 Files that changed between either parent are marked as changed for
5435 the next commit and a commit must be performed before any further
5437 the next commit and a commit must be performed before any further
5436 updates to the repository are allowed. The next commit will have
5438 updates to the repository are allowed. The next commit will have
5437 two parents.
5439 two parents.
5438
5440
5439 ``--tool`` can be used to specify the merge tool used for file
5441 ``--tool`` can be used to specify the merge tool used for file
5440 merges. It overrides the HGMERGE environment variable and your
5442 merges. It overrides the HGMERGE environment variable and your
5441 configuration files. See :hg:`help merge-tools` for options.
5443 configuration files. See :hg:`help merge-tools` for options.
5442
5444
5443 If no revision is specified, the working directory's parent is a
5445 If no revision is specified, the working directory's parent is a
5444 head revision, and the current branch contains exactly one other
5446 head revision, and the current branch contains exactly one other
5445 head, the other head is merged with by default. Otherwise, an
5447 head, the other head is merged with by default. Otherwise, an
5446 explicit revision with which to merge with must be provided.
5448 explicit revision with which to merge with must be provided.
5447
5449
5448 See :hg:`help resolve` for information on handling file conflicts.
5450 See :hg:`help resolve` for information on handling file conflicts.
5449
5451
5450 To undo an uncommitted merge, use :hg:`update --clean .` which
5452 To undo an uncommitted merge, use :hg:`update --clean .` which
5451 will check out a clean copy of the original merge parent, losing
5453 will check out a clean copy of the original merge parent, losing
5452 all changes.
5454 all changes.
5453
5455
5454 Returns 0 on success, 1 if there are unresolved files.
5456 Returns 0 on success, 1 if there are unresolved files.
5455 """
5457 """
5456
5458
5457 if opts.get('rev') and node:
5459 if opts.get('rev') and node:
5458 raise error.Abort(_("please specify just one revision"))
5460 raise error.Abort(_("please specify just one revision"))
5459 if not node:
5461 if not node:
5460 node = opts.get('rev')
5462 node = opts.get('rev')
5461
5463
5462 if node:
5464 if node:
5463 node = scmutil.revsingle(repo, node).node()
5465 node = scmutil.revsingle(repo, node).node()
5464
5466
5465 if not node:
5467 if not node:
5466 node = repo[destutil.destmerge(repo)].node()
5468 node = repo[destutil.destmerge(repo)].node()
5467
5469
5468 if opts.get('preview'):
5470 if opts.get('preview'):
5469 # find nodes that are ancestors of p2 but not of p1
5471 # find nodes that are ancestors of p2 but not of p1
5470 p1 = repo.lookup('.')
5472 p1 = repo.lookup('.')
5471 p2 = repo.lookup(node)
5473 p2 = repo.lookup(node)
5472 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5474 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5473
5475
5474 displayer = cmdutil.show_changeset(ui, repo, opts)
5476 displayer = cmdutil.show_changeset(ui, repo, opts)
5475 for node in nodes:
5477 for node in nodes:
5476 displayer.show(repo[node])
5478 displayer.show(repo[node])
5477 displayer.close()
5479 displayer.close()
5478 return 0
5480 return 0
5479
5481
5480 try:
5482 try:
5481 # ui.forcemerge is an internal variable, do not document
5483 # ui.forcemerge is an internal variable, do not document
5482 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5484 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5483 force = opts.get('force')
5485 force = opts.get('force')
5484 labels = ['working copy', 'merge rev']
5486 labels = ['working copy', 'merge rev']
5485 return hg.merge(repo, node, force=force, mergeforce=force,
5487 return hg.merge(repo, node, force=force, mergeforce=force,
5486 labels=labels)
5488 labels=labels)
5487 finally:
5489 finally:
5488 ui.setconfig('ui', 'forcemerge', '', 'merge')
5490 ui.setconfig('ui', 'forcemerge', '', 'merge')
5489
5491
5490 @command('outgoing|out',
5492 @command('outgoing|out',
5491 [('f', 'force', None, _('run even when the destination is unrelated')),
5493 [('f', 'force', None, _('run even when the destination is unrelated')),
5492 ('r', 'rev', [],
5494 ('r', 'rev', [],
5493 _('a changeset intended to be included in the destination'), _('REV')),
5495 _('a changeset intended to be included in the destination'), _('REV')),
5494 ('n', 'newest-first', None, _('show newest record first')),
5496 ('n', 'newest-first', None, _('show newest record first')),
5495 ('B', 'bookmarks', False, _('compare bookmarks')),
5497 ('B', 'bookmarks', False, _('compare bookmarks')),
5496 ('b', 'branch', [], _('a specific branch you would like to push'),
5498 ('b', 'branch', [], _('a specific branch you would like to push'),
5497 _('BRANCH')),
5499 _('BRANCH')),
5498 ] + logopts + remoteopts + subrepoopts,
5500 ] + logopts + remoteopts + subrepoopts,
5499 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5501 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5500 def outgoing(ui, repo, dest=None, **opts):
5502 def outgoing(ui, repo, dest=None, **opts):
5501 """show changesets not found in the destination
5503 """show changesets not found in the destination
5502
5504
5503 Show changesets not found in the specified destination repository
5505 Show changesets not found in the specified destination repository
5504 or the default push location. These are the changesets that would
5506 or the default push location. These are the changesets that would
5505 be pushed if a push was requested.
5507 be pushed if a push was requested.
5506
5508
5507 See pull for details of valid destination formats.
5509 See pull for details of valid destination formats.
5508
5510
5509 .. container:: verbose
5511 .. container:: verbose
5510
5512
5511 With -B/--bookmarks, the result of bookmark comparison between
5513 With -B/--bookmarks, the result of bookmark comparison between
5512 local and remote repositories is displayed. With -v/--verbose,
5514 local and remote repositories is displayed. With -v/--verbose,
5513 status is also displayed for each bookmark like below::
5515 status is also displayed for each bookmark like below::
5514
5516
5515 BM1 01234567890a added
5517 BM1 01234567890a added
5516 BM2 deleted
5518 BM2 deleted
5517 BM3 234567890abc advanced
5519 BM3 234567890abc advanced
5518 BM4 34567890abcd diverged
5520 BM4 34567890abcd diverged
5519 BM5 4567890abcde changed
5521 BM5 4567890abcde changed
5520
5522
5521 The action taken when pushing depends on the
5523 The action taken when pushing depends on the
5522 status of each bookmark:
5524 status of each bookmark:
5523
5525
5524 :``added``: push with ``-B`` will create it
5526 :``added``: push with ``-B`` will create it
5525 :``deleted``: push with ``-B`` will delete it
5527 :``deleted``: push with ``-B`` will delete it
5526 :``advanced``: push will update it
5528 :``advanced``: push will update it
5527 :``diverged``: push with ``-B`` will update it
5529 :``diverged``: push with ``-B`` will update it
5528 :``changed``: push with ``-B`` will update it
5530 :``changed``: push with ``-B`` will update it
5529
5531
5530 From the point of view of pushing behavior, bookmarks
5532 From the point of view of pushing behavior, bookmarks
5531 existing only in the remote repository are treated as
5533 existing only in the remote repository are treated as
5532 ``deleted``, even if it is in fact added remotely.
5534 ``deleted``, even if it is in fact added remotely.
5533
5535
5534 Returns 0 if there are outgoing changes, 1 otherwise.
5536 Returns 0 if there are outgoing changes, 1 otherwise.
5535 """
5537 """
5536 if opts.get('graph'):
5538 if opts.get('graph'):
5537 cmdutil.checkunsupportedgraphflags([], opts)
5539 cmdutil.checkunsupportedgraphflags([], opts)
5538 o, other = hg._outgoing(ui, repo, dest, opts)
5540 o, other = hg._outgoing(ui, repo, dest, opts)
5539 if not o:
5541 if not o:
5540 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5542 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5541 return
5543 return
5542
5544
5543 revdag = cmdutil.graphrevs(repo, o, opts)
5545 revdag = cmdutil.graphrevs(repo, o, opts)
5544 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5546 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5545 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5547 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5546 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5548 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5547 return 0
5549 return 0
5548
5550
5549 if opts.get('bookmarks'):
5551 if opts.get('bookmarks'):
5550 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5552 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5551 dest, branches = hg.parseurl(dest, opts.get('branch'))
5553 dest, branches = hg.parseurl(dest, opts.get('branch'))
5552 other = hg.peer(repo, opts, dest)
5554 other = hg.peer(repo, opts, dest)
5553 if 'bookmarks' not in other.listkeys('namespaces'):
5555 if 'bookmarks' not in other.listkeys('namespaces'):
5554 ui.warn(_("remote doesn't support bookmarks\n"))
5556 ui.warn(_("remote doesn't support bookmarks\n"))
5555 return 0
5557 return 0
5556 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5558 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5557 return bookmarks.outgoing(ui, repo, other)
5559 return bookmarks.outgoing(ui, repo, other)
5558
5560
5559 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5561 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5560 try:
5562 try:
5561 return hg.outgoing(ui, repo, dest, opts)
5563 return hg.outgoing(ui, repo, dest, opts)
5562 finally:
5564 finally:
5563 del repo._subtoppath
5565 del repo._subtoppath
5564
5566
5565 @command('parents',
5567 @command('parents',
5566 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5568 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5567 ] + templateopts,
5569 ] + templateopts,
5568 _('[-r REV] [FILE]'),
5570 _('[-r REV] [FILE]'),
5569 inferrepo=True)
5571 inferrepo=True)
5570 def parents(ui, repo, file_=None, **opts):
5572 def parents(ui, repo, file_=None, **opts):
5571 """show the parents of the working directory or revision (DEPRECATED)
5573 """show the parents of the working directory or revision (DEPRECATED)
5572
5574
5573 Print the working directory's parent revisions. If a revision is
5575 Print the working directory's parent revisions. If a revision is
5574 given via -r/--rev, the parent of that revision will be printed.
5576 given via -r/--rev, the parent of that revision will be printed.
5575 If a file argument is given, the revision in which the file was
5577 If a file argument is given, the revision in which the file was
5576 last changed (before the working directory revision or the
5578 last changed (before the working directory revision or the
5577 argument to --rev if given) is printed.
5579 argument to --rev if given) is printed.
5578
5580
5579 This command is equivalent to::
5581 This command is equivalent to::
5580
5582
5581 hg log -r "p1()+p2()" or
5583 hg log -r "p1()+p2()" or
5582 hg log -r "p1(REV)+p2(REV)" or
5584 hg log -r "p1(REV)+p2(REV)" or
5583 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5585 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5584 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5586 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5585
5587
5586 See :hg:`summary` and :hg:`help revsets` for related information.
5588 See :hg:`summary` and :hg:`help revsets` for related information.
5587
5589
5588 Returns 0 on success.
5590 Returns 0 on success.
5589 """
5591 """
5590
5592
5591 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5593 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5592
5594
5593 if file_:
5595 if file_:
5594 m = scmutil.match(ctx, (file_,), opts)
5596 m = scmutil.match(ctx, (file_,), opts)
5595 if m.anypats() or len(m.files()) != 1:
5597 if m.anypats() or len(m.files()) != 1:
5596 raise error.Abort(_('can only specify an explicit filename'))
5598 raise error.Abort(_('can only specify an explicit filename'))
5597 file_ = m.files()[0]
5599 file_ = m.files()[0]
5598 filenodes = []
5600 filenodes = []
5599 for cp in ctx.parents():
5601 for cp in ctx.parents():
5600 if not cp:
5602 if not cp:
5601 continue
5603 continue
5602 try:
5604 try:
5603 filenodes.append(cp.filenode(file_))
5605 filenodes.append(cp.filenode(file_))
5604 except error.LookupError:
5606 except error.LookupError:
5605 pass
5607 pass
5606 if not filenodes:
5608 if not filenodes:
5607 raise error.Abort(_("'%s' not found in manifest!") % file_)
5609 raise error.Abort(_("'%s' not found in manifest!") % file_)
5608 p = []
5610 p = []
5609 for fn in filenodes:
5611 for fn in filenodes:
5610 fctx = repo.filectx(file_, fileid=fn)
5612 fctx = repo.filectx(file_, fileid=fn)
5611 p.append(fctx.node())
5613 p.append(fctx.node())
5612 else:
5614 else:
5613 p = [cp.node() for cp in ctx.parents()]
5615 p = [cp.node() for cp in ctx.parents()]
5614
5616
5615 displayer = cmdutil.show_changeset(ui, repo, opts)
5617 displayer = cmdutil.show_changeset(ui, repo, opts)
5616 for n in p:
5618 for n in p:
5617 if n != nullid:
5619 if n != nullid:
5618 displayer.show(repo[n])
5620 displayer.show(repo[n])
5619 displayer.close()
5621 displayer.close()
5620
5622
5621 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5623 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5622 def paths(ui, repo, search=None, **opts):
5624 def paths(ui, repo, search=None, **opts):
5623 """show aliases for remote repositories
5625 """show aliases for remote repositories
5624
5626
5625 Show definition of symbolic path name NAME. If no name is given,
5627 Show definition of symbolic path name NAME. If no name is given,
5626 show definition of all available names.
5628 show definition of all available names.
5627
5629
5628 Option -q/--quiet suppresses all output when searching for NAME
5630 Option -q/--quiet suppresses all output when searching for NAME
5629 and shows only the path names when listing all definitions.
5631 and shows only the path names when listing all definitions.
5630
5632
5631 Path names are defined in the [paths] section of your
5633 Path names are defined in the [paths] section of your
5632 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5634 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5633 repository, ``.hg/hgrc`` is used, too.
5635 repository, ``.hg/hgrc`` is used, too.
5634
5636
5635 The path names ``default`` and ``default-push`` have a special
5637 The path names ``default`` and ``default-push`` have a special
5636 meaning. When performing a push or pull operation, they are used
5638 meaning. When performing a push or pull operation, they are used
5637 as fallbacks if no location is specified on the command-line.
5639 as fallbacks if no location is specified on the command-line.
5638 When ``default-push`` is set, it will be used for push and
5640 When ``default-push`` is set, it will be used for push and
5639 ``default`` will be used for pull; otherwise ``default`` is used
5641 ``default`` will be used for pull; otherwise ``default`` is used
5640 as the fallback for both. When cloning a repository, the clone
5642 as the fallback for both. When cloning a repository, the clone
5641 source is written as ``default`` in ``.hg/hgrc``.
5643 source is written as ``default`` in ``.hg/hgrc``.
5642
5644
5643 .. note::
5645 .. note::
5644
5646
5645 ``default`` and ``default-push`` apply to all inbound (e.g.
5647 ``default`` and ``default-push`` apply to all inbound (e.g.
5646 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5648 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5647 and :hg:`bundle`) operations.
5649 and :hg:`bundle`) operations.
5648
5650
5649 See :hg:`help urls` for more information.
5651 See :hg:`help urls` for more information.
5650
5652
5651 Returns 0 on success.
5653 Returns 0 on success.
5652 """
5654 """
5653 if search:
5655 if search:
5654 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5656 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5655 if name == search]
5657 if name == search]
5656 else:
5658 else:
5657 pathitems = sorted(ui.paths.iteritems())
5659 pathitems = sorted(ui.paths.iteritems())
5658
5660
5659 fm = ui.formatter('paths', opts)
5661 fm = ui.formatter('paths', opts)
5660 if fm.isplain():
5662 if fm.isplain():
5661 hidepassword = util.hidepassword
5663 hidepassword = util.hidepassword
5662 else:
5664 else:
5663 hidepassword = str
5665 hidepassword = str
5664 if ui.quiet:
5666 if ui.quiet:
5665 namefmt = '%s\n'
5667 namefmt = '%s\n'
5666 else:
5668 else:
5667 namefmt = '%s = '
5669 namefmt = '%s = '
5668 showsubopts = not search and not ui.quiet
5670 showsubopts = not search and not ui.quiet
5669
5671
5670 for name, path in pathitems:
5672 for name, path in pathitems:
5671 fm.startitem()
5673 fm.startitem()
5672 fm.condwrite(not search, 'name', namefmt, name)
5674 fm.condwrite(not search, 'name', namefmt, name)
5673 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5675 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5674 for subopt, value in sorted(path.suboptions.items()):
5676 for subopt, value in sorted(path.suboptions.items()):
5675 assert subopt not in ('name', 'url')
5677 assert subopt not in ('name', 'url')
5676 if showsubopts:
5678 if showsubopts:
5677 fm.plain('%s:%s = ' % (name, subopt))
5679 fm.plain('%s:%s = ' % (name, subopt))
5678 fm.condwrite(showsubopts, subopt, '%s\n', value)
5680 fm.condwrite(showsubopts, subopt, '%s\n', value)
5679
5681
5680 fm.end()
5682 fm.end()
5681
5683
5682 if search and not pathitems:
5684 if search and not pathitems:
5683 if not ui.quiet:
5685 if not ui.quiet:
5684 ui.warn(_("not found!\n"))
5686 ui.warn(_("not found!\n"))
5685 return 1
5687 return 1
5686 else:
5688 else:
5687 return 0
5689 return 0
5688
5690
5689 @command('phase',
5691 @command('phase',
5690 [('p', 'public', False, _('set changeset phase to public')),
5692 [('p', 'public', False, _('set changeset phase to public')),
5691 ('d', 'draft', False, _('set changeset phase to draft')),
5693 ('d', 'draft', False, _('set changeset phase to draft')),
5692 ('s', 'secret', False, _('set changeset phase to secret')),
5694 ('s', 'secret', False, _('set changeset phase to secret')),
5693 ('f', 'force', False, _('allow to move boundary backward')),
5695 ('f', 'force', False, _('allow to move boundary backward')),
5694 ('r', 'rev', [], _('target revision'), _('REV')),
5696 ('r', 'rev', [], _('target revision'), _('REV')),
5695 ],
5697 ],
5696 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5698 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5697 def phase(ui, repo, *revs, **opts):
5699 def phase(ui, repo, *revs, **opts):
5698 """set or show the current phase name
5700 """set or show the current phase name
5699
5701
5700 With no argument, show the phase name of the current revision(s).
5702 With no argument, show the phase name of the current revision(s).
5701
5703
5702 With one of -p/--public, -d/--draft or -s/--secret, change the
5704 With one of -p/--public, -d/--draft or -s/--secret, change the
5703 phase value of the specified revisions.
5705 phase value of the specified revisions.
5704
5706
5705 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5707 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5706 lower phase to an higher phase. Phases are ordered as follows::
5708 lower phase to an higher phase. Phases are ordered as follows::
5707
5709
5708 public < draft < secret
5710 public < draft < secret
5709
5711
5710 Returns 0 on success, 1 if some phases could not be changed.
5712 Returns 0 on success, 1 if some phases could not be changed.
5711
5713
5712 (For more information about the phases concept, see :hg:`help phases`.)
5714 (For more information about the phases concept, see :hg:`help phases`.)
5713 """
5715 """
5714 # search for a unique phase argument
5716 # search for a unique phase argument
5715 targetphase = None
5717 targetphase = None
5716 for idx, name in enumerate(phases.phasenames):
5718 for idx, name in enumerate(phases.phasenames):
5717 if opts[name]:
5719 if opts[name]:
5718 if targetphase is not None:
5720 if targetphase is not None:
5719 raise error.Abort(_('only one phase can be specified'))
5721 raise error.Abort(_('only one phase can be specified'))
5720 targetphase = idx
5722 targetphase = idx
5721
5723
5722 # look for specified revision
5724 # look for specified revision
5723 revs = list(revs)
5725 revs = list(revs)
5724 revs.extend(opts['rev'])
5726 revs.extend(opts['rev'])
5725 if not revs:
5727 if not revs:
5726 # display both parents as the second parent phase can influence
5728 # display both parents as the second parent phase can influence
5727 # the phase of a merge commit
5729 # the phase of a merge commit
5728 revs = [c.rev() for c in repo[None].parents()]
5730 revs = [c.rev() for c in repo[None].parents()]
5729
5731
5730 revs = scmutil.revrange(repo, revs)
5732 revs = scmutil.revrange(repo, revs)
5731
5733
5732 lock = None
5734 lock = None
5733 ret = 0
5735 ret = 0
5734 if targetphase is None:
5736 if targetphase is None:
5735 # display
5737 # display
5736 for r in revs:
5738 for r in revs:
5737 ctx = repo[r]
5739 ctx = repo[r]
5738 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5740 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5739 else:
5741 else:
5740 tr = None
5742 tr = None
5741 lock = repo.lock()
5743 lock = repo.lock()
5742 try:
5744 try:
5743 tr = repo.transaction("phase")
5745 tr = repo.transaction("phase")
5744 # set phase
5746 # set phase
5745 if not revs:
5747 if not revs:
5746 raise error.Abort(_('empty revision set'))
5748 raise error.Abort(_('empty revision set'))
5747 nodes = [repo[r].node() for r in revs]
5749 nodes = [repo[r].node() for r in revs]
5748 # moving revision from public to draft may hide them
5750 # moving revision from public to draft may hide them
5749 # We have to check result on an unfiltered repository
5751 # We have to check result on an unfiltered repository
5750 unfi = repo.unfiltered()
5752 unfi = repo.unfiltered()
5751 getphase = unfi._phasecache.phase
5753 getphase = unfi._phasecache.phase
5752 olddata = [getphase(unfi, r) for r in unfi]
5754 olddata = [getphase(unfi, r) for r in unfi]
5753 phases.advanceboundary(repo, tr, targetphase, nodes)
5755 phases.advanceboundary(repo, tr, targetphase, nodes)
5754 if opts['force']:
5756 if opts['force']:
5755 phases.retractboundary(repo, tr, targetphase, nodes)
5757 phases.retractboundary(repo, tr, targetphase, nodes)
5756 tr.close()
5758 tr.close()
5757 finally:
5759 finally:
5758 if tr is not None:
5760 if tr is not None:
5759 tr.release()
5761 tr.release()
5760 lock.release()
5762 lock.release()
5761 getphase = unfi._phasecache.phase
5763 getphase = unfi._phasecache.phase
5762 newdata = [getphase(unfi, r) for r in unfi]
5764 newdata = [getphase(unfi, r) for r in unfi]
5763 changes = sum(newdata[r] != olddata[r] for r in unfi)
5765 changes = sum(newdata[r] != olddata[r] for r in unfi)
5764 cl = unfi.changelog
5766 cl = unfi.changelog
5765 rejected = [n for n in nodes
5767 rejected = [n for n in nodes
5766 if newdata[cl.rev(n)] < targetphase]
5768 if newdata[cl.rev(n)] < targetphase]
5767 if rejected:
5769 if rejected:
5768 ui.warn(_('cannot move %i changesets to a higher '
5770 ui.warn(_('cannot move %i changesets to a higher '
5769 'phase, use --force\n') % len(rejected))
5771 'phase, use --force\n') % len(rejected))
5770 ret = 1
5772 ret = 1
5771 if changes:
5773 if changes:
5772 msg = _('phase changed for %i changesets\n') % changes
5774 msg = _('phase changed for %i changesets\n') % changes
5773 if ret:
5775 if ret:
5774 ui.status(msg)
5776 ui.status(msg)
5775 else:
5777 else:
5776 ui.note(msg)
5778 ui.note(msg)
5777 else:
5779 else:
5778 ui.warn(_('no phases changed\n'))
5780 ui.warn(_('no phases changed\n'))
5779 return ret
5781 return ret
5780
5782
5781 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5783 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5782 """Run after a changegroup has been added via pull/unbundle
5784 """Run after a changegroup has been added via pull/unbundle
5783
5785
5784 This takes arguments below:
5786 This takes arguments below:
5785
5787
5786 :modheads: change of heads by pull/unbundle
5788 :modheads: change of heads by pull/unbundle
5787 :optupdate: updating working directory is needed or not
5789 :optupdate: updating working directory is needed or not
5788 :checkout: update destination revision (or None to default destination)
5790 :checkout: update destination revision (or None to default destination)
5789 :brev: a name, which might be a bookmark to be activated after updating
5791 :brev: a name, which might be a bookmark to be activated after updating
5790 """
5792 """
5791 if modheads == 0:
5793 if modheads == 0:
5792 return
5794 return
5793 if optupdate:
5795 if optupdate:
5794 try:
5796 try:
5795 return hg.updatetotally(ui, repo, checkout, brev)
5797 return hg.updatetotally(ui, repo, checkout, brev)
5796 except error.UpdateAbort as inst:
5798 except error.UpdateAbort as inst:
5797 msg = _("not updating: %s") % str(inst)
5799 msg = _("not updating: %s") % str(inst)
5798 hint = inst.hint
5800 hint = inst.hint
5799 raise error.UpdateAbort(msg, hint=hint)
5801 raise error.UpdateAbort(msg, hint=hint)
5800 if modheads > 1:
5802 if modheads > 1:
5801 currentbranchheads = len(repo.branchheads())
5803 currentbranchheads = len(repo.branchheads())
5802 if currentbranchheads == modheads:
5804 if currentbranchheads == modheads:
5803 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5805 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5804 elif currentbranchheads > 1:
5806 elif currentbranchheads > 1:
5805 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5807 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5806 "merge)\n"))
5808 "merge)\n"))
5807 else:
5809 else:
5808 ui.status(_("(run 'hg heads' to see heads)\n"))
5810 ui.status(_("(run 'hg heads' to see heads)\n"))
5809 else:
5811 else:
5810 ui.status(_("(run 'hg update' to get a working copy)\n"))
5812 ui.status(_("(run 'hg update' to get a working copy)\n"))
5811
5813
5812 @command('^pull',
5814 @command('^pull',
5813 [('u', 'update', None,
5815 [('u', 'update', None,
5814 _('update to new branch head if changesets were pulled')),
5816 _('update to new branch head if changesets were pulled')),
5815 ('f', 'force', None, _('run even when remote repository is unrelated')),
5817 ('f', 'force', None, _('run even when remote repository is unrelated')),
5816 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5818 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5817 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5819 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5818 ('b', 'branch', [], _('a specific branch you would like to pull'),
5820 ('b', 'branch', [], _('a specific branch you would like to pull'),
5819 _('BRANCH')),
5821 _('BRANCH')),
5820 ] + remoteopts,
5822 ] + remoteopts,
5821 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5823 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5822 def pull(ui, repo, source="default", **opts):
5824 def pull(ui, repo, source="default", **opts):
5823 """pull changes from the specified source
5825 """pull changes from the specified source
5824
5826
5825 Pull changes from a remote repository to a local one.
5827 Pull changes from a remote repository to a local one.
5826
5828
5827 This finds all changes from the repository at the specified path
5829 This finds all changes from the repository at the specified path
5828 or URL and adds them to a local repository (the current one unless
5830 or URL and adds them to a local repository (the current one unless
5829 -R is specified). By default, this does not update the copy of the
5831 -R is specified). By default, this does not update the copy of the
5830 project in the working directory.
5832 project in the working directory.
5831
5833
5832 Use :hg:`incoming` if you want to see what would have been added
5834 Use :hg:`incoming` if you want to see what would have been added
5833 by a pull at the time you issued this command. If you then decide
5835 by a pull at the time you issued this command. If you then decide
5834 to add those changes to the repository, you should use :hg:`pull
5836 to add those changes to the repository, you should use :hg:`pull
5835 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5837 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5836
5838
5837 If SOURCE is omitted, the 'default' path will be used.
5839 If SOURCE is omitted, the 'default' path will be used.
5838 See :hg:`help urls` for more information.
5840 See :hg:`help urls` for more information.
5839
5841
5840 Specifying bookmark as ``.`` is equivalent to specifying the active
5842 Specifying bookmark as ``.`` is equivalent to specifying the active
5841 bookmark's name.
5843 bookmark's name.
5842
5844
5843 Returns 0 on success, 1 if an update had unresolved files.
5845 Returns 0 on success, 1 if an update had unresolved files.
5844 """
5846 """
5845 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5847 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5846 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5848 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5847 other = hg.peer(repo, opts, source)
5849 other = hg.peer(repo, opts, source)
5848 try:
5850 try:
5849 revs, checkout = hg.addbranchrevs(repo, other, branches,
5851 revs, checkout = hg.addbranchrevs(repo, other, branches,
5850 opts.get('rev'))
5852 opts.get('rev'))
5851
5853
5852
5854
5853 pullopargs = {}
5855 pullopargs = {}
5854 if opts.get('bookmark'):
5856 if opts.get('bookmark'):
5855 if not revs:
5857 if not revs:
5856 revs = []
5858 revs = []
5857 # The list of bookmark used here is not the one used to actually
5859 # The list of bookmark used here is not the one used to actually
5858 # update the bookmark name. This can result in the revision pulled
5860 # update the bookmark name. This can result in the revision pulled
5859 # not ending up with the name of the bookmark because of a race
5861 # not ending up with the name of the bookmark because of a race
5860 # condition on the server. (See issue 4689 for details)
5862 # condition on the server. (See issue 4689 for details)
5861 remotebookmarks = other.listkeys('bookmarks')
5863 remotebookmarks = other.listkeys('bookmarks')
5862 pullopargs['remotebookmarks'] = remotebookmarks
5864 pullopargs['remotebookmarks'] = remotebookmarks
5863 for b in opts['bookmark']:
5865 for b in opts['bookmark']:
5864 b = repo._bookmarks.expandname(b)
5866 b = repo._bookmarks.expandname(b)
5865 if b not in remotebookmarks:
5867 if b not in remotebookmarks:
5866 raise error.Abort(_('remote bookmark %s not found!') % b)
5868 raise error.Abort(_('remote bookmark %s not found!') % b)
5867 revs.append(remotebookmarks[b])
5869 revs.append(remotebookmarks[b])
5868
5870
5869 if revs:
5871 if revs:
5870 try:
5872 try:
5871 # When 'rev' is a bookmark name, we cannot guarantee that it
5873 # When 'rev' is a bookmark name, we cannot guarantee that it
5872 # will be updated with that name because of a race condition
5874 # will be updated with that name because of a race condition
5873 # server side. (See issue 4689 for details)
5875 # server side. (See issue 4689 for details)
5874 oldrevs = revs
5876 oldrevs = revs
5875 revs = [] # actually, nodes
5877 revs = [] # actually, nodes
5876 for r in oldrevs:
5878 for r in oldrevs:
5877 node = other.lookup(r)
5879 node = other.lookup(r)
5878 revs.append(node)
5880 revs.append(node)
5879 if r == checkout:
5881 if r == checkout:
5880 checkout = node
5882 checkout = node
5881 except error.CapabilityError:
5883 except error.CapabilityError:
5882 err = _("other repository doesn't support revision lookup, "
5884 err = _("other repository doesn't support revision lookup, "
5883 "so a rev cannot be specified.")
5885 "so a rev cannot be specified.")
5884 raise error.Abort(err)
5886 raise error.Abort(err)
5885
5887
5886 pullopargs.update(opts.get('opargs', {}))
5888 pullopargs.update(opts.get('opargs', {}))
5887 modheads = exchange.pull(repo, other, heads=revs,
5889 modheads = exchange.pull(repo, other, heads=revs,
5888 force=opts.get('force'),
5890 force=opts.get('force'),
5889 bookmarks=opts.get('bookmark', ()),
5891 bookmarks=opts.get('bookmark', ()),
5890 opargs=pullopargs).cgresult
5892 opargs=pullopargs).cgresult
5891
5893
5892 # brev is a name, which might be a bookmark to be activated at
5894 # brev is a name, which might be a bookmark to be activated at
5893 # the end of the update. In other words, it is an explicit
5895 # the end of the update. In other words, it is an explicit
5894 # destination of the update
5896 # destination of the update
5895 brev = None
5897 brev = None
5896
5898
5897 if checkout:
5899 if checkout:
5898 checkout = str(repo.changelog.rev(checkout))
5900 checkout = str(repo.changelog.rev(checkout))
5899
5901
5900 # order below depends on implementation of
5902 # order below depends on implementation of
5901 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5903 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5902 # because 'checkout' is determined without it.
5904 # because 'checkout' is determined without it.
5903 if opts.get('rev'):
5905 if opts.get('rev'):
5904 brev = opts['rev'][0]
5906 brev = opts['rev'][0]
5905 elif opts.get('branch'):
5907 elif opts.get('branch'):
5906 brev = opts['branch'][0]
5908 brev = opts['branch'][0]
5907 else:
5909 else:
5908 brev = branches[0]
5910 brev = branches[0]
5909 repo._subtoppath = source
5911 repo._subtoppath = source
5910 try:
5912 try:
5911 ret = postincoming(ui, repo, modheads, opts.get('update'),
5913 ret = postincoming(ui, repo, modheads, opts.get('update'),
5912 checkout, brev)
5914 checkout, brev)
5913
5915
5914 finally:
5916 finally:
5915 del repo._subtoppath
5917 del repo._subtoppath
5916
5918
5917 finally:
5919 finally:
5918 other.close()
5920 other.close()
5919 return ret
5921 return ret
5920
5922
5921 @command('^push',
5923 @command('^push',
5922 [('f', 'force', None, _('force push')),
5924 [('f', 'force', None, _('force push')),
5923 ('r', 'rev', [],
5925 ('r', 'rev', [],
5924 _('a changeset intended to be included in the destination'),
5926 _('a changeset intended to be included in the destination'),
5925 _('REV')),
5927 _('REV')),
5926 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5928 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5927 ('b', 'branch', [],
5929 ('b', 'branch', [],
5928 _('a specific branch you would like to push'), _('BRANCH')),
5930 _('a specific branch you would like to push'), _('BRANCH')),
5929 ('', 'new-branch', False, _('allow pushing a new branch')),
5931 ('', 'new-branch', False, _('allow pushing a new branch')),
5930 ] + remoteopts,
5932 ] + remoteopts,
5931 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5933 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5932 def push(ui, repo, dest=None, **opts):
5934 def push(ui, repo, dest=None, **opts):
5933 """push changes to the specified destination
5935 """push changes to the specified destination
5934
5936
5935 Push changesets from the local repository to the specified
5937 Push changesets from the local repository to the specified
5936 destination.
5938 destination.
5937
5939
5938 This operation is symmetrical to pull: it is identical to a pull
5940 This operation is symmetrical to pull: it is identical to a pull
5939 in the destination repository from the current one.
5941 in the destination repository from the current one.
5940
5942
5941 By default, push will not allow creation of new heads at the
5943 By default, push will not allow creation of new heads at the
5942 destination, since multiple heads would make it unclear which head
5944 destination, since multiple heads would make it unclear which head
5943 to use. In this situation, it is recommended to pull and merge
5945 to use. In this situation, it is recommended to pull and merge
5944 before pushing.
5946 before pushing.
5945
5947
5946 Use --new-branch if you want to allow push to create a new named
5948 Use --new-branch if you want to allow push to create a new named
5947 branch that is not present at the destination. This allows you to
5949 branch that is not present at the destination. This allows you to
5948 only create a new branch without forcing other changes.
5950 only create a new branch without forcing other changes.
5949
5951
5950 .. note::
5952 .. note::
5951
5953
5952 Extra care should be taken with the -f/--force option,
5954 Extra care should be taken with the -f/--force option,
5953 which will push all new heads on all branches, an action which will
5955 which will push all new heads on all branches, an action which will
5954 almost always cause confusion for collaborators.
5956 almost always cause confusion for collaborators.
5955
5957
5956 If -r/--rev is used, the specified revision and all its ancestors
5958 If -r/--rev is used, the specified revision and all its ancestors
5957 will be pushed to the remote repository.
5959 will be pushed to the remote repository.
5958
5960
5959 If -B/--bookmark is used, the specified bookmarked revision, its
5961 If -B/--bookmark is used, the specified bookmarked revision, its
5960 ancestors, and the bookmark will be pushed to the remote
5962 ancestors, and the bookmark will be pushed to the remote
5961 repository. Specifying ``.`` is equivalent to specifying the active
5963 repository. Specifying ``.`` is equivalent to specifying the active
5962 bookmark's name.
5964 bookmark's name.
5963
5965
5964 Please see :hg:`help urls` for important details about ``ssh://``
5966 Please see :hg:`help urls` for important details about ``ssh://``
5965 URLs. If DESTINATION is omitted, a default path will be used.
5967 URLs. If DESTINATION is omitted, a default path will be used.
5966
5968
5967 Returns 0 if push was successful, 1 if nothing to push.
5969 Returns 0 if push was successful, 1 if nothing to push.
5968 """
5970 """
5969
5971
5970 if opts.get('bookmark'):
5972 if opts.get('bookmark'):
5971 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5973 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5972 for b in opts['bookmark']:
5974 for b in opts['bookmark']:
5973 # translate -B options to -r so changesets get pushed
5975 # translate -B options to -r so changesets get pushed
5974 b = repo._bookmarks.expandname(b)
5976 b = repo._bookmarks.expandname(b)
5975 if b in repo._bookmarks:
5977 if b in repo._bookmarks:
5976 opts.setdefault('rev', []).append(b)
5978 opts.setdefault('rev', []).append(b)
5977 else:
5979 else:
5978 # if we try to push a deleted bookmark, translate it to null
5980 # if we try to push a deleted bookmark, translate it to null
5979 # this lets simultaneous -r, -b options continue working
5981 # this lets simultaneous -r, -b options continue working
5980 opts.setdefault('rev', []).append("null")
5982 opts.setdefault('rev', []).append("null")
5981
5983
5982 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5984 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5983 if not path:
5985 if not path:
5984 raise error.Abort(_('default repository not configured!'),
5986 raise error.Abort(_('default repository not configured!'),
5985 hint=_("see 'hg help config.paths'"))
5987 hint=_("see 'hg help config.paths'"))
5986 dest = path.pushloc or path.loc
5988 dest = path.pushloc or path.loc
5987 branches = (path.branch, opts.get('branch') or [])
5989 branches = (path.branch, opts.get('branch') or [])
5988 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5990 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5989 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5991 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5990 other = hg.peer(repo, opts, dest)
5992 other = hg.peer(repo, opts, dest)
5991
5993
5992 if revs:
5994 if revs:
5993 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5995 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5994 if not revs:
5996 if not revs:
5995 raise error.Abort(_("specified revisions evaluate to an empty set"),
5997 raise error.Abort(_("specified revisions evaluate to an empty set"),
5996 hint=_("use different revision arguments"))
5998 hint=_("use different revision arguments"))
5997 elif path.pushrev:
5999 elif path.pushrev:
5998 # It doesn't make any sense to specify ancestor revisions. So limit
6000 # It doesn't make any sense to specify ancestor revisions. So limit
5999 # to DAG heads to make discovery simpler.
6001 # to DAG heads to make discovery simpler.
6000 expr = revset.formatspec('heads(%r)', path.pushrev)
6002 expr = revset.formatspec('heads(%r)', path.pushrev)
6001 revs = scmutil.revrange(repo, [expr])
6003 revs = scmutil.revrange(repo, [expr])
6002 revs = [repo[rev].node() for rev in revs]
6004 revs = [repo[rev].node() for rev in revs]
6003 if not revs:
6005 if not revs:
6004 raise error.Abort(_('default push revset for path evaluates to an '
6006 raise error.Abort(_('default push revset for path evaluates to an '
6005 'empty set'))
6007 'empty set'))
6006
6008
6007 repo._subtoppath = dest
6009 repo._subtoppath = dest
6008 try:
6010 try:
6009 # push subrepos depth-first for coherent ordering
6011 # push subrepos depth-first for coherent ordering
6010 c = repo['']
6012 c = repo['']
6011 subs = c.substate # only repos that are committed
6013 subs = c.substate # only repos that are committed
6012 for s in sorted(subs):
6014 for s in sorted(subs):
6013 result = c.sub(s).push(opts)
6015 result = c.sub(s).push(opts)
6014 if result == 0:
6016 if result == 0:
6015 return not result
6017 return not result
6016 finally:
6018 finally:
6017 del repo._subtoppath
6019 del repo._subtoppath
6018 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
6020 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
6019 newbranch=opts.get('new_branch'),
6021 newbranch=opts.get('new_branch'),
6020 bookmarks=opts.get('bookmark', ()),
6022 bookmarks=opts.get('bookmark', ()),
6021 opargs=opts.get('opargs'))
6023 opargs=opts.get('opargs'))
6022
6024
6023 result = not pushop.cgresult
6025 result = not pushop.cgresult
6024
6026
6025 if pushop.bkresult is not None:
6027 if pushop.bkresult is not None:
6026 if pushop.bkresult == 2:
6028 if pushop.bkresult == 2:
6027 result = 2
6029 result = 2
6028 elif not result and pushop.bkresult:
6030 elif not result and pushop.bkresult:
6029 result = 2
6031 result = 2
6030
6032
6031 return result
6033 return result
6032
6034
6033 @command('recover', [])
6035 @command('recover', [])
6034 def recover(ui, repo):
6036 def recover(ui, repo):
6035 """roll back an interrupted transaction
6037 """roll back an interrupted transaction
6036
6038
6037 Recover from an interrupted commit or pull.
6039 Recover from an interrupted commit or pull.
6038
6040
6039 This command tries to fix the repository status after an
6041 This command tries to fix the repository status after an
6040 interrupted operation. It should only be necessary when Mercurial
6042 interrupted operation. It should only be necessary when Mercurial
6041 suggests it.
6043 suggests it.
6042
6044
6043 Returns 0 if successful, 1 if nothing to recover or verify fails.
6045 Returns 0 if successful, 1 if nothing to recover or verify fails.
6044 """
6046 """
6045 if repo.recover():
6047 if repo.recover():
6046 return hg.verify(repo)
6048 return hg.verify(repo)
6047 return 1
6049 return 1
6048
6050
6049 @command('^remove|rm',
6051 @command('^remove|rm',
6050 [('A', 'after', None, _('record delete for missing files')),
6052 [('A', 'after', None, _('record delete for missing files')),
6051 ('f', 'force', None,
6053 ('f', 'force', None,
6052 _('forget added files, delete modified files')),
6054 _('forget added files, delete modified files')),
6053 ] + subrepoopts + walkopts,
6055 ] + subrepoopts + walkopts,
6054 _('[OPTION]... FILE...'),
6056 _('[OPTION]... FILE...'),
6055 inferrepo=True)
6057 inferrepo=True)
6056 def remove(ui, repo, *pats, **opts):
6058 def remove(ui, repo, *pats, **opts):
6057 """remove the specified files on the next commit
6059 """remove the specified files on the next commit
6058
6060
6059 Schedule the indicated files for removal from the current branch.
6061 Schedule the indicated files for removal from the current branch.
6060
6062
6061 This command schedules the files to be removed at the next commit.
6063 This command schedules the files to be removed at the next commit.
6062 To undo a remove before that, see :hg:`revert`. To undo added
6064 To undo a remove before that, see :hg:`revert`. To undo added
6063 files, see :hg:`forget`.
6065 files, see :hg:`forget`.
6064
6066
6065 .. container:: verbose
6067 .. container:: verbose
6066
6068
6067 -A/--after can be used to remove only files that have already
6069 -A/--after can be used to remove only files that have already
6068 been deleted, -f/--force can be used to force deletion, and -Af
6070 been deleted, -f/--force can be used to force deletion, and -Af
6069 can be used to remove files from the next revision without
6071 can be used to remove files from the next revision without
6070 deleting them from the working directory.
6072 deleting them from the working directory.
6071
6073
6072 The following table details the behavior of remove for different
6074 The following table details the behavior of remove for different
6073 file states (columns) and option combinations (rows). The file
6075 file states (columns) and option combinations (rows). The file
6074 states are Added [A], Clean [C], Modified [M] and Missing [!]
6076 states are Added [A], Clean [C], Modified [M] and Missing [!]
6075 (as reported by :hg:`status`). The actions are Warn, Remove
6077 (as reported by :hg:`status`). The actions are Warn, Remove
6076 (from branch) and Delete (from disk):
6078 (from branch) and Delete (from disk):
6077
6079
6078 ========= == == == ==
6080 ========= == == == ==
6079 opt/state A C M !
6081 opt/state A C M !
6080 ========= == == == ==
6082 ========= == == == ==
6081 none W RD W R
6083 none W RD W R
6082 -f R RD RD R
6084 -f R RD RD R
6083 -A W W W R
6085 -A W W W R
6084 -Af R R R R
6086 -Af R R R R
6085 ========= == == == ==
6087 ========= == == == ==
6086
6088
6087 .. note::
6089 .. note::
6088
6090
6089 :hg:`remove` never deletes files in Added [A] state from the
6091 :hg:`remove` never deletes files in Added [A] state from the
6090 working directory, not even if ``--force`` is specified.
6092 working directory, not even if ``--force`` is specified.
6091
6093
6092 Returns 0 on success, 1 if any warnings encountered.
6094 Returns 0 on success, 1 if any warnings encountered.
6093 """
6095 """
6094
6096
6095 after, force = opts.get('after'), opts.get('force')
6097 after, force = opts.get('after'), opts.get('force')
6096 if not pats and not after:
6098 if not pats and not after:
6097 raise error.Abort(_('no files specified'))
6099 raise error.Abort(_('no files specified'))
6098
6100
6099 m = scmutil.match(repo[None], pats, opts)
6101 m = scmutil.match(repo[None], pats, opts)
6100 subrepos = opts.get('subrepos')
6102 subrepos = opts.get('subrepos')
6101 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6103 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6102
6104
6103 @command('rename|move|mv',
6105 @command('rename|move|mv',
6104 [('A', 'after', None, _('record a rename that has already occurred')),
6106 [('A', 'after', None, _('record a rename that has already occurred')),
6105 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6107 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6106 ] + walkopts + dryrunopts,
6108 ] + walkopts + dryrunopts,
6107 _('[OPTION]... SOURCE... DEST'))
6109 _('[OPTION]... SOURCE... DEST'))
6108 def rename(ui, repo, *pats, **opts):
6110 def rename(ui, repo, *pats, **opts):
6109 """rename files; equivalent of copy + remove
6111 """rename files; equivalent of copy + remove
6110
6112
6111 Mark dest as copies of sources; mark sources for deletion. If dest
6113 Mark dest as copies of sources; mark sources for deletion. If dest
6112 is a directory, copies are put in that directory. If dest is a
6114 is a directory, copies are put in that directory. If dest is a
6113 file, there can only be one source.
6115 file, there can only be one source.
6114
6116
6115 By default, this command copies the contents of files as they
6117 By default, this command copies the contents of files as they
6116 exist in the working directory. If invoked with -A/--after, the
6118 exist in the working directory. If invoked with -A/--after, the
6117 operation is recorded, but no copying is performed.
6119 operation is recorded, but no copying is performed.
6118
6120
6119 This command takes effect at the next commit. To undo a rename
6121 This command takes effect at the next commit. To undo a rename
6120 before that, see :hg:`revert`.
6122 before that, see :hg:`revert`.
6121
6123
6122 Returns 0 on success, 1 if errors are encountered.
6124 Returns 0 on success, 1 if errors are encountered.
6123 """
6125 """
6124 with repo.wlock(False):
6126 with repo.wlock(False):
6125 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6127 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6126
6128
6127 @command('resolve',
6129 @command('resolve',
6128 [('a', 'all', None, _('select all unresolved files')),
6130 [('a', 'all', None, _('select all unresolved files')),
6129 ('l', 'list', None, _('list state of files needing merge')),
6131 ('l', 'list', None, _('list state of files needing merge')),
6130 ('m', 'mark', None, _('mark files as resolved')),
6132 ('m', 'mark', None, _('mark files as resolved')),
6131 ('u', 'unmark', None, _('mark files as unresolved')),
6133 ('u', 'unmark', None, _('mark files as unresolved')),
6132 ('n', 'no-status', None, _('hide status prefix'))]
6134 ('n', 'no-status', None, _('hide status prefix'))]
6133 + mergetoolopts + walkopts + formatteropts,
6135 + mergetoolopts + walkopts + formatteropts,
6134 _('[OPTION]... [FILE]...'),
6136 _('[OPTION]... [FILE]...'),
6135 inferrepo=True)
6137 inferrepo=True)
6136 def resolve(ui, repo, *pats, **opts):
6138 def resolve(ui, repo, *pats, **opts):
6137 """redo merges or set/view the merge status of files
6139 """redo merges or set/view the merge status of files
6138
6140
6139 Merges with unresolved conflicts are often the result of
6141 Merges with unresolved conflicts are often the result of
6140 non-interactive merging using the ``internal:merge`` configuration
6142 non-interactive merging using the ``internal:merge`` configuration
6141 setting, or a command-line merge tool like ``diff3``. The resolve
6143 setting, or a command-line merge tool like ``diff3``. The resolve
6142 command is used to manage the files involved in a merge, after
6144 command is used to manage the files involved in a merge, after
6143 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6145 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6144 working directory must have two parents). See :hg:`help
6146 working directory must have two parents). See :hg:`help
6145 merge-tools` for information on configuring merge tools.
6147 merge-tools` for information on configuring merge tools.
6146
6148
6147 The resolve command can be used in the following ways:
6149 The resolve command can be used in the following ways:
6148
6150
6149 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6151 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6150 files, discarding any previous merge attempts. Re-merging is not
6152 files, discarding any previous merge attempts. Re-merging is not
6151 performed for files already marked as resolved. Use ``--all/-a``
6153 performed for files already marked as resolved. Use ``--all/-a``
6152 to select all unresolved files. ``--tool`` can be used to specify
6154 to select all unresolved files. ``--tool`` can be used to specify
6153 the merge tool used for the given files. It overrides the HGMERGE
6155 the merge tool used for the given files. It overrides the HGMERGE
6154 environment variable and your configuration files. Previous file
6156 environment variable and your configuration files. Previous file
6155 contents are saved with a ``.orig`` suffix.
6157 contents are saved with a ``.orig`` suffix.
6156
6158
6157 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6159 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6158 (e.g. after having manually fixed-up the files). The default is
6160 (e.g. after having manually fixed-up the files). The default is
6159 to mark all unresolved files.
6161 to mark all unresolved files.
6160
6162
6161 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6163 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6162 default is to mark all resolved files.
6164 default is to mark all resolved files.
6163
6165
6164 - :hg:`resolve -l`: list files which had or still have conflicts.
6166 - :hg:`resolve -l`: list files which had or still have conflicts.
6165 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6167 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6166
6168
6167 .. note::
6169 .. note::
6168
6170
6169 Mercurial will not let you commit files with unresolved merge
6171 Mercurial will not let you commit files with unresolved merge
6170 conflicts. You must use :hg:`resolve -m ...` before you can
6172 conflicts. You must use :hg:`resolve -m ...` before you can
6171 commit after a conflicting merge.
6173 commit after a conflicting merge.
6172
6174
6173 Returns 0 on success, 1 if any files fail a resolve attempt.
6175 Returns 0 on success, 1 if any files fail a resolve attempt.
6174 """
6176 """
6175
6177
6176 flaglist = 'all mark unmark list no_status'.split()
6178 flaglist = 'all mark unmark list no_status'.split()
6177 all, mark, unmark, show, nostatus = \
6179 all, mark, unmark, show, nostatus = \
6178 [opts.get(o) for o in flaglist]
6180 [opts.get(o) for o in flaglist]
6179
6181
6180 if (show and (mark or unmark)) or (mark and unmark):
6182 if (show and (mark or unmark)) or (mark and unmark):
6181 raise error.Abort(_("too many options specified"))
6183 raise error.Abort(_("too many options specified"))
6182 if pats and all:
6184 if pats and all:
6183 raise error.Abort(_("can't specify --all and patterns"))
6185 raise error.Abort(_("can't specify --all and patterns"))
6184 if not (all or pats or show or mark or unmark):
6186 if not (all or pats or show or mark or unmark):
6185 raise error.Abort(_('no files or directories specified'),
6187 raise error.Abort(_('no files or directories specified'),
6186 hint=('use --all to re-merge all unresolved files'))
6188 hint=('use --all to re-merge all unresolved files'))
6187
6189
6188 if show:
6190 if show:
6189 fm = ui.formatter('resolve', opts)
6191 fm = ui.formatter('resolve', opts)
6190 ms = mergemod.mergestate.read(repo)
6192 ms = mergemod.mergestate.read(repo)
6191 m = scmutil.match(repo[None], pats, opts)
6193 m = scmutil.match(repo[None], pats, opts)
6192 for f in ms:
6194 for f in ms:
6193 if not m(f):
6195 if not m(f):
6194 continue
6196 continue
6195 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6197 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6196 'd': 'driverresolved'}[ms[f]]
6198 'd': 'driverresolved'}[ms[f]]
6197 fm.startitem()
6199 fm.startitem()
6198 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6200 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6199 fm.write('path', '%s\n', f, label=l)
6201 fm.write('path', '%s\n', f, label=l)
6200 fm.end()
6202 fm.end()
6201 return 0
6203 return 0
6202
6204
6203 with repo.wlock():
6205 with repo.wlock():
6204 ms = mergemod.mergestate.read(repo)
6206 ms = mergemod.mergestate.read(repo)
6205
6207
6206 if not (ms.active() or repo.dirstate.p2() != nullid):
6208 if not (ms.active() or repo.dirstate.p2() != nullid):
6207 raise error.Abort(
6209 raise error.Abort(
6208 _('resolve command not applicable when not merging'))
6210 _('resolve command not applicable when not merging'))
6209
6211
6210 wctx = repo[None]
6212 wctx = repo[None]
6211
6213
6212 if ms.mergedriver and ms.mdstate() == 'u':
6214 if ms.mergedriver and ms.mdstate() == 'u':
6213 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6215 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6214 ms.commit()
6216 ms.commit()
6215 # allow mark and unmark to go through
6217 # allow mark and unmark to go through
6216 if not mark and not unmark and not proceed:
6218 if not mark and not unmark and not proceed:
6217 return 1
6219 return 1
6218
6220
6219 m = scmutil.match(wctx, pats, opts)
6221 m = scmutil.match(wctx, pats, opts)
6220 ret = 0
6222 ret = 0
6221 didwork = False
6223 didwork = False
6222 runconclude = False
6224 runconclude = False
6223
6225
6224 tocomplete = []
6226 tocomplete = []
6225 for f in ms:
6227 for f in ms:
6226 if not m(f):
6228 if not m(f):
6227 continue
6229 continue
6228
6230
6229 didwork = True
6231 didwork = True
6230
6232
6231 # don't let driver-resolved files be marked, and run the conclude
6233 # don't let driver-resolved files be marked, and run the conclude
6232 # step if asked to resolve
6234 # step if asked to resolve
6233 if ms[f] == "d":
6235 if ms[f] == "d":
6234 exact = m.exact(f)
6236 exact = m.exact(f)
6235 if mark:
6237 if mark:
6236 if exact:
6238 if exact:
6237 ui.warn(_('not marking %s as it is driver-resolved\n')
6239 ui.warn(_('not marking %s as it is driver-resolved\n')
6238 % f)
6240 % f)
6239 elif unmark:
6241 elif unmark:
6240 if exact:
6242 if exact:
6241 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6243 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6242 % f)
6244 % f)
6243 else:
6245 else:
6244 runconclude = True
6246 runconclude = True
6245 continue
6247 continue
6246
6248
6247 if mark:
6249 if mark:
6248 ms.mark(f, "r")
6250 ms.mark(f, "r")
6249 elif unmark:
6251 elif unmark:
6250 ms.mark(f, "u")
6252 ms.mark(f, "u")
6251 else:
6253 else:
6252 # backup pre-resolve (merge uses .orig for its own purposes)
6254 # backup pre-resolve (merge uses .orig for its own purposes)
6253 a = repo.wjoin(f)
6255 a = repo.wjoin(f)
6254 try:
6256 try:
6255 util.copyfile(a, a + ".resolve")
6257 util.copyfile(a, a + ".resolve")
6256 except (IOError, OSError) as inst:
6258 except (IOError, OSError) as inst:
6257 if inst.errno != errno.ENOENT:
6259 if inst.errno != errno.ENOENT:
6258 raise
6260 raise
6259
6261
6260 try:
6262 try:
6261 # preresolve file
6263 # preresolve file
6262 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6264 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6263 'resolve')
6265 'resolve')
6264 complete, r = ms.preresolve(f, wctx)
6266 complete, r = ms.preresolve(f, wctx)
6265 if not complete:
6267 if not complete:
6266 tocomplete.append(f)
6268 tocomplete.append(f)
6267 elif r:
6269 elif r:
6268 ret = 1
6270 ret = 1
6269 finally:
6271 finally:
6270 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6272 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6271 ms.commit()
6273 ms.commit()
6272
6274
6273 # replace filemerge's .orig file with our resolve file, but only
6275 # replace filemerge's .orig file with our resolve file, but only
6274 # for merges that are complete
6276 # for merges that are complete
6275 if complete:
6277 if complete:
6276 try:
6278 try:
6277 util.rename(a + ".resolve",
6279 util.rename(a + ".resolve",
6278 scmutil.origpath(ui, repo, a))
6280 scmutil.origpath(ui, repo, a))
6279 except OSError as inst:
6281 except OSError as inst:
6280 if inst.errno != errno.ENOENT:
6282 if inst.errno != errno.ENOENT:
6281 raise
6283 raise
6282
6284
6283 for f in tocomplete:
6285 for f in tocomplete:
6284 try:
6286 try:
6285 # resolve file
6287 # resolve file
6286 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6288 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6287 'resolve')
6289 'resolve')
6288 r = ms.resolve(f, wctx)
6290 r = ms.resolve(f, wctx)
6289 if r:
6291 if r:
6290 ret = 1
6292 ret = 1
6291 finally:
6293 finally:
6292 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6294 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6293 ms.commit()
6295 ms.commit()
6294
6296
6295 # replace filemerge's .orig file with our resolve file
6297 # replace filemerge's .orig file with our resolve file
6296 a = repo.wjoin(f)
6298 a = repo.wjoin(f)
6297 try:
6299 try:
6298 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6300 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6299 except OSError as inst:
6301 except OSError as inst:
6300 if inst.errno != errno.ENOENT:
6302 if inst.errno != errno.ENOENT:
6301 raise
6303 raise
6302
6304
6303 ms.commit()
6305 ms.commit()
6304 ms.recordactions()
6306 ms.recordactions()
6305
6307
6306 if not didwork and pats:
6308 if not didwork and pats:
6307 hint = None
6309 hint = None
6308 if not any([p for p in pats if p.find(':') >= 0]):
6310 if not any([p for p in pats if p.find(':') >= 0]):
6309 pats = ['path:%s' % p for p in pats]
6311 pats = ['path:%s' % p for p in pats]
6310 m = scmutil.match(wctx, pats, opts)
6312 m = scmutil.match(wctx, pats, opts)
6311 for f in ms:
6313 for f in ms:
6312 if not m(f):
6314 if not m(f):
6313 continue
6315 continue
6314 flags = ''.join(['-%s ' % o[0] for o in flaglist
6316 flags = ''.join(['-%s ' % o[0] for o in flaglist
6315 if opts.get(o)])
6317 if opts.get(o)])
6316 hint = _("(try: hg resolve %s%s)\n") % (
6318 hint = _("(try: hg resolve %s%s)\n") % (
6317 flags,
6319 flags,
6318 ' '.join(pats))
6320 ' '.join(pats))
6319 break
6321 break
6320 ui.warn(_("arguments do not match paths that need resolving\n"))
6322 ui.warn(_("arguments do not match paths that need resolving\n"))
6321 if hint:
6323 if hint:
6322 ui.warn(hint)
6324 ui.warn(hint)
6323 elif ms.mergedriver and ms.mdstate() != 's':
6325 elif ms.mergedriver and ms.mdstate() != 's':
6324 # run conclude step when either a driver-resolved file is requested
6326 # run conclude step when either a driver-resolved file is requested
6325 # or there are no driver-resolved files
6327 # or there are no driver-resolved files
6326 # we can't use 'ret' to determine whether any files are unresolved
6328 # we can't use 'ret' to determine whether any files are unresolved
6327 # because we might not have tried to resolve some
6329 # because we might not have tried to resolve some
6328 if ((runconclude or not list(ms.driverresolved()))
6330 if ((runconclude or not list(ms.driverresolved()))
6329 and not list(ms.unresolved())):
6331 and not list(ms.unresolved())):
6330 proceed = mergemod.driverconclude(repo, ms, wctx)
6332 proceed = mergemod.driverconclude(repo, ms, wctx)
6331 ms.commit()
6333 ms.commit()
6332 if not proceed:
6334 if not proceed:
6333 return 1
6335 return 1
6334
6336
6335 # Nudge users into finishing an unfinished operation
6337 # Nudge users into finishing an unfinished operation
6336 unresolvedf = list(ms.unresolved())
6338 unresolvedf = list(ms.unresolved())
6337 driverresolvedf = list(ms.driverresolved())
6339 driverresolvedf = list(ms.driverresolved())
6338 if not unresolvedf and not driverresolvedf:
6340 if not unresolvedf and not driverresolvedf:
6339 ui.status(_('(no more unresolved files)\n'))
6341 ui.status(_('(no more unresolved files)\n'))
6340 cmdutil.checkafterresolved(repo)
6342 cmdutil.checkafterresolved(repo)
6341 elif not unresolvedf:
6343 elif not unresolvedf:
6342 ui.status(_('(no more unresolved files -- '
6344 ui.status(_('(no more unresolved files -- '
6343 'run "hg resolve --all" to conclude)\n'))
6345 'run "hg resolve --all" to conclude)\n'))
6344
6346
6345 return ret
6347 return ret
6346
6348
6347 @command('revert',
6349 @command('revert',
6348 [('a', 'all', None, _('revert all changes when no arguments given')),
6350 [('a', 'all', None, _('revert all changes when no arguments given')),
6349 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6351 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6350 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6352 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6351 ('C', 'no-backup', None, _('do not save backup copies of files')),
6353 ('C', 'no-backup', None, _('do not save backup copies of files')),
6352 ('i', 'interactive', None,
6354 ('i', 'interactive', None,
6353 _('interactively select the changes (EXPERIMENTAL)')),
6355 _('interactively select the changes (EXPERIMENTAL)')),
6354 ] + walkopts + dryrunopts,
6356 ] + walkopts + dryrunopts,
6355 _('[OPTION]... [-r REV] [NAME]...'))
6357 _('[OPTION]... [-r REV] [NAME]...'))
6356 def revert(ui, repo, *pats, **opts):
6358 def revert(ui, repo, *pats, **opts):
6357 """restore files to their checkout state
6359 """restore files to their checkout state
6358
6360
6359 .. note::
6361 .. note::
6360
6362
6361 To check out earlier revisions, you should use :hg:`update REV`.
6363 To check out earlier revisions, you should use :hg:`update REV`.
6362 To cancel an uncommitted merge (and lose your changes),
6364 To cancel an uncommitted merge (and lose your changes),
6363 use :hg:`update --clean .`.
6365 use :hg:`update --clean .`.
6364
6366
6365 With no revision specified, revert the specified files or directories
6367 With no revision specified, revert the specified files or directories
6366 to the contents they had in the parent of the working directory.
6368 to the contents they had in the parent of the working directory.
6367 This restores the contents of files to an unmodified
6369 This restores the contents of files to an unmodified
6368 state and unschedules adds, removes, copies, and renames. If the
6370 state and unschedules adds, removes, copies, and renames. If the
6369 working directory has two parents, you must explicitly specify a
6371 working directory has two parents, you must explicitly specify a
6370 revision.
6372 revision.
6371
6373
6372 Using the -r/--rev or -d/--date options, revert the given files or
6374 Using the -r/--rev or -d/--date options, revert the given files or
6373 directories to their states as of a specific revision. Because
6375 directories to their states as of a specific revision. Because
6374 revert does not change the working directory parents, this will
6376 revert does not change the working directory parents, this will
6375 cause these files to appear modified. This can be helpful to "back
6377 cause these files to appear modified. This can be helpful to "back
6376 out" some or all of an earlier change. See :hg:`backout` for a
6378 out" some or all of an earlier change. See :hg:`backout` for a
6377 related method.
6379 related method.
6378
6380
6379 Modified files are saved with a .orig suffix before reverting.
6381 Modified files are saved with a .orig suffix before reverting.
6380 To disable these backups, use --no-backup. It is possible to store
6382 To disable these backups, use --no-backup. It is possible to store
6381 the backup files in a custom directory relative to the root of the
6383 the backup files in a custom directory relative to the root of the
6382 repository by setting the ``ui.origbackuppath`` configuration
6384 repository by setting the ``ui.origbackuppath`` configuration
6383 option.
6385 option.
6384
6386
6385 See :hg:`help dates` for a list of formats valid for -d/--date.
6387 See :hg:`help dates` for a list of formats valid for -d/--date.
6386
6388
6387 See :hg:`help backout` for a way to reverse the effect of an
6389 See :hg:`help backout` for a way to reverse the effect of an
6388 earlier changeset.
6390 earlier changeset.
6389
6391
6390 Returns 0 on success.
6392 Returns 0 on success.
6391 """
6393 """
6392
6394
6393 if opts.get("date"):
6395 if opts.get("date"):
6394 if opts.get("rev"):
6396 if opts.get("rev"):
6395 raise error.Abort(_("you can't specify a revision and a date"))
6397 raise error.Abort(_("you can't specify a revision and a date"))
6396 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6398 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6397
6399
6398 parent, p2 = repo.dirstate.parents()
6400 parent, p2 = repo.dirstate.parents()
6399 if not opts.get('rev') and p2 != nullid:
6401 if not opts.get('rev') and p2 != nullid:
6400 # revert after merge is a trap for new users (issue2915)
6402 # revert after merge is a trap for new users (issue2915)
6401 raise error.Abort(_('uncommitted merge with no revision specified'),
6403 raise error.Abort(_('uncommitted merge with no revision specified'),
6402 hint=_("use 'hg update' or see 'hg help revert'"))
6404 hint=_("use 'hg update' or see 'hg help revert'"))
6403
6405
6404 ctx = scmutil.revsingle(repo, opts.get('rev'))
6406 ctx = scmutil.revsingle(repo, opts.get('rev'))
6405
6407
6406 if (not (pats or opts.get('include') or opts.get('exclude') or
6408 if (not (pats or opts.get('include') or opts.get('exclude') or
6407 opts.get('all') or opts.get('interactive'))):
6409 opts.get('all') or opts.get('interactive'))):
6408 msg = _("no files or directories specified")
6410 msg = _("no files or directories specified")
6409 if p2 != nullid:
6411 if p2 != nullid:
6410 hint = _("uncommitted merge, use --all to discard all changes,"
6412 hint = _("uncommitted merge, use --all to discard all changes,"
6411 " or 'hg update -C .' to abort the merge")
6413 " or 'hg update -C .' to abort the merge")
6412 raise error.Abort(msg, hint=hint)
6414 raise error.Abort(msg, hint=hint)
6413 dirty = any(repo.status())
6415 dirty = any(repo.status())
6414 node = ctx.node()
6416 node = ctx.node()
6415 if node != parent:
6417 if node != parent:
6416 if dirty:
6418 if dirty:
6417 hint = _("uncommitted changes, use --all to discard all"
6419 hint = _("uncommitted changes, use --all to discard all"
6418 " changes, or 'hg update %s' to update") % ctx.rev()
6420 " changes, or 'hg update %s' to update") % ctx.rev()
6419 else:
6421 else:
6420 hint = _("use --all to revert all files,"
6422 hint = _("use --all to revert all files,"
6421 " or 'hg update %s' to update") % ctx.rev()
6423 " or 'hg update %s' to update") % ctx.rev()
6422 elif dirty:
6424 elif dirty:
6423 hint = _("uncommitted changes, use --all to discard all changes")
6425 hint = _("uncommitted changes, use --all to discard all changes")
6424 else:
6426 else:
6425 hint = _("use --all to revert all files")
6427 hint = _("use --all to revert all files")
6426 raise error.Abort(msg, hint=hint)
6428 raise error.Abort(msg, hint=hint)
6427
6429
6428 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6430 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6429
6431
6430 @command('rollback', dryrunopts +
6432 @command('rollback', dryrunopts +
6431 [('f', 'force', False, _('ignore safety measures'))])
6433 [('f', 'force', False, _('ignore safety measures'))])
6432 def rollback(ui, repo, **opts):
6434 def rollback(ui, repo, **opts):
6433 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6435 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6434
6436
6435 Please use :hg:`commit --amend` instead of rollback to correct
6437 Please use :hg:`commit --amend` instead of rollback to correct
6436 mistakes in the last commit.
6438 mistakes in the last commit.
6437
6439
6438 This command should be used with care. There is only one level of
6440 This command should be used with care. There is only one level of
6439 rollback, and there is no way to undo a rollback. It will also
6441 rollback, and there is no way to undo a rollback. It will also
6440 restore the dirstate at the time of the last transaction, losing
6442 restore the dirstate at the time of the last transaction, losing
6441 any dirstate changes since that time. This command does not alter
6443 any dirstate changes since that time. This command does not alter
6442 the working directory.
6444 the working directory.
6443
6445
6444 Transactions are used to encapsulate the effects of all commands
6446 Transactions are used to encapsulate the effects of all commands
6445 that create new changesets or propagate existing changesets into a
6447 that create new changesets or propagate existing changesets into a
6446 repository.
6448 repository.
6447
6449
6448 .. container:: verbose
6450 .. container:: verbose
6449
6451
6450 For example, the following commands are transactional, and their
6452 For example, the following commands are transactional, and their
6451 effects can be rolled back:
6453 effects can be rolled back:
6452
6454
6453 - commit
6455 - commit
6454 - import
6456 - import
6455 - pull
6457 - pull
6456 - push (with this repository as the destination)
6458 - push (with this repository as the destination)
6457 - unbundle
6459 - unbundle
6458
6460
6459 To avoid permanent data loss, rollback will refuse to rollback a
6461 To avoid permanent data loss, rollback will refuse to rollback a
6460 commit transaction if it isn't checked out. Use --force to
6462 commit transaction if it isn't checked out. Use --force to
6461 override this protection.
6463 override this protection.
6462
6464
6463 The rollback command can be entirely disabled by setting the
6465 The rollback command can be entirely disabled by setting the
6464 ``ui.rollback`` configuration setting to false. If you're here
6466 ``ui.rollback`` configuration setting to false. If you're here
6465 because you want to use rollback and it's disabled, you can
6467 because you want to use rollback and it's disabled, you can
6466 re-enable the command by setting ``ui.rollback`` to true.
6468 re-enable the command by setting ``ui.rollback`` to true.
6467
6469
6468 This command is not intended for use on public repositories. Once
6470 This command is not intended for use on public repositories. Once
6469 changes are visible for pull by other users, rolling a transaction
6471 changes are visible for pull by other users, rolling a transaction
6470 back locally is ineffective (someone else may already have pulled
6472 back locally is ineffective (someone else may already have pulled
6471 the changes). Furthermore, a race is possible with readers of the
6473 the changes). Furthermore, a race is possible with readers of the
6472 repository; for example an in-progress pull from the repository
6474 repository; for example an in-progress pull from the repository
6473 may fail if a rollback is performed.
6475 may fail if a rollback is performed.
6474
6476
6475 Returns 0 on success, 1 if no rollback data is available.
6477 Returns 0 on success, 1 if no rollback data is available.
6476 """
6478 """
6477 if not ui.configbool('ui', 'rollback', True):
6479 if not ui.configbool('ui', 'rollback', True):
6478 raise error.Abort(_('rollback is disabled because it is unsafe'),
6480 raise error.Abort(_('rollback is disabled because it is unsafe'),
6479 hint=('see `hg help -v rollback` for information'))
6481 hint=('see `hg help -v rollback` for information'))
6480 return repo.rollback(dryrun=opts.get('dry_run'),
6482 return repo.rollback(dryrun=opts.get('dry_run'),
6481 force=opts.get('force'))
6483 force=opts.get('force'))
6482
6484
6483 @command('root', [])
6485 @command('root', [])
6484 def root(ui, repo):
6486 def root(ui, repo):
6485 """print the root (top) of the current working directory
6487 """print the root (top) of the current working directory
6486
6488
6487 Print the root directory of the current repository.
6489 Print the root directory of the current repository.
6488
6490
6489 Returns 0 on success.
6491 Returns 0 on success.
6490 """
6492 """
6491 ui.write(repo.root + "\n")
6493 ui.write(repo.root + "\n")
6492
6494
6493 @command('^serve',
6495 @command('^serve',
6494 [('A', 'accesslog', '', _('name of access log file to write to'),
6496 [('A', 'accesslog', '', _('name of access log file to write to'),
6495 _('FILE')),
6497 _('FILE')),
6496 ('d', 'daemon', None, _('run server in background')),
6498 ('d', 'daemon', None, _('run server in background')),
6497 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6499 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6498 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6500 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6499 # use string type, then we can check if something was passed
6501 # use string type, then we can check if something was passed
6500 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6502 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6501 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6503 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6502 _('ADDR')),
6504 _('ADDR')),
6503 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6505 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6504 _('PREFIX')),
6506 _('PREFIX')),
6505 ('n', 'name', '',
6507 ('n', 'name', '',
6506 _('name to show in web pages (default: working directory)'), _('NAME')),
6508 _('name to show in web pages (default: working directory)'), _('NAME')),
6507 ('', 'web-conf', '',
6509 ('', 'web-conf', '',
6508 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6510 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6509 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6511 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6510 _('FILE')),
6512 _('FILE')),
6511 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6513 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6512 ('', 'stdio', None, _('for remote clients')),
6514 ('', 'stdio', None, _('for remote clients')),
6513 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6515 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6514 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6516 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6515 ('', 'style', '', _('template style to use'), _('STYLE')),
6517 ('', 'style', '', _('template style to use'), _('STYLE')),
6516 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6518 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6517 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6519 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6518 _('[OPTION]...'),
6520 _('[OPTION]...'),
6519 optionalrepo=True)
6521 optionalrepo=True)
6520 def serve(ui, repo, **opts):
6522 def serve(ui, repo, **opts):
6521 """start stand-alone webserver
6523 """start stand-alone webserver
6522
6524
6523 Start a local HTTP repository browser and pull server. You can use
6525 Start a local HTTP repository browser and pull server. You can use
6524 this for ad-hoc sharing and browsing of repositories. It is
6526 this for ad-hoc sharing and browsing of repositories. It is
6525 recommended to use a real web server to serve a repository for
6527 recommended to use a real web server to serve a repository for
6526 longer periods of time.
6528 longer periods of time.
6527
6529
6528 Please note that the server does not implement access control.
6530 Please note that the server does not implement access control.
6529 This means that, by default, anybody can read from the server and
6531 This means that, by default, anybody can read from the server and
6530 nobody can write to it by default. Set the ``web.allow_push``
6532 nobody can write to it by default. Set the ``web.allow_push``
6531 option to ``*`` to allow everybody to push to the server. You
6533 option to ``*`` to allow everybody to push to the server. You
6532 should use a real web server if you need to authenticate users.
6534 should use a real web server if you need to authenticate users.
6533
6535
6534 By default, the server logs accesses to stdout and errors to
6536 By default, the server logs accesses to stdout and errors to
6535 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6537 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6536 files.
6538 files.
6537
6539
6538 To have the server choose a free port number to listen on, specify
6540 To have the server choose a free port number to listen on, specify
6539 a port number of 0; in this case, the server will print the port
6541 a port number of 0; in this case, the server will print the port
6540 number it uses.
6542 number it uses.
6541
6543
6542 Returns 0 on success.
6544 Returns 0 on success.
6543 """
6545 """
6544
6546
6545 if opts["stdio"] and opts["cmdserver"]:
6547 if opts["stdio"] and opts["cmdserver"]:
6546 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6548 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6547
6549
6548 if opts["stdio"]:
6550 if opts["stdio"]:
6549 if repo is None:
6551 if repo is None:
6550 raise error.RepoError(_("there is no Mercurial repository here"
6552 raise error.RepoError(_("there is no Mercurial repository here"
6551 " (.hg not found)"))
6553 " (.hg not found)"))
6552 s = sshserver.sshserver(ui, repo)
6554 s = sshserver.sshserver(ui, repo)
6553 s.serve_forever()
6555 s.serve_forever()
6554
6556
6555 if opts["cmdserver"]:
6557 if opts["cmdserver"]:
6556 service = commandserver.createservice(ui, repo, opts)
6558 service = commandserver.createservice(ui, repo, opts)
6557 else:
6559 else:
6558 service = hgweb.createservice(ui, repo, opts)
6560 service = hgweb.createservice(ui, repo, opts)
6559 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6561 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6560
6562
6561 @command('^status|st',
6563 @command('^status|st',
6562 [('A', 'all', None, _('show status of all files')),
6564 [('A', 'all', None, _('show status of all files')),
6563 ('m', 'modified', None, _('show only modified files')),
6565 ('m', 'modified', None, _('show only modified files')),
6564 ('a', 'added', None, _('show only added files')),
6566 ('a', 'added', None, _('show only added files')),
6565 ('r', 'removed', None, _('show only removed files')),
6567 ('r', 'removed', None, _('show only removed files')),
6566 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6568 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6567 ('c', 'clean', None, _('show only files without changes')),
6569 ('c', 'clean', None, _('show only files without changes')),
6568 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6570 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6569 ('i', 'ignored', None, _('show only ignored files')),
6571 ('i', 'ignored', None, _('show only ignored files')),
6570 ('n', 'no-status', None, _('hide status prefix')),
6572 ('n', 'no-status', None, _('hide status prefix')),
6571 ('C', 'copies', None, _('show source of copied files')),
6573 ('C', 'copies', None, _('show source of copied files')),
6572 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6574 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6573 ('', 'rev', [], _('show difference from revision'), _('REV')),
6575 ('', 'rev', [], _('show difference from revision'), _('REV')),
6574 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6576 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6575 ] + walkopts + subrepoopts + formatteropts,
6577 ] + walkopts + subrepoopts + formatteropts,
6576 _('[OPTION]... [FILE]...'),
6578 _('[OPTION]... [FILE]...'),
6577 inferrepo=True)
6579 inferrepo=True)
6578 def status(ui, repo, *pats, **opts):
6580 def status(ui, repo, *pats, **opts):
6579 """show changed files in the working directory
6581 """show changed files in the working directory
6580
6582
6581 Show status of files in the repository. If names are given, only
6583 Show status of files in the repository. If names are given, only
6582 files that match are shown. Files that are clean or ignored or
6584 files that match are shown. Files that are clean or ignored or
6583 the source of a copy/move operation, are not listed unless
6585 the source of a copy/move operation, are not listed unless
6584 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6586 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6585 Unless options described with "show only ..." are given, the
6587 Unless options described with "show only ..." are given, the
6586 options -mardu are used.
6588 options -mardu are used.
6587
6589
6588 Option -q/--quiet hides untracked (unknown and ignored) files
6590 Option -q/--quiet hides untracked (unknown and ignored) files
6589 unless explicitly requested with -u/--unknown or -i/--ignored.
6591 unless explicitly requested with -u/--unknown or -i/--ignored.
6590
6592
6591 .. note::
6593 .. note::
6592
6594
6593 :hg:`status` may appear to disagree with diff if permissions have
6595 :hg:`status` may appear to disagree with diff if permissions have
6594 changed or a merge has occurred. The standard diff format does
6596 changed or a merge has occurred. The standard diff format does
6595 not report permission changes and diff only reports changes
6597 not report permission changes and diff only reports changes
6596 relative to one merge parent.
6598 relative to one merge parent.
6597
6599
6598 If one revision is given, it is used as the base revision.
6600 If one revision is given, it is used as the base revision.
6599 If two revisions are given, the differences between them are
6601 If two revisions are given, the differences between them are
6600 shown. The --change option can also be used as a shortcut to list
6602 shown. The --change option can also be used as a shortcut to list
6601 the changed files of a revision from its first parent.
6603 the changed files of a revision from its first parent.
6602
6604
6603 The codes used to show the status of files are::
6605 The codes used to show the status of files are::
6604
6606
6605 M = modified
6607 M = modified
6606 A = added
6608 A = added
6607 R = removed
6609 R = removed
6608 C = clean
6610 C = clean
6609 ! = missing (deleted by non-hg command, but still tracked)
6611 ! = missing (deleted by non-hg command, but still tracked)
6610 ? = not tracked
6612 ? = not tracked
6611 I = ignored
6613 I = ignored
6612 = origin of the previous file (with --copies)
6614 = origin of the previous file (with --copies)
6613
6615
6614 .. container:: verbose
6616 .. container:: verbose
6615
6617
6616 Examples:
6618 Examples:
6617
6619
6618 - show changes in the working directory relative to a
6620 - show changes in the working directory relative to a
6619 changeset::
6621 changeset::
6620
6622
6621 hg status --rev 9353
6623 hg status --rev 9353
6622
6624
6623 - show changes in the working directory relative to the
6625 - show changes in the working directory relative to the
6624 current directory (see :hg:`help patterns` for more information)::
6626 current directory (see :hg:`help patterns` for more information)::
6625
6627
6626 hg status re:
6628 hg status re:
6627
6629
6628 - show all changes including copies in an existing changeset::
6630 - show all changes including copies in an existing changeset::
6629
6631
6630 hg status --copies --change 9353
6632 hg status --copies --change 9353
6631
6633
6632 - get a NUL separated list of added files, suitable for xargs::
6634 - get a NUL separated list of added files, suitable for xargs::
6633
6635
6634 hg status -an0
6636 hg status -an0
6635
6637
6636 Returns 0 on success.
6638 Returns 0 on success.
6637 """
6639 """
6638
6640
6639 revs = opts.get('rev')
6641 revs = opts.get('rev')
6640 change = opts.get('change')
6642 change = opts.get('change')
6641
6643
6642 if revs and change:
6644 if revs and change:
6643 msg = _('cannot specify --rev and --change at the same time')
6645 msg = _('cannot specify --rev and --change at the same time')
6644 raise error.Abort(msg)
6646 raise error.Abort(msg)
6645 elif change:
6647 elif change:
6646 node2 = scmutil.revsingle(repo, change, None).node()
6648 node2 = scmutil.revsingle(repo, change, None).node()
6647 node1 = repo[node2].p1().node()
6649 node1 = repo[node2].p1().node()
6648 else:
6650 else:
6649 node1, node2 = scmutil.revpair(repo, revs)
6651 node1, node2 = scmutil.revpair(repo, revs)
6650
6652
6651 if pats:
6653 if pats:
6652 cwd = repo.getcwd()
6654 cwd = repo.getcwd()
6653 else:
6655 else:
6654 cwd = ''
6656 cwd = ''
6655
6657
6656 if opts.get('print0'):
6658 if opts.get('print0'):
6657 end = '\0'
6659 end = '\0'
6658 else:
6660 else:
6659 end = '\n'
6661 end = '\n'
6660 copy = {}
6662 copy = {}
6661 states = 'modified added removed deleted unknown ignored clean'.split()
6663 states = 'modified added removed deleted unknown ignored clean'.split()
6662 show = [k for k in states if opts.get(k)]
6664 show = [k for k in states if opts.get(k)]
6663 if opts.get('all'):
6665 if opts.get('all'):
6664 show += ui.quiet and (states[:4] + ['clean']) or states
6666 show += ui.quiet and (states[:4] + ['clean']) or states
6665 if not show:
6667 if not show:
6666 if ui.quiet:
6668 if ui.quiet:
6667 show = states[:4]
6669 show = states[:4]
6668 else:
6670 else:
6669 show = states[:5]
6671 show = states[:5]
6670
6672
6671 m = scmutil.match(repo[node2], pats, opts)
6673 m = scmutil.match(repo[node2], pats, opts)
6672 stat = repo.status(node1, node2, m,
6674 stat = repo.status(node1, node2, m,
6673 'ignored' in show, 'clean' in show, 'unknown' in show,
6675 'ignored' in show, 'clean' in show, 'unknown' in show,
6674 opts.get('subrepos'))
6676 opts.get('subrepos'))
6675 changestates = zip(states, 'MAR!?IC', stat)
6677 changestates = zip(states, 'MAR!?IC', stat)
6676
6678
6677 if (opts.get('all') or opts.get('copies')
6679 if (opts.get('all') or opts.get('copies')
6678 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6680 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6679 copy = copies.pathcopies(repo[node1], repo[node2], m)
6681 copy = copies.pathcopies(repo[node1], repo[node2], m)
6680
6682
6681 fm = ui.formatter('status', opts)
6683 fm = ui.formatter('status', opts)
6682 fmt = '%s' + end
6684 fmt = '%s' + end
6683 showchar = not opts.get('no_status')
6685 showchar = not opts.get('no_status')
6684
6686
6685 for state, char, files in changestates:
6687 for state, char, files in changestates:
6686 if state in show:
6688 if state in show:
6687 label = 'status.' + state
6689 label = 'status.' + state
6688 for f in files:
6690 for f in files:
6689 fm.startitem()
6691 fm.startitem()
6690 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6692 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6691 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6693 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6692 if f in copy:
6694 if f in copy:
6693 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6695 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6694 label='status.copied')
6696 label='status.copied')
6695 fm.end()
6697 fm.end()
6696
6698
6697 @command('^summary|sum',
6699 @command('^summary|sum',
6698 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6700 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6699 def summary(ui, repo, **opts):
6701 def summary(ui, repo, **opts):
6700 """summarize working directory state
6702 """summarize working directory state
6701
6703
6702 This generates a brief summary of the working directory state,
6704 This generates a brief summary of the working directory state,
6703 including parents, branch, commit status, phase and available updates.
6705 including parents, branch, commit status, phase and available updates.
6704
6706
6705 With the --remote option, this will check the default paths for
6707 With the --remote option, this will check the default paths for
6706 incoming and outgoing changes. This can be time-consuming.
6708 incoming and outgoing changes. This can be time-consuming.
6707
6709
6708 Returns 0 on success.
6710 Returns 0 on success.
6709 """
6711 """
6710
6712
6711 ctx = repo[None]
6713 ctx = repo[None]
6712 parents = ctx.parents()
6714 parents = ctx.parents()
6713 pnode = parents[0].node()
6715 pnode = parents[0].node()
6714 marks = []
6716 marks = []
6715
6717
6716 ms = None
6718 ms = None
6717 try:
6719 try:
6718 ms = mergemod.mergestate.read(repo)
6720 ms = mergemod.mergestate.read(repo)
6719 except error.UnsupportedMergeRecords as e:
6721 except error.UnsupportedMergeRecords as e:
6720 s = ' '.join(e.recordtypes)
6722 s = ' '.join(e.recordtypes)
6721 ui.warn(
6723 ui.warn(
6722 _('warning: merge state has unsupported record types: %s\n') % s)
6724 _('warning: merge state has unsupported record types: %s\n') % s)
6723 unresolved = 0
6725 unresolved = 0
6724 else:
6726 else:
6725 unresolved = [f for f in ms if ms[f] == 'u']
6727 unresolved = [f for f in ms if ms[f] == 'u']
6726
6728
6727 for p in parents:
6729 for p in parents:
6728 # label with log.changeset (instead of log.parent) since this
6730 # label with log.changeset (instead of log.parent) since this
6729 # shows a working directory parent *changeset*:
6731 # shows a working directory parent *changeset*:
6730 # i18n: column positioning for "hg summary"
6732 # i18n: column positioning for "hg summary"
6731 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6733 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6732 label='log.changeset changeset.%s' % p.phasestr())
6734 label='log.changeset changeset.%s' % p.phasestr())
6733 ui.write(' '.join(p.tags()), label='log.tag')
6735 ui.write(' '.join(p.tags()), label='log.tag')
6734 if p.bookmarks():
6736 if p.bookmarks():
6735 marks.extend(p.bookmarks())
6737 marks.extend(p.bookmarks())
6736 if p.rev() == -1:
6738 if p.rev() == -1:
6737 if not len(repo):
6739 if not len(repo):
6738 ui.write(_(' (empty repository)'))
6740 ui.write(_(' (empty repository)'))
6739 else:
6741 else:
6740 ui.write(_(' (no revision checked out)'))
6742 ui.write(_(' (no revision checked out)'))
6741 ui.write('\n')
6743 ui.write('\n')
6742 if p.description():
6744 if p.description():
6743 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6745 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6744 label='log.summary')
6746 label='log.summary')
6745
6747
6746 branch = ctx.branch()
6748 branch = ctx.branch()
6747 bheads = repo.branchheads(branch)
6749 bheads = repo.branchheads(branch)
6748 # i18n: column positioning for "hg summary"
6750 # i18n: column positioning for "hg summary"
6749 m = _('branch: %s\n') % branch
6751 m = _('branch: %s\n') % branch
6750 if branch != 'default':
6752 if branch != 'default':
6751 ui.write(m, label='log.branch')
6753 ui.write(m, label='log.branch')
6752 else:
6754 else:
6753 ui.status(m, label='log.branch')
6755 ui.status(m, label='log.branch')
6754
6756
6755 if marks:
6757 if marks:
6756 active = repo._activebookmark
6758 active = repo._activebookmark
6757 # i18n: column positioning for "hg summary"
6759 # i18n: column positioning for "hg summary"
6758 ui.write(_('bookmarks:'), label='log.bookmark')
6760 ui.write(_('bookmarks:'), label='log.bookmark')
6759 if active is not None:
6761 if active is not None:
6760 if active in marks:
6762 if active in marks:
6761 ui.write(' *' + active, label=activebookmarklabel)
6763 ui.write(' *' + active, label=activebookmarklabel)
6762 marks.remove(active)
6764 marks.remove(active)
6763 else:
6765 else:
6764 ui.write(' [%s]' % active, label=activebookmarklabel)
6766 ui.write(' [%s]' % active, label=activebookmarklabel)
6765 for m in marks:
6767 for m in marks:
6766 ui.write(' ' + m, label='log.bookmark')
6768 ui.write(' ' + m, label='log.bookmark')
6767 ui.write('\n', label='log.bookmark')
6769 ui.write('\n', label='log.bookmark')
6768
6770
6769 status = repo.status(unknown=True)
6771 status = repo.status(unknown=True)
6770
6772
6771 c = repo.dirstate.copies()
6773 c = repo.dirstate.copies()
6772 copied, renamed = [], []
6774 copied, renamed = [], []
6773 for d, s in c.iteritems():
6775 for d, s in c.iteritems():
6774 if s in status.removed:
6776 if s in status.removed:
6775 status.removed.remove(s)
6777 status.removed.remove(s)
6776 renamed.append(d)
6778 renamed.append(d)
6777 else:
6779 else:
6778 copied.append(d)
6780 copied.append(d)
6779 if d in status.added:
6781 if d in status.added:
6780 status.added.remove(d)
6782 status.added.remove(d)
6781
6783
6782 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6784 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6783
6785
6784 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6786 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6785 (ui.label(_('%d added'), 'status.added'), status.added),
6787 (ui.label(_('%d added'), 'status.added'), status.added),
6786 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6788 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6787 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6789 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6788 (ui.label(_('%d copied'), 'status.copied'), copied),
6790 (ui.label(_('%d copied'), 'status.copied'), copied),
6789 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6791 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6790 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6792 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6791 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6793 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6792 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6794 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6793 t = []
6795 t = []
6794 for l, s in labels:
6796 for l, s in labels:
6795 if s:
6797 if s:
6796 t.append(l % len(s))
6798 t.append(l % len(s))
6797
6799
6798 t = ', '.join(t)
6800 t = ', '.join(t)
6799 cleanworkdir = False
6801 cleanworkdir = False
6800
6802
6801 if repo.vfs.exists('graftstate'):
6803 if repo.vfs.exists('graftstate'):
6802 t += _(' (graft in progress)')
6804 t += _(' (graft in progress)')
6803 if repo.vfs.exists('updatestate'):
6805 if repo.vfs.exists('updatestate'):
6804 t += _(' (interrupted update)')
6806 t += _(' (interrupted update)')
6805 elif len(parents) > 1:
6807 elif len(parents) > 1:
6806 t += _(' (merge)')
6808 t += _(' (merge)')
6807 elif branch != parents[0].branch():
6809 elif branch != parents[0].branch():
6808 t += _(' (new branch)')
6810 t += _(' (new branch)')
6809 elif (parents[0].closesbranch() and
6811 elif (parents[0].closesbranch() and
6810 pnode in repo.branchheads(branch, closed=True)):
6812 pnode in repo.branchheads(branch, closed=True)):
6811 t += _(' (head closed)')
6813 t += _(' (head closed)')
6812 elif not (status.modified or status.added or status.removed or renamed or
6814 elif not (status.modified or status.added or status.removed or renamed or
6813 copied or subs):
6815 copied or subs):
6814 t += _(' (clean)')
6816 t += _(' (clean)')
6815 cleanworkdir = True
6817 cleanworkdir = True
6816 elif pnode not in bheads:
6818 elif pnode not in bheads:
6817 t += _(' (new branch head)')
6819 t += _(' (new branch head)')
6818
6820
6819 if parents:
6821 if parents:
6820 pendingphase = max(p.phase() for p in parents)
6822 pendingphase = max(p.phase() for p in parents)
6821 else:
6823 else:
6822 pendingphase = phases.public
6824 pendingphase = phases.public
6823
6825
6824 if pendingphase > phases.newcommitphase(ui):
6826 if pendingphase > phases.newcommitphase(ui):
6825 t += ' (%s)' % phases.phasenames[pendingphase]
6827 t += ' (%s)' % phases.phasenames[pendingphase]
6826
6828
6827 if cleanworkdir:
6829 if cleanworkdir:
6828 # i18n: column positioning for "hg summary"
6830 # i18n: column positioning for "hg summary"
6829 ui.status(_('commit: %s\n') % t.strip())
6831 ui.status(_('commit: %s\n') % t.strip())
6830 else:
6832 else:
6831 # i18n: column positioning for "hg summary"
6833 # i18n: column positioning for "hg summary"
6832 ui.write(_('commit: %s\n') % t.strip())
6834 ui.write(_('commit: %s\n') % t.strip())
6833
6835
6834 # all ancestors of branch heads - all ancestors of parent = new csets
6836 # all ancestors of branch heads - all ancestors of parent = new csets
6835 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6837 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6836 bheads))
6838 bheads))
6837
6839
6838 if new == 0:
6840 if new == 0:
6839 # i18n: column positioning for "hg summary"
6841 # i18n: column positioning for "hg summary"
6840 ui.status(_('update: (current)\n'))
6842 ui.status(_('update: (current)\n'))
6841 elif pnode not in bheads:
6843 elif pnode not in bheads:
6842 # i18n: column positioning for "hg summary"
6844 # i18n: column positioning for "hg summary"
6843 ui.write(_('update: %d new changesets (update)\n') % new)
6845 ui.write(_('update: %d new changesets (update)\n') % new)
6844 else:
6846 else:
6845 # i18n: column positioning for "hg summary"
6847 # i18n: column positioning for "hg summary"
6846 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6848 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6847 (new, len(bheads)))
6849 (new, len(bheads)))
6848
6850
6849 t = []
6851 t = []
6850 draft = len(repo.revs('draft()'))
6852 draft = len(repo.revs('draft()'))
6851 if draft:
6853 if draft:
6852 t.append(_('%d draft') % draft)
6854 t.append(_('%d draft') % draft)
6853 secret = len(repo.revs('secret()'))
6855 secret = len(repo.revs('secret()'))
6854 if secret:
6856 if secret:
6855 t.append(_('%d secret') % secret)
6857 t.append(_('%d secret') % secret)
6856
6858
6857 if draft or secret:
6859 if draft or secret:
6858 ui.status(_('phases: %s\n') % ', '.join(t))
6860 ui.status(_('phases: %s\n') % ', '.join(t))
6859
6861
6860 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6862 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6861 for trouble in ("unstable", "divergent", "bumped"):
6863 for trouble in ("unstable", "divergent", "bumped"):
6862 numtrouble = len(repo.revs(trouble + "()"))
6864 numtrouble = len(repo.revs(trouble + "()"))
6863 # We write all the possibilities to ease translation
6865 # We write all the possibilities to ease translation
6864 troublemsg = {
6866 troublemsg = {
6865 "unstable": _("unstable: %d changesets"),
6867 "unstable": _("unstable: %d changesets"),
6866 "divergent": _("divergent: %d changesets"),
6868 "divergent": _("divergent: %d changesets"),
6867 "bumped": _("bumped: %d changesets"),
6869 "bumped": _("bumped: %d changesets"),
6868 }
6870 }
6869 if numtrouble > 0:
6871 if numtrouble > 0:
6870 ui.status(troublemsg[trouble] % numtrouble + "\n")
6872 ui.status(troublemsg[trouble] % numtrouble + "\n")
6871
6873
6872 cmdutil.summaryhooks(ui, repo)
6874 cmdutil.summaryhooks(ui, repo)
6873
6875
6874 if opts.get('remote'):
6876 if opts.get('remote'):
6875 needsincoming, needsoutgoing = True, True
6877 needsincoming, needsoutgoing = True, True
6876 else:
6878 else:
6877 needsincoming, needsoutgoing = False, False
6879 needsincoming, needsoutgoing = False, False
6878 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6880 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6879 if i:
6881 if i:
6880 needsincoming = True
6882 needsincoming = True
6881 if o:
6883 if o:
6882 needsoutgoing = True
6884 needsoutgoing = True
6883 if not needsincoming and not needsoutgoing:
6885 if not needsincoming and not needsoutgoing:
6884 return
6886 return
6885
6887
6886 def getincoming():
6888 def getincoming():
6887 source, branches = hg.parseurl(ui.expandpath('default'))
6889 source, branches = hg.parseurl(ui.expandpath('default'))
6888 sbranch = branches[0]
6890 sbranch = branches[0]
6889 try:
6891 try:
6890 other = hg.peer(repo, {}, source)
6892 other = hg.peer(repo, {}, source)
6891 except error.RepoError:
6893 except error.RepoError:
6892 if opts.get('remote'):
6894 if opts.get('remote'):
6893 raise
6895 raise
6894 return source, sbranch, None, None, None
6896 return source, sbranch, None, None, None
6895 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6897 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6896 if revs:
6898 if revs:
6897 revs = [other.lookup(rev) for rev in revs]
6899 revs = [other.lookup(rev) for rev in revs]
6898 ui.debug('comparing with %s\n' % util.hidepassword(source))
6900 ui.debug('comparing with %s\n' % util.hidepassword(source))
6899 repo.ui.pushbuffer()
6901 repo.ui.pushbuffer()
6900 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6902 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6901 repo.ui.popbuffer()
6903 repo.ui.popbuffer()
6902 return source, sbranch, other, commoninc, commoninc[1]
6904 return source, sbranch, other, commoninc, commoninc[1]
6903
6905
6904 if needsincoming:
6906 if needsincoming:
6905 source, sbranch, sother, commoninc, incoming = getincoming()
6907 source, sbranch, sother, commoninc, incoming = getincoming()
6906 else:
6908 else:
6907 source = sbranch = sother = commoninc = incoming = None
6909 source = sbranch = sother = commoninc = incoming = None
6908
6910
6909 def getoutgoing():
6911 def getoutgoing():
6910 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6912 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6911 dbranch = branches[0]
6913 dbranch = branches[0]
6912 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6914 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6913 if source != dest:
6915 if source != dest:
6914 try:
6916 try:
6915 dother = hg.peer(repo, {}, dest)
6917 dother = hg.peer(repo, {}, dest)
6916 except error.RepoError:
6918 except error.RepoError:
6917 if opts.get('remote'):
6919 if opts.get('remote'):
6918 raise
6920 raise
6919 return dest, dbranch, None, None
6921 return dest, dbranch, None, None
6920 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6922 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6921 elif sother is None:
6923 elif sother is None:
6922 # there is no explicit destination peer, but source one is invalid
6924 # there is no explicit destination peer, but source one is invalid
6923 return dest, dbranch, None, None
6925 return dest, dbranch, None, None
6924 else:
6926 else:
6925 dother = sother
6927 dother = sother
6926 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6928 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6927 common = None
6929 common = None
6928 else:
6930 else:
6929 common = commoninc
6931 common = commoninc
6930 if revs:
6932 if revs:
6931 revs = [repo.lookup(rev) for rev in revs]
6933 revs = [repo.lookup(rev) for rev in revs]
6932 repo.ui.pushbuffer()
6934 repo.ui.pushbuffer()
6933 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6935 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6934 commoninc=common)
6936 commoninc=common)
6935 repo.ui.popbuffer()
6937 repo.ui.popbuffer()
6936 return dest, dbranch, dother, outgoing
6938 return dest, dbranch, dother, outgoing
6937
6939
6938 if needsoutgoing:
6940 if needsoutgoing:
6939 dest, dbranch, dother, outgoing = getoutgoing()
6941 dest, dbranch, dother, outgoing = getoutgoing()
6940 else:
6942 else:
6941 dest = dbranch = dother = outgoing = None
6943 dest = dbranch = dother = outgoing = None
6942
6944
6943 if opts.get('remote'):
6945 if opts.get('remote'):
6944 t = []
6946 t = []
6945 if incoming:
6947 if incoming:
6946 t.append(_('1 or more incoming'))
6948 t.append(_('1 or more incoming'))
6947 o = outgoing.missing
6949 o = outgoing.missing
6948 if o:
6950 if o:
6949 t.append(_('%d outgoing') % len(o))
6951 t.append(_('%d outgoing') % len(o))
6950 other = dother or sother
6952 other = dother or sother
6951 if 'bookmarks' in other.listkeys('namespaces'):
6953 if 'bookmarks' in other.listkeys('namespaces'):
6952 counts = bookmarks.summary(repo, other)
6954 counts = bookmarks.summary(repo, other)
6953 if counts[0] > 0:
6955 if counts[0] > 0:
6954 t.append(_('%d incoming bookmarks') % counts[0])
6956 t.append(_('%d incoming bookmarks') % counts[0])
6955 if counts[1] > 0:
6957 if counts[1] > 0:
6956 t.append(_('%d outgoing bookmarks') % counts[1])
6958 t.append(_('%d outgoing bookmarks') % counts[1])
6957
6959
6958 if t:
6960 if t:
6959 # i18n: column positioning for "hg summary"
6961 # i18n: column positioning for "hg summary"
6960 ui.write(_('remote: %s\n') % (', '.join(t)))
6962 ui.write(_('remote: %s\n') % (', '.join(t)))
6961 else:
6963 else:
6962 # i18n: column positioning for "hg summary"
6964 # i18n: column positioning for "hg summary"
6963 ui.status(_('remote: (synced)\n'))
6965 ui.status(_('remote: (synced)\n'))
6964
6966
6965 cmdutil.summaryremotehooks(ui, repo, opts,
6967 cmdutil.summaryremotehooks(ui, repo, opts,
6966 ((source, sbranch, sother, commoninc),
6968 ((source, sbranch, sother, commoninc),
6967 (dest, dbranch, dother, outgoing)))
6969 (dest, dbranch, dother, outgoing)))
6968
6970
6969 @command('tag',
6971 @command('tag',
6970 [('f', 'force', None, _('force tag')),
6972 [('f', 'force', None, _('force tag')),
6971 ('l', 'local', None, _('make the tag local')),
6973 ('l', 'local', None, _('make the tag local')),
6972 ('r', 'rev', '', _('revision to tag'), _('REV')),
6974 ('r', 'rev', '', _('revision to tag'), _('REV')),
6973 ('', 'remove', None, _('remove a tag')),
6975 ('', 'remove', None, _('remove a tag')),
6974 # -l/--local is already there, commitopts cannot be used
6976 # -l/--local is already there, commitopts cannot be used
6975 ('e', 'edit', None, _('invoke editor on commit messages')),
6977 ('e', 'edit', None, _('invoke editor on commit messages')),
6976 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6978 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6977 ] + commitopts2,
6979 ] + commitopts2,
6978 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6980 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6979 def tag(ui, repo, name1, *names, **opts):
6981 def tag(ui, repo, name1, *names, **opts):
6980 """add one or more tags for the current or given revision
6982 """add one or more tags for the current or given revision
6981
6983
6982 Name a particular revision using <name>.
6984 Name a particular revision using <name>.
6983
6985
6984 Tags are used to name particular revisions of the repository and are
6986 Tags are used to name particular revisions of the repository and are
6985 very useful to compare different revisions, to go back to significant
6987 very useful to compare different revisions, to go back to significant
6986 earlier versions or to mark branch points as releases, etc. Changing
6988 earlier versions or to mark branch points as releases, etc. Changing
6987 an existing tag is normally disallowed; use -f/--force to override.
6989 an existing tag is normally disallowed; use -f/--force to override.
6988
6990
6989 If no revision is given, the parent of the working directory is
6991 If no revision is given, the parent of the working directory is
6990 used.
6992 used.
6991
6993
6992 To facilitate version control, distribution, and merging of tags,
6994 To facilitate version control, distribution, and merging of tags,
6993 they are stored as a file named ".hgtags" which is managed similarly
6995 they are stored as a file named ".hgtags" which is managed similarly
6994 to other project files and can be hand-edited if necessary. This
6996 to other project files and can be hand-edited if necessary. This
6995 also means that tagging creates a new commit. The file
6997 also means that tagging creates a new commit. The file
6996 ".hg/localtags" is used for local tags (not shared among
6998 ".hg/localtags" is used for local tags (not shared among
6997 repositories).
6999 repositories).
6998
7000
6999 Tag commits are usually made at the head of a branch. If the parent
7001 Tag commits are usually made at the head of a branch. If the parent
7000 of the working directory is not a branch head, :hg:`tag` aborts; use
7002 of the working directory is not a branch head, :hg:`tag` aborts; use
7001 -f/--force to force the tag commit to be based on a non-head
7003 -f/--force to force the tag commit to be based on a non-head
7002 changeset.
7004 changeset.
7003
7005
7004 See :hg:`help dates` for a list of formats valid for -d/--date.
7006 See :hg:`help dates` for a list of formats valid for -d/--date.
7005
7007
7006 Since tag names have priority over branch names during revision
7008 Since tag names have priority over branch names during revision
7007 lookup, using an existing branch name as a tag name is discouraged.
7009 lookup, using an existing branch name as a tag name is discouraged.
7008
7010
7009 Returns 0 on success.
7011 Returns 0 on success.
7010 """
7012 """
7011 wlock = lock = None
7013 wlock = lock = None
7012 try:
7014 try:
7013 wlock = repo.wlock()
7015 wlock = repo.wlock()
7014 lock = repo.lock()
7016 lock = repo.lock()
7015 rev_ = "."
7017 rev_ = "."
7016 names = [t.strip() for t in (name1,) + names]
7018 names = [t.strip() for t in (name1,) + names]
7017 if len(names) != len(set(names)):
7019 if len(names) != len(set(names)):
7018 raise error.Abort(_('tag names must be unique'))
7020 raise error.Abort(_('tag names must be unique'))
7019 for n in names:
7021 for n in names:
7020 scmutil.checknewlabel(repo, n, 'tag')
7022 scmutil.checknewlabel(repo, n, 'tag')
7021 if not n:
7023 if not n:
7022 raise error.Abort(_('tag names cannot consist entirely of '
7024 raise error.Abort(_('tag names cannot consist entirely of '
7023 'whitespace'))
7025 'whitespace'))
7024 if opts.get('rev') and opts.get('remove'):
7026 if opts.get('rev') and opts.get('remove'):
7025 raise error.Abort(_("--rev and --remove are incompatible"))
7027 raise error.Abort(_("--rev and --remove are incompatible"))
7026 if opts.get('rev'):
7028 if opts.get('rev'):
7027 rev_ = opts['rev']
7029 rev_ = opts['rev']
7028 message = opts.get('message')
7030 message = opts.get('message')
7029 if opts.get('remove'):
7031 if opts.get('remove'):
7030 if opts.get('local'):
7032 if opts.get('local'):
7031 expectedtype = 'local'
7033 expectedtype = 'local'
7032 else:
7034 else:
7033 expectedtype = 'global'
7035 expectedtype = 'global'
7034
7036
7035 for n in names:
7037 for n in names:
7036 if not repo.tagtype(n):
7038 if not repo.tagtype(n):
7037 raise error.Abort(_("tag '%s' does not exist") % n)
7039 raise error.Abort(_("tag '%s' does not exist") % n)
7038 if repo.tagtype(n) != expectedtype:
7040 if repo.tagtype(n) != expectedtype:
7039 if expectedtype == 'global':
7041 if expectedtype == 'global':
7040 raise error.Abort(_("tag '%s' is not a global tag") % n)
7042 raise error.Abort(_("tag '%s' is not a global tag") % n)
7041 else:
7043 else:
7042 raise error.Abort(_("tag '%s' is not a local tag") % n)
7044 raise error.Abort(_("tag '%s' is not a local tag") % n)
7043 rev_ = 'null'
7045 rev_ = 'null'
7044 if not message:
7046 if not message:
7045 # we don't translate commit messages
7047 # we don't translate commit messages
7046 message = 'Removed tag %s' % ', '.join(names)
7048 message = 'Removed tag %s' % ', '.join(names)
7047 elif not opts.get('force'):
7049 elif not opts.get('force'):
7048 for n in names:
7050 for n in names:
7049 if n in repo.tags():
7051 if n in repo.tags():
7050 raise error.Abort(_("tag '%s' already exists "
7052 raise error.Abort(_("tag '%s' already exists "
7051 "(use -f to force)") % n)
7053 "(use -f to force)") % n)
7052 if not opts.get('local'):
7054 if not opts.get('local'):
7053 p1, p2 = repo.dirstate.parents()
7055 p1, p2 = repo.dirstate.parents()
7054 if p2 != nullid:
7056 if p2 != nullid:
7055 raise error.Abort(_('uncommitted merge'))
7057 raise error.Abort(_('uncommitted merge'))
7056 bheads = repo.branchheads()
7058 bheads = repo.branchheads()
7057 if not opts.get('force') and bheads and p1 not in bheads:
7059 if not opts.get('force') and bheads and p1 not in bheads:
7058 raise error.Abort(_('not at a branch head (use -f to force)'))
7060 raise error.Abort(_('not at a branch head (use -f to force)'))
7059 r = scmutil.revsingle(repo, rev_).node()
7061 r = scmutil.revsingle(repo, rev_).node()
7060
7062
7061 if not message:
7063 if not message:
7062 # we don't translate commit messages
7064 # we don't translate commit messages
7063 message = ('Added tag %s for changeset %s' %
7065 message = ('Added tag %s for changeset %s' %
7064 (', '.join(names), short(r)))
7066 (', '.join(names), short(r)))
7065
7067
7066 date = opts.get('date')
7068 date = opts.get('date')
7067 if date:
7069 if date:
7068 date = util.parsedate(date)
7070 date = util.parsedate(date)
7069
7071
7070 if opts.get('remove'):
7072 if opts.get('remove'):
7071 editform = 'tag.remove'
7073 editform = 'tag.remove'
7072 else:
7074 else:
7073 editform = 'tag.add'
7075 editform = 'tag.add'
7074 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7076 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7075
7077
7076 # don't allow tagging the null rev
7078 # don't allow tagging the null rev
7077 if (not opts.get('remove') and
7079 if (not opts.get('remove') and
7078 scmutil.revsingle(repo, rev_).rev() == nullrev):
7080 scmutil.revsingle(repo, rev_).rev() == nullrev):
7079 raise error.Abort(_("cannot tag null revision"))
7081 raise error.Abort(_("cannot tag null revision"))
7080
7082
7081 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7083 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7082 editor=editor)
7084 editor=editor)
7083 finally:
7085 finally:
7084 release(lock, wlock)
7086 release(lock, wlock)
7085
7087
7086 @command('tags', formatteropts, '')
7088 @command('tags', formatteropts, '')
7087 def tags(ui, repo, **opts):
7089 def tags(ui, repo, **opts):
7088 """list repository tags
7090 """list repository tags
7089
7091
7090 This lists both regular and local tags. When the -v/--verbose
7092 This lists both regular and local tags. When the -v/--verbose
7091 switch is used, a third column "local" is printed for local tags.
7093 switch is used, a third column "local" is printed for local tags.
7092 When the -q/--quiet switch is used, only the tag name is printed.
7094 When the -q/--quiet switch is used, only the tag name is printed.
7093
7095
7094 Returns 0 on success.
7096 Returns 0 on success.
7095 """
7097 """
7096
7098
7097 fm = ui.formatter('tags', opts)
7099 fm = ui.formatter('tags', opts)
7098 hexfunc = fm.hexfunc
7100 hexfunc = fm.hexfunc
7099 tagtype = ""
7101 tagtype = ""
7100
7102
7101 for t, n in reversed(repo.tagslist()):
7103 for t, n in reversed(repo.tagslist()):
7102 hn = hexfunc(n)
7104 hn = hexfunc(n)
7103 label = 'tags.normal'
7105 label = 'tags.normal'
7104 tagtype = ''
7106 tagtype = ''
7105 if repo.tagtype(t) == 'local':
7107 if repo.tagtype(t) == 'local':
7106 label = 'tags.local'
7108 label = 'tags.local'
7107 tagtype = 'local'
7109 tagtype = 'local'
7108
7110
7109 fm.startitem()
7111 fm.startitem()
7110 fm.write('tag', '%s', t, label=label)
7112 fm.write('tag', '%s', t, label=label)
7111 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7113 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7112 fm.condwrite(not ui.quiet, 'rev node', fmt,
7114 fm.condwrite(not ui.quiet, 'rev node', fmt,
7113 repo.changelog.rev(n), hn, label=label)
7115 repo.changelog.rev(n), hn, label=label)
7114 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7116 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7115 tagtype, label=label)
7117 tagtype, label=label)
7116 fm.plain('\n')
7118 fm.plain('\n')
7117 fm.end()
7119 fm.end()
7118
7120
7119 @command('tip',
7121 @command('tip',
7120 [('p', 'patch', None, _('show patch')),
7122 [('p', 'patch', None, _('show patch')),
7121 ('g', 'git', None, _('use git extended diff format')),
7123 ('g', 'git', None, _('use git extended diff format')),
7122 ] + templateopts,
7124 ] + templateopts,
7123 _('[-p] [-g]'))
7125 _('[-p] [-g]'))
7124 def tip(ui, repo, **opts):
7126 def tip(ui, repo, **opts):
7125 """show the tip revision (DEPRECATED)
7127 """show the tip revision (DEPRECATED)
7126
7128
7127 The tip revision (usually just called the tip) is the changeset
7129 The tip revision (usually just called the tip) is the changeset
7128 most recently added to the repository (and therefore the most
7130 most recently added to the repository (and therefore the most
7129 recently changed head).
7131 recently changed head).
7130
7132
7131 If you have just made a commit, that commit will be the tip. If
7133 If you have just made a commit, that commit will be the tip. If
7132 you have just pulled changes from another repository, the tip of
7134 you have just pulled changes from another repository, the tip of
7133 that repository becomes the current tip. The "tip" tag is special
7135 that repository becomes the current tip. The "tip" tag is special
7134 and cannot be renamed or assigned to a different changeset.
7136 and cannot be renamed or assigned to a different changeset.
7135
7137
7136 This command is deprecated, please use :hg:`heads` instead.
7138 This command is deprecated, please use :hg:`heads` instead.
7137
7139
7138 Returns 0 on success.
7140 Returns 0 on success.
7139 """
7141 """
7140 displayer = cmdutil.show_changeset(ui, repo, opts)
7142 displayer = cmdutil.show_changeset(ui, repo, opts)
7141 displayer.show(repo['tip'])
7143 displayer.show(repo['tip'])
7142 displayer.close()
7144 displayer.close()
7143
7145
7144 @command('unbundle',
7146 @command('unbundle',
7145 [('u', 'update', None,
7147 [('u', 'update', None,
7146 _('update to new branch head if changesets were unbundled'))],
7148 _('update to new branch head if changesets were unbundled'))],
7147 _('[-u] FILE...'))
7149 _('[-u] FILE...'))
7148 def unbundle(ui, repo, fname1, *fnames, **opts):
7150 def unbundle(ui, repo, fname1, *fnames, **opts):
7149 """apply one or more changegroup files
7151 """apply one or more changegroup files
7150
7152
7151 Apply one or more compressed changegroup files generated by the
7153 Apply one or more compressed changegroup files generated by the
7152 bundle command.
7154 bundle command.
7153
7155
7154 Returns 0 on success, 1 if an update has unresolved files.
7156 Returns 0 on success, 1 if an update has unresolved files.
7155 """
7157 """
7156 fnames = (fname1,) + fnames
7158 fnames = (fname1,) + fnames
7157
7159
7158 with repo.lock():
7160 with repo.lock():
7159 for fname in fnames:
7161 for fname in fnames:
7160 f = hg.openpath(ui, fname)
7162 f = hg.openpath(ui, fname)
7161 gen = exchange.readbundle(ui, f, fname)
7163 gen = exchange.readbundle(ui, f, fname)
7162 if isinstance(gen, bundle2.unbundle20):
7164 if isinstance(gen, bundle2.unbundle20):
7163 tr = repo.transaction('unbundle')
7165 tr = repo.transaction('unbundle')
7164 try:
7166 try:
7165 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7167 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7166 url='bundle:' + fname)
7168 url='bundle:' + fname)
7167 tr.close()
7169 tr.close()
7168 except error.BundleUnknownFeatureError as exc:
7170 except error.BundleUnknownFeatureError as exc:
7169 raise error.Abort(_('%s: unknown bundle feature, %s')
7171 raise error.Abort(_('%s: unknown bundle feature, %s')
7170 % (fname, exc),
7172 % (fname, exc),
7171 hint=_("see https://mercurial-scm.org/"
7173 hint=_("see https://mercurial-scm.org/"
7172 "wiki/BundleFeature for more "
7174 "wiki/BundleFeature for more "
7173 "information"))
7175 "information"))
7174 finally:
7176 finally:
7175 if tr:
7177 if tr:
7176 tr.release()
7178 tr.release()
7177 changes = [r.get('return', 0)
7179 changes = [r.get('return', 0)
7178 for r in op.records['changegroup']]
7180 for r in op.records['changegroup']]
7179 modheads = changegroup.combineresults(changes)
7181 modheads = changegroup.combineresults(changes)
7180 elif isinstance(gen, streamclone.streamcloneapplier):
7182 elif isinstance(gen, streamclone.streamcloneapplier):
7181 raise error.Abort(
7183 raise error.Abort(
7182 _('packed bundles cannot be applied with '
7184 _('packed bundles cannot be applied with '
7183 '"hg unbundle"'),
7185 '"hg unbundle"'),
7184 hint=_('use "hg debugapplystreamclonebundle"'))
7186 hint=_('use "hg debugapplystreamclonebundle"'))
7185 else:
7187 else:
7186 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7188 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7187
7189
7188 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7190 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7189
7191
7190 @command('^update|up|checkout|co',
7192 @command('^update|up|checkout|co',
7191 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7193 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7192 ('c', 'check', None, _('require clean working directory')),
7194 ('c', 'check', None, _('require clean working directory')),
7193 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7195 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7194 ('r', 'rev', '', _('revision'), _('REV'))
7196 ('r', 'rev', '', _('revision'), _('REV'))
7195 ] + mergetoolopts,
7197 ] + mergetoolopts,
7196 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7198 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7197 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7199 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7198 tool=None):
7200 tool=None):
7199 """update working directory (or switch revisions)
7201 """update working directory (or switch revisions)
7200
7202
7201 Update the repository's working directory to the specified
7203 Update the repository's working directory to the specified
7202 changeset. If no changeset is specified, update to the tip of the
7204 changeset. If no changeset is specified, update to the tip of the
7203 current named branch and move the active bookmark (see :hg:`help
7205 current named branch and move the active bookmark (see :hg:`help
7204 bookmarks`).
7206 bookmarks`).
7205
7207
7206 Update sets the working directory's parent revision to the specified
7208 Update sets the working directory's parent revision to the specified
7207 changeset (see :hg:`help parents`).
7209 changeset (see :hg:`help parents`).
7208
7210
7209 If the changeset is not a descendant or ancestor of the working
7211 If the changeset is not a descendant or ancestor of the working
7210 directory's parent, the update is aborted. With the -c/--check
7212 directory's parent, the update is aborted. With the -c/--check
7211 option, the working directory is checked for uncommitted changes; if
7213 option, the working directory is checked for uncommitted changes; if
7212 none are found, the working directory is updated to the specified
7214 none are found, the working directory is updated to the specified
7213 changeset.
7215 changeset.
7214
7216
7215 .. container:: verbose
7217 .. container:: verbose
7216
7218
7217 The following rules apply when the working directory contains
7219 The following rules apply when the working directory contains
7218 uncommitted changes:
7220 uncommitted changes:
7219
7221
7220 1. If neither -c/--check nor -C/--clean is specified, and if
7222 1. If neither -c/--check nor -C/--clean is specified, and if
7221 the requested changeset is an ancestor or descendant of
7223 the requested changeset is an ancestor or descendant of
7222 the working directory's parent, the uncommitted changes
7224 the working directory's parent, the uncommitted changes
7223 are merged into the requested changeset and the merged
7225 are merged into the requested changeset and the merged
7224 result is left uncommitted. If the requested changeset is
7226 result is left uncommitted. If the requested changeset is
7225 not an ancestor or descendant (that is, it is on another
7227 not an ancestor or descendant (that is, it is on another
7226 branch), the update is aborted and the uncommitted changes
7228 branch), the update is aborted and the uncommitted changes
7227 are preserved.
7229 are preserved.
7228
7230
7229 2. With the -c/--check option, the update is aborted and the
7231 2. With the -c/--check option, the update is aborted and the
7230 uncommitted changes are preserved.
7232 uncommitted changes are preserved.
7231
7233
7232 3. With the -C/--clean option, uncommitted changes are discarded and
7234 3. With the -C/--clean option, uncommitted changes are discarded and
7233 the working directory is updated to the requested changeset.
7235 the working directory is updated to the requested changeset.
7234
7236
7235 To cancel an uncommitted merge (and lose your changes), use
7237 To cancel an uncommitted merge (and lose your changes), use
7236 :hg:`update --clean .`.
7238 :hg:`update --clean .`.
7237
7239
7238 Use null as the changeset to remove the working directory (like
7240 Use null as the changeset to remove the working directory (like
7239 :hg:`clone -U`).
7241 :hg:`clone -U`).
7240
7242
7241 If you want to revert just one file to an older revision, use
7243 If you want to revert just one file to an older revision, use
7242 :hg:`revert [-r REV] NAME`.
7244 :hg:`revert [-r REV] NAME`.
7243
7245
7244 See :hg:`help dates` for a list of formats valid for -d/--date.
7246 See :hg:`help dates` for a list of formats valid for -d/--date.
7245
7247
7246 Returns 0 on success, 1 if there are unresolved files.
7248 Returns 0 on success, 1 if there are unresolved files.
7247 """
7249 """
7248 if rev and node:
7250 if rev and node:
7249 raise error.Abort(_("please specify just one revision"))
7251 raise error.Abort(_("please specify just one revision"))
7250
7252
7251 if rev is None or rev == '':
7253 if rev is None or rev == '':
7252 rev = node
7254 rev = node
7253
7255
7254 if date and rev is not None:
7256 if date and rev is not None:
7255 raise error.Abort(_("you can't specify a revision and a date"))
7257 raise error.Abort(_("you can't specify a revision and a date"))
7256
7258
7257 if check and clean:
7259 if check and clean:
7258 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7260 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7259
7261
7260 with repo.wlock():
7262 with repo.wlock():
7261 cmdutil.clearunfinished(repo)
7263 cmdutil.clearunfinished(repo)
7262
7264
7263 if date:
7265 if date:
7264 rev = cmdutil.finddate(ui, repo, date)
7266 rev = cmdutil.finddate(ui, repo, date)
7265
7267
7266 # if we defined a bookmark, we have to remember the original name
7268 # if we defined a bookmark, we have to remember the original name
7267 brev = rev
7269 brev = rev
7268 rev = scmutil.revsingle(repo, rev, rev).rev()
7270 rev = scmutil.revsingle(repo, rev, rev).rev()
7269
7271
7270 if check:
7272 if check:
7271 cmdutil.bailifchanged(repo, merge=False)
7273 cmdutil.bailifchanged(repo, merge=False)
7272
7274
7273 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7275 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7274
7276
7275 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7277 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7276
7278
7277 @command('verify', [])
7279 @command('verify', [])
7278 def verify(ui, repo):
7280 def verify(ui, repo):
7279 """verify the integrity of the repository
7281 """verify the integrity of the repository
7280
7282
7281 Verify the integrity of the current repository.
7283 Verify the integrity of the current repository.
7282
7284
7283 This will perform an extensive check of the repository's
7285 This will perform an extensive check of the repository's
7284 integrity, validating the hashes and checksums of each entry in
7286 integrity, validating the hashes and checksums of each entry in
7285 the changelog, manifest, and tracked files, as well as the
7287 the changelog, manifest, and tracked files, as well as the
7286 integrity of their crosslinks and indices.
7288 integrity of their crosslinks and indices.
7287
7289
7288 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7290 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7289 for more information about recovery from corruption of the
7291 for more information about recovery from corruption of the
7290 repository.
7292 repository.
7291
7293
7292 Returns 0 on success, 1 if errors are encountered.
7294 Returns 0 on success, 1 if errors are encountered.
7293 """
7295 """
7294 return hg.verify(repo)
7296 return hg.verify(repo)
7295
7297
7296 @command('version', [] + formatteropts, norepo=True)
7298 @command('version', [] + formatteropts, norepo=True)
7297 def version_(ui, **opts):
7299 def version_(ui, **opts):
7298 """output version and copyright information"""
7300 """output version and copyright information"""
7299 fm = ui.formatter("version", opts)
7301 fm = ui.formatter("version", opts)
7300 fm.startitem()
7302 fm.startitem()
7301 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7303 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7302 util.version())
7304 util.version())
7303 license = _(
7305 license = _(
7304 "(see https://mercurial-scm.org for more information)\n"
7306 "(see https://mercurial-scm.org for more information)\n"
7305 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7307 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7306 "This is free software; see the source for copying conditions. "
7308 "This is free software; see the source for copying conditions. "
7307 "There is NO\nwarranty; "
7309 "There is NO\nwarranty; "
7308 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7310 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7309 )
7311 )
7310 if not ui.quiet:
7312 if not ui.quiet:
7311 fm.plain(license)
7313 fm.plain(license)
7312
7314
7313 if ui.verbose:
7315 if ui.verbose:
7314 fm.plain(_("\nEnabled extensions:\n\n"))
7316 fm.plain(_("\nEnabled extensions:\n\n"))
7315 # format names and versions into columns
7317 # format names and versions into columns
7316 names = []
7318 names = []
7317 vers = []
7319 vers = []
7318 isinternals = []
7320 isinternals = []
7319 for name, module in extensions.extensions():
7321 for name, module in extensions.extensions():
7320 names.append(name)
7322 names.append(name)
7321 vers.append(extensions.moduleversion(module) or None)
7323 vers.append(extensions.moduleversion(module) or None)
7322 isinternals.append(extensions.ismoduleinternal(module))
7324 isinternals.append(extensions.ismoduleinternal(module))
7323 fn = fm.nested("extensions")
7325 fn = fm.nested("extensions")
7324 if names:
7326 if names:
7325 namefmt = " %%-%ds " % max(len(n) for n in names)
7327 namefmt = " %%-%ds " % max(len(n) for n in names)
7326 places = [_("external"), _("internal")]
7328 places = [_("external"), _("internal")]
7327 for n, v, p in zip(names, vers, isinternals):
7329 for n, v, p in zip(names, vers, isinternals):
7328 fn.startitem()
7330 fn.startitem()
7329 fn.condwrite(ui.verbose, "name", namefmt, n)
7331 fn.condwrite(ui.verbose, "name", namefmt, n)
7330 if ui.verbose:
7332 if ui.verbose:
7331 fn.plain("%s " % places[p])
7333 fn.plain("%s " % places[p])
7332 fn.data(bundled=p)
7334 fn.data(bundled=p)
7333 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7335 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7334 if ui.verbose:
7336 if ui.verbose:
7335 fn.plain("\n")
7337 fn.plain("\n")
7336 fn.end()
7338 fn.end()
7337 fm.end()
7339 fm.end()
7338
7340
7339 def loadcmdtable(ui, name, cmdtable):
7341 def loadcmdtable(ui, name, cmdtable):
7340 """Load command functions from specified cmdtable
7342 """Load command functions from specified cmdtable
7341 """
7343 """
7342 overrides = [cmd for cmd in cmdtable if cmd in table]
7344 overrides = [cmd for cmd in cmdtable if cmd in table]
7343 if overrides:
7345 if overrides:
7344 ui.warn(_("extension '%s' overrides commands: %s\n")
7346 ui.warn(_("extension '%s' overrides commands: %s\n")
7345 % (name, " ".join(overrides)))
7347 % (name, " ".join(overrides)))
7346 table.update(cmdtable)
7348 table.update(cmdtable)
@@ -1,403 +1,405 b''
1 Set up a repo
1 Set up a repo
2
2
3 $ cp $HGRCPATH $HGRCPATH.pretest
3 $ cp $HGRCPATH $HGRCPATH.pretest
4 $ cat <<EOF >> $HGRCPATH
4 $ cat <<EOF >> $HGRCPATH
5 > [ui]
5 > [ui]
6 > interactive = true
6 > interactive = true
7 > interface = curses
7 > interface = curses
8 > [experimental]
8 > [experimental]
9 > crecordtest = testModeCommands
9 > crecordtest = testModeCommands
10 > EOF
10 > EOF
11
11
12 Record with noeol at eof (issue5268)
12 Record with noeol at eof (issue5268)
13 $ hg init noeol
13 $ hg init noeol
14 $ cd noeol
14 $ cd noeol
15 $ printf '0' > a
15 $ printf '0' > a
16 $ printf '0\n' > b
16 $ printf '0\n' > b
17 $ hg ci -Aqm initial
17 $ hg ci -Aqm initial
18 $ printf '1\n0' > a
18 $ printf '1\n0' > a
19 $ printf '1\n0\n' > b
19 $ printf '1\n0\n' > b
20 $ cat <<EOF >testModeCommands
20 $ cat <<EOF >testModeCommands
21 > c
21 > c
22 > EOF
22 > EOF
23 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "add hunks" -d "0 0"
23 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "add hunks" -d "0 0"
24 $ cd ..
24 $ cd ..
25
25
26 Normal repo
26 Normal repo
27 $ hg init a
27 $ hg init a
28 $ cd a
28 $ cd a
29
29
30 Committing some changes but stopping on the way
30 Committing some changes but stopping on the way
31
31
32 $ echo "a" > a
32 $ echo "a" > a
33 $ hg add a
33 $ hg add a
34 $ cat <<EOF >testModeCommands
34 $ cat <<EOF >testModeCommands
35 > TOGGLE
35 > TOGGLE
36 > X
36 > X
37 > EOF
37 > EOF
38 $ hg commit -i -m "a" -d "0 0"
38 $ hg commit -i -m "a" -d "0 0"
39 no changes to record
39 no changes to record
40 [1]
40 $ hg tip
41 $ hg tip
41 changeset: -1:000000000000
42 changeset: -1:000000000000
42 tag: tip
43 tag: tip
43 user:
44 user:
44 date: Thu Jan 01 00:00:00 1970 +0000
45 date: Thu Jan 01 00:00:00 1970 +0000
45
46
46
47
47 Committing some changes
48 Committing some changes
48
49
49 $ cat <<EOF >testModeCommands
50 $ cat <<EOF >testModeCommands
50 > X
51 > X
51 > EOF
52 > EOF
52 $ hg commit -i -m "a" -d "0 0"
53 $ hg commit -i -m "a" -d "0 0"
53 $ hg tip
54 $ hg tip
54 changeset: 0:cb9a9f314b8b
55 changeset: 0:cb9a9f314b8b
55 tag: tip
56 tag: tip
56 user: test
57 user: test
57 date: Thu Jan 01 00:00:00 1970 +0000
58 date: Thu Jan 01 00:00:00 1970 +0000
58 summary: a
59 summary: a
59
60
60 Check that commit -i works with no changes
61 Check that commit -i works with no changes
61 $ hg commit -i
62 $ hg commit -i
62 no changes to record
63 no changes to record
64 [1]
63
65
64 Committing only one file
66 Committing only one file
65
67
66 $ echo "a" >> a
68 $ echo "a" >> a
67 >>> open('b', 'wb').write("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
69 >>> open('b', 'wb').write("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")
68 $ hg add b
70 $ hg add b
69 $ cat <<EOF >testModeCommands
71 $ cat <<EOF >testModeCommands
70 > TOGGLE
72 > TOGGLE
71 > KEY_DOWN
73 > KEY_DOWN
72 > X
74 > X
73 > EOF
75 > EOF
74 $ hg commit -i -m "one file" -d "0 0"
76 $ hg commit -i -m "one file" -d "0 0"
75 $ hg tip
77 $ hg tip
76 changeset: 1:fb2705a663ea
78 changeset: 1:fb2705a663ea
77 tag: tip
79 tag: tip
78 user: test
80 user: test
79 date: Thu Jan 01 00:00:00 1970 +0000
81 date: Thu Jan 01 00:00:00 1970 +0000
80 summary: one file
82 summary: one file
81
83
82 $ hg cat -r tip a
84 $ hg cat -r tip a
83 a
85 a
84 $ cat a
86 $ cat a
85 a
87 a
86 a
88 a
87
89
88 Committing only one hunk while aborting edition of hunk
90 Committing only one hunk while aborting edition of hunk
89
91
90 - Untoggle all the hunks, go down to the second file
92 - Untoggle all the hunks, go down to the second file
91 - unfold it
93 - unfold it
92 - go down to second hunk (1 for the first hunk, 1 for the first hunkline, 1 for the second hunk, 1 for the second hunklike)
94 - go down to second hunk (1 for the first hunk, 1 for the first hunkline, 1 for the second hunk, 1 for the second hunklike)
93 - toggle the second hunk
95 - toggle the second hunk
94 - toggle on and off the amend mode (to check that it toggles off)
96 - toggle on and off the amend mode (to check that it toggles off)
95 - edit the hunk and quit the editor immediately with non-zero status
97 - edit the hunk and quit the editor immediately with non-zero status
96 - commit
98 - commit
97
99
98 $ printf "printf 'editor ran\n'; exit 1" > editor.sh
100 $ printf "printf 'editor ran\n'; exit 1" > editor.sh
99 $ echo "x" > c
101 $ echo "x" > c
100 $ cat b >> c
102 $ cat b >> c
101 $ echo "y" >> c
103 $ echo "y" >> c
102 $ mv c b
104 $ mv c b
103 $ cat <<EOF >testModeCommands
105 $ cat <<EOF >testModeCommands
104 > A
106 > A
105 > KEY_DOWN
107 > KEY_DOWN
106 > f
108 > f
107 > KEY_DOWN
109 > KEY_DOWN
108 > KEY_DOWN
110 > KEY_DOWN
109 > KEY_DOWN
111 > KEY_DOWN
110 > KEY_DOWN
112 > KEY_DOWN
111 > TOGGLE
113 > TOGGLE
112 > a
114 > a
113 > a
115 > a
114 > e
116 > e
115 > X
117 > X
116 > EOF
118 > EOF
117 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "one hunk" -d "0 0"
119 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "one hunk" -d "0 0"
118 editor ran
120 editor ran
119 $ rm editor.sh
121 $ rm editor.sh
120 $ hg tip
122 $ hg tip
121 changeset: 2:7d10dfe755a8
123 changeset: 2:7d10dfe755a8
122 tag: tip
124 tag: tip
123 user: test
125 user: test
124 date: Thu Jan 01 00:00:00 1970 +0000
126 date: Thu Jan 01 00:00:00 1970 +0000
125 summary: one hunk
127 summary: one hunk
126
128
127 $ hg cat -r tip b
129 $ hg cat -r tip b
128 1
130 1
129 2
131 2
130 3
132 3
131 4
133 4
132 5
134 5
133 6
135 6
134 7
136 7
135 8
137 8
136 9
138 9
137 10
139 10
138 y
140 y
139 $ cat b
141 $ cat b
140 x
142 x
141 1
143 1
142 2
144 2
143 3
145 3
144 4
146 4
145 5
147 5
146 6
148 6
147 7
149 7
148 8
150 8
149 9
151 9
150 10
152 10
151 y
153 y
152 $ hg commit -m "other hunks"
154 $ hg commit -m "other hunks"
153 $ hg tip
155 $ hg tip
154 changeset: 3:a6735021574d
156 changeset: 3:a6735021574d
155 tag: tip
157 tag: tip
156 user: test
158 user: test
157 date: Thu Jan 01 00:00:00 1970 +0000
159 date: Thu Jan 01 00:00:00 1970 +0000
158 summary: other hunks
160 summary: other hunks
159
161
160 $ hg cat -r tip b
162 $ hg cat -r tip b
161 x
163 x
162 1
164 1
163 2
165 2
164 3
166 3
165 4
167 4
166 5
168 5
167 6
169 6
168 7
170 7
169 8
171 8
170 9
172 9
171 10
173 10
172 y
174 y
173
175
174 Newly added files can be selected with the curses interface
176 Newly added files can be selected with the curses interface
175
177
176 $ hg update -C .
178 $ hg update -C .
177 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 $ echo "hello" > x
180 $ echo "hello" > x
179 $ hg add x
181 $ hg add x
180 $ cat <<EOF >testModeCommands
182 $ cat <<EOF >testModeCommands
181 > TOGGLE
183 > TOGGLE
182 > TOGGLE
184 > TOGGLE
183 > X
185 > X
184 > EOF
186 > EOF
185 $ hg st
187 $ hg st
186 A x
188 A x
187 ? testModeCommands
189 ? testModeCommands
188 $ hg commit -i -m "newly added file" -d "0 0"
190 $ hg commit -i -m "newly added file" -d "0 0"
189 $ hg st
191 $ hg st
190 ? testModeCommands
192 ? testModeCommands
191
193
192 Amend option works
194 Amend option works
193 $ echo "hello world" > x
195 $ echo "hello world" > x
194 $ hg diff -c .
196 $ hg diff -c .
195 diff -r a6735021574d -r 2b0e9be4d336 x
197 diff -r a6735021574d -r 2b0e9be4d336 x
196 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
198 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
197 +++ b/x Thu Jan 01 00:00:00 1970 +0000
199 +++ b/x Thu Jan 01 00:00:00 1970 +0000
198 @@ -0,0 +1,1 @@
200 @@ -0,0 +1,1 @@
199 +hello
201 +hello
200 $ cat <<EOF >testModeCommands
202 $ cat <<EOF >testModeCommands
201 > a
203 > a
202 > X
204 > X
203 > EOF
205 > EOF
204 $ hg commit -i -m "newly added file" -d "0 0"
206 $ hg commit -i -m "newly added file" -d "0 0"
205 saved backup bundle to $TESTTMP/a/.hg/strip-backup/2b0e9be4d336-28bbe4e2-amend-backup.hg (glob)
207 saved backup bundle to $TESTTMP/a/.hg/strip-backup/2b0e9be4d336-28bbe4e2-amend-backup.hg (glob)
206 $ hg diff -c .
208 $ hg diff -c .
207 diff -r a6735021574d -r c1d239d165ae x
209 diff -r a6735021574d -r c1d239d165ae x
208 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
210 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
209 +++ b/x Thu Jan 01 00:00:00 1970 +0000
211 +++ b/x Thu Jan 01 00:00:00 1970 +0000
210 @@ -0,0 +1,1 @@
212 @@ -0,0 +1,1 @@
211 +hello world
213 +hello world
212
214
213 Editing a hunk puts you back on that hunk when done editing (issue5041)
215 Editing a hunk puts you back on that hunk when done editing (issue5041)
214 To do that, we change two lines in a file, pretend to edit the second line,
216 To do that, we change two lines in a file, pretend to edit the second line,
215 exit, toggle the line selected at the end of the edit and commit.
217 exit, toggle the line selected at the end of the edit and commit.
216 The first line should be recorded if we were put on the second line at the end
218 The first line should be recorded if we were put on the second line at the end
217 of the edit.
219 of the edit.
218
220
219 $ hg update -C .
221 $ hg update -C .
220 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 $ echo "foo" > x
223 $ echo "foo" > x
222 $ echo "hello world" >> x
224 $ echo "hello world" >> x
223 $ echo "bar" >> x
225 $ echo "bar" >> x
224 $ cat <<EOF >testModeCommands
226 $ cat <<EOF >testModeCommands
225 > f
227 > f
226 > KEY_DOWN
228 > KEY_DOWN
227 > KEY_DOWN
229 > KEY_DOWN
228 > KEY_DOWN
230 > KEY_DOWN
229 > KEY_DOWN
231 > KEY_DOWN
230 > e
232 > e
231 > TOGGLE
233 > TOGGLE
232 > X
234 > X
233 > EOF
235 > EOF
234 $ printf "printf 'editor ran\n'; exit 0" > editor.sh
236 $ printf "printf 'editor ran\n'; exit 0" > editor.sh
235 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "edit hunk" -d "0 0"
237 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "edit hunk" -d "0 0"
236 editor ran
238 editor ran
237 $ hg cat -r . x
239 $ hg cat -r . x
238 foo
240 foo
239 hello world
241 hello world
240
242
241 Testing the review option. The entire final filtered patch should show
243 Testing the review option. The entire final filtered patch should show
242 up in the editor and be editable. We will unselect the second file and
244 up in the editor and be editable. We will unselect the second file and
243 the first hunk of the third file. During review, we will decide that
245 the first hunk of the third file. During review, we will decide that
244 "lower" sounds better than "bottom", and the final commit should
246 "lower" sounds better than "bottom", and the final commit should
245 reflect this edition.
247 reflect this edition.
246
248
247 $ hg update -C .
249 $ hg update -C .
248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
250 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
249 $ echo "top" > c
251 $ echo "top" > c
250 $ cat x >> c
252 $ cat x >> c
251 $ echo "bottom" >> c
253 $ echo "bottom" >> c
252 $ mv c x
254 $ mv c x
253 $ echo "third a" >> a
255 $ echo "third a" >> a
254 $ echo "we will unselect this" >> b
256 $ echo "we will unselect this" >> b
255
257
256 $ cat > editor.sh <<EOF
258 $ cat > editor.sh <<EOF
257 > cat "\$1"
259 > cat "\$1"
258 > cat "\$1" | sed s/bottom/lower/ > tmp
260 > cat "\$1" | sed s/bottom/lower/ > tmp
259 > mv tmp "\$1"
261 > mv tmp "\$1"
260 > EOF
262 > EOF
261 $ cat > testModeCommands <<EOF
263 $ cat > testModeCommands <<EOF
262 > KEY_DOWN
264 > KEY_DOWN
263 > TOGGLE
265 > TOGGLE
264 > KEY_DOWN
266 > KEY_DOWN
265 > f
267 > f
266 > KEY_DOWN
268 > KEY_DOWN
267 > TOGGLE
269 > TOGGLE
268 > R
270 > R
269 > EOF
271 > EOF
270
272
271 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "review hunks" -d "0 0"
273 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -m "review hunks" -d "0 0"
272 # To remove '-' lines, make them ' ' lines (context).
274 # To remove '-' lines, make them ' ' lines (context).
273 # To remove '+' lines, delete them.
275 # To remove '+' lines, delete them.
274 # Lines starting with # will be removed from the patch.
276 # Lines starting with # will be removed from the patch.
275 #
277 #
276 # If the patch applies cleanly, the edited patch will immediately
278 # If the patch applies cleanly, the edited patch will immediately
277 # be finalised. If it does not apply cleanly, rejects files will be
279 # be finalised. If it does not apply cleanly, rejects files will be
278 # generated. You can use those when you try again.
280 # generated. You can use those when you try again.
279 diff --git a/a b/a
281 diff --git a/a b/a
280 --- a/a
282 --- a/a
281 +++ b/a
283 +++ b/a
282 @@ -1,2 +1,3 @@
284 @@ -1,2 +1,3 @@
283 a
285 a
284 a
286 a
285 +third a
287 +third a
286 diff --git a/x b/x
288 diff --git a/x b/x
287 --- a/x
289 --- a/x
288 +++ b/x
290 +++ b/x
289 @@ -1,2 +1,3 @@
291 @@ -1,2 +1,3 @@
290 foo
292 foo
291 hello world
293 hello world
292 +bottom
294 +bottom
293
295
294 $ hg cat -r . a
296 $ hg cat -r . a
295 a
297 a
296 a
298 a
297 third a
299 third a
298
300
299 $ hg cat -r . b
301 $ hg cat -r . b
300 x
302 x
301 1
303 1
302 2
304 2
303 3
305 3
304 4
306 4
305 5
307 5
306 6
308 6
307 7
309 7
308 8
310 8
309 9
311 9
310 10
312 10
311 y
313 y
312
314
313 $ hg cat -r . x
315 $ hg cat -r . x
314 foo
316 foo
315 hello world
317 hello world
316 lower
318 lower
317 Check ui.interface logic for the chunkselector
319 Check ui.interface logic for the chunkselector
318
320
319 The default interface is text
321 The default interface is text
320 $ cp $HGRCPATH.pretest $HGRCPATH
322 $ cp $HGRCPATH.pretest $HGRCPATH
321 $ chunkselectorinterface() {
323 $ chunkselectorinterface() {
322 > python <<EOF
324 > python <<EOF
323 > from mercurial import hg, ui, parsers;\
325 > from mercurial import hg, ui, parsers;\
324 > repo = hg.repository(ui.ui(), ".");\
326 > repo = hg.repository(ui.ui(), ".");\
325 > print repo.ui.interface("chunkselector")
327 > print repo.ui.interface("chunkselector")
326 > EOF
328 > EOF
327 > }
329 > }
328 $ chunkselectorinterface
330 $ chunkselectorinterface
329 text
331 text
330
332
331 If only the default is set, we'll use that for the feature, too
333 If only the default is set, we'll use that for the feature, too
332 $ cp $HGRCPATH.pretest $HGRCPATH
334 $ cp $HGRCPATH.pretest $HGRCPATH
333 $ cat <<EOF >> $HGRCPATH
335 $ cat <<EOF >> $HGRCPATH
334 > [ui]
336 > [ui]
335 > interface = curses
337 > interface = curses
336 > EOF
338 > EOF
337 $ chunkselectorinterface
339 $ chunkselectorinterface
338 curses
340 curses
339
341
340 It is possible to override the default interface with a feature specific
342 It is possible to override the default interface with a feature specific
341 interface
343 interface
342 $ cp $HGRCPATH.pretest $HGRCPATH
344 $ cp $HGRCPATH.pretest $HGRCPATH
343 $ cat <<EOF >> $HGRCPATH
345 $ cat <<EOF >> $HGRCPATH
344 > [ui]
346 > [ui]
345 > interface = text
347 > interface = text
346 > interface.chunkselector = curses
348 > interface.chunkselector = curses
347 > EOF
349 > EOF
348
350
349 $ chunkselectorinterface
351 $ chunkselectorinterface
350 curses
352 curses
351
353
352 $ cp $HGRCPATH.pretest $HGRCPATH
354 $ cp $HGRCPATH.pretest $HGRCPATH
353 $ cat <<EOF >> $HGRCPATH
355 $ cat <<EOF >> $HGRCPATH
354 > [ui]
356 > [ui]
355 > interface = curses
357 > interface = curses
356 > interface.chunkselector = text
358 > interface.chunkselector = text
357 > EOF
359 > EOF
358
360
359 $ chunkselectorinterface
361 $ chunkselectorinterface
360 text
362 text
361
363
362 If a bad interface name is given, we use the default value (with a nice
364 If a bad interface name is given, we use the default value (with a nice
363 error message to suggest that the configuration needs to be fixed)
365 error message to suggest that the configuration needs to be fixed)
364
366
365 $ cp $HGRCPATH.pretest $HGRCPATH
367 $ cp $HGRCPATH.pretest $HGRCPATH
366 $ cat <<EOF >> $HGRCPATH
368 $ cat <<EOF >> $HGRCPATH
367 > [ui]
369 > [ui]
368 > interface = blah
370 > interface = blah
369 > EOF
371 > EOF
370 $ chunkselectorinterface
372 $ chunkselectorinterface
371 invalid value for ui.interface: blah (using text)
373 invalid value for ui.interface: blah (using text)
372 text
374 text
373
375
374 $ cp $HGRCPATH.pretest $HGRCPATH
376 $ cp $HGRCPATH.pretest $HGRCPATH
375 $ cat <<EOF >> $HGRCPATH
377 $ cat <<EOF >> $HGRCPATH
376 > [ui]
378 > [ui]
377 > interface = curses
379 > interface = curses
378 > interface.chunkselector = blah
380 > interface.chunkselector = blah
379 > EOF
381 > EOF
380 $ chunkselectorinterface
382 $ chunkselectorinterface
381 invalid value for ui.interface.chunkselector: blah (using curses)
383 invalid value for ui.interface.chunkselector: blah (using curses)
382 curses
384 curses
383
385
384 $ cp $HGRCPATH.pretest $HGRCPATH
386 $ cp $HGRCPATH.pretest $HGRCPATH
385 $ cat <<EOF >> $HGRCPATH
387 $ cat <<EOF >> $HGRCPATH
386 > [ui]
388 > [ui]
387 > interface = blah
389 > interface = blah
388 > interface.chunkselector = curses
390 > interface.chunkselector = curses
389 > EOF
391 > EOF
390 $ chunkselectorinterface
392 $ chunkselectorinterface
391 invalid value for ui.interface: blah
393 invalid value for ui.interface: blah
392 curses
394 curses
393
395
394 $ cp $HGRCPATH.pretest $HGRCPATH
396 $ cp $HGRCPATH.pretest $HGRCPATH
395 $ cat <<EOF >> $HGRCPATH
397 $ cat <<EOF >> $HGRCPATH
396 > [ui]
398 > [ui]
397 > interface = blah
399 > interface = blah
398 > interface.chunkselector = blah
400 > interface.chunkselector = blah
399 > EOF
401 > EOF
400 $ chunkselectorinterface
402 $ chunkselectorinterface
401 invalid value for ui.interface: blah
403 invalid value for ui.interface: blah
402 invalid value for ui.interface.chunkselector: blah (using text)
404 invalid value for ui.interface.chunkselector: blah (using text)
403 text
405 text
@@ -1,1800 +1,1803 b''
1 Set up a repo
1 Set up a repo
2
2
3 $ cat <<EOF >> $HGRCPATH
3 $ cat <<EOF >> $HGRCPATH
4 > [ui]
4 > [ui]
5 > interactive = true
5 > interactive = true
6 > [extensions]
6 > [extensions]
7 > record =
7 > record =
8 > EOF
8 > EOF
9
9
10 $ hg init a
10 $ hg init a
11 $ cd a
11 $ cd a
12
12
13 Select no files
13 Select no files
14
14
15 $ touch empty-rw
15 $ touch empty-rw
16 $ hg add empty-rw
16 $ hg add empty-rw
17
17
18 $ hg record --config ui.interactive=false
18 $ hg record --config ui.interactive=false
19 abort: running non-interactively, use commit instead
19 abort: running non-interactively, use commit instead
20 [255]
20 [255]
21 $ hg commit -i --config ui.interactive=false
21 $ hg commit -i --config ui.interactive=false
22 abort: running non-interactively
22 abort: running non-interactively
23 [255]
23 [255]
24 $ hg commit -i empty-rw<<EOF
24 $ hg commit -i empty-rw<<EOF
25 > n
25 > n
26 > EOF
26 > EOF
27 diff --git a/empty-rw b/empty-rw
27 diff --git a/empty-rw b/empty-rw
28 new file mode 100644
28 new file mode 100644
29 examine changes to 'empty-rw'? [Ynesfdaq?] n
29 examine changes to 'empty-rw'? [Ynesfdaq?] n
30
30
31 no changes to record
31 no changes to record
32 [1]
32
33
33 $ hg tip -p
34 $ hg tip -p
34 changeset: -1:000000000000
35 changeset: -1:000000000000
35 tag: tip
36 tag: tip
36 user:
37 user:
37 date: Thu Jan 01 00:00:00 1970 +0000
38 date: Thu Jan 01 00:00:00 1970 +0000
38
39
39
40
40
41
41 Select files but no hunks
42 Select files but no hunks
42
43
43 $ hg commit -i empty-rw<<EOF
44 $ hg commit -i empty-rw<<EOF
44 > y
45 > y
45 > n
46 > n
46 > EOF
47 > EOF
47 diff --git a/empty-rw b/empty-rw
48 diff --git a/empty-rw b/empty-rw
48 new file mode 100644
49 new file mode 100644
49 examine changes to 'empty-rw'? [Ynesfdaq?] y
50 examine changes to 'empty-rw'? [Ynesfdaq?] y
50
51
51 abort: empty commit message
52 abort: empty commit message
52 [255]
53 [255]
53
54
54 $ hg tip -p
55 $ hg tip -p
55 changeset: -1:000000000000
56 changeset: -1:000000000000
56 tag: tip
57 tag: tip
57 user:
58 user:
58 date: Thu Jan 01 00:00:00 1970 +0000
59 date: Thu Jan 01 00:00:00 1970 +0000
59
60
60
61
61
62
62 Abort for untracked
63 Abort for untracked
63
64
64 $ touch untracked
65 $ touch untracked
65 $ hg commit -i -m should-fail empty-rw untracked
66 $ hg commit -i -m should-fail empty-rw untracked
66 abort: untracked: file not tracked!
67 abort: untracked: file not tracked!
67 [255]
68 [255]
68 $ rm untracked
69 $ rm untracked
69
70
70 Record empty file
71 Record empty file
71
72
72 $ hg commit -i -d '0 0' -m empty empty-rw<<EOF
73 $ hg commit -i -d '0 0' -m empty empty-rw<<EOF
73 > y
74 > y
74 > y
75 > y
75 > EOF
76 > EOF
76 diff --git a/empty-rw b/empty-rw
77 diff --git a/empty-rw b/empty-rw
77 new file mode 100644
78 new file mode 100644
78 examine changes to 'empty-rw'? [Ynesfdaq?] y
79 examine changes to 'empty-rw'? [Ynesfdaq?] y
79
80
80
81
81 $ hg tip -p
82 $ hg tip -p
82 changeset: 0:c0708cf4e46e
83 changeset: 0:c0708cf4e46e
83 tag: tip
84 tag: tip
84 user: test
85 user: test
85 date: Thu Jan 01 00:00:00 1970 +0000
86 date: Thu Jan 01 00:00:00 1970 +0000
86 summary: empty
87 summary: empty
87
88
88
89
89
90
90 Summary shows we updated to the new cset
91 Summary shows we updated to the new cset
91
92
92 $ hg summary
93 $ hg summary
93 parent: 0:c0708cf4e46e tip
94 parent: 0:c0708cf4e46e tip
94 empty
95 empty
95 branch: default
96 branch: default
96 commit: (clean)
97 commit: (clean)
97 update: (current)
98 update: (current)
98 phases: 1 draft
99 phases: 1 draft
99
100
100 Rename empty file
101 Rename empty file
101
102
102 $ hg mv empty-rw empty-rename
103 $ hg mv empty-rw empty-rename
103 $ hg commit -i -d '1 0' -m rename<<EOF
104 $ hg commit -i -d '1 0' -m rename<<EOF
104 > y
105 > y
105 > EOF
106 > EOF
106 diff --git a/empty-rw b/empty-rename
107 diff --git a/empty-rw b/empty-rename
107 rename from empty-rw
108 rename from empty-rw
108 rename to empty-rename
109 rename to empty-rename
109 examine changes to 'empty-rw' and 'empty-rename'? [Ynesfdaq?] y
110 examine changes to 'empty-rw' and 'empty-rename'? [Ynesfdaq?] y
110
111
111
112
112 $ hg tip -p
113 $ hg tip -p
113 changeset: 1:d695e8dcb197
114 changeset: 1:d695e8dcb197
114 tag: tip
115 tag: tip
115 user: test
116 user: test
116 date: Thu Jan 01 00:00:01 1970 +0000
117 date: Thu Jan 01 00:00:01 1970 +0000
117 summary: rename
118 summary: rename
118
119
119
120
120
121
121 Copy empty file
122 Copy empty file
122
123
123 $ hg cp empty-rename empty-copy
124 $ hg cp empty-rename empty-copy
124 $ hg commit -i -d '2 0' -m copy<<EOF
125 $ hg commit -i -d '2 0' -m copy<<EOF
125 > y
126 > y
126 > EOF
127 > EOF
127 diff --git a/empty-rename b/empty-copy
128 diff --git a/empty-rename b/empty-copy
128 copy from empty-rename
129 copy from empty-rename
129 copy to empty-copy
130 copy to empty-copy
130 examine changes to 'empty-rename' and 'empty-copy'? [Ynesfdaq?] y
131 examine changes to 'empty-rename' and 'empty-copy'? [Ynesfdaq?] y
131
132
132
133
133 $ hg tip -p
134 $ hg tip -p
134 changeset: 2:1d4b90bea524
135 changeset: 2:1d4b90bea524
135 tag: tip
136 tag: tip
136 user: test
137 user: test
137 date: Thu Jan 01 00:00:02 1970 +0000
138 date: Thu Jan 01 00:00:02 1970 +0000
138 summary: copy
139 summary: copy
139
140
140
141
141
142
142 Delete empty file
143 Delete empty file
143
144
144 $ hg rm empty-copy
145 $ hg rm empty-copy
145 $ hg commit -i -d '3 0' -m delete<<EOF
146 $ hg commit -i -d '3 0' -m delete<<EOF
146 > y
147 > y
147 > EOF
148 > EOF
148 diff --git a/empty-copy b/empty-copy
149 diff --git a/empty-copy b/empty-copy
149 deleted file mode 100644
150 deleted file mode 100644
150 examine changes to 'empty-copy'? [Ynesfdaq?] y
151 examine changes to 'empty-copy'? [Ynesfdaq?] y
151
152
152
153
153 $ hg tip -p
154 $ hg tip -p
154 changeset: 3:b39a238f01a1
155 changeset: 3:b39a238f01a1
155 tag: tip
156 tag: tip
156 user: test
157 user: test
157 date: Thu Jan 01 00:00:03 1970 +0000
158 date: Thu Jan 01 00:00:03 1970 +0000
158 summary: delete
159 summary: delete
159
160
160
161
161
162
162 Add binary file
163 Add binary file
163
164
164 $ hg bundle --type v1 --base -2 tip.bundle
165 $ hg bundle --type v1 --base -2 tip.bundle
165 1 changesets found
166 1 changesets found
166 $ hg add tip.bundle
167 $ hg add tip.bundle
167 $ hg commit -i -d '4 0' -m binary<<EOF
168 $ hg commit -i -d '4 0' -m binary<<EOF
168 > y
169 > y
169 > EOF
170 > EOF
170 diff --git a/tip.bundle b/tip.bundle
171 diff --git a/tip.bundle b/tip.bundle
171 new file mode 100644
172 new file mode 100644
172 this is a binary file
173 this is a binary file
173 examine changes to 'tip.bundle'? [Ynesfdaq?] y
174 examine changes to 'tip.bundle'? [Ynesfdaq?] y
174
175
175
176
176 $ hg tip -p
177 $ hg tip -p
177 changeset: 4:ad816da3711e
178 changeset: 4:ad816da3711e
178 tag: tip
179 tag: tip
179 user: test
180 user: test
180 date: Thu Jan 01 00:00:04 1970 +0000
181 date: Thu Jan 01 00:00:04 1970 +0000
181 summary: binary
182 summary: binary
182
183
183 diff -r b39a238f01a1 -r ad816da3711e tip.bundle
184 diff -r b39a238f01a1 -r ad816da3711e tip.bundle
184 Binary file tip.bundle has changed
185 Binary file tip.bundle has changed
185
186
186
187
187 Change binary file
188 Change binary file
188
189
189 $ hg bundle --base -2 --type v1 tip.bundle
190 $ hg bundle --base -2 --type v1 tip.bundle
190 1 changesets found
191 1 changesets found
191 $ hg commit -i -d '5 0' -m binary-change<<EOF
192 $ hg commit -i -d '5 0' -m binary-change<<EOF
192 > y
193 > y
193 > EOF
194 > EOF
194 diff --git a/tip.bundle b/tip.bundle
195 diff --git a/tip.bundle b/tip.bundle
195 this modifies a binary file (all or nothing)
196 this modifies a binary file (all or nothing)
196 examine changes to 'tip.bundle'? [Ynesfdaq?] y
197 examine changes to 'tip.bundle'? [Ynesfdaq?] y
197
198
198
199
199 $ hg tip -p
200 $ hg tip -p
200 changeset: 5:dccd6f3eb485
201 changeset: 5:dccd6f3eb485
201 tag: tip
202 tag: tip
202 user: test
203 user: test
203 date: Thu Jan 01 00:00:05 1970 +0000
204 date: Thu Jan 01 00:00:05 1970 +0000
204 summary: binary-change
205 summary: binary-change
205
206
206 diff -r ad816da3711e -r dccd6f3eb485 tip.bundle
207 diff -r ad816da3711e -r dccd6f3eb485 tip.bundle
207 Binary file tip.bundle has changed
208 Binary file tip.bundle has changed
208
209
209
210
210 Rename and change binary file
211 Rename and change binary file
211
212
212 $ hg mv tip.bundle top.bundle
213 $ hg mv tip.bundle top.bundle
213 $ hg bundle --base -2 --type v1 top.bundle
214 $ hg bundle --base -2 --type v1 top.bundle
214 1 changesets found
215 1 changesets found
215 $ hg commit -i -d '6 0' -m binary-change-rename<<EOF
216 $ hg commit -i -d '6 0' -m binary-change-rename<<EOF
216 > y
217 > y
217 > EOF
218 > EOF
218 diff --git a/tip.bundle b/top.bundle
219 diff --git a/tip.bundle b/top.bundle
219 rename from tip.bundle
220 rename from tip.bundle
220 rename to top.bundle
221 rename to top.bundle
221 this modifies a binary file (all or nothing)
222 this modifies a binary file (all or nothing)
222 examine changes to 'tip.bundle' and 'top.bundle'? [Ynesfdaq?] y
223 examine changes to 'tip.bundle' and 'top.bundle'? [Ynesfdaq?] y
223
224
224
225
225 $ hg tip -p
226 $ hg tip -p
226 changeset: 6:7fa44105f5b3
227 changeset: 6:7fa44105f5b3
227 tag: tip
228 tag: tip
228 user: test
229 user: test
229 date: Thu Jan 01 00:00:06 1970 +0000
230 date: Thu Jan 01 00:00:06 1970 +0000
230 summary: binary-change-rename
231 summary: binary-change-rename
231
232
232 diff -r dccd6f3eb485 -r 7fa44105f5b3 tip.bundle
233 diff -r dccd6f3eb485 -r 7fa44105f5b3 tip.bundle
233 Binary file tip.bundle has changed
234 Binary file tip.bundle has changed
234 diff -r dccd6f3eb485 -r 7fa44105f5b3 top.bundle
235 diff -r dccd6f3eb485 -r 7fa44105f5b3 top.bundle
235 Binary file top.bundle has changed
236 Binary file top.bundle has changed
236
237
237
238
238 Add plain file
239 Add plain file
239
240
240 $ for i in 1 2 3 4 5 6 7 8 9 10; do
241 $ for i in 1 2 3 4 5 6 7 8 9 10; do
241 > echo $i >> plain
242 > echo $i >> plain
242 > done
243 > done
243
244
244 $ hg add plain
245 $ hg add plain
245 $ hg commit -i -d '7 0' -m plain plain<<EOF
246 $ hg commit -i -d '7 0' -m plain plain<<EOF
246 > y
247 > y
247 > y
248 > y
248 > EOF
249 > EOF
249 diff --git a/plain b/plain
250 diff --git a/plain b/plain
250 new file mode 100644
251 new file mode 100644
251 examine changes to 'plain'? [Ynesfdaq?] y
252 examine changes to 'plain'? [Ynesfdaq?] y
252
253
253 @@ -0,0 +1,10 @@
254 @@ -0,0 +1,10 @@
254 +1
255 +1
255 +2
256 +2
256 +3
257 +3
257 +4
258 +4
258 +5
259 +5
259 +6
260 +6
260 +7
261 +7
261 +8
262 +8
262 +9
263 +9
263 +10
264 +10
264 record this change to 'plain'? [Ynesfdaq?] y
265 record this change to 'plain'? [Ynesfdaq?] y
265
266
266 $ hg tip -p
267 $ hg tip -p
267 changeset: 7:11fb457c1be4
268 changeset: 7:11fb457c1be4
268 tag: tip
269 tag: tip
269 user: test
270 user: test
270 date: Thu Jan 01 00:00:07 1970 +0000
271 date: Thu Jan 01 00:00:07 1970 +0000
271 summary: plain
272 summary: plain
272
273
273 diff -r 7fa44105f5b3 -r 11fb457c1be4 plain
274 diff -r 7fa44105f5b3 -r 11fb457c1be4 plain
274 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
275 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
275 +++ b/plain Thu Jan 01 00:00:07 1970 +0000
276 +++ b/plain Thu Jan 01 00:00:07 1970 +0000
276 @@ -0,0 +1,10 @@
277 @@ -0,0 +1,10 @@
277 +1
278 +1
278 +2
279 +2
279 +3
280 +3
280 +4
281 +4
281 +5
282 +5
282 +6
283 +6
283 +7
284 +7
284 +8
285 +8
285 +9
286 +9
286 +10
287 +10
287
288
288 Modify end of plain file with username unset
289 Modify end of plain file with username unset
289
290
290 $ echo 11 >> plain
291 $ echo 11 >> plain
291 $ unset HGUSER
292 $ unset HGUSER
292 $ hg commit -i --config ui.username= -d '8 0' -m end plain
293 $ hg commit -i --config ui.username= -d '8 0' -m end plain
293 abort: no username supplied
294 abort: no username supplied
294 (use 'hg config --edit' to set your username)
295 (use 'hg config --edit' to set your username)
295 [255]
296 [255]
296
297
297
298
298 Modify end of plain file, also test that diffopts are accounted for
299 Modify end of plain file, also test that diffopts are accounted for
299
300
300 $ HGUSER="test"
301 $ HGUSER="test"
301 $ export HGUSER
302 $ export HGUSER
302 $ hg commit -i --config diff.showfunc=true -d '8 0' -m end plain <<EOF
303 $ hg commit -i --config diff.showfunc=true -d '8 0' -m end plain <<EOF
303 > y
304 > y
304 > y
305 > y
305 > EOF
306 > EOF
306 diff --git a/plain b/plain
307 diff --git a/plain b/plain
307 1 hunks, 1 lines changed
308 1 hunks, 1 lines changed
308 examine changes to 'plain'? [Ynesfdaq?] y
309 examine changes to 'plain'? [Ynesfdaq?] y
309
310
310 @@ -8,3 +8,4 @@ 7
311 @@ -8,3 +8,4 @@ 7
311 8
312 8
312 9
313 9
313 10
314 10
314 +11
315 +11
315 record this change to 'plain'? [Ynesfdaq?] y
316 record this change to 'plain'? [Ynesfdaq?] y
316
317
317
318
318 Modify end of plain file, no EOL
319 Modify end of plain file, no EOL
319
320
320 $ hg tip --template '{node}' >> plain
321 $ hg tip --template '{node}' >> plain
321 $ hg commit -i -d '9 0' -m noeol plain <<EOF
322 $ hg commit -i -d '9 0' -m noeol plain <<EOF
322 > y
323 > y
323 > y
324 > y
324 > EOF
325 > EOF
325 diff --git a/plain b/plain
326 diff --git a/plain b/plain
326 1 hunks, 1 lines changed
327 1 hunks, 1 lines changed
327 examine changes to 'plain'? [Ynesfdaq?] y
328 examine changes to 'plain'? [Ynesfdaq?] y
328
329
329 @@ -9,3 +9,4 @@ 8
330 @@ -9,3 +9,4 @@ 8
330 9
331 9
331 10
332 10
332 11
333 11
333 +7264f99c5f5ff3261504828afa4fb4d406c3af54
334 +7264f99c5f5ff3261504828afa4fb4d406c3af54
334 \ No newline at end of file
335 \ No newline at end of file
335 record this change to 'plain'? [Ynesfdaq?] y
336 record this change to 'plain'? [Ynesfdaq?] y
336
337
337
338
338 Record showfunc should preserve function across sections
339 Record showfunc should preserve function across sections
339
340
340 $ cat > f1.py <<EOF
341 $ cat > f1.py <<EOF
341 > def annotate(ui, repo, *pats, **opts):
342 > def annotate(ui, repo, *pats, **opts):
342 > """show changeset information by line for each file
343 > """show changeset information by line for each file
343 >
344 >
344 > List changes in files, showing the revision id responsible for
345 > List changes in files, showing the revision id responsible for
345 > each line.
346 > each line.
346 >
347 >
347 > This command is useful for discovering when a change was made and
348 > This command is useful for discovering when a change was made and
348 > by whom.
349 > by whom.
349 >
350 >
350 > If you include -f/-u/-d, the revision number is suppressed unless
351 > If you include -f/-u/-d, the revision number is suppressed unless
351 > you also include -the revision number is suppressed unless
352 > you also include -the revision number is suppressed unless
352 > you also include -n.
353 > you also include -n.
353 >
354 >
354 > Without the -a/--text option, annotate will avoid processing files
355 > Without the -a/--text option, annotate will avoid processing files
355 > it detects as binary. With -a, annotate will annotate the file
356 > it detects as binary. With -a, annotate will annotate the file
356 > anyway, although the results will probably be neither useful
357 > anyway, although the results will probably be neither useful
357 > nor desirable.
358 > nor desirable.
358 >
359 >
359 > Returns 0 on success.
360 > Returns 0 on success.
360 > """
361 > """
361 > return 0
362 > return 0
362 > def archive(ui, repo, dest, **opts):
363 > def archive(ui, repo, dest, **opts):
363 > '''create an unversioned archive of a repository revision
364 > '''create an unversioned archive of a repository revision
364 >
365 >
365 > By default, the revision used is the parent of the working
366 > By default, the revision used is the parent of the working
366 > directory; use -r/--rev to specify a different revision.
367 > directory; use -r/--rev to specify a different revision.
367 >
368 >
368 > The archive type is automatically detected based on file
369 > The archive type is automatically detected based on file
369 > extension (to override, use -t/--type).
370 > extension (to override, use -t/--type).
370 >
371 >
371 > .. container:: verbose
372 > .. container:: verbose
372 >
373 >
373 > Valid types are:
374 > Valid types are:
374 > EOF
375 > EOF
375 $ hg add f1.py
376 $ hg add f1.py
376 $ hg commit -m funcs
377 $ hg commit -m funcs
377 $ cat > f1.py <<EOF
378 $ cat > f1.py <<EOF
378 > def annotate(ui, repo, *pats, **opts):
379 > def annotate(ui, repo, *pats, **opts):
379 > """show changeset information by line for each file
380 > """show changeset information by line for each file
380 >
381 >
381 > List changes in files, showing the revision id responsible for
382 > List changes in files, showing the revision id responsible for
382 > each line
383 > each line
383 >
384 >
384 > This command is useful for discovering when a change was made and
385 > This command is useful for discovering when a change was made and
385 > by whom.
386 > by whom.
386 >
387 >
387 > Without the -a/--text option, annotate will avoid processing files
388 > Without the -a/--text option, annotate will avoid processing files
388 > it detects as binary. With -a, annotate will annotate the file
389 > it detects as binary. With -a, annotate will annotate the file
389 > anyway, although the results will probably be neither useful
390 > anyway, although the results will probably be neither useful
390 > nor desirable.
391 > nor desirable.
391 >
392 >
392 > Returns 0 on success.
393 > Returns 0 on success.
393 > """
394 > """
394 > return 0
395 > return 0
395 > def archive(ui, repo, dest, **opts):
396 > def archive(ui, repo, dest, **opts):
396 > '''create an unversioned archive of a repository revision
397 > '''create an unversioned archive of a repository revision
397 >
398 >
398 > By default, the revision used is the parent of the working
399 > By default, the revision used is the parent of the working
399 > directory; use -r/--rev to specify a different revision.
400 > directory; use -r/--rev to specify a different revision.
400 >
401 >
401 > The archive type is automatically detected based on file
402 > The archive type is automatically detected based on file
402 > extension (or override using -t/--type).
403 > extension (or override using -t/--type).
403 >
404 >
404 > .. container:: verbose
405 > .. container:: verbose
405 >
406 >
406 > Valid types are:
407 > Valid types are:
407 > EOF
408 > EOF
408 $ hg commit -i -m interactive <<EOF
409 $ hg commit -i -m interactive <<EOF
409 > y
410 > y
410 > y
411 > y
411 > y
412 > y
412 > y
413 > y
413 > EOF
414 > EOF
414 diff --git a/f1.py b/f1.py
415 diff --git a/f1.py b/f1.py
415 3 hunks, 6 lines changed
416 3 hunks, 6 lines changed
416 examine changes to 'f1.py'? [Ynesfdaq?] y
417 examine changes to 'f1.py'? [Ynesfdaq?] y
417
418
418 @@ -2,8 +2,8 @@ def annotate(ui, repo, *pats, **opts):
419 @@ -2,8 +2,8 @@ def annotate(ui, repo, *pats, **opts):
419 """show changeset information by line for each file
420 """show changeset information by line for each file
420
421
421 List changes in files, showing the revision id responsible for
422 List changes in files, showing the revision id responsible for
422 - each line.
423 - each line.
423 + each line
424 + each line
424
425
425 This command is useful for discovering when a change was made and
426 This command is useful for discovering when a change was made and
426 by whom.
427 by whom.
427
428
428 record change 1/3 to 'f1.py'? [Ynesfdaq?] y
429 record change 1/3 to 'f1.py'? [Ynesfdaq?] y
429
430
430 @@ -6,11 +6,7 @@ def annotate(ui, repo, *pats, **opts):
431 @@ -6,11 +6,7 @@ def annotate(ui, repo, *pats, **opts):
431
432
432 This command is useful for discovering when a change was made and
433 This command is useful for discovering when a change was made and
433 by whom.
434 by whom.
434
435
435 - If you include -f/-u/-d, the revision number is suppressed unless
436 - If you include -f/-u/-d, the revision number is suppressed unless
436 - you also include -the revision number is suppressed unless
437 - you also include -the revision number is suppressed unless
437 - you also include -n.
438 - you also include -n.
438 -
439 -
439 Without the -a/--text option, annotate will avoid processing files
440 Without the -a/--text option, annotate will avoid processing files
440 it detects as binary. With -a, annotate will annotate the file
441 it detects as binary. With -a, annotate will annotate the file
441 anyway, although the results will probably be neither useful
442 anyway, although the results will probably be neither useful
442 record change 2/3 to 'f1.py'? [Ynesfdaq?] y
443 record change 2/3 to 'f1.py'? [Ynesfdaq?] y
443
444
444 @@ -26,7 +22,7 @@ def archive(ui, repo, dest, **opts):
445 @@ -26,7 +22,7 @@ def archive(ui, repo, dest, **opts):
445 directory; use -r/--rev to specify a different revision.
446 directory; use -r/--rev to specify a different revision.
446
447
447 The archive type is automatically detected based on file
448 The archive type is automatically detected based on file
448 - extension (to override, use -t/--type).
449 - extension (to override, use -t/--type).
449 + extension (or override using -t/--type).
450 + extension (or override using -t/--type).
450
451
451 .. container:: verbose
452 .. container:: verbose
452
453
453 record change 3/3 to 'f1.py'? [Ynesfdaq?] y
454 record change 3/3 to 'f1.py'? [Ynesfdaq?] y
454
455
455
456
456 Modify end of plain file, add EOL
457 Modify end of plain file, add EOL
457
458
458 $ echo >> plain
459 $ echo >> plain
459 $ echo 1 > plain2
460 $ echo 1 > plain2
460 $ hg add plain2
461 $ hg add plain2
461 $ hg commit -i -d '10 0' -m eol plain plain2 <<EOF
462 $ hg commit -i -d '10 0' -m eol plain plain2 <<EOF
462 > y
463 > y
463 > y
464 > y
464 > y
465 > y
465 > y
466 > y
466 > EOF
467 > EOF
467 diff --git a/plain b/plain
468 diff --git a/plain b/plain
468 1 hunks, 1 lines changed
469 1 hunks, 1 lines changed
469 examine changes to 'plain'? [Ynesfdaq?] y
470 examine changes to 'plain'? [Ynesfdaq?] y
470
471
471 @@ -9,4 +9,4 @@ 8
472 @@ -9,4 +9,4 @@ 8
472 9
473 9
473 10
474 10
474 11
475 11
475 -7264f99c5f5ff3261504828afa4fb4d406c3af54
476 -7264f99c5f5ff3261504828afa4fb4d406c3af54
476 \ No newline at end of file
477 \ No newline at end of file
477 +7264f99c5f5ff3261504828afa4fb4d406c3af54
478 +7264f99c5f5ff3261504828afa4fb4d406c3af54
478 record change 1/2 to 'plain'? [Ynesfdaq?] y
479 record change 1/2 to 'plain'? [Ynesfdaq?] y
479
480
480 diff --git a/plain2 b/plain2
481 diff --git a/plain2 b/plain2
481 new file mode 100644
482 new file mode 100644
482 examine changes to 'plain2'? [Ynesfdaq?] y
483 examine changes to 'plain2'? [Ynesfdaq?] y
483
484
484 @@ -0,0 +1,1 @@
485 @@ -0,0 +1,1 @@
485 +1
486 +1
486 record change 2/2 to 'plain2'? [Ynesfdaq?] y
487 record change 2/2 to 'plain2'? [Ynesfdaq?] y
487
488
488 Modify beginning, trim end, record both, add another file to test
489 Modify beginning, trim end, record both, add another file to test
489 changes numbering
490 changes numbering
490
491
491 $ rm plain
492 $ rm plain
492 $ for i in 2 2 3 4 5 6 7 8 9 10; do
493 $ for i in 2 2 3 4 5 6 7 8 9 10; do
493 > echo $i >> plain
494 > echo $i >> plain
494 > done
495 > done
495 $ echo 2 >> plain2
496 $ echo 2 >> plain2
496
497
497 $ hg commit -i -d '10 0' -m begin-and-end plain plain2 <<EOF
498 $ hg commit -i -d '10 0' -m begin-and-end plain plain2 <<EOF
498 > y
499 > y
499 > y
500 > y
500 > y
501 > y
501 > y
502 > y
502 > y
503 > y
503 > EOF
504 > EOF
504 diff --git a/plain b/plain
505 diff --git a/plain b/plain
505 2 hunks, 3 lines changed
506 2 hunks, 3 lines changed
506 examine changes to 'plain'? [Ynesfdaq?] y
507 examine changes to 'plain'? [Ynesfdaq?] y
507
508
508 @@ -1,4 +1,4 @@
509 @@ -1,4 +1,4 @@
509 -1
510 -1
510 +2
511 +2
511 2
512 2
512 3
513 3
513 4
514 4
514 record change 1/3 to 'plain'? [Ynesfdaq?] y
515 record change 1/3 to 'plain'? [Ynesfdaq?] y
515
516
516 @@ -8,5 +8,3 @@ 7
517 @@ -8,5 +8,3 @@ 7
517 8
518 8
518 9
519 9
519 10
520 10
520 -11
521 -11
521 -7264f99c5f5ff3261504828afa4fb4d406c3af54
522 -7264f99c5f5ff3261504828afa4fb4d406c3af54
522 record change 2/3 to 'plain'? [Ynesfdaq?] y
523 record change 2/3 to 'plain'? [Ynesfdaq?] y
523
524
524 diff --git a/plain2 b/plain2
525 diff --git a/plain2 b/plain2
525 1 hunks, 1 lines changed
526 1 hunks, 1 lines changed
526 examine changes to 'plain2'? [Ynesfdaq?] y
527 examine changes to 'plain2'? [Ynesfdaq?] y
527
528
528 @@ -1,1 +1,2 @@
529 @@ -1,1 +1,2 @@
529 1
530 1
530 +2
531 +2
531 record change 3/3 to 'plain2'? [Ynesfdaq?] y
532 record change 3/3 to 'plain2'? [Ynesfdaq?] y
532
533
533
534
534 $ hg tip -p
535 $ hg tip -p
535 changeset: 13:f941910cff62
536 changeset: 13:f941910cff62
536 tag: tip
537 tag: tip
537 user: test
538 user: test
538 date: Thu Jan 01 00:00:10 1970 +0000
539 date: Thu Jan 01 00:00:10 1970 +0000
539 summary: begin-and-end
540 summary: begin-and-end
540
541
541 diff -r 33abe24d946c -r f941910cff62 plain
542 diff -r 33abe24d946c -r f941910cff62 plain
542 --- a/plain Thu Jan 01 00:00:10 1970 +0000
543 --- a/plain Thu Jan 01 00:00:10 1970 +0000
543 +++ b/plain Thu Jan 01 00:00:10 1970 +0000
544 +++ b/plain Thu Jan 01 00:00:10 1970 +0000
544 @@ -1,4 +1,4 @@
545 @@ -1,4 +1,4 @@
545 -1
546 -1
546 +2
547 +2
547 2
548 2
548 3
549 3
549 4
550 4
550 @@ -8,5 +8,3 @@
551 @@ -8,5 +8,3 @@
551 8
552 8
552 9
553 9
553 10
554 10
554 -11
555 -11
555 -7264f99c5f5ff3261504828afa4fb4d406c3af54
556 -7264f99c5f5ff3261504828afa4fb4d406c3af54
556 diff -r 33abe24d946c -r f941910cff62 plain2
557 diff -r 33abe24d946c -r f941910cff62 plain2
557 --- a/plain2 Thu Jan 01 00:00:10 1970 +0000
558 --- a/plain2 Thu Jan 01 00:00:10 1970 +0000
558 +++ b/plain2 Thu Jan 01 00:00:10 1970 +0000
559 +++ b/plain2 Thu Jan 01 00:00:10 1970 +0000
559 @@ -1,1 +1,2 @@
560 @@ -1,1 +1,2 @@
560 1
561 1
561 +2
562 +2
562
563
563
564
564 Trim beginning, modify end
565 Trim beginning, modify end
565
566
566 $ rm plain
567 $ rm plain
567 > for i in 4 5 6 7 8 9 10.new; do
568 > for i in 4 5 6 7 8 9 10.new; do
568 > echo $i >> plain
569 > echo $i >> plain
569 > done
570 > done
570
571
571 Record end
572 Record end
572
573
573 $ hg commit -i -d '11 0' -m end-only plain <<EOF
574 $ hg commit -i -d '11 0' -m end-only plain <<EOF
574 > y
575 > y
575 > n
576 > n
576 > y
577 > y
577 > EOF
578 > EOF
578 diff --git a/plain b/plain
579 diff --git a/plain b/plain
579 2 hunks, 4 lines changed
580 2 hunks, 4 lines changed
580 examine changes to 'plain'? [Ynesfdaq?] y
581 examine changes to 'plain'? [Ynesfdaq?] y
581
582
582 @@ -1,9 +1,6 @@
583 @@ -1,9 +1,6 @@
583 -2
584 -2
584 -2
585 -2
585 -3
586 -3
586 4
587 4
587 5
588 5
588 6
589 6
589 7
590 7
590 8
591 8
591 9
592 9
592 record change 1/2 to 'plain'? [Ynesfdaq?] n
593 record change 1/2 to 'plain'? [Ynesfdaq?] n
593
594
594 @@ -4,7 +1,7 @@
595 @@ -4,7 +1,7 @@
595 4
596 4
596 5
597 5
597 6
598 6
598 7
599 7
599 8
600 8
600 9
601 9
601 -10
602 -10
602 +10.new
603 +10.new
603 record change 2/2 to 'plain'? [Ynesfdaq?] y
604 record change 2/2 to 'plain'? [Ynesfdaq?] y
604
605
605
606
606 $ hg tip -p
607 $ hg tip -p
607 changeset: 14:4915f538659b
608 changeset: 14:4915f538659b
608 tag: tip
609 tag: tip
609 user: test
610 user: test
610 date: Thu Jan 01 00:00:11 1970 +0000
611 date: Thu Jan 01 00:00:11 1970 +0000
611 summary: end-only
612 summary: end-only
612
613
613 diff -r f941910cff62 -r 4915f538659b plain
614 diff -r f941910cff62 -r 4915f538659b plain
614 --- a/plain Thu Jan 01 00:00:10 1970 +0000
615 --- a/plain Thu Jan 01 00:00:10 1970 +0000
615 +++ b/plain Thu Jan 01 00:00:11 1970 +0000
616 +++ b/plain Thu Jan 01 00:00:11 1970 +0000
616 @@ -7,4 +7,4 @@
617 @@ -7,4 +7,4 @@
617 7
618 7
618 8
619 8
619 9
620 9
620 -10
621 -10
621 +10.new
622 +10.new
622
623
623
624
624 Record beginning
625 Record beginning
625
626
626 $ hg commit -i -d '12 0' -m begin-only plain <<EOF
627 $ hg commit -i -d '12 0' -m begin-only plain <<EOF
627 > y
628 > y
628 > y
629 > y
629 > EOF
630 > EOF
630 diff --git a/plain b/plain
631 diff --git a/plain b/plain
631 1 hunks, 3 lines changed
632 1 hunks, 3 lines changed
632 examine changes to 'plain'? [Ynesfdaq?] y
633 examine changes to 'plain'? [Ynesfdaq?] y
633
634
634 @@ -1,6 +1,3 @@
635 @@ -1,6 +1,3 @@
635 -2
636 -2
636 -2
637 -2
637 -3
638 -3
638 4
639 4
639 5
640 5
640 6
641 6
641 record this change to 'plain'? [Ynesfdaq?] y
642 record this change to 'plain'? [Ynesfdaq?] y
642
643
643
644
644 $ hg tip -p
645 $ hg tip -p
645 changeset: 15:1b1f93d4b94b
646 changeset: 15:1b1f93d4b94b
646 tag: tip
647 tag: tip
647 user: test
648 user: test
648 date: Thu Jan 01 00:00:12 1970 +0000
649 date: Thu Jan 01 00:00:12 1970 +0000
649 summary: begin-only
650 summary: begin-only
650
651
651 diff -r 4915f538659b -r 1b1f93d4b94b plain
652 diff -r 4915f538659b -r 1b1f93d4b94b plain
652 --- a/plain Thu Jan 01 00:00:11 1970 +0000
653 --- a/plain Thu Jan 01 00:00:11 1970 +0000
653 +++ b/plain Thu Jan 01 00:00:12 1970 +0000
654 +++ b/plain Thu Jan 01 00:00:12 1970 +0000
654 @@ -1,6 +1,3 @@
655 @@ -1,6 +1,3 @@
655 -2
656 -2
656 -2
657 -2
657 -3
658 -3
658 4
659 4
659 5
660 5
660 6
661 6
661
662
662
663
663 Add to beginning, trim from end
664 Add to beginning, trim from end
664
665
665 $ rm plain
666 $ rm plain
666 $ for i in 1 2 3 4 5 6 7 8 9; do
667 $ for i in 1 2 3 4 5 6 7 8 9; do
667 > echo $i >> plain
668 > echo $i >> plain
668 > done
669 > done
669
670
670 Record end
671 Record end
671
672
672 $ hg commit -i --traceback -d '13 0' -m end-again plain<<EOF
673 $ hg commit -i --traceback -d '13 0' -m end-again plain<<EOF
673 > y
674 > y
674 > n
675 > n
675 > y
676 > y
676 > EOF
677 > EOF
677 diff --git a/plain b/plain
678 diff --git a/plain b/plain
678 2 hunks, 4 lines changed
679 2 hunks, 4 lines changed
679 examine changes to 'plain'? [Ynesfdaq?] y
680 examine changes to 'plain'? [Ynesfdaq?] y
680
681
681 @@ -1,6 +1,9 @@
682 @@ -1,6 +1,9 @@
682 +1
683 +1
683 +2
684 +2
684 +3
685 +3
685 4
686 4
686 5
687 5
687 6
688 6
688 7
689 7
689 8
690 8
690 9
691 9
691 record change 1/2 to 'plain'? [Ynesfdaq?] n
692 record change 1/2 to 'plain'? [Ynesfdaq?] n
692
693
693 @@ -1,7 +4,6 @@
694 @@ -1,7 +4,6 @@
694 4
695 4
695 5
696 5
696 6
697 6
697 7
698 7
698 8
699 8
699 9
700 9
700 -10.new
701 -10.new
701 record change 2/2 to 'plain'? [Ynesfdaq?] y
702 record change 2/2 to 'plain'? [Ynesfdaq?] y
702
703
703
704
704 Add to beginning, middle, end
705 Add to beginning, middle, end
705
706
706 $ rm plain
707 $ rm plain
707 $ for i in 1 2 3 4 5 5.new 5.reallynew 6 7 8 9 10 11; do
708 $ for i in 1 2 3 4 5 5.new 5.reallynew 6 7 8 9 10 11; do
708 > echo $i >> plain
709 > echo $i >> plain
709 > done
710 > done
710
711
711 Record beginning, middle, and test that format-breaking diffopts are ignored
712 Record beginning, middle, and test that format-breaking diffopts are ignored
712
713
713 $ hg commit -i --config diff.noprefix=True -d '14 0' -m middle-only plain <<EOF
714 $ hg commit -i --config diff.noprefix=True -d '14 0' -m middle-only plain <<EOF
714 > y
715 > y
715 > y
716 > y
716 > y
717 > y
717 > n
718 > n
718 > EOF
719 > EOF
719 diff --git a/plain b/plain
720 diff --git a/plain b/plain
720 3 hunks, 7 lines changed
721 3 hunks, 7 lines changed
721 examine changes to 'plain'? [Ynesfdaq?] y
722 examine changes to 'plain'? [Ynesfdaq?] y
722
723
723 @@ -1,2 +1,5 @@
724 @@ -1,2 +1,5 @@
724 +1
725 +1
725 +2
726 +2
726 +3
727 +3
727 4
728 4
728 5
729 5
729 record change 1/3 to 'plain'? [Ynesfdaq?] y
730 record change 1/3 to 'plain'? [Ynesfdaq?] y
730
731
731 @@ -1,6 +4,8 @@
732 @@ -1,6 +4,8 @@
732 4
733 4
733 5
734 5
734 +5.new
735 +5.new
735 +5.reallynew
736 +5.reallynew
736 6
737 6
737 7
738 7
738 8
739 8
739 9
740 9
740 record change 2/3 to 'plain'? [Ynesfdaq?] y
741 record change 2/3 to 'plain'? [Ynesfdaq?] y
741
742
742 @@ -3,4 +8,6 @@
743 @@ -3,4 +8,6 @@
743 6
744 6
744 7
745 7
745 8
746 8
746 9
747 9
747 +10
748 +10
748 +11
749 +11
749 record change 3/3 to 'plain'? [Ynesfdaq?] n
750 record change 3/3 to 'plain'? [Ynesfdaq?] n
750
751
751
752
752 $ hg tip -p
753 $ hg tip -p
753 changeset: 17:41cf3f5c55ae
754 changeset: 17:41cf3f5c55ae
754 tag: tip
755 tag: tip
755 user: test
756 user: test
756 date: Thu Jan 01 00:00:14 1970 +0000
757 date: Thu Jan 01 00:00:14 1970 +0000
757 summary: middle-only
758 summary: middle-only
758
759
759 diff -r a69d252246e1 -r 41cf3f5c55ae plain
760 diff -r a69d252246e1 -r 41cf3f5c55ae plain
760 --- a/plain Thu Jan 01 00:00:13 1970 +0000
761 --- a/plain Thu Jan 01 00:00:13 1970 +0000
761 +++ b/plain Thu Jan 01 00:00:14 1970 +0000
762 +++ b/plain Thu Jan 01 00:00:14 1970 +0000
762 @@ -1,5 +1,10 @@
763 @@ -1,5 +1,10 @@
763 +1
764 +1
764 +2
765 +2
765 +3
766 +3
766 4
767 4
767 5
768 5
768 +5.new
769 +5.new
769 +5.reallynew
770 +5.reallynew
770 6
771 6
771 7
772 7
772 8
773 8
773
774
774
775
775 Record end
776 Record end
776
777
777 $ hg commit -i -d '15 0' -m end-only plain <<EOF
778 $ hg commit -i -d '15 0' -m end-only plain <<EOF
778 > y
779 > y
779 > y
780 > y
780 > EOF
781 > EOF
781 diff --git a/plain b/plain
782 diff --git a/plain b/plain
782 1 hunks, 2 lines changed
783 1 hunks, 2 lines changed
783 examine changes to 'plain'? [Ynesfdaq?] y
784 examine changes to 'plain'? [Ynesfdaq?] y
784
785
785 @@ -9,3 +9,5 @@ 6
786 @@ -9,3 +9,5 @@ 6
786 7
787 7
787 8
788 8
788 9
789 9
789 +10
790 +10
790 +11
791 +11
791 record this change to 'plain'? [Ynesfdaq?] y
792 record this change to 'plain'? [Ynesfdaq?] y
792
793
793
794
794 $ hg tip -p
795 $ hg tip -p
795 changeset: 18:58a72f46bc24
796 changeset: 18:58a72f46bc24
796 tag: tip
797 tag: tip
797 user: test
798 user: test
798 date: Thu Jan 01 00:00:15 1970 +0000
799 date: Thu Jan 01 00:00:15 1970 +0000
799 summary: end-only
800 summary: end-only
800
801
801 diff -r 41cf3f5c55ae -r 58a72f46bc24 plain
802 diff -r 41cf3f5c55ae -r 58a72f46bc24 plain
802 --- a/plain Thu Jan 01 00:00:14 1970 +0000
803 --- a/plain Thu Jan 01 00:00:14 1970 +0000
803 +++ b/plain Thu Jan 01 00:00:15 1970 +0000
804 +++ b/plain Thu Jan 01 00:00:15 1970 +0000
804 @@ -9,3 +9,5 @@
805 @@ -9,3 +9,5 @@
805 7
806 7
806 8
807 8
807 9
808 9
808 +10
809 +10
809 +11
810 +11
810
811
811
812
812 $ mkdir subdir
813 $ mkdir subdir
813 $ cd subdir
814 $ cd subdir
814 $ echo a > a
815 $ echo a > a
815 $ hg ci -d '16 0' -Amsubdir
816 $ hg ci -d '16 0' -Amsubdir
816 adding subdir/a
817 adding subdir/a
817
818
818 $ echo a >> a
819 $ echo a >> a
819 $ hg commit -i -d '16 0' -m subdir-change a <<EOF
820 $ hg commit -i -d '16 0' -m subdir-change a <<EOF
820 > y
821 > y
821 > y
822 > y
822 > EOF
823 > EOF
823 diff --git a/subdir/a b/subdir/a
824 diff --git a/subdir/a b/subdir/a
824 1 hunks, 1 lines changed
825 1 hunks, 1 lines changed
825 examine changes to 'subdir/a'? [Ynesfdaq?] y
826 examine changes to 'subdir/a'? [Ynesfdaq?] y
826
827
827 @@ -1,1 +1,2 @@
828 @@ -1,1 +1,2 @@
828 a
829 a
829 +a
830 +a
830 record this change to 'subdir/a'? [Ynesfdaq?] y
831 record this change to 'subdir/a'? [Ynesfdaq?] y
831
832
832
833
833 $ hg tip -p
834 $ hg tip -p
834 changeset: 20:e0f6b99f6c49
835 changeset: 20:e0f6b99f6c49
835 tag: tip
836 tag: tip
836 user: test
837 user: test
837 date: Thu Jan 01 00:00:16 1970 +0000
838 date: Thu Jan 01 00:00:16 1970 +0000
838 summary: subdir-change
839 summary: subdir-change
839
840
840 diff -r abd26b51de37 -r e0f6b99f6c49 subdir/a
841 diff -r abd26b51de37 -r e0f6b99f6c49 subdir/a
841 --- a/subdir/a Thu Jan 01 00:00:16 1970 +0000
842 --- a/subdir/a Thu Jan 01 00:00:16 1970 +0000
842 +++ b/subdir/a Thu Jan 01 00:00:16 1970 +0000
843 +++ b/subdir/a Thu Jan 01 00:00:16 1970 +0000
843 @@ -1,1 +1,2 @@
844 @@ -1,1 +1,2 @@
844 a
845 a
845 +a
846 +a
846
847
847
848
848 $ echo a > f1
849 $ echo a > f1
849 $ echo b > f2
850 $ echo b > f2
850 $ hg add f1 f2
851 $ hg add f1 f2
851
852
852 $ hg ci -mz -d '17 0'
853 $ hg ci -mz -d '17 0'
853
854
854 $ echo a >> f1
855 $ echo a >> f1
855 $ echo b >> f2
856 $ echo b >> f2
856
857
857 Help, quit
858 Help, quit
858
859
859 $ hg commit -i <<EOF
860 $ hg commit -i <<EOF
860 > ?
861 > ?
861 > q
862 > q
862 > EOF
863 > EOF
863 diff --git a/subdir/f1 b/subdir/f1
864 diff --git a/subdir/f1 b/subdir/f1
864 1 hunks, 1 lines changed
865 1 hunks, 1 lines changed
865 examine changes to 'subdir/f1'? [Ynesfdaq?] ?
866 examine changes to 'subdir/f1'? [Ynesfdaq?] ?
866
867
867 y - yes, record this change
868 y - yes, record this change
868 n - no, skip this change
869 n - no, skip this change
869 e - edit this change manually
870 e - edit this change manually
870 s - skip remaining changes to this file
871 s - skip remaining changes to this file
871 f - record remaining changes to this file
872 f - record remaining changes to this file
872 d - done, skip remaining changes and files
873 d - done, skip remaining changes and files
873 a - record all changes to all remaining files
874 a - record all changes to all remaining files
874 q - quit, recording no changes
875 q - quit, recording no changes
875 ? - ? (display help)
876 ? - ? (display help)
876 examine changes to 'subdir/f1'? [Ynesfdaq?] q
877 examine changes to 'subdir/f1'? [Ynesfdaq?] q
877
878
878 abort: user quit
879 abort: user quit
879 [255]
880 [255]
880
881
881 #if gettext
882 #if gettext
882
883
883 Test translated help message
884 Test translated help message
884
885
885 str.lower() instead of encoding.lower(str) on translated message might
886 str.lower() instead of encoding.lower(str) on translated message might
886 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
887 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
887 as the second or later byte of multi-byte character.
888 as the second or later byte of multi-byte character.
888
889
889 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
890 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
890 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
891 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
891 replacement makes message meaningless.
892 replacement makes message meaningless.
892
893
893 This tests that translated help message is lower()-ed correctly.
894 This tests that translated help message is lower()-ed correctly.
894
895
895 $ LANGUAGE=ja
896 $ LANGUAGE=ja
896 $ export LANGUAGE
897 $ export LANGUAGE
897
898
898 $ cat > $TESTTMP/escape.py <<EOF
899 $ cat > $TESTTMP/escape.py <<EOF
899 > from __future__ import absolute_import
900 > from __future__ import absolute_import
900 > import sys
901 > import sys
901 > def escape(c):
902 > def escape(c):
902 > o = ord(c)
903 > o = ord(c)
903 > if o < 0x80:
904 > if o < 0x80:
904 > return c
905 > return c
905 > else:
906 > else:
906 > return r'\x%02x' % o # escape char setting MSB
907 > return r'\x%02x' % o # escape char setting MSB
907 > for l in sys.stdin:
908 > for l in sys.stdin:
908 > sys.stdout.write(''.join(escape(c) for c in l))
909 > sys.stdout.write(''.join(escape(c) for c in l))
909 > EOF
910 > EOF
910
911
911 $ hg commit -i --encoding cp932 2>&1 <<EOF | python $TESTTMP/escape.py | grep '^y - '
912 $ hg commit -i --encoding cp932 2>&1 <<EOF | python $TESTTMP/escape.py | grep '^y - '
912 > ?
913 > ?
913 > q
914 > q
914 > EOF
915 > EOF
915 y - \x82\xb1\x82\xcc\x95\xcf\x8dX\x82\xf0\x8bL\x98^(yes)
916 y - \x82\xb1\x82\xcc\x95\xcf\x8dX\x82\xf0\x8bL\x98^(yes)
916
917
917 $ LANGUAGE=
918 $ LANGUAGE=
918 #endif
919 #endif
919
920
920 Skip
921 Skip
921
922
922 $ hg commit -i <<EOF
923 $ hg commit -i <<EOF
923 > s
924 > s
924 > EOF
925 > EOF
925 diff --git a/subdir/f1 b/subdir/f1
926 diff --git a/subdir/f1 b/subdir/f1
926 1 hunks, 1 lines changed
927 1 hunks, 1 lines changed
927 examine changes to 'subdir/f1'? [Ynesfdaq?] s
928 examine changes to 'subdir/f1'? [Ynesfdaq?] s
928
929
929 diff --git a/subdir/f2 b/subdir/f2
930 diff --git a/subdir/f2 b/subdir/f2
930 1 hunks, 1 lines changed
931 1 hunks, 1 lines changed
931 examine changes to 'subdir/f2'? [Ynesfdaq?] abort: response expected
932 examine changes to 'subdir/f2'? [Ynesfdaq?] abort: response expected
932 [255]
933 [255]
933
934
934 No
935 No
935
936
936 $ hg commit -i <<EOF
937 $ hg commit -i <<EOF
937 > n
938 > n
938 > EOF
939 > EOF
939 diff --git a/subdir/f1 b/subdir/f1
940 diff --git a/subdir/f1 b/subdir/f1
940 1 hunks, 1 lines changed
941 1 hunks, 1 lines changed
941 examine changes to 'subdir/f1'? [Ynesfdaq?] n
942 examine changes to 'subdir/f1'? [Ynesfdaq?] n
942
943
943 diff --git a/subdir/f2 b/subdir/f2
944 diff --git a/subdir/f2 b/subdir/f2
944 1 hunks, 1 lines changed
945 1 hunks, 1 lines changed
945 examine changes to 'subdir/f2'? [Ynesfdaq?] abort: response expected
946 examine changes to 'subdir/f2'? [Ynesfdaq?] abort: response expected
946 [255]
947 [255]
947
948
948 f, quit
949 f, quit
949
950
950 $ hg commit -i <<EOF
951 $ hg commit -i <<EOF
951 > f
952 > f
952 > q
953 > q
953 > EOF
954 > EOF
954 diff --git a/subdir/f1 b/subdir/f1
955 diff --git a/subdir/f1 b/subdir/f1
955 1 hunks, 1 lines changed
956 1 hunks, 1 lines changed
956 examine changes to 'subdir/f1'? [Ynesfdaq?] f
957 examine changes to 'subdir/f1'? [Ynesfdaq?] f
957
958
958 diff --git a/subdir/f2 b/subdir/f2
959 diff --git a/subdir/f2 b/subdir/f2
959 1 hunks, 1 lines changed
960 1 hunks, 1 lines changed
960 examine changes to 'subdir/f2'? [Ynesfdaq?] q
961 examine changes to 'subdir/f2'? [Ynesfdaq?] q
961
962
962 abort: user quit
963 abort: user quit
963 [255]
964 [255]
964
965
965 s, all
966 s, all
966
967
967 $ hg commit -i -d '18 0' -mx <<EOF
968 $ hg commit -i -d '18 0' -mx <<EOF
968 > s
969 > s
969 > a
970 > a
970 > EOF
971 > EOF
971 diff --git a/subdir/f1 b/subdir/f1
972 diff --git a/subdir/f1 b/subdir/f1
972 1 hunks, 1 lines changed
973 1 hunks, 1 lines changed
973 examine changes to 'subdir/f1'? [Ynesfdaq?] s
974 examine changes to 'subdir/f1'? [Ynesfdaq?] s
974
975
975 diff --git a/subdir/f2 b/subdir/f2
976 diff --git a/subdir/f2 b/subdir/f2
976 1 hunks, 1 lines changed
977 1 hunks, 1 lines changed
977 examine changes to 'subdir/f2'? [Ynesfdaq?] a
978 examine changes to 'subdir/f2'? [Ynesfdaq?] a
978
979
979
980
980 $ hg tip -p
981 $ hg tip -p
981 changeset: 22:6afbbefacf35
982 changeset: 22:6afbbefacf35
982 tag: tip
983 tag: tip
983 user: test
984 user: test
984 date: Thu Jan 01 00:00:18 1970 +0000
985 date: Thu Jan 01 00:00:18 1970 +0000
985 summary: x
986 summary: x
986
987
987 diff -r b73c401c693c -r 6afbbefacf35 subdir/f2
988 diff -r b73c401c693c -r 6afbbefacf35 subdir/f2
988 --- a/subdir/f2 Thu Jan 01 00:00:17 1970 +0000
989 --- a/subdir/f2 Thu Jan 01 00:00:17 1970 +0000
989 +++ b/subdir/f2 Thu Jan 01 00:00:18 1970 +0000
990 +++ b/subdir/f2 Thu Jan 01 00:00:18 1970 +0000
990 @@ -1,1 +1,2 @@
991 @@ -1,1 +1,2 @@
991 b
992 b
992 +b
993 +b
993
994
994
995
995 f
996 f
996
997
997 $ hg commit -i -d '19 0' -my <<EOF
998 $ hg commit -i -d '19 0' -my <<EOF
998 > f
999 > f
999 > EOF
1000 > EOF
1000 diff --git a/subdir/f1 b/subdir/f1
1001 diff --git a/subdir/f1 b/subdir/f1
1001 1 hunks, 1 lines changed
1002 1 hunks, 1 lines changed
1002 examine changes to 'subdir/f1'? [Ynesfdaq?] f
1003 examine changes to 'subdir/f1'? [Ynesfdaq?] f
1003
1004
1004
1005
1005 $ hg tip -p
1006 $ hg tip -p
1006 changeset: 23:715028a33949
1007 changeset: 23:715028a33949
1007 tag: tip
1008 tag: tip
1008 user: test
1009 user: test
1009 date: Thu Jan 01 00:00:19 1970 +0000
1010 date: Thu Jan 01 00:00:19 1970 +0000
1010 summary: y
1011 summary: y
1011
1012
1012 diff -r 6afbbefacf35 -r 715028a33949 subdir/f1
1013 diff -r 6afbbefacf35 -r 715028a33949 subdir/f1
1013 --- a/subdir/f1 Thu Jan 01 00:00:18 1970 +0000
1014 --- a/subdir/f1 Thu Jan 01 00:00:18 1970 +0000
1014 +++ b/subdir/f1 Thu Jan 01 00:00:19 1970 +0000
1015 +++ b/subdir/f1 Thu Jan 01 00:00:19 1970 +0000
1015 @@ -1,1 +1,2 @@
1016 @@ -1,1 +1,2 @@
1016 a
1017 a
1017 +a
1018 +a
1018
1019
1019
1020
1020 #if execbit
1021 #if execbit
1021
1022
1022 Preserve chmod +x
1023 Preserve chmod +x
1023
1024
1024 $ chmod +x f1
1025 $ chmod +x f1
1025 $ echo a >> f1
1026 $ echo a >> f1
1026 $ hg commit -i -d '20 0' -mz <<EOF
1027 $ hg commit -i -d '20 0' -mz <<EOF
1027 > y
1028 > y
1028 > y
1029 > y
1029 > y
1030 > y
1030 > EOF
1031 > EOF
1031 diff --git a/subdir/f1 b/subdir/f1
1032 diff --git a/subdir/f1 b/subdir/f1
1032 old mode 100644
1033 old mode 100644
1033 new mode 100755
1034 new mode 100755
1034 1 hunks, 1 lines changed
1035 1 hunks, 1 lines changed
1035 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1036 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1036
1037
1037 @@ -1,2 +1,3 @@
1038 @@ -1,2 +1,3 @@
1038 a
1039 a
1039 a
1040 a
1040 +a
1041 +a
1041 record this change to 'subdir/f1'? [Ynesfdaq?] y
1042 record this change to 'subdir/f1'? [Ynesfdaq?] y
1042
1043
1043
1044
1044 $ hg tip --config diff.git=True -p
1045 $ hg tip --config diff.git=True -p
1045 changeset: 24:db967c1e5884
1046 changeset: 24:db967c1e5884
1046 tag: tip
1047 tag: tip
1047 user: test
1048 user: test
1048 date: Thu Jan 01 00:00:20 1970 +0000
1049 date: Thu Jan 01 00:00:20 1970 +0000
1049 summary: z
1050 summary: z
1050
1051
1051 diff --git a/subdir/f1 b/subdir/f1
1052 diff --git a/subdir/f1 b/subdir/f1
1052 old mode 100644
1053 old mode 100644
1053 new mode 100755
1054 new mode 100755
1054 --- a/subdir/f1
1055 --- a/subdir/f1
1055 +++ b/subdir/f1
1056 +++ b/subdir/f1
1056 @@ -1,2 +1,3 @@
1057 @@ -1,2 +1,3 @@
1057 a
1058 a
1058 a
1059 a
1059 +a
1060 +a
1060
1061
1061
1062
1062 Preserve execute permission on original
1063 Preserve execute permission on original
1063
1064
1064 $ echo b >> f1
1065 $ echo b >> f1
1065 $ hg commit -i -d '21 0' -maa <<EOF
1066 $ hg commit -i -d '21 0' -maa <<EOF
1066 > y
1067 > y
1067 > y
1068 > y
1068 > y
1069 > y
1069 > EOF
1070 > EOF
1070 diff --git a/subdir/f1 b/subdir/f1
1071 diff --git a/subdir/f1 b/subdir/f1
1071 1 hunks, 1 lines changed
1072 1 hunks, 1 lines changed
1072 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1073 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1073
1074
1074 @@ -1,3 +1,4 @@
1075 @@ -1,3 +1,4 @@
1075 a
1076 a
1076 a
1077 a
1077 a
1078 a
1078 +b
1079 +b
1079 record this change to 'subdir/f1'? [Ynesfdaq?] y
1080 record this change to 'subdir/f1'? [Ynesfdaq?] y
1080
1081
1081
1082
1082 $ hg tip --config diff.git=True -p
1083 $ hg tip --config diff.git=True -p
1083 changeset: 25:88903aef81c3
1084 changeset: 25:88903aef81c3
1084 tag: tip
1085 tag: tip
1085 user: test
1086 user: test
1086 date: Thu Jan 01 00:00:21 1970 +0000
1087 date: Thu Jan 01 00:00:21 1970 +0000
1087 summary: aa
1088 summary: aa
1088
1089
1089 diff --git a/subdir/f1 b/subdir/f1
1090 diff --git a/subdir/f1 b/subdir/f1
1090 --- a/subdir/f1
1091 --- a/subdir/f1
1091 +++ b/subdir/f1
1092 +++ b/subdir/f1
1092 @@ -1,3 +1,4 @@
1093 @@ -1,3 +1,4 @@
1093 a
1094 a
1094 a
1095 a
1095 a
1096 a
1096 +b
1097 +b
1097
1098
1098
1099
1099 Preserve chmod -x
1100 Preserve chmod -x
1100
1101
1101 $ chmod -x f1
1102 $ chmod -x f1
1102 $ echo c >> f1
1103 $ echo c >> f1
1103 $ hg commit -i -d '22 0' -mab <<EOF
1104 $ hg commit -i -d '22 0' -mab <<EOF
1104 > y
1105 > y
1105 > y
1106 > y
1106 > y
1107 > y
1107 > EOF
1108 > EOF
1108 diff --git a/subdir/f1 b/subdir/f1
1109 diff --git a/subdir/f1 b/subdir/f1
1109 old mode 100755
1110 old mode 100755
1110 new mode 100644
1111 new mode 100644
1111 1 hunks, 1 lines changed
1112 1 hunks, 1 lines changed
1112 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1113 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1113
1114
1114 @@ -2,3 +2,4 @@ a
1115 @@ -2,3 +2,4 @@ a
1115 a
1116 a
1116 a
1117 a
1117 b
1118 b
1118 +c
1119 +c
1119 record this change to 'subdir/f1'? [Ynesfdaq?] y
1120 record this change to 'subdir/f1'? [Ynesfdaq?] y
1120
1121
1121
1122
1122 $ hg tip --config diff.git=True -p
1123 $ hg tip --config diff.git=True -p
1123 changeset: 26:7af84b6cf560
1124 changeset: 26:7af84b6cf560
1124 tag: tip
1125 tag: tip
1125 user: test
1126 user: test
1126 date: Thu Jan 01 00:00:22 1970 +0000
1127 date: Thu Jan 01 00:00:22 1970 +0000
1127 summary: ab
1128 summary: ab
1128
1129
1129 diff --git a/subdir/f1 b/subdir/f1
1130 diff --git a/subdir/f1 b/subdir/f1
1130 old mode 100755
1131 old mode 100755
1131 new mode 100644
1132 new mode 100644
1132 --- a/subdir/f1
1133 --- a/subdir/f1
1133 +++ b/subdir/f1
1134 +++ b/subdir/f1
1134 @@ -2,3 +2,4 @@
1135 @@ -2,3 +2,4 @@
1135 a
1136 a
1136 a
1137 a
1137 b
1138 b
1138 +c
1139 +c
1139
1140
1140
1141
1141 #else
1142 #else
1142
1143
1143 Slightly bogus tests to get almost same repo structure as when x bit is used
1144 Slightly bogus tests to get almost same repo structure as when x bit is used
1144 - but with different hashes.
1145 - but with different hashes.
1145
1146
1146 Mock "Preserve chmod +x"
1147 Mock "Preserve chmod +x"
1147
1148
1148 $ echo a >> f1
1149 $ echo a >> f1
1149 $ hg commit -i -d '20 0' -mz <<EOF
1150 $ hg commit -i -d '20 0' -mz <<EOF
1150 > y
1151 > y
1151 > y
1152 > y
1152 > y
1153 > y
1153 > EOF
1154 > EOF
1154 diff --git a/subdir/f1 b/subdir/f1
1155 diff --git a/subdir/f1 b/subdir/f1
1155 1 hunks, 1 lines changed
1156 1 hunks, 1 lines changed
1156 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1157 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1157
1158
1158 @@ -1,2 +1,3 @@
1159 @@ -1,2 +1,3 @@
1159 a
1160 a
1160 a
1161 a
1161 +a
1162 +a
1162 record this change to 'subdir/f1'? [Ynesfdaq?] y
1163 record this change to 'subdir/f1'? [Ynesfdaq?] y
1163
1164
1164
1165
1165 $ hg tip --config diff.git=True -p
1166 $ hg tip --config diff.git=True -p
1166 changeset: 24:c26cfe2c4eb0
1167 changeset: 24:c26cfe2c4eb0
1167 tag: tip
1168 tag: tip
1168 user: test
1169 user: test
1169 date: Thu Jan 01 00:00:20 1970 +0000
1170 date: Thu Jan 01 00:00:20 1970 +0000
1170 summary: z
1171 summary: z
1171
1172
1172 diff --git a/subdir/f1 b/subdir/f1
1173 diff --git a/subdir/f1 b/subdir/f1
1173 --- a/subdir/f1
1174 --- a/subdir/f1
1174 +++ b/subdir/f1
1175 +++ b/subdir/f1
1175 @@ -1,2 +1,3 @@
1176 @@ -1,2 +1,3 @@
1176 a
1177 a
1177 a
1178 a
1178 +a
1179 +a
1179
1180
1180
1181
1181 Mock "Preserve execute permission on original"
1182 Mock "Preserve execute permission on original"
1182
1183
1183 $ echo b >> f1
1184 $ echo b >> f1
1184 $ hg commit -i -d '21 0' -maa <<EOF
1185 $ hg commit -i -d '21 0' -maa <<EOF
1185 > y
1186 > y
1186 > y
1187 > y
1187 > y
1188 > y
1188 > EOF
1189 > EOF
1189 diff --git a/subdir/f1 b/subdir/f1
1190 diff --git a/subdir/f1 b/subdir/f1
1190 1 hunks, 1 lines changed
1191 1 hunks, 1 lines changed
1191 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1192 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1192
1193
1193 @@ -1,3 +1,4 @@
1194 @@ -1,3 +1,4 @@
1194 a
1195 a
1195 a
1196 a
1196 a
1197 a
1197 +b
1198 +b
1198 record this change to 'subdir/f1'? [Ynesfdaq?] y
1199 record this change to 'subdir/f1'? [Ynesfdaq?] y
1199
1200
1200
1201
1201 $ hg tip --config diff.git=True -p
1202 $ hg tip --config diff.git=True -p
1202 changeset: 25:a48d2d60adde
1203 changeset: 25:a48d2d60adde
1203 tag: tip
1204 tag: tip
1204 user: test
1205 user: test
1205 date: Thu Jan 01 00:00:21 1970 +0000
1206 date: Thu Jan 01 00:00:21 1970 +0000
1206 summary: aa
1207 summary: aa
1207
1208
1208 diff --git a/subdir/f1 b/subdir/f1
1209 diff --git a/subdir/f1 b/subdir/f1
1209 --- a/subdir/f1
1210 --- a/subdir/f1
1210 +++ b/subdir/f1
1211 +++ b/subdir/f1
1211 @@ -1,3 +1,4 @@
1212 @@ -1,3 +1,4 @@
1212 a
1213 a
1213 a
1214 a
1214 a
1215 a
1215 +b
1216 +b
1216
1217
1217
1218
1218 Mock "Preserve chmod -x"
1219 Mock "Preserve chmod -x"
1219
1220
1220 $ chmod -x f1
1221 $ chmod -x f1
1221 $ echo c >> f1
1222 $ echo c >> f1
1222 $ hg commit -i -d '22 0' -mab <<EOF
1223 $ hg commit -i -d '22 0' -mab <<EOF
1223 > y
1224 > y
1224 > y
1225 > y
1225 > y
1226 > y
1226 > EOF
1227 > EOF
1227 diff --git a/subdir/f1 b/subdir/f1
1228 diff --git a/subdir/f1 b/subdir/f1
1228 1 hunks, 1 lines changed
1229 1 hunks, 1 lines changed
1229 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1230 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1230
1231
1231 @@ -2,3 +2,4 @@ a
1232 @@ -2,3 +2,4 @@ a
1232 a
1233 a
1233 a
1234 a
1234 b
1235 b
1235 +c
1236 +c
1236 record this change to 'subdir/f1'? [Ynesfdaq?] y
1237 record this change to 'subdir/f1'? [Ynesfdaq?] y
1237
1238
1238
1239
1239 $ hg tip --config diff.git=True -p
1240 $ hg tip --config diff.git=True -p
1240 changeset: 26:5cc89ae210fa
1241 changeset: 26:5cc89ae210fa
1241 tag: tip
1242 tag: tip
1242 user: test
1243 user: test
1243 date: Thu Jan 01 00:00:22 1970 +0000
1244 date: Thu Jan 01 00:00:22 1970 +0000
1244 summary: ab
1245 summary: ab
1245
1246
1246 diff --git a/subdir/f1 b/subdir/f1
1247 diff --git a/subdir/f1 b/subdir/f1
1247 --- a/subdir/f1
1248 --- a/subdir/f1
1248 +++ b/subdir/f1
1249 +++ b/subdir/f1
1249 @@ -2,3 +2,4 @@
1250 @@ -2,3 +2,4 @@
1250 a
1251 a
1251 a
1252 a
1252 b
1253 b
1253 +c
1254 +c
1254
1255
1255
1256
1256 #endif
1257 #endif
1257
1258
1258 $ cd ..
1259 $ cd ..
1259
1260
1260
1261
1261 Abort early when a merge is in progress
1262 Abort early when a merge is in progress
1262
1263
1263 $ hg up 4
1264 $ hg up 4
1264 1 files updated, 0 files merged, 7 files removed, 0 files unresolved
1265 1 files updated, 0 files merged, 7 files removed, 0 files unresolved
1265
1266
1266 $ touch iwillmergethat
1267 $ touch iwillmergethat
1267 $ hg add iwillmergethat
1268 $ hg add iwillmergethat
1268
1269
1269 $ hg branch thatbranch
1270 $ hg branch thatbranch
1270 marked working directory as branch thatbranch
1271 marked working directory as branch thatbranch
1271 (branches are permanent and global, did you want a bookmark?)
1272 (branches are permanent and global, did you want a bookmark?)
1272
1273
1273 $ hg ci -m'new head'
1274 $ hg ci -m'new head'
1274
1275
1275 $ hg up default
1276 $ hg up default
1276 7 files updated, 0 files merged, 2 files removed, 0 files unresolved
1277 7 files updated, 0 files merged, 2 files removed, 0 files unresolved
1277
1278
1278 $ hg merge thatbranch
1279 $ hg merge thatbranch
1279 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1280 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1280 (branch merge, don't forget to commit)
1281 (branch merge, don't forget to commit)
1281
1282
1282 $ hg commit -i -m'will abort'
1283 $ hg commit -i -m'will abort'
1283 abort: cannot partially commit a merge (use "hg commit" instead)
1284 abort: cannot partially commit a merge (use "hg commit" instead)
1284 [255]
1285 [255]
1285
1286
1286 $ hg up -C
1287 $ hg up -C
1287 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1288 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1288
1289
1289 Editing patch (and ignoring trailing text)
1290 Editing patch (and ignoring trailing text)
1290
1291
1291 $ cat > editor.sh << '__EOF__'
1292 $ cat > editor.sh << '__EOF__'
1292 > sed -e 7d -e '5s/^-/ /' -e '/^# ---/i\
1293 > sed -e 7d -e '5s/^-/ /' -e '/^# ---/i\
1293 > trailing\nditto' "$1" > tmp
1294 > trailing\nditto' "$1" > tmp
1294 > mv tmp "$1"
1295 > mv tmp "$1"
1295 > __EOF__
1296 > __EOF__
1296 $ cat > editedfile << '__EOF__'
1297 $ cat > editedfile << '__EOF__'
1297 > This is the first line
1298 > This is the first line
1298 > This is the second line
1299 > This is the second line
1299 > This is the third line
1300 > This is the third line
1300 > __EOF__
1301 > __EOF__
1301 $ hg add editedfile
1302 $ hg add editedfile
1302 $ hg commit -medit-patch-1
1303 $ hg commit -medit-patch-1
1303 $ cat > editedfile << '__EOF__'
1304 $ cat > editedfile << '__EOF__'
1304 > This line has changed
1305 > This line has changed
1305 > This change will be committed
1306 > This change will be committed
1306 > This is the third line
1307 > This is the third line
1307 > __EOF__
1308 > __EOF__
1308 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -d '23 0' -medit-patch-2 <<EOF
1309 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -d '23 0' -medit-patch-2 <<EOF
1309 > y
1310 > y
1310 > e
1311 > e
1311 > EOF
1312 > EOF
1312 diff --git a/editedfile b/editedfile
1313 diff --git a/editedfile b/editedfile
1313 1 hunks, 2 lines changed
1314 1 hunks, 2 lines changed
1314 examine changes to 'editedfile'? [Ynesfdaq?] y
1315 examine changes to 'editedfile'? [Ynesfdaq?] y
1315
1316
1316 @@ -1,3 +1,3 @@
1317 @@ -1,3 +1,3 @@
1317 -This is the first line
1318 -This is the first line
1318 -This is the second line
1319 -This is the second line
1319 +This line has changed
1320 +This line has changed
1320 +This change will be committed
1321 +This change will be committed
1321 This is the third line
1322 This is the third line
1322 record this change to 'editedfile'? [Ynesfdaq?] e
1323 record this change to 'editedfile'? [Ynesfdaq?] e
1323
1324
1324 $ cat editedfile
1325 $ cat editedfile
1325 This line has changed
1326 This line has changed
1326 This change will be committed
1327 This change will be committed
1327 This is the third line
1328 This is the third line
1328 $ hg cat -r tip editedfile
1329 $ hg cat -r tip editedfile
1329 This is the first line
1330 This is the first line
1330 This change will be committed
1331 This change will be committed
1331 This is the third line
1332 This is the third line
1332 $ hg revert editedfile
1333 $ hg revert editedfile
1333
1334
1334 Trying to edit patch for whole file
1335 Trying to edit patch for whole file
1335
1336
1336 $ echo "This is the fourth line" >> editedfile
1337 $ echo "This is the fourth line" >> editedfile
1337 $ hg commit -i <<EOF
1338 $ hg commit -i <<EOF
1338 > e
1339 > e
1339 > q
1340 > q
1340 > EOF
1341 > EOF
1341 diff --git a/editedfile b/editedfile
1342 diff --git a/editedfile b/editedfile
1342 1 hunks, 1 lines changed
1343 1 hunks, 1 lines changed
1343 examine changes to 'editedfile'? [Ynesfdaq?] e
1344 examine changes to 'editedfile'? [Ynesfdaq?] e
1344
1345
1345 cannot edit patch for whole file
1346 cannot edit patch for whole file
1346 examine changes to 'editedfile'? [Ynesfdaq?] q
1347 examine changes to 'editedfile'? [Ynesfdaq?] q
1347
1348
1348 abort: user quit
1349 abort: user quit
1349 [255]
1350 [255]
1350 $ hg revert editedfile
1351 $ hg revert editedfile
1351
1352
1352 Removing changes from patch
1353 Removing changes from patch
1353
1354
1354 $ sed -e '3s/third/second/' -e '2s/will/will not/' -e 1d editedfile > tmp
1355 $ sed -e '3s/third/second/' -e '2s/will/will not/' -e 1d editedfile > tmp
1355 $ mv tmp editedfile
1356 $ mv tmp editedfile
1356 $ echo "This line has been added" >> editedfile
1357 $ echo "This line has been added" >> editedfile
1357 $ cat > editor.sh << '__EOF__'
1358 $ cat > editor.sh << '__EOF__'
1358 > sed -e 's/^[-+]/ /' "$1" > tmp
1359 > sed -e 's/^[-+]/ /' "$1" > tmp
1359 > mv tmp "$1"
1360 > mv tmp "$1"
1360 > __EOF__
1361 > __EOF__
1361 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i <<EOF
1362 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i <<EOF
1362 > y
1363 > y
1363 > e
1364 > e
1364 > EOF
1365 > EOF
1365 diff --git a/editedfile b/editedfile
1366 diff --git a/editedfile b/editedfile
1366 1 hunks, 3 lines changed
1367 1 hunks, 3 lines changed
1367 examine changes to 'editedfile'? [Ynesfdaq?] y
1368 examine changes to 'editedfile'? [Ynesfdaq?] y
1368
1369
1369 @@ -1,3 +1,3 @@
1370 @@ -1,3 +1,3 @@
1370 -This is the first line
1371 -This is the first line
1371 -This change will be committed
1372 -This change will be committed
1372 -This is the third line
1373 -This is the third line
1373 +This change will not be committed
1374 +This change will not be committed
1374 +This is the second line
1375 +This is the second line
1375 +This line has been added
1376 +This line has been added
1376 record this change to 'editedfile'? [Ynesfdaq?] e
1377 record this change to 'editedfile'? [Ynesfdaq?] e
1377
1378
1378 no changes to record
1379 no changes to record
1380 [1]
1379 $ cat editedfile
1381 $ cat editedfile
1380 This change will not be committed
1382 This change will not be committed
1381 This is the second line
1383 This is the second line
1382 This line has been added
1384 This line has been added
1383 $ hg cat -r tip editedfile
1385 $ hg cat -r tip editedfile
1384 This is the first line
1386 This is the first line
1385 This change will be committed
1387 This change will be committed
1386 This is the third line
1388 This is the third line
1387 $ hg revert editedfile
1389 $ hg revert editedfile
1388
1390
1389 Invalid patch
1391 Invalid patch
1390
1392
1391 $ sed -e '3s/third/second/' -e '2s/will/will not/' -e 1d editedfile > tmp
1393 $ sed -e '3s/third/second/' -e '2s/will/will not/' -e 1d editedfile > tmp
1392 $ mv tmp editedfile
1394 $ mv tmp editedfile
1393 $ echo "This line has been added" >> editedfile
1395 $ echo "This line has been added" >> editedfile
1394 $ cat > editor.sh << '__EOF__'
1396 $ cat > editor.sh << '__EOF__'
1395 > sed s/This/That/ "$1" > tmp
1397 > sed s/This/That/ "$1" > tmp
1396 > mv tmp "$1"
1398 > mv tmp "$1"
1397 > __EOF__
1399 > __EOF__
1398 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i <<EOF
1400 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i <<EOF
1399 > y
1401 > y
1400 > e
1402 > e
1401 > EOF
1403 > EOF
1402 diff --git a/editedfile b/editedfile
1404 diff --git a/editedfile b/editedfile
1403 1 hunks, 3 lines changed
1405 1 hunks, 3 lines changed
1404 examine changes to 'editedfile'? [Ynesfdaq?] y
1406 examine changes to 'editedfile'? [Ynesfdaq?] y
1405
1407
1406 @@ -1,3 +1,3 @@
1408 @@ -1,3 +1,3 @@
1407 -This is the first line
1409 -This is the first line
1408 -This change will be committed
1410 -This change will be committed
1409 -This is the third line
1411 -This is the third line
1410 +This change will not be committed
1412 +This change will not be committed
1411 +This is the second line
1413 +This is the second line
1412 +This line has been added
1414 +This line has been added
1413 record this change to 'editedfile'? [Ynesfdaq?] e
1415 record this change to 'editedfile'? [Ynesfdaq?] e
1414
1416
1415 patching file editedfile
1417 patching file editedfile
1416 Hunk #1 FAILED at 0
1418 Hunk #1 FAILED at 0
1417 1 out of 1 hunks FAILED -- saving rejects to file editedfile.rej
1419 1 out of 1 hunks FAILED -- saving rejects to file editedfile.rej
1418 abort: patch failed to apply
1420 abort: patch failed to apply
1419 [255]
1421 [255]
1420 $ cat editedfile
1422 $ cat editedfile
1421 This change will not be committed
1423 This change will not be committed
1422 This is the second line
1424 This is the second line
1423 This line has been added
1425 This line has been added
1424 $ hg cat -r tip editedfile
1426 $ hg cat -r tip editedfile
1425 This is the first line
1427 This is the first line
1426 This change will be committed
1428 This change will be committed
1427 This is the third line
1429 This is the third line
1428 $ cat editedfile.rej
1430 $ cat editedfile.rej
1429 --- editedfile
1431 --- editedfile
1430 +++ editedfile
1432 +++ editedfile
1431 @@ -1,3 +1,3 @@
1433 @@ -1,3 +1,3 @@
1432 -That is the first line
1434 -That is the first line
1433 -That change will be committed
1435 -That change will be committed
1434 -That is the third line
1436 -That is the third line
1435 +That change will not be committed
1437 +That change will not be committed
1436 +That is the second line
1438 +That is the second line
1437 +That line has been added
1439 +That line has been added
1438
1440
1439 Malformed patch - error handling
1441 Malformed patch - error handling
1440
1442
1441 $ cat > editor.sh << '__EOF__'
1443 $ cat > editor.sh << '__EOF__'
1442 > sed -e '/^@/p' "$1" > tmp
1444 > sed -e '/^@/p' "$1" > tmp
1443 > mv tmp "$1"
1445 > mv tmp "$1"
1444 > __EOF__
1446 > __EOF__
1445 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i <<EOF
1447 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i <<EOF
1446 > y
1448 > y
1447 > e
1449 > e
1448 > EOF
1450 > EOF
1449 diff --git a/editedfile b/editedfile
1451 diff --git a/editedfile b/editedfile
1450 1 hunks, 3 lines changed
1452 1 hunks, 3 lines changed
1451 examine changes to 'editedfile'? [Ynesfdaq?] y
1453 examine changes to 'editedfile'? [Ynesfdaq?] y
1452
1454
1453 @@ -1,3 +1,3 @@
1455 @@ -1,3 +1,3 @@
1454 -This is the first line
1456 -This is the first line
1455 -This change will be committed
1457 -This change will be committed
1456 -This is the third line
1458 -This is the third line
1457 +This change will not be committed
1459 +This change will not be committed
1458 +This is the second line
1460 +This is the second line
1459 +This line has been added
1461 +This line has been added
1460 record this change to 'editedfile'? [Ynesfdaq?] e
1462 record this change to 'editedfile'? [Ynesfdaq?] e
1461
1463
1462 abort: error parsing patch: unhandled transition: range -> range
1464 abort: error parsing patch: unhandled transition: range -> range
1463 [255]
1465 [255]
1464
1466
1465 Exiting editor with status 1, ignores the edit but does not stop the recording
1467 Exiting editor with status 1, ignores the edit but does not stop the recording
1466 session
1468 session
1467
1469
1468 $ HGEDITOR=false hg commit -i <<EOF
1470 $ HGEDITOR=false hg commit -i <<EOF
1469 > y
1471 > y
1470 > e
1472 > e
1471 > n
1473 > n
1472 > EOF
1474 > EOF
1473 diff --git a/editedfile b/editedfile
1475 diff --git a/editedfile b/editedfile
1474 1 hunks, 3 lines changed
1476 1 hunks, 3 lines changed
1475 examine changes to 'editedfile'? [Ynesfdaq?] y
1477 examine changes to 'editedfile'? [Ynesfdaq?] y
1476
1478
1477 @@ -1,3 +1,3 @@
1479 @@ -1,3 +1,3 @@
1478 -This is the first line
1480 -This is the first line
1479 -This change will be committed
1481 -This change will be committed
1480 -This is the third line
1482 -This is the third line
1481 +This change will not be committed
1483 +This change will not be committed
1482 +This is the second line
1484 +This is the second line
1483 +This line has been added
1485 +This line has been added
1484 record this change to 'editedfile'? [Ynesfdaq?] e
1486 record this change to 'editedfile'? [Ynesfdaq?] e
1485
1487
1486 editor exited with exit code 1
1488 editor exited with exit code 1
1487 record this change to 'editedfile'? [Ynesfdaq?] n
1489 record this change to 'editedfile'? [Ynesfdaq?] n
1488
1490
1489 no changes to record
1491 no changes to record
1492 [1]
1490
1493
1491
1494
1492 random text in random positions is still an error
1495 random text in random positions is still an error
1493
1496
1494 $ cat > editor.sh << '__EOF__'
1497 $ cat > editor.sh << '__EOF__'
1495 > sed -e '/^@/i\
1498 > sed -e '/^@/i\
1496 > other' "$1" > tmp
1499 > other' "$1" > tmp
1497 > mv tmp "$1"
1500 > mv tmp "$1"
1498 > __EOF__
1501 > __EOF__
1499 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i <<EOF
1502 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i <<EOF
1500 > y
1503 > y
1501 > e
1504 > e
1502 > EOF
1505 > EOF
1503 diff --git a/editedfile b/editedfile
1506 diff --git a/editedfile b/editedfile
1504 1 hunks, 3 lines changed
1507 1 hunks, 3 lines changed
1505 examine changes to 'editedfile'? [Ynesfdaq?] y
1508 examine changes to 'editedfile'? [Ynesfdaq?] y
1506
1509
1507 @@ -1,3 +1,3 @@
1510 @@ -1,3 +1,3 @@
1508 -This is the first line
1511 -This is the first line
1509 -This change will be committed
1512 -This change will be committed
1510 -This is the third line
1513 -This is the third line
1511 +This change will not be committed
1514 +This change will not be committed
1512 +This is the second line
1515 +This is the second line
1513 +This line has been added
1516 +This line has been added
1514 record this change to 'editedfile'? [Ynesfdaq?] e
1517 record this change to 'editedfile'? [Ynesfdaq?] e
1515
1518
1516 abort: error parsing patch: unhandled transition: file -> other
1519 abort: error parsing patch: unhandled transition: file -> other
1517 [255]
1520 [255]
1518
1521
1519 $ hg up -C
1522 $ hg up -C
1520 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1523 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1521
1524
1522 With win32text
1525 With win32text
1523
1526
1524 $ echo '[extensions]' >> .hg/hgrc
1527 $ echo '[extensions]' >> .hg/hgrc
1525 $ echo 'win32text = ' >> .hg/hgrc
1528 $ echo 'win32text = ' >> .hg/hgrc
1526 $ echo '[decode]' >> .hg/hgrc
1529 $ echo '[decode]' >> .hg/hgrc
1527 $ echo '** = cleverdecode:' >> .hg/hgrc
1530 $ echo '** = cleverdecode:' >> .hg/hgrc
1528 $ echo '[encode]' >> .hg/hgrc
1531 $ echo '[encode]' >> .hg/hgrc
1529 $ echo '** = cleverencode:' >> .hg/hgrc
1532 $ echo '** = cleverencode:' >> .hg/hgrc
1530 $ echo '[patch]' >> .hg/hgrc
1533 $ echo '[patch]' >> .hg/hgrc
1531 $ echo 'eol = crlf' >> .hg/hgrc
1534 $ echo 'eol = crlf' >> .hg/hgrc
1532
1535
1533 Ignore win32text deprecation warning for now:
1536 Ignore win32text deprecation warning for now:
1534
1537
1535 $ echo '[win32text]' >> .hg/hgrc
1538 $ echo '[win32text]' >> .hg/hgrc
1536 $ echo 'warn = no' >> .hg/hgrc
1539 $ echo 'warn = no' >> .hg/hgrc
1537
1540
1538 $ echo d >> subdir/f1
1541 $ echo d >> subdir/f1
1539 $ hg commit -i -d '24 0' -mw1 <<EOF
1542 $ hg commit -i -d '24 0' -mw1 <<EOF
1540 > y
1543 > y
1541 > y
1544 > y
1542 > EOF
1545 > EOF
1543 diff --git a/subdir/f1 b/subdir/f1
1546 diff --git a/subdir/f1 b/subdir/f1
1544 1 hunks, 1 lines changed
1547 1 hunks, 1 lines changed
1545 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1548 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1546
1549
1547 @@ -3,3 +3,4 @@ a
1550 @@ -3,3 +3,4 @@ a
1548 a
1551 a
1549 b
1552 b
1550 c
1553 c
1551 +d
1554 +d
1552 record this change to 'subdir/f1'? [Ynesfdaq?] y
1555 record this change to 'subdir/f1'? [Ynesfdaq?] y
1553
1556
1554
1557
1555 $ hg status -A subdir/f1
1558 $ hg status -A subdir/f1
1556 C subdir/f1
1559 C subdir/f1
1557 $ hg tip -p
1560 $ hg tip -p
1558 changeset: 30:* (glob)
1561 changeset: 30:* (glob)
1559 tag: tip
1562 tag: tip
1560 user: test
1563 user: test
1561 date: Thu Jan 01 00:00:24 1970 +0000
1564 date: Thu Jan 01 00:00:24 1970 +0000
1562 summary: w1
1565 summary: w1
1563
1566
1564 diff -r ???????????? -r ???????????? subdir/f1 (glob)
1567 diff -r ???????????? -r ???????????? subdir/f1 (glob)
1565 --- a/subdir/f1 Thu Jan 01 00:00:23 1970 +0000
1568 --- a/subdir/f1 Thu Jan 01 00:00:23 1970 +0000
1566 +++ b/subdir/f1 Thu Jan 01 00:00:24 1970 +0000
1569 +++ b/subdir/f1 Thu Jan 01 00:00:24 1970 +0000
1567 @@ -3,3 +3,4 @@
1570 @@ -3,3 +3,4 @@
1568 a
1571 a
1569 b
1572 b
1570 c
1573 c
1571 +d
1574 +d
1572
1575
1573
1576
1574
1577
1575 Test --user when ui.username not set
1578 Test --user when ui.username not set
1576 $ unset HGUSER
1579 $ unset HGUSER
1577 $ echo e >> subdir/f1
1580 $ echo e >> subdir/f1
1578 $ hg commit -i --config ui.username= -d '8 0' --user xyz -m "user flag" <<EOF
1581 $ hg commit -i --config ui.username= -d '8 0' --user xyz -m "user flag" <<EOF
1579 > y
1582 > y
1580 > y
1583 > y
1581 > EOF
1584 > EOF
1582 diff --git a/subdir/f1 b/subdir/f1
1585 diff --git a/subdir/f1 b/subdir/f1
1583 1 hunks, 1 lines changed
1586 1 hunks, 1 lines changed
1584 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1587 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1585
1588
1586 @@ -4,3 +4,4 @@ a
1589 @@ -4,3 +4,4 @@ a
1587 b
1590 b
1588 c
1591 c
1589 d
1592 d
1590 +e
1593 +e
1591 record this change to 'subdir/f1'? [Ynesfdaq?] y
1594 record this change to 'subdir/f1'? [Ynesfdaq?] y
1592
1595
1593 $ hg status -A subdir/f1
1596 $ hg status -A subdir/f1
1594 C subdir/f1
1597 C subdir/f1
1595 $ hg log --template '{author}\n' -l 1
1598 $ hg log --template '{author}\n' -l 1
1596 xyz
1599 xyz
1597 $ HGUSER="test"
1600 $ HGUSER="test"
1598 $ export HGUSER
1601 $ export HGUSER
1599
1602
1600
1603
1601 Moving files
1604 Moving files
1602
1605
1603 $ hg update -C .
1606 $ hg update -C .
1604 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1607 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1605 $ hg mv plain plain3
1608 $ hg mv plain plain3
1606 $ echo somechange >> plain3
1609 $ echo somechange >> plain3
1607 $ hg commit -i -d '23 0' -mmoving_files << EOF
1610 $ hg commit -i -d '23 0' -mmoving_files << EOF
1608 > y
1611 > y
1609 > y
1612 > y
1610 > EOF
1613 > EOF
1611 diff --git a/plain b/plain3
1614 diff --git a/plain b/plain3
1612 rename from plain
1615 rename from plain
1613 rename to plain3
1616 rename to plain3
1614 1 hunks, 1 lines changed
1617 1 hunks, 1 lines changed
1615 examine changes to 'plain' and 'plain3'? [Ynesfdaq?] y
1618 examine changes to 'plain' and 'plain3'? [Ynesfdaq?] y
1616
1619
1617 @@ -11,3 +11,4 @@ 8
1620 @@ -11,3 +11,4 @@ 8
1618 9
1621 9
1619 10
1622 10
1620 11
1623 11
1621 +somechange
1624 +somechange
1622 record this change to 'plain3'? [Ynesfdaq?] y
1625 record this change to 'plain3'? [Ynesfdaq?] y
1623
1626
1624 The #if execbit block above changes the hash here on some systems
1627 The #if execbit block above changes the hash here on some systems
1625 $ hg status -A plain3
1628 $ hg status -A plain3
1626 C plain3
1629 C plain3
1627 $ hg tip
1630 $ hg tip
1628 changeset: 32:* (glob)
1631 changeset: 32:* (glob)
1629 tag: tip
1632 tag: tip
1630 user: test
1633 user: test
1631 date: Thu Jan 01 00:00:23 1970 +0000
1634 date: Thu Jan 01 00:00:23 1970 +0000
1632 summary: moving_files
1635 summary: moving_files
1633
1636
1634 Editing patch of newly added file
1637 Editing patch of newly added file
1635
1638
1636 $ hg update -C .
1639 $ hg update -C .
1637 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1640 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1638 $ cat > editor.sh << '__EOF__'
1641 $ cat > editor.sh << '__EOF__'
1639 > cat "$1" | sed "s/first/very/g" > tt
1642 > cat "$1" | sed "s/first/very/g" > tt
1640 > mv tt "$1"
1643 > mv tt "$1"
1641 > __EOF__
1644 > __EOF__
1642 $ cat > newfile << '__EOF__'
1645 $ cat > newfile << '__EOF__'
1643 > This is the first line
1646 > This is the first line
1644 > This is the second line
1647 > This is the second line
1645 > This is the third line
1648 > This is the third line
1646 > __EOF__
1649 > __EOF__
1647 $ hg add newfile
1650 $ hg add newfile
1648 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -d '23 0' -medit-patch-new <<EOF
1651 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit -i -d '23 0' -medit-patch-new <<EOF
1649 > y
1652 > y
1650 > e
1653 > e
1651 > EOF
1654 > EOF
1652 diff --git a/newfile b/newfile
1655 diff --git a/newfile b/newfile
1653 new file mode 100644
1656 new file mode 100644
1654 examine changes to 'newfile'? [Ynesfdaq?] y
1657 examine changes to 'newfile'? [Ynesfdaq?] y
1655
1658
1656 @@ -0,0 +1,3 @@
1659 @@ -0,0 +1,3 @@
1657 +This is the first line
1660 +This is the first line
1658 +This is the second line
1661 +This is the second line
1659 +This is the third line
1662 +This is the third line
1660 record this change to 'newfile'? [Ynesfdaq?] e
1663 record this change to 'newfile'? [Ynesfdaq?] e
1661
1664
1662 $ hg cat -r tip newfile
1665 $ hg cat -r tip newfile
1663 This is the very line
1666 This is the very line
1664 This is the second line
1667 This is the second line
1665 This is the third line
1668 This is the third line
1666
1669
1667 $ cat newfile
1670 $ cat newfile
1668 This is the first line
1671 This is the first line
1669 This is the second line
1672 This is the second line
1670 This is the third line
1673 This is the third line
1671
1674
1672 Add new file from within a subdirectory
1675 Add new file from within a subdirectory
1673 $ hg update -C .
1676 $ hg update -C .
1674 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1677 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1675 $ mkdir folder
1678 $ mkdir folder
1676 $ cd folder
1679 $ cd folder
1677 $ echo "foo" > bar
1680 $ echo "foo" > bar
1678 $ hg add bar
1681 $ hg add bar
1679 $ hg commit -i -d '23 0' -mnewfilesubdir <<EOF
1682 $ hg commit -i -d '23 0' -mnewfilesubdir <<EOF
1680 > y
1683 > y
1681 > y
1684 > y
1682 > EOF
1685 > EOF
1683 diff --git a/folder/bar b/folder/bar
1686 diff --git a/folder/bar b/folder/bar
1684 new file mode 100644
1687 new file mode 100644
1685 examine changes to 'folder/bar'? [Ynesfdaq?] y
1688 examine changes to 'folder/bar'? [Ynesfdaq?] y
1686
1689
1687 @@ -0,0 +1,1 @@
1690 @@ -0,0 +1,1 @@
1688 +foo
1691 +foo
1689 record this change to 'folder/bar'? [Ynesfdaq?] y
1692 record this change to 'folder/bar'? [Ynesfdaq?] y
1690
1693
1691 The #if execbit block above changes the hashes here on some systems
1694 The #if execbit block above changes the hashes here on some systems
1692 $ hg tip -p
1695 $ hg tip -p
1693 changeset: 34:* (glob)
1696 changeset: 34:* (glob)
1694 tag: tip
1697 tag: tip
1695 user: test
1698 user: test
1696 date: Thu Jan 01 00:00:23 1970 +0000
1699 date: Thu Jan 01 00:00:23 1970 +0000
1697 summary: newfilesubdir
1700 summary: newfilesubdir
1698
1701
1699 diff -r * -r * folder/bar (glob)
1702 diff -r * -r * folder/bar (glob)
1700 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1703 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1701 +++ b/folder/bar Thu Jan 01 00:00:23 1970 +0000
1704 +++ b/folder/bar Thu Jan 01 00:00:23 1970 +0000
1702 @@ -0,0 +1,1 @@
1705 @@ -0,0 +1,1 @@
1703 +foo
1706 +foo
1704
1707
1705 $ cd ..
1708 $ cd ..
1706
1709
1707 $ hg status -A folder/bar
1710 $ hg status -A folder/bar
1708 C folder/bar
1711 C folder/bar
1709
1712
1710 Clear win32text configuration before size/timestamp sensitive test
1713 Clear win32text configuration before size/timestamp sensitive test
1711
1714
1712 $ cat >> .hg/hgrc <<EOF
1715 $ cat >> .hg/hgrc <<EOF
1713 > [extensions]
1716 > [extensions]
1714 > win32text = !
1717 > win32text = !
1715 > [decode]
1718 > [decode]
1716 > ** = !
1719 > ** = !
1717 > [encode]
1720 > [encode]
1718 > ** = !
1721 > ** = !
1719 > [patch]
1722 > [patch]
1720 > eol = strict
1723 > eol = strict
1721 > EOF
1724 > EOF
1722 $ hg update -q -C null
1725 $ hg update -q -C null
1723 $ hg update -q -C tip
1726 $ hg update -q -C tip
1724
1727
1725 Test that partially committed file is still treated as "modified",
1728 Test that partially committed file is still treated as "modified",
1726 even if none of mode, size and timestamp is changed on the filesystem
1729 even if none of mode, size and timestamp is changed on the filesystem
1727 (see also issue4583).
1730 (see also issue4583).
1728
1731
1729 $ cat > subdir/f1 <<EOF
1732 $ cat > subdir/f1 <<EOF
1730 > A
1733 > A
1731 > a
1734 > a
1732 > a
1735 > a
1733 > b
1736 > b
1734 > c
1737 > c
1735 > d
1738 > d
1736 > E
1739 > E
1737 > EOF
1740 > EOF
1738 $ hg diff --git subdir/f1
1741 $ hg diff --git subdir/f1
1739 diff --git a/subdir/f1 b/subdir/f1
1742 diff --git a/subdir/f1 b/subdir/f1
1740 --- a/subdir/f1
1743 --- a/subdir/f1
1741 +++ b/subdir/f1
1744 +++ b/subdir/f1
1742 @@ -1,7 +1,7 @@
1745 @@ -1,7 +1,7 @@
1743 -a
1746 -a
1744 +A
1747 +A
1745 a
1748 a
1746 a
1749 a
1747 b
1750 b
1748 c
1751 c
1749 d
1752 d
1750 -e
1753 -e
1751 +E
1754 +E
1752
1755
1753 $ touch -t 200001010000 subdir/f1
1756 $ touch -t 200001010000 subdir/f1
1754
1757
1755 $ cat >> .hg/hgrc <<EOF
1758 $ cat >> .hg/hgrc <<EOF
1756 > # emulate invoking patch.internalpatch() at 2000-01-01 00:00
1759 > # emulate invoking patch.internalpatch() at 2000-01-01 00:00
1757 > [fakepatchtime]
1760 > [fakepatchtime]
1758 > fakenow = 200001010000
1761 > fakenow = 200001010000
1759 >
1762 >
1760 > [extensions]
1763 > [extensions]
1761 > fakepatchtime = $TESTDIR/fakepatchtime.py
1764 > fakepatchtime = $TESTDIR/fakepatchtime.py
1762 > EOF
1765 > EOF
1763 $ hg commit -i -m 'commit subdir/f1 partially' <<EOF
1766 $ hg commit -i -m 'commit subdir/f1 partially' <<EOF
1764 > y
1767 > y
1765 > y
1768 > y
1766 > n
1769 > n
1767 > EOF
1770 > EOF
1768 diff --git a/subdir/f1 b/subdir/f1
1771 diff --git a/subdir/f1 b/subdir/f1
1769 2 hunks, 2 lines changed
1772 2 hunks, 2 lines changed
1770 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1773 examine changes to 'subdir/f1'? [Ynesfdaq?] y
1771
1774
1772 @@ -1,6 +1,6 @@
1775 @@ -1,6 +1,6 @@
1773 -a
1776 -a
1774 +A
1777 +A
1775 a
1778 a
1776 a
1779 a
1777 b
1780 b
1778 c
1781 c
1779 d
1782 d
1780 record change 1/2 to 'subdir/f1'? [Ynesfdaq?] y
1783 record change 1/2 to 'subdir/f1'? [Ynesfdaq?] y
1781
1784
1782 @@ -2,6 +2,6 @@
1785 @@ -2,6 +2,6 @@
1783 a
1786 a
1784 a
1787 a
1785 b
1788 b
1786 c
1789 c
1787 d
1790 d
1788 -e
1791 -e
1789 +E
1792 +E
1790 record change 2/2 to 'subdir/f1'? [Ynesfdaq?] n
1793 record change 2/2 to 'subdir/f1'? [Ynesfdaq?] n
1791
1794
1792 $ cat >> .hg/hgrc <<EOF
1795 $ cat >> .hg/hgrc <<EOF
1793 > [extensions]
1796 > [extensions]
1794 > fakepatchtime = !
1797 > fakepatchtime = !
1795 > EOF
1798 > EOF
1796
1799
1797 $ hg debugstate | grep ' subdir/f1$'
1800 $ hg debugstate | grep ' subdir/f1$'
1798 n 0 -1 unset subdir/f1
1801 n 0 -1 unset subdir/f1
1799 $ hg status -A subdir/f1
1802 $ hg status -A subdir/f1
1800 M subdir/f1
1803 M subdir/f1
General Comments 0
You need to be logged in to leave comments. Login now