##// END OF EJS Templates
bundle: warn for --base with --all
timeless -
r27423:c953e26f default
parent child Browse files
Show More
@@ -1,6999 +1,7001 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 node import hex, bin, nullhex, nullid, nullrev, short
8 from node import hex, bin, nullhex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys, socket
12 import sys, socket
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb
16 import sshserver, hgweb
17 import extensions
17 import extensions
18 import merge as mergemod
18 import merge as mergemod
19 import minirst, revset, fileset
19 import minirst, revset, fileset
20 import dagparser, context, simplemerge, graphmod, copies
20 import dagparser, context, simplemerge, graphmod, copies
21 import random, operator
21 import random, operator
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
24 import ui as uimod
24 import ui as uimod
25 import streamclone
25 import streamclone
26 import commandserver
26 import commandserver
27
27
28 table = {}
28 table = {}
29
29
30 command = cmdutil.command(table)
30 command = cmdutil.command(table)
31
31
32 # Space delimited list of commands that don't require local repositories.
32 # Space delimited list of commands that don't require local repositories.
33 # This should be populated by passing norepo=True into the @command decorator.
33 # This should be populated by passing norepo=True into the @command decorator.
34 norepo = ''
34 norepo = ''
35 # Space delimited list of commands that optionally require local repositories.
35 # Space delimited list of commands that optionally require local repositories.
36 # This should be populated by passing optionalrepo=True into the @command
36 # This should be populated by passing optionalrepo=True into the @command
37 # decorator.
37 # decorator.
38 optionalrepo = ''
38 optionalrepo = ''
39 # Space delimited list of commands that will examine arguments looking for
39 # Space delimited list of commands that will examine arguments looking for
40 # a repository. This should be populated by passing inferrepo=True into the
40 # a repository. This should be populated by passing inferrepo=True into the
41 # @command decorator.
41 # @command decorator.
42 inferrepo = ''
42 inferrepo = ''
43
43
44 # label constants
44 # label constants
45 # until 3.5, bookmarks.current was the advertised name, not
45 # until 3.5, bookmarks.current was the advertised name, not
46 # bookmarks.active, so we must use both to avoid breaking old
46 # bookmarks.active, so we must use both to avoid breaking old
47 # custom styles
47 # custom styles
48 activebookmarklabel = 'bookmarks.active bookmarks.current'
48 activebookmarklabel = 'bookmarks.active bookmarks.current'
49
49
50 # common command options
50 # common command options
51
51
52 globalopts = [
52 globalopts = [
53 ('R', 'repository', '',
53 ('R', 'repository', '',
54 _('repository root directory or name of overlay bundle file'),
54 _('repository root directory or name of overlay bundle file'),
55 _('REPO')),
55 _('REPO')),
56 ('', 'cwd', '',
56 ('', 'cwd', '',
57 _('change working directory'), _('DIR')),
57 _('change working directory'), _('DIR')),
58 ('y', 'noninteractive', None,
58 ('y', 'noninteractive', None,
59 _('do not prompt, automatically pick the first choice for all prompts')),
59 _('do not prompt, automatically pick the first choice for all prompts')),
60 ('q', 'quiet', None, _('suppress output')),
60 ('q', 'quiet', None, _('suppress output')),
61 ('v', 'verbose', None, _('enable additional output')),
61 ('v', 'verbose', None, _('enable additional output')),
62 ('', 'config', [],
62 ('', 'config', [],
63 _('set/override config option (use \'section.name=value\')'),
63 _('set/override config option (use \'section.name=value\')'),
64 _('CONFIG')),
64 _('CONFIG')),
65 ('', 'debug', None, _('enable debugging output')),
65 ('', 'debug', None, _('enable debugging output')),
66 ('', 'debugger', None, _('start debugger')),
66 ('', 'debugger', None, _('start debugger')),
67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
68 _('ENCODE')),
68 _('ENCODE')),
69 ('', 'encodingmode', encoding.encodingmode,
69 ('', 'encodingmode', encoding.encodingmode,
70 _('set the charset encoding mode'), _('MODE')),
70 _('set the charset encoding mode'), _('MODE')),
71 ('', 'traceback', None, _('always print a traceback on exception')),
71 ('', 'traceback', None, _('always print a traceback on exception')),
72 ('', 'time', None, _('time how long the command takes')),
72 ('', 'time', None, _('time how long the command takes')),
73 ('', 'profile', None, _('print command execution profile')),
73 ('', 'profile', None, _('print command execution profile')),
74 ('', 'version', None, _('output version information and exit')),
74 ('', 'version', None, _('output version information and exit')),
75 ('h', 'help', None, _('display help and exit')),
75 ('h', 'help', None, _('display help and exit')),
76 ('', 'hidden', False, _('consider hidden changesets')),
76 ('', 'hidden', False, _('consider hidden changesets')),
77 ]
77 ]
78
78
79 dryrunopts = [('n', 'dry-run', None,
79 dryrunopts = [('n', 'dry-run', None,
80 _('do not perform actions, just print output'))]
80 _('do not perform actions, just print output'))]
81
81
82 remoteopts = [
82 remoteopts = [
83 ('e', 'ssh', '',
83 ('e', 'ssh', '',
84 _('specify ssh command to use'), _('CMD')),
84 _('specify ssh command to use'), _('CMD')),
85 ('', 'remotecmd', '',
85 ('', 'remotecmd', '',
86 _('specify hg command to run on the remote side'), _('CMD')),
86 _('specify hg command to run on the remote side'), _('CMD')),
87 ('', 'insecure', None,
87 ('', 'insecure', None,
88 _('do not verify server certificate (ignoring web.cacerts config)')),
88 _('do not verify server certificate (ignoring web.cacerts config)')),
89 ]
89 ]
90
90
91 walkopts = [
91 walkopts = [
92 ('I', 'include', [],
92 ('I', 'include', [],
93 _('include names matching the given patterns'), _('PATTERN')),
93 _('include names matching the given patterns'), _('PATTERN')),
94 ('X', 'exclude', [],
94 ('X', 'exclude', [],
95 _('exclude names matching the given patterns'), _('PATTERN')),
95 _('exclude names matching the given patterns'), _('PATTERN')),
96 ]
96 ]
97
97
98 commitopts = [
98 commitopts = [
99 ('m', 'message', '',
99 ('m', 'message', '',
100 _('use text as commit message'), _('TEXT')),
100 _('use text as commit message'), _('TEXT')),
101 ('l', 'logfile', '',
101 ('l', 'logfile', '',
102 _('read commit message from file'), _('FILE')),
102 _('read commit message from file'), _('FILE')),
103 ]
103 ]
104
104
105 commitopts2 = [
105 commitopts2 = [
106 ('d', 'date', '',
106 ('d', 'date', '',
107 _('record the specified date as commit date'), _('DATE')),
107 _('record the specified date as commit date'), _('DATE')),
108 ('u', 'user', '',
108 ('u', 'user', '',
109 _('record the specified user as committer'), _('USER')),
109 _('record the specified user as committer'), _('USER')),
110 ]
110 ]
111
111
112 # hidden for now
112 # hidden for now
113 formatteropts = [
113 formatteropts = [
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 templateopts = [
118 templateopts = [
119 ('', 'style', '',
119 ('', 'style', '',
120 _('display using template map file (DEPRECATED)'), _('STYLE')),
120 _('display using template map file (DEPRECATED)'), _('STYLE')),
121 ('T', 'template', '',
121 ('T', 'template', '',
122 _('display with template'), _('TEMPLATE')),
122 _('display with template'), _('TEMPLATE')),
123 ]
123 ]
124
124
125 logopts = [
125 logopts = [
126 ('p', 'patch', None, _('show patch')),
126 ('p', 'patch', None, _('show patch')),
127 ('g', 'git', None, _('use git extended diff format')),
127 ('g', 'git', None, _('use git extended diff format')),
128 ('l', 'limit', '',
128 ('l', 'limit', '',
129 _('limit number of changes displayed'), _('NUM')),
129 _('limit number of changes displayed'), _('NUM')),
130 ('M', 'no-merges', None, _('do not show merges')),
130 ('M', 'no-merges', None, _('do not show merges')),
131 ('', 'stat', None, _('output diffstat-style summary of changes')),
131 ('', 'stat', None, _('output diffstat-style summary of changes')),
132 ('G', 'graph', None, _("show the revision DAG")),
132 ('G', 'graph', None, _("show the revision DAG")),
133 ] + templateopts
133 ] + templateopts
134
134
135 diffopts = [
135 diffopts = [
136 ('a', 'text', None, _('treat all files as text')),
136 ('a', 'text', None, _('treat all files as text')),
137 ('g', 'git', None, _('use git extended diff format')),
137 ('g', 'git', None, _('use git extended diff format')),
138 ('', 'nodates', None, _('omit dates from diff headers'))
138 ('', 'nodates', None, _('omit dates from diff headers'))
139 ]
139 ]
140
140
141 diffwsopts = [
141 diffwsopts = [
142 ('w', 'ignore-all-space', None,
142 ('w', 'ignore-all-space', None,
143 _('ignore white space when comparing lines')),
143 _('ignore white space when comparing lines')),
144 ('b', 'ignore-space-change', None,
144 ('b', 'ignore-space-change', None,
145 _('ignore changes in the amount of white space')),
145 _('ignore changes in the amount of white space')),
146 ('B', 'ignore-blank-lines', None,
146 ('B', 'ignore-blank-lines', None,
147 _('ignore changes whose lines are all blank')),
147 _('ignore changes whose lines are all blank')),
148 ]
148 ]
149
149
150 diffopts2 = [
150 diffopts2 = [
151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
152 ('p', 'show-function', None, _('show which function each change is in')),
152 ('p', 'show-function', None, _('show which function each change is in')),
153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
154 ] + diffwsopts + [
154 ] + diffwsopts + [
155 ('U', 'unified', '',
155 ('U', 'unified', '',
156 _('number of lines of context to show'), _('NUM')),
156 _('number of lines of context to show'), _('NUM')),
157 ('', 'stat', None, _('output diffstat-style summary of changes')),
157 ('', 'stat', None, _('output diffstat-style summary of changes')),
158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
159 ]
159 ]
160
160
161 mergetoolopts = [
161 mergetoolopts = [
162 ('t', 'tool', '', _('specify merge tool')),
162 ('t', 'tool', '', _('specify merge tool')),
163 ]
163 ]
164
164
165 similarityopts = [
165 similarityopts = [
166 ('s', 'similarity', '',
166 ('s', 'similarity', '',
167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
168 ]
168 ]
169
169
170 subrepoopts = [
170 subrepoopts = [
171 ('S', 'subrepos', None,
171 ('S', 'subrepos', None,
172 _('recurse into subrepositories'))
172 _('recurse into subrepositories'))
173 ]
173 ]
174
174
175 debugrevlogopts = [
175 debugrevlogopts = [
176 ('c', 'changelog', False, _('open changelog')),
176 ('c', 'changelog', False, _('open changelog')),
177 ('m', 'manifest', False, _('open manifest')),
177 ('m', 'manifest', False, _('open manifest')),
178 ('', 'dir', False, _('open directory manifest')),
178 ('', 'dir', False, _('open directory manifest')),
179 ]
179 ]
180
180
181 # Commands start here, listed alphabetically
181 # Commands start here, listed alphabetically
182
182
183 @command('^add',
183 @command('^add',
184 walkopts + subrepoopts + dryrunopts,
184 walkopts + subrepoopts + dryrunopts,
185 _('[OPTION]... [FILE]...'),
185 _('[OPTION]... [FILE]...'),
186 inferrepo=True)
186 inferrepo=True)
187 def add(ui, repo, *pats, **opts):
187 def add(ui, repo, *pats, **opts):
188 """add the specified files on the next commit
188 """add the specified files on the next commit
189
189
190 Schedule files to be version controlled and added to the
190 Schedule files to be version controlled and added to the
191 repository.
191 repository.
192
192
193 The files will be added to the repository at the next commit. To
193 The files will be added to the repository at the next commit. To
194 undo an add before that, see :hg:`forget`.
194 undo an add before that, see :hg:`forget`.
195
195
196 If no names are given, add all files to the repository.
196 If no names are given, add all files to the repository.
197
197
198 .. container:: verbose
198 .. container:: verbose
199
199
200 Examples:
200 Examples:
201
201
202 - New (unknown) files are added
202 - New (unknown) files are added
203 automatically by :hg:`add`::
203 automatically by :hg:`add`::
204
204
205 $ ls
205 $ ls
206 foo.c
206 foo.c
207 $ hg status
207 $ hg status
208 ? foo.c
208 ? foo.c
209 $ hg add
209 $ hg add
210 adding foo.c
210 adding foo.c
211 $ hg status
211 $ hg status
212 A foo.c
212 A foo.c
213
213
214 - Specific files to be added can be specified::
214 - Specific files to be added can be specified::
215
215
216 $ ls
216 $ ls
217 bar.c foo.c
217 bar.c foo.c
218 $ hg status
218 $ hg status
219 ? bar.c
219 ? bar.c
220 ? foo.c
220 ? foo.c
221 $ hg add bar.c
221 $ hg add bar.c
222 $ hg status
222 $ hg status
223 A bar.c
223 A bar.c
224 ? foo.c
224 ? foo.c
225
225
226 Returns 0 if all files are successfully added.
226 Returns 0 if all files are successfully added.
227 """
227 """
228
228
229 m = scmutil.match(repo[None], pats, opts)
229 m = scmutil.match(repo[None], pats, opts)
230 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
230 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
231 return rejected and 1 or 0
231 return rejected and 1 or 0
232
232
233 @command('addremove',
233 @command('addremove',
234 similarityopts + subrepoopts + walkopts + dryrunopts,
234 similarityopts + subrepoopts + walkopts + dryrunopts,
235 _('[OPTION]... [FILE]...'),
235 _('[OPTION]... [FILE]...'),
236 inferrepo=True)
236 inferrepo=True)
237 def addremove(ui, repo, *pats, **opts):
237 def addremove(ui, repo, *pats, **opts):
238 """add all new files, delete all missing files
238 """add all new files, delete all missing files
239
239
240 Add all new files and remove all missing files from the
240 Add all new files and remove all missing files from the
241 repository.
241 repository.
242
242
243 New files are ignored if they match any of the patterns in
243 New files are ignored if they match any of the patterns in
244 ``.hgignore``. As with add, these changes take effect at the next
244 ``.hgignore``. As with add, these changes take effect at the next
245 commit.
245 commit.
246
246
247 Use the -s/--similarity option to detect renamed files. This
247 Use the -s/--similarity option to detect renamed files. This
248 option takes a percentage between 0 (disabled) and 100 (files must
248 option takes a percentage between 0 (disabled) and 100 (files must
249 be identical) as its parameter. With a parameter greater than 0,
249 be identical) as its parameter. With a parameter greater than 0,
250 this compares every removed file with every added file and records
250 this compares every removed file with every added file and records
251 those similar enough as renames. Detecting renamed files this way
251 those similar enough as renames. Detecting renamed files this way
252 can be expensive. After using this option, :hg:`status -C` can be
252 can be expensive. After using this option, :hg:`status -C` can be
253 used to check which files were identified as moved or renamed. If
253 used to check which files were identified as moved or renamed. If
254 not specified, -s/--similarity defaults to 100 and only renames of
254 not specified, -s/--similarity defaults to 100 and only renames of
255 identical files are detected.
255 identical files are detected.
256
256
257 .. container:: verbose
257 .. container:: verbose
258
258
259 Examples:
259 Examples:
260
260
261 - A number of files (bar.c and foo.c) are new,
261 - A number of files (bar.c and foo.c) are new,
262 while foobar.c has been removed (without using :hg:`remove`)
262 while foobar.c has been removed (without using :hg:`remove`)
263 from the repository::
263 from the repository::
264
264
265 $ ls
265 $ ls
266 bar.c foo.c
266 bar.c foo.c
267 $ hg status
267 $ hg status
268 ! foobar.c
268 ! foobar.c
269 ? bar.c
269 ? bar.c
270 ? foo.c
270 ? foo.c
271 $ hg addremove
271 $ hg addremove
272 adding bar.c
272 adding bar.c
273 adding foo.c
273 adding foo.c
274 removing foobar.c
274 removing foobar.c
275 $ hg status
275 $ hg status
276 A bar.c
276 A bar.c
277 A foo.c
277 A foo.c
278 R foobar.c
278 R foobar.c
279
279
280 - A file foobar.c was moved to foo.c without using :hg:`rename`.
280 - A file foobar.c was moved to foo.c without using :hg:`rename`.
281 Afterwards, it was edited slightly::
281 Afterwards, it was edited slightly::
282
282
283 $ ls
283 $ ls
284 foo.c
284 foo.c
285 $ hg status
285 $ hg status
286 ! foobar.c
286 ! foobar.c
287 ? foo.c
287 ? foo.c
288 $ hg addremove --similarity 90
288 $ hg addremove --similarity 90
289 removing foobar.c
289 removing foobar.c
290 adding foo.c
290 adding foo.c
291 recording removal of foobar.c as rename to foo.c (94% similar)
291 recording removal of foobar.c as rename to foo.c (94% similar)
292 $ hg status -C
292 $ hg status -C
293 A foo.c
293 A foo.c
294 foobar.c
294 foobar.c
295 R foobar.c
295 R foobar.c
296
296
297 Returns 0 if all files are successfully added.
297 Returns 0 if all files are successfully added.
298 """
298 """
299 try:
299 try:
300 sim = float(opts.get('similarity') or 100)
300 sim = float(opts.get('similarity') or 100)
301 except ValueError:
301 except ValueError:
302 raise error.Abort(_('similarity must be a number'))
302 raise error.Abort(_('similarity must be a number'))
303 if sim < 0 or sim > 100:
303 if sim < 0 or sim > 100:
304 raise error.Abort(_('similarity must be between 0 and 100'))
304 raise error.Abort(_('similarity must be between 0 and 100'))
305 matcher = scmutil.match(repo[None], pats, opts)
305 matcher = scmutil.match(repo[None], pats, opts)
306 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
306 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
307
307
308 @command('^annotate|blame',
308 @command('^annotate|blame',
309 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
309 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
310 ('', 'follow', None,
310 ('', 'follow', None,
311 _('follow copies/renames and list the filename (DEPRECATED)')),
311 _('follow copies/renames and list the filename (DEPRECATED)')),
312 ('', 'no-follow', None, _("don't follow copies and renames")),
312 ('', 'no-follow', None, _("don't follow copies and renames")),
313 ('a', 'text', None, _('treat all files as text')),
313 ('a', 'text', None, _('treat all files as text')),
314 ('u', 'user', None, _('list the author (long with -v)')),
314 ('u', 'user', None, _('list the author (long with -v)')),
315 ('f', 'file', None, _('list the filename')),
315 ('f', 'file', None, _('list the filename')),
316 ('d', 'date', None, _('list the date (short with -q)')),
316 ('d', 'date', None, _('list the date (short with -q)')),
317 ('n', 'number', None, _('list the revision number (default)')),
317 ('n', 'number', None, _('list the revision number (default)')),
318 ('c', 'changeset', None, _('list the changeset')),
318 ('c', 'changeset', None, _('list the changeset')),
319 ('l', 'line-number', None, _('show line number at the first appearance'))
319 ('l', 'line-number', None, _('show line number at the first appearance'))
320 ] + diffwsopts + walkopts + formatteropts,
320 ] + diffwsopts + walkopts + formatteropts,
321 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
321 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
322 inferrepo=True)
322 inferrepo=True)
323 def annotate(ui, repo, *pats, **opts):
323 def annotate(ui, repo, *pats, **opts):
324 """show changeset information by line for each file
324 """show changeset information by line for each file
325
325
326 List changes in files, showing the revision id responsible for
326 List changes in files, showing the revision id responsible for
327 each line
327 each line
328
328
329 This command is useful for discovering when a change was made and
329 This command is useful for discovering when a change was made and
330 by whom.
330 by whom.
331
331
332 Without the -a/--text option, annotate will avoid processing files
332 Without the -a/--text option, annotate will avoid processing files
333 it detects as binary. With -a, annotate will annotate the file
333 it detects as binary. With -a, annotate will annotate the file
334 anyway, although the results will probably be neither useful
334 anyway, although the results will probably be neither useful
335 nor desirable.
335 nor desirable.
336
336
337 Returns 0 on success.
337 Returns 0 on success.
338 """
338 """
339 if not pats:
339 if not pats:
340 raise error.Abort(_('at least one filename or pattern is required'))
340 raise error.Abort(_('at least one filename or pattern is required'))
341
341
342 if opts.get('follow'):
342 if opts.get('follow'):
343 # --follow is deprecated and now just an alias for -f/--file
343 # --follow is deprecated and now just an alias for -f/--file
344 # to mimic the behavior of Mercurial before version 1.5
344 # to mimic the behavior of Mercurial before version 1.5
345 opts['file'] = True
345 opts['file'] = True
346
346
347 ctx = scmutil.revsingle(repo, opts.get('rev'))
347 ctx = scmutil.revsingle(repo, opts.get('rev'))
348
348
349 fm = ui.formatter('annotate', opts)
349 fm = ui.formatter('annotate', opts)
350 if ui.quiet:
350 if ui.quiet:
351 datefunc = util.shortdate
351 datefunc = util.shortdate
352 else:
352 else:
353 datefunc = util.datestr
353 datefunc = util.datestr
354 if ctx.rev() is None:
354 if ctx.rev() is None:
355 def hexfn(node):
355 def hexfn(node):
356 if node is None:
356 if node is None:
357 return None
357 return None
358 else:
358 else:
359 return fm.hexfunc(node)
359 return fm.hexfunc(node)
360 if opts.get('changeset'):
360 if opts.get('changeset'):
361 # omit "+" suffix which is appended to node hex
361 # omit "+" suffix which is appended to node hex
362 def formatrev(rev):
362 def formatrev(rev):
363 if rev is None:
363 if rev is None:
364 return '%d' % ctx.p1().rev()
364 return '%d' % ctx.p1().rev()
365 else:
365 else:
366 return '%d' % rev
366 return '%d' % rev
367 else:
367 else:
368 def formatrev(rev):
368 def formatrev(rev):
369 if rev is None:
369 if rev is None:
370 return '%d+' % ctx.p1().rev()
370 return '%d+' % ctx.p1().rev()
371 else:
371 else:
372 return '%d ' % rev
372 return '%d ' % rev
373 def formathex(hex):
373 def formathex(hex):
374 if hex is None:
374 if hex is None:
375 return '%s+' % fm.hexfunc(ctx.p1().node())
375 return '%s+' % fm.hexfunc(ctx.p1().node())
376 else:
376 else:
377 return '%s ' % hex
377 return '%s ' % hex
378 else:
378 else:
379 hexfn = fm.hexfunc
379 hexfn = fm.hexfunc
380 formatrev = formathex = str
380 formatrev = formathex = str
381
381
382 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
382 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
383 ('number', ' ', lambda x: x[0].rev(), formatrev),
383 ('number', ' ', lambda x: x[0].rev(), formatrev),
384 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
384 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
385 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
385 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
386 ('file', ' ', lambda x: x[0].path(), str),
386 ('file', ' ', lambda x: x[0].path(), str),
387 ('line_number', ':', lambda x: x[1], str),
387 ('line_number', ':', lambda x: x[1], str),
388 ]
388 ]
389 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
389 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
390
390
391 if (not opts.get('user') and not opts.get('changeset')
391 if (not opts.get('user') and not opts.get('changeset')
392 and not opts.get('date') and not opts.get('file')):
392 and not opts.get('date') and not opts.get('file')):
393 opts['number'] = True
393 opts['number'] = True
394
394
395 linenumber = opts.get('line_number') is not None
395 linenumber = opts.get('line_number') is not None
396 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
396 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
397 raise error.Abort(_('at least one of -n/-c is required for -l'))
397 raise error.Abort(_('at least one of -n/-c is required for -l'))
398
398
399 if fm:
399 if fm:
400 def makefunc(get, fmt):
400 def makefunc(get, fmt):
401 return get
401 return get
402 else:
402 else:
403 def makefunc(get, fmt):
403 def makefunc(get, fmt):
404 return lambda x: fmt(get(x))
404 return lambda x: fmt(get(x))
405 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
405 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
406 if opts.get(op)]
406 if opts.get(op)]
407 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
407 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
408 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
408 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
409 if opts.get(op))
409 if opts.get(op))
410
410
411 def bad(x, y):
411 def bad(x, y):
412 raise error.Abort("%s: %s" % (x, y))
412 raise error.Abort("%s: %s" % (x, y))
413
413
414 m = scmutil.match(ctx, pats, opts, badfn=bad)
414 m = scmutil.match(ctx, pats, opts, badfn=bad)
415
415
416 follow = not opts.get('no_follow')
416 follow = not opts.get('no_follow')
417 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
417 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
418 whitespace=True)
418 whitespace=True)
419 for abs in ctx.walk(m):
419 for abs in ctx.walk(m):
420 fctx = ctx[abs]
420 fctx = ctx[abs]
421 if not opts.get('text') and util.binary(fctx.data()):
421 if not opts.get('text') and util.binary(fctx.data()):
422 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
422 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
423 continue
423 continue
424
424
425 lines = fctx.annotate(follow=follow, linenumber=linenumber,
425 lines = fctx.annotate(follow=follow, linenumber=linenumber,
426 diffopts=diffopts)
426 diffopts=diffopts)
427 formats = []
427 formats = []
428 pieces = []
428 pieces = []
429
429
430 for f, sep in funcmap:
430 for f, sep in funcmap:
431 l = [f(n) for n, dummy in lines]
431 l = [f(n) for n, dummy in lines]
432 if l:
432 if l:
433 if fm:
433 if fm:
434 formats.append(['%s' for x in l])
434 formats.append(['%s' for x in l])
435 else:
435 else:
436 sizes = [encoding.colwidth(x) for x in l]
436 sizes = [encoding.colwidth(x) for x in l]
437 ml = max(sizes)
437 ml = max(sizes)
438 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
438 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
439 pieces.append(l)
439 pieces.append(l)
440
440
441 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
441 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
442 fm.startitem()
442 fm.startitem()
443 fm.write(fields, "".join(f), *p)
443 fm.write(fields, "".join(f), *p)
444 fm.write('line', ": %s", l[1])
444 fm.write('line', ": %s", l[1])
445
445
446 if lines and not lines[-1][1].endswith('\n'):
446 if lines and not lines[-1][1].endswith('\n'):
447 fm.plain('\n')
447 fm.plain('\n')
448
448
449 fm.end()
449 fm.end()
450
450
451 @command('archive',
451 @command('archive',
452 [('', 'no-decode', None, _('do not pass files through decoders')),
452 [('', 'no-decode', None, _('do not pass files through decoders')),
453 ('p', 'prefix', '', _('directory prefix for files in archive'),
453 ('p', 'prefix', '', _('directory prefix for files in archive'),
454 _('PREFIX')),
454 _('PREFIX')),
455 ('r', 'rev', '', _('revision to distribute'), _('REV')),
455 ('r', 'rev', '', _('revision to distribute'), _('REV')),
456 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
456 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
457 ] + subrepoopts + walkopts,
457 ] + subrepoopts + walkopts,
458 _('[OPTION]... DEST'))
458 _('[OPTION]... DEST'))
459 def archive(ui, repo, dest, **opts):
459 def archive(ui, repo, dest, **opts):
460 '''create an unversioned archive of a repository revision
460 '''create an unversioned archive of a repository revision
461
461
462 By default, the revision used is the parent of the working
462 By default, the revision used is the parent of the working
463 directory; use -r/--rev to specify a different revision.
463 directory; use -r/--rev to specify a different revision.
464
464
465 The archive type is automatically detected based on file
465 The archive type is automatically detected based on file
466 extension (or override using -t/--type).
466 extension (or override using -t/--type).
467
467
468 .. container:: verbose
468 .. container:: verbose
469
469
470 Examples:
470 Examples:
471
471
472 - create a zip file containing the 1.0 release::
472 - create a zip file containing the 1.0 release::
473
473
474 hg archive -r 1.0 project-1.0.zip
474 hg archive -r 1.0 project-1.0.zip
475
475
476 - create a tarball excluding .hg files::
476 - create a tarball excluding .hg files::
477
477
478 hg archive project.tar.gz -X ".hg*"
478 hg archive project.tar.gz -X ".hg*"
479
479
480 Valid types are:
480 Valid types are:
481
481
482 :``files``: a directory full of files (default)
482 :``files``: a directory full of files (default)
483 :``tar``: tar archive, uncompressed
483 :``tar``: tar archive, uncompressed
484 :``tbz2``: tar archive, compressed using bzip2
484 :``tbz2``: tar archive, compressed using bzip2
485 :``tgz``: tar archive, compressed using gzip
485 :``tgz``: tar archive, compressed using gzip
486 :``uzip``: zip archive, uncompressed
486 :``uzip``: zip archive, uncompressed
487 :``zip``: zip archive, compressed using deflate
487 :``zip``: zip archive, compressed using deflate
488
488
489 The exact name of the destination archive or directory is given
489 The exact name of the destination archive or directory is given
490 using a format string; see :hg:`help export` for details.
490 using a format string; see :hg:`help export` for details.
491
491
492 Each member added to an archive file has a directory prefix
492 Each member added to an archive file has a directory prefix
493 prepended. Use -p/--prefix to specify a format string for the
493 prepended. Use -p/--prefix to specify a format string for the
494 prefix. The default is the basename of the archive, with suffixes
494 prefix. The default is the basename of the archive, with suffixes
495 removed.
495 removed.
496
496
497 Returns 0 on success.
497 Returns 0 on success.
498 '''
498 '''
499
499
500 ctx = scmutil.revsingle(repo, opts.get('rev'))
500 ctx = scmutil.revsingle(repo, opts.get('rev'))
501 if not ctx:
501 if not ctx:
502 raise error.Abort(_('no working directory: please specify a revision'))
502 raise error.Abort(_('no working directory: please specify a revision'))
503 node = ctx.node()
503 node = ctx.node()
504 dest = cmdutil.makefilename(repo, dest, node)
504 dest = cmdutil.makefilename(repo, dest, node)
505 if os.path.realpath(dest) == repo.root:
505 if os.path.realpath(dest) == repo.root:
506 raise error.Abort(_('repository root cannot be destination'))
506 raise error.Abort(_('repository root cannot be destination'))
507
507
508 kind = opts.get('type') or archival.guesskind(dest) or 'files'
508 kind = opts.get('type') or archival.guesskind(dest) or 'files'
509 prefix = opts.get('prefix')
509 prefix = opts.get('prefix')
510
510
511 if dest == '-':
511 if dest == '-':
512 if kind == 'files':
512 if kind == 'files':
513 raise error.Abort(_('cannot archive plain files to stdout'))
513 raise error.Abort(_('cannot archive plain files to stdout'))
514 dest = cmdutil.makefileobj(repo, dest)
514 dest = cmdutil.makefileobj(repo, dest)
515 if not prefix:
515 if not prefix:
516 prefix = os.path.basename(repo.root) + '-%h'
516 prefix = os.path.basename(repo.root) + '-%h'
517
517
518 prefix = cmdutil.makefilename(repo, prefix, node)
518 prefix = cmdutil.makefilename(repo, prefix, node)
519 matchfn = scmutil.match(ctx, [], opts)
519 matchfn = scmutil.match(ctx, [], opts)
520 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
520 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
521 matchfn, prefix, subrepos=opts.get('subrepos'))
521 matchfn, prefix, subrepos=opts.get('subrepos'))
522
522
523 @command('backout',
523 @command('backout',
524 [('', 'merge', None, _('merge with old dirstate parent after backout')),
524 [('', 'merge', None, _('merge with old dirstate parent after backout')),
525 ('', 'commit', None, _('commit if no conflicts were encountered')),
525 ('', 'commit', None, _('commit if no conflicts were encountered')),
526 ('', 'parent', '',
526 ('', 'parent', '',
527 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
527 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
528 ('r', 'rev', '', _('revision to backout'), _('REV')),
528 ('r', 'rev', '', _('revision to backout'), _('REV')),
529 ('e', 'edit', False, _('invoke editor on commit messages')),
529 ('e', 'edit', False, _('invoke editor on commit messages')),
530 ] + mergetoolopts + walkopts + commitopts + commitopts2,
530 ] + mergetoolopts + walkopts + commitopts + commitopts2,
531 _('[OPTION]... [-r] REV'))
531 _('[OPTION]... [-r] REV'))
532 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
532 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
533 '''reverse effect of earlier changeset
533 '''reverse effect of earlier changeset
534
534
535 Prepare a new changeset with the effect of REV undone in the
535 Prepare a new changeset with the effect of REV undone in the
536 current working directory.
536 current working directory.
537
537
538 If REV is the parent of the working directory, then this new changeset
538 If REV is the parent of the working directory, then this new changeset
539 is committed automatically. Otherwise, hg needs to merge the
539 is committed automatically. Otherwise, hg needs to merge the
540 changes and the merged result is left uncommitted.
540 changes and the merged result is left uncommitted.
541
541
542 .. note::
542 .. note::
543
543
544 backout cannot be used to fix either an unwanted or
544 backout cannot be used to fix either an unwanted or
545 incorrect merge.
545 incorrect merge.
546
546
547 .. container:: verbose
547 .. container:: verbose
548
548
549 Examples:
549 Examples:
550
550
551 - Reverse the effect of the parent of the working directory.
551 - Reverse the effect of the parent of the working directory.
552 This backout will be committed immediately::
552 This backout will be committed immediately::
553
553
554 hg backout -r .
554 hg backout -r .
555
555
556 - Reverse the effect of previous bad revision 23::
556 - Reverse the effect of previous bad revision 23::
557
557
558 hg backout -r 23
558 hg backout -r 23
559 hg commit -m "Backout revision 23"
559 hg commit -m "Backout revision 23"
560
560
561 - Reverse the effect of previous bad revision 23 and
561 - Reverse the effect of previous bad revision 23 and
562 commit the backout immediately::
562 commit the backout immediately::
563
563
564 hg backout -r 23 --commit
564 hg backout -r 23 --commit
565
565
566 By default, the pending changeset will have one parent,
566 By default, the pending changeset will have one parent,
567 maintaining a linear history. With --merge, the pending
567 maintaining a linear history. With --merge, the pending
568 changeset will instead have two parents: the old parent of the
568 changeset will instead have two parents: the old parent of the
569 working directory and a new child of REV that simply undoes REV.
569 working directory and a new child of REV that simply undoes REV.
570
570
571 Before version 1.7, the behavior without --merge was equivalent
571 Before version 1.7, the behavior without --merge was equivalent
572 to specifying --merge followed by :hg:`update --clean .` to
572 to specifying --merge followed by :hg:`update --clean .` to
573 cancel the merge and leave the child of REV as a head to be
573 cancel the merge and leave the child of REV as a head to be
574 merged separately.
574 merged separately.
575
575
576 See :hg:`help dates` for a list of formats valid for -d/--date.
576 See :hg:`help dates` for a list of formats valid for -d/--date.
577
577
578 See :hg:`help revert` for a way to restore files to the state
578 See :hg:`help revert` for a way to restore files to the state
579 of another revision.
579 of another revision.
580
580
581 Returns 0 on success, 1 if nothing to backout or there are unresolved
581 Returns 0 on success, 1 if nothing to backout or there are unresolved
582 files.
582 files.
583 '''
583 '''
584 wlock = lock = None
584 wlock = lock = None
585 try:
585 try:
586 wlock = repo.wlock()
586 wlock = repo.wlock()
587 lock = repo.lock()
587 lock = repo.lock()
588 return _dobackout(ui, repo, node, rev, commit, **opts)
588 return _dobackout(ui, repo, node, rev, commit, **opts)
589 finally:
589 finally:
590 release(lock, wlock)
590 release(lock, wlock)
591
591
592 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
592 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
593 if rev and node:
593 if rev and node:
594 raise error.Abort(_("please specify just one revision"))
594 raise error.Abort(_("please specify just one revision"))
595
595
596 if not rev:
596 if not rev:
597 rev = node
597 rev = node
598
598
599 if not rev:
599 if not rev:
600 raise error.Abort(_("please specify a revision to backout"))
600 raise error.Abort(_("please specify a revision to backout"))
601
601
602 date = opts.get('date')
602 date = opts.get('date')
603 if date:
603 if date:
604 opts['date'] = util.parsedate(date)
604 opts['date'] = util.parsedate(date)
605
605
606 cmdutil.checkunfinished(repo)
606 cmdutil.checkunfinished(repo)
607 cmdutil.bailifchanged(repo)
607 cmdutil.bailifchanged(repo)
608 node = scmutil.revsingle(repo, rev).node()
608 node = scmutil.revsingle(repo, rev).node()
609
609
610 op1, op2 = repo.dirstate.parents()
610 op1, op2 = repo.dirstate.parents()
611 if not repo.changelog.isancestor(node, op1):
611 if not repo.changelog.isancestor(node, op1):
612 raise error.Abort(_('cannot backout change that is not an ancestor'))
612 raise error.Abort(_('cannot backout change that is not an ancestor'))
613
613
614 p1, p2 = repo.changelog.parents(node)
614 p1, p2 = repo.changelog.parents(node)
615 if p1 == nullid:
615 if p1 == nullid:
616 raise error.Abort(_('cannot backout a change with no parents'))
616 raise error.Abort(_('cannot backout a change with no parents'))
617 if p2 != nullid:
617 if p2 != nullid:
618 if not opts.get('parent'):
618 if not opts.get('parent'):
619 raise error.Abort(_('cannot backout a merge changeset'))
619 raise error.Abort(_('cannot backout a merge changeset'))
620 p = repo.lookup(opts['parent'])
620 p = repo.lookup(opts['parent'])
621 if p not in (p1, p2):
621 if p not in (p1, p2):
622 raise error.Abort(_('%s is not a parent of %s') %
622 raise error.Abort(_('%s is not a parent of %s') %
623 (short(p), short(node)))
623 (short(p), short(node)))
624 parent = p
624 parent = p
625 else:
625 else:
626 if opts.get('parent'):
626 if opts.get('parent'):
627 raise error.Abort(_('cannot use --parent on non-merge changeset'))
627 raise error.Abort(_('cannot use --parent on non-merge changeset'))
628 parent = p1
628 parent = p1
629
629
630 # the backout should appear on the same branch
630 # the backout should appear on the same branch
631 try:
631 try:
632 branch = repo.dirstate.branch()
632 branch = repo.dirstate.branch()
633 bheads = repo.branchheads(branch)
633 bheads = repo.branchheads(branch)
634 rctx = scmutil.revsingle(repo, hex(parent))
634 rctx = scmutil.revsingle(repo, hex(parent))
635 if not opts.get('merge') and op1 != node:
635 if not opts.get('merge') and op1 != node:
636 dsguard = cmdutil.dirstateguard(repo, 'backout')
636 dsguard = cmdutil.dirstateguard(repo, 'backout')
637 try:
637 try:
638 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
638 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
639 'backout')
639 'backout')
640 stats = mergemod.update(repo, parent, True, True, node, False)
640 stats = mergemod.update(repo, parent, True, True, node, False)
641 repo.setparents(op1, op2)
641 repo.setparents(op1, op2)
642 dsguard.close()
642 dsguard.close()
643 hg._showstats(repo, stats)
643 hg._showstats(repo, stats)
644 if stats[3]:
644 if stats[3]:
645 repo.ui.status(_("use 'hg resolve' to retry unresolved "
645 repo.ui.status(_("use 'hg resolve' to retry unresolved "
646 "file merges\n"))
646 "file merges\n"))
647 return 1
647 return 1
648 elif not commit:
648 elif not commit:
649 msg = _("changeset %s backed out, "
649 msg = _("changeset %s backed out, "
650 "don't forget to commit.\n")
650 "don't forget to commit.\n")
651 ui.status(msg % short(node))
651 ui.status(msg % short(node))
652 return 0
652 return 0
653 finally:
653 finally:
654 ui.setconfig('ui', 'forcemerge', '', '')
654 ui.setconfig('ui', 'forcemerge', '', '')
655 lockmod.release(dsguard)
655 lockmod.release(dsguard)
656 else:
656 else:
657 hg.clean(repo, node, show_stats=False)
657 hg.clean(repo, node, show_stats=False)
658 repo.dirstate.setbranch(branch)
658 repo.dirstate.setbranch(branch)
659 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
659 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
660
660
661
661
662 def commitfunc(ui, repo, message, match, opts):
662 def commitfunc(ui, repo, message, match, opts):
663 editform = 'backout'
663 editform = 'backout'
664 e = cmdutil.getcommiteditor(editform=editform, **opts)
664 e = cmdutil.getcommiteditor(editform=editform, **opts)
665 if not message:
665 if not message:
666 # we don't translate commit messages
666 # we don't translate commit messages
667 message = "Backed out changeset %s" % short(node)
667 message = "Backed out changeset %s" % short(node)
668 e = cmdutil.getcommiteditor(edit=True, editform=editform)
668 e = cmdutil.getcommiteditor(edit=True, editform=editform)
669 return repo.commit(message, opts.get('user'), opts.get('date'),
669 return repo.commit(message, opts.get('user'), opts.get('date'),
670 match, editor=e)
670 match, editor=e)
671 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
671 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
672 if not newnode:
672 if not newnode:
673 ui.status(_("nothing changed\n"))
673 ui.status(_("nothing changed\n"))
674 return 1
674 return 1
675 cmdutil.commitstatus(repo, newnode, branch, bheads)
675 cmdutil.commitstatus(repo, newnode, branch, bheads)
676
676
677 def nice(node):
677 def nice(node):
678 return '%d:%s' % (repo.changelog.rev(node), short(node))
678 return '%d:%s' % (repo.changelog.rev(node), short(node))
679 ui.status(_('changeset %s backs out changeset %s\n') %
679 ui.status(_('changeset %s backs out changeset %s\n') %
680 (nice(repo.changelog.tip()), nice(node)))
680 (nice(repo.changelog.tip()), nice(node)))
681 if opts.get('merge') and op1 != node:
681 if opts.get('merge') and op1 != node:
682 hg.clean(repo, op1, show_stats=False)
682 hg.clean(repo, op1, show_stats=False)
683 ui.status(_('merging with changeset %s\n')
683 ui.status(_('merging with changeset %s\n')
684 % nice(repo.changelog.tip()))
684 % nice(repo.changelog.tip()))
685 try:
685 try:
686 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
686 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
687 'backout')
687 'backout')
688 return hg.merge(repo, hex(repo.changelog.tip()))
688 return hg.merge(repo, hex(repo.changelog.tip()))
689 finally:
689 finally:
690 ui.setconfig('ui', 'forcemerge', '', '')
690 ui.setconfig('ui', 'forcemerge', '', '')
691 finally:
691 finally:
692 # TODO: get rid of this meaningless try/finally enclosing.
692 # TODO: get rid of this meaningless try/finally enclosing.
693 # this is kept only to reduce changes in a patch.
693 # this is kept only to reduce changes in a patch.
694 pass
694 pass
695 return 0
695 return 0
696
696
697 @command('bisect',
697 @command('bisect',
698 [('r', 'reset', False, _('reset bisect state')),
698 [('r', 'reset', False, _('reset bisect state')),
699 ('g', 'good', False, _('mark changeset good')),
699 ('g', 'good', False, _('mark changeset good')),
700 ('b', 'bad', False, _('mark changeset bad')),
700 ('b', 'bad', False, _('mark changeset bad')),
701 ('s', 'skip', False, _('skip testing changeset')),
701 ('s', 'skip', False, _('skip testing changeset')),
702 ('e', 'extend', False, _('extend the bisect range')),
702 ('e', 'extend', False, _('extend the bisect range')),
703 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
703 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
704 ('U', 'noupdate', False, _('do not update to target'))],
704 ('U', 'noupdate', False, _('do not update to target'))],
705 _("[-gbsr] [-U] [-c CMD] [REV]"))
705 _("[-gbsr] [-U] [-c CMD] [REV]"))
706 def bisect(ui, repo, rev=None, extra=None, command=None,
706 def bisect(ui, repo, rev=None, extra=None, command=None,
707 reset=None, good=None, bad=None, skip=None, extend=None,
707 reset=None, good=None, bad=None, skip=None, extend=None,
708 noupdate=None):
708 noupdate=None):
709 """subdivision search of changesets
709 """subdivision search of changesets
710
710
711 This command helps to find changesets which introduce problems. To
711 This command helps to find changesets which introduce problems. To
712 use, mark the earliest changeset you know exhibits the problem as
712 use, mark the earliest changeset you know exhibits the problem as
713 bad, then mark the latest changeset which is free from the problem
713 bad, then mark the latest changeset which is free from the problem
714 as good. Bisect will update your working directory to a revision
714 as good. Bisect will update your working directory to a revision
715 for testing (unless the -U/--noupdate option is specified). Once
715 for testing (unless the -U/--noupdate option is specified). Once
716 you have performed tests, mark the working directory as good or
716 you have performed tests, mark the working directory as good or
717 bad, and bisect will either update to another candidate changeset
717 bad, and bisect will either update to another candidate changeset
718 or announce that it has found the bad revision.
718 or announce that it has found the bad revision.
719
719
720 As a shortcut, you can also use the revision argument to mark a
720 As a shortcut, you can also use the revision argument to mark a
721 revision as good or bad without checking it out first.
721 revision as good or bad without checking it out first.
722
722
723 If you supply a command, it will be used for automatic bisection.
723 If you supply a command, it will be used for automatic bisection.
724 The environment variable HG_NODE will contain the ID of the
724 The environment variable HG_NODE will contain the ID of the
725 changeset being tested. The exit status of the command will be
725 changeset being tested. The exit status of the command will be
726 used to mark revisions as good or bad: status 0 means good, 125
726 used to mark revisions as good or bad: status 0 means good, 125
727 means to skip the revision, 127 (command not found) will abort the
727 means to skip the revision, 127 (command not found) will abort the
728 bisection, and any other non-zero exit status means the revision
728 bisection, and any other non-zero exit status means the revision
729 is bad.
729 is bad.
730
730
731 .. container:: verbose
731 .. container:: verbose
732
732
733 Some examples:
733 Some examples:
734
734
735 - start a bisection with known bad revision 34, and good revision 12::
735 - start a bisection with known bad revision 34, and good revision 12::
736
736
737 hg bisect --bad 34
737 hg bisect --bad 34
738 hg bisect --good 12
738 hg bisect --good 12
739
739
740 - advance the current bisection by marking current revision as good or
740 - advance the current bisection by marking current revision as good or
741 bad::
741 bad::
742
742
743 hg bisect --good
743 hg bisect --good
744 hg bisect --bad
744 hg bisect --bad
745
745
746 - mark the current revision, or a known revision, to be skipped (e.g. if
746 - mark the current revision, or a known revision, to be skipped (e.g. if
747 that revision is not usable because of another issue)::
747 that revision is not usable because of another issue)::
748
748
749 hg bisect --skip
749 hg bisect --skip
750 hg bisect --skip 23
750 hg bisect --skip 23
751
751
752 - skip all revisions that do not touch directories ``foo`` or ``bar``::
752 - skip all revisions that do not touch directories ``foo`` or ``bar``::
753
753
754 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
754 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
755
755
756 - forget the current bisection::
756 - forget the current bisection::
757
757
758 hg bisect --reset
758 hg bisect --reset
759
759
760 - use 'make && make tests' to automatically find the first broken
760 - use 'make && make tests' to automatically find the first broken
761 revision::
761 revision::
762
762
763 hg bisect --reset
763 hg bisect --reset
764 hg bisect --bad 34
764 hg bisect --bad 34
765 hg bisect --good 12
765 hg bisect --good 12
766 hg bisect --command "make && make tests"
766 hg bisect --command "make && make tests"
767
767
768 - see all changesets whose states are already known in the current
768 - see all changesets whose states are already known in the current
769 bisection::
769 bisection::
770
770
771 hg log -r "bisect(pruned)"
771 hg log -r "bisect(pruned)"
772
772
773 - see the changeset currently being bisected (especially useful
773 - see the changeset currently being bisected (especially useful
774 if running with -U/--noupdate)::
774 if running with -U/--noupdate)::
775
775
776 hg log -r "bisect(current)"
776 hg log -r "bisect(current)"
777
777
778 - see all changesets that took part in the current bisection::
778 - see all changesets that took part in the current bisection::
779
779
780 hg log -r "bisect(range)"
780 hg log -r "bisect(range)"
781
781
782 - you can even get a nice graph::
782 - you can even get a nice graph::
783
783
784 hg log --graph -r "bisect(range)"
784 hg log --graph -r "bisect(range)"
785
785
786 See :hg:`help revsets` for more about the `bisect()` keyword.
786 See :hg:`help revsets` for more about the `bisect()` keyword.
787
787
788 Returns 0 on success.
788 Returns 0 on success.
789 """
789 """
790 def extendbisectrange(nodes, good):
790 def extendbisectrange(nodes, good):
791 # bisect is incomplete when it ends on a merge node and
791 # bisect is incomplete when it ends on a merge node and
792 # one of the parent was not checked.
792 # one of the parent was not checked.
793 parents = repo[nodes[0]].parents()
793 parents = repo[nodes[0]].parents()
794 if len(parents) > 1:
794 if len(parents) > 1:
795 if good:
795 if good:
796 side = state['bad']
796 side = state['bad']
797 else:
797 else:
798 side = state['good']
798 side = state['good']
799 num = len(set(i.node() for i in parents) & set(side))
799 num = len(set(i.node() for i in parents) & set(side))
800 if num == 1:
800 if num == 1:
801 return parents[0].ancestor(parents[1])
801 return parents[0].ancestor(parents[1])
802 return None
802 return None
803
803
804 def print_result(nodes, good):
804 def print_result(nodes, good):
805 displayer = cmdutil.show_changeset(ui, repo, {})
805 displayer = cmdutil.show_changeset(ui, repo, {})
806 if len(nodes) == 1:
806 if len(nodes) == 1:
807 # narrowed it down to a single revision
807 # narrowed it down to a single revision
808 if good:
808 if good:
809 ui.write(_("The first good revision is:\n"))
809 ui.write(_("The first good revision is:\n"))
810 else:
810 else:
811 ui.write(_("The first bad revision is:\n"))
811 ui.write(_("The first bad revision is:\n"))
812 displayer.show(repo[nodes[0]])
812 displayer.show(repo[nodes[0]])
813 extendnode = extendbisectrange(nodes, good)
813 extendnode = extendbisectrange(nodes, good)
814 if extendnode is not None:
814 if extendnode is not None:
815 ui.write(_('Not all ancestors of this changeset have been'
815 ui.write(_('Not all ancestors of this changeset have been'
816 ' checked.\nUse bisect --extend to continue the '
816 ' checked.\nUse bisect --extend to continue the '
817 'bisection from\nthe common ancestor, %s.\n')
817 'bisection from\nthe common ancestor, %s.\n')
818 % extendnode)
818 % extendnode)
819 else:
819 else:
820 # multiple possible revisions
820 # multiple possible revisions
821 if good:
821 if good:
822 ui.write(_("Due to skipped revisions, the first "
822 ui.write(_("Due to skipped revisions, the first "
823 "good revision could be any of:\n"))
823 "good revision could be any of:\n"))
824 else:
824 else:
825 ui.write(_("Due to skipped revisions, the first "
825 ui.write(_("Due to skipped revisions, the first "
826 "bad revision could be any of:\n"))
826 "bad revision could be any of:\n"))
827 for n in nodes:
827 for n in nodes:
828 displayer.show(repo[n])
828 displayer.show(repo[n])
829 displayer.close()
829 displayer.close()
830
830
831 def check_state(state, interactive=True):
831 def check_state(state, interactive=True):
832 if not state['good'] or not state['bad']:
832 if not state['good'] or not state['bad']:
833 if (good or bad or skip or reset) and interactive:
833 if (good or bad or skip or reset) and interactive:
834 return
834 return
835 if not state['good']:
835 if not state['good']:
836 raise error.Abort(_('cannot bisect (no known good revisions)'))
836 raise error.Abort(_('cannot bisect (no known good revisions)'))
837 else:
837 else:
838 raise error.Abort(_('cannot bisect (no known bad revisions)'))
838 raise error.Abort(_('cannot bisect (no known bad revisions)'))
839 return True
839 return True
840
840
841 # backward compatibility
841 # backward compatibility
842 if rev in "good bad reset init".split():
842 if rev in "good bad reset init".split():
843 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
843 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
844 cmd, rev, extra = rev, extra, None
844 cmd, rev, extra = rev, extra, None
845 if cmd == "good":
845 if cmd == "good":
846 good = True
846 good = True
847 elif cmd == "bad":
847 elif cmd == "bad":
848 bad = True
848 bad = True
849 else:
849 else:
850 reset = True
850 reset = True
851 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
851 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
852 raise error.Abort(_('incompatible arguments'))
852 raise error.Abort(_('incompatible arguments'))
853
853
854 cmdutil.checkunfinished(repo)
854 cmdutil.checkunfinished(repo)
855
855
856 if reset:
856 if reset:
857 p = repo.join("bisect.state")
857 p = repo.join("bisect.state")
858 if os.path.exists(p):
858 if os.path.exists(p):
859 os.unlink(p)
859 os.unlink(p)
860 return
860 return
861
861
862 state = hbisect.load_state(repo)
862 state = hbisect.load_state(repo)
863
863
864 if command:
864 if command:
865 changesets = 1
865 changesets = 1
866 if noupdate:
866 if noupdate:
867 try:
867 try:
868 node = state['current'][0]
868 node = state['current'][0]
869 except LookupError:
869 except LookupError:
870 raise error.Abort(_('current bisect revision is unknown - '
870 raise error.Abort(_('current bisect revision is unknown - '
871 'start a new bisect to fix'))
871 'start a new bisect to fix'))
872 else:
872 else:
873 node, p2 = repo.dirstate.parents()
873 node, p2 = repo.dirstate.parents()
874 if p2 != nullid:
874 if p2 != nullid:
875 raise error.Abort(_('current bisect revision is a merge'))
875 raise error.Abort(_('current bisect revision is a merge'))
876 try:
876 try:
877 while changesets:
877 while changesets:
878 # update state
878 # update state
879 state['current'] = [node]
879 state['current'] = [node]
880 hbisect.save_state(repo, state)
880 hbisect.save_state(repo, state)
881 status = ui.system(command, environ={'HG_NODE': hex(node)})
881 status = ui.system(command, environ={'HG_NODE': hex(node)})
882 if status == 125:
882 if status == 125:
883 transition = "skip"
883 transition = "skip"
884 elif status == 0:
884 elif status == 0:
885 transition = "good"
885 transition = "good"
886 # status < 0 means process was killed
886 # status < 0 means process was killed
887 elif status == 127:
887 elif status == 127:
888 raise error.Abort(_("failed to execute %s") % command)
888 raise error.Abort(_("failed to execute %s") % command)
889 elif status < 0:
889 elif status < 0:
890 raise error.Abort(_("%s killed") % command)
890 raise error.Abort(_("%s killed") % command)
891 else:
891 else:
892 transition = "bad"
892 transition = "bad"
893 ctx = scmutil.revsingle(repo, rev, node)
893 ctx = scmutil.revsingle(repo, rev, node)
894 rev = None # clear for future iterations
894 rev = None # clear for future iterations
895 state[transition].append(ctx.node())
895 state[transition].append(ctx.node())
896 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
896 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
897 check_state(state, interactive=False)
897 check_state(state, interactive=False)
898 # bisect
898 # bisect
899 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
899 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
900 # update to next check
900 # update to next check
901 node = nodes[0]
901 node = nodes[0]
902 if not noupdate:
902 if not noupdate:
903 cmdutil.bailifchanged(repo)
903 cmdutil.bailifchanged(repo)
904 hg.clean(repo, node, show_stats=False)
904 hg.clean(repo, node, show_stats=False)
905 finally:
905 finally:
906 state['current'] = [node]
906 state['current'] = [node]
907 hbisect.save_state(repo, state)
907 hbisect.save_state(repo, state)
908 print_result(nodes, bgood)
908 print_result(nodes, bgood)
909 return
909 return
910
910
911 # update state
911 # update state
912
912
913 if rev:
913 if rev:
914 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
914 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
915 else:
915 else:
916 nodes = [repo.lookup('.')]
916 nodes = [repo.lookup('.')]
917
917
918 if good or bad or skip:
918 if good or bad or skip:
919 if good:
919 if good:
920 state['good'] += nodes
920 state['good'] += nodes
921 elif bad:
921 elif bad:
922 state['bad'] += nodes
922 state['bad'] += nodes
923 elif skip:
923 elif skip:
924 state['skip'] += nodes
924 state['skip'] += nodes
925 hbisect.save_state(repo, state)
925 hbisect.save_state(repo, state)
926
926
927 if not check_state(state):
927 if not check_state(state):
928 return
928 return
929
929
930 # actually bisect
930 # actually bisect
931 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
931 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
932 if extend:
932 if extend:
933 if not changesets:
933 if not changesets:
934 extendnode = extendbisectrange(nodes, good)
934 extendnode = extendbisectrange(nodes, good)
935 if extendnode is not None:
935 if extendnode is not None:
936 ui.write(_("Extending search to changeset %d:%s\n")
936 ui.write(_("Extending search to changeset %d:%s\n")
937 % (extendnode.rev(), extendnode))
937 % (extendnode.rev(), extendnode))
938 state['current'] = [extendnode.node()]
938 state['current'] = [extendnode.node()]
939 hbisect.save_state(repo, state)
939 hbisect.save_state(repo, state)
940 if noupdate:
940 if noupdate:
941 return
941 return
942 cmdutil.bailifchanged(repo)
942 cmdutil.bailifchanged(repo)
943 return hg.clean(repo, extendnode.node())
943 return hg.clean(repo, extendnode.node())
944 raise error.Abort(_("nothing to extend"))
944 raise error.Abort(_("nothing to extend"))
945
945
946 if changesets == 0:
946 if changesets == 0:
947 print_result(nodes, good)
947 print_result(nodes, good)
948 else:
948 else:
949 assert len(nodes) == 1 # only a single node can be tested next
949 assert len(nodes) == 1 # only a single node can be tested next
950 node = nodes[0]
950 node = nodes[0]
951 # compute the approximate number of remaining tests
951 # compute the approximate number of remaining tests
952 tests, size = 0, 2
952 tests, size = 0, 2
953 while size <= changesets:
953 while size <= changesets:
954 tests, size = tests + 1, size * 2
954 tests, size = tests + 1, size * 2
955 rev = repo.changelog.rev(node)
955 rev = repo.changelog.rev(node)
956 ui.write(_("Testing changeset %d:%s "
956 ui.write(_("Testing changeset %d:%s "
957 "(%d changesets remaining, ~%d tests)\n")
957 "(%d changesets remaining, ~%d tests)\n")
958 % (rev, short(node), changesets, tests))
958 % (rev, short(node), changesets, tests))
959 state['current'] = [node]
959 state['current'] = [node]
960 hbisect.save_state(repo, state)
960 hbisect.save_state(repo, state)
961 if not noupdate:
961 if not noupdate:
962 cmdutil.bailifchanged(repo)
962 cmdutil.bailifchanged(repo)
963 return hg.clean(repo, node)
963 return hg.clean(repo, node)
964
964
965 @command('bookmarks|bookmark',
965 @command('bookmarks|bookmark',
966 [('f', 'force', False, _('force')),
966 [('f', 'force', False, _('force')),
967 ('r', 'rev', '', _('revision'), _('REV')),
967 ('r', 'rev', '', _('revision'), _('REV')),
968 ('d', 'delete', False, _('delete a given bookmark')),
968 ('d', 'delete', False, _('delete a given bookmark')),
969 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
969 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
970 ('i', 'inactive', False, _('mark a bookmark inactive')),
970 ('i', 'inactive', False, _('mark a bookmark inactive')),
971 ] + formatteropts,
971 ] + formatteropts,
972 _('hg bookmarks [OPTIONS]... [NAME]...'))
972 _('hg bookmarks [OPTIONS]... [NAME]...'))
973 def bookmark(ui, repo, *names, **opts):
973 def bookmark(ui, repo, *names, **opts):
974 '''create a new bookmark or list existing bookmarks
974 '''create a new bookmark or list existing bookmarks
975
975
976 Bookmarks are labels on changesets to help track lines of development.
976 Bookmarks are labels on changesets to help track lines of development.
977 Bookmarks are unversioned and can be moved, renamed and deleted.
977 Bookmarks are unversioned and can be moved, renamed and deleted.
978 Deleting or moving a bookmark has no effect on the associated changesets.
978 Deleting or moving a bookmark has no effect on the associated changesets.
979
979
980 Creating or updating to a bookmark causes it to be marked as 'active'.
980 Creating or updating to a bookmark causes it to be marked as 'active'.
981 The active bookmark is indicated with a '*'.
981 The active bookmark is indicated with a '*'.
982 When a commit is made, the active bookmark will advance to the new commit.
982 When a commit is made, the active bookmark will advance to the new commit.
983 A plain :hg:`update` will also advance an active bookmark, if possible.
983 A plain :hg:`update` will also advance an active bookmark, if possible.
984 Updating away from a bookmark will cause it to be deactivated.
984 Updating away from a bookmark will cause it to be deactivated.
985
985
986 Bookmarks can be pushed and pulled between repositories (see
986 Bookmarks can be pushed and pulled between repositories (see
987 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
987 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
988 diverged, a new 'divergent bookmark' of the form 'name@path' will
988 diverged, a new 'divergent bookmark' of the form 'name@path' will
989 be created. Using :hg:`merge` will resolve the divergence.
989 be created. Using :hg:`merge` will resolve the divergence.
990
990
991 A bookmark named '@' has the special property that :hg:`clone` will
991 A bookmark named '@' has the special property that :hg:`clone` will
992 check it out by default if it exists.
992 check it out by default if it exists.
993
993
994 .. container:: verbose
994 .. container:: verbose
995
995
996 Examples:
996 Examples:
997
997
998 - create an active bookmark for a new line of development::
998 - create an active bookmark for a new line of development::
999
999
1000 hg book new-feature
1000 hg book new-feature
1001
1001
1002 - create an inactive bookmark as a place marker::
1002 - create an inactive bookmark as a place marker::
1003
1003
1004 hg book -i reviewed
1004 hg book -i reviewed
1005
1005
1006 - create an inactive bookmark on another changeset::
1006 - create an inactive bookmark on another changeset::
1007
1007
1008 hg book -r .^ tested
1008 hg book -r .^ tested
1009
1009
1010 - rename bookmark turkey to dinner::
1010 - rename bookmark turkey to dinner::
1011
1011
1012 hg book -m turkey dinner
1012 hg book -m turkey dinner
1013
1013
1014 - move the '@' bookmark from another branch::
1014 - move the '@' bookmark from another branch::
1015
1015
1016 hg book -f @
1016 hg book -f @
1017 '''
1017 '''
1018 force = opts.get('force')
1018 force = opts.get('force')
1019 rev = opts.get('rev')
1019 rev = opts.get('rev')
1020 delete = opts.get('delete')
1020 delete = opts.get('delete')
1021 rename = opts.get('rename')
1021 rename = opts.get('rename')
1022 inactive = opts.get('inactive')
1022 inactive = opts.get('inactive')
1023
1023
1024 def checkformat(mark):
1024 def checkformat(mark):
1025 mark = mark.strip()
1025 mark = mark.strip()
1026 if not mark:
1026 if not mark:
1027 raise error.Abort(_("bookmark names cannot consist entirely of "
1027 raise error.Abort(_("bookmark names cannot consist entirely of "
1028 "whitespace"))
1028 "whitespace"))
1029 scmutil.checknewlabel(repo, mark, 'bookmark')
1029 scmutil.checknewlabel(repo, mark, 'bookmark')
1030 return mark
1030 return mark
1031
1031
1032 def checkconflict(repo, mark, cur, force=False, target=None):
1032 def checkconflict(repo, mark, cur, force=False, target=None):
1033 if mark in marks and not force:
1033 if mark in marks and not force:
1034 if target:
1034 if target:
1035 if marks[mark] == target and target == cur:
1035 if marks[mark] == target and target == cur:
1036 # re-activating a bookmark
1036 # re-activating a bookmark
1037 return
1037 return
1038 anc = repo.changelog.ancestors([repo[target].rev()])
1038 anc = repo.changelog.ancestors([repo[target].rev()])
1039 bmctx = repo[marks[mark]]
1039 bmctx = repo[marks[mark]]
1040 divs = [repo[b].node() for b in marks
1040 divs = [repo[b].node() for b in marks
1041 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1041 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1042
1042
1043 # allow resolving a single divergent bookmark even if moving
1043 # allow resolving a single divergent bookmark even if moving
1044 # the bookmark across branches when a revision is specified
1044 # the bookmark across branches when a revision is specified
1045 # that contains a divergent bookmark
1045 # that contains a divergent bookmark
1046 if bmctx.rev() not in anc and target in divs:
1046 if bmctx.rev() not in anc and target in divs:
1047 bookmarks.deletedivergent(repo, [target], mark)
1047 bookmarks.deletedivergent(repo, [target], mark)
1048 return
1048 return
1049
1049
1050 deletefrom = [b for b in divs
1050 deletefrom = [b for b in divs
1051 if repo[b].rev() in anc or b == target]
1051 if repo[b].rev() in anc or b == target]
1052 bookmarks.deletedivergent(repo, deletefrom, mark)
1052 bookmarks.deletedivergent(repo, deletefrom, mark)
1053 if bookmarks.validdest(repo, bmctx, repo[target]):
1053 if bookmarks.validdest(repo, bmctx, repo[target]):
1054 ui.status(_("moving bookmark '%s' forward from %s\n") %
1054 ui.status(_("moving bookmark '%s' forward from %s\n") %
1055 (mark, short(bmctx.node())))
1055 (mark, short(bmctx.node())))
1056 return
1056 return
1057 raise error.Abort(_("bookmark '%s' already exists "
1057 raise error.Abort(_("bookmark '%s' already exists "
1058 "(use -f to force)") % mark)
1058 "(use -f to force)") % mark)
1059 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1059 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1060 and not force):
1060 and not force):
1061 raise error.Abort(
1061 raise error.Abort(
1062 _("a bookmark cannot have the name of an existing branch"))
1062 _("a bookmark cannot have the name of an existing branch"))
1063
1063
1064 if delete and rename:
1064 if delete and rename:
1065 raise error.Abort(_("--delete and --rename are incompatible"))
1065 raise error.Abort(_("--delete and --rename are incompatible"))
1066 if delete and rev:
1066 if delete and rev:
1067 raise error.Abort(_("--rev is incompatible with --delete"))
1067 raise error.Abort(_("--rev is incompatible with --delete"))
1068 if rename and rev:
1068 if rename and rev:
1069 raise error.Abort(_("--rev is incompatible with --rename"))
1069 raise error.Abort(_("--rev is incompatible with --rename"))
1070 if not names and (delete or rev):
1070 if not names and (delete or rev):
1071 raise error.Abort(_("bookmark name required"))
1071 raise error.Abort(_("bookmark name required"))
1072
1072
1073 if delete or rename or names or inactive:
1073 if delete or rename or names or inactive:
1074 wlock = lock = tr = None
1074 wlock = lock = tr = None
1075 try:
1075 try:
1076 wlock = repo.wlock()
1076 wlock = repo.wlock()
1077 lock = repo.lock()
1077 lock = repo.lock()
1078 cur = repo.changectx('.').node()
1078 cur = repo.changectx('.').node()
1079 marks = repo._bookmarks
1079 marks = repo._bookmarks
1080 if delete:
1080 if delete:
1081 tr = repo.transaction('bookmark')
1081 tr = repo.transaction('bookmark')
1082 for mark in names:
1082 for mark in names:
1083 if mark not in marks:
1083 if mark not in marks:
1084 raise error.Abort(_("bookmark '%s' does not exist") %
1084 raise error.Abort(_("bookmark '%s' does not exist") %
1085 mark)
1085 mark)
1086 if mark == repo._activebookmark:
1086 if mark == repo._activebookmark:
1087 bookmarks.deactivate(repo)
1087 bookmarks.deactivate(repo)
1088 del marks[mark]
1088 del marks[mark]
1089
1089
1090 elif rename:
1090 elif rename:
1091 tr = repo.transaction('bookmark')
1091 tr = repo.transaction('bookmark')
1092 if not names:
1092 if not names:
1093 raise error.Abort(_("new bookmark name required"))
1093 raise error.Abort(_("new bookmark name required"))
1094 elif len(names) > 1:
1094 elif len(names) > 1:
1095 raise error.Abort(_("only one new bookmark name allowed"))
1095 raise error.Abort(_("only one new bookmark name allowed"))
1096 mark = checkformat(names[0])
1096 mark = checkformat(names[0])
1097 if rename not in marks:
1097 if rename not in marks:
1098 raise error.Abort(_("bookmark '%s' does not exist")
1098 raise error.Abort(_("bookmark '%s' does not exist")
1099 % rename)
1099 % rename)
1100 checkconflict(repo, mark, cur, force)
1100 checkconflict(repo, mark, cur, force)
1101 marks[mark] = marks[rename]
1101 marks[mark] = marks[rename]
1102 if repo._activebookmark == rename and not inactive:
1102 if repo._activebookmark == rename and not inactive:
1103 bookmarks.activate(repo, mark)
1103 bookmarks.activate(repo, mark)
1104 del marks[rename]
1104 del marks[rename]
1105 elif names:
1105 elif names:
1106 tr = repo.transaction('bookmark')
1106 tr = repo.transaction('bookmark')
1107 newact = None
1107 newact = None
1108 for mark in names:
1108 for mark in names:
1109 mark = checkformat(mark)
1109 mark = checkformat(mark)
1110 if newact is None:
1110 if newact is None:
1111 newact = mark
1111 newact = mark
1112 if inactive and mark == repo._activebookmark:
1112 if inactive and mark == repo._activebookmark:
1113 bookmarks.deactivate(repo)
1113 bookmarks.deactivate(repo)
1114 return
1114 return
1115 tgt = cur
1115 tgt = cur
1116 if rev:
1116 if rev:
1117 tgt = scmutil.revsingle(repo, rev).node()
1117 tgt = scmutil.revsingle(repo, rev).node()
1118 checkconflict(repo, mark, cur, force, tgt)
1118 checkconflict(repo, mark, cur, force, tgt)
1119 marks[mark] = tgt
1119 marks[mark] = tgt
1120 if not inactive and cur == marks[newact] and not rev:
1120 if not inactive and cur == marks[newact] and not rev:
1121 bookmarks.activate(repo, newact)
1121 bookmarks.activate(repo, newact)
1122 elif cur != tgt and newact == repo._activebookmark:
1122 elif cur != tgt and newact == repo._activebookmark:
1123 bookmarks.deactivate(repo)
1123 bookmarks.deactivate(repo)
1124 elif inactive:
1124 elif inactive:
1125 if len(marks) == 0:
1125 if len(marks) == 0:
1126 ui.status(_("no bookmarks set\n"))
1126 ui.status(_("no bookmarks set\n"))
1127 elif not repo._activebookmark:
1127 elif not repo._activebookmark:
1128 ui.status(_("no active bookmark\n"))
1128 ui.status(_("no active bookmark\n"))
1129 else:
1129 else:
1130 bookmarks.deactivate(repo)
1130 bookmarks.deactivate(repo)
1131 if tr is not None:
1131 if tr is not None:
1132 marks.recordchange(tr)
1132 marks.recordchange(tr)
1133 tr.close()
1133 tr.close()
1134 finally:
1134 finally:
1135 lockmod.release(tr, lock, wlock)
1135 lockmod.release(tr, lock, wlock)
1136 else: # show bookmarks
1136 else: # show bookmarks
1137 fm = ui.formatter('bookmarks', opts)
1137 fm = ui.formatter('bookmarks', opts)
1138 hexfn = fm.hexfunc
1138 hexfn = fm.hexfunc
1139 marks = repo._bookmarks
1139 marks = repo._bookmarks
1140 if len(marks) == 0 and not fm:
1140 if len(marks) == 0 and not fm:
1141 ui.status(_("no bookmarks set\n"))
1141 ui.status(_("no bookmarks set\n"))
1142 for bmark, n in sorted(marks.iteritems()):
1142 for bmark, n in sorted(marks.iteritems()):
1143 active = repo._activebookmark
1143 active = repo._activebookmark
1144 if bmark == active:
1144 if bmark == active:
1145 prefix, label = '*', activebookmarklabel
1145 prefix, label = '*', activebookmarklabel
1146 else:
1146 else:
1147 prefix, label = ' ', ''
1147 prefix, label = ' ', ''
1148
1148
1149 fm.startitem()
1149 fm.startitem()
1150 if not ui.quiet:
1150 if not ui.quiet:
1151 fm.plain(' %s ' % prefix, label=label)
1151 fm.plain(' %s ' % prefix, label=label)
1152 fm.write('bookmark', '%s', bmark, label=label)
1152 fm.write('bookmark', '%s', bmark, label=label)
1153 pad = " " * (25 - encoding.colwidth(bmark))
1153 pad = " " * (25 - encoding.colwidth(bmark))
1154 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1154 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1155 repo.changelog.rev(n), hexfn(n), label=label)
1155 repo.changelog.rev(n), hexfn(n), label=label)
1156 fm.data(active=(bmark == active))
1156 fm.data(active=(bmark == active))
1157 fm.plain('\n')
1157 fm.plain('\n')
1158 fm.end()
1158 fm.end()
1159
1159
1160 @command('branch',
1160 @command('branch',
1161 [('f', 'force', None,
1161 [('f', 'force', None,
1162 _('set branch name even if it shadows an existing branch')),
1162 _('set branch name even if it shadows an existing branch')),
1163 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1163 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1164 _('[-fC] [NAME]'))
1164 _('[-fC] [NAME]'))
1165 def branch(ui, repo, label=None, **opts):
1165 def branch(ui, repo, label=None, **opts):
1166 """set or show the current branch name
1166 """set or show the current branch name
1167
1167
1168 .. note::
1168 .. note::
1169
1169
1170 Branch names are permanent and global. Use :hg:`bookmark` to create a
1170 Branch names are permanent and global. Use :hg:`bookmark` to create a
1171 light-weight bookmark instead. See :hg:`help glossary` for more
1171 light-weight bookmark instead. See :hg:`help glossary` for more
1172 information about named branches and bookmarks.
1172 information about named branches and bookmarks.
1173
1173
1174 With no argument, show the current branch name. With one argument,
1174 With no argument, show the current branch name. With one argument,
1175 set the working directory branch name (the branch will not exist
1175 set the working directory branch name (the branch will not exist
1176 in the repository until the next commit). Standard practice
1176 in the repository until the next commit). Standard practice
1177 recommends that primary development take place on the 'default'
1177 recommends that primary development take place on the 'default'
1178 branch.
1178 branch.
1179
1179
1180 Unless -f/--force is specified, branch will not let you set a
1180 Unless -f/--force is specified, branch will not let you set a
1181 branch name that already exists.
1181 branch name that already exists.
1182
1182
1183 Use -C/--clean to reset the working directory branch to that of
1183 Use -C/--clean to reset the working directory branch to that of
1184 the parent of the working directory, negating a previous branch
1184 the parent of the working directory, negating a previous branch
1185 change.
1185 change.
1186
1186
1187 Use the command :hg:`update` to switch to an existing branch. Use
1187 Use the command :hg:`update` to switch to an existing branch. Use
1188 :hg:`commit --close-branch` to mark this branch head as closed.
1188 :hg:`commit --close-branch` to mark this branch head as closed.
1189 When all heads of the branch are closed, the branch will be
1189 When all heads of the branch are closed, the branch will be
1190 considered closed.
1190 considered closed.
1191
1191
1192 Returns 0 on success.
1192 Returns 0 on success.
1193 """
1193 """
1194 if label:
1194 if label:
1195 label = label.strip()
1195 label = label.strip()
1196
1196
1197 if not opts.get('clean') and not label:
1197 if not opts.get('clean') and not label:
1198 ui.write("%s\n" % repo.dirstate.branch())
1198 ui.write("%s\n" % repo.dirstate.branch())
1199 return
1199 return
1200
1200
1201 wlock = repo.wlock()
1201 wlock = repo.wlock()
1202 try:
1202 try:
1203 if opts.get('clean'):
1203 if opts.get('clean'):
1204 label = repo[None].p1().branch()
1204 label = repo[None].p1().branch()
1205 repo.dirstate.setbranch(label)
1205 repo.dirstate.setbranch(label)
1206 ui.status(_('reset working directory to branch %s\n') % label)
1206 ui.status(_('reset working directory to branch %s\n') % label)
1207 elif label:
1207 elif label:
1208 if not opts.get('force') and label in repo.branchmap():
1208 if not opts.get('force') and label in repo.branchmap():
1209 if label not in [p.branch() for p in repo[None].parents()]:
1209 if label not in [p.branch() for p in repo[None].parents()]:
1210 raise error.Abort(_('a branch of the same name already'
1210 raise error.Abort(_('a branch of the same name already'
1211 ' exists'),
1211 ' exists'),
1212 # i18n: "it" refers to an existing branch
1212 # i18n: "it" refers to an existing branch
1213 hint=_("use 'hg update' to switch to it"))
1213 hint=_("use 'hg update' to switch to it"))
1214 scmutil.checknewlabel(repo, label, 'branch')
1214 scmutil.checknewlabel(repo, label, 'branch')
1215 repo.dirstate.setbranch(label)
1215 repo.dirstate.setbranch(label)
1216 ui.status(_('marked working directory as branch %s\n') % label)
1216 ui.status(_('marked working directory as branch %s\n') % label)
1217
1217
1218 # find any open named branches aside from default
1218 # find any open named branches aside from default
1219 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1219 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1220 if n != "default" and not c]
1220 if n != "default" and not c]
1221 if not others:
1221 if not others:
1222 ui.status(_('(branches are permanent and global, '
1222 ui.status(_('(branches are permanent and global, '
1223 'did you want a bookmark?)\n'))
1223 'did you want a bookmark?)\n'))
1224 finally:
1224 finally:
1225 wlock.release()
1225 wlock.release()
1226
1226
1227 @command('branches',
1227 @command('branches',
1228 [('a', 'active', False,
1228 [('a', 'active', False,
1229 _('show only branches that have unmerged heads (DEPRECATED)')),
1229 _('show only branches that have unmerged heads (DEPRECATED)')),
1230 ('c', 'closed', False, _('show normal and closed branches')),
1230 ('c', 'closed', False, _('show normal and closed branches')),
1231 ] + formatteropts,
1231 ] + formatteropts,
1232 _('[-ac]'))
1232 _('[-ac]'))
1233 def branches(ui, repo, active=False, closed=False, **opts):
1233 def branches(ui, repo, active=False, closed=False, **opts):
1234 """list repository named branches
1234 """list repository named branches
1235
1235
1236 List the repository's named branches, indicating which ones are
1236 List the repository's named branches, indicating which ones are
1237 inactive. If -c/--closed is specified, also list branches which have
1237 inactive. If -c/--closed is specified, also list branches which have
1238 been marked closed (see :hg:`commit --close-branch`).
1238 been marked closed (see :hg:`commit --close-branch`).
1239
1239
1240 Use the command :hg:`update` to switch to an existing branch.
1240 Use the command :hg:`update` to switch to an existing branch.
1241
1241
1242 Returns 0.
1242 Returns 0.
1243 """
1243 """
1244
1244
1245 fm = ui.formatter('branches', opts)
1245 fm = ui.formatter('branches', opts)
1246 hexfunc = fm.hexfunc
1246 hexfunc = fm.hexfunc
1247
1247
1248 allheads = set(repo.heads())
1248 allheads = set(repo.heads())
1249 branches = []
1249 branches = []
1250 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1250 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1251 isactive = not isclosed and bool(set(heads) & allheads)
1251 isactive = not isclosed and bool(set(heads) & allheads)
1252 branches.append((tag, repo[tip], isactive, not isclosed))
1252 branches.append((tag, repo[tip], isactive, not isclosed))
1253 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1253 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1254 reverse=True)
1254 reverse=True)
1255
1255
1256 for tag, ctx, isactive, isopen in branches:
1256 for tag, ctx, isactive, isopen in branches:
1257 if active and not isactive:
1257 if active and not isactive:
1258 continue
1258 continue
1259 if isactive:
1259 if isactive:
1260 label = 'branches.active'
1260 label = 'branches.active'
1261 notice = ''
1261 notice = ''
1262 elif not isopen:
1262 elif not isopen:
1263 if not closed:
1263 if not closed:
1264 continue
1264 continue
1265 label = 'branches.closed'
1265 label = 'branches.closed'
1266 notice = _(' (closed)')
1266 notice = _(' (closed)')
1267 else:
1267 else:
1268 label = 'branches.inactive'
1268 label = 'branches.inactive'
1269 notice = _(' (inactive)')
1269 notice = _(' (inactive)')
1270 current = (tag == repo.dirstate.branch())
1270 current = (tag == repo.dirstate.branch())
1271 if current:
1271 if current:
1272 label = 'branches.current'
1272 label = 'branches.current'
1273
1273
1274 fm.startitem()
1274 fm.startitem()
1275 fm.write('branch', '%s', tag, label=label)
1275 fm.write('branch', '%s', tag, label=label)
1276 rev = ctx.rev()
1276 rev = ctx.rev()
1277 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1277 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1278 fmt = ' ' * padsize + ' %d:%s'
1278 fmt = ' ' * padsize + ' %d:%s'
1279 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1279 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1280 label='log.changeset changeset.%s' % ctx.phasestr())
1280 label='log.changeset changeset.%s' % ctx.phasestr())
1281 fm.data(active=isactive, closed=not isopen, current=current)
1281 fm.data(active=isactive, closed=not isopen, current=current)
1282 if not ui.quiet:
1282 if not ui.quiet:
1283 fm.plain(notice)
1283 fm.plain(notice)
1284 fm.plain('\n')
1284 fm.plain('\n')
1285 fm.end()
1285 fm.end()
1286
1286
1287 @command('bundle',
1287 @command('bundle',
1288 [('f', 'force', None, _('run even when the destination is unrelated')),
1288 [('f', 'force', None, _('run even when the destination is unrelated')),
1289 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1289 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1290 _('REV')),
1290 _('REV')),
1291 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1291 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1292 _('BRANCH')),
1292 _('BRANCH')),
1293 ('', 'base', [],
1293 ('', 'base', [],
1294 _('a base changeset assumed to be available at the destination'),
1294 _('a base changeset assumed to be available at the destination'),
1295 _('REV')),
1295 _('REV')),
1296 ('a', 'all', None, _('bundle all changesets in the repository')),
1296 ('a', 'all', None, _('bundle all changesets in the repository')),
1297 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1297 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1298 ] + remoteopts,
1298 ] + remoteopts,
1299 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1299 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1300 def bundle(ui, repo, fname, dest=None, **opts):
1300 def bundle(ui, repo, fname, dest=None, **opts):
1301 """create a changegroup file
1301 """create a changegroup file
1302
1302
1303 Generate a changegroup file collecting changesets to be added
1303 Generate a changegroup file collecting changesets to be added
1304 to a repository.
1304 to a repository.
1305
1305
1306 To create a bundle containing all changesets, use -a/--all
1306 To create a bundle containing all changesets, use -a/--all
1307 (or --base null). Otherwise, hg assumes the destination will have
1307 (or --base null). Otherwise, hg assumes the destination will have
1308 all the nodes you specify with --base parameters. Otherwise, hg
1308 all the nodes you specify with --base parameters. Otherwise, hg
1309 will assume the repository has all the nodes in destination, or
1309 will assume the repository has all the nodes in destination, or
1310 default-push/default if no destination is specified.
1310 default-push/default if no destination is specified.
1311
1311
1312 You can change bundle format with the -t/--type option. You can
1312 You can change bundle format with the -t/--type option. You can
1313 specify a compression, a bundle version or both using a dash
1313 specify a compression, a bundle version or both using a dash
1314 (comp-version). The available compression methods are: none, bzip2,
1314 (comp-version). The available compression methods are: none, bzip2,
1315 and gzip (by default, bundles are compressed using bzip2). The
1315 and gzip (by default, bundles are compressed using bzip2). The
1316 available formats are: v1, v2 (default to most suitable).
1316 available formats are: v1, v2 (default to most suitable).
1317
1317
1318 The bundle file can then be transferred using conventional means
1318 The bundle file can then be transferred using conventional means
1319 and applied to another repository with the unbundle or pull
1319 and applied to another repository with the unbundle or pull
1320 command. This is useful when direct push and pull are not
1320 command. This is useful when direct push and pull are not
1321 available or when exporting an entire repository is undesirable.
1321 available or when exporting an entire repository is undesirable.
1322
1322
1323 Applying bundles preserves all changeset contents including
1323 Applying bundles preserves all changeset contents including
1324 permissions, copy/rename information, and revision history.
1324 permissions, copy/rename information, and revision history.
1325
1325
1326 Returns 0 on success, 1 if no changes found.
1326 Returns 0 on success, 1 if no changes found.
1327 """
1327 """
1328 revs = None
1328 revs = None
1329 if 'rev' in opts:
1329 if 'rev' in opts:
1330 revs = scmutil.revrange(repo, opts['rev'])
1330 revs = scmutil.revrange(repo, opts['rev'])
1331
1331
1332 bundletype = opts.get('type', 'bzip2').lower()
1332 bundletype = opts.get('type', 'bzip2').lower()
1333 try:
1333 try:
1334 bcompression, cgversion, params = exchange.parsebundlespec(
1334 bcompression, cgversion, params = exchange.parsebundlespec(
1335 repo, bundletype, strict=False)
1335 repo, bundletype, strict=False)
1336 except error.UnsupportedBundleSpecification as e:
1336 except error.UnsupportedBundleSpecification as e:
1337 raise error.Abort(str(e),
1337 raise error.Abort(str(e),
1338 hint=_('see "hg help bundle" for supported '
1338 hint=_('see "hg help bundle" for supported '
1339 'values for --type'))
1339 'values for --type'))
1340
1340
1341 # Packed bundles are a pseudo bundle format for now.
1341 # Packed bundles are a pseudo bundle format for now.
1342 if cgversion == 's1':
1342 if cgversion == 's1':
1343 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1343 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1344 hint=_('use "hg debugcreatestreamclonebundle"'))
1344 hint=_('use "hg debugcreatestreamclonebundle"'))
1345
1345
1346 if opts.get('all'):
1346 if opts.get('all'):
1347 if dest:
1347 if dest:
1348 raise error.Abort(_("--all is incompatible with specifying "
1348 raise error.Abort(_("--all is incompatible with specifying "
1349 "a destination"))
1349 "a destination"))
1350 if opts.get('base'):
1351 ui.warn(_("ignoring --base because --all was specified\n"))
1350 base = ['null']
1352 base = ['null']
1351 else:
1353 else:
1352 base = scmutil.revrange(repo, opts.get('base'))
1354 base = scmutil.revrange(repo, opts.get('base'))
1353 # TODO: get desired bundlecaps from command line.
1355 # TODO: get desired bundlecaps from command line.
1354 bundlecaps = None
1356 bundlecaps = None
1355 if base:
1357 if base:
1356 if dest:
1358 if dest:
1357 raise error.Abort(_("--base is incompatible with specifying "
1359 raise error.Abort(_("--base is incompatible with specifying "
1358 "a destination"))
1360 "a destination"))
1359 common = [repo.lookup(rev) for rev in base]
1361 common = [repo.lookup(rev) for rev in base]
1360 heads = revs and map(repo.lookup, revs) or revs
1362 heads = revs and map(repo.lookup, revs) or revs
1361 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1363 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1362 common=common, bundlecaps=bundlecaps,
1364 common=common, bundlecaps=bundlecaps,
1363 version=cgversion)
1365 version=cgversion)
1364 outgoing = None
1366 outgoing = None
1365 else:
1367 else:
1366 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1368 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1367 dest, branches = hg.parseurl(dest, opts.get('branch'))
1369 dest, branches = hg.parseurl(dest, opts.get('branch'))
1368 other = hg.peer(repo, opts, dest)
1370 other = hg.peer(repo, opts, dest)
1369 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1371 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1370 heads = revs and map(repo.lookup, revs) or revs
1372 heads = revs and map(repo.lookup, revs) or revs
1371 outgoing = discovery.findcommonoutgoing(repo, other,
1373 outgoing = discovery.findcommonoutgoing(repo, other,
1372 onlyheads=heads,
1374 onlyheads=heads,
1373 force=opts.get('force'),
1375 force=opts.get('force'),
1374 portable=True)
1376 portable=True)
1375 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1377 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1376 bundlecaps, version=cgversion)
1378 bundlecaps, version=cgversion)
1377 if not cg:
1379 if not cg:
1378 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1380 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1379 return 1
1381 return 1
1380
1382
1381 if cgversion == '01': #bundle1
1383 if cgversion == '01': #bundle1
1382 if bcompression is None:
1384 if bcompression is None:
1383 bcompression = 'UN'
1385 bcompression = 'UN'
1384 bversion = 'HG10' + bcompression
1386 bversion = 'HG10' + bcompression
1385 bcompression = None
1387 bcompression = None
1386 else:
1388 else:
1387 assert cgversion == '02'
1389 assert cgversion == '02'
1388 bversion = 'HG20'
1390 bversion = 'HG20'
1389
1391
1390
1392
1391 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1393 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1392
1394
1393 @command('cat',
1395 @command('cat',
1394 [('o', 'output', '',
1396 [('o', 'output', '',
1395 _('print output to file with formatted name'), _('FORMAT')),
1397 _('print output to file with formatted name'), _('FORMAT')),
1396 ('r', 'rev', '', _('print the given revision'), _('REV')),
1398 ('r', 'rev', '', _('print the given revision'), _('REV')),
1397 ('', 'decode', None, _('apply any matching decode filter')),
1399 ('', 'decode', None, _('apply any matching decode filter')),
1398 ] + walkopts,
1400 ] + walkopts,
1399 _('[OPTION]... FILE...'),
1401 _('[OPTION]... FILE...'),
1400 inferrepo=True)
1402 inferrepo=True)
1401 def cat(ui, repo, file1, *pats, **opts):
1403 def cat(ui, repo, file1, *pats, **opts):
1402 """output the current or given revision of files
1404 """output the current or given revision of files
1403
1405
1404 Print the specified files as they were at the given revision. If
1406 Print the specified files as they were at the given revision. If
1405 no revision is given, the parent of the working directory is used.
1407 no revision is given, the parent of the working directory is used.
1406
1408
1407 Output may be to a file, in which case the name of the file is
1409 Output may be to a file, in which case the name of the file is
1408 given using a format string. The formatting rules as follows:
1410 given using a format string. The formatting rules as follows:
1409
1411
1410 :``%%``: literal "%" character
1412 :``%%``: literal "%" character
1411 :``%s``: basename of file being printed
1413 :``%s``: basename of file being printed
1412 :``%d``: dirname of file being printed, or '.' if in repository root
1414 :``%d``: dirname of file being printed, or '.' if in repository root
1413 :``%p``: root-relative path name of file being printed
1415 :``%p``: root-relative path name of file being printed
1414 :``%H``: changeset hash (40 hexadecimal digits)
1416 :``%H``: changeset hash (40 hexadecimal digits)
1415 :``%R``: changeset revision number
1417 :``%R``: changeset revision number
1416 :``%h``: short-form changeset hash (12 hexadecimal digits)
1418 :``%h``: short-form changeset hash (12 hexadecimal digits)
1417 :``%r``: zero-padded changeset revision number
1419 :``%r``: zero-padded changeset revision number
1418 :``%b``: basename of the exporting repository
1420 :``%b``: basename of the exporting repository
1419
1421
1420 Returns 0 on success.
1422 Returns 0 on success.
1421 """
1423 """
1422 ctx = scmutil.revsingle(repo, opts.get('rev'))
1424 ctx = scmutil.revsingle(repo, opts.get('rev'))
1423 m = scmutil.match(ctx, (file1,) + pats, opts)
1425 m = scmutil.match(ctx, (file1,) + pats, opts)
1424
1426
1425 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1427 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1426
1428
1427 @command('^clone',
1429 @command('^clone',
1428 [('U', 'noupdate', None, _('the clone will include an empty working '
1430 [('U', 'noupdate', None, _('the clone will include an empty working '
1429 'directory (only a repository)')),
1431 'directory (only a repository)')),
1430 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1432 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1431 _('REV')),
1433 _('REV')),
1432 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1434 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1433 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1435 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1434 ('', 'pull', None, _('use pull protocol to copy metadata')),
1436 ('', 'pull', None, _('use pull protocol to copy metadata')),
1435 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1437 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1436 ] + remoteopts,
1438 ] + remoteopts,
1437 _('[OPTION]... SOURCE [DEST]'),
1439 _('[OPTION]... SOURCE [DEST]'),
1438 norepo=True)
1440 norepo=True)
1439 def clone(ui, source, dest=None, **opts):
1441 def clone(ui, source, dest=None, **opts):
1440 """make a copy of an existing repository
1442 """make a copy of an existing repository
1441
1443
1442 Create a copy of an existing repository in a new directory.
1444 Create a copy of an existing repository in a new directory.
1443
1445
1444 If no destination directory name is specified, it defaults to the
1446 If no destination directory name is specified, it defaults to the
1445 basename of the source.
1447 basename of the source.
1446
1448
1447 The location of the source is added to the new repository's
1449 The location of the source is added to the new repository's
1448 ``.hg/hgrc`` file, as the default to be used for future pulls.
1450 ``.hg/hgrc`` file, as the default to be used for future pulls.
1449
1451
1450 Only local paths and ``ssh://`` URLs are supported as
1452 Only local paths and ``ssh://`` URLs are supported as
1451 destinations. For ``ssh://`` destinations, no working directory or
1453 destinations. For ``ssh://`` destinations, no working directory or
1452 ``.hg/hgrc`` will be created on the remote side.
1454 ``.hg/hgrc`` will be created on the remote side.
1453
1455
1454 To pull only a subset of changesets, specify one or more revisions
1456 To pull only a subset of changesets, specify one or more revisions
1455 identifiers with -r/--rev or branches with -b/--branch. The
1457 identifiers with -r/--rev or branches with -b/--branch. The
1456 resulting clone will contain only the specified changesets and
1458 resulting clone will contain only the specified changesets and
1457 their ancestors. These options (or 'clone src#rev dest') imply
1459 their ancestors. These options (or 'clone src#rev dest') imply
1458 --pull, even for local source repositories. Note that specifying a
1460 --pull, even for local source repositories. Note that specifying a
1459 tag will include the tagged changeset but not the changeset
1461 tag will include the tagged changeset but not the changeset
1460 containing the tag.
1462 containing the tag.
1461
1463
1462 If the source repository has a bookmark called '@' set, that
1464 If the source repository has a bookmark called '@' set, that
1463 revision will be checked out in the new repository by default.
1465 revision will be checked out in the new repository by default.
1464
1466
1465 To check out a particular version, use -u/--update, or
1467 To check out a particular version, use -u/--update, or
1466 -U/--noupdate to create a clone with no working directory.
1468 -U/--noupdate to create a clone with no working directory.
1467
1469
1468 .. container:: verbose
1470 .. container:: verbose
1469
1471
1470 For efficiency, hardlinks are used for cloning whenever the
1472 For efficiency, hardlinks are used for cloning whenever the
1471 source and destination are on the same filesystem (note this
1473 source and destination are on the same filesystem (note this
1472 applies only to the repository data, not to the working
1474 applies only to the repository data, not to the working
1473 directory). Some filesystems, such as AFS, implement hardlinking
1475 directory). Some filesystems, such as AFS, implement hardlinking
1474 incorrectly, but do not report errors. In these cases, use the
1476 incorrectly, but do not report errors. In these cases, use the
1475 --pull option to avoid hardlinking.
1477 --pull option to avoid hardlinking.
1476
1478
1477 In some cases, you can clone repositories and the working
1479 In some cases, you can clone repositories and the working
1478 directory using full hardlinks with ::
1480 directory using full hardlinks with ::
1479
1481
1480 $ cp -al REPO REPOCLONE
1482 $ cp -al REPO REPOCLONE
1481
1483
1482 This is the fastest way to clone, but it is not always safe. The
1484 This is the fastest way to clone, but it is not always safe. The
1483 operation is not atomic (making sure REPO is not modified during
1485 operation is not atomic (making sure REPO is not modified during
1484 the operation is up to you) and you have to make sure your
1486 the operation is up to you) and you have to make sure your
1485 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1487 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1486 so). Also, this is not compatible with certain extensions that
1488 so). Also, this is not compatible with certain extensions that
1487 place their metadata under the .hg directory, such as mq.
1489 place their metadata under the .hg directory, such as mq.
1488
1490
1489 Mercurial will update the working directory to the first applicable
1491 Mercurial will update the working directory to the first applicable
1490 revision from this list:
1492 revision from this list:
1491
1493
1492 a) null if -U or the source repository has no changesets
1494 a) null if -U or the source repository has no changesets
1493 b) if -u . and the source repository is local, the first parent of
1495 b) if -u . and the source repository is local, the first parent of
1494 the source repository's working directory
1496 the source repository's working directory
1495 c) the changeset specified with -u (if a branch name, this means the
1497 c) the changeset specified with -u (if a branch name, this means the
1496 latest head of that branch)
1498 latest head of that branch)
1497 d) the changeset specified with -r
1499 d) the changeset specified with -r
1498 e) the tipmost head specified with -b
1500 e) the tipmost head specified with -b
1499 f) the tipmost head specified with the url#branch source syntax
1501 f) the tipmost head specified with the url#branch source syntax
1500 g) the revision marked with the '@' bookmark, if present
1502 g) the revision marked with the '@' bookmark, if present
1501 h) the tipmost head of the default branch
1503 h) the tipmost head of the default branch
1502 i) tip
1504 i) tip
1503
1505
1504 Examples:
1506 Examples:
1505
1507
1506 - clone a remote repository to a new directory named hg/::
1508 - clone a remote repository to a new directory named hg/::
1507
1509
1508 hg clone http://selenic.com/hg
1510 hg clone http://selenic.com/hg
1509
1511
1510 - create a lightweight local clone::
1512 - create a lightweight local clone::
1511
1513
1512 hg clone project/ project-feature/
1514 hg clone project/ project-feature/
1513
1515
1514 - clone from an absolute path on an ssh server (note double-slash)::
1516 - clone from an absolute path on an ssh server (note double-slash)::
1515
1517
1516 hg clone ssh://user@server//home/projects/alpha/
1518 hg clone ssh://user@server//home/projects/alpha/
1517
1519
1518 - do a high-speed clone over a LAN while checking out a
1520 - do a high-speed clone over a LAN while checking out a
1519 specified version::
1521 specified version::
1520
1522
1521 hg clone --uncompressed http://server/repo -u 1.5
1523 hg clone --uncompressed http://server/repo -u 1.5
1522
1524
1523 - create a repository without changesets after a particular revision::
1525 - create a repository without changesets after a particular revision::
1524
1526
1525 hg clone -r 04e544 experimental/ good/
1527 hg clone -r 04e544 experimental/ good/
1526
1528
1527 - clone (and track) a particular named branch::
1529 - clone (and track) a particular named branch::
1528
1530
1529 hg clone http://selenic.com/hg#stable
1531 hg clone http://selenic.com/hg#stable
1530
1532
1531 See :hg:`help urls` for details on specifying URLs.
1533 See :hg:`help urls` for details on specifying URLs.
1532
1534
1533 Returns 0 on success.
1535 Returns 0 on success.
1534 """
1536 """
1535 if opts.get('noupdate') and opts.get('updaterev'):
1537 if opts.get('noupdate') and opts.get('updaterev'):
1536 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1538 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1537
1539
1538 r = hg.clone(ui, opts, source, dest,
1540 r = hg.clone(ui, opts, source, dest,
1539 pull=opts.get('pull'),
1541 pull=opts.get('pull'),
1540 stream=opts.get('uncompressed'),
1542 stream=opts.get('uncompressed'),
1541 rev=opts.get('rev'),
1543 rev=opts.get('rev'),
1542 update=opts.get('updaterev') or not opts.get('noupdate'),
1544 update=opts.get('updaterev') or not opts.get('noupdate'),
1543 branch=opts.get('branch'),
1545 branch=opts.get('branch'),
1544 shareopts=opts.get('shareopts'))
1546 shareopts=opts.get('shareopts'))
1545
1547
1546 return r is None
1548 return r is None
1547
1549
1548 @command('^commit|ci',
1550 @command('^commit|ci',
1549 [('A', 'addremove', None,
1551 [('A', 'addremove', None,
1550 _('mark new/missing files as added/removed before committing')),
1552 _('mark new/missing files as added/removed before committing')),
1551 ('', 'close-branch', None,
1553 ('', 'close-branch', None,
1552 _('mark a branch head as closed')),
1554 _('mark a branch head as closed')),
1553 ('', 'amend', None, _('amend the parent of the working directory')),
1555 ('', 'amend', None, _('amend the parent of the working directory')),
1554 ('s', 'secret', None, _('use the secret phase for committing')),
1556 ('s', 'secret', None, _('use the secret phase for committing')),
1555 ('e', 'edit', None, _('invoke editor on commit messages')),
1557 ('e', 'edit', None, _('invoke editor on commit messages')),
1556 ('i', 'interactive', None, _('use interactive mode')),
1558 ('i', 'interactive', None, _('use interactive mode')),
1557 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1559 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1558 _('[OPTION]... [FILE]...'),
1560 _('[OPTION]... [FILE]...'),
1559 inferrepo=True)
1561 inferrepo=True)
1560 def commit(ui, repo, *pats, **opts):
1562 def commit(ui, repo, *pats, **opts):
1561 """commit the specified files or all outstanding changes
1563 """commit the specified files or all outstanding changes
1562
1564
1563 Commit changes to the given files into the repository. Unlike a
1565 Commit changes to the given files into the repository. Unlike a
1564 centralized SCM, this operation is a local operation. See
1566 centralized SCM, this operation is a local operation. See
1565 :hg:`push` for a way to actively distribute your changes.
1567 :hg:`push` for a way to actively distribute your changes.
1566
1568
1567 If a list of files is omitted, all changes reported by :hg:`status`
1569 If a list of files is omitted, all changes reported by :hg:`status`
1568 will be committed.
1570 will be committed.
1569
1571
1570 If you are committing the result of a merge, do not provide any
1572 If you are committing the result of a merge, do not provide any
1571 filenames or -I/-X filters.
1573 filenames or -I/-X filters.
1572
1574
1573 If no commit message is specified, Mercurial starts your
1575 If no commit message is specified, Mercurial starts your
1574 configured editor where you can enter a message. In case your
1576 configured editor where you can enter a message. In case your
1575 commit fails, you will find a backup of your message in
1577 commit fails, you will find a backup of your message in
1576 ``.hg/last-message.txt``.
1578 ``.hg/last-message.txt``.
1577
1579
1578 The --close-branch flag can be used to mark the current branch
1580 The --close-branch flag can be used to mark the current branch
1579 head closed. When all heads of a branch are closed, the branch
1581 head closed. When all heads of a branch are closed, the branch
1580 will be considered closed and no longer listed.
1582 will be considered closed and no longer listed.
1581
1583
1582 The --amend flag can be used to amend the parent of the
1584 The --amend flag can be used to amend the parent of the
1583 working directory with a new commit that contains the changes
1585 working directory with a new commit that contains the changes
1584 in the parent in addition to those currently reported by :hg:`status`,
1586 in the parent in addition to those currently reported by :hg:`status`,
1585 if there are any. The old commit is stored in a backup bundle in
1587 if there are any. The old commit is stored in a backup bundle in
1586 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1588 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1587 on how to restore it).
1589 on how to restore it).
1588
1590
1589 Message, user and date are taken from the amended commit unless
1591 Message, user and date are taken from the amended commit unless
1590 specified. When a message isn't specified on the command line,
1592 specified. When a message isn't specified on the command line,
1591 the editor will open with the message of the amended commit.
1593 the editor will open with the message of the amended commit.
1592
1594
1593 It is not possible to amend public changesets (see :hg:`help phases`)
1595 It is not possible to amend public changesets (see :hg:`help phases`)
1594 or changesets that have children.
1596 or changesets that have children.
1595
1597
1596 See :hg:`help dates` for a list of formats valid for -d/--date.
1598 See :hg:`help dates` for a list of formats valid for -d/--date.
1597
1599
1598 Returns 0 on success, 1 if nothing changed.
1600 Returns 0 on success, 1 if nothing changed.
1599
1601
1600 .. container:: verbose
1602 .. container:: verbose
1601
1603
1602 Examples:
1604 Examples:
1603
1605
1604 - commit all files ending in .py::
1606 - commit all files ending in .py::
1605
1607
1606 hg commit --include "set:**.py"
1608 hg commit --include "set:**.py"
1607
1609
1608 - commit all non-binary files::
1610 - commit all non-binary files::
1609
1611
1610 hg commit --exclude "set:binary()"
1612 hg commit --exclude "set:binary()"
1611
1613
1612 - amend the current commit and set the date to now::
1614 - amend the current commit and set the date to now::
1613
1615
1614 hg commit --amend --date now
1616 hg commit --amend --date now
1615 """
1617 """
1616 wlock = lock = None
1618 wlock = lock = None
1617 try:
1619 try:
1618 wlock = repo.wlock()
1620 wlock = repo.wlock()
1619 lock = repo.lock()
1621 lock = repo.lock()
1620 return _docommit(ui, repo, *pats, **opts)
1622 return _docommit(ui, repo, *pats, **opts)
1621 finally:
1623 finally:
1622 release(lock, wlock)
1624 release(lock, wlock)
1623
1625
1624 def _docommit(ui, repo, *pats, **opts):
1626 def _docommit(ui, repo, *pats, **opts):
1625 if opts.get('interactive'):
1627 if opts.get('interactive'):
1626 opts.pop('interactive')
1628 opts.pop('interactive')
1627 cmdutil.dorecord(ui, repo, commit, None, False,
1629 cmdutil.dorecord(ui, repo, commit, None, False,
1628 cmdutil.recordfilter, *pats, **opts)
1630 cmdutil.recordfilter, *pats, **opts)
1629 return
1631 return
1630
1632
1631 if opts.get('subrepos'):
1633 if opts.get('subrepos'):
1632 if opts.get('amend'):
1634 if opts.get('amend'):
1633 raise error.Abort(_('cannot amend with --subrepos'))
1635 raise error.Abort(_('cannot amend with --subrepos'))
1634 # Let --subrepos on the command line override config setting.
1636 # Let --subrepos on the command line override config setting.
1635 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1637 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1636
1638
1637 cmdutil.checkunfinished(repo, commit=True)
1639 cmdutil.checkunfinished(repo, commit=True)
1638
1640
1639 branch = repo[None].branch()
1641 branch = repo[None].branch()
1640 bheads = repo.branchheads(branch)
1642 bheads = repo.branchheads(branch)
1641
1643
1642 extra = {}
1644 extra = {}
1643 if opts.get('close_branch'):
1645 if opts.get('close_branch'):
1644 extra['close'] = 1
1646 extra['close'] = 1
1645
1647
1646 if not bheads:
1648 if not bheads:
1647 raise error.Abort(_('can only close branch heads'))
1649 raise error.Abort(_('can only close branch heads'))
1648 elif opts.get('amend'):
1650 elif opts.get('amend'):
1649 if repo[None].parents()[0].p1().branch() != branch and \
1651 if repo[None].parents()[0].p1().branch() != branch and \
1650 repo[None].parents()[0].p2().branch() != branch:
1652 repo[None].parents()[0].p2().branch() != branch:
1651 raise error.Abort(_('can only close branch heads'))
1653 raise error.Abort(_('can only close branch heads'))
1652
1654
1653 if opts.get('amend'):
1655 if opts.get('amend'):
1654 if ui.configbool('ui', 'commitsubrepos'):
1656 if ui.configbool('ui', 'commitsubrepos'):
1655 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1657 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1656
1658
1657 old = repo['.']
1659 old = repo['.']
1658 if not old.mutable():
1660 if not old.mutable():
1659 raise error.Abort(_('cannot amend public changesets'))
1661 raise error.Abort(_('cannot amend public changesets'))
1660 if len(repo[None].parents()) > 1:
1662 if len(repo[None].parents()) > 1:
1661 raise error.Abort(_('cannot amend while merging'))
1663 raise error.Abort(_('cannot amend while merging'))
1662 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1664 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1663 if not allowunstable and old.children():
1665 if not allowunstable and old.children():
1664 raise error.Abort(_('cannot amend changeset with children'))
1666 raise error.Abort(_('cannot amend changeset with children'))
1665
1667
1666 newextra = extra.copy()
1668 newextra = extra.copy()
1667 newextra['branch'] = branch
1669 newextra['branch'] = branch
1668 extra = newextra
1670 extra = newextra
1669 # commitfunc is used only for temporary amend commit by cmdutil.amend
1671 # commitfunc is used only for temporary amend commit by cmdutil.amend
1670 def commitfunc(ui, repo, message, match, opts):
1672 def commitfunc(ui, repo, message, match, opts):
1671 return repo.commit(message,
1673 return repo.commit(message,
1672 opts.get('user') or old.user(),
1674 opts.get('user') or old.user(),
1673 opts.get('date') or old.date(),
1675 opts.get('date') or old.date(),
1674 match,
1676 match,
1675 extra=extra)
1677 extra=extra)
1676
1678
1677 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1679 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1678 if node == old.node():
1680 if node == old.node():
1679 ui.status(_("nothing changed\n"))
1681 ui.status(_("nothing changed\n"))
1680 return 1
1682 return 1
1681 else:
1683 else:
1682 def commitfunc(ui, repo, message, match, opts):
1684 def commitfunc(ui, repo, message, match, opts):
1683 backup = ui.backupconfig('phases', 'new-commit')
1685 backup = ui.backupconfig('phases', 'new-commit')
1684 baseui = repo.baseui
1686 baseui = repo.baseui
1685 basebackup = baseui.backupconfig('phases', 'new-commit')
1687 basebackup = baseui.backupconfig('phases', 'new-commit')
1686 try:
1688 try:
1687 if opts.get('secret'):
1689 if opts.get('secret'):
1688 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1690 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1689 # Propagate to subrepos
1691 # Propagate to subrepos
1690 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1692 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1691
1693
1692 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1694 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1693 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1695 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1694 return repo.commit(message, opts.get('user'), opts.get('date'),
1696 return repo.commit(message, opts.get('user'), opts.get('date'),
1695 match,
1697 match,
1696 editor=editor,
1698 editor=editor,
1697 extra=extra)
1699 extra=extra)
1698 finally:
1700 finally:
1699 ui.restoreconfig(backup)
1701 ui.restoreconfig(backup)
1700 repo.baseui.restoreconfig(basebackup)
1702 repo.baseui.restoreconfig(basebackup)
1701
1703
1702
1704
1703 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1705 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1704
1706
1705 if not node:
1707 if not node:
1706 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1708 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1707 if stat[3]:
1709 if stat[3]:
1708 ui.status(_("nothing changed (%d missing files, see "
1710 ui.status(_("nothing changed (%d missing files, see "
1709 "'hg status')\n") % len(stat[3]))
1711 "'hg status')\n") % len(stat[3]))
1710 else:
1712 else:
1711 ui.status(_("nothing changed\n"))
1713 ui.status(_("nothing changed\n"))
1712 return 1
1714 return 1
1713
1715
1714 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1716 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1715
1717
1716 @command('config|showconfig|debugconfig',
1718 @command('config|showconfig|debugconfig',
1717 [('u', 'untrusted', None, _('show untrusted configuration options')),
1719 [('u', 'untrusted', None, _('show untrusted configuration options')),
1718 ('e', 'edit', None, _('edit user config')),
1720 ('e', 'edit', None, _('edit user config')),
1719 ('l', 'local', None, _('edit repository config')),
1721 ('l', 'local', None, _('edit repository config')),
1720 ('g', 'global', None, _('edit global config'))],
1722 ('g', 'global', None, _('edit global config'))],
1721 _('[-u] [NAME]...'),
1723 _('[-u] [NAME]...'),
1722 optionalrepo=True)
1724 optionalrepo=True)
1723 def config(ui, repo, *values, **opts):
1725 def config(ui, repo, *values, **opts):
1724 """show combined config settings from all hgrc files
1726 """show combined config settings from all hgrc files
1725
1727
1726 With no arguments, print names and values of all config items.
1728 With no arguments, print names and values of all config items.
1727
1729
1728 With one argument of the form section.name, print just the value
1730 With one argument of the form section.name, print just the value
1729 of that config item.
1731 of that config item.
1730
1732
1731 With multiple arguments, print names and values of all config
1733 With multiple arguments, print names and values of all config
1732 items with matching section names.
1734 items with matching section names.
1733
1735
1734 With --edit, start an editor on the user-level config file. With
1736 With --edit, start an editor on the user-level config file. With
1735 --global, edit the system-wide config file. With --local, edit the
1737 --global, edit the system-wide config file. With --local, edit the
1736 repository-level config file.
1738 repository-level config file.
1737
1739
1738 With --debug, the source (filename and line number) is printed
1740 With --debug, the source (filename and line number) is printed
1739 for each config item.
1741 for each config item.
1740
1742
1741 See :hg:`help config` for more information about config files.
1743 See :hg:`help config` for more information about config files.
1742
1744
1743 Returns 0 on success, 1 if NAME does not exist.
1745 Returns 0 on success, 1 if NAME does not exist.
1744
1746
1745 """
1747 """
1746
1748
1747 if opts.get('edit') or opts.get('local') or opts.get('global'):
1749 if opts.get('edit') or opts.get('local') or opts.get('global'):
1748 if opts.get('local') and opts.get('global'):
1750 if opts.get('local') and opts.get('global'):
1749 raise error.Abort(_("can't use --local and --global together"))
1751 raise error.Abort(_("can't use --local and --global together"))
1750
1752
1751 if opts.get('local'):
1753 if opts.get('local'):
1752 if not repo:
1754 if not repo:
1753 raise error.Abort(_("can't use --local outside a repository"))
1755 raise error.Abort(_("can't use --local outside a repository"))
1754 paths = [repo.join('hgrc')]
1756 paths = [repo.join('hgrc')]
1755 elif opts.get('global'):
1757 elif opts.get('global'):
1756 paths = scmutil.systemrcpath()
1758 paths = scmutil.systemrcpath()
1757 else:
1759 else:
1758 paths = scmutil.userrcpath()
1760 paths = scmutil.userrcpath()
1759
1761
1760 for f in paths:
1762 for f in paths:
1761 if os.path.exists(f):
1763 if os.path.exists(f):
1762 break
1764 break
1763 else:
1765 else:
1764 if opts.get('global'):
1766 if opts.get('global'):
1765 samplehgrc = uimod.samplehgrcs['global']
1767 samplehgrc = uimod.samplehgrcs['global']
1766 elif opts.get('local'):
1768 elif opts.get('local'):
1767 samplehgrc = uimod.samplehgrcs['local']
1769 samplehgrc = uimod.samplehgrcs['local']
1768 else:
1770 else:
1769 samplehgrc = uimod.samplehgrcs['user']
1771 samplehgrc = uimod.samplehgrcs['user']
1770
1772
1771 f = paths[0]
1773 f = paths[0]
1772 fp = open(f, "w")
1774 fp = open(f, "w")
1773 fp.write(samplehgrc)
1775 fp.write(samplehgrc)
1774 fp.close()
1776 fp.close()
1775
1777
1776 editor = ui.geteditor()
1778 editor = ui.geteditor()
1777 ui.system("%s \"%s\"" % (editor, f),
1779 ui.system("%s \"%s\"" % (editor, f),
1778 onerr=error.Abort, errprefix=_("edit failed"))
1780 onerr=error.Abort, errprefix=_("edit failed"))
1779 return
1781 return
1780
1782
1781 for f in scmutil.rcpath():
1783 for f in scmutil.rcpath():
1782 ui.debug('read config from: %s\n' % f)
1784 ui.debug('read config from: %s\n' % f)
1783 untrusted = bool(opts.get('untrusted'))
1785 untrusted = bool(opts.get('untrusted'))
1784 if values:
1786 if values:
1785 sections = [v for v in values if '.' not in v]
1787 sections = [v for v in values if '.' not in v]
1786 items = [v for v in values if '.' in v]
1788 items = [v for v in values if '.' in v]
1787 if len(items) > 1 or items and sections:
1789 if len(items) > 1 or items and sections:
1788 raise error.Abort(_('only one config item permitted'))
1790 raise error.Abort(_('only one config item permitted'))
1789 matched = False
1791 matched = False
1790 for section, name, value in ui.walkconfig(untrusted=untrusted):
1792 for section, name, value in ui.walkconfig(untrusted=untrusted):
1791 value = str(value).replace('\n', '\\n')
1793 value = str(value).replace('\n', '\\n')
1792 sectname = section + '.' + name
1794 sectname = section + '.' + name
1793 if values:
1795 if values:
1794 for v in values:
1796 for v in values:
1795 if v == section:
1797 if v == section:
1796 ui.debug('%s: ' %
1798 ui.debug('%s: ' %
1797 ui.configsource(section, name, untrusted))
1799 ui.configsource(section, name, untrusted))
1798 ui.write('%s=%s\n' % (sectname, value))
1800 ui.write('%s=%s\n' % (sectname, value))
1799 matched = True
1801 matched = True
1800 elif v == sectname:
1802 elif v == sectname:
1801 ui.debug('%s: ' %
1803 ui.debug('%s: ' %
1802 ui.configsource(section, name, untrusted))
1804 ui.configsource(section, name, untrusted))
1803 ui.write(value, '\n')
1805 ui.write(value, '\n')
1804 matched = True
1806 matched = True
1805 else:
1807 else:
1806 ui.debug('%s: ' %
1808 ui.debug('%s: ' %
1807 ui.configsource(section, name, untrusted))
1809 ui.configsource(section, name, untrusted))
1808 ui.write('%s=%s\n' % (sectname, value))
1810 ui.write('%s=%s\n' % (sectname, value))
1809 matched = True
1811 matched = True
1810 if matched:
1812 if matched:
1811 return 0
1813 return 0
1812 return 1
1814 return 1
1813
1815
1814 @command('copy|cp',
1816 @command('copy|cp',
1815 [('A', 'after', None, _('record a copy that has already occurred')),
1817 [('A', 'after', None, _('record a copy that has already occurred')),
1816 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1818 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1817 ] + walkopts + dryrunopts,
1819 ] + walkopts + dryrunopts,
1818 _('[OPTION]... [SOURCE]... DEST'))
1820 _('[OPTION]... [SOURCE]... DEST'))
1819 def copy(ui, repo, *pats, **opts):
1821 def copy(ui, repo, *pats, **opts):
1820 """mark files as copied for the next commit
1822 """mark files as copied for the next commit
1821
1823
1822 Mark dest as having copies of source files. If dest is a
1824 Mark dest as having copies of source files. If dest is a
1823 directory, copies are put in that directory. If dest is a file,
1825 directory, copies are put in that directory. If dest is a file,
1824 the source must be a single file.
1826 the source must be a single file.
1825
1827
1826 By default, this command copies the contents of files as they
1828 By default, this command copies the contents of files as they
1827 exist in the working directory. If invoked with -A/--after, the
1829 exist in the working directory. If invoked with -A/--after, the
1828 operation is recorded, but no copying is performed.
1830 operation is recorded, but no copying is performed.
1829
1831
1830 This command takes effect with the next commit. To undo a copy
1832 This command takes effect with the next commit. To undo a copy
1831 before that, see :hg:`revert`.
1833 before that, see :hg:`revert`.
1832
1834
1833 Returns 0 on success, 1 if errors are encountered.
1835 Returns 0 on success, 1 if errors are encountered.
1834 """
1836 """
1835 wlock = repo.wlock(False)
1837 wlock = repo.wlock(False)
1836 try:
1838 try:
1837 return cmdutil.copy(ui, repo, pats, opts)
1839 return cmdutil.copy(ui, repo, pats, opts)
1838 finally:
1840 finally:
1839 wlock.release()
1841 wlock.release()
1840
1842
1841 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1843 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1842 def debugancestor(ui, repo, *args):
1844 def debugancestor(ui, repo, *args):
1843 """find the ancestor revision of two revisions in a given index"""
1845 """find the ancestor revision of two revisions in a given index"""
1844 if len(args) == 3:
1846 if len(args) == 3:
1845 index, rev1, rev2 = args
1847 index, rev1, rev2 = args
1846 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1848 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1847 lookup = r.lookup
1849 lookup = r.lookup
1848 elif len(args) == 2:
1850 elif len(args) == 2:
1849 if not repo:
1851 if not repo:
1850 raise error.Abort(_("there is no Mercurial repository here "
1852 raise error.Abort(_("there is no Mercurial repository here "
1851 "(.hg not found)"))
1853 "(.hg not found)"))
1852 rev1, rev2 = args
1854 rev1, rev2 = args
1853 r = repo.changelog
1855 r = repo.changelog
1854 lookup = repo.lookup
1856 lookup = repo.lookup
1855 else:
1857 else:
1856 raise error.Abort(_('either two or three arguments required'))
1858 raise error.Abort(_('either two or three arguments required'))
1857 a = r.ancestor(lookup(rev1), lookup(rev2))
1859 a = r.ancestor(lookup(rev1), lookup(rev2))
1858 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1860 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1859
1861
1860 @command('debugbuilddag',
1862 @command('debugbuilddag',
1861 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1863 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1862 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1864 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1863 ('n', 'new-file', None, _('add new file at each rev'))],
1865 ('n', 'new-file', None, _('add new file at each rev'))],
1864 _('[OPTION]... [TEXT]'))
1866 _('[OPTION]... [TEXT]'))
1865 def debugbuilddag(ui, repo, text=None,
1867 def debugbuilddag(ui, repo, text=None,
1866 mergeable_file=False,
1868 mergeable_file=False,
1867 overwritten_file=False,
1869 overwritten_file=False,
1868 new_file=False):
1870 new_file=False):
1869 """builds a repo with a given DAG from scratch in the current empty repo
1871 """builds a repo with a given DAG from scratch in the current empty repo
1870
1872
1871 The description of the DAG is read from stdin if not given on the
1873 The description of the DAG is read from stdin if not given on the
1872 command line.
1874 command line.
1873
1875
1874 Elements:
1876 Elements:
1875
1877
1876 - "+n" is a linear run of n nodes based on the current default parent
1878 - "+n" is a linear run of n nodes based on the current default parent
1877 - "." is a single node based on the current default parent
1879 - "." is a single node based on the current default parent
1878 - "$" resets the default parent to null (implied at the start);
1880 - "$" resets the default parent to null (implied at the start);
1879 otherwise the default parent is always the last node created
1881 otherwise the default parent is always the last node created
1880 - "<p" sets the default parent to the backref p
1882 - "<p" sets the default parent to the backref p
1881 - "*p" is a fork at parent p, which is a backref
1883 - "*p" is a fork at parent p, which is a backref
1882 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1884 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1883 - "/p2" is a merge of the preceding node and p2
1885 - "/p2" is a merge of the preceding node and p2
1884 - ":tag" defines a local tag for the preceding node
1886 - ":tag" defines a local tag for the preceding node
1885 - "@branch" sets the named branch for subsequent nodes
1887 - "@branch" sets the named branch for subsequent nodes
1886 - "#...\\n" is a comment up to the end of the line
1888 - "#...\\n" is a comment up to the end of the line
1887
1889
1888 Whitespace between the above elements is ignored.
1890 Whitespace between the above elements is ignored.
1889
1891
1890 A backref is either
1892 A backref is either
1891
1893
1892 - a number n, which references the node curr-n, where curr is the current
1894 - a number n, which references the node curr-n, where curr is the current
1893 node, or
1895 node, or
1894 - the name of a local tag you placed earlier using ":tag", or
1896 - the name of a local tag you placed earlier using ":tag", or
1895 - empty to denote the default parent.
1897 - empty to denote the default parent.
1896
1898
1897 All string valued-elements are either strictly alphanumeric, or must
1899 All string valued-elements are either strictly alphanumeric, or must
1898 be enclosed in double quotes ("..."), with "\\" as escape character.
1900 be enclosed in double quotes ("..."), with "\\" as escape character.
1899 """
1901 """
1900
1902
1901 if text is None:
1903 if text is None:
1902 ui.status(_("reading DAG from stdin\n"))
1904 ui.status(_("reading DAG from stdin\n"))
1903 text = ui.fin.read()
1905 text = ui.fin.read()
1904
1906
1905 cl = repo.changelog
1907 cl = repo.changelog
1906 if len(cl) > 0:
1908 if len(cl) > 0:
1907 raise error.Abort(_('repository is not empty'))
1909 raise error.Abort(_('repository is not empty'))
1908
1910
1909 # determine number of revs in DAG
1911 # determine number of revs in DAG
1910 total = 0
1912 total = 0
1911 for type, data in dagparser.parsedag(text):
1913 for type, data in dagparser.parsedag(text):
1912 if type == 'n':
1914 if type == 'n':
1913 total += 1
1915 total += 1
1914
1916
1915 if mergeable_file:
1917 if mergeable_file:
1916 linesperrev = 2
1918 linesperrev = 2
1917 # make a file with k lines per rev
1919 # make a file with k lines per rev
1918 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1920 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1919 initialmergedlines.append("")
1921 initialmergedlines.append("")
1920
1922
1921 tags = []
1923 tags = []
1922
1924
1923 lock = tr = None
1925 lock = tr = None
1924 try:
1926 try:
1925 lock = repo.lock()
1927 lock = repo.lock()
1926 tr = repo.transaction("builddag")
1928 tr = repo.transaction("builddag")
1927
1929
1928 at = -1
1930 at = -1
1929 atbranch = 'default'
1931 atbranch = 'default'
1930 nodeids = []
1932 nodeids = []
1931 id = 0
1933 id = 0
1932 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1934 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1933 for type, data in dagparser.parsedag(text):
1935 for type, data in dagparser.parsedag(text):
1934 if type == 'n':
1936 if type == 'n':
1935 ui.note(('node %s\n' % str(data)))
1937 ui.note(('node %s\n' % str(data)))
1936 id, ps = data
1938 id, ps = data
1937
1939
1938 files = []
1940 files = []
1939 fctxs = {}
1941 fctxs = {}
1940
1942
1941 p2 = None
1943 p2 = None
1942 if mergeable_file:
1944 if mergeable_file:
1943 fn = "mf"
1945 fn = "mf"
1944 p1 = repo[ps[0]]
1946 p1 = repo[ps[0]]
1945 if len(ps) > 1:
1947 if len(ps) > 1:
1946 p2 = repo[ps[1]]
1948 p2 = repo[ps[1]]
1947 pa = p1.ancestor(p2)
1949 pa = p1.ancestor(p2)
1948 base, local, other = [x[fn].data() for x in (pa, p1,
1950 base, local, other = [x[fn].data() for x in (pa, p1,
1949 p2)]
1951 p2)]
1950 m3 = simplemerge.Merge3Text(base, local, other)
1952 m3 = simplemerge.Merge3Text(base, local, other)
1951 ml = [l.strip() for l in m3.merge_lines()]
1953 ml = [l.strip() for l in m3.merge_lines()]
1952 ml.append("")
1954 ml.append("")
1953 elif at > 0:
1955 elif at > 0:
1954 ml = p1[fn].data().split("\n")
1956 ml = p1[fn].data().split("\n")
1955 else:
1957 else:
1956 ml = initialmergedlines
1958 ml = initialmergedlines
1957 ml[id * linesperrev] += " r%i" % id
1959 ml[id * linesperrev] += " r%i" % id
1958 mergedtext = "\n".join(ml)
1960 mergedtext = "\n".join(ml)
1959 files.append(fn)
1961 files.append(fn)
1960 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1962 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1961
1963
1962 if overwritten_file:
1964 if overwritten_file:
1963 fn = "of"
1965 fn = "of"
1964 files.append(fn)
1966 files.append(fn)
1965 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1967 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1966
1968
1967 if new_file:
1969 if new_file:
1968 fn = "nf%i" % id
1970 fn = "nf%i" % id
1969 files.append(fn)
1971 files.append(fn)
1970 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1972 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1971 if len(ps) > 1:
1973 if len(ps) > 1:
1972 if not p2:
1974 if not p2:
1973 p2 = repo[ps[1]]
1975 p2 = repo[ps[1]]
1974 for fn in p2:
1976 for fn in p2:
1975 if fn.startswith("nf"):
1977 if fn.startswith("nf"):
1976 files.append(fn)
1978 files.append(fn)
1977 fctxs[fn] = p2[fn]
1979 fctxs[fn] = p2[fn]
1978
1980
1979 def fctxfn(repo, cx, path):
1981 def fctxfn(repo, cx, path):
1980 return fctxs.get(path)
1982 return fctxs.get(path)
1981
1983
1982 if len(ps) == 0 or ps[0] < 0:
1984 if len(ps) == 0 or ps[0] < 0:
1983 pars = [None, None]
1985 pars = [None, None]
1984 elif len(ps) == 1:
1986 elif len(ps) == 1:
1985 pars = [nodeids[ps[0]], None]
1987 pars = [nodeids[ps[0]], None]
1986 else:
1988 else:
1987 pars = [nodeids[p] for p in ps]
1989 pars = [nodeids[p] for p in ps]
1988 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1990 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1989 date=(id, 0),
1991 date=(id, 0),
1990 user="debugbuilddag",
1992 user="debugbuilddag",
1991 extra={'branch': atbranch})
1993 extra={'branch': atbranch})
1992 nodeid = repo.commitctx(cx)
1994 nodeid = repo.commitctx(cx)
1993 nodeids.append(nodeid)
1995 nodeids.append(nodeid)
1994 at = id
1996 at = id
1995 elif type == 'l':
1997 elif type == 'l':
1996 id, name = data
1998 id, name = data
1997 ui.note(('tag %s\n' % name))
1999 ui.note(('tag %s\n' % name))
1998 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2000 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1999 elif type == 'a':
2001 elif type == 'a':
2000 ui.note(('branch %s\n' % data))
2002 ui.note(('branch %s\n' % data))
2001 atbranch = data
2003 atbranch = data
2002 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2004 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2003 tr.close()
2005 tr.close()
2004
2006
2005 if tags:
2007 if tags:
2006 repo.vfs.write("localtags", "".join(tags))
2008 repo.vfs.write("localtags", "".join(tags))
2007 finally:
2009 finally:
2008 ui.progress(_('building'), None)
2010 ui.progress(_('building'), None)
2009 release(tr, lock)
2011 release(tr, lock)
2010
2012
2011 @command('debugbundle',
2013 @command('debugbundle',
2012 [('a', 'all', None, _('show all details'))],
2014 [('a', 'all', None, _('show all details'))],
2013 _('FILE'),
2015 _('FILE'),
2014 norepo=True)
2016 norepo=True)
2015 def debugbundle(ui, bundlepath, all=None, **opts):
2017 def debugbundle(ui, bundlepath, all=None, **opts):
2016 """lists the contents of a bundle"""
2018 """lists the contents of a bundle"""
2017 f = hg.openpath(ui, bundlepath)
2019 f = hg.openpath(ui, bundlepath)
2018 try:
2020 try:
2019 gen = exchange.readbundle(ui, f, bundlepath)
2021 gen = exchange.readbundle(ui, f, bundlepath)
2020 if isinstance(gen, bundle2.unbundle20):
2022 if isinstance(gen, bundle2.unbundle20):
2021 return _debugbundle2(ui, gen, all=all, **opts)
2023 return _debugbundle2(ui, gen, all=all, **opts)
2022 if all:
2024 if all:
2023 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2025 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2024
2026
2025 def showchunks(named):
2027 def showchunks(named):
2026 ui.write("\n%s\n" % named)
2028 ui.write("\n%s\n" % named)
2027 chain = None
2029 chain = None
2028 while True:
2030 while True:
2029 chunkdata = gen.deltachunk(chain)
2031 chunkdata = gen.deltachunk(chain)
2030 if not chunkdata:
2032 if not chunkdata:
2031 break
2033 break
2032 node = chunkdata['node']
2034 node = chunkdata['node']
2033 p1 = chunkdata['p1']
2035 p1 = chunkdata['p1']
2034 p2 = chunkdata['p2']
2036 p2 = chunkdata['p2']
2035 cs = chunkdata['cs']
2037 cs = chunkdata['cs']
2036 deltabase = chunkdata['deltabase']
2038 deltabase = chunkdata['deltabase']
2037 delta = chunkdata['delta']
2039 delta = chunkdata['delta']
2038 ui.write("%s %s %s %s %s %s\n" %
2040 ui.write("%s %s %s %s %s %s\n" %
2039 (hex(node), hex(p1), hex(p2),
2041 (hex(node), hex(p1), hex(p2),
2040 hex(cs), hex(deltabase), len(delta)))
2042 hex(cs), hex(deltabase), len(delta)))
2041 chain = node
2043 chain = node
2042
2044
2043 chunkdata = gen.changelogheader()
2045 chunkdata = gen.changelogheader()
2044 showchunks("changelog")
2046 showchunks("changelog")
2045 chunkdata = gen.manifestheader()
2047 chunkdata = gen.manifestheader()
2046 showchunks("manifest")
2048 showchunks("manifest")
2047 while True:
2049 while True:
2048 chunkdata = gen.filelogheader()
2050 chunkdata = gen.filelogheader()
2049 if not chunkdata:
2051 if not chunkdata:
2050 break
2052 break
2051 fname = chunkdata['filename']
2053 fname = chunkdata['filename']
2052 showchunks(fname)
2054 showchunks(fname)
2053 else:
2055 else:
2054 if isinstance(gen, bundle2.unbundle20):
2056 if isinstance(gen, bundle2.unbundle20):
2055 raise error.Abort(_('use debugbundle2 for this file'))
2057 raise error.Abort(_('use debugbundle2 for this file'))
2056 chunkdata = gen.changelogheader()
2058 chunkdata = gen.changelogheader()
2057 chain = None
2059 chain = None
2058 while True:
2060 while True:
2059 chunkdata = gen.deltachunk(chain)
2061 chunkdata = gen.deltachunk(chain)
2060 if not chunkdata:
2062 if not chunkdata:
2061 break
2063 break
2062 node = chunkdata['node']
2064 node = chunkdata['node']
2063 ui.write("%s\n" % hex(node))
2065 ui.write("%s\n" % hex(node))
2064 chain = node
2066 chain = node
2065 finally:
2067 finally:
2066 f.close()
2068 f.close()
2067
2069
2068 def _debugbundle2(ui, gen, **opts):
2070 def _debugbundle2(ui, gen, **opts):
2069 """lists the contents of a bundle2"""
2071 """lists the contents of a bundle2"""
2070 if not isinstance(gen, bundle2.unbundle20):
2072 if not isinstance(gen, bundle2.unbundle20):
2071 raise error.Abort(_('not a bundle2 file'))
2073 raise error.Abort(_('not a bundle2 file'))
2072 ui.write(('Stream params: %s\n' % repr(gen.params)))
2074 ui.write(('Stream params: %s\n' % repr(gen.params)))
2073 for part in gen.iterparts():
2075 for part in gen.iterparts():
2074 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2076 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2075 if part.type == 'changegroup':
2077 if part.type == 'changegroup':
2076 version = part.params.get('version', '01')
2078 version = part.params.get('version', '01')
2077 cg = changegroup.packermap[version][1](part, 'UN')
2079 cg = changegroup.packermap[version][1](part, 'UN')
2078 chunkdata = cg.changelogheader()
2080 chunkdata = cg.changelogheader()
2079 chain = None
2081 chain = None
2080 while True:
2082 while True:
2081 chunkdata = cg.deltachunk(chain)
2083 chunkdata = cg.deltachunk(chain)
2082 if not chunkdata:
2084 if not chunkdata:
2083 break
2085 break
2084 node = chunkdata['node']
2086 node = chunkdata['node']
2085 ui.write(" %s\n" % hex(node))
2087 ui.write(" %s\n" % hex(node))
2086 chain = node
2088 chain = node
2087
2089
2088 @command('debugcreatestreamclonebundle', [], 'FILE')
2090 @command('debugcreatestreamclonebundle', [], 'FILE')
2089 def debugcreatestreamclonebundle(ui, repo, fname):
2091 def debugcreatestreamclonebundle(ui, repo, fname):
2090 """create a stream clone bundle file
2092 """create a stream clone bundle file
2091
2093
2092 Stream bundles are special bundles that are essentially archives of
2094 Stream bundles are special bundles that are essentially archives of
2093 revlog files. They are commonly used for cloning very quickly.
2095 revlog files. They are commonly used for cloning very quickly.
2094 """
2096 """
2095 requirements, gen = streamclone.generatebundlev1(repo)
2097 requirements, gen = streamclone.generatebundlev1(repo)
2096 changegroup.writechunks(ui, gen, fname)
2098 changegroup.writechunks(ui, gen, fname)
2097
2099
2098 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2100 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2099
2101
2100 @command('debugapplystreamclonebundle', [], 'FILE')
2102 @command('debugapplystreamclonebundle', [], 'FILE')
2101 def debugapplystreamclonebundle(ui, repo, fname):
2103 def debugapplystreamclonebundle(ui, repo, fname):
2102 """apply a stream clone bundle file"""
2104 """apply a stream clone bundle file"""
2103 f = hg.openpath(ui, fname)
2105 f = hg.openpath(ui, fname)
2104 gen = exchange.readbundle(ui, f, fname)
2106 gen = exchange.readbundle(ui, f, fname)
2105 gen.apply(repo)
2107 gen.apply(repo)
2106
2108
2107 @command('debugcheckstate', [], '')
2109 @command('debugcheckstate', [], '')
2108 def debugcheckstate(ui, repo):
2110 def debugcheckstate(ui, repo):
2109 """validate the correctness of the current dirstate"""
2111 """validate the correctness of the current dirstate"""
2110 parent1, parent2 = repo.dirstate.parents()
2112 parent1, parent2 = repo.dirstate.parents()
2111 m1 = repo[parent1].manifest()
2113 m1 = repo[parent1].manifest()
2112 m2 = repo[parent2].manifest()
2114 m2 = repo[parent2].manifest()
2113 errors = 0
2115 errors = 0
2114 for f in repo.dirstate:
2116 for f in repo.dirstate:
2115 state = repo.dirstate[f]
2117 state = repo.dirstate[f]
2116 if state in "nr" and f not in m1:
2118 if state in "nr" and f not in m1:
2117 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2119 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2118 errors += 1
2120 errors += 1
2119 if state in "a" and f in m1:
2121 if state in "a" and f in m1:
2120 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2122 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2121 errors += 1
2123 errors += 1
2122 if state in "m" and f not in m1 and f not in m2:
2124 if state in "m" and f not in m1 and f not in m2:
2123 ui.warn(_("%s in state %s, but not in either manifest\n") %
2125 ui.warn(_("%s in state %s, but not in either manifest\n") %
2124 (f, state))
2126 (f, state))
2125 errors += 1
2127 errors += 1
2126 for f in m1:
2128 for f in m1:
2127 state = repo.dirstate[f]
2129 state = repo.dirstate[f]
2128 if state not in "nrm":
2130 if state not in "nrm":
2129 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2131 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2130 errors += 1
2132 errors += 1
2131 if errors:
2133 if errors:
2132 error = _(".hg/dirstate inconsistent with current parent's manifest")
2134 error = _(".hg/dirstate inconsistent with current parent's manifest")
2133 raise error.Abort(error)
2135 raise error.Abort(error)
2134
2136
2135 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2137 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2136 def debugcommands(ui, cmd='', *args):
2138 def debugcommands(ui, cmd='', *args):
2137 """list all available commands and options"""
2139 """list all available commands and options"""
2138 for cmd, vals in sorted(table.iteritems()):
2140 for cmd, vals in sorted(table.iteritems()):
2139 cmd = cmd.split('|')[0].strip('^')
2141 cmd = cmd.split('|')[0].strip('^')
2140 opts = ', '.join([i[1] for i in vals[1]])
2142 opts = ', '.join([i[1] for i in vals[1]])
2141 ui.write('%s: %s\n' % (cmd, opts))
2143 ui.write('%s: %s\n' % (cmd, opts))
2142
2144
2143 @command('debugcomplete',
2145 @command('debugcomplete',
2144 [('o', 'options', None, _('show the command options'))],
2146 [('o', 'options', None, _('show the command options'))],
2145 _('[-o] CMD'),
2147 _('[-o] CMD'),
2146 norepo=True)
2148 norepo=True)
2147 def debugcomplete(ui, cmd='', **opts):
2149 def debugcomplete(ui, cmd='', **opts):
2148 """returns the completion list associated with the given command"""
2150 """returns the completion list associated with the given command"""
2149
2151
2150 if opts.get('options'):
2152 if opts.get('options'):
2151 options = []
2153 options = []
2152 otables = [globalopts]
2154 otables = [globalopts]
2153 if cmd:
2155 if cmd:
2154 aliases, entry = cmdutil.findcmd(cmd, table, False)
2156 aliases, entry = cmdutil.findcmd(cmd, table, False)
2155 otables.append(entry[1])
2157 otables.append(entry[1])
2156 for t in otables:
2158 for t in otables:
2157 for o in t:
2159 for o in t:
2158 if "(DEPRECATED)" in o[3]:
2160 if "(DEPRECATED)" in o[3]:
2159 continue
2161 continue
2160 if o[0]:
2162 if o[0]:
2161 options.append('-%s' % o[0])
2163 options.append('-%s' % o[0])
2162 options.append('--%s' % o[1])
2164 options.append('--%s' % o[1])
2163 ui.write("%s\n" % "\n".join(options))
2165 ui.write("%s\n" % "\n".join(options))
2164 return
2166 return
2165
2167
2166 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2168 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2167 if ui.verbose:
2169 if ui.verbose:
2168 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2170 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2169 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2171 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2170
2172
2171 @command('debugdag',
2173 @command('debugdag',
2172 [('t', 'tags', None, _('use tags as labels')),
2174 [('t', 'tags', None, _('use tags as labels')),
2173 ('b', 'branches', None, _('annotate with branch names')),
2175 ('b', 'branches', None, _('annotate with branch names')),
2174 ('', 'dots', None, _('use dots for runs')),
2176 ('', 'dots', None, _('use dots for runs')),
2175 ('s', 'spaces', None, _('separate elements by spaces'))],
2177 ('s', 'spaces', None, _('separate elements by spaces'))],
2176 _('[OPTION]... [FILE [REV]...]'),
2178 _('[OPTION]... [FILE [REV]...]'),
2177 optionalrepo=True)
2179 optionalrepo=True)
2178 def debugdag(ui, repo, file_=None, *revs, **opts):
2180 def debugdag(ui, repo, file_=None, *revs, **opts):
2179 """format the changelog or an index DAG as a concise textual description
2181 """format the changelog or an index DAG as a concise textual description
2180
2182
2181 If you pass a revlog index, the revlog's DAG is emitted. If you list
2183 If you pass a revlog index, the revlog's DAG is emitted. If you list
2182 revision numbers, they get labeled in the output as rN.
2184 revision numbers, they get labeled in the output as rN.
2183
2185
2184 Otherwise, the changelog DAG of the current repo is emitted.
2186 Otherwise, the changelog DAG of the current repo is emitted.
2185 """
2187 """
2186 spaces = opts.get('spaces')
2188 spaces = opts.get('spaces')
2187 dots = opts.get('dots')
2189 dots = opts.get('dots')
2188 if file_:
2190 if file_:
2189 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2191 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2190 revs = set((int(r) for r in revs))
2192 revs = set((int(r) for r in revs))
2191 def events():
2193 def events():
2192 for r in rlog:
2194 for r in rlog:
2193 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2195 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2194 if p != -1))
2196 if p != -1))
2195 if r in revs:
2197 if r in revs:
2196 yield 'l', (r, "r%i" % r)
2198 yield 'l', (r, "r%i" % r)
2197 elif repo:
2199 elif repo:
2198 cl = repo.changelog
2200 cl = repo.changelog
2199 tags = opts.get('tags')
2201 tags = opts.get('tags')
2200 branches = opts.get('branches')
2202 branches = opts.get('branches')
2201 if tags:
2203 if tags:
2202 labels = {}
2204 labels = {}
2203 for l, n in repo.tags().items():
2205 for l, n in repo.tags().items():
2204 labels.setdefault(cl.rev(n), []).append(l)
2206 labels.setdefault(cl.rev(n), []).append(l)
2205 def events():
2207 def events():
2206 b = "default"
2208 b = "default"
2207 for r in cl:
2209 for r in cl:
2208 if branches:
2210 if branches:
2209 newb = cl.read(cl.node(r))[5]['branch']
2211 newb = cl.read(cl.node(r))[5]['branch']
2210 if newb != b:
2212 if newb != b:
2211 yield 'a', newb
2213 yield 'a', newb
2212 b = newb
2214 b = newb
2213 yield 'n', (r, list(p for p in cl.parentrevs(r)
2215 yield 'n', (r, list(p for p in cl.parentrevs(r)
2214 if p != -1))
2216 if p != -1))
2215 if tags:
2217 if tags:
2216 ls = labels.get(r)
2218 ls = labels.get(r)
2217 if ls:
2219 if ls:
2218 for l in ls:
2220 for l in ls:
2219 yield 'l', (r, l)
2221 yield 'l', (r, l)
2220 else:
2222 else:
2221 raise error.Abort(_('need repo for changelog dag'))
2223 raise error.Abort(_('need repo for changelog dag'))
2222
2224
2223 for line in dagparser.dagtextlines(events(),
2225 for line in dagparser.dagtextlines(events(),
2224 addspaces=spaces,
2226 addspaces=spaces,
2225 wraplabels=True,
2227 wraplabels=True,
2226 wrapannotations=True,
2228 wrapannotations=True,
2227 wrapnonlinear=dots,
2229 wrapnonlinear=dots,
2228 usedots=dots,
2230 usedots=dots,
2229 maxlinewidth=70):
2231 maxlinewidth=70):
2230 ui.write(line)
2232 ui.write(line)
2231 ui.write("\n")
2233 ui.write("\n")
2232
2234
2233 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2235 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2234 def debugdata(ui, repo, file_, rev=None, **opts):
2236 def debugdata(ui, repo, file_, rev=None, **opts):
2235 """dump the contents of a data file revision"""
2237 """dump the contents of a data file revision"""
2236 if opts.get('changelog') or opts.get('manifest'):
2238 if opts.get('changelog') or opts.get('manifest'):
2237 file_, rev = None, file_
2239 file_, rev = None, file_
2238 elif rev is None:
2240 elif rev is None:
2239 raise error.CommandError('debugdata', _('invalid arguments'))
2241 raise error.CommandError('debugdata', _('invalid arguments'))
2240 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2242 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2241 try:
2243 try:
2242 ui.write(r.revision(r.lookup(rev)))
2244 ui.write(r.revision(r.lookup(rev)))
2243 except KeyError:
2245 except KeyError:
2244 raise error.Abort(_('invalid revision identifier %s') % rev)
2246 raise error.Abort(_('invalid revision identifier %s') % rev)
2245
2247
2246 @command('debugdate',
2248 @command('debugdate',
2247 [('e', 'extended', None, _('try extended date formats'))],
2249 [('e', 'extended', None, _('try extended date formats'))],
2248 _('[-e] DATE [RANGE]'),
2250 _('[-e] DATE [RANGE]'),
2249 norepo=True, optionalrepo=True)
2251 norepo=True, optionalrepo=True)
2250 def debugdate(ui, date, range=None, **opts):
2252 def debugdate(ui, date, range=None, **opts):
2251 """parse and display a date"""
2253 """parse and display a date"""
2252 if opts["extended"]:
2254 if opts["extended"]:
2253 d = util.parsedate(date, util.extendeddateformats)
2255 d = util.parsedate(date, util.extendeddateformats)
2254 else:
2256 else:
2255 d = util.parsedate(date)
2257 d = util.parsedate(date)
2256 ui.write(("internal: %s %s\n") % d)
2258 ui.write(("internal: %s %s\n") % d)
2257 ui.write(("standard: %s\n") % util.datestr(d))
2259 ui.write(("standard: %s\n") % util.datestr(d))
2258 if range:
2260 if range:
2259 m = util.matchdate(range)
2261 m = util.matchdate(range)
2260 ui.write(("match: %s\n") % m(d[0]))
2262 ui.write(("match: %s\n") % m(d[0]))
2261
2263
2262 @command('debugdiscovery',
2264 @command('debugdiscovery',
2263 [('', 'old', None, _('use old-style discovery')),
2265 [('', 'old', None, _('use old-style discovery')),
2264 ('', 'nonheads', None,
2266 ('', 'nonheads', None,
2265 _('use old-style discovery with non-heads included')),
2267 _('use old-style discovery with non-heads included')),
2266 ] + remoteopts,
2268 ] + remoteopts,
2267 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2269 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2268 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2270 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2269 """runs the changeset discovery protocol in isolation"""
2271 """runs the changeset discovery protocol in isolation"""
2270 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2272 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2271 opts.get('branch'))
2273 opts.get('branch'))
2272 remote = hg.peer(repo, opts, remoteurl)
2274 remote = hg.peer(repo, opts, remoteurl)
2273 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2275 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2274
2276
2275 # make sure tests are repeatable
2277 # make sure tests are repeatable
2276 random.seed(12323)
2278 random.seed(12323)
2277
2279
2278 def doit(localheads, remoteheads, remote=remote):
2280 def doit(localheads, remoteheads, remote=remote):
2279 if opts.get('old'):
2281 if opts.get('old'):
2280 if localheads:
2282 if localheads:
2281 raise error.Abort('cannot use localheads with old style '
2283 raise error.Abort('cannot use localheads with old style '
2282 'discovery')
2284 'discovery')
2283 if not util.safehasattr(remote, 'branches'):
2285 if not util.safehasattr(remote, 'branches'):
2284 # enable in-client legacy support
2286 # enable in-client legacy support
2285 remote = localrepo.locallegacypeer(remote.local())
2287 remote = localrepo.locallegacypeer(remote.local())
2286 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2288 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2287 force=True)
2289 force=True)
2288 common = set(common)
2290 common = set(common)
2289 if not opts.get('nonheads'):
2291 if not opts.get('nonheads'):
2290 ui.write(("unpruned common: %s\n") %
2292 ui.write(("unpruned common: %s\n") %
2291 " ".join(sorted(short(n) for n in common)))
2293 " ".join(sorted(short(n) for n in common)))
2292 dag = dagutil.revlogdag(repo.changelog)
2294 dag = dagutil.revlogdag(repo.changelog)
2293 all = dag.ancestorset(dag.internalizeall(common))
2295 all = dag.ancestorset(dag.internalizeall(common))
2294 common = dag.externalizeall(dag.headsetofconnecteds(all))
2296 common = dag.externalizeall(dag.headsetofconnecteds(all))
2295 else:
2297 else:
2296 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2298 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2297 common = set(common)
2299 common = set(common)
2298 rheads = set(hds)
2300 rheads = set(hds)
2299 lheads = set(repo.heads())
2301 lheads = set(repo.heads())
2300 ui.write(("common heads: %s\n") %
2302 ui.write(("common heads: %s\n") %
2301 " ".join(sorted(short(n) for n in common)))
2303 " ".join(sorted(short(n) for n in common)))
2302 if lheads <= common:
2304 if lheads <= common:
2303 ui.write(("local is subset\n"))
2305 ui.write(("local is subset\n"))
2304 elif rheads <= common:
2306 elif rheads <= common:
2305 ui.write(("remote is subset\n"))
2307 ui.write(("remote is subset\n"))
2306
2308
2307 serverlogs = opts.get('serverlog')
2309 serverlogs = opts.get('serverlog')
2308 if serverlogs:
2310 if serverlogs:
2309 for filename in serverlogs:
2311 for filename in serverlogs:
2310 logfile = open(filename, 'r')
2312 logfile = open(filename, 'r')
2311 try:
2313 try:
2312 line = logfile.readline()
2314 line = logfile.readline()
2313 while line:
2315 while line:
2314 parts = line.strip().split(';')
2316 parts = line.strip().split(';')
2315 op = parts[1]
2317 op = parts[1]
2316 if op == 'cg':
2318 if op == 'cg':
2317 pass
2319 pass
2318 elif op == 'cgss':
2320 elif op == 'cgss':
2319 doit(parts[2].split(' '), parts[3].split(' '))
2321 doit(parts[2].split(' '), parts[3].split(' '))
2320 elif op == 'unb':
2322 elif op == 'unb':
2321 doit(parts[3].split(' '), parts[2].split(' '))
2323 doit(parts[3].split(' '), parts[2].split(' '))
2322 line = logfile.readline()
2324 line = logfile.readline()
2323 finally:
2325 finally:
2324 logfile.close()
2326 logfile.close()
2325
2327
2326 else:
2328 else:
2327 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2329 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2328 opts.get('remote_head'))
2330 opts.get('remote_head'))
2329 localrevs = opts.get('local_head')
2331 localrevs = opts.get('local_head')
2330 doit(localrevs, remoterevs)
2332 doit(localrevs, remoterevs)
2331
2333
2332 @command('debugextensions', formatteropts, [], norepo=True)
2334 @command('debugextensions', formatteropts, [], norepo=True)
2333 def debugextensions(ui, **opts):
2335 def debugextensions(ui, **opts):
2334 '''show information about active extensions'''
2336 '''show information about active extensions'''
2335 exts = extensions.extensions(ui)
2337 exts = extensions.extensions(ui)
2336 fm = ui.formatter('debugextensions', opts)
2338 fm = ui.formatter('debugextensions', opts)
2337 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2339 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2338 extsource = extmod.__file__
2340 extsource = extmod.__file__
2339 exttestedwith = getattr(extmod, 'testedwith', None)
2341 exttestedwith = getattr(extmod, 'testedwith', None)
2340 if exttestedwith is not None:
2342 if exttestedwith is not None:
2341 exttestedwith = exttestedwith.split()
2343 exttestedwith = exttestedwith.split()
2342 extbuglink = getattr(extmod, 'buglink', None)
2344 extbuglink = getattr(extmod, 'buglink', None)
2343
2345
2344 fm.startitem()
2346 fm.startitem()
2345
2347
2346 if ui.quiet or ui.verbose:
2348 if ui.quiet or ui.verbose:
2347 fm.write('name', '%s\n', extname)
2349 fm.write('name', '%s\n', extname)
2348 else:
2350 else:
2349 fm.write('name', '%s', extname)
2351 fm.write('name', '%s', extname)
2350 if not exttestedwith:
2352 if not exttestedwith:
2351 fm.plain(_(' (untested!)\n'))
2353 fm.plain(_(' (untested!)\n'))
2352 else:
2354 else:
2353 if exttestedwith == ['internal'] or \
2355 if exttestedwith == ['internal'] or \
2354 util.version() in exttestedwith:
2356 util.version() in exttestedwith:
2355 fm.plain('\n')
2357 fm.plain('\n')
2356 else:
2358 else:
2357 lasttestedversion = exttestedwith[-1]
2359 lasttestedversion = exttestedwith[-1]
2358 fm.plain(' (%s!)\n' % lasttestedversion)
2360 fm.plain(' (%s!)\n' % lasttestedversion)
2359
2361
2360 fm.condwrite(ui.verbose and extsource, 'source',
2362 fm.condwrite(ui.verbose and extsource, 'source',
2361 _(' location: %s\n'), extsource or "")
2363 _(' location: %s\n'), extsource or "")
2362
2364
2363 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2365 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2364 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2366 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2365
2367
2366 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2368 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2367 _(' bug reporting: %s\n'), extbuglink or "")
2369 _(' bug reporting: %s\n'), extbuglink or "")
2368
2370
2369 fm.end()
2371 fm.end()
2370
2372
2371 @command('debugfileset',
2373 @command('debugfileset',
2372 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2374 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2373 _('[-r REV] FILESPEC'))
2375 _('[-r REV] FILESPEC'))
2374 def debugfileset(ui, repo, expr, **opts):
2376 def debugfileset(ui, repo, expr, **opts):
2375 '''parse and apply a fileset specification'''
2377 '''parse and apply a fileset specification'''
2376 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2378 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2377 if ui.verbose:
2379 if ui.verbose:
2378 tree = fileset.parse(expr)
2380 tree = fileset.parse(expr)
2379 ui.note(fileset.prettyformat(tree), "\n")
2381 ui.note(fileset.prettyformat(tree), "\n")
2380
2382
2381 for f in ctx.getfileset(expr):
2383 for f in ctx.getfileset(expr):
2382 ui.write("%s\n" % f)
2384 ui.write("%s\n" % f)
2383
2385
2384 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2386 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2385 def debugfsinfo(ui, path="."):
2387 def debugfsinfo(ui, path="."):
2386 """show information detected about current filesystem"""
2388 """show information detected about current filesystem"""
2387 util.writefile('.debugfsinfo', '')
2389 util.writefile('.debugfsinfo', '')
2388 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2390 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2389 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2391 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2390 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2392 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2391 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2393 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2392 and 'yes' or 'no'))
2394 and 'yes' or 'no'))
2393 os.unlink('.debugfsinfo')
2395 os.unlink('.debugfsinfo')
2394
2396
2395 @command('debuggetbundle',
2397 @command('debuggetbundle',
2396 [('H', 'head', [], _('id of head node'), _('ID')),
2398 [('H', 'head', [], _('id of head node'), _('ID')),
2397 ('C', 'common', [], _('id of common node'), _('ID')),
2399 ('C', 'common', [], _('id of common node'), _('ID')),
2398 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2400 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2399 _('REPO FILE [-H|-C ID]...'),
2401 _('REPO FILE [-H|-C ID]...'),
2400 norepo=True)
2402 norepo=True)
2401 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2403 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2402 """retrieves a bundle from a repo
2404 """retrieves a bundle from a repo
2403
2405
2404 Every ID must be a full-length hex node id string. Saves the bundle to the
2406 Every ID must be a full-length hex node id string. Saves the bundle to the
2405 given file.
2407 given file.
2406 """
2408 """
2407 repo = hg.peer(ui, opts, repopath)
2409 repo = hg.peer(ui, opts, repopath)
2408 if not repo.capable('getbundle'):
2410 if not repo.capable('getbundle'):
2409 raise error.Abort("getbundle() not supported by target repository")
2411 raise error.Abort("getbundle() not supported by target repository")
2410 args = {}
2412 args = {}
2411 if common:
2413 if common:
2412 args['common'] = [bin(s) for s in common]
2414 args['common'] = [bin(s) for s in common]
2413 if head:
2415 if head:
2414 args['heads'] = [bin(s) for s in head]
2416 args['heads'] = [bin(s) for s in head]
2415 # TODO: get desired bundlecaps from command line.
2417 # TODO: get desired bundlecaps from command line.
2416 args['bundlecaps'] = None
2418 args['bundlecaps'] = None
2417 bundle = repo.getbundle('debug', **args)
2419 bundle = repo.getbundle('debug', **args)
2418
2420
2419 bundletype = opts.get('type', 'bzip2').lower()
2421 bundletype = opts.get('type', 'bzip2').lower()
2420 btypes = {'none': 'HG10UN',
2422 btypes = {'none': 'HG10UN',
2421 'bzip2': 'HG10BZ',
2423 'bzip2': 'HG10BZ',
2422 'gzip': 'HG10GZ',
2424 'gzip': 'HG10GZ',
2423 'bundle2': 'HG20'}
2425 'bundle2': 'HG20'}
2424 bundletype = btypes.get(bundletype)
2426 bundletype = btypes.get(bundletype)
2425 if bundletype not in changegroup.bundletypes:
2427 if bundletype not in changegroup.bundletypes:
2426 raise error.Abort(_('unknown bundle type specified with --type'))
2428 raise error.Abort(_('unknown bundle type specified with --type'))
2427 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2429 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2428
2430
2429 @command('debugignore', [], '')
2431 @command('debugignore', [], '')
2430 def debugignore(ui, repo, *values, **opts):
2432 def debugignore(ui, repo, *values, **opts):
2431 """display the combined ignore pattern"""
2433 """display the combined ignore pattern"""
2432 ignore = repo.dirstate._ignore
2434 ignore = repo.dirstate._ignore
2433 includepat = getattr(ignore, 'includepat', None)
2435 includepat = getattr(ignore, 'includepat', None)
2434 if includepat is not None:
2436 if includepat is not None:
2435 ui.write("%s\n" % includepat)
2437 ui.write("%s\n" % includepat)
2436 else:
2438 else:
2437 raise error.Abort(_("no ignore patterns found"))
2439 raise error.Abort(_("no ignore patterns found"))
2438
2440
2439 @command('debugindex', debugrevlogopts +
2441 @command('debugindex', debugrevlogopts +
2440 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2442 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2441 _('[-f FORMAT] -c|-m|FILE'),
2443 _('[-f FORMAT] -c|-m|FILE'),
2442 optionalrepo=True)
2444 optionalrepo=True)
2443 def debugindex(ui, repo, file_=None, **opts):
2445 def debugindex(ui, repo, file_=None, **opts):
2444 """dump the contents of an index file"""
2446 """dump the contents of an index file"""
2445 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2447 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2446 format = opts.get('format', 0)
2448 format = opts.get('format', 0)
2447 if format not in (0, 1):
2449 if format not in (0, 1):
2448 raise error.Abort(_("unknown format %d") % format)
2450 raise error.Abort(_("unknown format %d") % format)
2449
2451
2450 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2452 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2451 if generaldelta:
2453 if generaldelta:
2452 basehdr = ' delta'
2454 basehdr = ' delta'
2453 else:
2455 else:
2454 basehdr = ' base'
2456 basehdr = ' base'
2455
2457
2456 if ui.debugflag:
2458 if ui.debugflag:
2457 shortfn = hex
2459 shortfn = hex
2458 else:
2460 else:
2459 shortfn = short
2461 shortfn = short
2460
2462
2461 # There might not be anything in r, so have a sane default
2463 # There might not be anything in r, so have a sane default
2462 idlen = 12
2464 idlen = 12
2463 for i in r:
2465 for i in r:
2464 idlen = len(shortfn(r.node(i)))
2466 idlen = len(shortfn(r.node(i)))
2465 break
2467 break
2466
2468
2467 if format == 0:
2469 if format == 0:
2468 ui.write(" rev offset length " + basehdr + " linkrev"
2470 ui.write(" rev offset length " + basehdr + " linkrev"
2469 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2471 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2470 elif format == 1:
2472 elif format == 1:
2471 ui.write(" rev flag offset length"
2473 ui.write(" rev flag offset length"
2472 " size " + basehdr + " link p1 p2"
2474 " size " + basehdr + " link p1 p2"
2473 " %s\n" % "nodeid".rjust(idlen))
2475 " %s\n" % "nodeid".rjust(idlen))
2474
2476
2475 for i in r:
2477 for i in r:
2476 node = r.node(i)
2478 node = r.node(i)
2477 if generaldelta:
2479 if generaldelta:
2478 base = r.deltaparent(i)
2480 base = r.deltaparent(i)
2479 else:
2481 else:
2480 base = r.chainbase(i)
2482 base = r.chainbase(i)
2481 if format == 0:
2483 if format == 0:
2482 try:
2484 try:
2483 pp = r.parents(node)
2485 pp = r.parents(node)
2484 except Exception:
2486 except Exception:
2485 pp = [nullid, nullid]
2487 pp = [nullid, nullid]
2486 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2488 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2487 i, r.start(i), r.length(i), base, r.linkrev(i),
2489 i, r.start(i), r.length(i), base, r.linkrev(i),
2488 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2490 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2489 elif format == 1:
2491 elif format == 1:
2490 pr = r.parentrevs(i)
2492 pr = r.parentrevs(i)
2491 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2493 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2492 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2494 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2493 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2495 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2494
2496
2495 @command('debugindexdot', debugrevlogopts,
2497 @command('debugindexdot', debugrevlogopts,
2496 _('-c|-m|FILE'), optionalrepo=True)
2498 _('-c|-m|FILE'), optionalrepo=True)
2497 def debugindexdot(ui, repo, file_=None, **opts):
2499 def debugindexdot(ui, repo, file_=None, **opts):
2498 """dump an index DAG as a graphviz dot file"""
2500 """dump an index DAG as a graphviz dot file"""
2499 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2501 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2500 ui.write(("digraph G {\n"))
2502 ui.write(("digraph G {\n"))
2501 for i in r:
2503 for i in r:
2502 node = r.node(i)
2504 node = r.node(i)
2503 pp = r.parents(node)
2505 pp = r.parents(node)
2504 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2506 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2505 if pp[1] != nullid:
2507 if pp[1] != nullid:
2506 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2508 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2507 ui.write("}\n")
2509 ui.write("}\n")
2508
2510
2509 @command('debugdeltachain',
2511 @command('debugdeltachain',
2510 debugrevlogopts + formatteropts,
2512 debugrevlogopts + formatteropts,
2511 _('-c|-m|FILE'),
2513 _('-c|-m|FILE'),
2512 optionalrepo=True)
2514 optionalrepo=True)
2513 def debugdeltachain(ui, repo, file_=None, **opts):
2515 def debugdeltachain(ui, repo, file_=None, **opts):
2514 """dump information about delta chains in a revlog
2516 """dump information about delta chains in a revlog
2515
2517
2516 Output can be templatized. Available template keywords are:
2518 Output can be templatized. Available template keywords are:
2517
2519
2518 rev revision number
2520 rev revision number
2519 chainid delta chain identifier (numbered by unique base)
2521 chainid delta chain identifier (numbered by unique base)
2520 chainlen delta chain length to this revision
2522 chainlen delta chain length to this revision
2521 prevrev previous revision in delta chain
2523 prevrev previous revision in delta chain
2522 deltatype role of delta / how it was computed
2524 deltatype role of delta / how it was computed
2523 compsize compressed size of revision
2525 compsize compressed size of revision
2524 uncompsize uncompressed size of revision
2526 uncompsize uncompressed size of revision
2525 chainsize total size of compressed revisions in chain
2527 chainsize total size of compressed revisions in chain
2526 chainratio total chain size divided by uncompressed revision size
2528 chainratio total chain size divided by uncompressed revision size
2527 (new delta chains typically start at ratio 2.00)
2529 (new delta chains typically start at ratio 2.00)
2528 lindist linear distance from base revision in delta chain to end
2530 lindist linear distance from base revision in delta chain to end
2529 of this revision
2531 of this revision
2530 extradist total size of revisions not part of this delta chain from
2532 extradist total size of revisions not part of this delta chain from
2531 base of delta chain to end of this revision; a measurement
2533 base of delta chain to end of this revision; a measurement
2532 of how much extra data we need to read/seek across to read
2534 of how much extra data we need to read/seek across to read
2533 the delta chain for this revision
2535 the delta chain for this revision
2534 extraratio extradist divided by chainsize; another representation of
2536 extraratio extradist divided by chainsize; another representation of
2535 how much unrelated data is needed to load this delta chain
2537 how much unrelated data is needed to load this delta chain
2536 """
2538 """
2537 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2539 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2538 index = r.index
2540 index = r.index
2539 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2541 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2540
2542
2541 def revinfo(rev):
2543 def revinfo(rev):
2542 iterrev = rev
2544 iterrev = rev
2543 e = index[iterrev]
2545 e = index[iterrev]
2544 chain = []
2546 chain = []
2545 compsize = e[1]
2547 compsize = e[1]
2546 uncompsize = e[2]
2548 uncompsize = e[2]
2547 chainsize = 0
2549 chainsize = 0
2548
2550
2549 if generaldelta:
2551 if generaldelta:
2550 if e[3] == e[5]:
2552 if e[3] == e[5]:
2551 deltatype = 'p1'
2553 deltatype = 'p1'
2552 elif e[3] == e[6]:
2554 elif e[3] == e[6]:
2553 deltatype = 'p2'
2555 deltatype = 'p2'
2554 elif e[3] == rev - 1:
2556 elif e[3] == rev - 1:
2555 deltatype = 'prev'
2557 deltatype = 'prev'
2556 elif e[3] == rev:
2558 elif e[3] == rev:
2557 deltatype = 'base'
2559 deltatype = 'base'
2558 else:
2560 else:
2559 deltatype = 'other'
2561 deltatype = 'other'
2560 else:
2562 else:
2561 if e[3] == rev:
2563 if e[3] == rev:
2562 deltatype = 'base'
2564 deltatype = 'base'
2563 else:
2565 else:
2564 deltatype = 'prev'
2566 deltatype = 'prev'
2565
2567
2566 while iterrev != e[3]:
2568 while iterrev != e[3]:
2567 chain.append(iterrev)
2569 chain.append(iterrev)
2568 chainsize += e[1]
2570 chainsize += e[1]
2569 if generaldelta:
2571 if generaldelta:
2570 iterrev = e[3]
2572 iterrev = e[3]
2571 else:
2573 else:
2572 iterrev -= 1
2574 iterrev -= 1
2573 e = index[iterrev]
2575 e = index[iterrev]
2574 else:
2576 else:
2575 chainsize += e[1]
2577 chainsize += e[1]
2576 chain.append(iterrev)
2578 chain.append(iterrev)
2577
2579
2578 chain.reverse()
2580 chain.reverse()
2579 return compsize, uncompsize, deltatype, chain, chainsize
2581 return compsize, uncompsize, deltatype, chain, chainsize
2580
2582
2581 fm = ui.formatter('debugdeltachain', opts)
2583 fm = ui.formatter('debugdeltachain', opts)
2582
2584
2583 fm.plain(' rev chain# chainlen prev delta '
2585 fm.plain(' rev chain# chainlen prev delta '
2584 'size rawsize chainsize ratio lindist extradist '
2586 'size rawsize chainsize ratio lindist extradist '
2585 'extraratio\n')
2587 'extraratio\n')
2586
2588
2587 chainbases = {}
2589 chainbases = {}
2588 for rev in r:
2590 for rev in r:
2589 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2591 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2590 chainbase = chain[0]
2592 chainbase = chain[0]
2591 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2593 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2592 basestart = r.start(chainbase)
2594 basestart = r.start(chainbase)
2593 revstart = r.start(rev)
2595 revstart = r.start(rev)
2594 lineardist = revstart + comp - basestart
2596 lineardist = revstart + comp - basestart
2595 extradist = lineardist - chainsize
2597 extradist = lineardist - chainsize
2596 try:
2598 try:
2597 prevrev = chain[-2]
2599 prevrev = chain[-2]
2598 except IndexError:
2600 except IndexError:
2599 prevrev = -1
2601 prevrev = -1
2600
2602
2601 chainratio = float(chainsize) / float(uncomp)
2603 chainratio = float(chainsize) / float(uncomp)
2602 extraratio = float(extradist) / float(chainsize)
2604 extraratio = float(extradist) / float(chainsize)
2603
2605
2604 fm.startitem()
2606 fm.startitem()
2605 fm.write('rev chainid chainlen prevrev deltatype compsize '
2607 fm.write('rev chainid chainlen prevrev deltatype compsize '
2606 'uncompsize chainsize chainratio lindist extradist '
2608 'uncompsize chainsize chainratio lindist extradist '
2607 'extraratio',
2609 'extraratio',
2608 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2610 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2609 rev, chainid, len(chain), prevrev, deltatype, comp,
2611 rev, chainid, len(chain), prevrev, deltatype, comp,
2610 uncomp, chainsize, chainratio, lineardist, extradist,
2612 uncomp, chainsize, chainratio, lineardist, extradist,
2611 extraratio,
2613 extraratio,
2612 rev=rev, chainid=chainid, chainlen=len(chain),
2614 rev=rev, chainid=chainid, chainlen=len(chain),
2613 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2615 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2614 uncompsize=uncomp, chainsize=chainsize,
2616 uncompsize=uncomp, chainsize=chainsize,
2615 chainratio=chainratio, lindist=lineardist,
2617 chainratio=chainratio, lindist=lineardist,
2616 extradist=extradist, extraratio=extraratio)
2618 extradist=extradist, extraratio=extraratio)
2617
2619
2618 fm.end()
2620 fm.end()
2619
2621
2620 @command('debuginstall', [], '', norepo=True)
2622 @command('debuginstall', [], '', norepo=True)
2621 def debuginstall(ui):
2623 def debuginstall(ui):
2622 '''test Mercurial installation
2624 '''test Mercurial installation
2623
2625
2624 Returns 0 on success.
2626 Returns 0 on success.
2625 '''
2627 '''
2626
2628
2627 def writetemp(contents):
2629 def writetemp(contents):
2628 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2630 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2629 f = os.fdopen(fd, "wb")
2631 f = os.fdopen(fd, "wb")
2630 f.write(contents)
2632 f.write(contents)
2631 f.close()
2633 f.close()
2632 return name
2634 return name
2633
2635
2634 problems = 0
2636 problems = 0
2635
2637
2636 # encoding
2638 # encoding
2637 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2639 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2638 try:
2640 try:
2639 encoding.fromlocal("test")
2641 encoding.fromlocal("test")
2640 except error.Abort as inst:
2642 except error.Abort as inst:
2641 ui.write(" %s\n" % inst)
2643 ui.write(" %s\n" % inst)
2642 ui.write(_(" (check that your locale is properly set)\n"))
2644 ui.write(_(" (check that your locale is properly set)\n"))
2643 problems += 1
2645 problems += 1
2644
2646
2645 # Python
2647 # Python
2646 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2648 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2647 ui.status(_("checking Python version (%s)\n")
2649 ui.status(_("checking Python version (%s)\n")
2648 % ("%s.%s.%s" % sys.version_info[:3]))
2650 % ("%s.%s.%s" % sys.version_info[:3]))
2649 ui.status(_("checking Python lib (%s)...\n")
2651 ui.status(_("checking Python lib (%s)...\n")
2650 % os.path.dirname(os.__file__))
2652 % os.path.dirname(os.__file__))
2651
2653
2652 # compiled modules
2654 # compiled modules
2653 ui.status(_("checking installed modules (%s)...\n")
2655 ui.status(_("checking installed modules (%s)...\n")
2654 % os.path.dirname(__file__))
2656 % os.path.dirname(__file__))
2655 try:
2657 try:
2656 import bdiff, mpatch, base85, osutil
2658 import bdiff, mpatch, base85, osutil
2657 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2659 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2658 except Exception as inst:
2660 except Exception as inst:
2659 ui.write(" %s\n" % inst)
2661 ui.write(" %s\n" % inst)
2660 ui.write(_(" One or more extensions could not be found"))
2662 ui.write(_(" One or more extensions could not be found"))
2661 ui.write(_(" (check that you compiled the extensions)\n"))
2663 ui.write(_(" (check that you compiled the extensions)\n"))
2662 problems += 1
2664 problems += 1
2663
2665
2664 # templates
2666 # templates
2665 import templater
2667 import templater
2666 p = templater.templatepaths()
2668 p = templater.templatepaths()
2667 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2669 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2668 if p:
2670 if p:
2669 m = templater.templatepath("map-cmdline.default")
2671 m = templater.templatepath("map-cmdline.default")
2670 if m:
2672 if m:
2671 # template found, check if it is working
2673 # template found, check if it is working
2672 try:
2674 try:
2673 templater.templater(m)
2675 templater.templater(m)
2674 except Exception as inst:
2676 except Exception as inst:
2675 ui.write(" %s\n" % inst)
2677 ui.write(" %s\n" % inst)
2676 p = None
2678 p = None
2677 else:
2679 else:
2678 ui.write(_(" template 'default' not found\n"))
2680 ui.write(_(" template 'default' not found\n"))
2679 p = None
2681 p = None
2680 else:
2682 else:
2681 ui.write(_(" no template directories found\n"))
2683 ui.write(_(" no template directories found\n"))
2682 if not p:
2684 if not p:
2683 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2685 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2684 problems += 1
2686 problems += 1
2685
2687
2686 # editor
2688 # editor
2687 ui.status(_("checking commit editor...\n"))
2689 ui.status(_("checking commit editor...\n"))
2688 editor = ui.geteditor()
2690 editor = ui.geteditor()
2689 editor = util.expandpath(editor)
2691 editor = util.expandpath(editor)
2690 cmdpath = util.findexe(shlex.split(editor)[0])
2692 cmdpath = util.findexe(shlex.split(editor)[0])
2691 if not cmdpath:
2693 if not cmdpath:
2692 if editor == 'vi':
2694 if editor == 'vi':
2693 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2695 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2694 ui.write(_(" (specify a commit editor in your configuration"
2696 ui.write(_(" (specify a commit editor in your configuration"
2695 " file)\n"))
2697 " file)\n"))
2696 else:
2698 else:
2697 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2699 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2698 ui.write(_(" (specify a commit editor in your configuration"
2700 ui.write(_(" (specify a commit editor in your configuration"
2699 " file)\n"))
2701 " file)\n"))
2700 problems += 1
2702 problems += 1
2701
2703
2702 # check username
2704 # check username
2703 ui.status(_("checking username...\n"))
2705 ui.status(_("checking username...\n"))
2704 try:
2706 try:
2705 ui.username()
2707 ui.username()
2706 except error.Abort as e:
2708 except error.Abort as e:
2707 ui.write(" %s\n" % e)
2709 ui.write(" %s\n" % e)
2708 ui.write(_(" (specify a username in your configuration file)\n"))
2710 ui.write(_(" (specify a username in your configuration file)\n"))
2709 problems += 1
2711 problems += 1
2710
2712
2711 if not problems:
2713 if not problems:
2712 ui.status(_("no problems detected\n"))
2714 ui.status(_("no problems detected\n"))
2713 else:
2715 else:
2714 ui.write(_("%s problems detected,"
2716 ui.write(_("%s problems detected,"
2715 " please check your install!\n") % problems)
2717 " please check your install!\n") % problems)
2716
2718
2717 return problems
2719 return problems
2718
2720
2719 @command('debugknown', [], _('REPO ID...'), norepo=True)
2721 @command('debugknown', [], _('REPO ID...'), norepo=True)
2720 def debugknown(ui, repopath, *ids, **opts):
2722 def debugknown(ui, repopath, *ids, **opts):
2721 """test whether node ids are known to a repo
2723 """test whether node ids are known to a repo
2722
2724
2723 Every ID must be a full-length hex node id string. Returns a list of 0s
2725 Every ID must be a full-length hex node id string. Returns a list of 0s
2724 and 1s indicating unknown/known.
2726 and 1s indicating unknown/known.
2725 """
2727 """
2726 repo = hg.peer(ui, opts, repopath)
2728 repo = hg.peer(ui, opts, repopath)
2727 if not repo.capable('known'):
2729 if not repo.capable('known'):
2728 raise error.Abort("known() not supported by target repository")
2730 raise error.Abort("known() not supported by target repository")
2729 flags = repo.known([bin(s) for s in ids])
2731 flags = repo.known([bin(s) for s in ids])
2730 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2732 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2731
2733
2732 @command('debuglabelcomplete', [], _('LABEL...'))
2734 @command('debuglabelcomplete', [], _('LABEL...'))
2733 def debuglabelcomplete(ui, repo, *args):
2735 def debuglabelcomplete(ui, repo, *args):
2734 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2736 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2735 debugnamecomplete(ui, repo, *args)
2737 debugnamecomplete(ui, repo, *args)
2736
2738
2737 @command('debugmergestate', [], '')
2739 @command('debugmergestate', [], '')
2738 def debugmergestate(ui, repo, *args):
2740 def debugmergestate(ui, repo, *args):
2739 """print merge state
2741 """print merge state
2740
2742
2741 Use --verbose to print out information about whether v1 or v2 merge state
2743 Use --verbose to print out information about whether v1 or v2 merge state
2742 was chosen."""
2744 was chosen."""
2743 def _hashornull(h):
2745 def _hashornull(h):
2744 if h == nullhex:
2746 if h == nullhex:
2745 return 'null'
2747 return 'null'
2746 else:
2748 else:
2747 return h
2749 return h
2748
2750
2749 def printrecords(version):
2751 def printrecords(version):
2750 ui.write(('* version %s records\n') % version)
2752 ui.write(('* version %s records\n') % version)
2751 if version == 1:
2753 if version == 1:
2752 records = v1records
2754 records = v1records
2753 else:
2755 else:
2754 records = v2records
2756 records = v2records
2755
2757
2756 for rtype, record in records:
2758 for rtype, record in records:
2757 # pretty print some record types
2759 # pretty print some record types
2758 if rtype == 'L':
2760 if rtype == 'L':
2759 ui.write(('local: %s\n') % record)
2761 ui.write(('local: %s\n') % record)
2760 elif rtype == 'O':
2762 elif rtype == 'O':
2761 ui.write(('other: %s\n') % record)
2763 ui.write(('other: %s\n') % record)
2762 elif rtype == 'm':
2764 elif rtype == 'm':
2763 driver, mdstate = record.split('\0', 1)
2765 driver, mdstate = record.split('\0', 1)
2764 ui.write(('merge driver: %s (state "%s")\n')
2766 ui.write(('merge driver: %s (state "%s")\n')
2765 % (driver, mdstate))
2767 % (driver, mdstate))
2766 elif rtype in 'FDC':
2768 elif rtype in 'FDC':
2767 r = record.split('\0')
2769 r = record.split('\0')
2768 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2770 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2769 if version == 1:
2771 if version == 1:
2770 onode = 'not stored in v1 format'
2772 onode = 'not stored in v1 format'
2771 flags = r[7]
2773 flags = r[7]
2772 else:
2774 else:
2773 onode, flags = r[7:9]
2775 onode, flags = r[7:9]
2774 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2776 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2775 % (f, rtype, state, _hashornull(hash)))
2777 % (f, rtype, state, _hashornull(hash)))
2776 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2778 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2777 ui.write((' ancestor path: %s (node %s)\n')
2779 ui.write((' ancestor path: %s (node %s)\n')
2778 % (afile, _hashornull(anode)))
2780 % (afile, _hashornull(anode)))
2779 ui.write((' other path: %s (node %s)\n')
2781 ui.write((' other path: %s (node %s)\n')
2780 % (ofile, _hashornull(onode)))
2782 % (ofile, _hashornull(onode)))
2781 else:
2783 else:
2782 ui.write(('unrecognized entry: %s\t%s\n')
2784 ui.write(('unrecognized entry: %s\t%s\n')
2783 % (rtype, record.replace('\0', '\t')))
2785 % (rtype, record.replace('\0', '\t')))
2784
2786
2785 # Avoid mergestate.read() since it may raise an exception for unsupported
2787 # Avoid mergestate.read() since it may raise an exception for unsupported
2786 # merge state records. We shouldn't be doing this, but this is OK since this
2788 # merge state records. We shouldn't be doing this, but this is OK since this
2787 # command is pretty low-level.
2789 # command is pretty low-level.
2788 ms = mergemod.mergestate(repo)
2790 ms = mergemod.mergestate(repo)
2789
2791
2790 # sort so that reasonable information is on top
2792 # sort so that reasonable information is on top
2791 v1records = ms._readrecordsv1()
2793 v1records = ms._readrecordsv1()
2792 v2records = ms._readrecordsv2()
2794 v2records = ms._readrecordsv2()
2793 order = 'LOm'
2795 order = 'LOm'
2794 def key(r):
2796 def key(r):
2795 idx = order.find(r[0])
2797 idx = order.find(r[0])
2796 if idx == -1:
2798 if idx == -1:
2797 return (1, r[1])
2799 return (1, r[1])
2798 else:
2800 else:
2799 return (0, idx)
2801 return (0, idx)
2800 v1records.sort(key=key)
2802 v1records.sort(key=key)
2801 v2records.sort(key=key)
2803 v2records.sort(key=key)
2802
2804
2803 if not v1records and not v2records:
2805 if not v1records and not v2records:
2804 ui.write(('no merge state found\n'))
2806 ui.write(('no merge state found\n'))
2805 elif not v2records:
2807 elif not v2records:
2806 ui.note(('no version 2 merge state\n'))
2808 ui.note(('no version 2 merge state\n'))
2807 printrecords(1)
2809 printrecords(1)
2808 elif ms._v1v2match(v1records, v2records):
2810 elif ms._v1v2match(v1records, v2records):
2809 ui.note(('v1 and v2 states match: using v2\n'))
2811 ui.note(('v1 and v2 states match: using v2\n'))
2810 printrecords(2)
2812 printrecords(2)
2811 else:
2813 else:
2812 ui.note(('v1 and v2 states mismatch: using v1\n'))
2814 ui.note(('v1 and v2 states mismatch: using v1\n'))
2813 printrecords(1)
2815 printrecords(1)
2814 if ui.verbose:
2816 if ui.verbose:
2815 printrecords(2)
2817 printrecords(2)
2816
2818
2817 @command('debugnamecomplete', [], _('NAME...'))
2819 @command('debugnamecomplete', [], _('NAME...'))
2818 def debugnamecomplete(ui, repo, *args):
2820 def debugnamecomplete(ui, repo, *args):
2819 '''complete "names" - tags, open branch names, bookmark names'''
2821 '''complete "names" - tags, open branch names, bookmark names'''
2820
2822
2821 names = set()
2823 names = set()
2822 # since we previously only listed open branches, we will handle that
2824 # since we previously only listed open branches, we will handle that
2823 # specially (after this for loop)
2825 # specially (after this for loop)
2824 for name, ns in repo.names.iteritems():
2826 for name, ns in repo.names.iteritems():
2825 if name != 'branches':
2827 if name != 'branches':
2826 names.update(ns.listnames(repo))
2828 names.update(ns.listnames(repo))
2827 names.update(tag for (tag, heads, tip, closed)
2829 names.update(tag for (tag, heads, tip, closed)
2828 in repo.branchmap().iterbranches() if not closed)
2830 in repo.branchmap().iterbranches() if not closed)
2829 completions = set()
2831 completions = set()
2830 if not args:
2832 if not args:
2831 args = ['']
2833 args = ['']
2832 for a in args:
2834 for a in args:
2833 completions.update(n for n in names if n.startswith(a))
2835 completions.update(n for n in names if n.startswith(a))
2834 ui.write('\n'.join(sorted(completions)))
2836 ui.write('\n'.join(sorted(completions)))
2835 ui.write('\n')
2837 ui.write('\n')
2836
2838
2837 @command('debuglocks',
2839 @command('debuglocks',
2838 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2840 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2839 ('W', 'force-wlock', None,
2841 ('W', 'force-wlock', None,
2840 _('free the working state lock (DANGEROUS)'))],
2842 _('free the working state lock (DANGEROUS)'))],
2841 _('[OPTION]...'))
2843 _('[OPTION]...'))
2842 def debuglocks(ui, repo, **opts):
2844 def debuglocks(ui, repo, **opts):
2843 """show or modify state of locks
2845 """show or modify state of locks
2844
2846
2845 By default, this command will show which locks are held. This
2847 By default, this command will show which locks are held. This
2846 includes the user and process holding the lock, the amount of time
2848 includes the user and process holding the lock, the amount of time
2847 the lock has been held, and the machine name where the process is
2849 the lock has been held, and the machine name where the process is
2848 running if it's not local.
2850 running if it's not local.
2849
2851
2850 Locks protect the integrity of Mercurial's data, so should be
2852 Locks protect the integrity of Mercurial's data, so should be
2851 treated with care. System crashes or other interruptions may cause
2853 treated with care. System crashes or other interruptions may cause
2852 locks to not be properly released, though Mercurial will usually
2854 locks to not be properly released, though Mercurial will usually
2853 detect and remove such stale locks automatically.
2855 detect and remove such stale locks automatically.
2854
2856
2855 However, detecting stale locks may not always be possible (for
2857 However, detecting stale locks may not always be possible (for
2856 instance, on a shared filesystem). Removing locks may also be
2858 instance, on a shared filesystem). Removing locks may also be
2857 blocked by filesystem permissions.
2859 blocked by filesystem permissions.
2858
2860
2859 Returns 0 if no locks are held.
2861 Returns 0 if no locks are held.
2860
2862
2861 """
2863 """
2862
2864
2863 if opts.get('force_lock'):
2865 if opts.get('force_lock'):
2864 repo.svfs.unlink('lock')
2866 repo.svfs.unlink('lock')
2865 if opts.get('force_wlock'):
2867 if opts.get('force_wlock'):
2866 repo.vfs.unlink('wlock')
2868 repo.vfs.unlink('wlock')
2867 if opts.get('force_lock') or opts.get('force_lock'):
2869 if opts.get('force_lock') or opts.get('force_lock'):
2868 return 0
2870 return 0
2869
2871
2870 now = time.time()
2872 now = time.time()
2871 held = 0
2873 held = 0
2872
2874
2873 def report(vfs, name, method):
2875 def report(vfs, name, method):
2874 # this causes stale locks to get reaped for more accurate reporting
2876 # this causes stale locks to get reaped for more accurate reporting
2875 try:
2877 try:
2876 l = method(False)
2878 l = method(False)
2877 except error.LockHeld:
2879 except error.LockHeld:
2878 l = None
2880 l = None
2879
2881
2880 if l:
2882 if l:
2881 l.release()
2883 l.release()
2882 else:
2884 else:
2883 try:
2885 try:
2884 stat = vfs.lstat(name)
2886 stat = vfs.lstat(name)
2885 age = now - stat.st_mtime
2887 age = now - stat.st_mtime
2886 user = util.username(stat.st_uid)
2888 user = util.username(stat.st_uid)
2887 locker = vfs.readlock(name)
2889 locker = vfs.readlock(name)
2888 if ":" in locker:
2890 if ":" in locker:
2889 host, pid = locker.split(':')
2891 host, pid = locker.split(':')
2890 if host == socket.gethostname():
2892 if host == socket.gethostname():
2891 locker = 'user %s, process %s' % (user, pid)
2893 locker = 'user %s, process %s' % (user, pid)
2892 else:
2894 else:
2893 locker = 'user %s, process %s, host %s' \
2895 locker = 'user %s, process %s, host %s' \
2894 % (user, pid, host)
2896 % (user, pid, host)
2895 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2897 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2896 return 1
2898 return 1
2897 except OSError as e:
2899 except OSError as e:
2898 if e.errno != errno.ENOENT:
2900 if e.errno != errno.ENOENT:
2899 raise
2901 raise
2900
2902
2901 ui.write("%-6s free\n" % (name + ":"))
2903 ui.write("%-6s free\n" % (name + ":"))
2902 return 0
2904 return 0
2903
2905
2904 held += report(repo.svfs, "lock", repo.lock)
2906 held += report(repo.svfs, "lock", repo.lock)
2905 held += report(repo.vfs, "wlock", repo.wlock)
2907 held += report(repo.vfs, "wlock", repo.wlock)
2906
2908
2907 return held
2909 return held
2908
2910
2909 @command('debugobsolete',
2911 @command('debugobsolete',
2910 [('', 'flags', 0, _('markers flag')),
2912 [('', 'flags', 0, _('markers flag')),
2911 ('', 'record-parents', False,
2913 ('', 'record-parents', False,
2912 _('record parent information for the precursor')),
2914 _('record parent information for the precursor')),
2913 ('r', 'rev', [], _('display markers relevant to REV')),
2915 ('r', 'rev', [], _('display markers relevant to REV')),
2914 ] + commitopts2,
2916 ] + commitopts2,
2915 _('[OBSOLETED [REPLACEMENT ...]]'))
2917 _('[OBSOLETED [REPLACEMENT ...]]'))
2916 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2918 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2917 """create arbitrary obsolete marker
2919 """create arbitrary obsolete marker
2918
2920
2919 With no arguments, displays the list of obsolescence markers."""
2921 With no arguments, displays the list of obsolescence markers."""
2920
2922
2921 def parsenodeid(s):
2923 def parsenodeid(s):
2922 try:
2924 try:
2923 # We do not use revsingle/revrange functions here to accept
2925 # We do not use revsingle/revrange functions here to accept
2924 # arbitrary node identifiers, possibly not present in the
2926 # arbitrary node identifiers, possibly not present in the
2925 # local repository.
2927 # local repository.
2926 n = bin(s)
2928 n = bin(s)
2927 if len(n) != len(nullid):
2929 if len(n) != len(nullid):
2928 raise TypeError()
2930 raise TypeError()
2929 return n
2931 return n
2930 except TypeError:
2932 except TypeError:
2931 raise error.Abort('changeset references must be full hexadecimal '
2933 raise error.Abort('changeset references must be full hexadecimal '
2932 'node identifiers')
2934 'node identifiers')
2933
2935
2934 if precursor is not None:
2936 if precursor is not None:
2935 if opts['rev']:
2937 if opts['rev']:
2936 raise error.Abort('cannot select revision when creating marker')
2938 raise error.Abort('cannot select revision when creating marker')
2937 metadata = {}
2939 metadata = {}
2938 metadata['user'] = opts['user'] or ui.username()
2940 metadata['user'] = opts['user'] or ui.username()
2939 succs = tuple(parsenodeid(succ) for succ in successors)
2941 succs = tuple(parsenodeid(succ) for succ in successors)
2940 l = repo.lock()
2942 l = repo.lock()
2941 try:
2943 try:
2942 tr = repo.transaction('debugobsolete')
2944 tr = repo.transaction('debugobsolete')
2943 try:
2945 try:
2944 date = opts.get('date')
2946 date = opts.get('date')
2945 if date:
2947 if date:
2946 date = util.parsedate(date)
2948 date = util.parsedate(date)
2947 else:
2949 else:
2948 date = None
2950 date = None
2949 prec = parsenodeid(precursor)
2951 prec = parsenodeid(precursor)
2950 parents = None
2952 parents = None
2951 if opts['record_parents']:
2953 if opts['record_parents']:
2952 if prec not in repo.unfiltered():
2954 if prec not in repo.unfiltered():
2953 raise error.Abort('cannot used --record-parents on '
2955 raise error.Abort('cannot used --record-parents on '
2954 'unknown changesets')
2956 'unknown changesets')
2955 parents = repo.unfiltered()[prec].parents()
2957 parents = repo.unfiltered()[prec].parents()
2956 parents = tuple(p.node() for p in parents)
2958 parents = tuple(p.node() for p in parents)
2957 repo.obsstore.create(tr, prec, succs, opts['flags'],
2959 repo.obsstore.create(tr, prec, succs, opts['flags'],
2958 parents=parents, date=date,
2960 parents=parents, date=date,
2959 metadata=metadata)
2961 metadata=metadata)
2960 tr.close()
2962 tr.close()
2961 except ValueError as exc:
2963 except ValueError as exc:
2962 raise error.Abort(_('bad obsmarker input: %s') % exc)
2964 raise error.Abort(_('bad obsmarker input: %s') % exc)
2963 finally:
2965 finally:
2964 tr.release()
2966 tr.release()
2965 finally:
2967 finally:
2966 l.release()
2968 l.release()
2967 else:
2969 else:
2968 if opts['rev']:
2970 if opts['rev']:
2969 revs = scmutil.revrange(repo, opts['rev'])
2971 revs = scmutil.revrange(repo, opts['rev'])
2970 nodes = [repo[r].node() for r in revs]
2972 nodes = [repo[r].node() for r in revs]
2971 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2973 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2972 markers.sort(key=lambda x: x._data)
2974 markers.sort(key=lambda x: x._data)
2973 else:
2975 else:
2974 markers = obsolete.getmarkers(repo)
2976 markers = obsolete.getmarkers(repo)
2975
2977
2976 for m in markers:
2978 for m in markers:
2977 cmdutil.showmarker(ui, m)
2979 cmdutil.showmarker(ui, m)
2978
2980
2979 @command('debugpathcomplete',
2981 @command('debugpathcomplete',
2980 [('f', 'full', None, _('complete an entire path')),
2982 [('f', 'full', None, _('complete an entire path')),
2981 ('n', 'normal', None, _('show only normal files')),
2983 ('n', 'normal', None, _('show only normal files')),
2982 ('a', 'added', None, _('show only added files')),
2984 ('a', 'added', None, _('show only added files')),
2983 ('r', 'removed', None, _('show only removed files'))],
2985 ('r', 'removed', None, _('show only removed files'))],
2984 _('FILESPEC...'))
2986 _('FILESPEC...'))
2985 def debugpathcomplete(ui, repo, *specs, **opts):
2987 def debugpathcomplete(ui, repo, *specs, **opts):
2986 '''complete part or all of a tracked path
2988 '''complete part or all of a tracked path
2987
2989
2988 This command supports shells that offer path name completion. It
2990 This command supports shells that offer path name completion. It
2989 currently completes only files already known to the dirstate.
2991 currently completes only files already known to the dirstate.
2990
2992
2991 Completion extends only to the next path segment unless
2993 Completion extends only to the next path segment unless
2992 --full is specified, in which case entire paths are used.'''
2994 --full is specified, in which case entire paths are used.'''
2993
2995
2994 def complete(path, acceptable):
2996 def complete(path, acceptable):
2995 dirstate = repo.dirstate
2997 dirstate = repo.dirstate
2996 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2998 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2997 rootdir = repo.root + os.sep
2999 rootdir = repo.root + os.sep
2998 if spec != repo.root and not spec.startswith(rootdir):
3000 if spec != repo.root and not spec.startswith(rootdir):
2999 return [], []
3001 return [], []
3000 if os.path.isdir(spec):
3002 if os.path.isdir(spec):
3001 spec += '/'
3003 spec += '/'
3002 spec = spec[len(rootdir):]
3004 spec = spec[len(rootdir):]
3003 fixpaths = os.sep != '/'
3005 fixpaths = os.sep != '/'
3004 if fixpaths:
3006 if fixpaths:
3005 spec = spec.replace(os.sep, '/')
3007 spec = spec.replace(os.sep, '/')
3006 speclen = len(spec)
3008 speclen = len(spec)
3007 fullpaths = opts['full']
3009 fullpaths = opts['full']
3008 files, dirs = set(), set()
3010 files, dirs = set(), set()
3009 adddir, addfile = dirs.add, files.add
3011 adddir, addfile = dirs.add, files.add
3010 for f, st in dirstate.iteritems():
3012 for f, st in dirstate.iteritems():
3011 if f.startswith(spec) and st[0] in acceptable:
3013 if f.startswith(spec) and st[0] in acceptable:
3012 if fixpaths:
3014 if fixpaths:
3013 f = f.replace('/', os.sep)
3015 f = f.replace('/', os.sep)
3014 if fullpaths:
3016 if fullpaths:
3015 addfile(f)
3017 addfile(f)
3016 continue
3018 continue
3017 s = f.find(os.sep, speclen)
3019 s = f.find(os.sep, speclen)
3018 if s >= 0:
3020 if s >= 0:
3019 adddir(f[:s])
3021 adddir(f[:s])
3020 else:
3022 else:
3021 addfile(f)
3023 addfile(f)
3022 return files, dirs
3024 return files, dirs
3023
3025
3024 acceptable = ''
3026 acceptable = ''
3025 if opts['normal']:
3027 if opts['normal']:
3026 acceptable += 'nm'
3028 acceptable += 'nm'
3027 if opts['added']:
3029 if opts['added']:
3028 acceptable += 'a'
3030 acceptable += 'a'
3029 if opts['removed']:
3031 if opts['removed']:
3030 acceptable += 'r'
3032 acceptable += 'r'
3031 cwd = repo.getcwd()
3033 cwd = repo.getcwd()
3032 if not specs:
3034 if not specs:
3033 specs = ['.']
3035 specs = ['.']
3034
3036
3035 files, dirs = set(), set()
3037 files, dirs = set(), set()
3036 for spec in specs:
3038 for spec in specs:
3037 f, d = complete(spec, acceptable or 'nmar')
3039 f, d = complete(spec, acceptable or 'nmar')
3038 files.update(f)
3040 files.update(f)
3039 dirs.update(d)
3041 dirs.update(d)
3040 files.update(dirs)
3042 files.update(dirs)
3041 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3043 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3042 ui.write('\n')
3044 ui.write('\n')
3043
3045
3044 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3046 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3045 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3047 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3046 '''access the pushkey key/value protocol
3048 '''access the pushkey key/value protocol
3047
3049
3048 With two args, list the keys in the given namespace.
3050 With two args, list the keys in the given namespace.
3049
3051
3050 With five args, set a key to new if it currently is set to old.
3052 With five args, set a key to new if it currently is set to old.
3051 Reports success or failure.
3053 Reports success or failure.
3052 '''
3054 '''
3053
3055
3054 target = hg.peer(ui, {}, repopath)
3056 target = hg.peer(ui, {}, repopath)
3055 if keyinfo:
3057 if keyinfo:
3056 key, old, new = keyinfo
3058 key, old, new = keyinfo
3057 r = target.pushkey(namespace, key, old, new)
3059 r = target.pushkey(namespace, key, old, new)
3058 ui.status(str(r) + '\n')
3060 ui.status(str(r) + '\n')
3059 return not r
3061 return not r
3060 else:
3062 else:
3061 for k, v in sorted(target.listkeys(namespace).iteritems()):
3063 for k, v in sorted(target.listkeys(namespace).iteritems()):
3062 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3064 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3063 v.encode('string-escape')))
3065 v.encode('string-escape')))
3064
3066
3065 @command('debugpvec', [], _('A B'))
3067 @command('debugpvec', [], _('A B'))
3066 def debugpvec(ui, repo, a, b=None):
3068 def debugpvec(ui, repo, a, b=None):
3067 ca = scmutil.revsingle(repo, a)
3069 ca = scmutil.revsingle(repo, a)
3068 cb = scmutil.revsingle(repo, b)
3070 cb = scmutil.revsingle(repo, b)
3069 pa = pvec.ctxpvec(ca)
3071 pa = pvec.ctxpvec(ca)
3070 pb = pvec.ctxpvec(cb)
3072 pb = pvec.ctxpvec(cb)
3071 if pa == pb:
3073 if pa == pb:
3072 rel = "="
3074 rel = "="
3073 elif pa > pb:
3075 elif pa > pb:
3074 rel = ">"
3076 rel = ">"
3075 elif pa < pb:
3077 elif pa < pb:
3076 rel = "<"
3078 rel = "<"
3077 elif pa | pb:
3079 elif pa | pb:
3078 rel = "|"
3080 rel = "|"
3079 ui.write(_("a: %s\n") % pa)
3081 ui.write(_("a: %s\n") % pa)
3080 ui.write(_("b: %s\n") % pb)
3082 ui.write(_("b: %s\n") % pb)
3081 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3083 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3082 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3084 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3083 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3085 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3084 pa.distance(pb), rel))
3086 pa.distance(pb), rel))
3085
3087
3086 @command('debugrebuilddirstate|debugrebuildstate',
3088 @command('debugrebuilddirstate|debugrebuildstate',
3087 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3089 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3088 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3090 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3089 'the working copy parent')),
3091 'the working copy parent')),
3090 ],
3092 ],
3091 _('[-r REV]'))
3093 _('[-r REV]'))
3092 def debugrebuilddirstate(ui, repo, rev, **opts):
3094 def debugrebuilddirstate(ui, repo, rev, **opts):
3093 """rebuild the dirstate as it would look like for the given revision
3095 """rebuild the dirstate as it would look like for the given revision
3094
3096
3095 If no revision is specified the first current parent will be used.
3097 If no revision is specified the first current parent will be used.
3096
3098
3097 The dirstate will be set to the files of the given revision.
3099 The dirstate will be set to the files of the given revision.
3098 The actual working directory content or existing dirstate
3100 The actual working directory content or existing dirstate
3099 information such as adds or removes is not considered.
3101 information such as adds or removes is not considered.
3100
3102
3101 ``minimal`` will only rebuild the dirstate status for files that claim to be
3103 ``minimal`` will only rebuild the dirstate status for files that claim to be
3102 tracked but are not in the parent manifest, or that exist in the parent
3104 tracked but are not in the parent manifest, or that exist in the parent
3103 manifest but are not in the dirstate. It will not change adds, removes, or
3105 manifest but are not in the dirstate. It will not change adds, removes, or
3104 modified files that are in the working copy parent.
3106 modified files that are in the working copy parent.
3105
3107
3106 One use of this command is to make the next :hg:`status` invocation
3108 One use of this command is to make the next :hg:`status` invocation
3107 check the actual file content.
3109 check the actual file content.
3108 """
3110 """
3109 ctx = scmutil.revsingle(repo, rev)
3111 ctx = scmutil.revsingle(repo, rev)
3110 wlock = repo.wlock()
3112 wlock = repo.wlock()
3111 try:
3113 try:
3112 dirstate = repo.dirstate
3114 dirstate = repo.dirstate
3113 changedfiles = None
3115 changedfiles = None
3114 # See command doc for what minimal does.
3116 # See command doc for what minimal does.
3115 if opts.get('minimal'):
3117 if opts.get('minimal'):
3116 manifestfiles = set(ctx.manifest().keys())
3118 manifestfiles = set(ctx.manifest().keys())
3117 dirstatefiles = set(dirstate)
3119 dirstatefiles = set(dirstate)
3118 manifestonly = manifestfiles - dirstatefiles
3120 manifestonly = manifestfiles - dirstatefiles
3119 dsonly = dirstatefiles - manifestfiles
3121 dsonly = dirstatefiles - manifestfiles
3120 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3122 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3121 changedfiles = manifestonly | dsnotadded
3123 changedfiles = manifestonly | dsnotadded
3122
3124
3123 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3125 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3124 finally:
3126 finally:
3125 wlock.release()
3127 wlock.release()
3126
3128
3127 @command('debugrebuildfncache', [], '')
3129 @command('debugrebuildfncache', [], '')
3128 def debugrebuildfncache(ui, repo):
3130 def debugrebuildfncache(ui, repo):
3129 """rebuild the fncache file"""
3131 """rebuild the fncache file"""
3130 repair.rebuildfncache(ui, repo)
3132 repair.rebuildfncache(ui, repo)
3131
3133
3132 @command('debugrename',
3134 @command('debugrename',
3133 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3135 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3134 _('[-r REV] FILE'))
3136 _('[-r REV] FILE'))
3135 def debugrename(ui, repo, file1, *pats, **opts):
3137 def debugrename(ui, repo, file1, *pats, **opts):
3136 """dump rename information"""
3138 """dump rename information"""
3137
3139
3138 ctx = scmutil.revsingle(repo, opts.get('rev'))
3140 ctx = scmutil.revsingle(repo, opts.get('rev'))
3139 m = scmutil.match(ctx, (file1,) + pats, opts)
3141 m = scmutil.match(ctx, (file1,) + pats, opts)
3140 for abs in ctx.walk(m):
3142 for abs in ctx.walk(m):
3141 fctx = ctx[abs]
3143 fctx = ctx[abs]
3142 o = fctx.filelog().renamed(fctx.filenode())
3144 o = fctx.filelog().renamed(fctx.filenode())
3143 rel = m.rel(abs)
3145 rel = m.rel(abs)
3144 if o:
3146 if o:
3145 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3147 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3146 else:
3148 else:
3147 ui.write(_("%s not renamed\n") % rel)
3149 ui.write(_("%s not renamed\n") % rel)
3148
3150
3149 @command('debugrevlog', debugrevlogopts +
3151 @command('debugrevlog', debugrevlogopts +
3150 [('d', 'dump', False, _('dump index data'))],
3152 [('d', 'dump', False, _('dump index data'))],
3151 _('-c|-m|FILE'),
3153 _('-c|-m|FILE'),
3152 optionalrepo=True)
3154 optionalrepo=True)
3153 def debugrevlog(ui, repo, file_=None, **opts):
3155 def debugrevlog(ui, repo, file_=None, **opts):
3154 """show data and statistics about a revlog"""
3156 """show data and statistics about a revlog"""
3155 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3157 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3156
3158
3157 if opts.get("dump"):
3159 if opts.get("dump"):
3158 numrevs = len(r)
3160 numrevs = len(r)
3159 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3161 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3160 " rawsize totalsize compression heads chainlen\n")
3162 " rawsize totalsize compression heads chainlen\n")
3161 ts = 0
3163 ts = 0
3162 heads = set()
3164 heads = set()
3163
3165
3164 for rev in xrange(numrevs):
3166 for rev in xrange(numrevs):
3165 dbase = r.deltaparent(rev)
3167 dbase = r.deltaparent(rev)
3166 if dbase == -1:
3168 if dbase == -1:
3167 dbase = rev
3169 dbase = rev
3168 cbase = r.chainbase(rev)
3170 cbase = r.chainbase(rev)
3169 clen = r.chainlen(rev)
3171 clen = r.chainlen(rev)
3170 p1, p2 = r.parentrevs(rev)
3172 p1, p2 = r.parentrevs(rev)
3171 rs = r.rawsize(rev)
3173 rs = r.rawsize(rev)
3172 ts = ts + rs
3174 ts = ts + rs
3173 heads -= set(r.parentrevs(rev))
3175 heads -= set(r.parentrevs(rev))
3174 heads.add(rev)
3176 heads.add(rev)
3175 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3177 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3176 "%11d %5d %8d\n" %
3178 "%11d %5d %8d\n" %
3177 (rev, p1, p2, r.start(rev), r.end(rev),
3179 (rev, p1, p2, r.start(rev), r.end(rev),
3178 r.start(dbase), r.start(cbase),
3180 r.start(dbase), r.start(cbase),
3179 r.start(p1), r.start(p2),
3181 r.start(p1), r.start(p2),
3180 rs, ts, ts / r.end(rev), len(heads), clen))
3182 rs, ts, ts / r.end(rev), len(heads), clen))
3181 return 0
3183 return 0
3182
3184
3183 v = r.version
3185 v = r.version
3184 format = v & 0xFFFF
3186 format = v & 0xFFFF
3185 flags = []
3187 flags = []
3186 gdelta = False
3188 gdelta = False
3187 if v & revlog.REVLOGNGINLINEDATA:
3189 if v & revlog.REVLOGNGINLINEDATA:
3188 flags.append('inline')
3190 flags.append('inline')
3189 if v & revlog.REVLOGGENERALDELTA:
3191 if v & revlog.REVLOGGENERALDELTA:
3190 gdelta = True
3192 gdelta = True
3191 flags.append('generaldelta')
3193 flags.append('generaldelta')
3192 if not flags:
3194 if not flags:
3193 flags = ['(none)']
3195 flags = ['(none)']
3194
3196
3195 nummerges = 0
3197 nummerges = 0
3196 numfull = 0
3198 numfull = 0
3197 numprev = 0
3199 numprev = 0
3198 nump1 = 0
3200 nump1 = 0
3199 nump2 = 0
3201 nump2 = 0
3200 numother = 0
3202 numother = 0
3201 nump1prev = 0
3203 nump1prev = 0
3202 nump2prev = 0
3204 nump2prev = 0
3203 chainlengths = []
3205 chainlengths = []
3204
3206
3205 datasize = [None, 0, 0L]
3207 datasize = [None, 0, 0L]
3206 fullsize = [None, 0, 0L]
3208 fullsize = [None, 0, 0L]
3207 deltasize = [None, 0, 0L]
3209 deltasize = [None, 0, 0L]
3208
3210
3209 def addsize(size, l):
3211 def addsize(size, l):
3210 if l[0] is None or size < l[0]:
3212 if l[0] is None or size < l[0]:
3211 l[0] = size
3213 l[0] = size
3212 if size > l[1]:
3214 if size > l[1]:
3213 l[1] = size
3215 l[1] = size
3214 l[2] += size
3216 l[2] += size
3215
3217
3216 numrevs = len(r)
3218 numrevs = len(r)
3217 for rev in xrange(numrevs):
3219 for rev in xrange(numrevs):
3218 p1, p2 = r.parentrevs(rev)
3220 p1, p2 = r.parentrevs(rev)
3219 delta = r.deltaparent(rev)
3221 delta = r.deltaparent(rev)
3220 if format > 0:
3222 if format > 0:
3221 addsize(r.rawsize(rev), datasize)
3223 addsize(r.rawsize(rev), datasize)
3222 if p2 != nullrev:
3224 if p2 != nullrev:
3223 nummerges += 1
3225 nummerges += 1
3224 size = r.length(rev)
3226 size = r.length(rev)
3225 if delta == nullrev:
3227 if delta == nullrev:
3226 chainlengths.append(0)
3228 chainlengths.append(0)
3227 numfull += 1
3229 numfull += 1
3228 addsize(size, fullsize)
3230 addsize(size, fullsize)
3229 else:
3231 else:
3230 chainlengths.append(chainlengths[delta] + 1)
3232 chainlengths.append(chainlengths[delta] + 1)
3231 addsize(size, deltasize)
3233 addsize(size, deltasize)
3232 if delta == rev - 1:
3234 if delta == rev - 1:
3233 numprev += 1
3235 numprev += 1
3234 if delta == p1:
3236 if delta == p1:
3235 nump1prev += 1
3237 nump1prev += 1
3236 elif delta == p2:
3238 elif delta == p2:
3237 nump2prev += 1
3239 nump2prev += 1
3238 elif delta == p1:
3240 elif delta == p1:
3239 nump1 += 1
3241 nump1 += 1
3240 elif delta == p2:
3242 elif delta == p2:
3241 nump2 += 1
3243 nump2 += 1
3242 elif delta != nullrev:
3244 elif delta != nullrev:
3243 numother += 1
3245 numother += 1
3244
3246
3245 # Adjust size min value for empty cases
3247 # Adjust size min value for empty cases
3246 for size in (datasize, fullsize, deltasize):
3248 for size in (datasize, fullsize, deltasize):
3247 if size[0] is None:
3249 if size[0] is None:
3248 size[0] = 0
3250 size[0] = 0
3249
3251
3250 numdeltas = numrevs - numfull
3252 numdeltas = numrevs - numfull
3251 numoprev = numprev - nump1prev - nump2prev
3253 numoprev = numprev - nump1prev - nump2prev
3252 totalrawsize = datasize[2]
3254 totalrawsize = datasize[2]
3253 datasize[2] /= numrevs
3255 datasize[2] /= numrevs
3254 fulltotal = fullsize[2]
3256 fulltotal = fullsize[2]
3255 fullsize[2] /= numfull
3257 fullsize[2] /= numfull
3256 deltatotal = deltasize[2]
3258 deltatotal = deltasize[2]
3257 if numrevs - numfull > 0:
3259 if numrevs - numfull > 0:
3258 deltasize[2] /= numrevs - numfull
3260 deltasize[2] /= numrevs - numfull
3259 totalsize = fulltotal + deltatotal
3261 totalsize = fulltotal + deltatotal
3260 avgchainlen = sum(chainlengths) / numrevs
3262 avgchainlen = sum(chainlengths) / numrevs
3261 maxchainlen = max(chainlengths)
3263 maxchainlen = max(chainlengths)
3262 compratio = 1
3264 compratio = 1
3263 if totalsize:
3265 if totalsize:
3264 compratio = totalrawsize / totalsize
3266 compratio = totalrawsize / totalsize
3265
3267
3266 basedfmtstr = '%%%dd\n'
3268 basedfmtstr = '%%%dd\n'
3267 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3269 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3268
3270
3269 def dfmtstr(max):
3271 def dfmtstr(max):
3270 return basedfmtstr % len(str(max))
3272 return basedfmtstr % len(str(max))
3271 def pcfmtstr(max, padding=0):
3273 def pcfmtstr(max, padding=0):
3272 return basepcfmtstr % (len(str(max)), ' ' * padding)
3274 return basepcfmtstr % (len(str(max)), ' ' * padding)
3273
3275
3274 def pcfmt(value, total):
3276 def pcfmt(value, total):
3275 if total:
3277 if total:
3276 return (value, 100 * float(value) / total)
3278 return (value, 100 * float(value) / total)
3277 else:
3279 else:
3278 return value, 100.0
3280 return value, 100.0
3279
3281
3280 ui.write(('format : %d\n') % format)
3282 ui.write(('format : %d\n') % format)
3281 ui.write(('flags : %s\n') % ', '.join(flags))
3283 ui.write(('flags : %s\n') % ', '.join(flags))
3282
3284
3283 ui.write('\n')
3285 ui.write('\n')
3284 fmt = pcfmtstr(totalsize)
3286 fmt = pcfmtstr(totalsize)
3285 fmt2 = dfmtstr(totalsize)
3287 fmt2 = dfmtstr(totalsize)
3286 ui.write(('revisions : ') + fmt2 % numrevs)
3288 ui.write(('revisions : ') + fmt2 % numrevs)
3287 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3289 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3288 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3290 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3289 ui.write(('revisions : ') + fmt2 % numrevs)
3291 ui.write(('revisions : ') + fmt2 % numrevs)
3290 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3292 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3291 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3293 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3292 ui.write(('revision size : ') + fmt2 % totalsize)
3294 ui.write(('revision size : ') + fmt2 % totalsize)
3293 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3295 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3294 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3296 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3295
3297
3296 ui.write('\n')
3298 ui.write('\n')
3297 fmt = dfmtstr(max(avgchainlen, compratio))
3299 fmt = dfmtstr(max(avgchainlen, compratio))
3298 ui.write(('avg chain length : ') + fmt % avgchainlen)
3300 ui.write(('avg chain length : ') + fmt % avgchainlen)
3299 ui.write(('max chain length : ') + fmt % maxchainlen)
3301 ui.write(('max chain length : ') + fmt % maxchainlen)
3300 ui.write(('compression ratio : ') + fmt % compratio)
3302 ui.write(('compression ratio : ') + fmt % compratio)
3301
3303
3302 if format > 0:
3304 if format > 0:
3303 ui.write('\n')
3305 ui.write('\n')
3304 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3306 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3305 % tuple(datasize))
3307 % tuple(datasize))
3306 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3308 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3307 % tuple(fullsize))
3309 % tuple(fullsize))
3308 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3310 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3309 % tuple(deltasize))
3311 % tuple(deltasize))
3310
3312
3311 if numdeltas > 0:
3313 if numdeltas > 0:
3312 ui.write('\n')
3314 ui.write('\n')
3313 fmt = pcfmtstr(numdeltas)
3315 fmt = pcfmtstr(numdeltas)
3314 fmt2 = pcfmtstr(numdeltas, 4)
3316 fmt2 = pcfmtstr(numdeltas, 4)
3315 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3317 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3316 if numprev > 0:
3318 if numprev > 0:
3317 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3319 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3318 numprev))
3320 numprev))
3319 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3321 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3320 numprev))
3322 numprev))
3321 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3323 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3322 numprev))
3324 numprev))
3323 if gdelta:
3325 if gdelta:
3324 ui.write(('deltas against p1 : ')
3326 ui.write(('deltas against p1 : ')
3325 + fmt % pcfmt(nump1, numdeltas))
3327 + fmt % pcfmt(nump1, numdeltas))
3326 ui.write(('deltas against p2 : ')
3328 ui.write(('deltas against p2 : ')
3327 + fmt % pcfmt(nump2, numdeltas))
3329 + fmt % pcfmt(nump2, numdeltas))
3328 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3330 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3329 numdeltas))
3331 numdeltas))
3330
3332
3331 @command('debugrevspec',
3333 @command('debugrevspec',
3332 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3334 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3333 ('REVSPEC'))
3335 ('REVSPEC'))
3334 def debugrevspec(ui, repo, expr, **opts):
3336 def debugrevspec(ui, repo, expr, **opts):
3335 """parse and apply a revision specification
3337 """parse and apply a revision specification
3336
3338
3337 Use --verbose to print the parsed tree before and after aliases
3339 Use --verbose to print the parsed tree before and after aliases
3338 expansion.
3340 expansion.
3339 """
3341 """
3340 if ui.verbose:
3342 if ui.verbose:
3341 tree = revset.parse(expr, lookup=repo.__contains__)
3343 tree = revset.parse(expr, lookup=repo.__contains__)
3342 ui.note(revset.prettyformat(tree), "\n")
3344 ui.note(revset.prettyformat(tree), "\n")
3343 newtree = revset.findaliases(ui, tree)
3345 newtree = revset.findaliases(ui, tree)
3344 if newtree != tree:
3346 if newtree != tree:
3345 ui.note(revset.prettyformat(newtree), "\n")
3347 ui.note(revset.prettyformat(newtree), "\n")
3346 tree = newtree
3348 tree = newtree
3347 newtree = revset.foldconcat(tree)
3349 newtree = revset.foldconcat(tree)
3348 if newtree != tree:
3350 if newtree != tree:
3349 ui.note(revset.prettyformat(newtree), "\n")
3351 ui.note(revset.prettyformat(newtree), "\n")
3350 if opts["optimize"]:
3352 if opts["optimize"]:
3351 weight, optimizedtree = revset.optimize(newtree, True)
3353 weight, optimizedtree = revset.optimize(newtree, True)
3352 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3354 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3353 func = revset.match(ui, expr, repo)
3355 func = revset.match(ui, expr, repo)
3354 revs = func(repo)
3356 revs = func(repo)
3355 if ui.verbose:
3357 if ui.verbose:
3356 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3358 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3357 for c in revs:
3359 for c in revs:
3358 ui.write("%s\n" % c)
3360 ui.write("%s\n" % c)
3359
3361
3360 @command('debugsetparents', [], _('REV1 [REV2]'))
3362 @command('debugsetparents', [], _('REV1 [REV2]'))
3361 def debugsetparents(ui, repo, rev1, rev2=None):
3363 def debugsetparents(ui, repo, rev1, rev2=None):
3362 """manually set the parents of the current working directory
3364 """manually set the parents of the current working directory
3363
3365
3364 This is useful for writing repository conversion tools, but should
3366 This is useful for writing repository conversion tools, but should
3365 be used with care. For example, neither the working directory nor the
3367 be used with care. For example, neither the working directory nor the
3366 dirstate is updated, so file status may be incorrect after running this
3368 dirstate is updated, so file status may be incorrect after running this
3367 command.
3369 command.
3368
3370
3369 Returns 0 on success.
3371 Returns 0 on success.
3370 """
3372 """
3371
3373
3372 r1 = scmutil.revsingle(repo, rev1).node()
3374 r1 = scmutil.revsingle(repo, rev1).node()
3373 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3375 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3374
3376
3375 wlock = repo.wlock()
3377 wlock = repo.wlock()
3376 try:
3378 try:
3377 repo.dirstate.beginparentchange()
3379 repo.dirstate.beginparentchange()
3378 repo.setparents(r1, r2)
3380 repo.setparents(r1, r2)
3379 repo.dirstate.endparentchange()
3381 repo.dirstate.endparentchange()
3380 finally:
3382 finally:
3381 wlock.release()
3383 wlock.release()
3382
3384
3383 @command('debugdirstate|debugstate',
3385 @command('debugdirstate|debugstate',
3384 [('', 'nodates', None, _('do not display the saved mtime')),
3386 [('', 'nodates', None, _('do not display the saved mtime')),
3385 ('', 'datesort', None, _('sort by saved mtime'))],
3387 ('', 'datesort', None, _('sort by saved mtime'))],
3386 _('[OPTION]...'))
3388 _('[OPTION]...'))
3387 def debugstate(ui, repo, **opts):
3389 def debugstate(ui, repo, **opts):
3388 """show the contents of the current dirstate"""
3390 """show the contents of the current dirstate"""
3389
3391
3390 nodates = opts.get('nodates')
3392 nodates = opts.get('nodates')
3391 datesort = opts.get('datesort')
3393 datesort = opts.get('datesort')
3392
3394
3393 timestr = ""
3395 timestr = ""
3394 if datesort:
3396 if datesort:
3395 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3397 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3396 else:
3398 else:
3397 keyfunc = None # sort by filename
3399 keyfunc = None # sort by filename
3398 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3400 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3399 if ent[3] == -1:
3401 if ent[3] == -1:
3400 timestr = 'unset '
3402 timestr = 'unset '
3401 elif nodates:
3403 elif nodates:
3402 timestr = 'set '
3404 timestr = 'set '
3403 else:
3405 else:
3404 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3406 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3405 time.localtime(ent[3]))
3407 time.localtime(ent[3]))
3406 if ent[1] & 0o20000:
3408 if ent[1] & 0o20000:
3407 mode = 'lnk'
3409 mode = 'lnk'
3408 else:
3410 else:
3409 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3411 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3410 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3412 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3411 for f in repo.dirstate.copies():
3413 for f in repo.dirstate.copies():
3412 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3414 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3413
3415
3414 @command('debugsub',
3416 @command('debugsub',
3415 [('r', 'rev', '',
3417 [('r', 'rev', '',
3416 _('revision to check'), _('REV'))],
3418 _('revision to check'), _('REV'))],
3417 _('[-r REV] [REV]'))
3419 _('[-r REV] [REV]'))
3418 def debugsub(ui, repo, rev=None):
3420 def debugsub(ui, repo, rev=None):
3419 ctx = scmutil.revsingle(repo, rev, None)
3421 ctx = scmutil.revsingle(repo, rev, None)
3420 for k, v in sorted(ctx.substate.items()):
3422 for k, v in sorted(ctx.substate.items()):
3421 ui.write(('path %s\n') % k)
3423 ui.write(('path %s\n') % k)
3422 ui.write((' source %s\n') % v[0])
3424 ui.write((' source %s\n') % v[0])
3423 ui.write((' revision %s\n') % v[1])
3425 ui.write((' revision %s\n') % v[1])
3424
3426
3425 @command('debugsuccessorssets',
3427 @command('debugsuccessorssets',
3426 [],
3428 [],
3427 _('[REV]'))
3429 _('[REV]'))
3428 def debugsuccessorssets(ui, repo, *revs):
3430 def debugsuccessorssets(ui, repo, *revs):
3429 """show set of successors for revision
3431 """show set of successors for revision
3430
3432
3431 A successors set of changeset A is a consistent group of revisions that
3433 A successors set of changeset A is a consistent group of revisions that
3432 succeed A. It contains non-obsolete changesets only.
3434 succeed A. It contains non-obsolete changesets only.
3433
3435
3434 In most cases a changeset A has a single successors set containing a single
3436 In most cases a changeset A has a single successors set containing a single
3435 successor (changeset A replaced by A').
3437 successor (changeset A replaced by A').
3436
3438
3437 A changeset that is made obsolete with no successors are called "pruned".
3439 A changeset that is made obsolete with no successors are called "pruned".
3438 Such changesets have no successors sets at all.
3440 Such changesets have no successors sets at all.
3439
3441
3440 A changeset that has been "split" will have a successors set containing
3442 A changeset that has been "split" will have a successors set containing
3441 more than one successor.
3443 more than one successor.
3442
3444
3443 A changeset that has been rewritten in multiple different ways is called
3445 A changeset that has been rewritten in multiple different ways is called
3444 "divergent". Such changesets have multiple successor sets (each of which
3446 "divergent". Such changesets have multiple successor sets (each of which
3445 may also be split, i.e. have multiple successors).
3447 may also be split, i.e. have multiple successors).
3446
3448
3447 Results are displayed as follows::
3449 Results are displayed as follows::
3448
3450
3449 <rev1>
3451 <rev1>
3450 <successors-1A>
3452 <successors-1A>
3451 <rev2>
3453 <rev2>
3452 <successors-2A>
3454 <successors-2A>
3453 <successors-2B1> <successors-2B2> <successors-2B3>
3455 <successors-2B1> <successors-2B2> <successors-2B3>
3454
3456
3455 Here rev2 has two possible (i.e. divergent) successors sets. The first
3457 Here rev2 has two possible (i.e. divergent) successors sets. The first
3456 holds one element, whereas the second holds three (i.e. the changeset has
3458 holds one element, whereas the second holds three (i.e. the changeset has
3457 been split).
3459 been split).
3458 """
3460 """
3459 # passed to successorssets caching computation from one call to another
3461 # passed to successorssets caching computation from one call to another
3460 cache = {}
3462 cache = {}
3461 ctx2str = str
3463 ctx2str = str
3462 node2str = short
3464 node2str = short
3463 if ui.debug():
3465 if ui.debug():
3464 def ctx2str(ctx):
3466 def ctx2str(ctx):
3465 return ctx.hex()
3467 return ctx.hex()
3466 node2str = hex
3468 node2str = hex
3467 for rev in scmutil.revrange(repo, revs):
3469 for rev in scmutil.revrange(repo, revs):
3468 ctx = repo[rev]
3470 ctx = repo[rev]
3469 ui.write('%s\n'% ctx2str(ctx))
3471 ui.write('%s\n'% ctx2str(ctx))
3470 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3472 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3471 if succsset:
3473 if succsset:
3472 ui.write(' ')
3474 ui.write(' ')
3473 ui.write(node2str(succsset[0]))
3475 ui.write(node2str(succsset[0]))
3474 for node in succsset[1:]:
3476 for node in succsset[1:]:
3475 ui.write(' ')
3477 ui.write(' ')
3476 ui.write(node2str(node))
3478 ui.write(node2str(node))
3477 ui.write('\n')
3479 ui.write('\n')
3478
3480
3479 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3481 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3480 def debugwalk(ui, repo, *pats, **opts):
3482 def debugwalk(ui, repo, *pats, **opts):
3481 """show how files match on given patterns"""
3483 """show how files match on given patterns"""
3482 m = scmutil.match(repo[None], pats, opts)
3484 m = scmutil.match(repo[None], pats, opts)
3483 items = list(repo.walk(m))
3485 items = list(repo.walk(m))
3484 if not items:
3486 if not items:
3485 return
3487 return
3486 f = lambda fn: fn
3488 f = lambda fn: fn
3487 if ui.configbool('ui', 'slash') and os.sep != '/':
3489 if ui.configbool('ui', 'slash') and os.sep != '/':
3488 f = lambda fn: util.normpath(fn)
3490 f = lambda fn: util.normpath(fn)
3489 fmt = 'f %%-%ds %%-%ds %%s' % (
3491 fmt = 'f %%-%ds %%-%ds %%s' % (
3490 max([len(abs) for abs in items]),
3492 max([len(abs) for abs in items]),
3491 max([len(m.rel(abs)) for abs in items]))
3493 max([len(m.rel(abs)) for abs in items]))
3492 for abs in items:
3494 for abs in items:
3493 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3495 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3494 ui.write("%s\n" % line.rstrip())
3496 ui.write("%s\n" % line.rstrip())
3495
3497
3496 @command('debugwireargs',
3498 @command('debugwireargs',
3497 [('', 'three', '', 'three'),
3499 [('', 'three', '', 'three'),
3498 ('', 'four', '', 'four'),
3500 ('', 'four', '', 'four'),
3499 ('', 'five', '', 'five'),
3501 ('', 'five', '', 'five'),
3500 ] + remoteopts,
3502 ] + remoteopts,
3501 _('REPO [OPTIONS]... [ONE [TWO]]'),
3503 _('REPO [OPTIONS]... [ONE [TWO]]'),
3502 norepo=True)
3504 norepo=True)
3503 def debugwireargs(ui, repopath, *vals, **opts):
3505 def debugwireargs(ui, repopath, *vals, **opts):
3504 repo = hg.peer(ui, opts, repopath)
3506 repo = hg.peer(ui, opts, repopath)
3505 for opt in remoteopts:
3507 for opt in remoteopts:
3506 del opts[opt[1]]
3508 del opts[opt[1]]
3507 args = {}
3509 args = {}
3508 for k, v in opts.iteritems():
3510 for k, v in opts.iteritems():
3509 if v:
3511 if v:
3510 args[k] = v
3512 args[k] = v
3511 # run twice to check that we don't mess up the stream for the next command
3513 # run twice to check that we don't mess up the stream for the next command
3512 res1 = repo.debugwireargs(*vals, **args)
3514 res1 = repo.debugwireargs(*vals, **args)
3513 res2 = repo.debugwireargs(*vals, **args)
3515 res2 = repo.debugwireargs(*vals, **args)
3514 ui.write("%s\n" % res1)
3516 ui.write("%s\n" % res1)
3515 if res1 != res2:
3517 if res1 != res2:
3516 ui.warn("%s\n" % res2)
3518 ui.warn("%s\n" % res2)
3517
3519
3518 @command('^diff',
3520 @command('^diff',
3519 [('r', 'rev', [], _('revision'), _('REV')),
3521 [('r', 'rev', [], _('revision'), _('REV')),
3520 ('c', 'change', '', _('change made by revision'), _('REV'))
3522 ('c', 'change', '', _('change made by revision'), _('REV'))
3521 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3523 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3522 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3524 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3523 inferrepo=True)
3525 inferrepo=True)
3524 def diff(ui, repo, *pats, **opts):
3526 def diff(ui, repo, *pats, **opts):
3525 """diff repository (or selected files)
3527 """diff repository (or selected files)
3526
3528
3527 Show differences between revisions for the specified files.
3529 Show differences between revisions for the specified files.
3528
3530
3529 Differences between files are shown using the unified diff format.
3531 Differences between files are shown using the unified diff format.
3530
3532
3531 .. note::
3533 .. note::
3532
3534
3533 diff may generate unexpected results for merges, as it will
3535 diff may generate unexpected results for merges, as it will
3534 default to comparing against the working directory's first
3536 default to comparing against the working directory's first
3535 parent changeset if no revisions are specified.
3537 parent changeset if no revisions are specified.
3536
3538
3537 When two revision arguments are given, then changes are shown
3539 When two revision arguments are given, then changes are shown
3538 between those revisions. If only one revision is specified then
3540 between those revisions. If only one revision is specified then
3539 that revision is compared to the working directory, and, when no
3541 that revision is compared to the working directory, and, when no
3540 revisions are specified, the working directory files are compared
3542 revisions are specified, the working directory files are compared
3541 to its parent.
3543 to its parent.
3542
3544
3543 Alternatively you can specify -c/--change with a revision to see
3545 Alternatively you can specify -c/--change with a revision to see
3544 the changes in that changeset relative to its first parent.
3546 the changes in that changeset relative to its first parent.
3545
3547
3546 Without the -a/--text option, diff will avoid generating diffs of
3548 Without the -a/--text option, diff will avoid generating diffs of
3547 files it detects as binary. With -a, diff will generate a diff
3549 files it detects as binary. With -a, diff will generate a diff
3548 anyway, probably with undesirable results.
3550 anyway, probably with undesirable results.
3549
3551
3550 Use the -g/--git option to generate diffs in the git extended diff
3552 Use the -g/--git option to generate diffs in the git extended diff
3551 format. For more information, read :hg:`help diffs`.
3553 format. For more information, read :hg:`help diffs`.
3552
3554
3553 .. container:: verbose
3555 .. container:: verbose
3554
3556
3555 Examples:
3557 Examples:
3556
3558
3557 - compare a file in the current working directory to its parent::
3559 - compare a file in the current working directory to its parent::
3558
3560
3559 hg diff foo.c
3561 hg diff foo.c
3560
3562
3561 - compare two historical versions of a directory, with rename info::
3563 - compare two historical versions of a directory, with rename info::
3562
3564
3563 hg diff --git -r 1.0:1.2 lib/
3565 hg diff --git -r 1.0:1.2 lib/
3564
3566
3565 - get change stats relative to the last change on some date::
3567 - get change stats relative to the last change on some date::
3566
3568
3567 hg diff --stat -r "date('may 2')"
3569 hg diff --stat -r "date('may 2')"
3568
3570
3569 - diff all newly-added files that contain a keyword::
3571 - diff all newly-added files that contain a keyword::
3570
3572
3571 hg diff "set:added() and grep(GNU)"
3573 hg diff "set:added() and grep(GNU)"
3572
3574
3573 - compare a revision and its parents::
3575 - compare a revision and its parents::
3574
3576
3575 hg diff -c 9353 # compare against first parent
3577 hg diff -c 9353 # compare against first parent
3576 hg diff -r 9353^:9353 # same using revset syntax
3578 hg diff -r 9353^:9353 # same using revset syntax
3577 hg diff -r 9353^2:9353 # compare against the second parent
3579 hg diff -r 9353^2:9353 # compare against the second parent
3578
3580
3579 Returns 0 on success.
3581 Returns 0 on success.
3580 """
3582 """
3581
3583
3582 revs = opts.get('rev')
3584 revs = opts.get('rev')
3583 change = opts.get('change')
3585 change = opts.get('change')
3584 stat = opts.get('stat')
3586 stat = opts.get('stat')
3585 reverse = opts.get('reverse')
3587 reverse = opts.get('reverse')
3586
3588
3587 if revs and change:
3589 if revs and change:
3588 msg = _('cannot specify --rev and --change at the same time')
3590 msg = _('cannot specify --rev and --change at the same time')
3589 raise error.Abort(msg)
3591 raise error.Abort(msg)
3590 elif change:
3592 elif change:
3591 node2 = scmutil.revsingle(repo, change, None).node()
3593 node2 = scmutil.revsingle(repo, change, None).node()
3592 node1 = repo[node2].p1().node()
3594 node1 = repo[node2].p1().node()
3593 else:
3595 else:
3594 node1, node2 = scmutil.revpair(repo, revs)
3596 node1, node2 = scmutil.revpair(repo, revs)
3595
3597
3596 if reverse:
3598 if reverse:
3597 node1, node2 = node2, node1
3599 node1, node2 = node2, node1
3598
3600
3599 diffopts = patch.diffallopts(ui, opts)
3601 diffopts = patch.diffallopts(ui, opts)
3600 m = scmutil.match(repo[node2], pats, opts)
3602 m = scmutil.match(repo[node2], pats, opts)
3601 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3603 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3602 listsubrepos=opts.get('subrepos'),
3604 listsubrepos=opts.get('subrepos'),
3603 root=opts.get('root'))
3605 root=opts.get('root'))
3604
3606
3605 @command('^export',
3607 @command('^export',
3606 [('o', 'output', '',
3608 [('o', 'output', '',
3607 _('print output to file with formatted name'), _('FORMAT')),
3609 _('print output to file with formatted name'), _('FORMAT')),
3608 ('', 'switch-parent', None, _('diff against the second parent')),
3610 ('', 'switch-parent', None, _('diff against the second parent')),
3609 ('r', 'rev', [], _('revisions to export'), _('REV')),
3611 ('r', 'rev', [], _('revisions to export'), _('REV')),
3610 ] + diffopts,
3612 ] + diffopts,
3611 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3613 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3612 def export(ui, repo, *changesets, **opts):
3614 def export(ui, repo, *changesets, **opts):
3613 """dump the header and diffs for one or more changesets
3615 """dump the header and diffs for one or more changesets
3614
3616
3615 Print the changeset header and diffs for one or more revisions.
3617 Print the changeset header and diffs for one or more revisions.
3616 If no revision is given, the parent of the working directory is used.
3618 If no revision is given, the parent of the working directory is used.
3617
3619
3618 The information shown in the changeset header is: author, date,
3620 The information shown in the changeset header is: author, date,
3619 branch name (if non-default), changeset hash, parent(s) and commit
3621 branch name (if non-default), changeset hash, parent(s) and commit
3620 comment.
3622 comment.
3621
3623
3622 .. note::
3624 .. note::
3623
3625
3624 export may generate unexpected diff output for merge
3626 export may generate unexpected diff output for merge
3625 changesets, as it will compare the merge changeset against its
3627 changesets, as it will compare the merge changeset against its
3626 first parent only.
3628 first parent only.
3627
3629
3628 Output may be to a file, in which case the name of the file is
3630 Output may be to a file, in which case the name of the file is
3629 given using a format string. The formatting rules are as follows:
3631 given using a format string. The formatting rules are as follows:
3630
3632
3631 :``%%``: literal "%" character
3633 :``%%``: literal "%" character
3632 :``%H``: changeset hash (40 hexadecimal digits)
3634 :``%H``: changeset hash (40 hexadecimal digits)
3633 :``%N``: number of patches being generated
3635 :``%N``: number of patches being generated
3634 :``%R``: changeset revision number
3636 :``%R``: changeset revision number
3635 :``%b``: basename of the exporting repository
3637 :``%b``: basename of the exporting repository
3636 :``%h``: short-form changeset hash (12 hexadecimal digits)
3638 :``%h``: short-form changeset hash (12 hexadecimal digits)
3637 :``%m``: first line of the commit message (only alphanumeric characters)
3639 :``%m``: first line of the commit message (only alphanumeric characters)
3638 :``%n``: zero-padded sequence number, starting at 1
3640 :``%n``: zero-padded sequence number, starting at 1
3639 :``%r``: zero-padded changeset revision number
3641 :``%r``: zero-padded changeset revision number
3640
3642
3641 Without the -a/--text option, export will avoid generating diffs
3643 Without the -a/--text option, export will avoid generating diffs
3642 of files it detects as binary. With -a, export will generate a
3644 of files it detects as binary. With -a, export will generate a
3643 diff anyway, probably with undesirable results.
3645 diff anyway, probably with undesirable results.
3644
3646
3645 Use the -g/--git option to generate diffs in the git extended diff
3647 Use the -g/--git option to generate diffs in the git extended diff
3646 format. See :hg:`help diffs` for more information.
3648 format. See :hg:`help diffs` for more information.
3647
3649
3648 With the --switch-parent option, the diff will be against the
3650 With the --switch-parent option, the diff will be against the
3649 second parent. It can be useful to review a merge.
3651 second parent. It can be useful to review a merge.
3650
3652
3651 .. container:: verbose
3653 .. container:: verbose
3652
3654
3653 Examples:
3655 Examples:
3654
3656
3655 - use export and import to transplant a bugfix to the current
3657 - use export and import to transplant a bugfix to the current
3656 branch::
3658 branch::
3657
3659
3658 hg export -r 9353 | hg import -
3660 hg export -r 9353 | hg import -
3659
3661
3660 - export all the changesets between two revisions to a file with
3662 - export all the changesets between two revisions to a file with
3661 rename information::
3663 rename information::
3662
3664
3663 hg export --git -r 123:150 > changes.txt
3665 hg export --git -r 123:150 > changes.txt
3664
3666
3665 - split outgoing changes into a series of patches with
3667 - split outgoing changes into a series of patches with
3666 descriptive names::
3668 descriptive names::
3667
3669
3668 hg export -r "outgoing()" -o "%n-%m.patch"
3670 hg export -r "outgoing()" -o "%n-%m.patch"
3669
3671
3670 Returns 0 on success.
3672 Returns 0 on success.
3671 """
3673 """
3672 changesets += tuple(opts.get('rev', []))
3674 changesets += tuple(opts.get('rev', []))
3673 if not changesets:
3675 if not changesets:
3674 changesets = ['.']
3676 changesets = ['.']
3675 revs = scmutil.revrange(repo, changesets)
3677 revs = scmutil.revrange(repo, changesets)
3676 if not revs:
3678 if not revs:
3677 raise error.Abort(_("export requires at least one changeset"))
3679 raise error.Abort(_("export requires at least one changeset"))
3678 if len(revs) > 1:
3680 if len(revs) > 1:
3679 ui.note(_('exporting patches:\n'))
3681 ui.note(_('exporting patches:\n'))
3680 else:
3682 else:
3681 ui.note(_('exporting patch:\n'))
3683 ui.note(_('exporting patch:\n'))
3682 cmdutil.export(repo, revs, template=opts.get('output'),
3684 cmdutil.export(repo, revs, template=opts.get('output'),
3683 switch_parent=opts.get('switch_parent'),
3685 switch_parent=opts.get('switch_parent'),
3684 opts=patch.diffallopts(ui, opts))
3686 opts=patch.diffallopts(ui, opts))
3685
3687
3686 @command('files',
3688 @command('files',
3687 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3689 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3688 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3690 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3689 ] + walkopts + formatteropts + subrepoopts,
3691 ] + walkopts + formatteropts + subrepoopts,
3690 _('[OPTION]... [PATTERN]...'))
3692 _('[OPTION]... [PATTERN]...'))
3691 def files(ui, repo, *pats, **opts):
3693 def files(ui, repo, *pats, **opts):
3692 """list tracked files
3694 """list tracked files
3693
3695
3694 Print files under Mercurial control in the working directory or
3696 Print files under Mercurial control in the working directory or
3695 specified revision whose names match the given patterns (excluding
3697 specified revision whose names match the given patterns (excluding
3696 removed files).
3698 removed files).
3697
3699
3698 If no patterns are given to match, this command prints the names
3700 If no patterns are given to match, this command prints the names
3699 of all files under Mercurial control in the working directory.
3701 of all files under Mercurial control in the working directory.
3700
3702
3701 .. container:: verbose
3703 .. container:: verbose
3702
3704
3703 Examples:
3705 Examples:
3704
3706
3705 - list all files under the current directory::
3707 - list all files under the current directory::
3706
3708
3707 hg files .
3709 hg files .
3708
3710
3709 - shows sizes and flags for current revision::
3711 - shows sizes and flags for current revision::
3710
3712
3711 hg files -vr .
3713 hg files -vr .
3712
3714
3713 - list all files named README::
3715 - list all files named README::
3714
3716
3715 hg files -I "**/README"
3717 hg files -I "**/README"
3716
3718
3717 - list all binary files::
3719 - list all binary files::
3718
3720
3719 hg files "set:binary()"
3721 hg files "set:binary()"
3720
3722
3721 - find files containing a regular expression::
3723 - find files containing a regular expression::
3722
3724
3723 hg files "set:grep('bob')"
3725 hg files "set:grep('bob')"
3724
3726
3725 - search tracked file contents with xargs and grep::
3727 - search tracked file contents with xargs and grep::
3726
3728
3727 hg files -0 | xargs -0 grep foo
3729 hg files -0 | xargs -0 grep foo
3728
3730
3729 See :hg:`help patterns` and :hg:`help filesets` for more information
3731 See :hg:`help patterns` and :hg:`help filesets` for more information
3730 on specifying file patterns.
3732 on specifying file patterns.
3731
3733
3732 Returns 0 if a match is found, 1 otherwise.
3734 Returns 0 if a match is found, 1 otherwise.
3733
3735
3734 """
3736 """
3735 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3737 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3736
3738
3737 end = '\n'
3739 end = '\n'
3738 if opts.get('print0'):
3740 if opts.get('print0'):
3739 end = '\0'
3741 end = '\0'
3740 fm = ui.formatter('files', opts)
3742 fm = ui.formatter('files', opts)
3741 fmt = '%s' + end
3743 fmt = '%s' + end
3742
3744
3743 m = scmutil.match(ctx, pats, opts)
3745 m = scmutil.match(ctx, pats, opts)
3744 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3746 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3745
3747
3746 fm.end()
3748 fm.end()
3747
3749
3748 return ret
3750 return ret
3749
3751
3750 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3752 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3751 def forget(ui, repo, *pats, **opts):
3753 def forget(ui, repo, *pats, **opts):
3752 """forget the specified files on the next commit
3754 """forget the specified files on the next commit
3753
3755
3754 Mark the specified files so they will no longer be tracked
3756 Mark the specified files so they will no longer be tracked
3755 after the next commit.
3757 after the next commit.
3756
3758
3757 This only removes files from the current branch, not from the
3759 This only removes files from the current branch, not from the
3758 entire project history, and it does not delete them from the
3760 entire project history, and it does not delete them from the
3759 working directory.
3761 working directory.
3760
3762
3761 To delete the file from the working directory, see :hg:`remove`.
3763 To delete the file from the working directory, see :hg:`remove`.
3762
3764
3763 To undo a forget before the next commit, see :hg:`add`.
3765 To undo a forget before the next commit, see :hg:`add`.
3764
3766
3765 .. container:: verbose
3767 .. container:: verbose
3766
3768
3767 Examples:
3769 Examples:
3768
3770
3769 - forget newly-added binary files::
3771 - forget newly-added binary files::
3770
3772
3771 hg forget "set:added() and binary()"
3773 hg forget "set:added() and binary()"
3772
3774
3773 - forget files that would be excluded by .hgignore::
3775 - forget files that would be excluded by .hgignore::
3774
3776
3775 hg forget "set:hgignore()"
3777 hg forget "set:hgignore()"
3776
3778
3777 Returns 0 on success.
3779 Returns 0 on success.
3778 """
3780 """
3779
3781
3780 if not pats:
3782 if not pats:
3781 raise error.Abort(_('no files specified'))
3783 raise error.Abort(_('no files specified'))
3782
3784
3783 m = scmutil.match(repo[None], pats, opts)
3785 m = scmutil.match(repo[None], pats, opts)
3784 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3786 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3785 return rejected and 1 or 0
3787 return rejected and 1 or 0
3786
3788
3787 @command(
3789 @command(
3788 'graft',
3790 'graft',
3789 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3791 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3790 ('c', 'continue', False, _('resume interrupted graft')),
3792 ('c', 'continue', False, _('resume interrupted graft')),
3791 ('e', 'edit', False, _('invoke editor on commit messages')),
3793 ('e', 'edit', False, _('invoke editor on commit messages')),
3792 ('', 'log', None, _('append graft info to log message')),
3794 ('', 'log', None, _('append graft info to log message')),
3793 ('f', 'force', False, _('force graft')),
3795 ('f', 'force', False, _('force graft')),
3794 ('D', 'currentdate', False,
3796 ('D', 'currentdate', False,
3795 _('record the current date as commit date')),
3797 _('record the current date as commit date')),
3796 ('U', 'currentuser', False,
3798 ('U', 'currentuser', False,
3797 _('record the current user as committer'), _('DATE'))]
3799 _('record the current user as committer'), _('DATE'))]
3798 + commitopts2 + mergetoolopts + dryrunopts,
3800 + commitopts2 + mergetoolopts + dryrunopts,
3799 _('[OPTION]... [-r] REV...'))
3801 _('[OPTION]... [-r] REV...'))
3800 def graft(ui, repo, *revs, **opts):
3802 def graft(ui, repo, *revs, **opts):
3801 '''copy changes from other branches onto the current branch
3803 '''copy changes from other branches onto the current branch
3802
3804
3803 This command uses Mercurial's merge logic to copy individual
3805 This command uses Mercurial's merge logic to copy individual
3804 changes from other branches without merging branches in the
3806 changes from other branches without merging branches in the
3805 history graph. This is sometimes known as 'backporting' or
3807 history graph. This is sometimes known as 'backporting' or
3806 'cherry-picking'. By default, graft will copy user, date, and
3808 'cherry-picking'. By default, graft will copy user, date, and
3807 description from the source changesets.
3809 description from the source changesets.
3808
3810
3809 Changesets that are ancestors of the current revision, that have
3811 Changesets that are ancestors of the current revision, that have
3810 already been grafted, or that are merges will be skipped.
3812 already been grafted, or that are merges will be skipped.
3811
3813
3812 If --log is specified, log messages will have a comment appended
3814 If --log is specified, log messages will have a comment appended
3813 of the form::
3815 of the form::
3814
3816
3815 (grafted from CHANGESETHASH)
3817 (grafted from CHANGESETHASH)
3816
3818
3817 If --force is specified, revisions will be grafted even if they
3819 If --force is specified, revisions will be grafted even if they
3818 are already ancestors of or have been grafted to the destination.
3820 are already ancestors of or have been grafted to the destination.
3819 This is useful when the revisions have since been backed out.
3821 This is useful when the revisions have since been backed out.
3820
3822
3821 If a graft merge results in conflicts, the graft process is
3823 If a graft merge results in conflicts, the graft process is
3822 interrupted so that the current merge can be manually resolved.
3824 interrupted so that the current merge can be manually resolved.
3823 Once all conflicts are addressed, the graft process can be
3825 Once all conflicts are addressed, the graft process can be
3824 continued with the -c/--continue option.
3826 continued with the -c/--continue option.
3825
3827
3826 .. note::
3828 .. note::
3827
3829
3828 The -c/--continue option does not reapply earlier options, except
3830 The -c/--continue option does not reapply earlier options, except
3829 for --force.
3831 for --force.
3830
3832
3831 .. container:: verbose
3833 .. container:: verbose
3832
3834
3833 Examples:
3835 Examples:
3834
3836
3835 - copy a single change to the stable branch and edit its description::
3837 - copy a single change to the stable branch and edit its description::
3836
3838
3837 hg update stable
3839 hg update stable
3838 hg graft --edit 9393
3840 hg graft --edit 9393
3839
3841
3840 - graft a range of changesets with one exception, updating dates::
3842 - graft a range of changesets with one exception, updating dates::
3841
3843
3842 hg graft -D "2085::2093 and not 2091"
3844 hg graft -D "2085::2093 and not 2091"
3843
3845
3844 - continue a graft after resolving conflicts::
3846 - continue a graft after resolving conflicts::
3845
3847
3846 hg graft -c
3848 hg graft -c
3847
3849
3848 - show the source of a grafted changeset::
3850 - show the source of a grafted changeset::
3849
3851
3850 hg log --debug -r .
3852 hg log --debug -r .
3851
3853
3852 See :hg:`help revisions` and :hg:`help revsets` for more about
3854 See :hg:`help revisions` and :hg:`help revsets` for more about
3853 specifying revisions.
3855 specifying revisions.
3854
3856
3855 Returns 0 on successful completion.
3857 Returns 0 on successful completion.
3856 '''
3858 '''
3857 wlock = None
3859 wlock = None
3858 try:
3860 try:
3859 wlock = repo.wlock()
3861 wlock = repo.wlock()
3860 return _dograft(ui, repo, *revs, **opts)
3862 return _dograft(ui, repo, *revs, **opts)
3861 finally:
3863 finally:
3862 release(wlock)
3864 release(wlock)
3863
3865
3864 def _dograft(ui, repo, *revs, **opts):
3866 def _dograft(ui, repo, *revs, **opts):
3865 revs = list(revs)
3867 revs = list(revs)
3866 revs.extend(opts['rev'])
3868 revs.extend(opts['rev'])
3867
3869
3868 if not opts.get('user') and opts.get('currentuser'):
3870 if not opts.get('user') and opts.get('currentuser'):
3869 opts['user'] = ui.username()
3871 opts['user'] = ui.username()
3870 if not opts.get('date') and opts.get('currentdate'):
3872 if not opts.get('date') and opts.get('currentdate'):
3871 opts['date'] = "%d %d" % util.makedate()
3873 opts['date'] = "%d %d" % util.makedate()
3872
3874
3873 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3875 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3874
3876
3875 cont = False
3877 cont = False
3876 if opts['continue']:
3878 if opts['continue']:
3877 cont = True
3879 cont = True
3878 if revs:
3880 if revs:
3879 raise error.Abort(_("can't specify --continue and revisions"))
3881 raise error.Abort(_("can't specify --continue and revisions"))
3880 # read in unfinished revisions
3882 # read in unfinished revisions
3881 try:
3883 try:
3882 nodes = repo.vfs.read('graftstate').splitlines()
3884 nodes = repo.vfs.read('graftstate').splitlines()
3883 revs = [repo[node].rev() for node in nodes]
3885 revs = [repo[node].rev() for node in nodes]
3884 except IOError as inst:
3886 except IOError as inst:
3885 if inst.errno != errno.ENOENT:
3887 if inst.errno != errno.ENOENT:
3886 raise
3888 raise
3887 raise error.Abort(_("no graft state found, can't continue"))
3889 raise error.Abort(_("no graft state found, can't continue"))
3888 else:
3890 else:
3889 cmdutil.checkunfinished(repo)
3891 cmdutil.checkunfinished(repo)
3890 cmdutil.bailifchanged(repo)
3892 cmdutil.bailifchanged(repo)
3891 if not revs:
3893 if not revs:
3892 raise error.Abort(_('no revisions specified'))
3894 raise error.Abort(_('no revisions specified'))
3893 revs = scmutil.revrange(repo, revs)
3895 revs = scmutil.revrange(repo, revs)
3894
3896
3895 skipped = set()
3897 skipped = set()
3896 # check for merges
3898 # check for merges
3897 for rev in repo.revs('%ld and merge()', revs):
3899 for rev in repo.revs('%ld and merge()', revs):
3898 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3900 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3899 skipped.add(rev)
3901 skipped.add(rev)
3900 revs = [r for r in revs if r not in skipped]
3902 revs = [r for r in revs if r not in skipped]
3901 if not revs:
3903 if not revs:
3902 return -1
3904 return -1
3903
3905
3904 # Don't check in the --continue case, in effect retaining --force across
3906 # Don't check in the --continue case, in effect retaining --force across
3905 # --continues. That's because without --force, any revisions we decided to
3907 # --continues. That's because without --force, any revisions we decided to
3906 # skip would have been filtered out here, so they wouldn't have made their
3908 # skip would have been filtered out here, so they wouldn't have made their
3907 # way to the graftstate. With --force, any revisions we would have otherwise
3909 # way to the graftstate. With --force, any revisions we would have otherwise
3908 # skipped would not have been filtered out, and if they hadn't been applied
3910 # skipped would not have been filtered out, and if they hadn't been applied
3909 # already, they'd have been in the graftstate.
3911 # already, they'd have been in the graftstate.
3910 if not (cont or opts.get('force')):
3912 if not (cont or opts.get('force')):
3911 # check for ancestors of dest branch
3913 # check for ancestors of dest branch
3912 crev = repo['.'].rev()
3914 crev = repo['.'].rev()
3913 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3915 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3914 # Cannot use x.remove(y) on smart set, this has to be a list.
3916 # Cannot use x.remove(y) on smart set, this has to be a list.
3915 # XXX make this lazy in the future
3917 # XXX make this lazy in the future
3916 revs = list(revs)
3918 revs = list(revs)
3917 # don't mutate while iterating, create a copy
3919 # don't mutate while iterating, create a copy
3918 for rev in list(revs):
3920 for rev in list(revs):
3919 if rev in ancestors:
3921 if rev in ancestors:
3920 ui.warn(_('skipping ancestor revision %d:%s\n') %
3922 ui.warn(_('skipping ancestor revision %d:%s\n') %
3921 (rev, repo[rev]))
3923 (rev, repo[rev]))
3922 # XXX remove on list is slow
3924 # XXX remove on list is slow
3923 revs.remove(rev)
3925 revs.remove(rev)
3924 if not revs:
3926 if not revs:
3925 return -1
3927 return -1
3926
3928
3927 # analyze revs for earlier grafts
3929 # analyze revs for earlier grafts
3928 ids = {}
3930 ids = {}
3929 for ctx in repo.set("%ld", revs):
3931 for ctx in repo.set("%ld", revs):
3930 ids[ctx.hex()] = ctx.rev()
3932 ids[ctx.hex()] = ctx.rev()
3931 n = ctx.extra().get('source')
3933 n = ctx.extra().get('source')
3932 if n:
3934 if n:
3933 ids[n] = ctx.rev()
3935 ids[n] = ctx.rev()
3934
3936
3935 # check ancestors for earlier grafts
3937 # check ancestors for earlier grafts
3936 ui.debug('scanning for duplicate grafts\n')
3938 ui.debug('scanning for duplicate grafts\n')
3937
3939
3938 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3940 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3939 ctx = repo[rev]
3941 ctx = repo[rev]
3940 n = ctx.extra().get('source')
3942 n = ctx.extra().get('source')
3941 if n in ids:
3943 if n in ids:
3942 try:
3944 try:
3943 r = repo[n].rev()
3945 r = repo[n].rev()
3944 except error.RepoLookupError:
3946 except error.RepoLookupError:
3945 r = None
3947 r = None
3946 if r in revs:
3948 if r in revs:
3947 ui.warn(_('skipping revision %d:%s '
3949 ui.warn(_('skipping revision %d:%s '
3948 '(already grafted to %d:%s)\n')
3950 '(already grafted to %d:%s)\n')
3949 % (r, repo[r], rev, ctx))
3951 % (r, repo[r], rev, ctx))
3950 revs.remove(r)
3952 revs.remove(r)
3951 elif ids[n] in revs:
3953 elif ids[n] in revs:
3952 if r is None:
3954 if r is None:
3953 ui.warn(_('skipping already grafted revision %d:%s '
3955 ui.warn(_('skipping already grafted revision %d:%s '
3954 '(%d:%s also has unknown origin %s)\n')
3956 '(%d:%s also has unknown origin %s)\n')
3955 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3957 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3956 else:
3958 else:
3957 ui.warn(_('skipping already grafted revision %d:%s '
3959 ui.warn(_('skipping already grafted revision %d:%s '
3958 '(%d:%s also has origin %d:%s)\n')
3960 '(%d:%s also has origin %d:%s)\n')
3959 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3961 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3960 revs.remove(ids[n])
3962 revs.remove(ids[n])
3961 elif ctx.hex() in ids:
3963 elif ctx.hex() in ids:
3962 r = ids[ctx.hex()]
3964 r = ids[ctx.hex()]
3963 ui.warn(_('skipping already grafted revision %d:%s '
3965 ui.warn(_('skipping already grafted revision %d:%s '
3964 '(was grafted from %d:%s)\n') %
3966 '(was grafted from %d:%s)\n') %
3965 (r, repo[r], rev, ctx))
3967 (r, repo[r], rev, ctx))
3966 revs.remove(r)
3968 revs.remove(r)
3967 if not revs:
3969 if not revs:
3968 return -1
3970 return -1
3969
3971
3970 try:
3972 try:
3971 for pos, ctx in enumerate(repo.set("%ld", revs)):
3973 for pos, ctx in enumerate(repo.set("%ld", revs)):
3972 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3974 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3973 ctx.description().split('\n', 1)[0])
3975 ctx.description().split('\n', 1)[0])
3974 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3976 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3975 if names:
3977 if names:
3976 desc += ' (%s)' % ' '.join(names)
3978 desc += ' (%s)' % ' '.join(names)
3977 ui.status(_('grafting %s\n') % desc)
3979 ui.status(_('grafting %s\n') % desc)
3978 if opts.get('dry_run'):
3980 if opts.get('dry_run'):
3979 continue
3981 continue
3980
3982
3981 extra = ctx.extra().copy()
3983 extra = ctx.extra().copy()
3982 del extra['branch']
3984 del extra['branch']
3983 source = extra.get('source')
3985 source = extra.get('source')
3984 if source:
3986 if source:
3985 extra['intermediate-source'] = ctx.hex()
3987 extra['intermediate-source'] = ctx.hex()
3986 else:
3988 else:
3987 extra['source'] = ctx.hex()
3989 extra['source'] = ctx.hex()
3988 user = ctx.user()
3990 user = ctx.user()
3989 if opts.get('user'):
3991 if opts.get('user'):
3990 user = opts['user']
3992 user = opts['user']
3991 date = ctx.date()
3993 date = ctx.date()
3992 if opts.get('date'):
3994 if opts.get('date'):
3993 date = opts['date']
3995 date = opts['date']
3994 message = ctx.description()
3996 message = ctx.description()
3995 if opts.get('log'):
3997 if opts.get('log'):
3996 message += '\n(grafted from %s)' % ctx.hex()
3998 message += '\n(grafted from %s)' % ctx.hex()
3997
3999
3998 # we don't merge the first commit when continuing
4000 # we don't merge the first commit when continuing
3999 if not cont:
4001 if not cont:
4000 # perform the graft merge with p1(rev) as 'ancestor'
4002 # perform the graft merge with p1(rev) as 'ancestor'
4001 try:
4003 try:
4002 # ui.forcemerge is an internal variable, do not document
4004 # ui.forcemerge is an internal variable, do not document
4003 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4005 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4004 'graft')
4006 'graft')
4005 stats = mergemod.graft(repo, ctx, ctx.p1(),
4007 stats = mergemod.graft(repo, ctx, ctx.p1(),
4006 ['local', 'graft'])
4008 ['local', 'graft'])
4007 finally:
4009 finally:
4008 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4010 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4009 # report any conflicts
4011 # report any conflicts
4010 if stats and stats[3] > 0:
4012 if stats and stats[3] > 0:
4011 # write out state for --continue
4013 # write out state for --continue
4012 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4014 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4013 repo.vfs.write('graftstate', ''.join(nodelines))
4015 repo.vfs.write('graftstate', ''.join(nodelines))
4014 extra = ''
4016 extra = ''
4015 if opts.get('user'):
4017 if opts.get('user'):
4016 extra += ' --user %s' % opts['user']
4018 extra += ' --user %s' % opts['user']
4017 if opts.get('date'):
4019 if opts.get('date'):
4018 extra += ' --date %s' % opts['date']
4020 extra += ' --date %s' % opts['date']
4019 if opts.get('log'):
4021 if opts.get('log'):
4020 extra += ' --log'
4022 extra += ' --log'
4021 hint=_('use hg resolve and hg graft --continue%s') % extra
4023 hint=_('use hg resolve and hg graft --continue%s') % extra
4022 raise error.Abort(
4024 raise error.Abort(
4023 _("unresolved conflicts, can't continue"),
4025 _("unresolved conflicts, can't continue"),
4024 hint=hint)
4026 hint=hint)
4025 else:
4027 else:
4026 cont = False
4028 cont = False
4027
4029
4028 # commit
4030 # commit
4029 node = repo.commit(text=message, user=user,
4031 node = repo.commit(text=message, user=user,
4030 date=date, extra=extra, editor=editor)
4032 date=date, extra=extra, editor=editor)
4031 if node is None:
4033 if node is None:
4032 ui.warn(
4034 ui.warn(
4033 _('note: graft of %d:%s created no changes to commit\n') %
4035 _('note: graft of %d:%s created no changes to commit\n') %
4034 (ctx.rev(), ctx))
4036 (ctx.rev(), ctx))
4035 finally:
4037 finally:
4036 # TODO: get rid of this meaningless try/finally enclosing.
4038 # TODO: get rid of this meaningless try/finally enclosing.
4037 # this is kept only to reduce changes in a patch.
4039 # this is kept only to reduce changes in a patch.
4038 pass
4040 pass
4039
4041
4040 # remove state when we complete successfully
4042 # remove state when we complete successfully
4041 if not opts.get('dry_run'):
4043 if not opts.get('dry_run'):
4042 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4044 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4043
4045
4044 return 0
4046 return 0
4045
4047
4046 @command('grep',
4048 @command('grep',
4047 [('0', 'print0', None, _('end fields with NUL')),
4049 [('0', 'print0', None, _('end fields with NUL')),
4048 ('', 'all', None, _('print all revisions that match')),
4050 ('', 'all', None, _('print all revisions that match')),
4049 ('a', 'text', None, _('treat all files as text')),
4051 ('a', 'text', None, _('treat all files as text')),
4050 ('f', 'follow', None,
4052 ('f', 'follow', None,
4051 _('follow changeset history,'
4053 _('follow changeset history,'
4052 ' or file history across copies and renames')),
4054 ' or file history across copies and renames')),
4053 ('i', 'ignore-case', None, _('ignore case when matching')),
4055 ('i', 'ignore-case', None, _('ignore case when matching')),
4054 ('l', 'files-with-matches', None,
4056 ('l', 'files-with-matches', None,
4055 _('print only filenames and revisions that match')),
4057 _('print only filenames and revisions that match')),
4056 ('n', 'line-number', None, _('print matching line numbers')),
4058 ('n', 'line-number', None, _('print matching line numbers')),
4057 ('r', 'rev', [],
4059 ('r', 'rev', [],
4058 _('only search files changed within revision range'), _('REV')),
4060 _('only search files changed within revision range'), _('REV')),
4059 ('u', 'user', None, _('list the author (long with -v)')),
4061 ('u', 'user', None, _('list the author (long with -v)')),
4060 ('d', 'date', None, _('list the date (short with -q)')),
4062 ('d', 'date', None, _('list the date (short with -q)')),
4061 ] + walkopts,
4063 ] + walkopts,
4062 _('[OPTION]... PATTERN [FILE]...'),
4064 _('[OPTION]... PATTERN [FILE]...'),
4063 inferrepo=True)
4065 inferrepo=True)
4064 def grep(ui, repo, pattern, *pats, **opts):
4066 def grep(ui, repo, pattern, *pats, **opts):
4065 """search for a pattern in specified files and revisions
4067 """search for a pattern in specified files and revisions
4066
4068
4067 Search revisions of files for a regular expression.
4069 Search revisions of files for a regular expression.
4068
4070
4069 This command behaves differently than Unix grep. It only accepts
4071 This command behaves differently than Unix grep. It only accepts
4070 Python/Perl regexps. It searches repository history, not the
4072 Python/Perl regexps. It searches repository history, not the
4071 working directory. It always prints the revision number in which a
4073 working directory. It always prints the revision number in which a
4072 match appears.
4074 match appears.
4073
4075
4074 By default, grep only prints output for the first revision of a
4076 By default, grep only prints output for the first revision of a
4075 file in which it finds a match. To get it to print every revision
4077 file in which it finds a match. To get it to print every revision
4076 that contains a change in match status ("-" for a match that
4078 that contains a change in match status ("-" for a match that
4077 becomes a non-match, or "+" for a non-match that becomes a match),
4079 becomes a non-match, or "+" for a non-match that becomes a match),
4078 use the --all flag.
4080 use the --all flag.
4079
4081
4080 Returns 0 if a match is found, 1 otherwise.
4082 Returns 0 if a match is found, 1 otherwise.
4081 """
4083 """
4082 reflags = re.M
4084 reflags = re.M
4083 if opts.get('ignore_case'):
4085 if opts.get('ignore_case'):
4084 reflags |= re.I
4086 reflags |= re.I
4085 try:
4087 try:
4086 regexp = util.re.compile(pattern, reflags)
4088 regexp = util.re.compile(pattern, reflags)
4087 except re.error as inst:
4089 except re.error as inst:
4088 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4090 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4089 return 1
4091 return 1
4090 sep, eol = ':', '\n'
4092 sep, eol = ':', '\n'
4091 if opts.get('print0'):
4093 if opts.get('print0'):
4092 sep = eol = '\0'
4094 sep = eol = '\0'
4093
4095
4094 getfile = util.lrucachefunc(repo.file)
4096 getfile = util.lrucachefunc(repo.file)
4095
4097
4096 def matchlines(body):
4098 def matchlines(body):
4097 begin = 0
4099 begin = 0
4098 linenum = 0
4100 linenum = 0
4099 while begin < len(body):
4101 while begin < len(body):
4100 match = regexp.search(body, begin)
4102 match = regexp.search(body, begin)
4101 if not match:
4103 if not match:
4102 break
4104 break
4103 mstart, mend = match.span()
4105 mstart, mend = match.span()
4104 linenum += body.count('\n', begin, mstart) + 1
4106 linenum += body.count('\n', begin, mstart) + 1
4105 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4107 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4106 begin = body.find('\n', mend) + 1 or len(body) + 1
4108 begin = body.find('\n', mend) + 1 or len(body) + 1
4107 lend = begin - 1
4109 lend = begin - 1
4108 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4110 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4109
4111
4110 class linestate(object):
4112 class linestate(object):
4111 def __init__(self, line, linenum, colstart, colend):
4113 def __init__(self, line, linenum, colstart, colend):
4112 self.line = line
4114 self.line = line
4113 self.linenum = linenum
4115 self.linenum = linenum
4114 self.colstart = colstart
4116 self.colstart = colstart
4115 self.colend = colend
4117 self.colend = colend
4116
4118
4117 def __hash__(self):
4119 def __hash__(self):
4118 return hash((self.linenum, self.line))
4120 return hash((self.linenum, self.line))
4119
4121
4120 def __eq__(self, other):
4122 def __eq__(self, other):
4121 return self.line == other.line
4123 return self.line == other.line
4122
4124
4123 def __iter__(self):
4125 def __iter__(self):
4124 yield (self.line[:self.colstart], '')
4126 yield (self.line[:self.colstart], '')
4125 yield (self.line[self.colstart:self.colend], 'grep.match')
4127 yield (self.line[self.colstart:self.colend], 'grep.match')
4126 rest = self.line[self.colend:]
4128 rest = self.line[self.colend:]
4127 while rest != '':
4129 while rest != '':
4128 match = regexp.search(rest)
4130 match = regexp.search(rest)
4129 if not match:
4131 if not match:
4130 yield (rest, '')
4132 yield (rest, '')
4131 break
4133 break
4132 mstart, mend = match.span()
4134 mstart, mend = match.span()
4133 yield (rest[:mstart], '')
4135 yield (rest[:mstart], '')
4134 yield (rest[mstart:mend], 'grep.match')
4136 yield (rest[mstart:mend], 'grep.match')
4135 rest = rest[mend:]
4137 rest = rest[mend:]
4136
4138
4137 matches = {}
4139 matches = {}
4138 copies = {}
4140 copies = {}
4139 def grepbody(fn, rev, body):
4141 def grepbody(fn, rev, body):
4140 matches[rev].setdefault(fn, [])
4142 matches[rev].setdefault(fn, [])
4141 m = matches[rev][fn]
4143 m = matches[rev][fn]
4142 for lnum, cstart, cend, line in matchlines(body):
4144 for lnum, cstart, cend, line in matchlines(body):
4143 s = linestate(line, lnum, cstart, cend)
4145 s = linestate(line, lnum, cstart, cend)
4144 m.append(s)
4146 m.append(s)
4145
4147
4146 def difflinestates(a, b):
4148 def difflinestates(a, b):
4147 sm = difflib.SequenceMatcher(None, a, b)
4149 sm = difflib.SequenceMatcher(None, a, b)
4148 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4150 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4149 if tag == 'insert':
4151 if tag == 'insert':
4150 for i in xrange(blo, bhi):
4152 for i in xrange(blo, bhi):
4151 yield ('+', b[i])
4153 yield ('+', b[i])
4152 elif tag == 'delete':
4154 elif tag == 'delete':
4153 for i in xrange(alo, ahi):
4155 for i in xrange(alo, ahi):
4154 yield ('-', a[i])
4156 yield ('-', a[i])
4155 elif tag == 'replace':
4157 elif tag == 'replace':
4156 for i in xrange(alo, ahi):
4158 for i in xrange(alo, ahi):
4157 yield ('-', a[i])
4159 yield ('-', a[i])
4158 for i in xrange(blo, bhi):
4160 for i in xrange(blo, bhi):
4159 yield ('+', b[i])
4161 yield ('+', b[i])
4160
4162
4161 def display(fn, ctx, pstates, states):
4163 def display(fn, ctx, pstates, states):
4162 rev = ctx.rev()
4164 rev = ctx.rev()
4163 if ui.quiet:
4165 if ui.quiet:
4164 datefunc = util.shortdate
4166 datefunc = util.shortdate
4165 else:
4167 else:
4166 datefunc = util.datestr
4168 datefunc = util.datestr
4167 found = False
4169 found = False
4168 @util.cachefunc
4170 @util.cachefunc
4169 def binary():
4171 def binary():
4170 flog = getfile(fn)
4172 flog = getfile(fn)
4171 return util.binary(flog.read(ctx.filenode(fn)))
4173 return util.binary(flog.read(ctx.filenode(fn)))
4172
4174
4173 if opts.get('all'):
4175 if opts.get('all'):
4174 iter = difflinestates(pstates, states)
4176 iter = difflinestates(pstates, states)
4175 else:
4177 else:
4176 iter = [('', l) for l in states]
4178 iter = [('', l) for l in states]
4177 for change, l in iter:
4179 for change, l in iter:
4178 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4180 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4179
4181
4180 if opts.get('line_number'):
4182 if opts.get('line_number'):
4181 cols.append((str(l.linenum), 'grep.linenumber'))
4183 cols.append((str(l.linenum), 'grep.linenumber'))
4182 if opts.get('all'):
4184 if opts.get('all'):
4183 cols.append((change, 'grep.change'))
4185 cols.append((change, 'grep.change'))
4184 if opts.get('user'):
4186 if opts.get('user'):
4185 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4187 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4186 if opts.get('date'):
4188 if opts.get('date'):
4187 cols.append((datefunc(ctx.date()), 'grep.date'))
4189 cols.append((datefunc(ctx.date()), 'grep.date'))
4188 for col, label in cols[:-1]:
4190 for col, label in cols[:-1]:
4189 ui.write(col, label=label)
4191 ui.write(col, label=label)
4190 ui.write(sep, label='grep.sep')
4192 ui.write(sep, label='grep.sep')
4191 ui.write(cols[-1][0], label=cols[-1][1])
4193 ui.write(cols[-1][0], label=cols[-1][1])
4192 if not opts.get('files_with_matches'):
4194 if not opts.get('files_with_matches'):
4193 ui.write(sep, label='grep.sep')
4195 ui.write(sep, label='grep.sep')
4194 if not opts.get('text') and binary():
4196 if not opts.get('text') and binary():
4195 ui.write(" Binary file matches")
4197 ui.write(" Binary file matches")
4196 else:
4198 else:
4197 for s, label in l:
4199 for s, label in l:
4198 ui.write(s, label=label)
4200 ui.write(s, label=label)
4199 ui.write(eol)
4201 ui.write(eol)
4200 found = True
4202 found = True
4201 if opts.get('files_with_matches'):
4203 if opts.get('files_with_matches'):
4202 break
4204 break
4203 return found
4205 return found
4204
4206
4205 skip = {}
4207 skip = {}
4206 revfiles = {}
4208 revfiles = {}
4207 matchfn = scmutil.match(repo[None], pats, opts)
4209 matchfn = scmutil.match(repo[None], pats, opts)
4208 found = False
4210 found = False
4209 follow = opts.get('follow')
4211 follow = opts.get('follow')
4210
4212
4211 def prep(ctx, fns):
4213 def prep(ctx, fns):
4212 rev = ctx.rev()
4214 rev = ctx.rev()
4213 pctx = ctx.p1()
4215 pctx = ctx.p1()
4214 parent = pctx.rev()
4216 parent = pctx.rev()
4215 matches.setdefault(rev, {})
4217 matches.setdefault(rev, {})
4216 matches.setdefault(parent, {})
4218 matches.setdefault(parent, {})
4217 files = revfiles.setdefault(rev, [])
4219 files = revfiles.setdefault(rev, [])
4218 for fn in fns:
4220 for fn in fns:
4219 flog = getfile(fn)
4221 flog = getfile(fn)
4220 try:
4222 try:
4221 fnode = ctx.filenode(fn)
4223 fnode = ctx.filenode(fn)
4222 except error.LookupError:
4224 except error.LookupError:
4223 continue
4225 continue
4224
4226
4225 copied = flog.renamed(fnode)
4227 copied = flog.renamed(fnode)
4226 copy = follow and copied and copied[0]
4228 copy = follow and copied and copied[0]
4227 if copy:
4229 if copy:
4228 copies.setdefault(rev, {})[fn] = copy
4230 copies.setdefault(rev, {})[fn] = copy
4229 if fn in skip:
4231 if fn in skip:
4230 if copy:
4232 if copy:
4231 skip[copy] = True
4233 skip[copy] = True
4232 continue
4234 continue
4233 files.append(fn)
4235 files.append(fn)
4234
4236
4235 if fn not in matches[rev]:
4237 if fn not in matches[rev]:
4236 grepbody(fn, rev, flog.read(fnode))
4238 grepbody(fn, rev, flog.read(fnode))
4237
4239
4238 pfn = copy or fn
4240 pfn = copy or fn
4239 if pfn not in matches[parent]:
4241 if pfn not in matches[parent]:
4240 try:
4242 try:
4241 fnode = pctx.filenode(pfn)
4243 fnode = pctx.filenode(pfn)
4242 grepbody(pfn, parent, flog.read(fnode))
4244 grepbody(pfn, parent, flog.read(fnode))
4243 except error.LookupError:
4245 except error.LookupError:
4244 pass
4246 pass
4245
4247
4246 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4248 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4247 rev = ctx.rev()
4249 rev = ctx.rev()
4248 parent = ctx.p1().rev()
4250 parent = ctx.p1().rev()
4249 for fn in sorted(revfiles.get(rev, [])):
4251 for fn in sorted(revfiles.get(rev, [])):
4250 states = matches[rev][fn]
4252 states = matches[rev][fn]
4251 copy = copies.get(rev, {}).get(fn)
4253 copy = copies.get(rev, {}).get(fn)
4252 if fn in skip:
4254 if fn in skip:
4253 if copy:
4255 if copy:
4254 skip[copy] = True
4256 skip[copy] = True
4255 continue
4257 continue
4256 pstates = matches.get(parent, {}).get(copy or fn, [])
4258 pstates = matches.get(parent, {}).get(copy or fn, [])
4257 if pstates or states:
4259 if pstates or states:
4258 r = display(fn, ctx, pstates, states)
4260 r = display(fn, ctx, pstates, states)
4259 found = found or r
4261 found = found or r
4260 if r and not opts.get('all'):
4262 if r and not opts.get('all'):
4261 skip[fn] = True
4263 skip[fn] = True
4262 if copy:
4264 if copy:
4263 skip[copy] = True
4265 skip[copy] = True
4264 del matches[rev]
4266 del matches[rev]
4265 del revfiles[rev]
4267 del revfiles[rev]
4266
4268
4267 return not found
4269 return not found
4268
4270
4269 @command('heads',
4271 @command('heads',
4270 [('r', 'rev', '',
4272 [('r', 'rev', '',
4271 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4273 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4272 ('t', 'topo', False, _('show topological heads only')),
4274 ('t', 'topo', False, _('show topological heads only')),
4273 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4275 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4274 ('c', 'closed', False, _('show normal and closed branch heads')),
4276 ('c', 'closed', False, _('show normal and closed branch heads')),
4275 ] + templateopts,
4277 ] + templateopts,
4276 _('[-ct] [-r STARTREV] [REV]...'))
4278 _('[-ct] [-r STARTREV] [REV]...'))
4277 def heads(ui, repo, *branchrevs, **opts):
4279 def heads(ui, repo, *branchrevs, **opts):
4278 """show branch heads
4280 """show branch heads
4279
4281
4280 With no arguments, show all open branch heads in the repository.
4282 With no arguments, show all open branch heads in the repository.
4281 Branch heads are changesets that have no descendants on the
4283 Branch heads are changesets that have no descendants on the
4282 same branch. They are where development generally takes place and
4284 same branch. They are where development generally takes place and
4283 are the usual targets for update and merge operations.
4285 are the usual targets for update and merge operations.
4284
4286
4285 If one or more REVs are given, only open branch heads on the
4287 If one or more REVs are given, only open branch heads on the
4286 branches associated with the specified changesets are shown. This
4288 branches associated with the specified changesets are shown. This
4287 means that you can use :hg:`heads .` to see the heads on the
4289 means that you can use :hg:`heads .` to see the heads on the
4288 currently checked-out branch.
4290 currently checked-out branch.
4289
4291
4290 If -c/--closed is specified, also show branch heads marked closed
4292 If -c/--closed is specified, also show branch heads marked closed
4291 (see :hg:`commit --close-branch`).
4293 (see :hg:`commit --close-branch`).
4292
4294
4293 If STARTREV is specified, only those heads that are descendants of
4295 If STARTREV is specified, only those heads that are descendants of
4294 STARTREV will be displayed.
4296 STARTREV will be displayed.
4295
4297
4296 If -t/--topo is specified, named branch mechanics will be ignored and only
4298 If -t/--topo is specified, named branch mechanics will be ignored and only
4297 topological heads (changesets with no children) will be shown.
4299 topological heads (changesets with no children) will be shown.
4298
4300
4299 Returns 0 if matching heads are found, 1 if not.
4301 Returns 0 if matching heads are found, 1 if not.
4300 """
4302 """
4301
4303
4302 start = None
4304 start = None
4303 if 'rev' in opts:
4305 if 'rev' in opts:
4304 start = scmutil.revsingle(repo, opts['rev'], None).node()
4306 start = scmutil.revsingle(repo, opts['rev'], None).node()
4305
4307
4306 if opts.get('topo'):
4308 if opts.get('topo'):
4307 heads = [repo[h] for h in repo.heads(start)]
4309 heads = [repo[h] for h in repo.heads(start)]
4308 else:
4310 else:
4309 heads = []
4311 heads = []
4310 for branch in repo.branchmap():
4312 for branch in repo.branchmap():
4311 heads += repo.branchheads(branch, start, opts.get('closed'))
4313 heads += repo.branchheads(branch, start, opts.get('closed'))
4312 heads = [repo[h] for h in heads]
4314 heads = [repo[h] for h in heads]
4313
4315
4314 if branchrevs:
4316 if branchrevs:
4315 branches = set(repo[br].branch() for br in branchrevs)
4317 branches = set(repo[br].branch() for br in branchrevs)
4316 heads = [h for h in heads if h.branch() in branches]
4318 heads = [h for h in heads if h.branch() in branches]
4317
4319
4318 if opts.get('active') and branchrevs:
4320 if opts.get('active') and branchrevs:
4319 dagheads = repo.heads(start)
4321 dagheads = repo.heads(start)
4320 heads = [h for h in heads if h.node() in dagheads]
4322 heads = [h for h in heads if h.node() in dagheads]
4321
4323
4322 if branchrevs:
4324 if branchrevs:
4323 haveheads = set(h.branch() for h in heads)
4325 haveheads = set(h.branch() for h in heads)
4324 if branches - haveheads:
4326 if branches - haveheads:
4325 headless = ', '.join(b for b in branches - haveheads)
4327 headless = ', '.join(b for b in branches - haveheads)
4326 msg = _('no open branch heads found on branches %s')
4328 msg = _('no open branch heads found on branches %s')
4327 if opts.get('rev'):
4329 if opts.get('rev'):
4328 msg += _(' (started at %s)') % opts['rev']
4330 msg += _(' (started at %s)') % opts['rev']
4329 ui.warn((msg + '\n') % headless)
4331 ui.warn((msg + '\n') % headless)
4330
4332
4331 if not heads:
4333 if not heads:
4332 return 1
4334 return 1
4333
4335
4334 heads = sorted(heads, key=lambda x: -x.rev())
4336 heads = sorted(heads, key=lambda x: -x.rev())
4335 displayer = cmdutil.show_changeset(ui, repo, opts)
4337 displayer = cmdutil.show_changeset(ui, repo, opts)
4336 for ctx in heads:
4338 for ctx in heads:
4337 displayer.show(ctx)
4339 displayer.show(ctx)
4338 displayer.close()
4340 displayer.close()
4339
4341
4340 @command('help',
4342 @command('help',
4341 [('e', 'extension', None, _('show only help for extensions')),
4343 [('e', 'extension', None, _('show only help for extensions')),
4342 ('c', 'command', None, _('show only help for commands')),
4344 ('c', 'command', None, _('show only help for commands')),
4343 ('k', 'keyword', None, _('show topics matching keyword')),
4345 ('k', 'keyword', None, _('show topics matching keyword')),
4344 ],
4346 ],
4345 _('[-eck] [TOPIC]'),
4347 _('[-eck] [TOPIC]'),
4346 norepo=True)
4348 norepo=True)
4347 def help_(ui, name=None, **opts):
4349 def help_(ui, name=None, **opts):
4348 """show help for a given topic or a help overview
4350 """show help for a given topic or a help overview
4349
4351
4350 With no arguments, print a list of commands with short help messages.
4352 With no arguments, print a list of commands with short help messages.
4351
4353
4352 Given a topic, extension, or command name, print help for that
4354 Given a topic, extension, or command name, print help for that
4353 topic.
4355 topic.
4354
4356
4355 Returns 0 if successful.
4357 Returns 0 if successful.
4356 """
4358 """
4357
4359
4358 textwidth = min(ui.termwidth(), 80) - 2
4360 textwidth = min(ui.termwidth(), 80) - 2
4359
4361
4360 keep = []
4362 keep = []
4361 if ui.verbose:
4363 if ui.verbose:
4362 keep.append('verbose')
4364 keep.append('verbose')
4363 if sys.platform.startswith('win'):
4365 if sys.platform.startswith('win'):
4364 keep.append('windows')
4366 keep.append('windows')
4365 elif sys.platform == 'OpenVMS':
4367 elif sys.platform == 'OpenVMS':
4366 keep.append('vms')
4368 keep.append('vms')
4367 elif sys.platform == 'plan9':
4369 elif sys.platform == 'plan9':
4368 keep.append('plan9')
4370 keep.append('plan9')
4369 else:
4371 else:
4370 keep.append('unix')
4372 keep.append('unix')
4371 keep.append(sys.platform.lower())
4373 keep.append(sys.platform.lower())
4372
4374
4373 section = None
4375 section = None
4374 subtopic = None
4376 subtopic = None
4375 if name and '.' in name:
4377 if name and '.' in name:
4376 name, section = name.split('.', 1)
4378 name, section = name.split('.', 1)
4377 section = section.lower()
4379 section = section.lower()
4378 if '.' in section:
4380 if '.' in section:
4379 subtopic, section = section.split('.', 1)
4381 subtopic, section = section.split('.', 1)
4380 else:
4382 else:
4381 subtopic = section
4383 subtopic = section
4382
4384
4383 text = help.help_(ui, name, subtopic=subtopic, **opts)
4385 text = help.help_(ui, name, subtopic=subtopic, **opts)
4384
4386
4385 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4387 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4386 section=section)
4388 section=section)
4387
4389
4388 # We could have been given a weird ".foo" section without a name
4390 # We could have been given a weird ".foo" section without a name
4389 # to look for, or we could have simply failed to found "foo.bar"
4391 # to look for, or we could have simply failed to found "foo.bar"
4390 # because bar isn't a section of foo
4392 # because bar isn't a section of foo
4391 if section and not (formatted and name):
4393 if section and not (formatted and name):
4392 raise error.Abort(_("help section not found"))
4394 raise error.Abort(_("help section not found"))
4393
4395
4394 if 'verbose' in pruned:
4396 if 'verbose' in pruned:
4395 keep.append('omitted')
4397 keep.append('omitted')
4396 else:
4398 else:
4397 keep.append('notomitted')
4399 keep.append('notomitted')
4398 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4400 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4399 section=section)
4401 section=section)
4400 ui.write(formatted)
4402 ui.write(formatted)
4401
4403
4402
4404
4403 @command('identify|id',
4405 @command('identify|id',
4404 [('r', 'rev', '',
4406 [('r', 'rev', '',
4405 _('identify the specified revision'), _('REV')),
4407 _('identify the specified revision'), _('REV')),
4406 ('n', 'num', None, _('show local revision number')),
4408 ('n', 'num', None, _('show local revision number')),
4407 ('i', 'id', None, _('show global revision id')),
4409 ('i', 'id', None, _('show global revision id')),
4408 ('b', 'branch', None, _('show branch')),
4410 ('b', 'branch', None, _('show branch')),
4409 ('t', 'tags', None, _('show tags')),
4411 ('t', 'tags', None, _('show tags')),
4410 ('B', 'bookmarks', None, _('show bookmarks')),
4412 ('B', 'bookmarks', None, _('show bookmarks')),
4411 ] + remoteopts,
4413 ] + remoteopts,
4412 _('[-nibtB] [-r REV] [SOURCE]'),
4414 _('[-nibtB] [-r REV] [SOURCE]'),
4413 optionalrepo=True)
4415 optionalrepo=True)
4414 def identify(ui, repo, source=None, rev=None,
4416 def identify(ui, repo, source=None, rev=None,
4415 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4417 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4416 """identify the working directory or specified revision
4418 """identify the working directory or specified revision
4417
4419
4418 Print a summary identifying the repository state at REV using one or
4420 Print a summary identifying the repository state at REV using one or
4419 two parent hash identifiers, followed by a "+" if the working
4421 two parent hash identifiers, followed by a "+" if the working
4420 directory has uncommitted changes, the branch name (if not default),
4422 directory has uncommitted changes, the branch name (if not default),
4421 a list of tags, and a list of bookmarks.
4423 a list of tags, and a list of bookmarks.
4422
4424
4423 When REV is not given, print a summary of the current state of the
4425 When REV is not given, print a summary of the current state of the
4424 repository.
4426 repository.
4425
4427
4426 Specifying a path to a repository root or Mercurial bundle will
4428 Specifying a path to a repository root or Mercurial bundle will
4427 cause lookup to operate on that repository/bundle.
4429 cause lookup to operate on that repository/bundle.
4428
4430
4429 .. container:: verbose
4431 .. container:: verbose
4430
4432
4431 Examples:
4433 Examples:
4432
4434
4433 - generate a build identifier for the working directory::
4435 - generate a build identifier for the working directory::
4434
4436
4435 hg id --id > build-id.dat
4437 hg id --id > build-id.dat
4436
4438
4437 - find the revision corresponding to a tag::
4439 - find the revision corresponding to a tag::
4438
4440
4439 hg id -n -r 1.3
4441 hg id -n -r 1.3
4440
4442
4441 - check the most recent revision of a remote repository::
4443 - check the most recent revision of a remote repository::
4442
4444
4443 hg id -r tip http://selenic.com/hg/
4445 hg id -r tip http://selenic.com/hg/
4444
4446
4445 See :hg:`log` for generating more information about specific revisions,
4447 See :hg:`log` for generating more information about specific revisions,
4446 including full hash identifiers.
4448 including full hash identifiers.
4447
4449
4448 Returns 0 if successful.
4450 Returns 0 if successful.
4449 """
4451 """
4450
4452
4451 if not repo and not source:
4453 if not repo and not source:
4452 raise error.Abort(_("there is no Mercurial repository here "
4454 raise error.Abort(_("there is no Mercurial repository here "
4453 "(.hg not found)"))
4455 "(.hg not found)"))
4454
4456
4455 if ui.debugflag:
4457 if ui.debugflag:
4456 hexfunc = hex
4458 hexfunc = hex
4457 else:
4459 else:
4458 hexfunc = short
4460 hexfunc = short
4459 default = not (num or id or branch or tags or bookmarks)
4461 default = not (num or id or branch or tags or bookmarks)
4460 output = []
4462 output = []
4461 revs = []
4463 revs = []
4462
4464
4463 if source:
4465 if source:
4464 source, branches = hg.parseurl(ui.expandpath(source))
4466 source, branches = hg.parseurl(ui.expandpath(source))
4465 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4467 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4466 repo = peer.local()
4468 repo = peer.local()
4467 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4469 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4468
4470
4469 if not repo:
4471 if not repo:
4470 if num or branch or tags:
4472 if num or branch or tags:
4471 raise error.Abort(
4473 raise error.Abort(
4472 _("can't query remote revision number, branch, or tags"))
4474 _("can't query remote revision number, branch, or tags"))
4473 if not rev and revs:
4475 if not rev and revs:
4474 rev = revs[0]
4476 rev = revs[0]
4475 if not rev:
4477 if not rev:
4476 rev = "tip"
4478 rev = "tip"
4477
4479
4478 remoterev = peer.lookup(rev)
4480 remoterev = peer.lookup(rev)
4479 if default or id:
4481 if default or id:
4480 output = [hexfunc(remoterev)]
4482 output = [hexfunc(remoterev)]
4481
4483
4482 def getbms():
4484 def getbms():
4483 bms = []
4485 bms = []
4484
4486
4485 if 'bookmarks' in peer.listkeys('namespaces'):
4487 if 'bookmarks' in peer.listkeys('namespaces'):
4486 hexremoterev = hex(remoterev)
4488 hexremoterev = hex(remoterev)
4487 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4489 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4488 if bmr == hexremoterev]
4490 if bmr == hexremoterev]
4489
4491
4490 return sorted(bms)
4492 return sorted(bms)
4491
4493
4492 if bookmarks:
4494 if bookmarks:
4493 output.extend(getbms())
4495 output.extend(getbms())
4494 elif default and not ui.quiet:
4496 elif default and not ui.quiet:
4495 # multiple bookmarks for a single parent separated by '/'
4497 # multiple bookmarks for a single parent separated by '/'
4496 bm = '/'.join(getbms())
4498 bm = '/'.join(getbms())
4497 if bm:
4499 if bm:
4498 output.append(bm)
4500 output.append(bm)
4499 else:
4501 else:
4500 ctx = scmutil.revsingle(repo, rev, None)
4502 ctx = scmutil.revsingle(repo, rev, None)
4501
4503
4502 if ctx.rev() is None:
4504 if ctx.rev() is None:
4503 ctx = repo[None]
4505 ctx = repo[None]
4504 parents = ctx.parents()
4506 parents = ctx.parents()
4505 taglist = []
4507 taglist = []
4506 for p in parents:
4508 for p in parents:
4507 taglist.extend(p.tags())
4509 taglist.extend(p.tags())
4508
4510
4509 changed = ""
4511 changed = ""
4510 if default or id or num:
4512 if default or id or num:
4511 if (any(repo.status())
4513 if (any(repo.status())
4512 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4514 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4513 changed = '+'
4515 changed = '+'
4514 if default or id:
4516 if default or id:
4515 output = ["%s%s" %
4517 output = ["%s%s" %
4516 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4518 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4517 if num:
4519 if num:
4518 output.append("%s%s" %
4520 output.append("%s%s" %
4519 ('+'.join([str(p.rev()) for p in parents]), changed))
4521 ('+'.join([str(p.rev()) for p in parents]), changed))
4520 else:
4522 else:
4521 if default or id:
4523 if default or id:
4522 output = [hexfunc(ctx.node())]
4524 output = [hexfunc(ctx.node())]
4523 if num:
4525 if num:
4524 output.append(str(ctx.rev()))
4526 output.append(str(ctx.rev()))
4525 taglist = ctx.tags()
4527 taglist = ctx.tags()
4526
4528
4527 if default and not ui.quiet:
4529 if default and not ui.quiet:
4528 b = ctx.branch()
4530 b = ctx.branch()
4529 if b != 'default':
4531 if b != 'default':
4530 output.append("(%s)" % b)
4532 output.append("(%s)" % b)
4531
4533
4532 # multiple tags for a single parent separated by '/'
4534 # multiple tags for a single parent separated by '/'
4533 t = '/'.join(taglist)
4535 t = '/'.join(taglist)
4534 if t:
4536 if t:
4535 output.append(t)
4537 output.append(t)
4536
4538
4537 # multiple bookmarks for a single parent separated by '/'
4539 # multiple bookmarks for a single parent separated by '/'
4538 bm = '/'.join(ctx.bookmarks())
4540 bm = '/'.join(ctx.bookmarks())
4539 if bm:
4541 if bm:
4540 output.append(bm)
4542 output.append(bm)
4541 else:
4543 else:
4542 if branch:
4544 if branch:
4543 output.append(ctx.branch())
4545 output.append(ctx.branch())
4544
4546
4545 if tags:
4547 if tags:
4546 output.extend(taglist)
4548 output.extend(taglist)
4547
4549
4548 if bookmarks:
4550 if bookmarks:
4549 output.extend(ctx.bookmarks())
4551 output.extend(ctx.bookmarks())
4550
4552
4551 ui.write("%s\n" % ' '.join(output))
4553 ui.write("%s\n" % ' '.join(output))
4552
4554
4553 @command('import|patch',
4555 @command('import|patch',
4554 [('p', 'strip', 1,
4556 [('p', 'strip', 1,
4555 _('directory strip option for patch. This has the same '
4557 _('directory strip option for patch. This has the same '
4556 'meaning as the corresponding patch option'), _('NUM')),
4558 'meaning as the corresponding patch option'), _('NUM')),
4557 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4559 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4558 ('e', 'edit', False, _('invoke editor on commit messages')),
4560 ('e', 'edit', False, _('invoke editor on commit messages')),
4559 ('f', 'force', None,
4561 ('f', 'force', None,
4560 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4562 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4561 ('', 'no-commit', None,
4563 ('', 'no-commit', None,
4562 _("don't commit, just update the working directory")),
4564 _("don't commit, just update the working directory")),
4563 ('', 'bypass', None,
4565 ('', 'bypass', None,
4564 _("apply patch without touching the working directory")),
4566 _("apply patch without touching the working directory")),
4565 ('', 'partial', None,
4567 ('', 'partial', None,
4566 _('commit even if some hunks fail')),
4568 _('commit even if some hunks fail')),
4567 ('', 'exact', None,
4569 ('', 'exact', None,
4568 _('apply patch to the nodes from which it was generated')),
4570 _('apply patch to the nodes from which it was generated')),
4569 ('', 'prefix', '',
4571 ('', 'prefix', '',
4570 _('apply patch to subdirectory'), _('DIR')),
4572 _('apply patch to subdirectory'), _('DIR')),
4571 ('', 'import-branch', None,
4573 ('', 'import-branch', None,
4572 _('use any branch information in patch (implied by --exact)'))] +
4574 _('use any branch information in patch (implied by --exact)'))] +
4573 commitopts + commitopts2 + similarityopts,
4575 commitopts + commitopts2 + similarityopts,
4574 _('[OPTION]... PATCH...'))
4576 _('[OPTION]... PATCH...'))
4575 def import_(ui, repo, patch1=None, *patches, **opts):
4577 def import_(ui, repo, patch1=None, *patches, **opts):
4576 """import an ordered set of patches
4578 """import an ordered set of patches
4577
4579
4578 Import a list of patches and commit them individually (unless
4580 Import a list of patches and commit them individually (unless
4579 --no-commit is specified).
4581 --no-commit is specified).
4580
4582
4581 To read a patch from standard input, use "-" as the patch name. If
4583 To read a patch from standard input, use "-" as the patch name. If
4582 a URL is specified, the patch will be downloaded from there.
4584 a URL is specified, the patch will be downloaded from there.
4583
4585
4584 Import first applies changes to the working directory (unless
4586 Import first applies changes to the working directory (unless
4585 --bypass is specified), import will abort if there are outstanding
4587 --bypass is specified), import will abort if there are outstanding
4586 changes.
4588 changes.
4587
4589
4588 Use --bypass to apply and commit patches directly to the
4590 Use --bypass to apply and commit patches directly to the
4589 repository, without affecting the working directory. Without
4591 repository, without affecting the working directory. Without
4590 --exact, patches will be applied on top of the working directory
4592 --exact, patches will be applied on top of the working directory
4591 parent revision.
4593 parent revision.
4592
4594
4593 You can import a patch straight from a mail message. Even patches
4595 You can import a patch straight from a mail message. Even patches
4594 as attachments work (to use the body part, it must have type
4596 as attachments work (to use the body part, it must have type
4595 text/plain or text/x-patch). From and Subject headers of email
4597 text/plain or text/x-patch). From and Subject headers of email
4596 message are used as default committer and commit message. All
4598 message are used as default committer and commit message. All
4597 text/plain body parts before first diff are added to the commit
4599 text/plain body parts before first diff are added to the commit
4598 message.
4600 message.
4599
4601
4600 If the imported patch was generated by :hg:`export`, user and
4602 If the imported patch was generated by :hg:`export`, user and
4601 description from patch override values from message headers and
4603 description from patch override values from message headers and
4602 body. Values given on command line with -m/--message and -u/--user
4604 body. Values given on command line with -m/--message and -u/--user
4603 override these.
4605 override these.
4604
4606
4605 If --exact is specified, import will set the working directory to
4607 If --exact is specified, import will set the working directory to
4606 the parent of each patch before applying it, and will abort if the
4608 the parent of each patch before applying it, and will abort if the
4607 resulting changeset has a different ID than the one recorded in
4609 resulting changeset has a different ID than the one recorded in
4608 the patch. This may happen due to character set problems or other
4610 the patch. This may happen due to character set problems or other
4609 deficiencies in the text patch format.
4611 deficiencies in the text patch format.
4610
4612
4611 Use --partial to ensure a changeset will be created from the patch
4613 Use --partial to ensure a changeset will be created from the patch
4612 even if some hunks fail to apply. Hunks that fail to apply will be
4614 even if some hunks fail to apply. Hunks that fail to apply will be
4613 written to a <target-file>.rej file. Conflicts can then be resolved
4615 written to a <target-file>.rej file. Conflicts can then be resolved
4614 by hand before :hg:`commit --amend` is run to update the created
4616 by hand before :hg:`commit --amend` is run to update the created
4615 changeset. This flag exists to let people import patches that
4617 changeset. This flag exists to let people import patches that
4616 partially apply without losing the associated metadata (author,
4618 partially apply without losing the associated metadata (author,
4617 date, description, ...). Note that when none of the hunk applies
4619 date, description, ...). Note that when none of the hunk applies
4618 cleanly, :hg:`import --partial` will create an empty changeset,
4620 cleanly, :hg:`import --partial` will create an empty changeset,
4619 importing only the patch metadata.
4621 importing only the patch metadata.
4620
4622
4621 With -s/--similarity, hg will attempt to discover renames and
4623 With -s/--similarity, hg will attempt to discover renames and
4622 copies in the patch in the same way as :hg:`addremove`.
4624 copies in the patch in the same way as :hg:`addremove`.
4623
4625
4624 It is possible to use external patch programs to perform the patch
4626 It is possible to use external patch programs to perform the patch
4625 by setting the ``ui.patch`` configuration option. For the default
4627 by setting the ``ui.patch`` configuration option. For the default
4626 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4628 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4627 See :hg:`help config` for more information about configuration
4629 See :hg:`help config` for more information about configuration
4628 files and how to use these options.
4630 files and how to use these options.
4629
4631
4630 See :hg:`help dates` for a list of formats valid for -d/--date.
4632 See :hg:`help dates` for a list of formats valid for -d/--date.
4631
4633
4632 .. container:: verbose
4634 .. container:: verbose
4633
4635
4634 Examples:
4636 Examples:
4635
4637
4636 - import a traditional patch from a website and detect renames::
4638 - import a traditional patch from a website and detect renames::
4637
4639
4638 hg import -s 80 http://example.com/bugfix.patch
4640 hg import -s 80 http://example.com/bugfix.patch
4639
4641
4640 - import a changeset from an hgweb server::
4642 - import a changeset from an hgweb server::
4641
4643
4642 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4644 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4643
4645
4644 - import all the patches in an Unix-style mbox::
4646 - import all the patches in an Unix-style mbox::
4645
4647
4646 hg import incoming-patches.mbox
4648 hg import incoming-patches.mbox
4647
4649
4648 - attempt to exactly restore an exported changeset (not always
4650 - attempt to exactly restore an exported changeset (not always
4649 possible)::
4651 possible)::
4650
4652
4651 hg import --exact proposed-fix.patch
4653 hg import --exact proposed-fix.patch
4652
4654
4653 - use an external tool to apply a patch which is too fuzzy for
4655 - use an external tool to apply a patch which is too fuzzy for
4654 the default internal tool.
4656 the default internal tool.
4655
4657
4656 hg import --config ui.patch="patch --merge" fuzzy.patch
4658 hg import --config ui.patch="patch --merge" fuzzy.patch
4657
4659
4658 - change the default fuzzing from 2 to a less strict 7
4660 - change the default fuzzing from 2 to a less strict 7
4659
4661
4660 hg import --config ui.fuzz=7 fuzz.patch
4662 hg import --config ui.fuzz=7 fuzz.patch
4661
4663
4662 Returns 0 on success, 1 on partial success (see --partial).
4664 Returns 0 on success, 1 on partial success (see --partial).
4663 """
4665 """
4664
4666
4665 if not patch1:
4667 if not patch1:
4666 raise error.Abort(_('need at least one patch to import'))
4668 raise error.Abort(_('need at least one patch to import'))
4667
4669
4668 patches = (patch1,) + patches
4670 patches = (patch1,) + patches
4669
4671
4670 date = opts.get('date')
4672 date = opts.get('date')
4671 if date:
4673 if date:
4672 opts['date'] = util.parsedate(date)
4674 opts['date'] = util.parsedate(date)
4673
4675
4674 exact = opts.get('exact')
4676 exact = opts.get('exact')
4675 update = not opts.get('bypass')
4677 update = not opts.get('bypass')
4676 if not update and opts.get('no_commit'):
4678 if not update and opts.get('no_commit'):
4677 raise error.Abort(_('cannot use --no-commit with --bypass'))
4679 raise error.Abort(_('cannot use --no-commit with --bypass'))
4678 try:
4680 try:
4679 sim = float(opts.get('similarity') or 0)
4681 sim = float(opts.get('similarity') or 0)
4680 except ValueError:
4682 except ValueError:
4681 raise error.Abort(_('similarity must be a number'))
4683 raise error.Abort(_('similarity must be a number'))
4682 if sim < 0 or sim > 100:
4684 if sim < 0 or sim > 100:
4683 raise error.Abort(_('similarity must be between 0 and 100'))
4685 raise error.Abort(_('similarity must be between 0 and 100'))
4684 if sim and not update:
4686 if sim and not update:
4685 raise error.Abort(_('cannot use --similarity with --bypass'))
4687 raise error.Abort(_('cannot use --similarity with --bypass'))
4686 if exact:
4688 if exact:
4687 if opts.get('edit'):
4689 if opts.get('edit'):
4688 raise error.Abort(_('cannot use --exact with --edit'))
4690 raise error.Abort(_('cannot use --exact with --edit'))
4689 if opts.get('prefix'):
4691 if opts.get('prefix'):
4690 raise error.Abort(_('cannot use --exact with --prefix'))
4692 raise error.Abort(_('cannot use --exact with --prefix'))
4691
4693
4692 base = opts["base"]
4694 base = opts["base"]
4693 wlock = dsguard = lock = tr = None
4695 wlock = dsguard = lock = tr = None
4694 msgs = []
4696 msgs = []
4695 ret = 0
4697 ret = 0
4696
4698
4697
4699
4698 try:
4700 try:
4699 try:
4701 try:
4700 wlock = repo.wlock()
4702 wlock = repo.wlock()
4701
4703
4702 if update:
4704 if update:
4703 cmdutil.checkunfinished(repo)
4705 cmdutil.checkunfinished(repo)
4704 if (exact or not opts.get('force')):
4706 if (exact or not opts.get('force')):
4705 cmdutil.bailifchanged(repo)
4707 cmdutil.bailifchanged(repo)
4706
4708
4707 if not opts.get('no_commit'):
4709 if not opts.get('no_commit'):
4708 lock = repo.lock()
4710 lock = repo.lock()
4709 tr = repo.transaction('import')
4711 tr = repo.transaction('import')
4710 else:
4712 else:
4711 dsguard = cmdutil.dirstateguard(repo, 'import')
4713 dsguard = cmdutil.dirstateguard(repo, 'import')
4712 parents = repo[None].parents()
4714 parents = repo[None].parents()
4713 for patchurl in patches:
4715 for patchurl in patches:
4714 if patchurl == '-':
4716 if patchurl == '-':
4715 ui.status(_('applying patch from stdin\n'))
4717 ui.status(_('applying patch from stdin\n'))
4716 patchfile = ui.fin
4718 patchfile = ui.fin
4717 patchurl = 'stdin' # for error message
4719 patchurl = 'stdin' # for error message
4718 else:
4720 else:
4719 patchurl = os.path.join(base, patchurl)
4721 patchurl = os.path.join(base, patchurl)
4720 ui.status(_('applying %s\n') % patchurl)
4722 ui.status(_('applying %s\n') % patchurl)
4721 patchfile = hg.openpath(ui, patchurl)
4723 patchfile = hg.openpath(ui, patchurl)
4722
4724
4723 haspatch = False
4725 haspatch = False
4724 for hunk in patch.split(patchfile):
4726 for hunk in patch.split(patchfile):
4725 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4727 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4726 parents, opts,
4728 parents, opts,
4727 msgs, hg.clean)
4729 msgs, hg.clean)
4728 if msg:
4730 if msg:
4729 haspatch = True
4731 haspatch = True
4730 ui.note(msg + '\n')
4732 ui.note(msg + '\n')
4731 if update or exact:
4733 if update or exact:
4732 parents = repo[None].parents()
4734 parents = repo[None].parents()
4733 else:
4735 else:
4734 parents = [repo[node]]
4736 parents = [repo[node]]
4735 if rej:
4737 if rej:
4736 ui.write_err(_("patch applied partially\n"))
4738 ui.write_err(_("patch applied partially\n"))
4737 ui.write_err(_("(fix the .rej files and run "
4739 ui.write_err(_("(fix the .rej files and run "
4738 "`hg commit --amend`)\n"))
4740 "`hg commit --amend`)\n"))
4739 ret = 1
4741 ret = 1
4740 break
4742 break
4741
4743
4742 if not haspatch:
4744 if not haspatch:
4743 raise error.Abort(_('%s: no diffs found') % patchurl)
4745 raise error.Abort(_('%s: no diffs found') % patchurl)
4744
4746
4745 if tr:
4747 if tr:
4746 tr.close()
4748 tr.close()
4747 if msgs:
4749 if msgs:
4748 repo.savecommitmessage('\n* * *\n'.join(msgs))
4750 repo.savecommitmessage('\n* * *\n'.join(msgs))
4749 if dsguard:
4751 if dsguard:
4750 dsguard.close()
4752 dsguard.close()
4751 return ret
4753 return ret
4752 finally:
4754 finally:
4753 # TODO: get rid of this meaningless try/finally enclosing.
4755 # TODO: get rid of this meaningless try/finally enclosing.
4754 # this is kept only to reduce changes in a patch.
4756 # this is kept only to reduce changes in a patch.
4755 pass
4757 pass
4756 finally:
4758 finally:
4757 if tr:
4759 if tr:
4758 tr.release()
4760 tr.release()
4759 release(lock, dsguard, wlock)
4761 release(lock, dsguard, wlock)
4760
4762
4761 @command('incoming|in',
4763 @command('incoming|in',
4762 [('f', 'force', None,
4764 [('f', 'force', None,
4763 _('run even if remote repository is unrelated')),
4765 _('run even if remote repository is unrelated')),
4764 ('n', 'newest-first', None, _('show newest record first')),
4766 ('n', 'newest-first', None, _('show newest record first')),
4765 ('', 'bundle', '',
4767 ('', 'bundle', '',
4766 _('file to store the bundles into'), _('FILE')),
4768 _('file to store the bundles into'), _('FILE')),
4767 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4769 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4768 ('B', 'bookmarks', False, _("compare bookmarks")),
4770 ('B', 'bookmarks', False, _("compare bookmarks")),
4769 ('b', 'branch', [],
4771 ('b', 'branch', [],
4770 _('a specific branch you would like to pull'), _('BRANCH')),
4772 _('a specific branch you would like to pull'), _('BRANCH')),
4771 ] + logopts + remoteopts + subrepoopts,
4773 ] + logopts + remoteopts + subrepoopts,
4772 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4774 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4773 def incoming(ui, repo, source="default", **opts):
4775 def incoming(ui, repo, source="default", **opts):
4774 """show new changesets found in source
4776 """show new changesets found in source
4775
4777
4776 Show new changesets found in the specified path/URL or the default
4778 Show new changesets found in the specified path/URL or the default
4777 pull location. These are the changesets that would have been pulled
4779 pull location. These are the changesets that would have been pulled
4778 if a pull at the time you issued this command.
4780 if a pull at the time you issued this command.
4779
4781
4780 See pull for valid source format details.
4782 See pull for valid source format details.
4781
4783
4782 .. container:: verbose
4784 .. container:: verbose
4783
4785
4784 With -B/--bookmarks, the result of bookmark comparison between
4786 With -B/--bookmarks, the result of bookmark comparison between
4785 local and remote repositories is displayed. With -v/--verbose,
4787 local and remote repositories is displayed. With -v/--verbose,
4786 status is also displayed for each bookmark like below::
4788 status is also displayed for each bookmark like below::
4787
4789
4788 BM1 01234567890a added
4790 BM1 01234567890a added
4789 BM2 1234567890ab advanced
4791 BM2 1234567890ab advanced
4790 BM3 234567890abc diverged
4792 BM3 234567890abc diverged
4791 BM4 34567890abcd changed
4793 BM4 34567890abcd changed
4792
4794
4793 The action taken locally when pulling depends on the
4795 The action taken locally when pulling depends on the
4794 status of each bookmark:
4796 status of each bookmark:
4795
4797
4796 :``added``: pull will create it
4798 :``added``: pull will create it
4797 :``advanced``: pull will update it
4799 :``advanced``: pull will update it
4798 :``diverged``: pull will create a divergent bookmark
4800 :``diverged``: pull will create a divergent bookmark
4799 :``changed``: result depends on remote changesets
4801 :``changed``: result depends on remote changesets
4800
4802
4801 From the point of view of pulling behavior, bookmark
4803 From the point of view of pulling behavior, bookmark
4802 existing only in the remote repository are treated as ``added``,
4804 existing only in the remote repository are treated as ``added``,
4803 even if it is in fact locally deleted.
4805 even if it is in fact locally deleted.
4804
4806
4805 .. container:: verbose
4807 .. container:: verbose
4806
4808
4807 For remote repository, using --bundle avoids downloading the
4809 For remote repository, using --bundle avoids downloading the
4808 changesets twice if the incoming is followed by a pull.
4810 changesets twice if the incoming is followed by a pull.
4809
4811
4810 Examples:
4812 Examples:
4811
4813
4812 - show incoming changes with patches and full description::
4814 - show incoming changes with patches and full description::
4813
4815
4814 hg incoming -vp
4816 hg incoming -vp
4815
4817
4816 - show incoming changes excluding merges, store a bundle::
4818 - show incoming changes excluding merges, store a bundle::
4817
4819
4818 hg in -vpM --bundle incoming.hg
4820 hg in -vpM --bundle incoming.hg
4819 hg pull incoming.hg
4821 hg pull incoming.hg
4820
4822
4821 - briefly list changes inside a bundle::
4823 - briefly list changes inside a bundle::
4822
4824
4823 hg in changes.hg -T "{desc|firstline}\\n"
4825 hg in changes.hg -T "{desc|firstline}\\n"
4824
4826
4825 Returns 0 if there are incoming changes, 1 otherwise.
4827 Returns 0 if there are incoming changes, 1 otherwise.
4826 """
4828 """
4827 if opts.get('graph'):
4829 if opts.get('graph'):
4828 cmdutil.checkunsupportedgraphflags([], opts)
4830 cmdutil.checkunsupportedgraphflags([], opts)
4829 def display(other, chlist, displayer):
4831 def display(other, chlist, displayer):
4830 revdag = cmdutil.graphrevs(other, chlist, opts)
4832 revdag = cmdutil.graphrevs(other, chlist, opts)
4831 cmdutil.displaygraph(ui, repo, revdag, displayer,
4833 cmdutil.displaygraph(ui, repo, revdag, displayer,
4832 graphmod.asciiedges)
4834 graphmod.asciiedges)
4833
4835
4834 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4836 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4835 return 0
4837 return 0
4836
4838
4837 if opts.get('bundle') and opts.get('subrepos'):
4839 if opts.get('bundle') and opts.get('subrepos'):
4838 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4840 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4839
4841
4840 if opts.get('bookmarks'):
4842 if opts.get('bookmarks'):
4841 source, branches = hg.parseurl(ui.expandpath(source),
4843 source, branches = hg.parseurl(ui.expandpath(source),
4842 opts.get('branch'))
4844 opts.get('branch'))
4843 other = hg.peer(repo, opts, source)
4845 other = hg.peer(repo, opts, source)
4844 if 'bookmarks' not in other.listkeys('namespaces'):
4846 if 'bookmarks' not in other.listkeys('namespaces'):
4845 ui.warn(_("remote doesn't support bookmarks\n"))
4847 ui.warn(_("remote doesn't support bookmarks\n"))
4846 return 0
4848 return 0
4847 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4849 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4848 return bookmarks.incoming(ui, repo, other)
4850 return bookmarks.incoming(ui, repo, other)
4849
4851
4850 repo._subtoppath = ui.expandpath(source)
4852 repo._subtoppath = ui.expandpath(source)
4851 try:
4853 try:
4852 return hg.incoming(ui, repo, source, opts)
4854 return hg.incoming(ui, repo, source, opts)
4853 finally:
4855 finally:
4854 del repo._subtoppath
4856 del repo._subtoppath
4855
4857
4856
4858
4857 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4859 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4858 norepo=True)
4860 norepo=True)
4859 def init(ui, dest=".", **opts):
4861 def init(ui, dest=".", **opts):
4860 """create a new repository in the given directory
4862 """create a new repository in the given directory
4861
4863
4862 Initialize a new repository in the given directory. If the given
4864 Initialize a new repository in the given directory. If the given
4863 directory does not exist, it will be created.
4865 directory does not exist, it will be created.
4864
4866
4865 If no directory is given, the current directory is used.
4867 If no directory is given, the current directory is used.
4866
4868
4867 It is possible to specify an ``ssh://`` URL as the destination.
4869 It is possible to specify an ``ssh://`` URL as the destination.
4868 See :hg:`help urls` for more information.
4870 See :hg:`help urls` for more information.
4869
4871
4870 Returns 0 on success.
4872 Returns 0 on success.
4871 """
4873 """
4872 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4874 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4873
4875
4874 @command('locate',
4876 @command('locate',
4875 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4877 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4876 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4878 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4877 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4879 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4878 ] + walkopts,
4880 ] + walkopts,
4879 _('[OPTION]... [PATTERN]...'))
4881 _('[OPTION]... [PATTERN]...'))
4880 def locate(ui, repo, *pats, **opts):
4882 def locate(ui, repo, *pats, **opts):
4881 """locate files matching specific patterns (DEPRECATED)
4883 """locate files matching specific patterns (DEPRECATED)
4882
4884
4883 Print files under Mercurial control in the working directory whose
4885 Print files under Mercurial control in the working directory whose
4884 names match the given patterns.
4886 names match the given patterns.
4885
4887
4886 By default, this command searches all directories in the working
4888 By default, this command searches all directories in the working
4887 directory. To search just the current directory and its
4889 directory. To search just the current directory and its
4888 subdirectories, use "--include .".
4890 subdirectories, use "--include .".
4889
4891
4890 If no patterns are given to match, this command prints the names
4892 If no patterns are given to match, this command prints the names
4891 of all files under Mercurial control in the working directory.
4893 of all files under Mercurial control in the working directory.
4892
4894
4893 If you want to feed the output of this command into the "xargs"
4895 If you want to feed the output of this command into the "xargs"
4894 command, use the -0 option to both this command and "xargs". This
4896 command, use the -0 option to both this command and "xargs". This
4895 will avoid the problem of "xargs" treating single filenames that
4897 will avoid the problem of "xargs" treating single filenames that
4896 contain whitespace as multiple filenames.
4898 contain whitespace as multiple filenames.
4897
4899
4898 See :hg:`help files` for a more versatile command.
4900 See :hg:`help files` for a more versatile command.
4899
4901
4900 Returns 0 if a match is found, 1 otherwise.
4902 Returns 0 if a match is found, 1 otherwise.
4901 """
4903 """
4902 if opts.get('print0'):
4904 if opts.get('print0'):
4903 end = '\0'
4905 end = '\0'
4904 else:
4906 else:
4905 end = '\n'
4907 end = '\n'
4906 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4908 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4907
4909
4908 ret = 1
4910 ret = 1
4909 ctx = repo[rev]
4911 ctx = repo[rev]
4910 m = scmutil.match(ctx, pats, opts, default='relglob',
4912 m = scmutil.match(ctx, pats, opts, default='relglob',
4911 badfn=lambda x, y: False)
4913 badfn=lambda x, y: False)
4912
4914
4913 for abs in ctx.matches(m):
4915 for abs in ctx.matches(m):
4914 if opts.get('fullpath'):
4916 if opts.get('fullpath'):
4915 ui.write(repo.wjoin(abs), end)
4917 ui.write(repo.wjoin(abs), end)
4916 else:
4918 else:
4917 ui.write(((pats and m.rel(abs)) or abs), end)
4919 ui.write(((pats and m.rel(abs)) or abs), end)
4918 ret = 0
4920 ret = 0
4919
4921
4920 return ret
4922 return ret
4921
4923
4922 @command('^log|history',
4924 @command('^log|history',
4923 [('f', 'follow', None,
4925 [('f', 'follow', None,
4924 _('follow changeset history, or file history across copies and renames')),
4926 _('follow changeset history, or file history across copies and renames')),
4925 ('', 'follow-first', None,
4927 ('', 'follow-first', None,
4926 _('only follow the first parent of merge changesets (DEPRECATED)')),
4928 _('only follow the first parent of merge changesets (DEPRECATED)')),
4927 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4929 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4928 ('C', 'copies', None, _('show copied files')),
4930 ('C', 'copies', None, _('show copied files')),
4929 ('k', 'keyword', [],
4931 ('k', 'keyword', [],
4930 _('do case-insensitive search for a given text'), _('TEXT')),
4932 _('do case-insensitive search for a given text'), _('TEXT')),
4931 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4933 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4932 ('', 'removed', None, _('include revisions where files were removed')),
4934 ('', 'removed', None, _('include revisions where files were removed')),
4933 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4935 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4934 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4936 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4935 ('', 'only-branch', [],
4937 ('', 'only-branch', [],
4936 _('show only changesets within the given named branch (DEPRECATED)'),
4938 _('show only changesets within the given named branch (DEPRECATED)'),
4937 _('BRANCH')),
4939 _('BRANCH')),
4938 ('b', 'branch', [],
4940 ('b', 'branch', [],
4939 _('show changesets within the given named branch'), _('BRANCH')),
4941 _('show changesets within the given named branch'), _('BRANCH')),
4940 ('P', 'prune', [],
4942 ('P', 'prune', [],
4941 _('do not display revision or any of its ancestors'), _('REV')),
4943 _('do not display revision or any of its ancestors'), _('REV')),
4942 ] + logopts + walkopts,
4944 ] + logopts + walkopts,
4943 _('[OPTION]... [FILE]'),
4945 _('[OPTION]... [FILE]'),
4944 inferrepo=True)
4946 inferrepo=True)
4945 def log(ui, repo, *pats, **opts):
4947 def log(ui, repo, *pats, **opts):
4946 """show revision history of entire repository or files
4948 """show revision history of entire repository or files
4947
4949
4948 Print the revision history of the specified files or the entire
4950 Print the revision history of the specified files or the entire
4949 project.
4951 project.
4950
4952
4951 If no revision range is specified, the default is ``tip:0`` unless
4953 If no revision range is specified, the default is ``tip:0`` unless
4952 --follow is set, in which case the working directory parent is
4954 --follow is set, in which case the working directory parent is
4953 used as the starting revision.
4955 used as the starting revision.
4954
4956
4955 File history is shown without following rename or copy history of
4957 File history is shown without following rename or copy history of
4956 files. Use -f/--follow with a filename to follow history across
4958 files. Use -f/--follow with a filename to follow history across
4957 renames and copies. --follow without a filename will only show
4959 renames and copies. --follow without a filename will only show
4958 ancestors or descendants of the starting revision.
4960 ancestors or descendants of the starting revision.
4959
4961
4960 By default this command prints revision number and changeset id,
4962 By default this command prints revision number and changeset id,
4961 tags, non-trivial parents, user, date and time, and a summary for
4963 tags, non-trivial parents, user, date and time, and a summary for
4962 each commit. When the -v/--verbose switch is used, the list of
4964 each commit. When the -v/--verbose switch is used, the list of
4963 changed files and full commit message are shown.
4965 changed files and full commit message are shown.
4964
4966
4965 With --graph the revisions are shown as an ASCII art DAG with the most
4967 With --graph the revisions are shown as an ASCII art DAG with the most
4966 recent changeset at the top.
4968 recent changeset at the top.
4967 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4969 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4968 and '+' represents a fork where the changeset from the lines below is a
4970 and '+' represents a fork where the changeset from the lines below is a
4969 parent of the 'o' merge on the same line.
4971 parent of the 'o' merge on the same line.
4970
4972
4971 .. note::
4973 .. note::
4972
4974
4973 log -p/--patch may generate unexpected diff output for merge
4975 log -p/--patch may generate unexpected diff output for merge
4974 changesets, as it will only compare the merge changeset against
4976 changesets, as it will only compare the merge changeset against
4975 its first parent. Also, only files different from BOTH parents
4977 its first parent. Also, only files different from BOTH parents
4976 will appear in files:.
4978 will appear in files:.
4977
4979
4978 .. note::
4980 .. note::
4979
4981
4980 for performance reasons, log FILE may omit duplicate changes
4982 for performance reasons, log FILE may omit duplicate changes
4981 made on branches and will not show removals or mode changes. To
4983 made on branches and will not show removals or mode changes. To
4982 see all such changes, use the --removed switch.
4984 see all such changes, use the --removed switch.
4983
4985
4984 .. container:: verbose
4986 .. container:: verbose
4985
4987
4986 Some examples:
4988 Some examples:
4987
4989
4988 - changesets with full descriptions and file lists::
4990 - changesets with full descriptions and file lists::
4989
4991
4990 hg log -v
4992 hg log -v
4991
4993
4992 - changesets ancestral to the working directory::
4994 - changesets ancestral to the working directory::
4993
4995
4994 hg log -f
4996 hg log -f
4995
4997
4996 - last 10 commits on the current branch::
4998 - last 10 commits on the current branch::
4997
4999
4998 hg log -l 10 -b .
5000 hg log -l 10 -b .
4999
5001
5000 - changesets showing all modifications of a file, including removals::
5002 - changesets showing all modifications of a file, including removals::
5001
5003
5002 hg log --removed file.c
5004 hg log --removed file.c
5003
5005
5004 - all changesets that touch a directory, with diffs, excluding merges::
5006 - all changesets that touch a directory, with diffs, excluding merges::
5005
5007
5006 hg log -Mp lib/
5008 hg log -Mp lib/
5007
5009
5008 - all revision numbers that match a keyword::
5010 - all revision numbers that match a keyword::
5009
5011
5010 hg log -k bug --template "{rev}\\n"
5012 hg log -k bug --template "{rev}\\n"
5011
5013
5012 - the full hash identifier of the working directory parent::
5014 - the full hash identifier of the working directory parent::
5013
5015
5014 hg log -r . --template "{node}\\n"
5016 hg log -r . --template "{node}\\n"
5015
5017
5016 - list available log templates::
5018 - list available log templates::
5017
5019
5018 hg log -T list
5020 hg log -T list
5019
5021
5020 - check if a given changeset is included in a tagged release::
5022 - check if a given changeset is included in a tagged release::
5021
5023
5022 hg log -r "a21ccf and ancestor(1.9)"
5024 hg log -r "a21ccf and ancestor(1.9)"
5023
5025
5024 - find all changesets by some user in a date range::
5026 - find all changesets by some user in a date range::
5025
5027
5026 hg log -k alice -d "may 2008 to jul 2008"
5028 hg log -k alice -d "may 2008 to jul 2008"
5027
5029
5028 - summary of all changesets after the last tag::
5030 - summary of all changesets after the last tag::
5029
5031
5030 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5032 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5031
5033
5032 See :hg:`help dates` for a list of formats valid for -d/--date.
5034 See :hg:`help dates` for a list of formats valid for -d/--date.
5033
5035
5034 See :hg:`help revisions` and :hg:`help revsets` for more about
5036 See :hg:`help revisions` and :hg:`help revsets` for more about
5035 specifying revisions.
5037 specifying revisions.
5036
5038
5037 See :hg:`help templates` for more about pre-packaged styles and
5039 See :hg:`help templates` for more about pre-packaged styles and
5038 specifying custom templates.
5040 specifying custom templates.
5039
5041
5040 Returns 0 on success.
5042 Returns 0 on success.
5041
5043
5042 """
5044 """
5043 if opts.get('follow') and opts.get('rev'):
5045 if opts.get('follow') and opts.get('rev'):
5044 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5046 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5045 del opts['follow']
5047 del opts['follow']
5046
5048
5047 if opts.get('graph'):
5049 if opts.get('graph'):
5048 return cmdutil.graphlog(ui, repo, *pats, **opts)
5050 return cmdutil.graphlog(ui, repo, *pats, **opts)
5049
5051
5050 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5052 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5051 limit = cmdutil.loglimit(opts)
5053 limit = cmdutil.loglimit(opts)
5052 count = 0
5054 count = 0
5053
5055
5054 getrenamed = None
5056 getrenamed = None
5055 if opts.get('copies'):
5057 if opts.get('copies'):
5056 endrev = None
5058 endrev = None
5057 if opts.get('rev'):
5059 if opts.get('rev'):
5058 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5060 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5059 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5061 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5060
5062
5061 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5063 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5062 for rev in revs:
5064 for rev in revs:
5063 if count == limit:
5065 if count == limit:
5064 break
5066 break
5065 ctx = repo[rev]
5067 ctx = repo[rev]
5066 copies = None
5068 copies = None
5067 if getrenamed is not None and rev:
5069 if getrenamed is not None and rev:
5068 copies = []
5070 copies = []
5069 for fn in ctx.files():
5071 for fn in ctx.files():
5070 rename = getrenamed(fn, rev)
5072 rename = getrenamed(fn, rev)
5071 if rename:
5073 if rename:
5072 copies.append((fn, rename[0]))
5074 copies.append((fn, rename[0]))
5073 if filematcher:
5075 if filematcher:
5074 revmatchfn = filematcher(ctx.rev())
5076 revmatchfn = filematcher(ctx.rev())
5075 else:
5077 else:
5076 revmatchfn = None
5078 revmatchfn = None
5077 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5079 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5078 if displayer.flush(ctx):
5080 if displayer.flush(ctx):
5079 count += 1
5081 count += 1
5080
5082
5081 displayer.close()
5083 displayer.close()
5082
5084
5083 @command('manifest',
5085 @command('manifest',
5084 [('r', 'rev', '', _('revision to display'), _('REV')),
5086 [('r', 'rev', '', _('revision to display'), _('REV')),
5085 ('', 'all', False, _("list files from all revisions"))]
5087 ('', 'all', False, _("list files from all revisions"))]
5086 + formatteropts,
5088 + formatteropts,
5087 _('[-r REV]'))
5089 _('[-r REV]'))
5088 def manifest(ui, repo, node=None, rev=None, **opts):
5090 def manifest(ui, repo, node=None, rev=None, **opts):
5089 """output the current or given revision of the project manifest
5091 """output the current or given revision of the project manifest
5090
5092
5091 Print a list of version controlled files for the given revision.
5093 Print a list of version controlled files for the given revision.
5092 If no revision is given, the first parent of the working directory
5094 If no revision is given, the first parent of the working directory
5093 is used, or the null revision if no revision is checked out.
5095 is used, or the null revision if no revision is checked out.
5094
5096
5095 With -v, print file permissions, symlink and executable bits.
5097 With -v, print file permissions, symlink and executable bits.
5096 With --debug, print file revision hashes.
5098 With --debug, print file revision hashes.
5097
5099
5098 If option --all is specified, the list of all files from all revisions
5100 If option --all is specified, the list of all files from all revisions
5099 is printed. This includes deleted and renamed files.
5101 is printed. This includes deleted and renamed files.
5100
5102
5101 Returns 0 on success.
5103 Returns 0 on success.
5102 """
5104 """
5103
5105
5104 fm = ui.formatter('manifest', opts)
5106 fm = ui.formatter('manifest', opts)
5105
5107
5106 if opts.get('all'):
5108 if opts.get('all'):
5107 if rev or node:
5109 if rev or node:
5108 raise error.Abort(_("can't specify a revision with --all"))
5110 raise error.Abort(_("can't specify a revision with --all"))
5109
5111
5110 res = []
5112 res = []
5111 prefix = "data/"
5113 prefix = "data/"
5112 suffix = ".i"
5114 suffix = ".i"
5113 plen = len(prefix)
5115 plen = len(prefix)
5114 slen = len(suffix)
5116 slen = len(suffix)
5115 lock = repo.lock()
5117 lock = repo.lock()
5116 try:
5118 try:
5117 for fn, b, size in repo.store.datafiles():
5119 for fn, b, size in repo.store.datafiles():
5118 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5120 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5119 res.append(fn[plen:-slen])
5121 res.append(fn[plen:-slen])
5120 finally:
5122 finally:
5121 lock.release()
5123 lock.release()
5122 for f in res:
5124 for f in res:
5123 fm.startitem()
5125 fm.startitem()
5124 fm.write("path", '%s\n', f)
5126 fm.write("path", '%s\n', f)
5125 fm.end()
5127 fm.end()
5126 return
5128 return
5127
5129
5128 if rev and node:
5130 if rev and node:
5129 raise error.Abort(_("please specify just one revision"))
5131 raise error.Abort(_("please specify just one revision"))
5130
5132
5131 if not node:
5133 if not node:
5132 node = rev
5134 node = rev
5133
5135
5134 char = {'l': '@', 'x': '*', '': ''}
5136 char = {'l': '@', 'x': '*', '': ''}
5135 mode = {'l': '644', 'x': '755', '': '644'}
5137 mode = {'l': '644', 'x': '755', '': '644'}
5136 ctx = scmutil.revsingle(repo, node)
5138 ctx = scmutil.revsingle(repo, node)
5137 mf = ctx.manifest()
5139 mf = ctx.manifest()
5138 for f in ctx:
5140 for f in ctx:
5139 fm.startitem()
5141 fm.startitem()
5140 fl = ctx[f].flags()
5142 fl = ctx[f].flags()
5141 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5143 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5142 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5144 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5143 fm.write('path', '%s\n', f)
5145 fm.write('path', '%s\n', f)
5144 fm.end()
5146 fm.end()
5145
5147
5146 @command('^merge',
5148 @command('^merge',
5147 [('f', 'force', None,
5149 [('f', 'force', None,
5148 _('force a merge including outstanding changes (DEPRECATED)')),
5150 _('force a merge including outstanding changes (DEPRECATED)')),
5149 ('r', 'rev', '', _('revision to merge'), _('REV')),
5151 ('r', 'rev', '', _('revision to merge'), _('REV')),
5150 ('P', 'preview', None,
5152 ('P', 'preview', None,
5151 _('review revisions to merge (no merge is performed)'))
5153 _('review revisions to merge (no merge is performed)'))
5152 ] + mergetoolopts,
5154 ] + mergetoolopts,
5153 _('[-P] [-f] [[-r] REV]'))
5155 _('[-P] [-f] [[-r] REV]'))
5154 def merge(ui, repo, node=None, **opts):
5156 def merge(ui, repo, node=None, **opts):
5155 """merge another revision into working directory
5157 """merge another revision into working directory
5156
5158
5157 The current working directory is updated with all changes made in
5159 The current working directory is updated with all changes made in
5158 the requested revision since the last common predecessor revision.
5160 the requested revision since the last common predecessor revision.
5159
5161
5160 Files that changed between either parent are marked as changed for
5162 Files that changed between either parent are marked as changed for
5161 the next commit and a commit must be performed before any further
5163 the next commit and a commit must be performed before any further
5162 updates to the repository are allowed. The next commit will have
5164 updates to the repository are allowed. The next commit will have
5163 two parents.
5165 two parents.
5164
5166
5165 ``--tool`` can be used to specify the merge tool used for file
5167 ``--tool`` can be used to specify the merge tool used for file
5166 merges. It overrides the HGMERGE environment variable and your
5168 merges. It overrides the HGMERGE environment variable and your
5167 configuration files. See :hg:`help merge-tools` for options.
5169 configuration files. See :hg:`help merge-tools` for options.
5168
5170
5169 If no revision is specified, the working directory's parent is a
5171 If no revision is specified, the working directory's parent is a
5170 head revision, and the current branch contains exactly one other
5172 head revision, and the current branch contains exactly one other
5171 head, the other head is merged with by default. Otherwise, an
5173 head, the other head is merged with by default. Otherwise, an
5172 explicit revision with which to merge with must be provided.
5174 explicit revision with which to merge with must be provided.
5173
5175
5174 :hg:`resolve` must be used to resolve unresolved files.
5176 :hg:`resolve` must be used to resolve unresolved files.
5175
5177
5176 To undo an uncommitted merge, use :hg:`update --clean .` which
5178 To undo an uncommitted merge, use :hg:`update --clean .` which
5177 will check out a clean copy of the original merge parent, losing
5179 will check out a clean copy of the original merge parent, losing
5178 all changes.
5180 all changes.
5179
5181
5180 Returns 0 on success, 1 if there are unresolved files.
5182 Returns 0 on success, 1 if there are unresolved files.
5181 """
5183 """
5182
5184
5183 if opts.get('rev') and node:
5185 if opts.get('rev') and node:
5184 raise error.Abort(_("please specify just one revision"))
5186 raise error.Abort(_("please specify just one revision"))
5185 if not node:
5187 if not node:
5186 node = opts.get('rev')
5188 node = opts.get('rev')
5187
5189
5188 if node:
5190 if node:
5189 node = scmutil.revsingle(repo, node).node()
5191 node = scmutil.revsingle(repo, node).node()
5190
5192
5191 if not node:
5193 if not node:
5192 node = repo[destutil.destmerge(repo)].node()
5194 node = repo[destutil.destmerge(repo)].node()
5193
5195
5194 if opts.get('preview'):
5196 if opts.get('preview'):
5195 # find nodes that are ancestors of p2 but not of p1
5197 # find nodes that are ancestors of p2 but not of p1
5196 p1 = repo.lookup('.')
5198 p1 = repo.lookup('.')
5197 p2 = repo.lookup(node)
5199 p2 = repo.lookup(node)
5198 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5200 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5199
5201
5200 displayer = cmdutil.show_changeset(ui, repo, opts)
5202 displayer = cmdutil.show_changeset(ui, repo, opts)
5201 for node in nodes:
5203 for node in nodes:
5202 displayer.show(repo[node])
5204 displayer.show(repo[node])
5203 displayer.close()
5205 displayer.close()
5204 return 0
5206 return 0
5205
5207
5206 try:
5208 try:
5207 # ui.forcemerge is an internal variable, do not document
5209 # ui.forcemerge is an internal variable, do not document
5208 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5210 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5209 return hg.merge(repo, node, force=opts.get('force'))
5211 return hg.merge(repo, node, force=opts.get('force'))
5210 finally:
5212 finally:
5211 ui.setconfig('ui', 'forcemerge', '', 'merge')
5213 ui.setconfig('ui', 'forcemerge', '', 'merge')
5212
5214
5213 @command('outgoing|out',
5215 @command('outgoing|out',
5214 [('f', 'force', None, _('run even when the destination is unrelated')),
5216 [('f', 'force', None, _('run even when the destination is unrelated')),
5215 ('r', 'rev', [],
5217 ('r', 'rev', [],
5216 _('a changeset intended to be included in the destination'), _('REV')),
5218 _('a changeset intended to be included in the destination'), _('REV')),
5217 ('n', 'newest-first', None, _('show newest record first')),
5219 ('n', 'newest-first', None, _('show newest record first')),
5218 ('B', 'bookmarks', False, _('compare bookmarks')),
5220 ('B', 'bookmarks', False, _('compare bookmarks')),
5219 ('b', 'branch', [], _('a specific branch you would like to push'),
5221 ('b', 'branch', [], _('a specific branch you would like to push'),
5220 _('BRANCH')),
5222 _('BRANCH')),
5221 ] + logopts + remoteopts + subrepoopts,
5223 ] + logopts + remoteopts + subrepoopts,
5222 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5224 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5223 def outgoing(ui, repo, dest=None, **opts):
5225 def outgoing(ui, repo, dest=None, **opts):
5224 """show changesets not found in the destination
5226 """show changesets not found in the destination
5225
5227
5226 Show changesets not found in the specified destination repository
5228 Show changesets not found in the specified destination repository
5227 or the default push location. These are the changesets that would
5229 or the default push location. These are the changesets that would
5228 be pushed if a push was requested.
5230 be pushed if a push was requested.
5229
5231
5230 See pull for details of valid destination formats.
5232 See pull for details of valid destination formats.
5231
5233
5232 .. container:: verbose
5234 .. container:: verbose
5233
5235
5234 With -B/--bookmarks, the result of bookmark comparison between
5236 With -B/--bookmarks, the result of bookmark comparison between
5235 local and remote repositories is displayed. With -v/--verbose,
5237 local and remote repositories is displayed. With -v/--verbose,
5236 status is also displayed for each bookmark like below::
5238 status is also displayed for each bookmark like below::
5237
5239
5238 BM1 01234567890a added
5240 BM1 01234567890a added
5239 BM2 deleted
5241 BM2 deleted
5240 BM3 234567890abc advanced
5242 BM3 234567890abc advanced
5241 BM4 34567890abcd diverged
5243 BM4 34567890abcd diverged
5242 BM5 4567890abcde changed
5244 BM5 4567890abcde changed
5243
5245
5244 The action taken when pushing depends on the
5246 The action taken when pushing depends on the
5245 status of each bookmark:
5247 status of each bookmark:
5246
5248
5247 :``added``: push with ``-B`` will create it
5249 :``added``: push with ``-B`` will create it
5248 :``deleted``: push with ``-B`` will delete it
5250 :``deleted``: push with ``-B`` will delete it
5249 :``advanced``: push will update it
5251 :``advanced``: push will update it
5250 :``diverged``: push with ``-B`` will update it
5252 :``diverged``: push with ``-B`` will update it
5251 :``changed``: push with ``-B`` will update it
5253 :``changed``: push with ``-B`` will update it
5252
5254
5253 From the point of view of pushing behavior, bookmarks
5255 From the point of view of pushing behavior, bookmarks
5254 existing only in the remote repository are treated as
5256 existing only in the remote repository are treated as
5255 ``deleted``, even if it is in fact added remotely.
5257 ``deleted``, even if it is in fact added remotely.
5256
5258
5257 Returns 0 if there are outgoing changes, 1 otherwise.
5259 Returns 0 if there are outgoing changes, 1 otherwise.
5258 """
5260 """
5259 if opts.get('graph'):
5261 if opts.get('graph'):
5260 cmdutil.checkunsupportedgraphflags([], opts)
5262 cmdutil.checkunsupportedgraphflags([], opts)
5261 o, other = hg._outgoing(ui, repo, dest, opts)
5263 o, other = hg._outgoing(ui, repo, dest, opts)
5262 if not o:
5264 if not o:
5263 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5265 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5264 return
5266 return
5265
5267
5266 revdag = cmdutil.graphrevs(repo, o, opts)
5268 revdag = cmdutil.graphrevs(repo, o, opts)
5267 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5269 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5268 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5270 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5269 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5271 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5270 return 0
5272 return 0
5271
5273
5272 if opts.get('bookmarks'):
5274 if opts.get('bookmarks'):
5273 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5275 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5274 dest, branches = hg.parseurl(dest, opts.get('branch'))
5276 dest, branches = hg.parseurl(dest, opts.get('branch'))
5275 other = hg.peer(repo, opts, dest)
5277 other = hg.peer(repo, opts, dest)
5276 if 'bookmarks' not in other.listkeys('namespaces'):
5278 if 'bookmarks' not in other.listkeys('namespaces'):
5277 ui.warn(_("remote doesn't support bookmarks\n"))
5279 ui.warn(_("remote doesn't support bookmarks\n"))
5278 return 0
5280 return 0
5279 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5281 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5280 return bookmarks.outgoing(ui, repo, other)
5282 return bookmarks.outgoing(ui, repo, other)
5281
5283
5282 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5284 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5283 try:
5285 try:
5284 return hg.outgoing(ui, repo, dest, opts)
5286 return hg.outgoing(ui, repo, dest, opts)
5285 finally:
5287 finally:
5286 del repo._subtoppath
5288 del repo._subtoppath
5287
5289
5288 @command('parents',
5290 @command('parents',
5289 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5291 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5290 ] + templateopts,
5292 ] + templateopts,
5291 _('[-r REV] [FILE]'),
5293 _('[-r REV] [FILE]'),
5292 inferrepo=True)
5294 inferrepo=True)
5293 def parents(ui, repo, file_=None, **opts):
5295 def parents(ui, repo, file_=None, **opts):
5294 """show the parents of the working directory or revision (DEPRECATED)
5296 """show the parents of the working directory or revision (DEPRECATED)
5295
5297
5296 Print the working directory's parent revisions. If a revision is
5298 Print the working directory's parent revisions. If a revision is
5297 given via -r/--rev, the parent of that revision will be printed.
5299 given via -r/--rev, the parent of that revision will be printed.
5298 If a file argument is given, the revision in which the file was
5300 If a file argument is given, the revision in which the file was
5299 last changed (before the working directory revision or the
5301 last changed (before the working directory revision or the
5300 argument to --rev if given) is printed.
5302 argument to --rev if given) is printed.
5301
5303
5302 This command is equivalent to::
5304 This command is equivalent to::
5303
5305
5304 hg log -r "parents()" or
5306 hg log -r "parents()" or
5305 hg log -r "parents(REV)" or
5307 hg log -r "parents(REV)" or
5306 hg log -r "max(file(FILE))" or
5308 hg log -r "max(file(FILE))" or
5307 hg log -r "max(::REV and file(FILE))"
5309 hg log -r "max(::REV and file(FILE))"
5308
5310
5309 See :hg:`summary` and :hg:`help revsets` for related information.
5311 See :hg:`summary` and :hg:`help revsets` for related information.
5310
5312
5311 Returns 0 on success.
5313 Returns 0 on success.
5312 """
5314 """
5313
5315
5314 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5316 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5315
5317
5316 if file_:
5318 if file_:
5317 m = scmutil.match(ctx, (file_,), opts)
5319 m = scmutil.match(ctx, (file_,), opts)
5318 if m.anypats() or len(m.files()) != 1:
5320 if m.anypats() or len(m.files()) != 1:
5319 raise error.Abort(_('can only specify an explicit filename'))
5321 raise error.Abort(_('can only specify an explicit filename'))
5320 file_ = m.files()[0]
5322 file_ = m.files()[0]
5321 filenodes = []
5323 filenodes = []
5322 for cp in ctx.parents():
5324 for cp in ctx.parents():
5323 if not cp:
5325 if not cp:
5324 continue
5326 continue
5325 try:
5327 try:
5326 filenodes.append(cp.filenode(file_))
5328 filenodes.append(cp.filenode(file_))
5327 except error.LookupError:
5329 except error.LookupError:
5328 pass
5330 pass
5329 if not filenodes:
5331 if not filenodes:
5330 raise error.Abort(_("'%s' not found in manifest!") % file_)
5332 raise error.Abort(_("'%s' not found in manifest!") % file_)
5331 p = []
5333 p = []
5332 for fn in filenodes:
5334 for fn in filenodes:
5333 fctx = repo.filectx(file_, fileid=fn)
5335 fctx = repo.filectx(file_, fileid=fn)
5334 p.append(fctx.node())
5336 p.append(fctx.node())
5335 else:
5337 else:
5336 p = [cp.node() for cp in ctx.parents()]
5338 p = [cp.node() for cp in ctx.parents()]
5337
5339
5338 displayer = cmdutil.show_changeset(ui, repo, opts)
5340 displayer = cmdutil.show_changeset(ui, repo, opts)
5339 for n in p:
5341 for n in p:
5340 if n != nullid:
5342 if n != nullid:
5341 displayer.show(repo[n])
5343 displayer.show(repo[n])
5342 displayer.close()
5344 displayer.close()
5343
5345
5344 @command('paths', [], _('[NAME]'), optionalrepo=True)
5346 @command('paths', [], _('[NAME]'), optionalrepo=True)
5345 def paths(ui, repo, search=None):
5347 def paths(ui, repo, search=None):
5346 """show aliases for remote repositories
5348 """show aliases for remote repositories
5347
5349
5348 Show definition of symbolic path name NAME. If no name is given,
5350 Show definition of symbolic path name NAME. If no name is given,
5349 show definition of all available names.
5351 show definition of all available names.
5350
5352
5351 Option -q/--quiet suppresses all output when searching for NAME
5353 Option -q/--quiet suppresses all output when searching for NAME
5352 and shows only the path names when listing all definitions.
5354 and shows only the path names when listing all definitions.
5353
5355
5354 Path names are defined in the [paths] section of your
5356 Path names are defined in the [paths] section of your
5355 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5357 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5356 repository, ``.hg/hgrc`` is used, too.
5358 repository, ``.hg/hgrc`` is used, too.
5357
5359
5358 The path names ``default`` and ``default-push`` have a special
5360 The path names ``default`` and ``default-push`` have a special
5359 meaning. When performing a push or pull operation, they are used
5361 meaning. When performing a push or pull operation, they are used
5360 as fallbacks if no location is specified on the command-line.
5362 as fallbacks if no location is specified on the command-line.
5361 When ``default-push`` is set, it will be used for push and
5363 When ``default-push`` is set, it will be used for push and
5362 ``default`` will be used for pull; otherwise ``default`` is used
5364 ``default`` will be used for pull; otherwise ``default`` is used
5363 as the fallback for both. When cloning a repository, the clone
5365 as the fallback for both. When cloning a repository, the clone
5364 source is written as ``default`` in ``.hg/hgrc``. Note that
5366 source is written as ``default`` in ``.hg/hgrc``. Note that
5365 ``default`` and ``default-push`` apply to all inbound (e.g.
5367 ``default`` and ``default-push`` apply to all inbound (e.g.
5366 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
5368 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
5367 :hg:`bundle`) operations.
5369 :hg:`bundle`) operations.
5368
5370
5369 See :hg:`help urls` for more information.
5371 See :hg:`help urls` for more information.
5370
5372
5371 Returns 0 on success.
5373 Returns 0 on success.
5372 """
5374 """
5373 if search:
5375 if search:
5374 for name, path in sorted(ui.paths.iteritems()):
5376 for name, path in sorted(ui.paths.iteritems()):
5375 if name == search:
5377 if name == search:
5376 ui.status("%s\n" % util.hidepassword(path.rawloc))
5378 ui.status("%s\n" % util.hidepassword(path.rawloc))
5377 return
5379 return
5378 if not ui.quiet:
5380 if not ui.quiet:
5379 ui.warn(_("not found!\n"))
5381 ui.warn(_("not found!\n"))
5380 return 1
5382 return 1
5381 else:
5383 else:
5382 for name, path in sorted(ui.paths.iteritems()):
5384 for name, path in sorted(ui.paths.iteritems()):
5383 if ui.quiet:
5385 if ui.quiet:
5384 ui.write("%s\n" % name)
5386 ui.write("%s\n" % name)
5385 else:
5387 else:
5386 ui.write("%s = %s\n" % (name,
5388 ui.write("%s = %s\n" % (name,
5387 util.hidepassword(path.rawloc)))
5389 util.hidepassword(path.rawloc)))
5388 for subopt, value in sorted(path.suboptions.items()):
5390 for subopt, value in sorted(path.suboptions.items()):
5389 ui.write('%s:%s = %s\n' % (name, subopt, value))
5391 ui.write('%s:%s = %s\n' % (name, subopt, value))
5390
5392
5391 @command('phase',
5393 @command('phase',
5392 [('p', 'public', False, _('set changeset phase to public')),
5394 [('p', 'public', False, _('set changeset phase to public')),
5393 ('d', 'draft', False, _('set changeset phase to draft')),
5395 ('d', 'draft', False, _('set changeset phase to draft')),
5394 ('s', 'secret', False, _('set changeset phase to secret')),
5396 ('s', 'secret', False, _('set changeset phase to secret')),
5395 ('f', 'force', False, _('allow to move boundary backward')),
5397 ('f', 'force', False, _('allow to move boundary backward')),
5396 ('r', 'rev', [], _('target revision'), _('REV')),
5398 ('r', 'rev', [], _('target revision'), _('REV')),
5397 ],
5399 ],
5398 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5400 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5399 def phase(ui, repo, *revs, **opts):
5401 def phase(ui, repo, *revs, **opts):
5400 """set or show the current phase name
5402 """set or show the current phase name
5401
5403
5402 With no argument, show the phase name of the current revision(s).
5404 With no argument, show the phase name of the current revision(s).
5403
5405
5404 With one of -p/--public, -d/--draft or -s/--secret, change the
5406 With one of -p/--public, -d/--draft or -s/--secret, change the
5405 phase value of the specified revisions.
5407 phase value of the specified revisions.
5406
5408
5407 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5409 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5408 lower phase to an higher phase. Phases are ordered as follows::
5410 lower phase to an higher phase. Phases are ordered as follows::
5409
5411
5410 public < draft < secret
5412 public < draft < secret
5411
5413
5412 Returns 0 on success, 1 if some phases could not be changed.
5414 Returns 0 on success, 1 if some phases could not be changed.
5413
5415
5414 (For more information about the phases concept, see :hg:`help phases`.)
5416 (For more information about the phases concept, see :hg:`help phases`.)
5415 """
5417 """
5416 # search for a unique phase argument
5418 # search for a unique phase argument
5417 targetphase = None
5419 targetphase = None
5418 for idx, name in enumerate(phases.phasenames):
5420 for idx, name in enumerate(phases.phasenames):
5419 if opts[name]:
5421 if opts[name]:
5420 if targetphase is not None:
5422 if targetphase is not None:
5421 raise error.Abort(_('only one phase can be specified'))
5423 raise error.Abort(_('only one phase can be specified'))
5422 targetphase = idx
5424 targetphase = idx
5423
5425
5424 # look for specified revision
5426 # look for specified revision
5425 revs = list(revs)
5427 revs = list(revs)
5426 revs.extend(opts['rev'])
5428 revs.extend(opts['rev'])
5427 if not revs:
5429 if not revs:
5428 # display both parents as the second parent phase can influence
5430 # display both parents as the second parent phase can influence
5429 # the phase of a merge commit
5431 # the phase of a merge commit
5430 revs = [c.rev() for c in repo[None].parents()]
5432 revs = [c.rev() for c in repo[None].parents()]
5431
5433
5432 revs = scmutil.revrange(repo, revs)
5434 revs = scmutil.revrange(repo, revs)
5433
5435
5434 lock = None
5436 lock = None
5435 ret = 0
5437 ret = 0
5436 if targetphase is None:
5438 if targetphase is None:
5437 # display
5439 # display
5438 for r in revs:
5440 for r in revs:
5439 ctx = repo[r]
5441 ctx = repo[r]
5440 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5442 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5441 else:
5443 else:
5442 tr = None
5444 tr = None
5443 lock = repo.lock()
5445 lock = repo.lock()
5444 try:
5446 try:
5445 tr = repo.transaction("phase")
5447 tr = repo.transaction("phase")
5446 # set phase
5448 # set phase
5447 if not revs:
5449 if not revs:
5448 raise error.Abort(_('empty revision set'))
5450 raise error.Abort(_('empty revision set'))
5449 nodes = [repo[r].node() for r in revs]
5451 nodes = [repo[r].node() for r in revs]
5450 # moving revision from public to draft may hide them
5452 # moving revision from public to draft may hide them
5451 # We have to check result on an unfiltered repository
5453 # We have to check result on an unfiltered repository
5452 unfi = repo.unfiltered()
5454 unfi = repo.unfiltered()
5453 getphase = unfi._phasecache.phase
5455 getphase = unfi._phasecache.phase
5454 olddata = [getphase(unfi, r) for r in unfi]
5456 olddata = [getphase(unfi, r) for r in unfi]
5455 phases.advanceboundary(repo, tr, targetphase, nodes)
5457 phases.advanceboundary(repo, tr, targetphase, nodes)
5456 if opts['force']:
5458 if opts['force']:
5457 phases.retractboundary(repo, tr, targetphase, nodes)
5459 phases.retractboundary(repo, tr, targetphase, nodes)
5458 tr.close()
5460 tr.close()
5459 finally:
5461 finally:
5460 if tr is not None:
5462 if tr is not None:
5461 tr.release()
5463 tr.release()
5462 lock.release()
5464 lock.release()
5463 getphase = unfi._phasecache.phase
5465 getphase = unfi._phasecache.phase
5464 newdata = [getphase(unfi, r) for r in unfi]
5466 newdata = [getphase(unfi, r) for r in unfi]
5465 changes = sum(newdata[r] != olddata[r] for r in unfi)
5467 changes = sum(newdata[r] != olddata[r] for r in unfi)
5466 cl = unfi.changelog
5468 cl = unfi.changelog
5467 rejected = [n for n in nodes
5469 rejected = [n for n in nodes
5468 if newdata[cl.rev(n)] < targetphase]
5470 if newdata[cl.rev(n)] < targetphase]
5469 if rejected:
5471 if rejected:
5470 ui.warn(_('cannot move %i changesets to a higher '
5472 ui.warn(_('cannot move %i changesets to a higher '
5471 'phase, use --force\n') % len(rejected))
5473 'phase, use --force\n') % len(rejected))
5472 ret = 1
5474 ret = 1
5473 if changes:
5475 if changes:
5474 msg = _('phase changed for %i changesets\n') % changes
5476 msg = _('phase changed for %i changesets\n') % changes
5475 if ret:
5477 if ret:
5476 ui.status(msg)
5478 ui.status(msg)
5477 else:
5479 else:
5478 ui.note(msg)
5480 ui.note(msg)
5479 else:
5481 else:
5480 ui.warn(_('no phases changed\n'))
5482 ui.warn(_('no phases changed\n'))
5481 return ret
5483 return ret
5482
5484
5483 def postincoming(ui, repo, modheads, optupdate, checkout):
5485 def postincoming(ui, repo, modheads, optupdate, checkout):
5484 if modheads == 0:
5486 if modheads == 0:
5485 return
5487 return
5486 if optupdate:
5488 if optupdate:
5487 try:
5489 try:
5488 brev = checkout
5490 brev = checkout
5489 movemarkfrom = None
5491 movemarkfrom = None
5490 if not checkout:
5492 if not checkout:
5491 updata = destutil.destupdate(repo)
5493 updata = destutil.destupdate(repo)
5492 checkout, movemarkfrom, brev = updata
5494 checkout, movemarkfrom, brev = updata
5493 ret = hg.update(repo, checkout)
5495 ret = hg.update(repo, checkout)
5494 except error.UpdateAbort as inst:
5496 except error.UpdateAbort as inst:
5495 msg = _("not updating: %s") % str(inst)
5497 msg = _("not updating: %s") % str(inst)
5496 hint = inst.hint
5498 hint = inst.hint
5497 raise error.UpdateAbort(msg, hint=hint)
5499 raise error.UpdateAbort(msg, hint=hint)
5498 if not ret and not checkout:
5500 if not ret and not checkout:
5499 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5501 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5500 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5502 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5501 return ret
5503 return ret
5502 if modheads > 1:
5504 if modheads > 1:
5503 currentbranchheads = len(repo.branchheads())
5505 currentbranchheads = len(repo.branchheads())
5504 if currentbranchheads == modheads:
5506 if currentbranchheads == modheads:
5505 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5507 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5506 elif currentbranchheads > 1:
5508 elif currentbranchheads > 1:
5507 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5509 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5508 "merge)\n"))
5510 "merge)\n"))
5509 else:
5511 else:
5510 ui.status(_("(run 'hg heads' to see heads)\n"))
5512 ui.status(_("(run 'hg heads' to see heads)\n"))
5511 else:
5513 else:
5512 ui.status(_("(run 'hg update' to get a working copy)\n"))
5514 ui.status(_("(run 'hg update' to get a working copy)\n"))
5513
5515
5514 @command('^pull',
5516 @command('^pull',
5515 [('u', 'update', None,
5517 [('u', 'update', None,
5516 _('update to new branch head if changesets were pulled')),
5518 _('update to new branch head if changesets were pulled')),
5517 ('f', 'force', None, _('run even when remote repository is unrelated')),
5519 ('f', 'force', None, _('run even when remote repository is unrelated')),
5518 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5520 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5519 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5521 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5520 ('b', 'branch', [], _('a specific branch you would like to pull'),
5522 ('b', 'branch', [], _('a specific branch you would like to pull'),
5521 _('BRANCH')),
5523 _('BRANCH')),
5522 ] + remoteopts,
5524 ] + remoteopts,
5523 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5525 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5524 def pull(ui, repo, source="default", **opts):
5526 def pull(ui, repo, source="default", **opts):
5525 """pull changes from the specified source
5527 """pull changes from the specified source
5526
5528
5527 Pull changes from a remote repository to a local one.
5529 Pull changes from a remote repository to a local one.
5528
5530
5529 This finds all changes from the repository at the specified path
5531 This finds all changes from the repository at the specified path
5530 or URL and adds them to a local repository (the current one unless
5532 or URL and adds them to a local repository (the current one unless
5531 -R is specified). By default, this does not update the copy of the
5533 -R is specified). By default, this does not update the copy of the
5532 project in the working directory.
5534 project in the working directory.
5533
5535
5534 Use :hg:`incoming` if you want to see what would have been added
5536 Use :hg:`incoming` if you want to see what would have been added
5535 by a pull at the time you issued this command. If you then decide
5537 by a pull at the time you issued this command. If you then decide
5536 to add those changes to the repository, you should use :hg:`pull
5538 to add those changes to the repository, you should use :hg:`pull
5537 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5539 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5538
5540
5539 If SOURCE is omitted, the 'default' path will be used.
5541 If SOURCE is omitted, the 'default' path will be used.
5540 See :hg:`help urls` for more information.
5542 See :hg:`help urls` for more information.
5541
5543
5542 Returns 0 on success, 1 if an update had unresolved files.
5544 Returns 0 on success, 1 if an update had unresolved files.
5543 """
5545 """
5544 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5546 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5545 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5547 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5546 other = hg.peer(repo, opts, source)
5548 other = hg.peer(repo, opts, source)
5547 try:
5549 try:
5548 revs, checkout = hg.addbranchrevs(repo, other, branches,
5550 revs, checkout = hg.addbranchrevs(repo, other, branches,
5549 opts.get('rev'))
5551 opts.get('rev'))
5550
5552
5551
5553
5552 pullopargs = {}
5554 pullopargs = {}
5553 if opts.get('bookmark'):
5555 if opts.get('bookmark'):
5554 if not revs:
5556 if not revs:
5555 revs = []
5557 revs = []
5556 # The list of bookmark used here is not the one used to actually
5558 # The list of bookmark used here is not the one used to actually
5557 # update the bookmark name. This can result in the revision pulled
5559 # update the bookmark name. This can result in the revision pulled
5558 # not ending up with the name of the bookmark because of a race
5560 # not ending up with the name of the bookmark because of a race
5559 # condition on the server. (See issue 4689 for details)
5561 # condition on the server. (See issue 4689 for details)
5560 remotebookmarks = other.listkeys('bookmarks')
5562 remotebookmarks = other.listkeys('bookmarks')
5561 pullopargs['remotebookmarks'] = remotebookmarks
5563 pullopargs['remotebookmarks'] = remotebookmarks
5562 for b in opts['bookmark']:
5564 for b in opts['bookmark']:
5563 if b not in remotebookmarks:
5565 if b not in remotebookmarks:
5564 raise error.Abort(_('remote bookmark %s not found!') % b)
5566 raise error.Abort(_('remote bookmark %s not found!') % b)
5565 revs.append(remotebookmarks[b])
5567 revs.append(remotebookmarks[b])
5566
5568
5567 if revs:
5569 if revs:
5568 try:
5570 try:
5569 # When 'rev' is a bookmark name, we cannot guarantee that it
5571 # When 'rev' is a bookmark name, we cannot guarantee that it
5570 # will be updated with that name because of a race condition
5572 # will be updated with that name because of a race condition
5571 # server side. (See issue 4689 for details)
5573 # server side. (See issue 4689 for details)
5572 oldrevs = revs
5574 oldrevs = revs
5573 revs = [] # actually, nodes
5575 revs = [] # actually, nodes
5574 for r in oldrevs:
5576 for r in oldrevs:
5575 node = other.lookup(r)
5577 node = other.lookup(r)
5576 revs.append(node)
5578 revs.append(node)
5577 if r == checkout:
5579 if r == checkout:
5578 checkout = node
5580 checkout = node
5579 except error.CapabilityError:
5581 except error.CapabilityError:
5580 err = _("other repository doesn't support revision lookup, "
5582 err = _("other repository doesn't support revision lookup, "
5581 "so a rev cannot be specified.")
5583 "so a rev cannot be specified.")
5582 raise error.Abort(err)
5584 raise error.Abort(err)
5583
5585
5584 pullopargs.update(opts.get('opargs', {}))
5586 pullopargs.update(opts.get('opargs', {}))
5585 modheads = exchange.pull(repo, other, heads=revs,
5587 modheads = exchange.pull(repo, other, heads=revs,
5586 force=opts.get('force'),
5588 force=opts.get('force'),
5587 bookmarks=opts.get('bookmark', ()),
5589 bookmarks=opts.get('bookmark', ()),
5588 opargs=pullopargs).cgresult
5590 opargs=pullopargs).cgresult
5589 if checkout:
5591 if checkout:
5590 checkout = str(repo.changelog.rev(checkout))
5592 checkout = str(repo.changelog.rev(checkout))
5591 repo._subtoppath = source
5593 repo._subtoppath = source
5592 try:
5594 try:
5593 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5595 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5594
5596
5595 finally:
5597 finally:
5596 del repo._subtoppath
5598 del repo._subtoppath
5597
5599
5598 finally:
5600 finally:
5599 other.close()
5601 other.close()
5600 return ret
5602 return ret
5601
5603
5602 @command('^push',
5604 @command('^push',
5603 [('f', 'force', None, _('force push')),
5605 [('f', 'force', None, _('force push')),
5604 ('r', 'rev', [],
5606 ('r', 'rev', [],
5605 _('a changeset intended to be included in the destination'),
5607 _('a changeset intended to be included in the destination'),
5606 _('REV')),
5608 _('REV')),
5607 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5609 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5608 ('b', 'branch', [],
5610 ('b', 'branch', [],
5609 _('a specific branch you would like to push'), _('BRANCH')),
5611 _('a specific branch you would like to push'), _('BRANCH')),
5610 ('', 'new-branch', False, _('allow pushing a new branch')),
5612 ('', 'new-branch', False, _('allow pushing a new branch')),
5611 ] + remoteopts,
5613 ] + remoteopts,
5612 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5614 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5613 def push(ui, repo, dest=None, **opts):
5615 def push(ui, repo, dest=None, **opts):
5614 """push changes to the specified destination
5616 """push changes to the specified destination
5615
5617
5616 Push changesets from the local repository to the specified
5618 Push changesets from the local repository to the specified
5617 destination.
5619 destination.
5618
5620
5619 This operation is symmetrical to pull: it is identical to a pull
5621 This operation is symmetrical to pull: it is identical to a pull
5620 in the destination repository from the current one.
5622 in the destination repository from the current one.
5621
5623
5622 By default, push will not allow creation of new heads at the
5624 By default, push will not allow creation of new heads at the
5623 destination, since multiple heads would make it unclear which head
5625 destination, since multiple heads would make it unclear which head
5624 to use. In this situation, it is recommended to pull and merge
5626 to use. In this situation, it is recommended to pull and merge
5625 before pushing.
5627 before pushing.
5626
5628
5627 Use --new-branch if you want to allow push to create a new named
5629 Use --new-branch if you want to allow push to create a new named
5628 branch that is not present at the destination. This allows you to
5630 branch that is not present at the destination. This allows you to
5629 only create a new branch without forcing other changes.
5631 only create a new branch without forcing other changes.
5630
5632
5631 .. note::
5633 .. note::
5632
5634
5633 Extra care should be taken with the -f/--force option,
5635 Extra care should be taken with the -f/--force option,
5634 which will push all new heads on all branches, an action which will
5636 which will push all new heads on all branches, an action which will
5635 almost always cause confusion for collaborators.
5637 almost always cause confusion for collaborators.
5636
5638
5637 If -r/--rev is used, the specified revision and all its ancestors
5639 If -r/--rev is used, the specified revision and all its ancestors
5638 will be pushed to the remote repository.
5640 will be pushed to the remote repository.
5639
5641
5640 If -B/--bookmark is used, the specified bookmarked revision, its
5642 If -B/--bookmark is used, the specified bookmarked revision, its
5641 ancestors, and the bookmark will be pushed to the remote
5643 ancestors, and the bookmark will be pushed to the remote
5642 repository.
5644 repository.
5643
5645
5644 Please see :hg:`help urls` for important details about ``ssh://``
5646 Please see :hg:`help urls` for important details about ``ssh://``
5645 URLs. If DESTINATION is omitted, a default path will be used.
5647 URLs. If DESTINATION is omitted, a default path will be used.
5646
5648
5647 Returns 0 if push was successful, 1 if nothing to push.
5649 Returns 0 if push was successful, 1 if nothing to push.
5648 """
5650 """
5649
5651
5650 if opts.get('bookmark'):
5652 if opts.get('bookmark'):
5651 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5653 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5652 for b in opts['bookmark']:
5654 for b in opts['bookmark']:
5653 # translate -B options to -r so changesets get pushed
5655 # translate -B options to -r so changesets get pushed
5654 if b in repo._bookmarks:
5656 if b in repo._bookmarks:
5655 opts.setdefault('rev', []).append(b)
5657 opts.setdefault('rev', []).append(b)
5656 else:
5658 else:
5657 # if we try to push a deleted bookmark, translate it to null
5659 # if we try to push a deleted bookmark, translate it to null
5658 # this lets simultaneous -r, -b options continue working
5660 # this lets simultaneous -r, -b options continue working
5659 opts.setdefault('rev', []).append("null")
5661 opts.setdefault('rev', []).append("null")
5660
5662
5661 path = ui.paths.getpath(dest, default='default')
5663 path = ui.paths.getpath(dest, default='default')
5662 if not path:
5664 if not path:
5663 raise error.Abort(_('default repository not configured!'),
5665 raise error.Abort(_('default repository not configured!'),
5664 hint=_('see the "path" section in "hg help config"'))
5666 hint=_('see the "path" section in "hg help config"'))
5665 dest = path.pushloc or path.loc
5667 dest = path.pushloc or path.loc
5666 branches = (path.branch, opts.get('branch') or [])
5668 branches = (path.branch, opts.get('branch') or [])
5667 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5669 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5668 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5670 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5669 other = hg.peer(repo, opts, dest)
5671 other = hg.peer(repo, opts, dest)
5670
5672
5671 if revs:
5673 if revs:
5672 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5674 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5673 if not revs:
5675 if not revs:
5674 raise error.Abort(_("specified revisions evaluate to an empty set"),
5676 raise error.Abort(_("specified revisions evaluate to an empty set"),
5675 hint=_("use different revision arguments"))
5677 hint=_("use different revision arguments"))
5676
5678
5677 repo._subtoppath = dest
5679 repo._subtoppath = dest
5678 try:
5680 try:
5679 # push subrepos depth-first for coherent ordering
5681 # push subrepos depth-first for coherent ordering
5680 c = repo['']
5682 c = repo['']
5681 subs = c.substate # only repos that are committed
5683 subs = c.substate # only repos that are committed
5682 for s in sorted(subs):
5684 for s in sorted(subs):
5683 result = c.sub(s).push(opts)
5685 result = c.sub(s).push(opts)
5684 if result == 0:
5686 if result == 0:
5685 return not result
5687 return not result
5686 finally:
5688 finally:
5687 del repo._subtoppath
5689 del repo._subtoppath
5688 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5690 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5689 newbranch=opts.get('new_branch'),
5691 newbranch=opts.get('new_branch'),
5690 bookmarks=opts.get('bookmark', ()),
5692 bookmarks=opts.get('bookmark', ()),
5691 opargs=opts.get('opargs'))
5693 opargs=opts.get('opargs'))
5692
5694
5693 result = not pushop.cgresult
5695 result = not pushop.cgresult
5694
5696
5695 if pushop.bkresult is not None:
5697 if pushop.bkresult is not None:
5696 if pushop.bkresult == 2:
5698 if pushop.bkresult == 2:
5697 result = 2
5699 result = 2
5698 elif not result and pushop.bkresult:
5700 elif not result and pushop.bkresult:
5699 result = 2
5701 result = 2
5700
5702
5701 return result
5703 return result
5702
5704
5703 @command('recover', [])
5705 @command('recover', [])
5704 def recover(ui, repo):
5706 def recover(ui, repo):
5705 """roll back an interrupted transaction
5707 """roll back an interrupted transaction
5706
5708
5707 Recover from an interrupted commit or pull.
5709 Recover from an interrupted commit or pull.
5708
5710
5709 This command tries to fix the repository status after an
5711 This command tries to fix the repository status after an
5710 interrupted operation. It should only be necessary when Mercurial
5712 interrupted operation. It should only be necessary when Mercurial
5711 suggests it.
5713 suggests it.
5712
5714
5713 Returns 0 if successful, 1 if nothing to recover or verify fails.
5715 Returns 0 if successful, 1 if nothing to recover or verify fails.
5714 """
5716 """
5715 if repo.recover():
5717 if repo.recover():
5716 return hg.verify(repo)
5718 return hg.verify(repo)
5717 return 1
5719 return 1
5718
5720
5719 @command('^remove|rm',
5721 @command('^remove|rm',
5720 [('A', 'after', None, _('record delete for missing files')),
5722 [('A', 'after', None, _('record delete for missing files')),
5721 ('f', 'force', None,
5723 ('f', 'force', None,
5722 _('remove (and delete) file even if added or modified')),
5724 _('remove (and delete) file even if added or modified')),
5723 ] + subrepoopts + walkopts,
5725 ] + subrepoopts + walkopts,
5724 _('[OPTION]... FILE...'),
5726 _('[OPTION]... FILE...'),
5725 inferrepo=True)
5727 inferrepo=True)
5726 def remove(ui, repo, *pats, **opts):
5728 def remove(ui, repo, *pats, **opts):
5727 """remove the specified files on the next commit
5729 """remove the specified files on the next commit
5728
5730
5729 Schedule the indicated files for removal from the current branch.
5731 Schedule the indicated files for removal from the current branch.
5730
5732
5731 This command schedules the files to be removed at the next commit.
5733 This command schedules the files to be removed at the next commit.
5732 To undo a remove before that, see :hg:`revert`. To undo added
5734 To undo a remove before that, see :hg:`revert`. To undo added
5733 files, see :hg:`forget`.
5735 files, see :hg:`forget`.
5734
5736
5735 .. container:: verbose
5737 .. container:: verbose
5736
5738
5737 -A/--after can be used to remove only files that have already
5739 -A/--after can be used to remove only files that have already
5738 been deleted, -f/--force can be used to force deletion, and -Af
5740 been deleted, -f/--force can be used to force deletion, and -Af
5739 can be used to remove files from the next revision without
5741 can be used to remove files from the next revision without
5740 deleting them from the working directory.
5742 deleting them from the working directory.
5741
5743
5742 The following table details the behavior of remove for different
5744 The following table details the behavior of remove for different
5743 file states (columns) and option combinations (rows). The file
5745 file states (columns) and option combinations (rows). The file
5744 states are Added [A], Clean [C], Modified [M] and Missing [!]
5746 states are Added [A], Clean [C], Modified [M] and Missing [!]
5745 (as reported by :hg:`status`). The actions are Warn, Remove
5747 (as reported by :hg:`status`). The actions are Warn, Remove
5746 (from branch) and Delete (from disk):
5748 (from branch) and Delete (from disk):
5747
5749
5748 ========= == == == ==
5750 ========= == == == ==
5749 opt/state A C M !
5751 opt/state A C M !
5750 ========= == == == ==
5752 ========= == == == ==
5751 none W RD W R
5753 none W RD W R
5752 -f R RD RD R
5754 -f R RD RD R
5753 -A W W W R
5755 -A W W W R
5754 -Af R R R R
5756 -Af R R R R
5755 ========= == == == ==
5757 ========= == == == ==
5756
5758
5757 Note that remove never deletes files in Added [A] state from the
5759 Note that remove never deletes files in Added [A] state from the
5758 working directory, not even if option --force is specified.
5760 working directory, not even if option --force is specified.
5759
5761
5760 Returns 0 on success, 1 if any warnings encountered.
5762 Returns 0 on success, 1 if any warnings encountered.
5761 """
5763 """
5762
5764
5763 after, force = opts.get('after'), opts.get('force')
5765 after, force = opts.get('after'), opts.get('force')
5764 if not pats and not after:
5766 if not pats and not after:
5765 raise error.Abort(_('no files specified'))
5767 raise error.Abort(_('no files specified'))
5766
5768
5767 m = scmutil.match(repo[None], pats, opts)
5769 m = scmutil.match(repo[None], pats, opts)
5768 subrepos = opts.get('subrepos')
5770 subrepos = opts.get('subrepos')
5769 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5771 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5770
5772
5771 @command('rename|move|mv',
5773 @command('rename|move|mv',
5772 [('A', 'after', None, _('record a rename that has already occurred')),
5774 [('A', 'after', None, _('record a rename that has already occurred')),
5773 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5775 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5774 ] + walkopts + dryrunopts,
5776 ] + walkopts + dryrunopts,
5775 _('[OPTION]... SOURCE... DEST'))
5777 _('[OPTION]... SOURCE... DEST'))
5776 def rename(ui, repo, *pats, **opts):
5778 def rename(ui, repo, *pats, **opts):
5777 """rename files; equivalent of copy + remove
5779 """rename files; equivalent of copy + remove
5778
5780
5779 Mark dest as copies of sources; mark sources for deletion. If dest
5781 Mark dest as copies of sources; mark sources for deletion. If dest
5780 is a directory, copies are put in that directory. If dest is a
5782 is a directory, copies are put in that directory. If dest is a
5781 file, there can only be one source.
5783 file, there can only be one source.
5782
5784
5783 By default, this command copies the contents of files as they
5785 By default, this command copies the contents of files as they
5784 exist in the working directory. If invoked with -A/--after, the
5786 exist in the working directory. If invoked with -A/--after, the
5785 operation is recorded, but no copying is performed.
5787 operation is recorded, but no copying is performed.
5786
5788
5787 This command takes effect at the next commit. To undo a rename
5789 This command takes effect at the next commit. To undo a rename
5788 before that, see :hg:`revert`.
5790 before that, see :hg:`revert`.
5789
5791
5790 Returns 0 on success, 1 if errors are encountered.
5792 Returns 0 on success, 1 if errors are encountered.
5791 """
5793 """
5792 wlock = repo.wlock(False)
5794 wlock = repo.wlock(False)
5793 try:
5795 try:
5794 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5796 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5795 finally:
5797 finally:
5796 wlock.release()
5798 wlock.release()
5797
5799
5798 @command('resolve',
5800 @command('resolve',
5799 [('a', 'all', None, _('select all unresolved files')),
5801 [('a', 'all', None, _('select all unresolved files')),
5800 ('l', 'list', None, _('list state of files needing merge')),
5802 ('l', 'list', None, _('list state of files needing merge')),
5801 ('m', 'mark', None, _('mark files as resolved')),
5803 ('m', 'mark', None, _('mark files as resolved')),
5802 ('u', 'unmark', None, _('mark files as unresolved')),
5804 ('u', 'unmark', None, _('mark files as unresolved')),
5803 ('n', 'no-status', None, _('hide status prefix'))]
5805 ('n', 'no-status', None, _('hide status prefix'))]
5804 + mergetoolopts + walkopts + formatteropts,
5806 + mergetoolopts + walkopts + formatteropts,
5805 _('[OPTION]... [FILE]...'),
5807 _('[OPTION]... [FILE]...'),
5806 inferrepo=True)
5808 inferrepo=True)
5807 def resolve(ui, repo, *pats, **opts):
5809 def resolve(ui, repo, *pats, **opts):
5808 """redo merges or set/view the merge status of files
5810 """redo merges or set/view the merge status of files
5809
5811
5810 Merges with unresolved conflicts are often the result of
5812 Merges with unresolved conflicts are often the result of
5811 non-interactive merging using the ``internal:merge`` configuration
5813 non-interactive merging using the ``internal:merge`` configuration
5812 setting, or a command-line merge tool like ``diff3``. The resolve
5814 setting, or a command-line merge tool like ``diff3``. The resolve
5813 command is used to manage the files involved in a merge, after
5815 command is used to manage the files involved in a merge, after
5814 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5816 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5815 working directory must have two parents). See :hg:`help
5817 working directory must have two parents). See :hg:`help
5816 merge-tools` for information on configuring merge tools.
5818 merge-tools` for information on configuring merge tools.
5817
5819
5818 The resolve command can be used in the following ways:
5820 The resolve command can be used in the following ways:
5819
5821
5820 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5822 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5821 files, discarding any previous merge attempts. Re-merging is not
5823 files, discarding any previous merge attempts. Re-merging is not
5822 performed for files already marked as resolved. Use ``--all/-a``
5824 performed for files already marked as resolved. Use ``--all/-a``
5823 to select all unresolved files. ``--tool`` can be used to specify
5825 to select all unresolved files. ``--tool`` can be used to specify
5824 the merge tool used for the given files. It overrides the HGMERGE
5826 the merge tool used for the given files. It overrides the HGMERGE
5825 environment variable and your configuration files. Previous file
5827 environment variable and your configuration files. Previous file
5826 contents are saved with a ``.orig`` suffix.
5828 contents are saved with a ``.orig`` suffix.
5827
5829
5828 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5830 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5829 (e.g. after having manually fixed-up the files). The default is
5831 (e.g. after having manually fixed-up the files). The default is
5830 to mark all unresolved files.
5832 to mark all unresolved files.
5831
5833
5832 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5834 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5833 default is to mark all resolved files.
5835 default is to mark all resolved files.
5834
5836
5835 - :hg:`resolve -l`: list files which had or still have conflicts.
5837 - :hg:`resolve -l`: list files which had or still have conflicts.
5836 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5838 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5837
5839
5838 Note that Mercurial will not let you commit files with unresolved
5840 Note that Mercurial will not let you commit files with unresolved
5839 merge conflicts. You must use :hg:`resolve -m ...` before you can
5841 merge conflicts. You must use :hg:`resolve -m ...` before you can
5840 commit after a conflicting merge.
5842 commit after a conflicting merge.
5841
5843
5842 Returns 0 on success, 1 if any files fail a resolve attempt.
5844 Returns 0 on success, 1 if any files fail a resolve attempt.
5843 """
5845 """
5844
5846
5845 all, mark, unmark, show, nostatus = \
5847 all, mark, unmark, show, nostatus = \
5846 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5848 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5847
5849
5848 if (show and (mark or unmark)) or (mark and unmark):
5850 if (show and (mark or unmark)) or (mark and unmark):
5849 raise error.Abort(_("too many options specified"))
5851 raise error.Abort(_("too many options specified"))
5850 if pats and all:
5852 if pats and all:
5851 raise error.Abort(_("can't specify --all and patterns"))
5853 raise error.Abort(_("can't specify --all and patterns"))
5852 if not (all or pats or show or mark or unmark):
5854 if not (all or pats or show or mark or unmark):
5853 raise error.Abort(_('no files or directories specified'),
5855 raise error.Abort(_('no files or directories specified'),
5854 hint=('use --all to re-merge all unresolved files'))
5856 hint=('use --all to re-merge all unresolved files'))
5855
5857
5856 if show:
5858 if show:
5857 fm = ui.formatter('resolve', opts)
5859 fm = ui.formatter('resolve', opts)
5858 ms = mergemod.mergestate.read(repo)
5860 ms = mergemod.mergestate.read(repo)
5859 m = scmutil.match(repo[None], pats, opts)
5861 m = scmutil.match(repo[None], pats, opts)
5860 for f in ms:
5862 for f in ms:
5861 if not m(f):
5863 if not m(f):
5862 continue
5864 continue
5863 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5865 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5864 'd': 'driverresolved'}[ms[f]]
5866 'd': 'driverresolved'}[ms[f]]
5865 fm.startitem()
5867 fm.startitem()
5866 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5868 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5867 fm.write('path', '%s\n', f, label=l)
5869 fm.write('path', '%s\n', f, label=l)
5868 fm.end()
5870 fm.end()
5869 return 0
5871 return 0
5870
5872
5871 wlock = repo.wlock()
5873 wlock = repo.wlock()
5872 try:
5874 try:
5873 ms = mergemod.mergestate.read(repo)
5875 ms = mergemod.mergestate.read(repo)
5874
5876
5875 if not (ms.active() or repo.dirstate.p2() != nullid):
5877 if not (ms.active() or repo.dirstate.p2() != nullid):
5876 raise error.Abort(
5878 raise error.Abort(
5877 _('resolve command not applicable when not merging'))
5879 _('resolve command not applicable when not merging'))
5878
5880
5879 wctx = repo[None]
5881 wctx = repo[None]
5880
5882
5881 if ms.mergedriver and ms.mdstate() == 'u':
5883 if ms.mergedriver and ms.mdstate() == 'u':
5882 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5884 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5883 ms.commit()
5885 ms.commit()
5884 # allow mark and unmark to go through
5886 # allow mark and unmark to go through
5885 if not mark and not unmark and not proceed:
5887 if not mark and not unmark and not proceed:
5886 return 1
5888 return 1
5887
5889
5888 m = scmutil.match(wctx, pats, opts)
5890 m = scmutil.match(wctx, pats, opts)
5889 ret = 0
5891 ret = 0
5890 didwork = False
5892 didwork = False
5891 runconclude = False
5893 runconclude = False
5892
5894
5893 tocomplete = []
5895 tocomplete = []
5894 for f in ms:
5896 for f in ms:
5895 if not m(f):
5897 if not m(f):
5896 continue
5898 continue
5897
5899
5898 didwork = True
5900 didwork = True
5899
5901
5900 # don't let driver-resolved files be marked, and run the conclude
5902 # don't let driver-resolved files be marked, and run the conclude
5901 # step if asked to resolve
5903 # step if asked to resolve
5902 if ms[f] == "d":
5904 if ms[f] == "d":
5903 exact = m.exact(f)
5905 exact = m.exact(f)
5904 if mark:
5906 if mark:
5905 if exact:
5907 if exact:
5906 ui.warn(_('not marking %s as it is driver-resolved\n')
5908 ui.warn(_('not marking %s as it is driver-resolved\n')
5907 % f)
5909 % f)
5908 elif unmark:
5910 elif unmark:
5909 if exact:
5911 if exact:
5910 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5912 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5911 % f)
5913 % f)
5912 else:
5914 else:
5913 runconclude = True
5915 runconclude = True
5914 continue
5916 continue
5915
5917
5916 if mark:
5918 if mark:
5917 ms.mark(f, "r")
5919 ms.mark(f, "r")
5918 elif unmark:
5920 elif unmark:
5919 ms.mark(f, "u")
5921 ms.mark(f, "u")
5920 else:
5922 else:
5921 # backup pre-resolve (merge uses .orig for its own purposes)
5923 # backup pre-resolve (merge uses .orig for its own purposes)
5922 a = repo.wjoin(f)
5924 a = repo.wjoin(f)
5923 try:
5925 try:
5924 util.copyfile(a, a + ".resolve")
5926 util.copyfile(a, a + ".resolve")
5925 except (IOError, OSError) as inst:
5927 except (IOError, OSError) as inst:
5926 if inst.errno != errno.ENOENT:
5928 if inst.errno != errno.ENOENT:
5927 raise
5929 raise
5928
5930
5929 try:
5931 try:
5930 # preresolve file
5932 # preresolve file
5931 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5933 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5932 'resolve')
5934 'resolve')
5933 complete, r = ms.preresolve(f, wctx)
5935 complete, r = ms.preresolve(f, wctx)
5934 if not complete:
5936 if not complete:
5935 tocomplete.append(f)
5937 tocomplete.append(f)
5936 elif r:
5938 elif r:
5937 ret = 1
5939 ret = 1
5938 finally:
5940 finally:
5939 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5941 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5940 ms.commit()
5942 ms.commit()
5941
5943
5942 # replace filemerge's .orig file with our resolve file, but only
5944 # replace filemerge's .orig file with our resolve file, but only
5943 # for merges that are complete
5945 # for merges that are complete
5944 if complete:
5946 if complete:
5945 try:
5947 try:
5946 util.rename(a + ".resolve",
5948 util.rename(a + ".resolve",
5947 cmdutil.origpath(ui, repo, a))
5949 cmdutil.origpath(ui, repo, a))
5948 except OSError as inst:
5950 except OSError as inst:
5949 if inst.errno != errno.ENOENT:
5951 if inst.errno != errno.ENOENT:
5950 raise
5952 raise
5951
5953
5952 for f in tocomplete:
5954 for f in tocomplete:
5953 try:
5955 try:
5954 # resolve file
5956 # resolve file
5955 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5957 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5956 'resolve')
5958 'resolve')
5957 r = ms.resolve(f, wctx)
5959 r = ms.resolve(f, wctx)
5958 if r:
5960 if r:
5959 ret = 1
5961 ret = 1
5960 finally:
5962 finally:
5961 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5963 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5962 ms.commit()
5964 ms.commit()
5963
5965
5964 # replace filemerge's .orig file with our resolve file
5966 # replace filemerge's .orig file with our resolve file
5965 a = repo.wjoin(f)
5967 a = repo.wjoin(f)
5966 try:
5968 try:
5967 util.rename(a + ".resolve", cmdutil.origpath(ui, repo, a))
5969 util.rename(a + ".resolve", cmdutil.origpath(ui, repo, a))
5968 except OSError as inst:
5970 except OSError as inst:
5969 if inst.errno != errno.ENOENT:
5971 if inst.errno != errno.ENOENT:
5970 raise
5972 raise
5971
5973
5972 ms.commit()
5974 ms.commit()
5973 ms.recordactions()
5975 ms.recordactions()
5974
5976
5975 if not didwork and pats:
5977 if not didwork and pats:
5976 ui.warn(_("arguments do not match paths that need resolving\n"))
5978 ui.warn(_("arguments do not match paths that need resolving\n"))
5977 elif ms.mergedriver and ms.mdstate() != 's':
5979 elif ms.mergedriver and ms.mdstate() != 's':
5978 # run conclude step when either a driver-resolved file is requested
5980 # run conclude step when either a driver-resolved file is requested
5979 # or there are no driver-resolved files
5981 # or there are no driver-resolved files
5980 # we can't use 'ret' to determine whether any files are unresolved
5982 # we can't use 'ret' to determine whether any files are unresolved
5981 # because we might not have tried to resolve some
5983 # because we might not have tried to resolve some
5982 if ((runconclude or not list(ms.driverresolved()))
5984 if ((runconclude or not list(ms.driverresolved()))
5983 and not list(ms.unresolved())):
5985 and not list(ms.unresolved())):
5984 proceed = mergemod.driverconclude(repo, ms, wctx)
5986 proceed = mergemod.driverconclude(repo, ms, wctx)
5985 ms.commit()
5987 ms.commit()
5986 if not proceed:
5988 if not proceed:
5987 return 1
5989 return 1
5988
5990
5989 finally:
5991 finally:
5990 wlock.release()
5992 wlock.release()
5991
5993
5992 # Nudge users into finishing an unfinished operation
5994 # Nudge users into finishing an unfinished operation
5993 unresolvedf = list(ms.unresolved())
5995 unresolvedf = list(ms.unresolved())
5994 driverresolvedf = list(ms.driverresolved())
5996 driverresolvedf = list(ms.driverresolved())
5995 if not unresolvedf and not driverresolvedf:
5997 if not unresolvedf and not driverresolvedf:
5996 ui.status(_('(no more unresolved files)\n'))
5998 ui.status(_('(no more unresolved files)\n'))
5997 elif not unresolvedf:
5999 elif not unresolvedf:
5998 ui.status(_('(no more unresolved files -- '
6000 ui.status(_('(no more unresolved files -- '
5999 'run "hg resolve --all" to conclude)\n'))
6001 'run "hg resolve --all" to conclude)\n'))
6000
6002
6001 return ret
6003 return ret
6002
6004
6003 @command('revert',
6005 @command('revert',
6004 [('a', 'all', None, _('revert all changes when no arguments given')),
6006 [('a', 'all', None, _('revert all changes when no arguments given')),
6005 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6007 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6006 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6008 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6007 ('C', 'no-backup', None, _('do not save backup copies of files')),
6009 ('C', 'no-backup', None, _('do not save backup copies of files')),
6008 ('i', 'interactive', None,
6010 ('i', 'interactive', None,
6009 _('interactively select the changes (EXPERIMENTAL)')),
6011 _('interactively select the changes (EXPERIMENTAL)')),
6010 ] + walkopts + dryrunopts,
6012 ] + walkopts + dryrunopts,
6011 _('[OPTION]... [-r REV] [NAME]...'))
6013 _('[OPTION]... [-r REV] [NAME]...'))
6012 def revert(ui, repo, *pats, **opts):
6014 def revert(ui, repo, *pats, **opts):
6013 """restore files to their checkout state
6015 """restore files to their checkout state
6014
6016
6015 .. note::
6017 .. note::
6016
6018
6017 To check out earlier revisions, you should use :hg:`update REV`.
6019 To check out earlier revisions, you should use :hg:`update REV`.
6018 To cancel an uncommitted merge (and lose your changes),
6020 To cancel an uncommitted merge (and lose your changes),
6019 use :hg:`update --clean .`.
6021 use :hg:`update --clean .`.
6020
6022
6021 With no revision specified, revert the specified files or directories
6023 With no revision specified, revert the specified files or directories
6022 to the contents they had in the parent of the working directory.
6024 to the contents they had in the parent of the working directory.
6023 This restores the contents of files to an unmodified
6025 This restores the contents of files to an unmodified
6024 state and unschedules adds, removes, copies, and renames. If the
6026 state and unschedules adds, removes, copies, and renames. If the
6025 working directory has two parents, you must explicitly specify a
6027 working directory has two parents, you must explicitly specify a
6026 revision.
6028 revision.
6027
6029
6028 Using the -r/--rev or -d/--date options, revert the given files or
6030 Using the -r/--rev or -d/--date options, revert the given files or
6029 directories to their states as of a specific revision. Because
6031 directories to their states as of a specific revision. Because
6030 revert does not change the working directory parents, this will
6032 revert does not change the working directory parents, this will
6031 cause these files to appear modified. This can be helpful to "back
6033 cause these files to appear modified. This can be helpful to "back
6032 out" some or all of an earlier change. See :hg:`backout` for a
6034 out" some or all of an earlier change. See :hg:`backout` for a
6033 related method.
6035 related method.
6034
6036
6035 Modified files are saved with a .orig suffix before reverting.
6037 Modified files are saved with a .orig suffix before reverting.
6036 To disable these backups, use --no-backup.
6038 To disable these backups, use --no-backup.
6037
6039
6038 See :hg:`help dates` for a list of formats valid for -d/--date.
6040 See :hg:`help dates` for a list of formats valid for -d/--date.
6039
6041
6040 See :hg:`help backout` for a way to reverse the effect of an
6042 See :hg:`help backout` for a way to reverse the effect of an
6041 earlier changeset.
6043 earlier changeset.
6042
6044
6043 Returns 0 on success.
6045 Returns 0 on success.
6044 """
6046 """
6045
6047
6046 if opts.get("date"):
6048 if opts.get("date"):
6047 if opts.get("rev"):
6049 if opts.get("rev"):
6048 raise error.Abort(_("you can't specify a revision and a date"))
6050 raise error.Abort(_("you can't specify a revision and a date"))
6049 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6051 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6050
6052
6051 parent, p2 = repo.dirstate.parents()
6053 parent, p2 = repo.dirstate.parents()
6052 if not opts.get('rev') and p2 != nullid:
6054 if not opts.get('rev') and p2 != nullid:
6053 # revert after merge is a trap for new users (issue2915)
6055 # revert after merge is a trap for new users (issue2915)
6054 raise error.Abort(_('uncommitted merge with no revision specified'),
6056 raise error.Abort(_('uncommitted merge with no revision specified'),
6055 hint=_('use "hg update" or see "hg help revert"'))
6057 hint=_('use "hg update" or see "hg help revert"'))
6056
6058
6057 ctx = scmutil.revsingle(repo, opts.get('rev'))
6059 ctx = scmutil.revsingle(repo, opts.get('rev'))
6058
6060
6059 if (not (pats or opts.get('include') or opts.get('exclude') or
6061 if (not (pats or opts.get('include') or opts.get('exclude') or
6060 opts.get('all') or opts.get('interactive'))):
6062 opts.get('all') or opts.get('interactive'))):
6061 msg = _("no files or directories specified")
6063 msg = _("no files or directories specified")
6062 if p2 != nullid:
6064 if p2 != nullid:
6063 hint = _("uncommitted merge, use --all to discard all changes,"
6065 hint = _("uncommitted merge, use --all to discard all changes,"
6064 " or 'hg update -C .' to abort the merge")
6066 " or 'hg update -C .' to abort the merge")
6065 raise error.Abort(msg, hint=hint)
6067 raise error.Abort(msg, hint=hint)
6066 dirty = any(repo.status())
6068 dirty = any(repo.status())
6067 node = ctx.node()
6069 node = ctx.node()
6068 if node != parent:
6070 if node != parent:
6069 if dirty:
6071 if dirty:
6070 hint = _("uncommitted changes, use --all to discard all"
6072 hint = _("uncommitted changes, use --all to discard all"
6071 " changes, or 'hg update %s' to update") % ctx.rev()
6073 " changes, or 'hg update %s' to update") % ctx.rev()
6072 else:
6074 else:
6073 hint = _("use --all to revert all files,"
6075 hint = _("use --all to revert all files,"
6074 " or 'hg update %s' to update") % ctx.rev()
6076 " or 'hg update %s' to update") % ctx.rev()
6075 elif dirty:
6077 elif dirty:
6076 hint = _("uncommitted changes, use --all to discard all changes")
6078 hint = _("uncommitted changes, use --all to discard all changes")
6077 else:
6079 else:
6078 hint = _("use --all to revert all files")
6080 hint = _("use --all to revert all files")
6079 raise error.Abort(msg, hint=hint)
6081 raise error.Abort(msg, hint=hint)
6080
6082
6081 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6083 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6082
6084
6083 @command('rollback', dryrunopts +
6085 @command('rollback', dryrunopts +
6084 [('f', 'force', False, _('ignore safety measures'))])
6086 [('f', 'force', False, _('ignore safety measures'))])
6085 def rollback(ui, repo, **opts):
6087 def rollback(ui, repo, **opts):
6086 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6088 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6087
6089
6088 Please use :hg:`commit --amend` instead of rollback to correct
6090 Please use :hg:`commit --amend` instead of rollback to correct
6089 mistakes in the last commit.
6091 mistakes in the last commit.
6090
6092
6091 This command should be used with care. There is only one level of
6093 This command should be used with care. There is only one level of
6092 rollback, and there is no way to undo a rollback. It will also
6094 rollback, and there is no way to undo a rollback. It will also
6093 restore the dirstate at the time of the last transaction, losing
6095 restore the dirstate at the time of the last transaction, losing
6094 any dirstate changes since that time. This command does not alter
6096 any dirstate changes since that time. This command does not alter
6095 the working directory.
6097 the working directory.
6096
6098
6097 Transactions are used to encapsulate the effects of all commands
6099 Transactions are used to encapsulate the effects of all commands
6098 that create new changesets or propagate existing changesets into a
6100 that create new changesets or propagate existing changesets into a
6099 repository.
6101 repository.
6100
6102
6101 .. container:: verbose
6103 .. container:: verbose
6102
6104
6103 For example, the following commands are transactional, and their
6105 For example, the following commands are transactional, and their
6104 effects can be rolled back:
6106 effects can be rolled back:
6105
6107
6106 - commit
6108 - commit
6107 - import
6109 - import
6108 - pull
6110 - pull
6109 - push (with this repository as the destination)
6111 - push (with this repository as the destination)
6110 - unbundle
6112 - unbundle
6111
6113
6112 To avoid permanent data loss, rollback will refuse to rollback a
6114 To avoid permanent data loss, rollback will refuse to rollback a
6113 commit transaction if it isn't checked out. Use --force to
6115 commit transaction if it isn't checked out. Use --force to
6114 override this protection.
6116 override this protection.
6115
6117
6116 This command is not intended for use on public repositories. Once
6118 This command is not intended for use on public repositories. Once
6117 changes are visible for pull by other users, rolling a transaction
6119 changes are visible for pull by other users, rolling a transaction
6118 back locally is ineffective (someone else may already have pulled
6120 back locally is ineffective (someone else may already have pulled
6119 the changes). Furthermore, a race is possible with readers of the
6121 the changes). Furthermore, a race is possible with readers of the
6120 repository; for example an in-progress pull from the repository
6122 repository; for example an in-progress pull from the repository
6121 may fail if a rollback is performed.
6123 may fail if a rollback is performed.
6122
6124
6123 Returns 0 on success, 1 if no rollback data is available.
6125 Returns 0 on success, 1 if no rollback data is available.
6124 """
6126 """
6125 return repo.rollback(dryrun=opts.get('dry_run'),
6127 return repo.rollback(dryrun=opts.get('dry_run'),
6126 force=opts.get('force'))
6128 force=opts.get('force'))
6127
6129
6128 @command('root', [])
6130 @command('root', [])
6129 def root(ui, repo):
6131 def root(ui, repo):
6130 """print the root (top) of the current working directory
6132 """print the root (top) of the current working directory
6131
6133
6132 Print the root directory of the current repository.
6134 Print the root directory of the current repository.
6133
6135
6134 Returns 0 on success.
6136 Returns 0 on success.
6135 """
6137 """
6136 ui.write(repo.root + "\n")
6138 ui.write(repo.root + "\n")
6137
6139
6138 @command('^serve',
6140 @command('^serve',
6139 [('A', 'accesslog', '', _('name of access log file to write to'),
6141 [('A', 'accesslog', '', _('name of access log file to write to'),
6140 _('FILE')),
6142 _('FILE')),
6141 ('d', 'daemon', None, _('run server in background')),
6143 ('d', 'daemon', None, _('run server in background')),
6142 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6144 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6143 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6145 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6144 # use string type, then we can check if something was passed
6146 # use string type, then we can check if something was passed
6145 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6147 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6146 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6148 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6147 _('ADDR')),
6149 _('ADDR')),
6148 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6150 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6149 _('PREFIX')),
6151 _('PREFIX')),
6150 ('n', 'name', '',
6152 ('n', 'name', '',
6151 _('name to show in web pages (default: working directory)'), _('NAME')),
6153 _('name to show in web pages (default: working directory)'), _('NAME')),
6152 ('', 'web-conf', '',
6154 ('', 'web-conf', '',
6153 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6155 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6154 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6156 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6155 _('FILE')),
6157 _('FILE')),
6156 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6158 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6157 ('', 'stdio', None, _('for remote clients')),
6159 ('', 'stdio', None, _('for remote clients')),
6158 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6160 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6159 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6161 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6160 ('', 'style', '', _('template style to use'), _('STYLE')),
6162 ('', 'style', '', _('template style to use'), _('STYLE')),
6161 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6163 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6162 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6164 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6163 _('[OPTION]...'),
6165 _('[OPTION]...'),
6164 optionalrepo=True)
6166 optionalrepo=True)
6165 def serve(ui, repo, **opts):
6167 def serve(ui, repo, **opts):
6166 """start stand-alone webserver
6168 """start stand-alone webserver
6167
6169
6168 Start a local HTTP repository browser and pull server. You can use
6170 Start a local HTTP repository browser and pull server. You can use
6169 this for ad-hoc sharing and browsing of repositories. It is
6171 this for ad-hoc sharing and browsing of repositories. It is
6170 recommended to use a real web server to serve a repository for
6172 recommended to use a real web server to serve a repository for
6171 longer periods of time.
6173 longer periods of time.
6172
6174
6173 Please note that the server does not implement access control.
6175 Please note that the server does not implement access control.
6174 This means that, by default, anybody can read from the server and
6176 This means that, by default, anybody can read from the server and
6175 nobody can write to it by default. Set the ``web.allow_push``
6177 nobody can write to it by default. Set the ``web.allow_push``
6176 option to ``*`` to allow everybody to push to the server. You
6178 option to ``*`` to allow everybody to push to the server. You
6177 should use a real web server if you need to authenticate users.
6179 should use a real web server if you need to authenticate users.
6178
6180
6179 By default, the server logs accesses to stdout and errors to
6181 By default, the server logs accesses to stdout and errors to
6180 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6182 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6181 files.
6183 files.
6182
6184
6183 To have the server choose a free port number to listen on, specify
6185 To have the server choose a free port number to listen on, specify
6184 a port number of 0; in this case, the server will print the port
6186 a port number of 0; in this case, the server will print the port
6185 number it uses.
6187 number it uses.
6186
6188
6187 Returns 0 on success.
6189 Returns 0 on success.
6188 """
6190 """
6189
6191
6190 if opts["stdio"] and opts["cmdserver"]:
6192 if opts["stdio"] and opts["cmdserver"]:
6191 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6193 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6192
6194
6193 if opts["stdio"]:
6195 if opts["stdio"]:
6194 if repo is None:
6196 if repo is None:
6195 raise error.RepoError(_("there is no Mercurial repository here"
6197 raise error.RepoError(_("there is no Mercurial repository here"
6196 " (.hg not found)"))
6198 " (.hg not found)"))
6197 s = sshserver.sshserver(ui, repo)
6199 s = sshserver.sshserver(ui, repo)
6198 s.serve_forever()
6200 s.serve_forever()
6199
6201
6200 if opts["cmdserver"]:
6202 if opts["cmdserver"]:
6201 service = commandserver.createservice(ui, repo, opts)
6203 service = commandserver.createservice(ui, repo, opts)
6202 else:
6204 else:
6203 service = hgweb.createservice(ui, repo, opts)
6205 service = hgweb.createservice(ui, repo, opts)
6204 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6206 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6205
6207
6206 @command('^status|st',
6208 @command('^status|st',
6207 [('A', 'all', None, _('show status of all files')),
6209 [('A', 'all', None, _('show status of all files')),
6208 ('m', 'modified', None, _('show only modified files')),
6210 ('m', 'modified', None, _('show only modified files')),
6209 ('a', 'added', None, _('show only added files')),
6211 ('a', 'added', None, _('show only added files')),
6210 ('r', 'removed', None, _('show only removed files')),
6212 ('r', 'removed', None, _('show only removed files')),
6211 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6213 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6212 ('c', 'clean', None, _('show only files without changes')),
6214 ('c', 'clean', None, _('show only files without changes')),
6213 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6215 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6214 ('i', 'ignored', None, _('show only ignored files')),
6216 ('i', 'ignored', None, _('show only ignored files')),
6215 ('n', 'no-status', None, _('hide status prefix')),
6217 ('n', 'no-status', None, _('hide status prefix')),
6216 ('C', 'copies', None, _('show source of copied files')),
6218 ('C', 'copies', None, _('show source of copied files')),
6217 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6219 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6218 ('', 'rev', [], _('show difference from revision'), _('REV')),
6220 ('', 'rev', [], _('show difference from revision'), _('REV')),
6219 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6221 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6220 ] + walkopts + subrepoopts + formatteropts,
6222 ] + walkopts + subrepoopts + formatteropts,
6221 _('[OPTION]... [FILE]...'),
6223 _('[OPTION]... [FILE]...'),
6222 inferrepo=True)
6224 inferrepo=True)
6223 def status(ui, repo, *pats, **opts):
6225 def status(ui, repo, *pats, **opts):
6224 """show changed files in the working directory
6226 """show changed files in the working directory
6225
6227
6226 Show status of files in the repository. If names are given, only
6228 Show status of files in the repository. If names are given, only
6227 files that match are shown. Files that are clean or ignored or
6229 files that match are shown. Files that are clean or ignored or
6228 the source of a copy/move operation, are not listed unless
6230 the source of a copy/move operation, are not listed unless
6229 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6231 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6230 Unless options described with "show only ..." are given, the
6232 Unless options described with "show only ..." are given, the
6231 options -mardu are used.
6233 options -mardu are used.
6232
6234
6233 Option -q/--quiet hides untracked (unknown and ignored) files
6235 Option -q/--quiet hides untracked (unknown and ignored) files
6234 unless explicitly requested with -u/--unknown or -i/--ignored.
6236 unless explicitly requested with -u/--unknown or -i/--ignored.
6235
6237
6236 .. note::
6238 .. note::
6237
6239
6238 status may appear to disagree with diff if permissions have
6240 status may appear to disagree with diff if permissions have
6239 changed or a merge has occurred. The standard diff format does
6241 changed or a merge has occurred. The standard diff format does
6240 not report permission changes and diff only reports changes
6242 not report permission changes and diff only reports changes
6241 relative to one merge parent.
6243 relative to one merge parent.
6242
6244
6243 If one revision is given, it is used as the base revision.
6245 If one revision is given, it is used as the base revision.
6244 If two revisions are given, the differences between them are
6246 If two revisions are given, the differences between them are
6245 shown. The --change option can also be used as a shortcut to list
6247 shown. The --change option can also be used as a shortcut to list
6246 the changed files of a revision from its first parent.
6248 the changed files of a revision from its first parent.
6247
6249
6248 The codes used to show the status of files are::
6250 The codes used to show the status of files are::
6249
6251
6250 M = modified
6252 M = modified
6251 A = added
6253 A = added
6252 R = removed
6254 R = removed
6253 C = clean
6255 C = clean
6254 ! = missing (deleted by non-hg command, but still tracked)
6256 ! = missing (deleted by non-hg command, but still tracked)
6255 ? = not tracked
6257 ? = not tracked
6256 I = ignored
6258 I = ignored
6257 = origin of the previous file (with --copies)
6259 = origin of the previous file (with --copies)
6258
6260
6259 .. container:: verbose
6261 .. container:: verbose
6260
6262
6261 Examples:
6263 Examples:
6262
6264
6263 - show changes in the working directory relative to a
6265 - show changes in the working directory relative to a
6264 changeset::
6266 changeset::
6265
6267
6266 hg status --rev 9353
6268 hg status --rev 9353
6267
6269
6268 - show changes in the working directory relative to the
6270 - show changes in the working directory relative to the
6269 current directory (see :hg:`help patterns` for more information)::
6271 current directory (see :hg:`help patterns` for more information)::
6270
6272
6271 hg status re:
6273 hg status re:
6272
6274
6273 - show all changes including copies in an existing changeset::
6275 - show all changes including copies in an existing changeset::
6274
6276
6275 hg status --copies --change 9353
6277 hg status --copies --change 9353
6276
6278
6277 - get a NUL separated list of added files, suitable for xargs::
6279 - get a NUL separated list of added files, suitable for xargs::
6278
6280
6279 hg status -an0
6281 hg status -an0
6280
6282
6281 Returns 0 on success.
6283 Returns 0 on success.
6282 """
6284 """
6283
6285
6284 revs = opts.get('rev')
6286 revs = opts.get('rev')
6285 change = opts.get('change')
6287 change = opts.get('change')
6286
6288
6287 if revs and change:
6289 if revs and change:
6288 msg = _('cannot specify --rev and --change at the same time')
6290 msg = _('cannot specify --rev and --change at the same time')
6289 raise error.Abort(msg)
6291 raise error.Abort(msg)
6290 elif change:
6292 elif change:
6291 node2 = scmutil.revsingle(repo, change, None).node()
6293 node2 = scmutil.revsingle(repo, change, None).node()
6292 node1 = repo[node2].p1().node()
6294 node1 = repo[node2].p1().node()
6293 else:
6295 else:
6294 node1, node2 = scmutil.revpair(repo, revs)
6296 node1, node2 = scmutil.revpair(repo, revs)
6295
6297
6296 if pats:
6298 if pats:
6297 cwd = repo.getcwd()
6299 cwd = repo.getcwd()
6298 else:
6300 else:
6299 cwd = ''
6301 cwd = ''
6300
6302
6301 if opts.get('print0'):
6303 if opts.get('print0'):
6302 end = '\0'
6304 end = '\0'
6303 else:
6305 else:
6304 end = '\n'
6306 end = '\n'
6305 copy = {}
6307 copy = {}
6306 states = 'modified added removed deleted unknown ignored clean'.split()
6308 states = 'modified added removed deleted unknown ignored clean'.split()
6307 show = [k for k in states if opts.get(k)]
6309 show = [k for k in states if opts.get(k)]
6308 if opts.get('all'):
6310 if opts.get('all'):
6309 show += ui.quiet and (states[:4] + ['clean']) or states
6311 show += ui.quiet and (states[:4] + ['clean']) or states
6310 if not show:
6312 if not show:
6311 if ui.quiet:
6313 if ui.quiet:
6312 show = states[:4]
6314 show = states[:4]
6313 else:
6315 else:
6314 show = states[:5]
6316 show = states[:5]
6315
6317
6316 m = scmutil.match(repo[node2], pats, opts)
6318 m = scmutil.match(repo[node2], pats, opts)
6317 stat = repo.status(node1, node2, m,
6319 stat = repo.status(node1, node2, m,
6318 'ignored' in show, 'clean' in show, 'unknown' in show,
6320 'ignored' in show, 'clean' in show, 'unknown' in show,
6319 opts.get('subrepos'))
6321 opts.get('subrepos'))
6320 changestates = zip(states, 'MAR!?IC', stat)
6322 changestates = zip(states, 'MAR!?IC', stat)
6321
6323
6322 if (opts.get('all') or opts.get('copies')
6324 if (opts.get('all') or opts.get('copies')
6323 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6325 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6324 copy = copies.pathcopies(repo[node1], repo[node2], m)
6326 copy = copies.pathcopies(repo[node1], repo[node2], m)
6325
6327
6326 fm = ui.formatter('status', opts)
6328 fm = ui.formatter('status', opts)
6327 fmt = '%s' + end
6329 fmt = '%s' + end
6328 showchar = not opts.get('no_status')
6330 showchar = not opts.get('no_status')
6329
6331
6330 for state, char, files in changestates:
6332 for state, char, files in changestates:
6331 if state in show:
6333 if state in show:
6332 label = 'status.' + state
6334 label = 'status.' + state
6333 for f in files:
6335 for f in files:
6334 fm.startitem()
6336 fm.startitem()
6335 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6337 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6336 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6338 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6337 if f in copy:
6339 if f in copy:
6338 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6340 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6339 label='status.copied')
6341 label='status.copied')
6340 fm.end()
6342 fm.end()
6341
6343
6342 @command('^summary|sum',
6344 @command('^summary|sum',
6343 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6345 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6344 def summary(ui, repo, **opts):
6346 def summary(ui, repo, **opts):
6345 """summarize working directory state
6347 """summarize working directory state
6346
6348
6347 This generates a brief summary of the working directory state,
6349 This generates a brief summary of the working directory state,
6348 including parents, branch, commit status, phase and available updates.
6350 including parents, branch, commit status, phase and available updates.
6349
6351
6350 With the --remote option, this will check the default paths for
6352 With the --remote option, this will check the default paths for
6351 incoming and outgoing changes. This can be time-consuming.
6353 incoming and outgoing changes. This can be time-consuming.
6352
6354
6353 Returns 0 on success.
6355 Returns 0 on success.
6354 """
6356 """
6355
6357
6356 ctx = repo[None]
6358 ctx = repo[None]
6357 parents = ctx.parents()
6359 parents = ctx.parents()
6358 pnode = parents[0].node()
6360 pnode = parents[0].node()
6359 marks = []
6361 marks = []
6360
6362
6361 for p in parents:
6363 for p in parents:
6362 # label with log.changeset (instead of log.parent) since this
6364 # label with log.changeset (instead of log.parent) since this
6363 # shows a working directory parent *changeset*:
6365 # shows a working directory parent *changeset*:
6364 # i18n: column positioning for "hg summary"
6366 # i18n: column positioning for "hg summary"
6365 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6367 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6366 label='log.changeset changeset.%s' % p.phasestr())
6368 label='log.changeset changeset.%s' % p.phasestr())
6367 ui.write(' '.join(p.tags()), label='log.tag')
6369 ui.write(' '.join(p.tags()), label='log.tag')
6368 if p.bookmarks():
6370 if p.bookmarks():
6369 marks.extend(p.bookmarks())
6371 marks.extend(p.bookmarks())
6370 if p.rev() == -1:
6372 if p.rev() == -1:
6371 if not len(repo):
6373 if not len(repo):
6372 ui.write(_(' (empty repository)'))
6374 ui.write(_(' (empty repository)'))
6373 else:
6375 else:
6374 ui.write(_(' (no revision checked out)'))
6376 ui.write(_(' (no revision checked out)'))
6375 ui.write('\n')
6377 ui.write('\n')
6376 if p.description():
6378 if p.description():
6377 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6379 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6378 label='log.summary')
6380 label='log.summary')
6379
6381
6380 branch = ctx.branch()
6382 branch = ctx.branch()
6381 bheads = repo.branchheads(branch)
6383 bheads = repo.branchheads(branch)
6382 # i18n: column positioning for "hg summary"
6384 # i18n: column positioning for "hg summary"
6383 m = _('branch: %s\n') % branch
6385 m = _('branch: %s\n') % branch
6384 if branch != 'default':
6386 if branch != 'default':
6385 ui.write(m, label='log.branch')
6387 ui.write(m, label='log.branch')
6386 else:
6388 else:
6387 ui.status(m, label='log.branch')
6389 ui.status(m, label='log.branch')
6388
6390
6389 if marks:
6391 if marks:
6390 active = repo._activebookmark
6392 active = repo._activebookmark
6391 # i18n: column positioning for "hg summary"
6393 # i18n: column positioning for "hg summary"
6392 ui.write(_('bookmarks:'), label='log.bookmark')
6394 ui.write(_('bookmarks:'), label='log.bookmark')
6393 if active is not None:
6395 if active is not None:
6394 if active in marks:
6396 if active in marks:
6395 ui.write(' *' + active, label=activebookmarklabel)
6397 ui.write(' *' + active, label=activebookmarklabel)
6396 marks.remove(active)
6398 marks.remove(active)
6397 else:
6399 else:
6398 ui.write(' [%s]' % active, label=activebookmarklabel)
6400 ui.write(' [%s]' % active, label=activebookmarklabel)
6399 for m in marks:
6401 for m in marks:
6400 ui.write(' ' + m, label='log.bookmark')
6402 ui.write(' ' + m, label='log.bookmark')
6401 ui.write('\n', label='log.bookmark')
6403 ui.write('\n', label='log.bookmark')
6402
6404
6403 status = repo.status(unknown=True)
6405 status = repo.status(unknown=True)
6404
6406
6405 c = repo.dirstate.copies()
6407 c = repo.dirstate.copies()
6406 copied, renamed = [], []
6408 copied, renamed = [], []
6407 for d, s in c.iteritems():
6409 for d, s in c.iteritems():
6408 if s in status.removed:
6410 if s in status.removed:
6409 status.removed.remove(s)
6411 status.removed.remove(s)
6410 renamed.append(d)
6412 renamed.append(d)
6411 else:
6413 else:
6412 copied.append(d)
6414 copied.append(d)
6413 if d in status.added:
6415 if d in status.added:
6414 status.added.remove(d)
6416 status.added.remove(d)
6415
6417
6416 try:
6418 try:
6417 ms = mergemod.mergestate.read(repo)
6419 ms = mergemod.mergestate.read(repo)
6418 except error.UnsupportedMergeRecords as e:
6420 except error.UnsupportedMergeRecords as e:
6419 s = ' '.join(e.recordtypes)
6421 s = ' '.join(e.recordtypes)
6420 ui.warn(
6422 ui.warn(
6421 _('warning: merge state has unsupported record types: %s\n') % s)
6423 _('warning: merge state has unsupported record types: %s\n') % s)
6422 unresolved = 0
6424 unresolved = 0
6423 else:
6425 else:
6424 unresolved = [f for f in ms if ms[f] == 'u']
6426 unresolved = [f for f in ms if ms[f] == 'u']
6425
6427
6426 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6428 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6427
6429
6428 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6430 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6429 (ui.label(_('%d added'), 'status.added'), status.added),
6431 (ui.label(_('%d added'), 'status.added'), status.added),
6430 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6432 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6431 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6433 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6432 (ui.label(_('%d copied'), 'status.copied'), copied),
6434 (ui.label(_('%d copied'), 'status.copied'), copied),
6433 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6435 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6434 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6436 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6435 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6437 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6436 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6438 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6437 t = []
6439 t = []
6438 for l, s in labels:
6440 for l, s in labels:
6439 if s:
6441 if s:
6440 t.append(l % len(s))
6442 t.append(l % len(s))
6441
6443
6442 t = ', '.join(t)
6444 t = ', '.join(t)
6443 cleanworkdir = False
6445 cleanworkdir = False
6444
6446
6445 if repo.vfs.exists('graftstate'):
6447 if repo.vfs.exists('graftstate'):
6446 t += _(' (graft in progress)')
6448 t += _(' (graft in progress)')
6447 if repo.vfs.exists('updatestate'):
6449 if repo.vfs.exists('updatestate'):
6448 t += _(' (interrupted update)')
6450 t += _(' (interrupted update)')
6449 elif len(parents) > 1:
6451 elif len(parents) > 1:
6450 t += _(' (merge)')
6452 t += _(' (merge)')
6451 elif branch != parents[0].branch():
6453 elif branch != parents[0].branch():
6452 t += _(' (new branch)')
6454 t += _(' (new branch)')
6453 elif (parents[0].closesbranch() and
6455 elif (parents[0].closesbranch() and
6454 pnode in repo.branchheads(branch, closed=True)):
6456 pnode in repo.branchheads(branch, closed=True)):
6455 t += _(' (head closed)')
6457 t += _(' (head closed)')
6456 elif not (status.modified or status.added or status.removed or renamed or
6458 elif not (status.modified or status.added or status.removed or renamed or
6457 copied or subs):
6459 copied or subs):
6458 t += _(' (clean)')
6460 t += _(' (clean)')
6459 cleanworkdir = True
6461 cleanworkdir = True
6460 elif pnode not in bheads:
6462 elif pnode not in bheads:
6461 t += _(' (new branch head)')
6463 t += _(' (new branch head)')
6462
6464
6463 if parents:
6465 if parents:
6464 pendingphase = max(p.phase() for p in parents)
6466 pendingphase = max(p.phase() for p in parents)
6465 else:
6467 else:
6466 pendingphase = phases.public
6468 pendingphase = phases.public
6467
6469
6468 if pendingphase > phases.newcommitphase(ui):
6470 if pendingphase > phases.newcommitphase(ui):
6469 t += ' (%s)' % phases.phasenames[pendingphase]
6471 t += ' (%s)' % phases.phasenames[pendingphase]
6470
6472
6471 if cleanworkdir:
6473 if cleanworkdir:
6472 # i18n: column positioning for "hg summary"
6474 # i18n: column positioning for "hg summary"
6473 ui.status(_('commit: %s\n') % t.strip())
6475 ui.status(_('commit: %s\n') % t.strip())
6474 else:
6476 else:
6475 # i18n: column positioning for "hg summary"
6477 # i18n: column positioning for "hg summary"
6476 ui.write(_('commit: %s\n') % t.strip())
6478 ui.write(_('commit: %s\n') % t.strip())
6477
6479
6478 # all ancestors of branch heads - all ancestors of parent = new csets
6480 # all ancestors of branch heads - all ancestors of parent = new csets
6479 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6481 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6480 bheads))
6482 bheads))
6481
6483
6482 if new == 0:
6484 if new == 0:
6483 # i18n: column positioning for "hg summary"
6485 # i18n: column positioning for "hg summary"
6484 ui.status(_('update: (current)\n'))
6486 ui.status(_('update: (current)\n'))
6485 elif pnode not in bheads:
6487 elif pnode not in bheads:
6486 # i18n: column positioning for "hg summary"
6488 # i18n: column positioning for "hg summary"
6487 ui.write(_('update: %d new changesets (update)\n') % new)
6489 ui.write(_('update: %d new changesets (update)\n') % new)
6488 else:
6490 else:
6489 # i18n: column positioning for "hg summary"
6491 # i18n: column positioning for "hg summary"
6490 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6492 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6491 (new, len(bheads)))
6493 (new, len(bheads)))
6492
6494
6493 t = []
6495 t = []
6494 draft = len(repo.revs('draft()'))
6496 draft = len(repo.revs('draft()'))
6495 if draft:
6497 if draft:
6496 t.append(_('%d draft') % draft)
6498 t.append(_('%d draft') % draft)
6497 secret = len(repo.revs('secret()'))
6499 secret = len(repo.revs('secret()'))
6498 if secret:
6500 if secret:
6499 t.append(_('%d secret') % secret)
6501 t.append(_('%d secret') % secret)
6500
6502
6501 if draft or secret:
6503 if draft or secret:
6502 ui.status(_('phases: %s\n') % ', '.join(t))
6504 ui.status(_('phases: %s\n') % ', '.join(t))
6503
6505
6504 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6506 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6505 for trouble in ("unstable", "divergent", "bumped"):
6507 for trouble in ("unstable", "divergent", "bumped"):
6506 numtrouble = len(repo.revs(trouble + "()"))
6508 numtrouble = len(repo.revs(trouble + "()"))
6507 # We write all the possibilities to ease translation
6509 # We write all the possibilities to ease translation
6508 troublemsg = {
6510 troublemsg = {
6509 "unstable": _("unstable: %d changeset"),
6511 "unstable": _("unstable: %d changeset"),
6510 "divergent": _("divergent: %d changeset"),
6512 "divergent": _("divergent: %d changeset"),
6511 "bumped": _("bumped: %d changeset"),
6513 "bumped": _("bumped: %d changeset"),
6512 }
6514 }
6513 if numtrouble > 0:
6515 if numtrouble > 0:
6514 ui.status(troublemsg[trouble] % numtrouble + "\n")
6516 ui.status(troublemsg[trouble] % numtrouble + "\n")
6515
6517
6516 cmdutil.summaryhooks(ui, repo)
6518 cmdutil.summaryhooks(ui, repo)
6517
6519
6518 if opts.get('remote'):
6520 if opts.get('remote'):
6519 needsincoming, needsoutgoing = True, True
6521 needsincoming, needsoutgoing = True, True
6520 else:
6522 else:
6521 needsincoming, needsoutgoing = False, False
6523 needsincoming, needsoutgoing = False, False
6522 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6524 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6523 if i:
6525 if i:
6524 needsincoming = True
6526 needsincoming = True
6525 if o:
6527 if o:
6526 needsoutgoing = True
6528 needsoutgoing = True
6527 if not needsincoming and not needsoutgoing:
6529 if not needsincoming and not needsoutgoing:
6528 return
6530 return
6529
6531
6530 def getincoming():
6532 def getincoming():
6531 source, branches = hg.parseurl(ui.expandpath('default'))
6533 source, branches = hg.parseurl(ui.expandpath('default'))
6532 sbranch = branches[0]
6534 sbranch = branches[0]
6533 try:
6535 try:
6534 other = hg.peer(repo, {}, source)
6536 other = hg.peer(repo, {}, source)
6535 except error.RepoError:
6537 except error.RepoError:
6536 if opts.get('remote'):
6538 if opts.get('remote'):
6537 raise
6539 raise
6538 return source, sbranch, None, None, None
6540 return source, sbranch, None, None, None
6539 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6541 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6540 if revs:
6542 if revs:
6541 revs = [other.lookup(rev) for rev in revs]
6543 revs = [other.lookup(rev) for rev in revs]
6542 ui.debug('comparing with %s\n' % util.hidepassword(source))
6544 ui.debug('comparing with %s\n' % util.hidepassword(source))
6543 repo.ui.pushbuffer()
6545 repo.ui.pushbuffer()
6544 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6546 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6545 repo.ui.popbuffer()
6547 repo.ui.popbuffer()
6546 return source, sbranch, other, commoninc, commoninc[1]
6548 return source, sbranch, other, commoninc, commoninc[1]
6547
6549
6548 if needsincoming:
6550 if needsincoming:
6549 source, sbranch, sother, commoninc, incoming = getincoming()
6551 source, sbranch, sother, commoninc, incoming = getincoming()
6550 else:
6552 else:
6551 source = sbranch = sother = commoninc = incoming = None
6553 source = sbranch = sother = commoninc = incoming = None
6552
6554
6553 def getoutgoing():
6555 def getoutgoing():
6554 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6556 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6555 dbranch = branches[0]
6557 dbranch = branches[0]
6556 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6558 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6557 if source != dest:
6559 if source != dest:
6558 try:
6560 try:
6559 dother = hg.peer(repo, {}, dest)
6561 dother = hg.peer(repo, {}, dest)
6560 except error.RepoError:
6562 except error.RepoError:
6561 if opts.get('remote'):
6563 if opts.get('remote'):
6562 raise
6564 raise
6563 return dest, dbranch, None, None
6565 return dest, dbranch, None, None
6564 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6566 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6565 elif sother is None:
6567 elif sother is None:
6566 # there is no explicit destination peer, but source one is invalid
6568 # there is no explicit destination peer, but source one is invalid
6567 return dest, dbranch, None, None
6569 return dest, dbranch, None, None
6568 else:
6570 else:
6569 dother = sother
6571 dother = sother
6570 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6572 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6571 common = None
6573 common = None
6572 else:
6574 else:
6573 common = commoninc
6575 common = commoninc
6574 if revs:
6576 if revs:
6575 revs = [repo.lookup(rev) for rev in revs]
6577 revs = [repo.lookup(rev) for rev in revs]
6576 repo.ui.pushbuffer()
6578 repo.ui.pushbuffer()
6577 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6579 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6578 commoninc=common)
6580 commoninc=common)
6579 repo.ui.popbuffer()
6581 repo.ui.popbuffer()
6580 return dest, dbranch, dother, outgoing
6582 return dest, dbranch, dother, outgoing
6581
6583
6582 if needsoutgoing:
6584 if needsoutgoing:
6583 dest, dbranch, dother, outgoing = getoutgoing()
6585 dest, dbranch, dother, outgoing = getoutgoing()
6584 else:
6586 else:
6585 dest = dbranch = dother = outgoing = None
6587 dest = dbranch = dother = outgoing = None
6586
6588
6587 if opts.get('remote'):
6589 if opts.get('remote'):
6588 t = []
6590 t = []
6589 if incoming:
6591 if incoming:
6590 t.append(_('1 or more incoming'))
6592 t.append(_('1 or more incoming'))
6591 o = outgoing.missing
6593 o = outgoing.missing
6592 if o:
6594 if o:
6593 t.append(_('%d outgoing') % len(o))
6595 t.append(_('%d outgoing') % len(o))
6594 other = dother or sother
6596 other = dother or sother
6595 if 'bookmarks' in other.listkeys('namespaces'):
6597 if 'bookmarks' in other.listkeys('namespaces'):
6596 counts = bookmarks.summary(repo, other)
6598 counts = bookmarks.summary(repo, other)
6597 if counts[0] > 0:
6599 if counts[0] > 0:
6598 t.append(_('%d incoming bookmarks') % counts[0])
6600 t.append(_('%d incoming bookmarks') % counts[0])
6599 if counts[1] > 0:
6601 if counts[1] > 0:
6600 t.append(_('%d outgoing bookmarks') % counts[1])
6602 t.append(_('%d outgoing bookmarks') % counts[1])
6601
6603
6602 if t:
6604 if t:
6603 # i18n: column positioning for "hg summary"
6605 # i18n: column positioning for "hg summary"
6604 ui.write(_('remote: %s\n') % (', '.join(t)))
6606 ui.write(_('remote: %s\n') % (', '.join(t)))
6605 else:
6607 else:
6606 # i18n: column positioning for "hg summary"
6608 # i18n: column positioning for "hg summary"
6607 ui.status(_('remote: (synced)\n'))
6609 ui.status(_('remote: (synced)\n'))
6608
6610
6609 cmdutil.summaryremotehooks(ui, repo, opts,
6611 cmdutil.summaryremotehooks(ui, repo, opts,
6610 ((source, sbranch, sother, commoninc),
6612 ((source, sbranch, sother, commoninc),
6611 (dest, dbranch, dother, outgoing)))
6613 (dest, dbranch, dother, outgoing)))
6612
6614
6613 @command('tag',
6615 @command('tag',
6614 [('f', 'force', None, _('force tag')),
6616 [('f', 'force', None, _('force tag')),
6615 ('l', 'local', None, _('make the tag local')),
6617 ('l', 'local', None, _('make the tag local')),
6616 ('r', 'rev', '', _('revision to tag'), _('REV')),
6618 ('r', 'rev', '', _('revision to tag'), _('REV')),
6617 ('', 'remove', None, _('remove a tag')),
6619 ('', 'remove', None, _('remove a tag')),
6618 # -l/--local is already there, commitopts cannot be used
6620 # -l/--local is already there, commitopts cannot be used
6619 ('e', 'edit', None, _('invoke editor on commit messages')),
6621 ('e', 'edit', None, _('invoke editor on commit messages')),
6620 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6622 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6621 ] + commitopts2,
6623 ] + commitopts2,
6622 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6624 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6623 def tag(ui, repo, name1, *names, **opts):
6625 def tag(ui, repo, name1, *names, **opts):
6624 """add one or more tags for the current or given revision
6626 """add one or more tags for the current or given revision
6625
6627
6626 Name a particular revision using <name>.
6628 Name a particular revision using <name>.
6627
6629
6628 Tags are used to name particular revisions of the repository and are
6630 Tags are used to name particular revisions of the repository and are
6629 very useful to compare different revisions, to go back to significant
6631 very useful to compare different revisions, to go back to significant
6630 earlier versions or to mark branch points as releases, etc. Changing
6632 earlier versions or to mark branch points as releases, etc. Changing
6631 an existing tag is normally disallowed; use -f/--force to override.
6633 an existing tag is normally disallowed; use -f/--force to override.
6632
6634
6633 If no revision is given, the parent of the working directory is
6635 If no revision is given, the parent of the working directory is
6634 used.
6636 used.
6635
6637
6636 To facilitate version control, distribution, and merging of tags,
6638 To facilitate version control, distribution, and merging of tags,
6637 they are stored as a file named ".hgtags" which is managed similarly
6639 they are stored as a file named ".hgtags" which is managed similarly
6638 to other project files and can be hand-edited if necessary. This
6640 to other project files and can be hand-edited if necessary. This
6639 also means that tagging creates a new commit. The file
6641 also means that tagging creates a new commit. The file
6640 ".hg/localtags" is used for local tags (not shared among
6642 ".hg/localtags" is used for local tags (not shared among
6641 repositories).
6643 repositories).
6642
6644
6643 Tag commits are usually made at the head of a branch. If the parent
6645 Tag commits are usually made at the head of a branch. If the parent
6644 of the working directory is not a branch head, :hg:`tag` aborts; use
6646 of the working directory is not a branch head, :hg:`tag` aborts; use
6645 -f/--force to force the tag commit to be based on a non-head
6647 -f/--force to force the tag commit to be based on a non-head
6646 changeset.
6648 changeset.
6647
6649
6648 See :hg:`help dates` for a list of formats valid for -d/--date.
6650 See :hg:`help dates` for a list of formats valid for -d/--date.
6649
6651
6650 Since tag names have priority over branch names during revision
6652 Since tag names have priority over branch names during revision
6651 lookup, using an existing branch name as a tag name is discouraged.
6653 lookup, using an existing branch name as a tag name is discouraged.
6652
6654
6653 Returns 0 on success.
6655 Returns 0 on success.
6654 """
6656 """
6655 wlock = lock = None
6657 wlock = lock = None
6656 try:
6658 try:
6657 wlock = repo.wlock()
6659 wlock = repo.wlock()
6658 lock = repo.lock()
6660 lock = repo.lock()
6659 rev_ = "."
6661 rev_ = "."
6660 names = [t.strip() for t in (name1,) + names]
6662 names = [t.strip() for t in (name1,) + names]
6661 if len(names) != len(set(names)):
6663 if len(names) != len(set(names)):
6662 raise error.Abort(_('tag names must be unique'))
6664 raise error.Abort(_('tag names must be unique'))
6663 for n in names:
6665 for n in names:
6664 scmutil.checknewlabel(repo, n, 'tag')
6666 scmutil.checknewlabel(repo, n, 'tag')
6665 if not n:
6667 if not n:
6666 raise error.Abort(_('tag names cannot consist entirely of '
6668 raise error.Abort(_('tag names cannot consist entirely of '
6667 'whitespace'))
6669 'whitespace'))
6668 if opts.get('rev') and opts.get('remove'):
6670 if opts.get('rev') and opts.get('remove'):
6669 raise error.Abort(_("--rev and --remove are incompatible"))
6671 raise error.Abort(_("--rev and --remove are incompatible"))
6670 if opts.get('rev'):
6672 if opts.get('rev'):
6671 rev_ = opts['rev']
6673 rev_ = opts['rev']
6672 message = opts.get('message')
6674 message = opts.get('message')
6673 if opts.get('remove'):
6675 if opts.get('remove'):
6674 if opts.get('local'):
6676 if opts.get('local'):
6675 expectedtype = 'local'
6677 expectedtype = 'local'
6676 else:
6678 else:
6677 expectedtype = 'global'
6679 expectedtype = 'global'
6678
6680
6679 for n in names:
6681 for n in names:
6680 if not repo.tagtype(n):
6682 if not repo.tagtype(n):
6681 raise error.Abort(_("tag '%s' does not exist") % n)
6683 raise error.Abort(_("tag '%s' does not exist") % n)
6682 if repo.tagtype(n) != expectedtype:
6684 if repo.tagtype(n) != expectedtype:
6683 if expectedtype == 'global':
6685 if expectedtype == 'global':
6684 raise error.Abort(_("tag '%s' is not a global tag") % n)
6686 raise error.Abort(_("tag '%s' is not a global tag") % n)
6685 else:
6687 else:
6686 raise error.Abort(_("tag '%s' is not a local tag") % n)
6688 raise error.Abort(_("tag '%s' is not a local tag") % n)
6687 rev_ = 'null'
6689 rev_ = 'null'
6688 if not message:
6690 if not message:
6689 # we don't translate commit messages
6691 # we don't translate commit messages
6690 message = 'Removed tag %s' % ', '.join(names)
6692 message = 'Removed tag %s' % ', '.join(names)
6691 elif not opts.get('force'):
6693 elif not opts.get('force'):
6692 for n in names:
6694 for n in names:
6693 if n in repo.tags():
6695 if n in repo.tags():
6694 raise error.Abort(_("tag '%s' already exists "
6696 raise error.Abort(_("tag '%s' already exists "
6695 "(use -f to force)") % n)
6697 "(use -f to force)") % n)
6696 if not opts.get('local'):
6698 if not opts.get('local'):
6697 p1, p2 = repo.dirstate.parents()
6699 p1, p2 = repo.dirstate.parents()
6698 if p2 != nullid:
6700 if p2 != nullid:
6699 raise error.Abort(_('uncommitted merge'))
6701 raise error.Abort(_('uncommitted merge'))
6700 bheads = repo.branchheads()
6702 bheads = repo.branchheads()
6701 if not opts.get('force') and bheads and p1 not in bheads:
6703 if not opts.get('force') and bheads and p1 not in bheads:
6702 raise error.Abort(_('not at a branch head (use -f to force)'))
6704 raise error.Abort(_('not at a branch head (use -f to force)'))
6703 r = scmutil.revsingle(repo, rev_).node()
6705 r = scmutil.revsingle(repo, rev_).node()
6704
6706
6705 if not message:
6707 if not message:
6706 # we don't translate commit messages
6708 # we don't translate commit messages
6707 message = ('Added tag %s for changeset %s' %
6709 message = ('Added tag %s for changeset %s' %
6708 (', '.join(names), short(r)))
6710 (', '.join(names), short(r)))
6709
6711
6710 date = opts.get('date')
6712 date = opts.get('date')
6711 if date:
6713 if date:
6712 date = util.parsedate(date)
6714 date = util.parsedate(date)
6713
6715
6714 if opts.get('remove'):
6716 if opts.get('remove'):
6715 editform = 'tag.remove'
6717 editform = 'tag.remove'
6716 else:
6718 else:
6717 editform = 'tag.add'
6719 editform = 'tag.add'
6718 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6720 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6719
6721
6720 # don't allow tagging the null rev
6722 # don't allow tagging the null rev
6721 if (not opts.get('remove') and
6723 if (not opts.get('remove') and
6722 scmutil.revsingle(repo, rev_).rev() == nullrev):
6724 scmutil.revsingle(repo, rev_).rev() == nullrev):
6723 raise error.Abort(_("cannot tag null revision"))
6725 raise error.Abort(_("cannot tag null revision"))
6724
6726
6725 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6727 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6726 editor=editor)
6728 editor=editor)
6727 finally:
6729 finally:
6728 release(lock, wlock)
6730 release(lock, wlock)
6729
6731
6730 @command('tags', formatteropts, '')
6732 @command('tags', formatteropts, '')
6731 def tags(ui, repo, **opts):
6733 def tags(ui, repo, **opts):
6732 """list repository tags
6734 """list repository tags
6733
6735
6734 This lists both regular and local tags. When the -v/--verbose
6736 This lists both regular and local tags. When the -v/--verbose
6735 switch is used, a third column "local" is printed for local tags.
6737 switch is used, a third column "local" is printed for local tags.
6736 When the -q/--quiet switch is used, only the tag name is printed.
6738 When the -q/--quiet switch is used, only the tag name is printed.
6737
6739
6738 Returns 0 on success.
6740 Returns 0 on success.
6739 """
6741 """
6740
6742
6741 fm = ui.formatter('tags', opts)
6743 fm = ui.formatter('tags', opts)
6742 hexfunc = fm.hexfunc
6744 hexfunc = fm.hexfunc
6743 tagtype = ""
6745 tagtype = ""
6744
6746
6745 for t, n in reversed(repo.tagslist()):
6747 for t, n in reversed(repo.tagslist()):
6746 hn = hexfunc(n)
6748 hn = hexfunc(n)
6747 label = 'tags.normal'
6749 label = 'tags.normal'
6748 tagtype = ''
6750 tagtype = ''
6749 if repo.tagtype(t) == 'local':
6751 if repo.tagtype(t) == 'local':
6750 label = 'tags.local'
6752 label = 'tags.local'
6751 tagtype = 'local'
6753 tagtype = 'local'
6752
6754
6753 fm.startitem()
6755 fm.startitem()
6754 fm.write('tag', '%s', t, label=label)
6756 fm.write('tag', '%s', t, label=label)
6755 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6757 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6756 fm.condwrite(not ui.quiet, 'rev node', fmt,
6758 fm.condwrite(not ui.quiet, 'rev node', fmt,
6757 repo.changelog.rev(n), hn, label=label)
6759 repo.changelog.rev(n), hn, label=label)
6758 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6760 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6759 tagtype, label=label)
6761 tagtype, label=label)
6760 fm.plain('\n')
6762 fm.plain('\n')
6761 fm.end()
6763 fm.end()
6762
6764
6763 @command('tip',
6765 @command('tip',
6764 [('p', 'patch', None, _('show patch')),
6766 [('p', 'patch', None, _('show patch')),
6765 ('g', 'git', None, _('use git extended diff format')),
6767 ('g', 'git', None, _('use git extended diff format')),
6766 ] + templateopts,
6768 ] + templateopts,
6767 _('[-p] [-g]'))
6769 _('[-p] [-g]'))
6768 def tip(ui, repo, **opts):
6770 def tip(ui, repo, **opts):
6769 """show the tip revision (DEPRECATED)
6771 """show the tip revision (DEPRECATED)
6770
6772
6771 The tip revision (usually just called the tip) is the changeset
6773 The tip revision (usually just called the tip) is the changeset
6772 most recently added to the repository (and therefore the most
6774 most recently added to the repository (and therefore the most
6773 recently changed head).
6775 recently changed head).
6774
6776
6775 If you have just made a commit, that commit will be the tip. If
6777 If you have just made a commit, that commit will be the tip. If
6776 you have just pulled changes from another repository, the tip of
6778 you have just pulled changes from another repository, the tip of
6777 that repository becomes the current tip. The "tip" tag is special
6779 that repository becomes the current tip. The "tip" tag is special
6778 and cannot be renamed or assigned to a different changeset.
6780 and cannot be renamed or assigned to a different changeset.
6779
6781
6780 This command is deprecated, please use :hg:`heads` instead.
6782 This command is deprecated, please use :hg:`heads` instead.
6781
6783
6782 Returns 0 on success.
6784 Returns 0 on success.
6783 """
6785 """
6784 displayer = cmdutil.show_changeset(ui, repo, opts)
6786 displayer = cmdutil.show_changeset(ui, repo, opts)
6785 displayer.show(repo['tip'])
6787 displayer.show(repo['tip'])
6786 displayer.close()
6788 displayer.close()
6787
6789
6788 @command('unbundle',
6790 @command('unbundle',
6789 [('u', 'update', None,
6791 [('u', 'update', None,
6790 _('update to new branch head if changesets were unbundled'))],
6792 _('update to new branch head if changesets were unbundled'))],
6791 _('[-u] FILE...'))
6793 _('[-u] FILE...'))
6792 def unbundle(ui, repo, fname1, *fnames, **opts):
6794 def unbundle(ui, repo, fname1, *fnames, **opts):
6793 """apply one or more changegroup files
6795 """apply one or more changegroup files
6794
6796
6795 Apply one or more compressed changegroup files generated by the
6797 Apply one or more compressed changegroup files generated by the
6796 bundle command.
6798 bundle command.
6797
6799
6798 Returns 0 on success, 1 if an update has unresolved files.
6800 Returns 0 on success, 1 if an update has unresolved files.
6799 """
6801 """
6800 fnames = (fname1,) + fnames
6802 fnames = (fname1,) + fnames
6801
6803
6802 lock = repo.lock()
6804 lock = repo.lock()
6803 try:
6805 try:
6804 for fname in fnames:
6806 for fname in fnames:
6805 f = hg.openpath(ui, fname)
6807 f = hg.openpath(ui, fname)
6806 gen = exchange.readbundle(ui, f, fname)
6808 gen = exchange.readbundle(ui, f, fname)
6807 if isinstance(gen, bundle2.unbundle20):
6809 if isinstance(gen, bundle2.unbundle20):
6808 tr = repo.transaction('unbundle')
6810 tr = repo.transaction('unbundle')
6809 try:
6811 try:
6810 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6812 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6811 url='bundle:' + fname)
6813 url='bundle:' + fname)
6812 tr.close()
6814 tr.close()
6813 except error.BundleUnknownFeatureError as exc:
6815 except error.BundleUnknownFeatureError as exc:
6814 raise error.Abort(_('%s: unknown bundle feature, %s')
6816 raise error.Abort(_('%s: unknown bundle feature, %s')
6815 % (fname, exc),
6817 % (fname, exc),
6816 hint=_("see https://mercurial-scm.org/"
6818 hint=_("see https://mercurial-scm.org/"
6817 "wiki/BundleFeature for more "
6819 "wiki/BundleFeature for more "
6818 "information"))
6820 "information"))
6819 finally:
6821 finally:
6820 if tr:
6822 if tr:
6821 tr.release()
6823 tr.release()
6822 changes = [r.get('return', 0)
6824 changes = [r.get('return', 0)
6823 for r in op.records['changegroup']]
6825 for r in op.records['changegroup']]
6824 modheads = changegroup.combineresults(changes)
6826 modheads = changegroup.combineresults(changes)
6825 elif isinstance(gen, streamclone.streamcloneapplier):
6827 elif isinstance(gen, streamclone.streamcloneapplier):
6826 raise error.Abort(
6828 raise error.Abort(
6827 _('packed bundles cannot be applied with '
6829 _('packed bundles cannot be applied with '
6828 '"hg unbundle"'),
6830 '"hg unbundle"'),
6829 hint=_('use "hg debugapplystreamclonebundle"'))
6831 hint=_('use "hg debugapplystreamclonebundle"'))
6830 else:
6832 else:
6831 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6833 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6832 finally:
6834 finally:
6833 lock.release()
6835 lock.release()
6834
6836
6835 return postincoming(ui, repo, modheads, opts.get('update'), None)
6837 return postincoming(ui, repo, modheads, opts.get('update'), None)
6836
6838
6837 @command('^update|up|checkout|co',
6839 @command('^update|up|checkout|co',
6838 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6840 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6839 ('c', 'check', None,
6841 ('c', 'check', None,
6840 _('update across branches if no uncommitted changes')),
6842 _('update across branches if no uncommitted changes')),
6841 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6843 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6842 ('r', 'rev', '', _('revision'), _('REV'))
6844 ('r', 'rev', '', _('revision'), _('REV'))
6843 ] + mergetoolopts,
6845 ] + mergetoolopts,
6844 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6846 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6845 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6847 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6846 tool=None):
6848 tool=None):
6847 """update working directory (or switch revisions)
6849 """update working directory (or switch revisions)
6848
6850
6849 Update the repository's working directory to the specified
6851 Update the repository's working directory to the specified
6850 changeset. If no changeset is specified, update to the tip of the
6852 changeset. If no changeset is specified, update to the tip of the
6851 current named branch and move the active bookmark (see :hg:`help
6853 current named branch and move the active bookmark (see :hg:`help
6852 bookmarks`).
6854 bookmarks`).
6853
6855
6854 Update sets the working directory's parent revision to the specified
6856 Update sets the working directory's parent revision to the specified
6855 changeset (see :hg:`help parents`).
6857 changeset (see :hg:`help parents`).
6856
6858
6857 If the changeset is not a descendant or ancestor of the working
6859 If the changeset is not a descendant or ancestor of the working
6858 directory's parent, the update is aborted. With the -c/--check
6860 directory's parent, the update is aborted. With the -c/--check
6859 option, the working directory is checked for uncommitted changes; if
6861 option, the working directory is checked for uncommitted changes; if
6860 none are found, the working directory is updated to the specified
6862 none are found, the working directory is updated to the specified
6861 changeset.
6863 changeset.
6862
6864
6863 .. container:: verbose
6865 .. container:: verbose
6864
6866
6865 The following rules apply when the working directory contains
6867 The following rules apply when the working directory contains
6866 uncommitted changes:
6868 uncommitted changes:
6867
6869
6868 1. If neither -c/--check nor -C/--clean is specified, and if
6870 1. If neither -c/--check nor -C/--clean is specified, and if
6869 the requested changeset is an ancestor or descendant of
6871 the requested changeset is an ancestor or descendant of
6870 the working directory's parent, the uncommitted changes
6872 the working directory's parent, the uncommitted changes
6871 are merged into the requested changeset and the merged
6873 are merged into the requested changeset and the merged
6872 result is left uncommitted. If the requested changeset is
6874 result is left uncommitted. If the requested changeset is
6873 not an ancestor or descendant (that is, it is on another
6875 not an ancestor or descendant (that is, it is on another
6874 branch), the update is aborted and the uncommitted changes
6876 branch), the update is aborted and the uncommitted changes
6875 are preserved.
6877 are preserved.
6876
6878
6877 2. With the -c/--check option, the update is aborted and the
6879 2. With the -c/--check option, the update is aborted and the
6878 uncommitted changes are preserved.
6880 uncommitted changes are preserved.
6879
6881
6880 3. With the -C/--clean option, uncommitted changes are discarded and
6882 3. With the -C/--clean option, uncommitted changes are discarded and
6881 the working directory is updated to the requested changeset.
6883 the working directory is updated to the requested changeset.
6882
6884
6883 To cancel an uncommitted merge (and lose your changes), use
6885 To cancel an uncommitted merge (and lose your changes), use
6884 :hg:`update --clean .`.
6886 :hg:`update --clean .`.
6885
6887
6886 Use null as the changeset to remove the working directory (like
6888 Use null as the changeset to remove the working directory (like
6887 :hg:`clone -U`).
6889 :hg:`clone -U`).
6888
6890
6889 If you want to revert just one file to an older revision, use
6891 If you want to revert just one file to an older revision, use
6890 :hg:`revert [-r REV] NAME`.
6892 :hg:`revert [-r REV] NAME`.
6891
6893
6892 See :hg:`help dates` for a list of formats valid for -d/--date.
6894 See :hg:`help dates` for a list of formats valid for -d/--date.
6893
6895
6894 Returns 0 on success, 1 if there are unresolved files.
6896 Returns 0 on success, 1 if there are unresolved files.
6895 """
6897 """
6896 movemarkfrom = None
6898 movemarkfrom = None
6897 if rev and node:
6899 if rev and node:
6898 raise error.Abort(_("please specify just one revision"))
6900 raise error.Abort(_("please specify just one revision"))
6899
6901
6900 if rev is None or rev == '':
6902 if rev is None or rev == '':
6901 rev = node
6903 rev = node
6902
6904
6903 wlock = repo.wlock()
6905 wlock = repo.wlock()
6904 try:
6906 try:
6905 cmdutil.clearunfinished(repo)
6907 cmdutil.clearunfinished(repo)
6906
6908
6907 if date:
6909 if date:
6908 if rev is not None:
6910 if rev is not None:
6909 raise error.Abort(_("you can't specify a revision and a date"))
6911 raise error.Abort(_("you can't specify a revision and a date"))
6910 rev = cmdutil.finddate(ui, repo, date)
6912 rev = cmdutil.finddate(ui, repo, date)
6911
6913
6912 # if we defined a bookmark, we have to remember the original name
6914 # if we defined a bookmark, we have to remember the original name
6913 brev = rev
6915 brev = rev
6914 rev = scmutil.revsingle(repo, rev, rev).rev()
6916 rev = scmutil.revsingle(repo, rev, rev).rev()
6915
6917
6916 if check and clean:
6918 if check and clean:
6917 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6919 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6918 )
6920 )
6919
6921
6920 if check:
6922 if check:
6921 cmdutil.bailifchanged(repo, merge=False)
6923 cmdutil.bailifchanged(repo, merge=False)
6922 if rev is None:
6924 if rev is None:
6923 updata = destutil.destupdate(repo, clean=clean, check=check)
6925 updata = destutil.destupdate(repo, clean=clean, check=check)
6924 rev, movemarkfrom, brev = updata
6926 rev, movemarkfrom, brev = updata
6925
6927
6926 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6928 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6927
6929
6928 if clean:
6930 if clean:
6929 ret = hg.clean(repo, rev)
6931 ret = hg.clean(repo, rev)
6930 else:
6932 else:
6931 ret = hg.update(repo, rev)
6933 ret = hg.update(repo, rev)
6932
6934
6933 if not ret and movemarkfrom:
6935 if not ret and movemarkfrom:
6934 if movemarkfrom == repo['.'].node():
6936 if movemarkfrom == repo['.'].node():
6935 pass # no-op update
6937 pass # no-op update
6936 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6938 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6937 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6939 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6938 else:
6940 else:
6939 # this can happen with a non-linear update
6941 # this can happen with a non-linear update
6940 ui.status(_("(leaving bookmark %s)\n") %
6942 ui.status(_("(leaving bookmark %s)\n") %
6941 repo._activebookmark)
6943 repo._activebookmark)
6942 bookmarks.deactivate(repo)
6944 bookmarks.deactivate(repo)
6943 elif brev in repo._bookmarks:
6945 elif brev in repo._bookmarks:
6944 bookmarks.activate(repo, brev)
6946 bookmarks.activate(repo, brev)
6945 ui.status(_("(activating bookmark %s)\n") % brev)
6947 ui.status(_("(activating bookmark %s)\n") % brev)
6946 elif brev:
6948 elif brev:
6947 if repo._activebookmark:
6949 if repo._activebookmark:
6948 ui.status(_("(leaving bookmark %s)\n") %
6950 ui.status(_("(leaving bookmark %s)\n") %
6949 repo._activebookmark)
6951 repo._activebookmark)
6950 bookmarks.deactivate(repo)
6952 bookmarks.deactivate(repo)
6951 finally:
6953 finally:
6952 wlock.release()
6954 wlock.release()
6953
6955
6954 return ret
6956 return ret
6955
6957
6956 @command('verify', [])
6958 @command('verify', [])
6957 def verify(ui, repo):
6959 def verify(ui, repo):
6958 """verify the integrity of the repository
6960 """verify the integrity of the repository
6959
6961
6960 Verify the integrity of the current repository.
6962 Verify the integrity of the current repository.
6961
6963
6962 This will perform an extensive check of the repository's
6964 This will perform an extensive check of the repository's
6963 integrity, validating the hashes and checksums of each entry in
6965 integrity, validating the hashes and checksums of each entry in
6964 the changelog, manifest, and tracked files, as well as the
6966 the changelog, manifest, and tracked files, as well as the
6965 integrity of their crosslinks and indices.
6967 integrity of their crosslinks and indices.
6966
6968
6967 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6969 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6968 for more information about recovery from corruption of the
6970 for more information about recovery from corruption of the
6969 repository.
6971 repository.
6970
6972
6971 Returns 0 on success, 1 if errors are encountered.
6973 Returns 0 on success, 1 if errors are encountered.
6972 """
6974 """
6973 return hg.verify(repo)
6975 return hg.verify(repo)
6974
6976
6975 @command('version', [], norepo=True)
6977 @command('version', [], norepo=True)
6976 def version_(ui):
6978 def version_(ui):
6977 """output version and copyright information"""
6979 """output version and copyright information"""
6978 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6980 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6979 % util.version())
6981 % util.version())
6980 ui.status(_(
6982 ui.status(_(
6981 "(see https://mercurial-scm.org for more information)\n"
6983 "(see https://mercurial-scm.org for more information)\n"
6982 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6984 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6983 "This is free software; see the source for copying conditions. "
6985 "This is free software; see the source for copying conditions. "
6984 "There is NO\nwarranty; "
6986 "There is NO\nwarranty; "
6985 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6987 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6986 ))
6988 ))
6987
6989
6988 ui.note(_("\nEnabled extensions:\n\n"))
6990 ui.note(_("\nEnabled extensions:\n\n"))
6989 if ui.verbose:
6991 if ui.verbose:
6990 # format names and versions into columns
6992 # format names and versions into columns
6991 names = []
6993 names = []
6992 vers = []
6994 vers = []
6993 for name, module in extensions.extensions():
6995 for name, module in extensions.extensions():
6994 names.append(name)
6996 names.append(name)
6995 vers.append(extensions.moduleversion(module))
6997 vers.append(extensions.moduleversion(module))
6996 if names:
6998 if names:
6997 maxnamelen = max(len(n) for n in names)
6999 maxnamelen = max(len(n) for n in names)
6998 for i, name in enumerate(names):
7000 for i, name in enumerate(names):
6999 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7001 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,331 +1,334 b''
1 $ hg init test
1 $ hg init test
2 $ cd test
2 $ cd test
3 $ hg unbundle "$TESTDIR/bundles/remote.hg"
3 $ hg unbundle "$TESTDIR/bundles/remote.hg"
4 adding changesets
4 adding changesets
5 adding manifests
5 adding manifests
6 adding file changes
6 adding file changes
7 added 9 changesets with 7 changes to 4 files (+1 heads)
7 added 9 changesets with 7 changes to 4 files (+1 heads)
8 (run 'hg heads' to see heads, 'hg merge' to merge)
8 (run 'hg heads' to see heads, 'hg merge' to merge)
9 $ hg up tip
9 $ hg up tip
10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 $ cd ..
11 $ cd ..
12
12
13 $ for i in 0 1 2 3 4 5 6 7 8; do
13 $ for i in 0 1 2 3 4 5 6 7 8; do
14 > mkdir test-"$i"
14 > mkdir test-"$i"
15 > hg --cwd test-"$i" init
15 > hg --cwd test-"$i" init
16 > hg -R test bundle -r "$i" test-"$i".hg test-"$i"
16 > hg -R test bundle -r "$i" test-"$i".hg test-"$i"
17 > cd test-"$i"
17 > cd test-"$i"
18 > hg unbundle ../test-"$i".hg
18 > hg unbundle ../test-"$i".hg
19 > hg verify
19 > hg verify
20 > hg tip -q
20 > hg tip -q
21 > cd ..
21 > cd ..
22 > done
22 > done
23 searching for changes
23 searching for changes
24 1 changesets found
24 1 changesets found
25 adding changesets
25 adding changesets
26 adding manifests
26 adding manifests
27 adding file changes
27 adding file changes
28 added 1 changesets with 1 changes to 1 files
28 added 1 changesets with 1 changes to 1 files
29 (run 'hg update' to get a working copy)
29 (run 'hg update' to get a working copy)
30 checking changesets
30 checking changesets
31 checking manifests
31 checking manifests
32 crosschecking files in changesets and manifests
32 crosschecking files in changesets and manifests
33 checking files
33 checking files
34 1 files, 1 changesets, 1 total revisions
34 1 files, 1 changesets, 1 total revisions
35 0:bfaf4b5cbf01
35 0:bfaf4b5cbf01
36 searching for changes
36 searching for changes
37 2 changesets found
37 2 changesets found
38 adding changesets
38 adding changesets
39 adding manifests
39 adding manifests
40 adding file changes
40 adding file changes
41 added 2 changesets with 2 changes to 1 files
41 added 2 changesets with 2 changes to 1 files
42 (run 'hg update' to get a working copy)
42 (run 'hg update' to get a working copy)
43 checking changesets
43 checking changesets
44 checking manifests
44 checking manifests
45 crosschecking files in changesets and manifests
45 crosschecking files in changesets and manifests
46 checking files
46 checking files
47 1 files, 2 changesets, 2 total revisions
47 1 files, 2 changesets, 2 total revisions
48 1:21f32785131f
48 1:21f32785131f
49 searching for changes
49 searching for changes
50 3 changesets found
50 3 changesets found
51 adding changesets
51 adding changesets
52 adding manifests
52 adding manifests
53 adding file changes
53 adding file changes
54 added 3 changesets with 3 changes to 1 files
54 added 3 changesets with 3 changes to 1 files
55 (run 'hg update' to get a working copy)
55 (run 'hg update' to get a working copy)
56 checking changesets
56 checking changesets
57 checking manifests
57 checking manifests
58 crosschecking files in changesets and manifests
58 crosschecking files in changesets and manifests
59 checking files
59 checking files
60 1 files, 3 changesets, 3 total revisions
60 1 files, 3 changesets, 3 total revisions
61 2:4ce51a113780
61 2:4ce51a113780
62 searching for changes
62 searching for changes
63 4 changesets found
63 4 changesets found
64 adding changesets
64 adding changesets
65 adding manifests
65 adding manifests
66 adding file changes
66 adding file changes
67 added 4 changesets with 4 changes to 1 files
67 added 4 changesets with 4 changes to 1 files
68 (run 'hg update' to get a working copy)
68 (run 'hg update' to get a working copy)
69 checking changesets
69 checking changesets
70 checking manifests
70 checking manifests
71 crosschecking files in changesets and manifests
71 crosschecking files in changesets and manifests
72 checking files
72 checking files
73 1 files, 4 changesets, 4 total revisions
73 1 files, 4 changesets, 4 total revisions
74 3:93ee6ab32777
74 3:93ee6ab32777
75 searching for changes
75 searching for changes
76 2 changesets found
76 2 changesets found
77 adding changesets
77 adding changesets
78 adding manifests
78 adding manifests
79 adding file changes
79 adding file changes
80 added 2 changesets with 2 changes to 1 files
80 added 2 changesets with 2 changes to 1 files
81 (run 'hg update' to get a working copy)
81 (run 'hg update' to get a working copy)
82 checking changesets
82 checking changesets
83 checking manifests
83 checking manifests
84 crosschecking files in changesets and manifests
84 crosschecking files in changesets and manifests
85 checking files
85 checking files
86 1 files, 2 changesets, 2 total revisions
86 1 files, 2 changesets, 2 total revisions
87 1:c70afb1ee985
87 1:c70afb1ee985
88 searching for changes
88 searching for changes
89 3 changesets found
89 3 changesets found
90 adding changesets
90 adding changesets
91 adding manifests
91 adding manifests
92 adding file changes
92 adding file changes
93 added 3 changesets with 3 changes to 1 files
93 added 3 changesets with 3 changes to 1 files
94 (run 'hg update' to get a working copy)
94 (run 'hg update' to get a working copy)
95 checking changesets
95 checking changesets
96 checking manifests
96 checking manifests
97 crosschecking files in changesets and manifests
97 crosschecking files in changesets and manifests
98 checking files
98 checking files
99 1 files, 3 changesets, 3 total revisions
99 1 files, 3 changesets, 3 total revisions
100 2:f03ae5a9b979
100 2:f03ae5a9b979
101 searching for changes
101 searching for changes
102 4 changesets found
102 4 changesets found
103 adding changesets
103 adding changesets
104 adding manifests
104 adding manifests
105 adding file changes
105 adding file changes
106 added 4 changesets with 5 changes to 2 files
106 added 4 changesets with 5 changes to 2 files
107 (run 'hg update' to get a working copy)
107 (run 'hg update' to get a working copy)
108 checking changesets
108 checking changesets
109 checking manifests
109 checking manifests
110 crosschecking files in changesets and manifests
110 crosschecking files in changesets and manifests
111 checking files
111 checking files
112 2 files, 4 changesets, 5 total revisions
112 2 files, 4 changesets, 5 total revisions
113 3:095cb14b1b4d
113 3:095cb14b1b4d
114 searching for changes
114 searching for changes
115 5 changesets found
115 5 changesets found
116 adding changesets
116 adding changesets
117 adding manifests
117 adding manifests
118 adding file changes
118 adding file changes
119 added 5 changesets with 6 changes to 3 files
119 added 5 changesets with 6 changes to 3 files
120 (run 'hg update' to get a working copy)
120 (run 'hg update' to get a working copy)
121 checking changesets
121 checking changesets
122 checking manifests
122 checking manifests
123 crosschecking files in changesets and manifests
123 crosschecking files in changesets and manifests
124 checking files
124 checking files
125 3 files, 5 changesets, 6 total revisions
125 3 files, 5 changesets, 6 total revisions
126 4:faa2e4234c7a
126 4:faa2e4234c7a
127 searching for changes
127 searching for changes
128 5 changesets found
128 5 changesets found
129 adding changesets
129 adding changesets
130 adding manifests
130 adding manifests
131 adding file changes
131 adding file changes
132 added 5 changesets with 5 changes to 2 files
132 added 5 changesets with 5 changes to 2 files
133 (run 'hg update' to get a working copy)
133 (run 'hg update' to get a working copy)
134 checking changesets
134 checking changesets
135 checking manifests
135 checking manifests
136 crosschecking files in changesets and manifests
136 crosschecking files in changesets and manifests
137 checking files
137 checking files
138 2 files, 5 changesets, 5 total revisions
138 2 files, 5 changesets, 5 total revisions
139 4:916f1afdef90
139 4:916f1afdef90
140 $ cd test-8
140 $ cd test-8
141 $ hg pull ../test-7
141 $ hg pull ../test-7
142 pulling from ../test-7
142 pulling from ../test-7
143 searching for changes
143 searching for changes
144 adding changesets
144 adding changesets
145 adding manifests
145 adding manifests
146 adding file changes
146 adding file changes
147 added 4 changesets with 2 changes to 3 files (+1 heads)
147 added 4 changesets with 2 changes to 3 files (+1 heads)
148 (run 'hg heads' to see heads, 'hg merge' to merge)
148 (run 'hg heads' to see heads, 'hg merge' to merge)
149 $ hg verify
149 $ hg verify
150 checking changesets
150 checking changesets
151 checking manifests
151 checking manifests
152 crosschecking files in changesets and manifests
152 crosschecking files in changesets and manifests
153 checking files
153 checking files
154 4 files, 9 changesets, 7 total revisions
154 4 files, 9 changesets, 7 total revisions
155 $ hg rollback
155 $ hg rollback
156 repository tip rolled back to revision 4 (undo pull)
156 repository tip rolled back to revision 4 (undo pull)
157 $ cd ..
157 $ cd ..
158
158
159 should fail
159 should fail
160
160
161 $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg test-3
161 $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg test-3
162 abort: --base is incompatible with specifying a destination
162 abort: --base is incompatible with specifying a destination
163 [255]
163 [255]
164 $ hg -R test bundle -a -r tip test-bundle-branch1.hg test-3
164 $ hg -R test bundle -a -r tip test-bundle-branch1.hg test-3
165 abort: --all is incompatible with specifying a destination
165 abort: --all is incompatible with specifying a destination
166 [255]
166 [255]
167 $ hg -R test bundle -r tip test-bundle-branch1.hg
167 $ hg -R test bundle -r tip test-bundle-branch1.hg
168 abort: repository default-push not found!
168 abort: repository default-push not found!
169 [255]
169 [255]
170
170
171 $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg
171 $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg
172 2 changesets found
172 2 changesets found
173 $ hg -R test bundle --base 2 -r 7 test-bundle-branch2.hg
173 $ hg -R test bundle --base 2 -r 7 test-bundle-branch2.hg
174 4 changesets found
174 4 changesets found
175 $ hg -R test bundle --base 2 test-bundle-all.hg
175 $ hg -R test bundle --base 2 test-bundle-all.hg
176 6 changesets found
176 6 changesets found
177 $ hg -R test bundle --base 2 --all test-bundle-all-2.hg
178 ignoring --base because --all was specified
179 9 changesets found
177 $ hg -R test bundle --base 3 -r tip test-bundle-should-fail.hg
180 $ hg -R test bundle --base 3 -r tip test-bundle-should-fail.hg
178 1 changesets found
181 1 changesets found
179
182
180 empty bundle
183 empty bundle
181
184
182 $ hg -R test bundle --base 7 --base 8 test-bundle-empty.hg
185 $ hg -R test bundle --base 7 --base 8 test-bundle-empty.hg
183 no changes found
186 no changes found
184 [1]
187 [1]
185
188
186 issue76 msg2163
189 issue76 msg2163
187
190
188 $ hg -R test bundle --base 3 -r 3 -r 3 test-bundle-cset-3.hg
191 $ hg -R test bundle --base 3 -r 3 -r 3 test-bundle-cset-3.hg
189 no changes found
192 no changes found
190 [1]
193 [1]
191
194
192 Issue1910: 'hg bundle --base $head' does not exclude $head from
195 Issue1910: 'hg bundle --base $head' does not exclude $head from
193 result
196 result
194
197
195 $ hg -R test bundle --base 7 test-bundle-cset-7.hg
198 $ hg -R test bundle --base 7 test-bundle-cset-7.hg
196 4 changesets found
199 4 changesets found
197
200
198 $ hg clone test-2 test-9
201 $ hg clone test-2 test-9
199 updating to branch default
202 updating to branch default
200 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
201 $ cd test-9
204 $ cd test-9
202
205
203 revision 2
206 revision 2
204
207
205 $ hg tip -q
208 $ hg tip -q
206 2:4ce51a113780
209 2:4ce51a113780
207 $ hg unbundle ../test-bundle-should-fail.hg
210 $ hg unbundle ../test-bundle-should-fail.hg
208 adding changesets
211 adding changesets
209 transaction abort!
212 transaction abort!
210 rollback completed
213 rollback completed
211 abort: 00changelog.i@93ee6ab32777: unknown parent!
214 abort: 00changelog.i@93ee6ab32777: unknown parent!
212 [255]
215 [255]
213
216
214 revision 2
217 revision 2
215
218
216 $ hg tip -q
219 $ hg tip -q
217 2:4ce51a113780
220 2:4ce51a113780
218 $ hg unbundle ../test-bundle-all.hg
221 $ hg unbundle ../test-bundle-all.hg
219 adding changesets
222 adding changesets
220 adding manifests
223 adding manifests
221 adding file changes
224 adding file changes
222 added 6 changesets with 4 changes to 4 files (+1 heads)
225 added 6 changesets with 4 changes to 4 files (+1 heads)
223 (run 'hg heads' to see heads, 'hg merge' to merge)
226 (run 'hg heads' to see heads, 'hg merge' to merge)
224
227
225 revision 8
228 revision 8
226
229
227 $ hg tip -q
230 $ hg tip -q
228 8:916f1afdef90
231 8:916f1afdef90
229 $ hg verify
232 $ hg verify
230 checking changesets
233 checking changesets
231 checking manifests
234 checking manifests
232 crosschecking files in changesets and manifests
235 crosschecking files in changesets and manifests
233 checking files
236 checking files
234 4 files, 9 changesets, 7 total revisions
237 4 files, 9 changesets, 7 total revisions
235 $ hg rollback
238 $ hg rollback
236 repository tip rolled back to revision 2 (undo unbundle)
239 repository tip rolled back to revision 2 (undo unbundle)
237
240
238 revision 2
241 revision 2
239
242
240 $ hg tip -q
243 $ hg tip -q
241 2:4ce51a113780
244 2:4ce51a113780
242 $ hg unbundle ../test-bundle-branch1.hg
245 $ hg unbundle ../test-bundle-branch1.hg
243 adding changesets
246 adding changesets
244 adding manifests
247 adding manifests
245 adding file changes
248 adding file changes
246 added 2 changesets with 2 changes to 2 files
249 added 2 changesets with 2 changes to 2 files
247 (run 'hg update' to get a working copy)
250 (run 'hg update' to get a working copy)
248
251
249 revision 4
252 revision 4
250
253
251 $ hg tip -q
254 $ hg tip -q
252 4:916f1afdef90
255 4:916f1afdef90
253 $ hg verify
256 $ hg verify
254 checking changesets
257 checking changesets
255 checking manifests
258 checking manifests
256 crosschecking files in changesets and manifests
259 crosschecking files in changesets and manifests
257 checking files
260 checking files
258 2 files, 5 changesets, 5 total revisions
261 2 files, 5 changesets, 5 total revisions
259 $ hg rollback
262 $ hg rollback
260 repository tip rolled back to revision 2 (undo unbundle)
263 repository tip rolled back to revision 2 (undo unbundle)
261 $ hg unbundle ../test-bundle-branch2.hg
264 $ hg unbundle ../test-bundle-branch2.hg
262 adding changesets
265 adding changesets
263 adding manifests
266 adding manifests
264 adding file changes
267 adding file changes
265 added 4 changesets with 3 changes to 3 files (+1 heads)
268 added 4 changesets with 3 changes to 3 files (+1 heads)
266 (run 'hg heads' to see heads, 'hg merge' to merge)
269 (run 'hg heads' to see heads, 'hg merge' to merge)
267
270
268 revision 6
271 revision 6
269
272
270 $ hg tip -q
273 $ hg tip -q
271 6:faa2e4234c7a
274 6:faa2e4234c7a
272 $ hg verify
275 $ hg verify
273 checking changesets
276 checking changesets
274 checking manifests
277 checking manifests
275 crosschecking files in changesets and manifests
278 crosschecking files in changesets and manifests
276 checking files
279 checking files
277 3 files, 7 changesets, 6 total revisions
280 3 files, 7 changesets, 6 total revisions
278 $ hg rollback
281 $ hg rollback
279 repository tip rolled back to revision 2 (undo unbundle)
282 repository tip rolled back to revision 2 (undo unbundle)
280 $ hg unbundle ../test-bundle-cset-7.hg
283 $ hg unbundle ../test-bundle-cset-7.hg
281 adding changesets
284 adding changesets
282 adding manifests
285 adding manifests
283 adding file changes
286 adding file changes
284 added 2 changesets with 2 changes to 2 files
287 added 2 changesets with 2 changes to 2 files
285 (run 'hg update' to get a working copy)
288 (run 'hg update' to get a working copy)
286
289
287 revision 4
290 revision 4
288
291
289 $ hg tip -q
292 $ hg tip -q
290 4:916f1afdef90
293 4:916f1afdef90
291 $ hg verify
294 $ hg verify
292 checking changesets
295 checking changesets
293 checking manifests
296 checking manifests
294 crosschecking files in changesets and manifests
297 crosschecking files in changesets and manifests
295 checking files
298 checking files
296 2 files, 5 changesets, 5 total revisions
299 2 files, 5 changesets, 5 total revisions
297
300
298 $ cd ../test
301 $ cd ../test
299 $ hg merge 7
302 $ hg merge 7
300 note: possible conflict - afile was renamed multiple times to:
303 note: possible conflict - afile was renamed multiple times to:
301 anotherfile
304 anotherfile
302 adifferentfile
305 adifferentfile
303 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
306 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
304 (branch merge, don't forget to commit)
307 (branch merge, don't forget to commit)
305 $ hg ci -m merge
308 $ hg ci -m merge
306 $ cd ..
309 $ cd ..
307 $ hg -R test bundle --base 2 test-bundle-head.hg
310 $ hg -R test bundle --base 2 test-bundle-head.hg
308 7 changesets found
311 7 changesets found
309 $ hg clone test-2 test-10
312 $ hg clone test-2 test-10
310 updating to branch default
313 updating to branch default
311 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
312 $ cd test-10
315 $ cd test-10
313 $ hg unbundle ../test-bundle-head.hg
316 $ hg unbundle ../test-bundle-head.hg
314 adding changesets
317 adding changesets
315 adding manifests
318 adding manifests
316 adding file changes
319 adding file changes
317 added 7 changesets with 4 changes to 4 files
320 added 7 changesets with 4 changes to 4 files
318 (run 'hg update' to get a working copy)
321 (run 'hg update' to get a working copy)
319
322
320 revision 9
323 revision 9
321
324
322 $ hg tip -q
325 $ hg tip -q
323 9:03fc0b0e347c
326 9:03fc0b0e347c
324 $ hg verify
327 $ hg verify
325 checking changesets
328 checking changesets
326 checking manifests
329 checking manifests
327 crosschecking files in changesets and manifests
330 crosschecking files in changesets and manifests
328 checking files
331 checking files
329 4 files, 10 changesets, 7 total revisions
332 4 files, 10 changesets, 7 total revisions
330
333
331 $ cd ..
334 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now