##// END OF EJS Templates
commands: split notes into note containers
timeless -
r27490:fe376159 default
parent child Browse files
Show More
@@ -1,6997 +1,7005 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 (except
196 If no names are given, add all files to the repository (except
197 files matching ``.hgignore``).
197 files matching ``.hgignore``).
198
198
199 .. container:: verbose
199 .. container:: verbose
200
200
201 Examples:
201 Examples:
202
202
203 - New (unknown) files are added
203 - New (unknown) files are added
204 automatically by :hg:`add`::
204 automatically by :hg:`add`::
205
205
206 $ ls
206 $ ls
207 foo.c
207 foo.c
208 $ hg status
208 $ hg status
209 ? foo.c
209 ? foo.c
210 $ hg add
210 $ hg add
211 adding foo.c
211 adding foo.c
212 $ hg status
212 $ hg status
213 A foo.c
213 A foo.c
214
214
215 - Specific files to be added can be specified::
215 - Specific files to be added can be specified::
216
216
217 $ ls
217 $ ls
218 bar.c foo.c
218 bar.c foo.c
219 $ hg status
219 $ hg status
220 ? bar.c
220 ? bar.c
221 ? foo.c
221 ? foo.c
222 $ hg add bar.c
222 $ hg add bar.c
223 $ hg status
223 $ hg status
224 A bar.c
224 A bar.c
225 ? foo.c
225 ? foo.c
226
226
227 Returns 0 if all files are successfully added.
227 Returns 0 if all files are successfully added.
228 """
228 """
229
229
230 m = scmutil.match(repo[None], pats, opts)
230 m = scmutil.match(repo[None], pats, opts)
231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
232 return rejected and 1 or 0
232 return rejected and 1 or 0
233
233
234 @command('addremove',
234 @command('addremove',
235 similarityopts + subrepoopts + walkopts + dryrunopts,
235 similarityopts + subrepoopts + walkopts + dryrunopts,
236 _('[OPTION]... [FILE]...'),
236 _('[OPTION]... [FILE]...'),
237 inferrepo=True)
237 inferrepo=True)
238 def addremove(ui, repo, *pats, **opts):
238 def addremove(ui, repo, *pats, **opts):
239 """add all new files, delete all missing files
239 """add all new files, delete all missing files
240
240
241 Add all new files and remove all missing files from the
241 Add all new files and remove all missing files from the
242 repository.
242 repository.
243
243
244 Unless names are given, new files are ignored if they match any of
244 Unless names are given, new files are ignored if they match any of
245 the patterns in ``.hgignore``. As with add, these changes take
245 the patterns in ``.hgignore``. As with add, these changes take
246 effect at the next commit.
246 effect at the next commit.
247
247
248 Use the -s/--similarity option to detect renamed files. This
248 Use the -s/--similarity option to detect renamed files. This
249 option takes a percentage between 0 (disabled) and 100 (files must
249 option takes a percentage between 0 (disabled) and 100 (files must
250 be identical) as its parameter. With a parameter greater than 0,
250 be identical) as its parameter. With a parameter greater than 0,
251 this compares every removed file with every added file and records
251 this compares every removed file with every added file and records
252 those similar enough as renames. Detecting renamed files this way
252 those similar enough as renames. Detecting renamed files this way
253 can be expensive. After using this option, :hg:`status -C` can be
253 can be expensive. After using this option, :hg:`status -C` can be
254 used to check which files were identified as moved or renamed. If
254 used to check which files were identified as moved or renamed. If
255 not specified, -s/--similarity defaults to 100 and only renames of
255 not specified, -s/--similarity defaults to 100 and only renames of
256 identical files are detected.
256 identical files are detected.
257
257
258 .. container:: verbose
258 .. container:: verbose
259
259
260 Examples:
260 Examples:
261
261
262 - A number of files (bar.c and foo.c) are new,
262 - A number of files (bar.c and foo.c) are new,
263 while foobar.c has been removed (without using :hg:`remove`)
263 while foobar.c has been removed (without using :hg:`remove`)
264 from the repository::
264 from the repository::
265
265
266 $ ls
266 $ ls
267 bar.c foo.c
267 bar.c foo.c
268 $ hg status
268 $ hg status
269 ! foobar.c
269 ! foobar.c
270 ? bar.c
270 ? bar.c
271 ? foo.c
271 ? foo.c
272 $ hg addremove
272 $ hg addremove
273 adding bar.c
273 adding bar.c
274 adding foo.c
274 adding foo.c
275 removing foobar.c
275 removing foobar.c
276 $ hg status
276 $ hg status
277 A bar.c
277 A bar.c
278 A foo.c
278 A foo.c
279 R foobar.c
279 R foobar.c
280
280
281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
282 Afterwards, it was edited slightly::
282 Afterwards, it was edited slightly::
283
283
284 $ ls
284 $ ls
285 foo.c
285 foo.c
286 $ hg status
286 $ hg status
287 ! foobar.c
287 ! foobar.c
288 ? foo.c
288 ? foo.c
289 $ hg addremove --similarity 90
289 $ hg addremove --similarity 90
290 removing foobar.c
290 removing foobar.c
291 adding foo.c
291 adding foo.c
292 recording removal of foobar.c as rename to foo.c (94% similar)
292 recording removal of foobar.c as rename to foo.c (94% similar)
293 $ hg status -C
293 $ hg status -C
294 A foo.c
294 A foo.c
295 foobar.c
295 foobar.c
296 R foobar.c
296 R foobar.c
297
297
298 Returns 0 if all files are successfully added.
298 Returns 0 if all files are successfully added.
299 """
299 """
300 try:
300 try:
301 sim = float(opts.get('similarity') or 100)
301 sim = float(opts.get('similarity') or 100)
302 except ValueError:
302 except ValueError:
303 raise error.Abort(_('similarity must be a number'))
303 raise error.Abort(_('similarity must be a number'))
304 if sim < 0 or sim > 100:
304 if sim < 0 or sim > 100:
305 raise error.Abort(_('similarity must be between 0 and 100'))
305 raise error.Abort(_('similarity must be between 0 and 100'))
306 matcher = scmutil.match(repo[None], pats, opts)
306 matcher = scmutil.match(repo[None], pats, opts)
307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
308
308
309 @command('^annotate|blame',
309 @command('^annotate|blame',
310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
311 ('', 'follow', None,
311 ('', 'follow', None,
312 _('follow copies/renames and list the filename (DEPRECATED)')),
312 _('follow copies/renames and list the filename (DEPRECATED)')),
313 ('', 'no-follow', None, _("don't follow copies and renames")),
313 ('', 'no-follow', None, _("don't follow copies and renames")),
314 ('a', 'text', None, _('treat all files as text')),
314 ('a', 'text', None, _('treat all files as text')),
315 ('u', 'user', None, _('list the author (long with -v)')),
315 ('u', 'user', None, _('list the author (long with -v)')),
316 ('f', 'file', None, _('list the filename')),
316 ('f', 'file', None, _('list the filename')),
317 ('d', 'date', None, _('list the date (short with -q)')),
317 ('d', 'date', None, _('list the date (short with -q)')),
318 ('n', 'number', None, _('list the revision number (default)')),
318 ('n', 'number', None, _('list the revision number (default)')),
319 ('c', 'changeset', None, _('list the changeset')),
319 ('c', 'changeset', None, _('list the changeset')),
320 ('l', 'line-number', None, _('show line number at the first appearance'))
320 ('l', 'line-number', None, _('show line number at the first appearance'))
321 ] + diffwsopts + walkopts + formatteropts,
321 ] + diffwsopts + walkopts + formatteropts,
322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
323 inferrepo=True)
323 inferrepo=True)
324 def annotate(ui, repo, *pats, **opts):
324 def annotate(ui, repo, *pats, **opts):
325 """show changeset information by line for each file
325 """show changeset information by line for each file
326
326
327 List changes in files, showing the revision id responsible for
327 List changes in files, showing the revision id responsible for
328 each line.
328 each line.
329
329
330 This command is useful for discovering when a change was made and
330 This command is useful for discovering when a change was made and
331 by whom.
331 by whom.
332
332
333 Without the -a/--text option, annotate will avoid processing files
333 Without the -a/--text option, annotate will avoid processing files
334 it detects as binary. With -a, annotate will annotate the file
334 it detects as binary. With -a, annotate will annotate the file
335 anyway, although the results will probably be neither useful
335 anyway, although the results will probably be neither useful
336 nor desirable.
336 nor desirable.
337
337
338 Returns 0 on success.
338 Returns 0 on success.
339 """
339 """
340 if not pats:
340 if not pats:
341 raise error.Abort(_('at least one filename or pattern is required'))
341 raise error.Abort(_('at least one filename or pattern is required'))
342
342
343 if opts.get('follow'):
343 if opts.get('follow'):
344 # --follow is deprecated and now just an alias for -f/--file
344 # --follow is deprecated and now just an alias for -f/--file
345 # to mimic the behavior of Mercurial before version 1.5
345 # to mimic the behavior of Mercurial before version 1.5
346 opts['file'] = True
346 opts['file'] = True
347
347
348 ctx = scmutil.revsingle(repo, opts.get('rev'))
348 ctx = scmutil.revsingle(repo, opts.get('rev'))
349
349
350 fm = ui.formatter('annotate', opts)
350 fm = ui.formatter('annotate', opts)
351 if ui.quiet:
351 if ui.quiet:
352 datefunc = util.shortdate
352 datefunc = util.shortdate
353 else:
353 else:
354 datefunc = util.datestr
354 datefunc = util.datestr
355 if ctx.rev() is None:
355 if ctx.rev() is None:
356 def hexfn(node):
356 def hexfn(node):
357 if node is None:
357 if node is None:
358 return None
358 return None
359 else:
359 else:
360 return fm.hexfunc(node)
360 return fm.hexfunc(node)
361 if opts.get('changeset'):
361 if opts.get('changeset'):
362 # omit "+" suffix which is appended to node hex
362 # omit "+" suffix which is appended to node hex
363 def formatrev(rev):
363 def formatrev(rev):
364 if rev is None:
364 if rev is None:
365 return '%d' % ctx.p1().rev()
365 return '%d' % ctx.p1().rev()
366 else:
366 else:
367 return '%d' % rev
367 return '%d' % rev
368 else:
368 else:
369 def formatrev(rev):
369 def formatrev(rev):
370 if rev is None:
370 if rev is None:
371 return '%d+' % ctx.p1().rev()
371 return '%d+' % ctx.p1().rev()
372 else:
372 else:
373 return '%d ' % rev
373 return '%d ' % rev
374 def formathex(hex):
374 def formathex(hex):
375 if hex is None:
375 if hex is None:
376 return '%s+' % fm.hexfunc(ctx.p1().node())
376 return '%s+' % fm.hexfunc(ctx.p1().node())
377 else:
377 else:
378 return '%s ' % hex
378 return '%s ' % hex
379 else:
379 else:
380 hexfn = fm.hexfunc
380 hexfn = fm.hexfunc
381 formatrev = formathex = str
381 formatrev = formathex = str
382
382
383 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
383 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
384 ('number', ' ', lambda x: x[0].rev(), formatrev),
384 ('number', ' ', lambda x: x[0].rev(), formatrev),
385 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
385 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
386 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
386 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
387 ('file', ' ', lambda x: x[0].path(), str),
387 ('file', ' ', lambda x: x[0].path(), str),
388 ('line_number', ':', lambda x: x[1], str),
388 ('line_number', ':', lambda x: x[1], str),
389 ]
389 ]
390 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
390 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
391
391
392 if (not opts.get('user') and not opts.get('changeset')
392 if (not opts.get('user') and not opts.get('changeset')
393 and not opts.get('date') and not opts.get('file')):
393 and not opts.get('date') and not opts.get('file')):
394 opts['number'] = True
394 opts['number'] = True
395
395
396 linenumber = opts.get('line_number') is not None
396 linenumber = opts.get('line_number') is not None
397 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
397 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
398 raise error.Abort(_('at least one of -n/-c is required for -l'))
398 raise error.Abort(_('at least one of -n/-c is required for -l'))
399
399
400 if fm:
400 if fm:
401 def makefunc(get, fmt):
401 def makefunc(get, fmt):
402 return get
402 return get
403 else:
403 else:
404 def makefunc(get, fmt):
404 def makefunc(get, fmt):
405 return lambda x: fmt(get(x))
405 return lambda x: fmt(get(x))
406 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
406 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
407 if opts.get(op)]
407 if opts.get(op)]
408 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
408 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
409 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
409 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
410 if opts.get(op))
410 if opts.get(op))
411
411
412 def bad(x, y):
412 def bad(x, y):
413 raise error.Abort("%s: %s" % (x, y))
413 raise error.Abort("%s: %s" % (x, y))
414
414
415 m = scmutil.match(ctx, pats, opts, badfn=bad)
415 m = scmutil.match(ctx, pats, opts, badfn=bad)
416
416
417 follow = not opts.get('no_follow')
417 follow = not opts.get('no_follow')
418 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
418 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
419 whitespace=True)
419 whitespace=True)
420 for abs in ctx.walk(m):
420 for abs in ctx.walk(m):
421 fctx = ctx[abs]
421 fctx = ctx[abs]
422 if not opts.get('text') and util.binary(fctx.data()):
422 if not opts.get('text') and util.binary(fctx.data()):
423 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
423 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
424 continue
424 continue
425
425
426 lines = fctx.annotate(follow=follow, linenumber=linenumber,
426 lines = fctx.annotate(follow=follow, linenumber=linenumber,
427 diffopts=diffopts)
427 diffopts=diffopts)
428 formats = []
428 formats = []
429 pieces = []
429 pieces = []
430
430
431 for f, sep in funcmap:
431 for f, sep in funcmap:
432 l = [f(n) for n, dummy in lines]
432 l = [f(n) for n, dummy in lines]
433 if l:
433 if l:
434 if fm:
434 if fm:
435 formats.append(['%s' for x in l])
435 formats.append(['%s' for x in l])
436 else:
436 else:
437 sizes = [encoding.colwidth(x) for x in l]
437 sizes = [encoding.colwidth(x) for x in l]
438 ml = max(sizes)
438 ml = max(sizes)
439 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
439 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
440 pieces.append(l)
440 pieces.append(l)
441
441
442 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
442 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
443 fm.startitem()
443 fm.startitem()
444 fm.write(fields, "".join(f), *p)
444 fm.write(fields, "".join(f), *p)
445 fm.write('line', ": %s", l[1])
445 fm.write('line', ": %s", l[1])
446
446
447 if lines and not lines[-1][1].endswith('\n'):
447 if lines and not lines[-1][1].endswith('\n'):
448 fm.plain('\n')
448 fm.plain('\n')
449
449
450 fm.end()
450 fm.end()
451
451
452 @command('archive',
452 @command('archive',
453 [('', 'no-decode', None, _('do not pass files through decoders')),
453 [('', 'no-decode', None, _('do not pass files through decoders')),
454 ('p', 'prefix', '', _('directory prefix for files in archive'),
454 ('p', 'prefix', '', _('directory prefix for files in archive'),
455 _('PREFIX')),
455 _('PREFIX')),
456 ('r', 'rev', '', _('revision to distribute'), _('REV')),
456 ('r', 'rev', '', _('revision to distribute'), _('REV')),
457 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
457 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
458 ] + subrepoopts + walkopts,
458 ] + subrepoopts + walkopts,
459 _('[OPTION]... DEST'))
459 _('[OPTION]... DEST'))
460 def archive(ui, repo, dest, **opts):
460 def archive(ui, repo, dest, **opts):
461 '''create an unversioned archive of a repository revision
461 '''create an unversioned archive of a repository revision
462
462
463 By default, the revision used is the parent of the working
463 By default, the revision used is the parent of the working
464 directory; use -r/--rev to specify a different revision.
464 directory; use -r/--rev to specify a different revision.
465
465
466 The archive type is automatically detected based on file
466 The archive type is automatically detected based on file
467 extension (to override, use -t/--type).
467 extension (to override, use -t/--type).
468
468
469 .. container:: verbose
469 .. container:: verbose
470
470
471 Examples:
471 Examples:
472
472
473 - create a zip file containing the 1.0 release::
473 - create a zip file containing the 1.0 release::
474
474
475 hg archive -r 1.0 project-1.0.zip
475 hg archive -r 1.0 project-1.0.zip
476
476
477 - create a tarball excluding .hg files::
477 - create a tarball excluding .hg files::
478
478
479 hg archive project.tar.gz -X ".hg*"
479 hg archive project.tar.gz -X ".hg*"
480
480
481 Valid types are:
481 Valid types are:
482
482
483 :``files``: a directory full of files (default)
483 :``files``: a directory full of files (default)
484 :``tar``: tar archive, uncompressed
484 :``tar``: tar archive, uncompressed
485 :``tbz2``: tar archive, compressed using bzip2
485 :``tbz2``: tar archive, compressed using bzip2
486 :``tgz``: tar archive, compressed using gzip
486 :``tgz``: tar archive, compressed using gzip
487 :``uzip``: zip archive, uncompressed
487 :``uzip``: zip archive, uncompressed
488 :``zip``: zip archive, compressed using deflate
488 :``zip``: zip archive, compressed using deflate
489
489
490 The exact name of the destination archive or directory is given
490 The exact name of the destination archive or directory is given
491 using a format string; see :hg:`help export` for details.
491 using a format string; see :hg:`help export` for details.
492
492
493 Each member added to an archive file has a directory prefix
493 Each member added to an archive file has a directory prefix
494 prepended. Use -p/--prefix to specify a format string for the
494 prepended. Use -p/--prefix to specify a format string for the
495 prefix. The default is the basename of the archive, with suffixes
495 prefix. The default is the basename of the archive, with suffixes
496 removed.
496 removed.
497
497
498 Returns 0 on success.
498 Returns 0 on success.
499 '''
499 '''
500
500
501 ctx = scmutil.revsingle(repo, opts.get('rev'))
501 ctx = scmutil.revsingle(repo, opts.get('rev'))
502 if not ctx:
502 if not ctx:
503 raise error.Abort(_('no working directory: please specify a revision'))
503 raise error.Abort(_('no working directory: please specify a revision'))
504 node = ctx.node()
504 node = ctx.node()
505 dest = cmdutil.makefilename(repo, dest, node)
505 dest = cmdutil.makefilename(repo, dest, node)
506 if os.path.realpath(dest) == repo.root:
506 if os.path.realpath(dest) == repo.root:
507 raise error.Abort(_('repository root cannot be destination'))
507 raise error.Abort(_('repository root cannot be destination'))
508
508
509 kind = opts.get('type') or archival.guesskind(dest) or 'files'
509 kind = opts.get('type') or archival.guesskind(dest) or 'files'
510 prefix = opts.get('prefix')
510 prefix = opts.get('prefix')
511
511
512 if dest == '-':
512 if dest == '-':
513 if kind == 'files':
513 if kind == 'files':
514 raise error.Abort(_('cannot archive plain files to stdout'))
514 raise error.Abort(_('cannot archive plain files to stdout'))
515 dest = cmdutil.makefileobj(repo, dest)
515 dest = cmdutil.makefileobj(repo, dest)
516 if not prefix:
516 if not prefix:
517 prefix = os.path.basename(repo.root) + '-%h'
517 prefix = os.path.basename(repo.root) + '-%h'
518
518
519 prefix = cmdutil.makefilename(repo, prefix, node)
519 prefix = cmdutil.makefilename(repo, prefix, node)
520 matchfn = scmutil.match(ctx, [], opts)
520 matchfn = scmutil.match(ctx, [], opts)
521 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
521 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
522 matchfn, prefix, subrepos=opts.get('subrepos'))
522 matchfn, prefix, subrepos=opts.get('subrepos'))
523
523
524 @command('backout',
524 @command('backout',
525 [('', 'merge', None, _('merge with old dirstate parent after backout')),
525 [('', 'merge', None, _('merge with old dirstate parent after backout')),
526 ('', 'commit', None, _('commit if no conflicts were encountered')),
526 ('', 'commit', None, _('commit if no conflicts were encountered')),
527 ('', 'parent', '',
527 ('', 'parent', '',
528 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
528 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
529 ('r', 'rev', '', _('revision to backout'), _('REV')),
529 ('r', 'rev', '', _('revision to backout'), _('REV')),
530 ('e', 'edit', False, _('invoke editor on commit messages')),
530 ('e', 'edit', False, _('invoke editor on commit messages')),
531 ] + mergetoolopts + walkopts + commitopts + commitopts2,
531 ] + mergetoolopts + walkopts + commitopts + commitopts2,
532 _('[OPTION]... [-r] REV'))
532 _('[OPTION]... [-r] REV'))
533 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
533 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
534 '''reverse effect of earlier changeset
534 '''reverse effect of earlier changeset
535
535
536 Prepare a new changeset with the effect of REV undone in the
536 Prepare a new changeset with the effect of REV undone in the
537 current working directory.
537 current working directory.
538
538
539 If REV is the parent of the working directory, then this new changeset
539 If REV is the parent of the working directory, then this new changeset
540 is committed automatically. Otherwise, hg needs to merge the
540 is committed automatically. Otherwise, hg needs to merge the
541 changes and the merged result is left uncommitted.
541 changes and the merged result is left uncommitted.
542
542
543 .. note::
543 .. note::
544
544
545 :hg:`backout` cannot be used to fix either an unwanted or
545 :hg:`backout` cannot be used to fix either an unwanted or
546 incorrect merge.
546 incorrect merge.
547
547
548 .. container:: verbose
548 .. container:: verbose
549
549
550 Examples:
550 Examples:
551
551
552 - Reverse the effect of the parent of the working directory.
552 - Reverse the effect of the parent of the working directory.
553 This backout will be committed immediately::
553 This backout will be committed immediately::
554
554
555 hg backout -r .
555 hg backout -r .
556
556
557 - Reverse the effect of previous bad revision 23::
557 - Reverse the effect of previous bad revision 23::
558
558
559 hg backout -r 23
559 hg backout -r 23
560 hg commit -m "Backout revision 23"
560 hg commit -m "Backout revision 23"
561
561
562 - Reverse the effect of previous bad revision 23 and
562 - Reverse the effect of previous bad revision 23 and
563 commit the backout immediately::
563 commit the backout immediately::
564
564
565 hg backout -r 23 --commit
565 hg backout -r 23 --commit
566
566
567 By default, the pending changeset will have one parent,
567 By default, the pending changeset will have one parent,
568 maintaining a linear history. With --merge, the pending
568 maintaining a linear history. With --merge, the pending
569 changeset will instead have two parents: the old parent of the
569 changeset will instead have two parents: the old parent of the
570 working directory and a new child of REV that simply undoes REV.
570 working directory and a new child of REV that simply undoes REV.
571
571
572 Before version 1.7, the behavior without --merge was equivalent
572 Before version 1.7, the behavior without --merge was equivalent
573 to specifying --merge followed by :hg:`update --clean .` to
573 to specifying --merge followed by :hg:`update --clean .` to
574 cancel the merge and leave the child of REV as a head to be
574 cancel the merge and leave the child of REV as a head to be
575 merged separately.
575 merged separately.
576
576
577 See :hg:`help dates` for a list of formats valid for -d/--date.
577 See :hg:`help dates` for a list of formats valid for -d/--date.
578
578
579 See :hg:`help revert` for a way to restore files to the state
579 See :hg:`help revert` for a way to restore files to the state
580 of another revision.
580 of another revision.
581
581
582 Returns 0 on success, 1 if nothing to backout or there are unresolved
582 Returns 0 on success, 1 if nothing to backout or there are unresolved
583 files.
583 files.
584 '''
584 '''
585 wlock = lock = None
585 wlock = lock = None
586 try:
586 try:
587 wlock = repo.wlock()
587 wlock = repo.wlock()
588 lock = repo.lock()
588 lock = repo.lock()
589 return _dobackout(ui, repo, node, rev, commit, **opts)
589 return _dobackout(ui, repo, node, rev, commit, **opts)
590 finally:
590 finally:
591 release(lock, wlock)
591 release(lock, wlock)
592
592
593 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
593 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
594 if rev and node:
594 if rev and node:
595 raise error.Abort(_("please specify just one revision"))
595 raise error.Abort(_("please specify just one revision"))
596
596
597 if not rev:
597 if not rev:
598 rev = node
598 rev = node
599
599
600 if not rev:
600 if not rev:
601 raise error.Abort(_("please specify a revision to backout"))
601 raise error.Abort(_("please specify a revision to backout"))
602
602
603 date = opts.get('date')
603 date = opts.get('date')
604 if date:
604 if date:
605 opts['date'] = util.parsedate(date)
605 opts['date'] = util.parsedate(date)
606
606
607 cmdutil.checkunfinished(repo)
607 cmdutil.checkunfinished(repo)
608 cmdutil.bailifchanged(repo)
608 cmdutil.bailifchanged(repo)
609 node = scmutil.revsingle(repo, rev).node()
609 node = scmutil.revsingle(repo, rev).node()
610
610
611 op1, op2 = repo.dirstate.parents()
611 op1, op2 = repo.dirstate.parents()
612 if not repo.changelog.isancestor(node, op1):
612 if not repo.changelog.isancestor(node, op1):
613 raise error.Abort(_('cannot backout change that is not an ancestor'))
613 raise error.Abort(_('cannot backout change that is not an ancestor'))
614
614
615 p1, p2 = repo.changelog.parents(node)
615 p1, p2 = repo.changelog.parents(node)
616 if p1 == nullid:
616 if p1 == nullid:
617 raise error.Abort(_('cannot backout a change with no parents'))
617 raise error.Abort(_('cannot backout a change with no parents'))
618 if p2 != nullid:
618 if p2 != nullid:
619 if not opts.get('parent'):
619 if not opts.get('parent'):
620 raise error.Abort(_('cannot backout a merge changeset'))
620 raise error.Abort(_('cannot backout a merge changeset'))
621 p = repo.lookup(opts['parent'])
621 p = repo.lookup(opts['parent'])
622 if p not in (p1, p2):
622 if p not in (p1, p2):
623 raise error.Abort(_('%s is not a parent of %s') %
623 raise error.Abort(_('%s is not a parent of %s') %
624 (short(p), short(node)))
624 (short(p), short(node)))
625 parent = p
625 parent = p
626 else:
626 else:
627 if opts.get('parent'):
627 if opts.get('parent'):
628 raise error.Abort(_('cannot use --parent on non-merge changeset'))
628 raise error.Abort(_('cannot use --parent on non-merge changeset'))
629 parent = p1
629 parent = p1
630
630
631 # the backout should appear on the same branch
631 # the backout should appear on the same branch
632 try:
632 try:
633 branch = repo.dirstate.branch()
633 branch = repo.dirstate.branch()
634 bheads = repo.branchheads(branch)
634 bheads = repo.branchheads(branch)
635 rctx = scmutil.revsingle(repo, hex(parent))
635 rctx = scmutil.revsingle(repo, hex(parent))
636 if not opts.get('merge') and op1 != node:
636 if not opts.get('merge') and op1 != node:
637 dsguard = cmdutil.dirstateguard(repo, 'backout')
637 dsguard = cmdutil.dirstateguard(repo, 'backout')
638 try:
638 try:
639 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
639 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
640 'backout')
640 'backout')
641 stats = mergemod.update(repo, parent, True, True, node, False)
641 stats = mergemod.update(repo, parent, True, True, node, False)
642 repo.setparents(op1, op2)
642 repo.setparents(op1, op2)
643 dsguard.close()
643 dsguard.close()
644 hg._showstats(repo, stats)
644 hg._showstats(repo, stats)
645 if stats[3]:
645 if stats[3]:
646 repo.ui.status(_("use 'hg resolve' to retry unresolved "
646 repo.ui.status(_("use 'hg resolve' to retry unresolved "
647 "file merges\n"))
647 "file merges\n"))
648 return 1
648 return 1
649 elif not commit:
649 elif not commit:
650 msg = _("changeset %s backed out, "
650 msg = _("changeset %s backed out, "
651 "don't forget to commit.\n")
651 "don't forget to commit.\n")
652 ui.status(msg % short(node))
652 ui.status(msg % short(node))
653 return 0
653 return 0
654 finally:
654 finally:
655 ui.setconfig('ui', 'forcemerge', '', '')
655 ui.setconfig('ui', 'forcemerge', '', '')
656 lockmod.release(dsguard)
656 lockmod.release(dsguard)
657 else:
657 else:
658 hg.clean(repo, node, show_stats=False)
658 hg.clean(repo, node, show_stats=False)
659 repo.dirstate.setbranch(branch)
659 repo.dirstate.setbranch(branch)
660 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
660 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
661
661
662
662
663 def commitfunc(ui, repo, message, match, opts):
663 def commitfunc(ui, repo, message, match, opts):
664 editform = 'backout'
664 editform = 'backout'
665 e = cmdutil.getcommiteditor(editform=editform, **opts)
665 e = cmdutil.getcommiteditor(editform=editform, **opts)
666 if not message:
666 if not message:
667 # we don't translate commit messages
667 # we don't translate commit messages
668 message = "Backed out changeset %s" % short(node)
668 message = "Backed out changeset %s" % short(node)
669 e = cmdutil.getcommiteditor(edit=True, editform=editform)
669 e = cmdutil.getcommiteditor(edit=True, editform=editform)
670 return repo.commit(message, opts.get('user'), opts.get('date'),
670 return repo.commit(message, opts.get('user'), opts.get('date'),
671 match, editor=e)
671 match, editor=e)
672 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
672 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
673 if not newnode:
673 if not newnode:
674 ui.status(_("nothing changed\n"))
674 ui.status(_("nothing changed\n"))
675 return 1
675 return 1
676 cmdutil.commitstatus(repo, newnode, branch, bheads)
676 cmdutil.commitstatus(repo, newnode, branch, bheads)
677
677
678 def nice(node):
678 def nice(node):
679 return '%d:%s' % (repo.changelog.rev(node), short(node))
679 return '%d:%s' % (repo.changelog.rev(node), short(node))
680 ui.status(_('changeset %s backs out changeset %s\n') %
680 ui.status(_('changeset %s backs out changeset %s\n') %
681 (nice(repo.changelog.tip()), nice(node)))
681 (nice(repo.changelog.tip()), nice(node)))
682 if opts.get('merge') and op1 != node:
682 if opts.get('merge') and op1 != node:
683 hg.clean(repo, op1, show_stats=False)
683 hg.clean(repo, op1, show_stats=False)
684 ui.status(_('merging with changeset %s\n')
684 ui.status(_('merging with changeset %s\n')
685 % nice(repo.changelog.tip()))
685 % nice(repo.changelog.tip()))
686 try:
686 try:
687 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
687 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
688 'backout')
688 'backout')
689 return hg.merge(repo, hex(repo.changelog.tip()))
689 return hg.merge(repo, hex(repo.changelog.tip()))
690 finally:
690 finally:
691 ui.setconfig('ui', 'forcemerge', '', '')
691 ui.setconfig('ui', 'forcemerge', '', '')
692 finally:
692 finally:
693 # TODO: get rid of this meaningless try/finally enclosing.
693 # TODO: get rid of this meaningless try/finally enclosing.
694 # this is kept only to reduce changes in a patch.
694 # this is kept only to reduce changes in a patch.
695 pass
695 pass
696 return 0
696 return 0
697
697
698 @command('bisect',
698 @command('bisect',
699 [('r', 'reset', False, _('reset bisect state')),
699 [('r', 'reset', False, _('reset bisect state')),
700 ('g', 'good', False, _('mark changeset good')),
700 ('g', 'good', False, _('mark changeset good')),
701 ('b', 'bad', False, _('mark changeset bad')),
701 ('b', 'bad', False, _('mark changeset bad')),
702 ('s', 'skip', False, _('skip testing changeset')),
702 ('s', 'skip', False, _('skip testing changeset')),
703 ('e', 'extend', False, _('extend the bisect range')),
703 ('e', 'extend', False, _('extend the bisect range')),
704 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
704 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
705 ('U', 'noupdate', False, _('do not update to target'))],
705 ('U', 'noupdate', False, _('do not update to target'))],
706 _("[-gbsr] [-U] [-c CMD] [REV]"))
706 _("[-gbsr] [-U] [-c CMD] [REV]"))
707 def bisect(ui, repo, rev=None, extra=None, command=None,
707 def bisect(ui, repo, rev=None, extra=None, command=None,
708 reset=None, good=None, bad=None, skip=None, extend=None,
708 reset=None, good=None, bad=None, skip=None, extend=None,
709 noupdate=None):
709 noupdate=None):
710 """subdivision search of changesets
710 """subdivision search of changesets
711
711
712 This command helps to find changesets which introduce problems. To
712 This command helps to find changesets which introduce problems. To
713 use, mark the earliest changeset you know exhibits the problem as
713 use, mark the earliest changeset you know exhibits the problem as
714 bad, then mark the latest changeset which is free from the problem
714 bad, then mark the latest changeset which is free from the problem
715 as good. Bisect will update your working directory to a revision
715 as good. Bisect will update your working directory to a revision
716 for testing (unless the -U/--noupdate option is specified). Once
716 for testing (unless the -U/--noupdate option is specified). Once
717 you have performed tests, mark the working directory as good or
717 you have performed tests, mark the working directory as good or
718 bad, and bisect will either update to another candidate changeset
718 bad, and bisect will either update to another candidate changeset
719 or announce that it has found the bad revision.
719 or announce that it has found the bad revision.
720
720
721 As a shortcut, you can also use the revision argument to mark a
721 As a shortcut, you can also use the revision argument to mark a
722 revision as good or bad without checking it out first.
722 revision as good or bad without checking it out first.
723
723
724 If you supply a command, it will be used for automatic bisection.
724 If you supply a command, it will be used for automatic bisection.
725 The environment variable HG_NODE will contain the ID of the
725 The environment variable HG_NODE will contain the ID of the
726 changeset being tested. The exit status of the command will be
726 changeset being tested. The exit status of the command will be
727 used to mark revisions as good or bad: status 0 means good, 125
727 used to mark revisions as good or bad: status 0 means good, 125
728 means to skip the revision, 127 (command not found) will abort the
728 means to skip the revision, 127 (command not found) will abort the
729 bisection, and any other non-zero exit status means the revision
729 bisection, and any other non-zero exit status means the revision
730 is bad.
730 is bad.
731
731
732 .. container:: verbose
732 .. container:: verbose
733
733
734 Some examples:
734 Some examples:
735
735
736 - start a bisection with known bad revision 34, and good revision 12::
736 - start a bisection with known bad revision 34, and good revision 12::
737
737
738 hg bisect --bad 34
738 hg bisect --bad 34
739 hg bisect --good 12
739 hg bisect --good 12
740
740
741 - advance the current bisection by marking current revision as good or
741 - advance the current bisection by marking current revision as good or
742 bad::
742 bad::
743
743
744 hg bisect --good
744 hg bisect --good
745 hg bisect --bad
745 hg bisect --bad
746
746
747 - mark the current revision, or a known revision, to be skipped (e.g. if
747 - mark the current revision, or a known revision, to be skipped (e.g. if
748 that revision is not usable because of another issue)::
748 that revision is not usable because of another issue)::
749
749
750 hg bisect --skip
750 hg bisect --skip
751 hg bisect --skip 23
751 hg bisect --skip 23
752
752
753 - skip all revisions that do not touch directories ``foo`` or ``bar``::
753 - skip all revisions that do not touch directories ``foo`` or ``bar``::
754
754
755 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
755 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
756
756
757 - forget the current bisection::
757 - forget the current bisection::
758
758
759 hg bisect --reset
759 hg bisect --reset
760
760
761 - use 'make && make tests' to automatically find the first broken
761 - use 'make && make tests' to automatically find the first broken
762 revision::
762 revision::
763
763
764 hg bisect --reset
764 hg bisect --reset
765 hg bisect --bad 34
765 hg bisect --bad 34
766 hg bisect --good 12
766 hg bisect --good 12
767 hg bisect --command "make && make tests"
767 hg bisect --command "make && make tests"
768
768
769 - see all changesets whose states are already known in the current
769 - see all changesets whose states are already known in the current
770 bisection::
770 bisection::
771
771
772 hg log -r "bisect(pruned)"
772 hg log -r "bisect(pruned)"
773
773
774 - see the changeset currently being bisected (especially useful
774 - see the changeset currently being bisected (especially useful
775 if running with -U/--noupdate)::
775 if running with -U/--noupdate)::
776
776
777 hg log -r "bisect(current)"
777 hg log -r "bisect(current)"
778
778
779 - see all changesets that took part in the current bisection::
779 - see all changesets that took part in the current bisection::
780
780
781 hg log -r "bisect(range)"
781 hg log -r "bisect(range)"
782
782
783 - you can even get a nice graph::
783 - you can even get a nice graph::
784
784
785 hg log --graph -r "bisect(range)"
785 hg log --graph -r "bisect(range)"
786
786
787 See :hg:`help revsets` for more about the `bisect()` keyword.
787 See :hg:`help revsets` for more about the `bisect()` keyword.
788
788
789 Returns 0 on success.
789 Returns 0 on success.
790 """
790 """
791 def extendbisectrange(nodes, good):
791 def extendbisectrange(nodes, good):
792 # bisect is incomplete when it ends on a merge node and
792 # bisect is incomplete when it ends on a merge node and
793 # one of the parent was not checked.
793 # one of the parent was not checked.
794 parents = repo[nodes[0]].parents()
794 parents = repo[nodes[0]].parents()
795 if len(parents) > 1:
795 if len(parents) > 1:
796 if good:
796 if good:
797 side = state['bad']
797 side = state['bad']
798 else:
798 else:
799 side = state['good']
799 side = state['good']
800 num = len(set(i.node() for i in parents) & set(side))
800 num = len(set(i.node() for i in parents) & set(side))
801 if num == 1:
801 if num == 1:
802 return parents[0].ancestor(parents[1])
802 return parents[0].ancestor(parents[1])
803 return None
803 return None
804
804
805 def print_result(nodes, good):
805 def print_result(nodes, good):
806 displayer = cmdutil.show_changeset(ui, repo, {})
806 displayer = cmdutil.show_changeset(ui, repo, {})
807 if len(nodes) == 1:
807 if len(nodes) == 1:
808 # narrowed it down to a single revision
808 # narrowed it down to a single revision
809 if good:
809 if good:
810 ui.write(_("The first good revision is:\n"))
810 ui.write(_("The first good revision is:\n"))
811 else:
811 else:
812 ui.write(_("The first bad revision is:\n"))
812 ui.write(_("The first bad revision is:\n"))
813 displayer.show(repo[nodes[0]])
813 displayer.show(repo[nodes[0]])
814 extendnode = extendbisectrange(nodes, good)
814 extendnode = extendbisectrange(nodes, good)
815 if extendnode is not None:
815 if extendnode is not None:
816 ui.write(_('Not all ancestors of this changeset have been'
816 ui.write(_('Not all ancestors of this changeset have been'
817 ' checked.\nUse bisect --extend to continue the '
817 ' checked.\nUse bisect --extend to continue the '
818 'bisection from\nthe common ancestor, %s.\n')
818 'bisection from\nthe common ancestor, %s.\n')
819 % extendnode)
819 % extendnode)
820 else:
820 else:
821 # multiple possible revisions
821 # multiple possible revisions
822 if good:
822 if good:
823 ui.write(_("Due to skipped revisions, the first "
823 ui.write(_("Due to skipped revisions, the first "
824 "good revision could be any of:\n"))
824 "good revision could be any of:\n"))
825 else:
825 else:
826 ui.write(_("Due to skipped revisions, the first "
826 ui.write(_("Due to skipped revisions, the first "
827 "bad revision could be any of:\n"))
827 "bad revision could be any of:\n"))
828 for n in nodes:
828 for n in nodes:
829 displayer.show(repo[n])
829 displayer.show(repo[n])
830 displayer.close()
830 displayer.close()
831
831
832 def check_state(state, interactive=True):
832 def check_state(state, interactive=True):
833 if not state['good'] or not state['bad']:
833 if not state['good'] or not state['bad']:
834 if (good or bad or skip or reset) and interactive:
834 if (good or bad or skip or reset) and interactive:
835 return
835 return
836 if not state['good']:
836 if not state['good']:
837 raise error.Abort(_('cannot bisect (no known good revisions)'))
837 raise error.Abort(_('cannot bisect (no known good revisions)'))
838 else:
838 else:
839 raise error.Abort(_('cannot bisect (no known bad revisions)'))
839 raise error.Abort(_('cannot bisect (no known bad revisions)'))
840 return True
840 return True
841
841
842 # backward compatibility
842 # backward compatibility
843 if rev in "good bad reset init".split():
843 if rev in "good bad reset init".split():
844 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
844 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
845 cmd, rev, extra = rev, extra, None
845 cmd, rev, extra = rev, extra, None
846 if cmd == "good":
846 if cmd == "good":
847 good = True
847 good = True
848 elif cmd == "bad":
848 elif cmd == "bad":
849 bad = True
849 bad = True
850 else:
850 else:
851 reset = True
851 reset = True
852 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
852 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
853 raise error.Abort(_('incompatible arguments'))
853 raise error.Abort(_('incompatible arguments'))
854
854
855 cmdutil.checkunfinished(repo)
855 cmdutil.checkunfinished(repo)
856
856
857 if reset:
857 if reset:
858 p = repo.join("bisect.state")
858 p = repo.join("bisect.state")
859 if os.path.exists(p):
859 if os.path.exists(p):
860 os.unlink(p)
860 os.unlink(p)
861 return
861 return
862
862
863 state = hbisect.load_state(repo)
863 state = hbisect.load_state(repo)
864
864
865 if command:
865 if command:
866 changesets = 1
866 changesets = 1
867 if noupdate:
867 if noupdate:
868 try:
868 try:
869 node = state['current'][0]
869 node = state['current'][0]
870 except LookupError:
870 except LookupError:
871 raise error.Abort(_('current bisect revision is unknown - '
871 raise error.Abort(_('current bisect revision is unknown - '
872 'start a new bisect to fix'))
872 'start a new bisect to fix'))
873 else:
873 else:
874 node, p2 = repo.dirstate.parents()
874 node, p2 = repo.dirstate.parents()
875 if p2 != nullid:
875 if p2 != nullid:
876 raise error.Abort(_('current bisect revision is a merge'))
876 raise error.Abort(_('current bisect revision is a merge'))
877 try:
877 try:
878 while changesets:
878 while changesets:
879 # update state
879 # update state
880 state['current'] = [node]
880 state['current'] = [node]
881 hbisect.save_state(repo, state)
881 hbisect.save_state(repo, state)
882 status = ui.system(command, environ={'HG_NODE': hex(node)})
882 status = ui.system(command, environ={'HG_NODE': hex(node)})
883 if status == 125:
883 if status == 125:
884 transition = "skip"
884 transition = "skip"
885 elif status == 0:
885 elif status == 0:
886 transition = "good"
886 transition = "good"
887 # status < 0 means process was killed
887 # status < 0 means process was killed
888 elif status == 127:
888 elif status == 127:
889 raise error.Abort(_("failed to execute %s") % command)
889 raise error.Abort(_("failed to execute %s") % command)
890 elif status < 0:
890 elif status < 0:
891 raise error.Abort(_("%s killed") % command)
891 raise error.Abort(_("%s killed") % command)
892 else:
892 else:
893 transition = "bad"
893 transition = "bad"
894 ctx = scmutil.revsingle(repo, rev, node)
894 ctx = scmutil.revsingle(repo, rev, node)
895 rev = None # clear for future iterations
895 rev = None # clear for future iterations
896 state[transition].append(ctx.node())
896 state[transition].append(ctx.node())
897 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
897 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
898 check_state(state, interactive=False)
898 check_state(state, interactive=False)
899 # bisect
899 # bisect
900 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
900 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
901 # update to next check
901 # update to next check
902 node = nodes[0]
902 node = nodes[0]
903 if not noupdate:
903 if not noupdate:
904 cmdutil.bailifchanged(repo)
904 cmdutil.bailifchanged(repo)
905 hg.clean(repo, node, show_stats=False)
905 hg.clean(repo, node, show_stats=False)
906 finally:
906 finally:
907 state['current'] = [node]
907 state['current'] = [node]
908 hbisect.save_state(repo, state)
908 hbisect.save_state(repo, state)
909 print_result(nodes, bgood)
909 print_result(nodes, bgood)
910 return
910 return
911
911
912 # update state
912 # update state
913
913
914 if rev:
914 if rev:
915 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
915 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
916 else:
916 else:
917 nodes = [repo.lookup('.')]
917 nodes = [repo.lookup('.')]
918
918
919 if good or bad or skip:
919 if good or bad or skip:
920 if good:
920 if good:
921 state['good'] += nodes
921 state['good'] += nodes
922 elif bad:
922 elif bad:
923 state['bad'] += nodes
923 state['bad'] += nodes
924 elif skip:
924 elif skip:
925 state['skip'] += nodes
925 state['skip'] += nodes
926 hbisect.save_state(repo, state)
926 hbisect.save_state(repo, state)
927
927
928 if not check_state(state):
928 if not check_state(state):
929 return
929 return
930
930
931 # actually bisect
931 # actually bisect
932 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
932 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
933 if extend:
933 if extend:
934 if not changesets:
934 if not changesets:
935 extendnode = extendbisectrange(nodes, good)
935 extendnode = extendbisectrange(nodes, good)
936 if extendnode is not None:
936 if extendnode is not None:
937 ui.write(_("Extending search to changeset %d:%s\n")
937 ui.write(_("Extending search to changeset %d:%s\n")
938 % (extendnode.rev(), extendnode))
938 % (extendnode.rev(), extendnode))
939 state['current'] = [extendnode.node()]
939 state['current'] = [extendnode.node()]
940 hbisect.save_state(repo, state)
940 hbisect.save_state(repo, state)
941 if noupdate:
941 if noupdate:
942 return
942 return
943 cmdutil.bailifchanged(repo)
943 cmdutil.bailifchanged(repo)
944 return hg.clean(repo, extendnode.node())
944 return hg.clean(repo, extendnode.node())
945 raise error.Abort(_("nothing to extend"))
945 raise error.Abort(_("nothing to extend"))
946
946
947 if changesets == 0:
947 if changesets == 0:
948 print_result(nodes, good)
948 print_result(nodes, good)
949 else:
949 else:
950 assert len(nodes) == 1 # only a single node can be tested next
950 assert len(nodes) == 1 # only a single node can be tested next
951 node = nodes[0]
951 node = nodes[0]
952 # compute the approximate number of remaining tests
952 # compute the approximate number of remaining tests
953 tests, size = 0, 2
953 tests, size = 0, 2
954 while size <= changesets:
954 while size <= changesets:
955 tests, size = tests + 1, size * 2
955 tests, size = tests + 1, size * 2
956 rev = repo.changelog.rev(node)
956 rev = repo.changelog.rev(node)
957 ui.write(_("Testing changeset %d:%s "
957 ui.write(_("Testing changeset %d:%s "
958 "(%d changesets remaining, ~%d tests)\n")
958 "(%d changesets remaining, ~%d tests)\n")
959 % (rev, short(node), changesets, tests))
959 % (rev, short(node), changesets, tests))
960 state['current'] = [node]
960 state['current'] = [node]
961 hbisect.save_state(repo, state)
961 hbisect.save_state(repo, state)
962 if not noupdate:
962 if not noupdate:
963 cmdutil.bailifchanged(repo)
963 cmdutil.bailifchanged(repo)
964 return hg.clean(repo, node)
964 return hg.clean(repo, node)
965
965
966 @command('bookmarks|bookmark',
966 @command('bookmarks|bookmark',
967 [('f', 'force', False, _('force')),
967 [('f', 'force', False, _('force')),
968 ('r', 'rev', '', _('revision'), _('REV')),
968 ('r', 'rev', '', _('revision'), _('REV')),
969 ('d', 'delete', False, _('delete a given bookmark')),
969 ('d', 'delete', False, _('delete a given bookmark')),
970 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
970 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
971 ('i', 'inactive', False, _('mark a bookmark inactive')),
971 ('i', 'inactive', False, _('mark a bookmark inactive')),
972 ] + formatteropts,
972 ] + formatteropts,
973 _('hg bookmarks [OPTIONS]... [NAME]...'))
973 _('hg bookmarks [OPTIONS]... [NAME]...'))
974 def bookmark(ui, repo, *names, **opts):
974 def bookmark(ui, repo, *names, **opts):
975 '''create a new bookmark or list existing bookmarks
975 '''create a new bookmark or list existing bookmarks
976
976
977 Bookmarks are labels on changesets to help track lines of development.
977 Bookmarks are labels on changesets to help track lines of development.
978 Bookmarks are unversioned and can be moved, renamed and deleted.
978 Bookmarks are unversioned and can be moved, renamed and deleted.
979 Deleting or moving a bookmark has no effect on the associated changesets.
979 Deleting or moving a bookmark has no effect on the associated changesets.
980
980
981 Creating or updating to a bookmark causes it to be marked as 'active'.
981 Creating or updating to a bookmark causes it to be marked as 'active'.
982 The active bookmark is indicated with a '*'.
982 The active bookmark is indicated with a '*'.
983 When a commit is made, the active bookmark will advance to the new commit.
983 When a commit is made, the active bookmark will advance to the new commit.
984 A plain :hg:`update` will also advance an active bookmark, if possible.
984 A plain :hg:`update` will also advance an active bookmark, if possible.
985 Updating away from a bookmark will cause it to be deactivated.
985 Updating away from a bookmark will cause it to be deactivated.
986
986
987 Bookmarks can be pushed and pulled between repositories (see
987 Bookmarks can be pushed and pulled between repositories (see
988 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
988 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
989 diverged, a new 'divergent bookmark' of the form 'name@path' will
989 diverged, a new 'divergent bookmark' of the form 'name@path' will
990 be created. Using :hg:`merge` will resolve the divergence.
990 be created. Using :hg:`merge` will resolve the divergence.
991
991
992 A bookmark named '@' has the special property that :hg:`clone` will
992 A bookmark named '@' has the special property that :hg:`clone` will
993 check it out by default if it exists.
993 check it out by default if it exists.
994
994
995 .. container:: verbose
995 .. container:: verbose
996
996
997 Examples:
997 Examples:
998
998
999 - create an active bookmark for a new line of development::
999 - create an active bookmark for a new line of development::
1000
1000
1001 hg book new-feature
1001 hg book new-feature
1002
1002
1003 - create an inactive bookmark as a place marker::
1003 - create an inactive bookmark as a place marker::
1004
1004
1005 hg book -i reviewed
1005 hg book -i reviewed
1006
1006
1007 - create an inactive bookmark on another changeset::
1007 - create an inactive bookmark on another changeset::
1008
1008
1009 hg book -r .^ tested
1009 hg book -r .^ tested
1010
1010
1011 - rename bookmark turkey to dinner::
1011 - rename bookmark turkey to dinner::
1012
1012
1013 hg book -m turkey dinner
1013 hg book -m turkey dinner
1014
1014
1015 - move the '@' bookmark from another branch::
1015 - move the '@' bookmark from another branch::
1016
1016
1017 hg book -f @
1017 hg book -f @
1018 '''
1018 '''
1019 force = opts.get('force')
1019 force = opts.get('force')
1020 rev = opts.get('rev')
1020 rev = opts.get('rev')
1021 delete = opts.get('delete')
1021 delete = opts.get('delete')
1022 rename = opts.get('rename')
1022 rename = opts.get('rename')
1023 inactive = opts.get('inactive')
1023 inactive = opts.get('inactive')
1024
1024
1025 def checkformat(mark):
1025 def checkformat(mark):
1026 mark = mark.strip()
1026 mark = mark.strip()
1027 if not mark:
1027 if not mark:
1028 raise error.Abort(_("bookmark names cannot consist entirely of "
1028 raise error.Abort(_("bookmark names cannot consist entirely of "
1029 "whitespace"))
1029 "whitespace"))
1030 scmutil.checknewlabel(repo, mark, 'bookmark')
1030 scmutil.checknewlabel(repo, mark, 'bookmark')
1031 return mark
1031 return mark
1032
1032
1033 def checkconflict(repo, mark, cur, force=False, target=None):
1033 def checkconflict(repo, mark, cur, force=False, target=None):
1034 if mark in marks and not force:
1034 if mark in marks and not force:
1035 if target:
1035 if target:
1036 if marks[mark] == target and target == cur:
1036 if marks[mark] == target and target == cur:
1037 # re-activating a bookmark
1037 # re-activating a bookmark
1038 return
1038 return
1039 anc = repo.changelog.ancestors([repo[target].rev()])
1039 anc = repo.changelog.ancestors([repo[target].rev()])
1040 bmctx = repo[marks[mark]]
1040 bmctx = repo[marks[mark]]
1041 divs = [repo[b].node() for b in marks
1041 divs = [repo[b].node() for b in marks
1042 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1042 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1043
1043
1044 # allow resolving a single divergent bookmark even if moving
1044 # allow resolving a single divergent bookmark even if moving
1045 # the bookmark across branches when a revision is specified
1045 # the bookmark across branches when a revision is specified
1046 # that contains a divergent bookmark
1046 # that contains a divergent bookmark
1047 if bmctx.rev() not in anc and target in divs:
1047 if bmctx.rev() not in anc and target in divs:
1048 bookmarks.deletedivergent(repo, [target], mark)
1048 bookmarks.deletedivergent(repo, [target], mark)
1049 return
1049 return
1050
1050
1051 deletefrom = [b for b in divs
1051 deletefrom = [b for b in divs
1052 if repo[b].rev() in anc or b == target]
1052 if repo[b].rev() in anc or b == target]
1053 bookmarks.deletedivergent(repo, deletefrom, mark)
1053 bookmarks.deletedivergent(repo, deletefrom, mark)
1054 if bookmarks.validdest(repo, bmctx, repo[target]):
1054 if bookmarks.validdest(repo, bmctx, repo[target]):
1055 ui.status(_("moving bookmark '%s' forward from %s\n") %
1055 ui.status(_("moving bookmark '%s' forward from %s\n") %
1056 (mark, short(bmctx.node())))
1056 (mark, short(bmctx.node())))
1057 return
1057 return
1058 raise error.Abort(_("bookmark '%s' already exists "
1058 raise error.Abort(_("bookmark '%s' already exists "
1059 "(use -f to force)") % mark)
1059 "(use -f to force)") % mark)
1060 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1060 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1061 and not force):
1061 and not force):
1062 raise error.Abort(
1062 raise error.Abort(
1063 _("a bookmark cannot have the name of an existing branch"))
1063 _("a bookmark cannot have the name of an existing branch"))
1064
1064
1065 if delete and rename:
1065 if delete and rename:
1066 raise error.Abort(_("--delete and --rename are incompatible"))
1066 raise error.Abort(_("--delete and --rename are incompatible"))
1067 if delete and rev:
1067 if delete and rev:
1068 raise error.Abort(_("--rev is incompatible with --delete"))
1068 raise error.Abort(_("--rev is incompatible with --delete"))
1069 if rename and rev:
1069 if rename and rev:
1070 raise error.Abort(_("--rev is incompatible with --rename"))
1070 raise error.Abort(_("--rev is incompatible with --rename"))
1071 if not names and (delete or rev):
1071 if not names and (delete or rev):
1072 raise error.Abort(_("bookmark name required"))
1072 raise error.Abort(_("bookmark name required"))
1073
1073
1074 if delete or rename or names or inactive:
1074 if delete or rename or names or inactive:
1075 wlock = lock = tr = None
1075 wlock = lock = tr = None
1076 try:
1076 try:
1077 wlock = repo.wlock()
1077 wlock = repo.wlock()
1078 lock = repo.lock()
1078 lock = repo.lock()
1079 cur = repo.changectx('.').node()
1079 cur = repo.changectx('.').node()
1080 marks = repo._bookmarks
1080 marks = repo._bookmarks
1081 if delete:
1081 if delete:
1082 tr = repo.transaction('bookmark')
1082 tr = repo.transaction('bookmark')
1083 for mark in names:
1083 for mark in names:
1084 if mark not in marks:
1084 if mark not in marks:
1085 raise error.Abort(_("bookmark '%s' does not exist") %
1085 raise error.Abort(_("bookmark '%s' does not exist") %
1086 mark)
1086 mark)
1087 if mark == repo._activebookmark:
1087 if mark == repo._activebookmark:
1088 bookmarks.deactivate(repo)
1088 bookmarks.deactivate(repo)
1089 del marks[mark]
1089 del marks[mark]
1090
1090
1091 elif rename:
1091 elif rename:
1092 tr = repo.transaction('bookmark')
1092 tr = repo.transaction('bookmark')
1093 if not names:
1093 if not names:
1094 raise error.Abort(_("new bookmark name required"))
1094 raise error.Abort(_("new bookmark name required"))
1095 elif len(names) > 1:
1095 elif len(names) > 1:
1096 raise error.Abort(_("only one new bookmark name allowed"))
1096 raise error.Abort(_("only one new bookmark name allowed"))
1097 mark = checkformat(names[0])
1097 mark = checkformat(names[0])
1098 if rename not in marks:
1098 if rename not in marks:
1099 raise error.Abort(_("bookmark '%s' does not exist")
1099 raise error.Abort(_("bookmark '%s' does not exist")
1100 % rename)
1100 % rename)
1101 checkconflict(repo, mark, cur, force)
1101 checkconflict(repo, mark, cur, force)
1102 marks[mark] = marks[rename]
1102 marks[mark] = marks[rename]
1103 if repo._activebookmark == rename and not inactive:
1103 if repo._activebookmark == rename and not inactive:
1104 bookmarks.activate(repo, mark)
1104 bookmarks.activate(repo, mark)
1105 del marks[rename]
1105 del marks[rename]
1106 elif names:
1106 elif names:
1107 tr = repo.transaction('bookmark')
1107 tr = repo.transaction('bookmark')
1108 newact = None
1108 newact = None
1109 for mark in names:
1109 for mark in names:
1110 mark = checkformat(mark)
1110 mark = checkformat(mark)
1111 if newact is None:
1111 if newact is None:
1112 newact = mark
1112 newact = mark
1113 if inactive and mark == repo._activebookmark:
1113 if inactive and mark == repo._activebookmark:
1114 bookmarks.deactivate(repo)
1114 bookmarks.deactivate(repo)
1115 return
1115 return
1116 tgt = cur
1116 tgt = cur
1117 if rev:
1117 if rev:
1118 tgt = scmutil.revsingle(repo, rev).node()
1118 tgt = scmutil.revsingle(repo, rev).node()
1119 checkconflict(repo, mark, cur, force, tgt)
1119 checkconflict(repo, mark, cur, force, tgt)
1120 marks[mark] = tgt
1120 marks[mark] = tgt
1121 if not inactive and cur == marks[newact] and not rev:
1121 if not inactive and cur == marks[newact] and not rev:
1122 bookmarks.activate(repo, newact)
1122 bookmarks.activate(repo, newact)
1123 elif cur != tgt and newact == repo._activebookmark:
1123 elif cur != tgt and newact == repo._activebookmark:
1124 bookmarks.deactivate(repo)
1124 bookmarks.deactivate(repo)
1125 elif inactive:
1125 elif inactive:
1126 if len(marks) == 0:
1126 if len(marks) == 0:
1127 ui.status(_("no bookmarks set\n"))
1127 ui.status(_("no bookmarks set\n"))
1128 elif not repo._activebookmark:
1128 elif not repo._activebookmark:
1129 ui.status(_("no active bookmark\n"))
1129 ui.status(_("no active bookmark\n"))
1130 else:
1130 else:
1131 bookmarks.deactivate(repo)
1131 bookmarks.deactivate(repo)
1132 if tr is not None:
1132 if tr is not None:
1133 marks.recordchange(tr)
1133 marks.recordchange(tr)
1134 tr.close()
1134 tr.close()
1135 finally:
1135 finally:
1136 lockmod.release(tr, lock, wlock)
1136 lockmod.release(tr, lock, wlock)
1137 else: # show bookmarks
1137 else: # show bookmarks
1138 fm = ui.formatter('bookmarks', opts)
1138 fm = ui.formatter('bookmarks', opts)
1139 hexfn = fm.hexfunc
1139 hexfn = fm.hexfunc
1140 marks = repo._bookmarks
1140 marks = repo._bookmarks
1141 if len(marks) == 0 and not fm:
1141 if len(marks) == 0 and not fm:
1142 ui.status(_("no bookmarks set\n"))
1142 ui.status(_("no bookmarks set\n"))
1143 for bmark, n in sorted(marks.iteritems()):
1143 for bmark, n in sorted(marks.iteritems()):
1144 active = repo._activebookmark
1144 active = repo._activebookmark
1145 if bmark == active:
1145 if bmark == active:
1146 prefix, label = '*', activebookmarklabel
1146 prefix, label = '*', activebookmarklabel
1147 else:
1147 else:
1148 prefix, label = ' ', ''
1148 prefix, label = ' ', ''
1149
1149
1150 fm.startitem()
1150 fm.startitem()
1151 if not ui.quiet:
1151 if not ui.quiet:
1152 fm.plain(' %s ' % prefix, label=label)
1152 fm.plain(' %s ' % prefix, label=label)
1153 fm.write('bookmark', '%s', bmark, label=label)
1153 fm.write('bookmark', '%s', bmark, label=label)
1154 pad = " " * (25 - encoding.colwidth(bmark))
1154 pad = " " * (25 - encoding.colwidth(bmark))
1155 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1155 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1156 repo.changelog.rev(n), hexfn(n), label=label)
1156 repo.changelog.rev(n), hexfn(n), label=label)
1157 fm.data(active=(bmark == active))
1157 fm.data(active=(bmark == active))
1158 fm.plain('\n')
1158 fm.plain('\n')
1159 fm.end()
1159 fm.end()
1160
1160
1161 @command('branch',
1161 @command('branch',
1162 [('f', 'force', None,
1162 [('f', 'force', None,
1163 _('set branch name even if it shadows an existing branch')),
1163 _('set branch name even if it shadows an existing branch')),
1164 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1164 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1165 _('[-fC] [NAME]'))
1165 _('[-fC] [NAME]'))
1166 def branch(ui, repo, label=None, **opts):
1166 def branch(ui, repo, label=None, **opts):
1167 """set or show the current branch name
1167 """set or show the current branch name
1168
1168
1169 .. note::
1169 .. note::
1170
1170
1171 Branch names are permanent and global. Use :hg:`bookmark` to create a
1171 Branch names are permanent and global. Use :hg:`bookmark` to create a
1172 light-weight bookmark instead. See :hg:`help glossary` for more
1172 light-weight bookmark instead. See :hg:`help glossary` for more
1173 information about named branches and bookmarks.
1173 information about named branches and bookmarks.
1174
1174
1175 With no argument, show the current branch name. With one argument,
1175 With no argument, show the current branch name. With one argument,
1176 set the working directory branch name (the branch will not exist
1176 set the working directory branch name (the branch will not exist
1177 in the repository until the next commit). Standard practice
1177 in the repository until the next commit). Standard practice
1178 recommends that primary development take place on the 'default'
1178 recommends that primary development take place on the 'default'
1179 branch.
1179 branch.
1180
1180
1181 Unless -f/--force is specified, branch will not let you set a
1181 Unless -f/--force is specified, branch will not let you set a
1182 branch name that already exists.
1182 branch name that already exists.
1183
1183
1184 Use -C/--clean to reset the working directory branch to that of
1184 Use -C/--clean to reset the working directory branch to that of
1185 the parent of the working directory, negating a previous branch
1185 the parent of the working directory, negating a previous branch
1186 change.
1186 change.
1187
1187
1188 Use the command :hg:`update` to switch to an existing branch. Use
1188 Use the command :hg:`update` to switch to an existing branch. Use
1189 :hg:`commit --close-branch` to mark this branch head as closed.
1189 :hg:`commit --close-branch` to mark this branch head as closed.
1190 When all heads of a branch are closed, the branch will be
1190 When all heads of a branch are closed, the branch will be
1191 considered closed.
1191 considered closed.
1192
1192
1193 Returns 0 on success.
1193 Returns 0 on success.
1194 """
1194 """
1195 if label:
1195 if label:
1196 label = label.strip()
1196 label = label.strip()
1197
1197
1198 if not opts.get('clean') and not label:
1198 if not opts.get('clean') and not label:
1199 ui.write("%s\n" % repo.dirstate.branch())
1199 ui.write("%s\n" % repo.dirstate.branch())
1200 return
1200 return
1201
1201
1202 wlock = repo.wlock()
1202 wlock = repo.wlock()
1203 try:
1203 try:
1204 if opts.get('clean'):
1204 if opts.get('clean'):
1205 label = repo[None].p1().branch()
1205 label = repo[None].p1().branch()
1206 repo.dirstate.setbranch(label)
1206 repo.dirstate.setbranch(label)
1207 ui.status(_('reset working directory to branch %s\n') % label)
1207 ui.status(_('reset working directory to branch %s\n') % label)
1208 elif label:
1208 elif label:
1209 if not opts.get('force') and label in repo.branchmap():
1209 if not opts.get('force') and label in repo.branchmap():
1210 if label not in [p.branch() for p in repo[None].parents()]:
1210 if label not in [p.branch() for p in repo[None].parents()]:
1211 raise error.Abort(_('a branch of the same name already'
1211 raise error.Abort(_('a branch of the same name already'
1212 ' exists'),
1212 ' exists'),
1213 # i18n: "it" refers to an existing branch
1213 # i18n: "it" refers to an existing branch
1214 hint=_("use 'hg update' to switch to it"))
1214 hint=_("use 'hg update' to switch to it"))
1215 scmutil.checknewlabel(repo, label, 'branch')
1215 scmutil.checknewlabel(repo, label, 'branch')
1216 repo.dirstate.setbranch(label)
1216 repo.dirstate.setbranch(label)
1217 ui.status(_('marked working directory as branch %s\n') % label)
1217 ui.status(_('marked working directory as branch %s\n') % label)
1218
1218
1219 # find any open named branches aside from default
1219 # find any open named branches aside from default
1220 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1220 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1221 if n != "default" and not c]
1221 if n != "default" and not c]
1222 if not others:
1222 if not others:
1223 ui.status(_('(branches are permanent and global, '
1223 ui.status(_('(branches are permanent and global, '
1224 'did you want a bookmark?)\n'))
1224 'did you want a bookmark?)\n'))
1225 finally:
1225 finally:
1226 wlock.release()
1226 wlock.release()
1227
1227
1228 @command('branches',
1228 @command('branches',
1229 [('a', 'active', False,
1229 [('a', 'active', False,
1230 _('show only branches that have unmerged heads (DEPRECATED)')),
1230 _('show only branches that have unmerged heads (DEPRECATED)')),
1231 ('c', 'closed', False, _('show normal and closed branches')),
1231 ('c', 'closed', False, _('show normal and closed branches')),
1232 ] + formatteropts,
1232 ] + formatteropts,
1233 _('[-ac]'))
1233 _('[-ac]'))
1234 def branches(ui, repo, active=False, closed=False, **opts):
1234 def branches(ui, repo, active=False, closed=False, **opts):
1235 """list repository named branches
1235 """list repository named branches
1236
1236
1237 List the repository's named branches, indicating which ones are
1237 List the repository's named branches, indicating which ones are
1238 inactive. If -c/--closed is specified, also list branches which have
1238 inactive. If -c/--closed is specified, also list branches which have
1239 been marked closed (see :hg:`commit --close-branch`).
1239 been marked closed (see :hg:`commit --close-branch`).
1240
1240
1241 Use the command :hg:`update` to switch to an existing branch.
1241 Use the command :hg:`update` to switch to an existing branch.
1242
1242
1243 Returns 0.
1243 Returns 0.
1244 """
1244 """
1245
1245
1246 fm = ui.formatter('branches', opts)
1246 fm = ui.formatter('branches', opts)
1247 hexfunc = fm.hexfunc
1247 hexfunc = fm.hexfunc
1248
1248
1249 allheads = set(repo.heads())
1249 allheads = set(repo.heads())
1250 branches = []
1250 branches = []
1251 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1251 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1252 isactive = not isclosed and bool(set(heads) & allheads)
1252 isactive = not isclosed and bool(set(heads) & allheads)
1253 branches.append((tag, repo[tip], isactive, not isclosed))
1253 branches.append((tag, repo[tip], isactive, not isclosed))
1254 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1254 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1255 reverse=True)
1255 reverse=True)
1256
1256
1257 for tag, ctx, isactive, isopen in branches:
1257 for tag, ctx, isactive, isopen in branches:
1258 if active and not isactive:
1258 if active and not isactive:
1259 continue
1259 continue
1260 if isactive:
1260 if isactive:
1261 label = 'branches.active'
1261 label = 'branches.active'
1262 notice = ''
1262 notice = ''
1263 elif not isopen:
1263 elif not isopen:
1264 if not closed:
1264 if not closed:
1265 continue
1265 continue
1266 label = 'branches.closed'
1266 label = 'branches.closed'
1267 notice = _(' (closed)')
1267 notice = _(' (closed)')
1268 else:
1268 else:
1269 label = 'branches.inactive'
1269 label = 'branches.inactive'
1270 notice = _(' (inactive)')
1270 notice = _(' (inactive)')
1271 current = (tag == repo.dirstate.branch())
1271 current = (tag == repo.dirstate.branch())
1272 if current:
1272 if current:
1273 label = 'branches.current'
1273 label = 'branches.current'
1274
1274
1275 fm.startitem()
1275 fm.startitem()
1276 fm.write('branch', '%s', tag, label=label)
1276 fm.write('branch', '%s', tag, label=label)
1277 rev = ctx.rev()
1277 rev = ctx.rev()
1278 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1278 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1279 fmt = ' ' * padsize + ' %d:%s'
1279 fmt = ' ' * padsize + ' %d:%s'
1280 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1280 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1281 label='log.changeset changeset.%s' % ctx.phasestr())
1281 label='log.changeset changeset.%s' % ctx.phasestr())
1282 fm.data(active=isactive, closed=not isopen, current=current)
1282 fm.data(active=isactive, closed=not isopen, current=current)
1283 if not ui.quiet:
1283 if not ui.quiet:
1284 fm.plain(notice)
1284 fm.plain(notice)
1285 fm.plain('\n')
1285 fm.plain('\n')
1286 fm.end()
1286 fm.end()
1287
1287
1288 @command('bundle',
1288 @command('bundle',
1289 [('f', 'force', None, _('run even when the destination is unrelated')),
1289 [('f', 'force', None, _('run even when the destination is unrelated')),
1290 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1290 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1291 _('REV')),
1291 _('REV')),
1292 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1292 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1293 _('BRANCH')),
1293 _('BRANCH')),
1294 ('', 'base', [],
1294 ('', 'base', [],
1295 _('a base changeset assumed to be available at the destination'),
1295 _('a base changeset assumed to be available at the destination'),
1296 _('REV')),
1296 _('REV')),
1297 ('a', 'all', None, _('bundle all changesets in the repository')),
1297 ('a', 'all', None, _('bundle all changesets in the repository')),
1298 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1298 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1299 ] + remoteopts,
1299 ] + remoteopts,
1300 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1300 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1301 def bundle(ui, repo, fname, dest=None, **opts):
1301 def bundle(ui, repo, fname, dest=None, **opts):
1302 """create a changegroup file
1302 """create a changegroup file
1303
1303
1304 Generate a changegroup file collecting changesets to be added
1304 Generate a changegroup file collecting changesets to be added
1305 to a repository.
1305 to a repository.
1306
1306
1307 To create a bundle containing all changesets, use -a/--all
1307 To create a bundle containing all changesets, use -a/--all
1308 (or --base null). Otherwise, hg assumes the destination will have
1308 (or --base null). Otherwise, hg assumes the destination will have
1309 all the nodes you specify with --base parameters. Otherwise, hg
1309 all the nodes you specify with --base parameters. Otherwise, hg
1310 will assume the repository has all the nodes in destination, or
1310 will assume the repository has all the nodes in destination, or
1311 default-push/default if no destination is specified.
1311 default-push/default if no destination is specified.
1312
1312
1313 You can change bundle format with the -t/--type option. You can
1313 You can change bundle format with the -t/--type option. You can
1314 specify a compression, a bundle version or both using a dash
1314 specify a compression, a bundle version or both using a dash
1315 (comp-version). The available compression methods are: none, bzip2,
1315 (comp-version). The available compression methods are: none, bzip2,
1316 and gzip (by default, bundles are compressed using bzip2). The
1316 and gzip (by default, bundles are compressed using bzip2). The
1317 available formats are: v1, v2 (default to most suitable).
1317 available formats are: v1, v2 (default to most suitable).
1318
1318
1319 The bundle file can then be transferred using conventional means
1319 The bundle file can then be transferred using conventional means
1320 and applied to another repository with the unbundle or pull
1320 and applied to another repository with the unbundle or pull
1321 command. This is useful when direct push and pull are not
1321 command. This is useful when direct push and pull are not
1322 available or when exporting an entire repository is undesirable.
1322 available or when exporting an entire repository is undesirable.
1323
1323
1324 Applying bundles preserves all changeset contents including
1324 Applying bundles preserves all changeset contents including
1325 permissions, copy/rename information, and revision history.
1325 permissions, copy/rename information, and revision history.
1326
1326
1327 Returns 0 on success, 1 if no changes found.
1327 Returns 0 on success, 1 if no changes found.
1328 """
1328 """
1329 revs = None
1329 revs = None
1330 if 'rev' in opts:
1330 if 'rev' in opts:
1331 revs = scmutil.revrange(repo, opts['rev'])
1331 revs = scmutil.revrange(repo, opts['rev'])
1332
1332
1333 bundletype = opts.get('type', 'bzip2').lower()
1333 bundletype = opts.get('type', 'bzip2').lower()
1334 try:
1334 try:
1335 bcompression, cgversion, params = exchange.parsebundlespec(
1335 bcompression, cgversion, params = exchange.parsebundlespec(
1336 repo, bundletype, strict=False)
1336 repo, bundletype, strict=False)
1337 except error.UnsupportedBundleSpecification as e:
1337 except error.UnsupportedBundleSpecification as e:
1338 raise error.Abort(str(e),
1338 raise error.Abort(str(e),
1339 hint=_('see "hg help bundle" for supported '
1339 hint=_('see "hg help bundle" for supported '
1340 'values for --type'))
1340 'values for --type'))
1341
1341
1342 # Packed bundles are a pseudo bundle format for now.
1342 # Packed bundles are a pseudo bundle format for now.
1343 if cgversion == 's1':
1343 if cgversion == 's1':
1344 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1344 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1345 hint=_('use "hg debugcreatestreamclonebundle"'))
1345 hint=_('use "hg debugcreatestreamclonebundle"'))
1346
1346
1347 if opts.get('all'):
1347 if opts.get('all'):
1348 if dest:
1348 if dest:
1349 raise error.Abort(_("--all is incompatible with specifying "
1349 raise error.Abort(_("--all is incompatible with specifying "
1350 "a destination"))
1350 "a destination"))
1351 if opts.get('base'):
1351 if opts.get('base'):
1352 ui.warn(_("ignoring --base because --all was specified\n"))
1352 ui.warn(_("ignoring --base because --all was specified\n"))
1353 base = ['null']
1353 base = ['null']
1354 else:
1354 else:
1355 base = scmutil.revrange(repo, opts.get('base'))
1355 base = scmutil.revrange(repo, opts.get('base'))
1356 # TODO: get desired bundlecaps from command line.
1356 # TODO: get desired bundlecaps from command line.
1357 bundlecaps = None
1357 bundlecaps = None
1358 if base:
1358 if base:
1359 if dest:
1359 if dest:
1360 raise error.Abort(_("--base is incompatible with specifying "
1360 raise error.Abort(_("--base is incompatible with specifying "
1361 "a destination"))
1361 "a destination"))
1362 common = [repo.lookup(rev) for rev in base]
1362 common = [repo.lookup(rev) for rev in base]
1363 heads = revs and map(repo.lookup, revs) or revs
1363 heads = revs and map(repo.lookup, revs) or revs
1364 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1364 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1365 common=common, bundlecaps=bundlecaps,
1365 common=common, bundlecaps=bundlecaps,
1366 version=cgversion)
1366 version=cgversion)
1367 outgoing = None
1367 outgoing = None
1368 else:
1368 else:
1369 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1369 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1370 dest, branches = hg.parseurl(dest, opts.get('branch'))
1370 dest, branches = hg.parseurl(dest, opts.get('branch'))
1371 other = hg.peer(repo, opts, dest)
1371 other = hg.peer(repo, opts, dest)
1372 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1372 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1373 heads = revs and map(repo.lookup, revs) or revs
1373 heads = revs and map(repo.lookup, revs) or revs
1374 outgoing = discovery.findcommonoutgoing(repo, other,
1374 outgoing = discovery.findcommonoutgoing(repo, other,
1375 onlyheads=heads,
1375 onlyheads=heads,
1376 force=opts.get('force'),
1376 force=opts.get('force'),
1377 portable=True)
1377 portable=True)
1378 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1378 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1379 bundlecaps, version=cgversion)
1379 bundlecaps, version=cgversion)
1380 if not cg:
1380 if not cg:
1381 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1381 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1382 return 1
1382 return 1
1383
1383
1384 if cgversion == '01': #bundle1
1384 if cgversion == '01': #bundle1
1385 if bcompression is None:
1385 if bcompression is None:
1386 bcompression = 'UN'
1386 bcompression = 'UN'
1387 bversion = 'HG10' + bcompression
1387 bversion = 'HG10' + bcompression
1388 bcompression = None
1388 bcompression = None
1389 else:
1389 else:
1390 assert cgversion == '02'
1390 assert cgversion == '02'
1391 bversion = 'HG20'
1391 bversion = 'HG20'
1392
1392
1393
1393
1394 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1394 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1395
1395
1396 @command('cat',
1396 @command('cat',
1397 [('o', 'output', '',
1397 [('o', 'output', '',
1398 _('print output to file with formatted name'), _('FORMAT')),
1398 _('print output to file with formatted name'), _('FORMAT')),
1399 ('r', 'rev', '', _('print the given revision'), _('REV')),
1399 ('r', 'rev', '', _('print the given revision'), _('REV')),
1400 ('', 'decode', None, _('apply any matching decode filter')),
1400 ('', 'decode', None, _('apply any matching decode filter')),
1401 ] + walkopts,
1401 ] + walkopts,
1402 _('[OPTION]... FILE...'),
1402 _('[OPTION]... FILE...'),
1403 inferrepo=True)
1403 inferrepo=True)
1404 def cat(ui, repo, file1, *pats, **opts):
1404 def cat(ui, repo, file1, *pats, **opts):
1405 """output the current or given revision of files
1405 """output the current or given revision of files
1406
1406
1407 Print the specified files as they were at the given revision. If
1407 Print the specified files as they were at the given revision. If
1408 no revision is given, the parent of the working directory is used.
1408 no revision is given, the parent of the working directory is used.
1409
1409
1410 Output may be to a file, in which case the name of the file is
1410 Output may be to a file, in which case the name of the file is
1411 given using a format string. The formatting rules as follows:
1411 given using a format string. The formatting rules as follows:
1412
1412
1413 :``%%``: literal "%" character
1413 :``%%``: literal "%" character
1414 :``%s``: basename of file being printed
1414 :``%s``: basename of file being printed
1415 :``%d``: dirname of file being printed, or '.' if in repository root
1415 :``%d``: dirname of file being printed, or '.' if in repository root
1416 :``%p``: root-relative path name of file being printed
1416 :``%p``: root-relative path name of file being printed
1417 :``%H``: changeset hash (40 hexadecimal digits)
1417 :``%H``: changeset hash (40 hexadecimal digits)
1418 :``%R``: changeset revision number
1418 :``%R``: changeset revision number
1419 :``%h``: short-form changeset hash (12 hexadecimal digits)
1419 :``%h``: short-form changeset hash (12 hexadecimal digits)
1420 :``%r``: zero-padded changeset revision number
1420 :``%r``: zero-padded changeset revision number
1421 :``%b``: basename of the exporting repository
1421 :``%b``: basename of the exporting repository
1422
1422
1423 Returns 0 on success.
1423 Returns 0 on success.
1424 """
1424 """
1425 ctx = scmutil.revsingle(repo, opts.get('rev'))
1425 ctx = scmutil.revsingle(repo, opts.get('rev'))
1426 m = scmutil.match(ctx, (file1,) + pats, opts)
1426 m = scmutil.match(ctx, (file1,) + pats, opts)
1427
1427
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1429
1429
1430 @command('^clone',
1430 @command('^clone',
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1432 'directory (only a repository)')),
1432 'directory (only a repository)')),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1434 _('REV')),
1434 _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1439 ] + remoteopts,
1439 ] + remoteopts,
1440 _('[OPTION]... SOURCE [DEST]'),
1440 _('[OPTION]... SOURCE [DEST]'),
1441 norepo=True)
1441 norepo=True)
1442 def clone(ui, source, dest=None, **opts):
1442 def clone(ui, source, dest=None, **opts):
1443 """make a copy of an existing repository
1443 """make a copy of an existing repository
1444
1444
1445 Create a copy of an existing repository in a new directory.
1445 Create a copy of an existing repository in a new directory.
1446
1446
1447 If no destination directory name is specified, it defaults to the
1447 If no destination directory name is specified, it defaults to the
1448 basename of the source.
1448 basename of the source.
1449
1449
1450 The location of the source is added to the new repository's
1450 The location of the source is added to the new repository's
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1452
1452
1453 Only local paths and ``ssh://`` URLs are supported as
1453 Only local paths and ``ssh://`` URLs are supported as
1454 destinations. For ``ssh://`` destinations, no working directory or
1454 destinations. For ``ssh://`` destinations, no working directory or
1455 ``.hg/hgrc`` will be created on the remote side.
1455 ``.hg/hgrc`` will be created on the remote side.
1456
1456
1457 To pull only a subset of changesets, specify one or more revisions
1457 To pull only a subset of changesets, specify one or more revisions
1458 identifiers with -r/--rev or branches with -b/--branch. The
1458 identifiers with -r/--rev or branches with -b/--branch. The
1459 resulting clone will contain only the specified changesets and
1459 resulting clone will contain only the specified changesets and
1460 their ancestors. These options (or 'clone src#rev dest') imply
1460 their ancestors. These options (or 'clone src#rev dest') imply
1461 --pull, even for local source repositories. Note that specifying a
1461 --pull, even for local source repositories.
1462 tag will include the tagged changeset but not the changeset
1462
1463 containing the tag.
1463 .. note::
1464
1465 Specifying a tag will include the tagged changeset but not the
1466 changeset containing the tag.
1464
1467
1465 If the source repository has a bookmark called '@' set, that
1468 If the source repository has a bookmark called '@' set, that
1466 revision will be checked out in the new repository by default.
1469 revision will be checked out in the new repository by default.
1467
1470
1468 To check out a particular version, use -u/--update, or
1471 To check out a particular version, use -u/--update, or
1469 -U/--noupdate to create a clone with no working directory.
1472 -U/--noupdate to create a clone with no working directory.
1470
1473
1471 .. container:: verbose
1474 .. container:: verbose
1472
1475
1473 For efficiency, hardlinks are used for cloning whenever the
1476 For efficiency, hardlinks are used for cloning whenever the
1474 source and destination are on the same filesystem (note this
1477 source and destination are on the same filesystem (note this
1475 applies only to the repository data, not to the working
1478 applies only to the repository data, not to the working
1476 directory). Some filesystems, such as AFS, implement hardlinking
1479 directory). Some filesystems, such as AFS, implement hardlinking
1477 incorrectly, but do not report errors. In these cases, use the
1480 incorrectly, but do not report errors. In these cases, use the
1478 --pull option to avoid hardlinking.
1481 --pull option to avoid hardlinking.
1479
1482
1480 In some cases, you can clone repositories and the working
1483 In some cases, you can clone repositories and the working
1481 directory using full hardlinks with ::
1484 directory using full hardlinks with ::
1482
1485
1483 $ cp -al REPO REPOCLONE
1486 $ cp -al REPO REPOCLONE
1484
1487
1485 This is the fastest way to clone, but it is not always safe. The
1488 This is the fastest way to clone, but it is not always safe. The
1486 operation is not atomic (making sure REPO is not modified during
1489 operation is not atomic (making sure REPO is not modified during
1487 the operation is up to you) and you have to make sure your
1490 the operation is up to you) and you have to make sure your
1488 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1489 so). Also, this is not compatible with certain extensions that
1492 so). Also, this is not compatible with certain extensions that
1490 place their metadata under the .hg directory, such as mq.
1493 place their metadata under the .hg directory, such as mq.
1491
1494
1492 Mercurial will update the working directory to the first applicable
1495 Mercurial will update the working directory to the first applicable
1493 revision from this list:
1496 revision from this list:
1494
1497
1495 a) null if -U or the source repository has no changesets
1498 a) null if -U or the source repository has no changesets
1496 b) if -u . and the source repository is local, the first parent of
1499 b) if -u . and the source repository is local, the first parent of
1497 the source repository's working directory
1500 the source repository's working directory
1498 c) the changeset specified with -u (if a branch name, this means the
1501 c) the changeset specified with -u (if a branch name, this means the
1499 latest head of that branch)
1502 latest head of that branch)
1500 d) the changeset specified with -r
1503 d) the changeset specified with -r
1501 e) the tipmost head specified with -b
1504 e) the tipmost head specified with -b
1502 f) the tipmost head specified with the url#branch source syntax
1505 f) the tipmost head specified with the url#branch source syntax
1503 g) the revision marked with the '@' bookmark, if present
1506 g) the revision marked with the '@' bookmark, if present
1504 h) the tipmost head of the default branch
1507 h) the tipmost head of the default branch
1505 i) tip
1508 i) tip
1506
1509
1507 Examples:
1510 Examples:
1508
1511
1509 - clone a remote repository to a new directory named hg/::
1512 - clone a remote repository to a new directory named hg/::
1510
1513
1511 hg clone http://selenic.com/hg
1514 hg clone http://selenic.com/hg
1512
1515
1513 - create a lightweight local clone::
1516 - create a lightweight local clone::
1514
1517
1515 hg clone project/ project-feature/
1518 hg clone project/ project-feature/
1516
1519
1517 - clone from an absolute path on an ssh server (note double-slash)::
1520 - clone from an absolute path on an ssh server (note double-slash)::
1518
1521
1519 hg clone ssh://user@server//home/projects/alpha/
1522 hg clone ssh://user@server//home/projects/alpha/
1520
1523
1521 - do a high-speed clone over a LAN while checking out a
1524 - do a high-speed clone over a LAN while checking out a
1522 specified version::
1525 specified version::
1523
1526
1524 hg clone --uncompressed http://server/repo -u 1.5
1527 hg clone --uncompressed http://server/repo -u 1.5
1525
1528
1526 - create a repository without changesets after a particular revision::
1529 - create a repository without changesets after a particular revision::
1527
1530
1528 hg clone -r 04e544 experimental/ good/
1531 hg clone -r 04e544 experimental/ good/
1529
1532
1530 - clone (and track) a particular named branch::
1533 - clone (and track) a particular named branch::
1531
1534
1532 hg clone http://selenic.com/hg#stable
1535 hg clone http://selenic.com/hg#stable
1533
1536
1534 See :hg:`help urls` for details on specifying URLs.
1537 See :hg:`help urls` for details on specifying URLs.
1535
1538
1536 Returns 0 on success.
1539 Returns 0 on success.
1537 """
1540 """
1538 if opts.get('noupdate') and opts.get('updaterev'):
1541 if opts.get('noupdate') and opts.get('updaterev'):
1539 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1542 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1540
1543
1541 r = hg.clone(ui, opts, source, dest,
1544 r = hg.clone(ui, opts, source, dest,
1542 pull=opts.get('pull'),
1545 pull=opts.get('pull'),
1543 stream=opts.get('uncompressed'),
1546 stream=opts.get('uncompressed'),
1544 rev=opts.get('rev'),
1547 rev=opts.get('rev'),
1545 update=opts.get('updaterev') or not opts.get('noupdate'),
1548 update=opts.get('updaterev') or not opts.get('noupdate'),
1546 branch=opts.get('branch'),
1549 branch=opts.get('branch'),
1547 shareopts=opts.get('shareopts'))
1550 shareopts=opts.get('shareopts'))
1548
1551
1549 return r is None
1552 return r is None
1550
1553
1551 @command('^commit|ci',
1554 @command('^commit|ci',
1552 [('A', 'addremove', None,
1555 [('A', 'addremove', None,
1553 _('mark new/missing files as added/removed before committing')),
1556 _('mark new/missing files as added/removed before committing')),
1554 ('', 'close-branch', None,
1557 ('', 'close-branch', None,
1555 _('mark a branch head as closed')),
1558 _('mark a branch head as closed')),
1556 ('', 'amend', None, _('amend the parent of the working directory')),
1559 ('', 'amend', None, _('amend the parent of the working directory')),
1557 ('s', 'secret', None, _('use the secret phase for committing')),
1560 ('s', 'secret', None, _('use the secret phase for committing')),
1558 ('e', 'edit', None, _('invoke editor on commit messages')),
1561 ('e', 'edit', None, _('invoke editor on commit messages')),
1559 ('i', 'interactive', None, _('use interactive mode')),
1562 ('i', 'interactive', None, _('use interactive mode')),
1560 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1563 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1561 _('[OPTION]... [FILE]...'),
1564 _('[OPTION]... [FILE]...'),
1562 inferrepo=True)
1565 inferrepo=True)
1563 def commit(ui, repo, *pats, **opts):
1566 def commit(ui, repo, *pats, **opts):
1564 """commit the specified files or all outstanding changes
1567 """commit the specified files or all outstanding changes
1565
1568
1566 Commit changes to the given files into the repository. Unlike a
1569 Commit changes to the given files into the repository. Unlike a
1567 centralized SCM, this operation is a local operation. See
1570 centralized SCM, this operation is a local operation. See
1568 :hg:`push` for a way to actively distribute your changes.
1571 :hg:`push` for a way to actively distribute your changes.
1569
1572
1570 If a list of files is omitted, all changes reported by :hg:`status`
1573 If a list of files is omitted, all changes reported by :hg:`status`
1571 will be committed.
1574 will be committed.
1572
1575
1573 If you are committing the result of a merge, do not provide any
1576 If you are committing the result of a merge, do not provide any
1574 filenames or -I/-X filters.
1577 filenames or -I/-X filters.
1575
1578
1576 If no commit message is specified, Mercurial starts your
1579 If no commit message is specified, Mercurial starts your
1577 configured editor where you can enter a message. In case your
1580 configured editor where you can enter a message. In case your
1578 commit fails, you will find a backup of your message in
1581 commit fails, you will find a backup of your message in
1579 ``.hg/last-message.txt``.
1582 ``.hg/last-message.txt``.
1580
1583
1581 The --close-branch flag can be used to mark the current branch
1584 The --close-branch flag can be used to mark the current branch
1582 head closed. When all heads of a branch are closed, the branch
1585 head closed. When all heads of a branch are closed, the branch
1583 will be considered closed and no longer listed.
1586 will be considered closed and no longer listed.
1584
1587
1585 The --amend flag can be used to amend the parent of the
1588 The --amend flag can be used to amend the parent of the
1586 working directory with a new commit that contains the changes
1589 working directory with a new commit that contains the changes
1587 in the parent in addition to those currently reported by :hg:`status`,
1590 in the parent in addition to those currently reported by :hg:`status`,
1588 if there are any. The old commit is stored in a backup bundle in
1591 if there are any. The old commit is stored in a backup bundle in
1589 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1592 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1590 on how to restore it).
1593 on how to restore it).
1591
1594
1592 Message, user and date are taken from the amended commit unless
1595 Message, user and date are taken from the amended commit unless
1593 specified. When a message isn't specified on the command line,
1596 specified. When a message isn't specified on the command line,
1594 the editor will open with the message of the amended commit.
1597 the editor will open with the message of the amended commit.
1595
1598
1596 It is not possible to amend public changesets (see :hg:`help phases`)
1599 It is not possible to amend public changesets (see :hg:`help phases`)
1597 or changesets that have children.
1600 or changesets that have children.
1598
1601
1599 See :hg:`help dates` for a list of formats valid for -d/--date.
1602 See :hg:`help dates` for a list of formats valid for -d/--date.
1600
1603
1601 Returns 0 on success, 1 if nothing changed.
1604 Returns 0 on success, 1 if nothing changed.
1602
1605
1603 .. container:: verbose
1606 .. container:: verbose
1604
1607
1605 Examples:
1608 Examples:
1606
1609
1607 - commit all files ending in .py::
1610 - commit all files ending in .py::
1608
1611
1609 hg commit --include "set:**.py"
1612 hg commit --include "set:**.py"
1610
1613
1611 - commit all non-binary files::
1614 - commit all non-binary files::
1612
1615
1613 hg commit --exclude "set:binary()"
1616 hg commit --exclude "set:binary()"
1614
1617
1615 - amend the current commit and set the date to now::
1618 - amend the current commit and set the date to now::
1616
1619
1617 hg commit --amend --date now
1620 hg commit --amend --date now
1618 """
1621 """
1619 wlock = lock = None
1622 wlock = lock = None
1620 try:
1623 try:
1621 wlock = repo.wlock()
1624 wlock = repo.wlock()
1622 lock = repo.lock()
1625 lock = repo.lock()
1623 return _docommit(ui, repo, *pats, **opts)
1626 return _docommit(ui, repo, *pats, **opts)
1624 finally:
1627 finally:
1625 release(lock, wlock)
1628 release(lock, wlock)
1626
1629
1627 def _docommit(ui, repo, *pats, **opts):
1630 def _docommit(ui, repo, *pats, **opts):
1628 if opts.get('interactive'):
1631 if opts.get('interactive'):
1629 opts.pop('interactive')
1632 opts.pop('interactive')
1630 cmdutil.dorecord(ui, repo, commit, None, False,
1633 cmdutil.dorecord(ui, repo, commit, None, False,
1631 cmdutil.recordfilter, *pats, **opts)
1634 cmdutil.recordfilter, *pats, **opts)
1632 return
1635 return
1633
1636
1634 if opts.get('subrepos'):
1637 if opts.get('subrepos'):
1635 if opts.get('amend'):
1638 if opts.get('amend'):
1636 raise error.Abort(_('cannot amend with --subrepos'))
1639 raise error.Abort(_('cannot amend with --subrepos'))
1637 # Let --subrepos on the command line override config setting.
1640 # Let --subrepos on the command line override config setting.
1638 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1641 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1639
1642
1640 cmdutil.checkunfinished(repo, commit=True)
1643 cmdutil.checkunfinished(repo, commit=True)
1641
1644
1642 branch = repo[None].branch()
1645 branch = repo[None].branch()
1643 bheads = repo.branchheads(branch)
1646 bheads = repo.branchheads(branch)
1644
1647
1645 extra = {}
1648 extra = {}
1646 if opts.get('close_branch'):
1649 if opts.get('close_branch'):
1647 extra['close'] = 1
1650 extra['close'] = 1
1648
1651
1649 if not bheads:
1652 if not bheads:
1650 raise error.Abort(_('can only close branch heads'))
1653 raise error.Abort(_('can only close branch heads'))
1651 elif opts.get('amend'):
1654 elif opts.get('amend'):
1652 if repo[None].parents()[0].p1().branch() != branch and \
1655 if repo[None].parents()[0].p1().branch() != branch and \
1653 repo[None].parents()[0].p2().branch() != branch:
1656 repo[None].parents()[0].p2().branch() != branch:
1654 raise error.Abort(_('can only close branch heads'))
1657 raise error.Abort(_('can only close branch heads'))
1655
1658
1656 if opts.get('amend'):
1659 if opts.get('amend'):
1657 if ui.configbool('ui', 'commitsubrepos'):
1660 if ui.configbool('ui', 'commitsubrepos'):
1658 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1661 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1659
1662
1660 old = repo['.']
1663 old = repo['.']
1661 if not old.mutable():
1664 if not old.mutable():
1662 raise error.Abort(_('cannot amend public changesets'))
1665 raise error.Abort(_('cannot amend public changesets'))
1663 if len(repo[None].parents()) > 1:
1666 if len(repo[None].parents()) > 1:
1664 raise error.Abort(_('cannot amend while merging'))
1667 raise error.Abort(_('cannot amend while merging'))
1665 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1668 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1666 if not allowunstable and old.children():
1669 if not allowunstable and old.children():
1667 raise error.Abort(_('cannot amend changeset with children'))
1670 raise error.Abort(_('cannot amend changeset with children'))
1668
1671
1669 newextra = extra.copy()
1672 newextra = extra.copy()
1670 newextra['branch'] = branch
1673 newextra['branch'] = branch
1671 extra = newextra
1674 extra = newextra
1672 # commitfunc is used only for temporary amend commit by cmdutil.amend
1675 # commitfunc is used only for temporary amend commit by cmdutil.amend
1673 def commitfunc(ui, repo, message, match, opts):
1676 def commitfunc(ui, repo, message, match, opts):
1674 return repo.commit(message,
1677 return repo.commit(message,
1675 opts.get('user') or old.user(),
1678 opts.get('user') or old.user(),
1676 opts.get('date') or old.date(),
1679 opts.get('date') or old.date(),
1677 match,
1680 match,
1678 extra=extra)
1681 extra=extra)
1679
1682
1680 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1683 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1681 if node == old.node():
1684 if node == old.node():
1682 ui.status(_("nothing changed\n"))
1685 ui.status(_("nothing changed\n"))
1683 return 1
1686 return 1
1684 else:
1687 else:
1685 def commitfunc(ui, repo, message, match, opts):
1688 def commitfunc(ui, repo, message, match, opts):
1686 backup = ui.backupconfig('phases', 'new-commit')
1689 backup = ui.backupconfig('phases', 'new-commit')
1687 baseui = repo.baseui
1690 baseui = repo.baseui
1688 basebackup = baseui.backupconfig('phases', 'new-commit')
1691 basebackup = baseui.backupconfig('phases', 'new-commit')
1689 try:
1692 try:
1690 if opts.get('secret'):
1693 if opts.get('secret'):
1691 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1694 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1692 # Propagate to subrepos
1695 # Propagate to subrepos
1693 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1696 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1694
1697
1695 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1698 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1696 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1699 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1697 return repo.commit(message, opts.get('user'), opts.get('date'),
1700 return repo.commit(message, opts.get('user'), opts.get('date'),
1698 match,
1701 match,
1699 editor=editor,
1702 editor=editor,
1700 extra=extra)
1703 extra=extra)
1701 finally:
1704 finally:
1702 ui.restoreconfig(backup)
1705 ui.restoreconfig(backup)
1703 repo.baseui.restoreconfig(basebackup)
1706 repo.baseui.restoreconfig(basebackup)
1704
1707
1705
1708
1706 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1709 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1707
1710
1708 if not node:
1711 if not node:
1709 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1712 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1710 if stat[3]:
1713 if stat[3]:
1711 ui.status(_("nothing changed (%d missing files, see "
1714 ui.status(_("nothing changed (%d missing files, see "
1712 "'hg status')\n") % len(stat[3]))
1715 "'hg status')\n") % len(stat[3]))
1713 else:
1716 else:
1714 ui.status(_("nothing changed\n"))
1717 ui.status(_("nothing changed\n"))
1715 return 1
1718 return 1
1716
1719
1717 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1720 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1718
1721
1719 @command('config|showconfig|debugconfig',
1722 @command('config|showconfig|debugconfig',
1720 [('u', 'untrusted', None, _('show untrusted configuration options')),
1723 [('u', 'untrusted', None, _('show untrusted configuration options')),
1721 ('e', 'edit', None, _('edit user config')),
1724 ('e', 'edit', None, _('edit user config')),
1722 ('l', 'local', None, _('edit repository config')),
1725 ('l', 'local', None, _('edit repository config')),
1723 ('g', 'global', None, _('edit global config'))],
1726 ('g', 'global', None, _('edit global config'))],
1724 _('[-u] [NAME]...'),
1727 _('[-u] [NAME]...'),
1725 optionalrepo=True)
1728 optionalrepo=True)
1726 def config(ui, repo, *values, **opts):
1729 def config(ui, repo, *values, **opts):
1727 """show combined config settings from all hgrc files
1730 """show combined config settings from all hgrc files
1728
1731
1729 With no arguments, print names and values of all config items.
1732 With no arguments, print names and values of all config items.
1730
1733
1731 With one argument of the form section.name, print just the value
1734 With one argument of the form section.name, print just the value
1732 of that config item.
1735 of that config item.
1733
1736
1734 With multiple arguments, print names and values of all config
1737 With multiple arguments, print names and values of all config
1735 items with matching section names.
1738 items with matching section names.
1736
1739
1737 With --edit, start an editor on the user-level config file. With
1740 With --edit, start an editor on the user-level config file. With
1738 --global, edit the system-wide config file. With --local, edit the
1741 --global, edit the system-wide config file. With --local, edit the
1739 repository-level config file.
1742 repository-level config file.
1740
1743
1741 With --debug, the source (filename and line number) is printed
1744 With --debug, the source (filename and line number) is printed
1742 for each config item.
1745 for each config item.
1743
1746
1744 See :hg:`help config` for more information about config files.
1747 See :hg:`help config` for more information about config files.
1745
1748
1746 Returns 0 on success, 1 if NAME does not exist.
1749 Returns 0 on success, 1 if NAME does not exist.
1747
1750
1748 """
1751 """
1749
1752
1750 if opts.get('edit') or opts.get('local') or opts.get('global'):
1753 if opts.get('edit') or opts.get('local') or opts.get('global'):
1751 if opts.get('local') and opts.get('global'):
1754 if opts.get('local') and opts.get('global'):
1752 raise error.Abort(_("can't use --local and --global together"))
1755 raise error.Abort(_("can't use --local and --global together"))
1753
1756
1754 if opts.get('local'):
1757 if opts.get('local'):
1755 if not repo:
1758 if not repo:
1756 raise error.Abort(_("can't use --local outside a repository"))
1759 raise error.Abort(_("can't use --local outside a repository"))
1757 paths = [repo.join('hgrc')]
1760 paths = [repo.join('hgrc')]
1758 elif opts.get('global'):
1761 elif opts.get('global'):
1759 paths = scmutil.systemrcpath()
1762 paths = scmutil.systemrcpath()
1760 else:
1763 else:
1761 paths = scmutil.userrcpath()
1764 paths = scmutil.userrcpath()
1762
1765
1763 for f in paths:
1766 for f in paths:
1764 if os.path.exists(f):
1767 if os.path.exists(f):
1765 break
1768 break
1766 else:
1769 else:
1767 if opts.get('global'):
1770 if opts.get('global'):
1768 samplehgrc = uimod.samplehgrcs['global']
1771 samplehgrc = uimod.samplehgrcs['global']
1769 elif opts.get('local'):
1772 elif opts.get('local'):
1770 samplehgrc = uimod.samplehgrcs['local']
1773 samplehgrc = uimod.samplehgrcs['local']
1771 else:
1774 else:
1772 samplehgrc = uimod.samplehgrcs['user']
1775 samplehgrc = uimod.samplehgrcs['user']
1773
1776
1774 f = paths[0]
1777 f = paths[0]
1775 fp = open(f, "w")
1778 fp = open(f, "w")
1776 fp.write(samplehgrc)
1779 fp.write(samplehgrc)
1777 fp.close()
1780 fp.close()
1778
1781
1779 editor = ui.geteditor()
1782 editor = ui.geteditor()
1780 ui.system("%s \"%s\"" % (editor, f),
1783 ui.system("%s \"%s\"" % (editor, f),
1781 onerr=error.Abort, errprefix=_("edit failed"))
1784 onerr=error.Abort, errprefix=_("edit failed"))
1782 return
1785 return
1783
1786
1784 for f in scmutil.rcpath():
1787 for f in scmutil.rcpath():
1785 ui.debug('read config from: %s\n' % f)
1788 ui.debug('read config from: %s\n' % f)
1786 untrusted = bool(opts.get('untrusted'))
1789 untrusted = bool(opts.get('untrusted'))
1787 if values:
1790 if values:
1788 sections = [v for v in values if '.' not in v]
1791 sections = [v for v in values if '.' not in v]
1789 items = [v for v in values if '.' in v]
1792 items = [v for v in values if '.' in v]
1790 if len(items) > 1 or items and sections:
1793 if len(items) > 1 or items and sections:
1791 raise error.Abort(_('only one config item permitted'))
1794 raise error.Abort(_('only one config item permitted'))
1792 matched = False
1795 matched = False
1793 for section, name, value in ui.walkconfig(untrusted=untrusted):
1796 for section, name, value in ui.walkconfig(untrusted=untrusted):
1794 value = str(value).replace('\n', '\\n')
1797 value = str(value).replace('\n', '\\n')
1795 sectname = section + '.' + name
1798 sectname = section + '.' + name
1796 if values:
1799 if values:
1797 for v in values:
1800 for v in values:
1798 if v == section:
1801 if v == section:
1799 ui.debug('%s: ' %
1802 ui.debug('%s: ' %
1800 ui.configsource(section, name, untrusted))
1803 ui.configsource(section, name, untrusted))
1801 ui.write('%s=%s\n' % (sectname, value))
1804 ui.write('%s=%s\n' % (sectname, value))
1802 matched = True
1805 matched = True
1803 elif v == sectname:
1806 elif v == sectname:
1804 ui.debug('%s: ' %
1807 ui.debug('%s: ' %
1805 ui.configsource(section, name, untrusted))
1808 ui.configsource(section, name, untrusted))
1806 ui.write(value, '\n')
1809 ui.write(value, '\n')
1807 matched = True
1810 matched = True
1808 else:
1811 else:
1809 ui.debug('%s: ' %
1812 ui.debug('%s: ' %
1810 ui.configsource(section, name, untrusted))
1813 ui.configsource(section, name, untrusted))
1811 ui.write('%s=%s\n' % (sectname, value))
1814 ui.write('%s=%s\n' % (sectname, value))
1812 matched = True
1815 matched = True
1813 if matched:
1816 if matched:
1814 return 0
1817 return 0
1815 return 1
1818 return 1
1816
1819
1817 @command('copy|cp',
1820 @command('copy|cp',
1818 [('A', 'after', None, _('record a copy that has already occurred')),
1821 [('A', 'after', None, _('record a copy that has already occurred')),
1819 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1822 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1820 ] + walkopts + dryrunopts,
1823 ] + walkopts + dryrunopts,
1821 _('[OPTION]... [SOURCE]... DEST'))
1824 _('[OPTION]... [SOURCE]... DEST'))
1822 def copy(ui, repo, *pats, **opts):
1825 def copy(ui, repo, *pats, **opts):
1823 """mark files as copied for the next commit
1826 """mark files as copied for the next commit
1824
1827
1825 Mark dest as having copies of source files. If dest is a
1828 Mark dest as having copies of source files. If dest is a
1826 directory, copies are put in that directory. If dest is a file,
1829 directory, copies are put in that directory. If dest is a file,
1827 the source must be a single file.
1830 the source must be a single file.
1828
1831
1829 By default, this command copies the contents of files as they
1832 By default, this command copies the contents of files as they
1830 exist in the working directory. If invoked with -A/--after, the
1833 exist in the working directory. If invoked with -A/--after, the
1831 operation is recorded, but no copying is performed.
1834 operation is recorded, but no copying is performed.
1832
1835
1833 This command takes effect with the next commit. To undo a copy
1836 This command takes effect with the next commit. To undo a copy
1834 before that, see :hg:`revert`.
1837 before that, see :hg:`revert`.
1835
1838
1836 Returns 0 on success, 1 if errors are encountered.
1839 Returns 0 on success, 1 if errors are encountered.
1837 """
1840 """
1838 wlock = repo.wlock(False)
1841 wlock = repo.wlock(False)
1839 try:
1842 try:
1840 return cmdutil.copy(ui, repo, pats, opts)
1843 return cmdutil.copy(ui, repo, pats, opts)
1841 finally:
1844 finally:
1842 wlock.release()
1845 wlock.release()
1843
1846
1844 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1847 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1845 def debugancestor(ui, repo, *args):
1848 def debugancestor(ui, repo, *args):
1846 """find the ancestor revision of two revisions in a given index"""
1849 """find the ancestor revision of two revisions in a given index"""
1847 if len(args) == 3:
1850 if len(args) == 3:
1848 index, rev1, rev2 = args
1851 index, rev1, rev2 = args
1849 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1852 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1850 lookup = r.lookup
1853 lookup = r.lookup
1851 elif len(args) == 2:
1854 elif len(args) == 2:
1852 if not repo:
1855 if not repo:
1853 raise error.Abort(_("there is no Mercurial repository here "
1856 raise error.Abort(_("there is no Mercurial repository here "
1854 "(.hg not found)"))
1857 "(.hg not found)"))
1855 rev1, rev2 = args
1858 rev1, rev2 = args
1856 r = repo.changelog
1859 r = repo.changelog
1857 lookup = repo.lookup
1860 lookup = repo.lookup
1858 else:
1861 else:
1859 raise error.Abort(_('either two or three arguments required'))
1862 raise error.Abort(_('either two or three arguments required'))
1860 a = r.ancestor(lookup(rev1), lookup(rev2))
1863 a = r.ancestor(lookup(rev1), lookup(rev2))
1861 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1864 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1862
1865
1863 @command('debugbuilddag',
1866 @command('debugbuilddag',
1864 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1867 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1865 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1868 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1866 ('n', 'new-file', None, _('add new file at each rev'))],
1869 ('n', 'new-file', None, _('add new file at each rev'))],
1867 _('[OPTION]... [TEXT]'))
1870 _('[OPTION]... [TEXT]'))
1868 def debugbuilddag(ui, repo, text=None,
1871 def debugbuilddag(ui, repo, text=None,
1869 mergeable_file=False,
1872 mergeable_file=False,
1870 overwritten_file=False,
1873 overwritten_file=False,
1871 new_file=False):
1874 new_file=False):
1872 """builds a repo with a given DAG from scratch in the current empty repo
1875 """builds a repo with a given DAG from scratch in the current empty repo
1873
1876
1874 The description of the DAG is read from stdin if not given on the
1877 The description of the DAG is read from stdin if not given on the
1875 command line.
1878 command line.
1876
1879
1877 Elements:
1880 Elements:
1878
1881
1879 - "+n" is a linear run of n nodes based on the current default parent
1882 - "+n" is a linear run of n nodes based on the current default parent
1880 - "." is a single node based on the current default parent
1883 - "." is a single node based on the current default parent
1881 - "$" resets the default parent to null (implied at the start);
1884 - "$" resets the default parent to null (implied at the start);
1882 otherwise the default parent is always the last node created
1885 otherwise the default parent is always the last node created
1883 - "<p" sets the default parent to the backref p
1886 - "<p" sets the default parent to the backref p
1884 - "*p" is a fork at parent p, which is a backref
1887 - "*p" is a fork at parent p, which is a backref
1885 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1888 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1886 - "/p2" is a merge of the preceding node and p2
1889 - "/p2" is a merge of the preceding node and p2
1887 - ":tag" defines a local tag for the preceding node
1890 - ":tag" defines a local tag for the preceding node
1888 - "@branch" sets the named branch for subsequent nodes
1891 - "@branch" sets the named branch for subsequent nodes
1889 - "#...\\n" is a comment up to the end of the line
1892 - "#...\\n" is a comment up to the end of the line
1890
1893
1891 Whitespace between the above elements is ignored.
1894 Whitespace between the above elements is ignored.
1892
1895
1893 A backref is either
1896 A backref is either
1894
1897
1895 - a number n, which references the node curr-n, where curr is the current
1898 - a number n, which references the node curr-n, where curr is the current
1896 node, or
1899 node, or
1897 - the name of a local tag you placed earlier using ":tag", or
1900 - the name of a local tag you placed earlier using ":tag", or
1898 - empty to denote the default parent.
1901 - empty to denote the default parent.
1899
1902
1900 All string valued-elements are either strictly alphanumeric, or must
1903 All string valued-elements are either strictly alphanumeric, or must
1901 be enclosed in double quotes ("..."), with "\\" as escape character.
1904 be enclosed in double quotes ("..."), with "\\" as escape character.
1902 """
1905 """
1903
1906
1904 if text is None:
1907 if text is None:
1905 ui.status(_("reading DAG from stdin\n"))
1908 ui.status(_("reading DAG from stdin\n"))
1906 text = ui.fin.read()
1909 text = ui.fin.read()
1907
1910
1908 cl = repo.changelog
1911 cl = repo.changelog
1909 if len(cl) > 0:
1912 if len(cl) > 0:
1910 raise error.Abort(_('repository is not empty'))
1913 raise error.Abort(_('repository is not empty'))
1911
1914
1912 # determine number of revs in DAG
1915 # determine number of revs in DAG
1913 total = 0
1916 total = 0
1914 for type, data in dagparser.parsedag(text):
1917 for type, data in dagparser.parsedag(text):
1915 if type == 'n':
1918 if type == 'n':
1916 total += 1
1919 total += 1
1917
1920
1918 if mergeable_file:
1921 if mergeable_file:
1919 linesperrev = 2
1922 linesperrev = 2
1920 # make a file with k lines per rev
1923 # make a file with k lines per rev
1921 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1924 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1922 initialmergedlines.append("")
1925 initialmergedlines.append("")
1923
1926
1924 tags = []
1927 tags = []
1925
1928
1926 lock = tr = None
1929 lock = tr = None
1927 try:
1930 try:
1928 lock = repo.lock()
1931 lock = repo.lock()
1929 tr = repo.transaction("builddag")
1932 tr = repo.transaction("builddag")
1930
1933
1931 at = -1
1934 at = -1
1932 atbranch = 'default'
1935 atbranch = 'default'
1933 nodeids = []
1936 nodeids = []
1934 id = 0
1937 id = 0
1935 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1938 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1936 for type, data in dagparser.parsedag(text):
1939 for type, data in dagparser.parsedag(text):
1937 if type == 'n':
1940 if type == 'n':
1938 ui.note(('node %s\n' % str(data)))
1941 ui.note(('node %s\n' % str(data)))
1939 id, ps = data
1942 id, ps = data
1940
1943
1941 files = []
1944 files = []
1942 fctxs = {}
1945 fctxs = {}
1943
1946
1944 p2 = None
1947 p2 = None
1945 if mergeable_file:
1948 if mergeable_file:
1946 fn = "mf"
1949 fn = "mf"
1947 p1 = repo[ps[0]]
1950 p1 = repo[ps[0]]
1948 if len(ps) > 1:
1951 if len(ps) > 1:
1949 p2 = repo[ps[1]]
1952 p2 = repo[ps[1]]
1950 pa = p1.ancestor(p2)
1953 pa = p1.ancestor(p2)
1951 base, local, other = [x[fn].data() for x in (pa, p1,
1954 base, local, other = [x[fn].data() for x in (pa, p1,
1952 p2)]
1955 p2)]
1953 m3 = simplemerge.Merge3Text(base, local, other)
1956 m3 = simplemerge.Merge3Text(base, local, other)
1954 ml = [l.strip() for l in m3.merge_lines()]
1957 ml = [l.strip() for l in m3.merge_lines()]
1955 ml.append("")
1958 ml.append("")
1956 elif at > 0:
1959 elif at > 0:
1957 ml = p1[fn].data().split("\n")
1960 ml = p1[fn].data().split("\n")
1958 else:
1961 else:
1959 ml = initialmergedlines
1962 ml = initialmergedlines
1960 ml[id * linesperrev] += " r%i" % id
1963 ml[id * linesperrev] += " r%i" % id
1961 mergedtext = "\n".join(ml)
1964 mergedtext = "\n".join(ml)
1962 files.append(fn)
1965 files.append(fn)
1963 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1966 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1964
1967
1965 if overwritten_file:
1968 if overwritten_file:
1966 fn = "of"
1969 fn = "of"
1967 files.append(fn)
1970 files.append(fn)
1968 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1971 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1969
1972
1970 if new_file:
1973 if new_file:
1971 fn = "nf%i" % id
1974 fn = "nf%i" % id
1972 files.append(fn)
1975 files.append(fn)
1973 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1976 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1974 if len(ps) > 1:
1977 if len(ps) > 1:
1975 if not p2:
1978 if not p2:
1976 p2 = repo[ps[1]]
1979 p2 = repo[ps[1]]
1977 for fn in p2:
1980 for fn in p2:
1978 if fn.startswith("nf"):
1981 if fn.startswith("nf"):
1979 files.append(fn)
1982 files.append(fn)
1980 fctxs[fn] = p2[fn]
1983 fctxs[fn] = p2[fn]
1981
1984
1982 def fctxfn(repo, cx, path):
1985 def fctxfn(repo, cx, path):
1983 return fctxs.get(path)
1986 return fctxs.get(path)
1984
1987
1985 if len(ps) == 0 or ps[0] < 0:
1988 if len(ps) == 0 or ps[0] < 0:
1986 pars = [None, None]
1989 pars = [None, None]
1987 elif len(ps) == 1:
1990 elif len(ps) == 1:
1988 pars = [nodeids[ps[0]], None]
1991 pars = [nodeids[ps[0]], None]
1989 else:
1992 else:
1990 pars = [nodeids[p] for p in ps]
1993 pars = [nodeids[p] for p in ps]
1991 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1994 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1992 date=(id, 0),
1995 date=(id, 0),
1993 user="debugbuilddag",
1996 user="debugbuilddag",
1994 extra={'branch': atbranch})
1997 extra={'branch': atbranch})
1995 nodeid = repo.commitctx(cx)
1998 nodeid = repo.commitctx(cx)
1996 nodeids.append(nodeid)
1999 nodeids.append(nodeid)
1997 at = id
2000 at = id
1998 elif type == 'l':
2001 elif type == 'l':
1999 id, name = data
2002 id, name = data
2000 ui.note(('tag %s\n' % name))
2003 ui.note(('tag %s\n' % name))
2001 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2004 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2002 elif type == 'a':
2005 elif type == 'a':
2003 ui.note(('branch %s\n' % data))
2006 ui.note(('branch %s\n' % data))
2004 atbranch = data
2007 atbranch = data
2005 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2008 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2006 tr.close()
2009 tr.close()
2007
2010
2008 if tags:
2011 if tags:
2009 repo.vfs.write("localtags", "".join(tags))
2012 repo.vfs.write("localtags", "".join(tags))
2010 finally:
2013 finally:
2011 ui.progress(_('building'), None)
2014 ui.progress(_('building'), None)
2012 release(tr, lock)
2015 release(tr, lock)
2013
2016
2014 @command('debugbundle',
2017 @command('debugbundle',
2015 [('a', 'all', None, _('show all details'))],
2018 [('a', 'all', None, _('show all details'))],
2016 _('FILE'),
2019 _('FILE'),
2017 norepo=True)
2020 norepo=True)
2018 def debugbundle(ui, bundlepath, all=None, **opts):
2021 def debugbundle(ui, bundlepath, all=None, **opts):
2019 """lists the contents of a bundle"""
2022 """lists the contents of a bundle"""
2020 f = hg.openpath(ui, bundlepath)
2023 f = hg.openpath(ui, bundlepath)
2021 try:
2024 try:
2022 gen = exchange.readbundle(ui, f, bundlepath)
2025 gen = exchange.readbundle(ui, f, bundlepath)
2023 if isinstance(gen, bundle2.unbundle20):
2026 if isinstance(gen, bundle2.unbundle20):
2024 return _debugbundle2(ui, gen, all=all, **opts)
2027 return _debugbundle2(ui, gen, all=all, **opts)
2025 if all:
2028 if all:
2026 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2029 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2027
2030
2028 def showchunks(named):
2031 def showchunks(named):
2029 ui.write("\n%s\n" % named)
2032 ui.write("\n%s\n" % named)
2030 chain = None
2033 chain = None
2031 while True:
2034 while True:
2032 chunkdata = gen.deltachunk(chain)
2035 chunkdata = gen.deltachunk(chain)
2033 if not chunkdata:
2036 if not chunkdata:
2034 break
2037 break
2035 node = chunkdata['node']
2038 node = chunkdata['node']
2036 p1 = chunkdata['p1']
2039 p1 = chunkdata['p1']
2037 p2 = chunkdata['p2']
2040 p2 = chunkdata['p2']
2038 cs = chunkdata['cs']
2041 cs = chunkdata['cs']
2039 deltabase = chunkdata['deltabase']
2042 deltabase = chunkdata['deltabase']
2040 delta = chunkdata['delta']
2043 delta = chunkdata['delta']
2041 ui.write("%s %s %s %s %s %s\n" %
2044 ui.write("%s %s %s %s %s %s\n" %
2042 (hex(node), hex(p1), hex(p2),
2045 (hex(node), hex(p1), hex(p2),
2043 hex(cs), hex(deltabase), len(delta)))
2046 hex(cs), hex(deltabase), len(delta)))
2044 chain = node
2047 chain = node
2045
2048
2046 chunkdata = gen.changelogheader()
2049 chunkdata = gen.changelogheader()
2047 showchunks("changelog")
2050 showchunks("changelog")
2048 chunkdata = gen.manifestheader()
2051 chunkdata = gen.manifestheader()
2049 showchunks("manifest")
2052 showchunks("manifest")
2050 while True:
2053 while True:
2051 chunkdata = gen.filelogheader()
2054 chunkdata = gen.filelogheader()
2052 if not chunkdata:
2055 if not chunkdata:
2053 break
2056 break
2054 fname = chunkdata['filename']
2057 fname = chunkdata['filename']
2055 showchunks(fname)
2058 showchunks(fname)
2056 else:
2059 else:
2057 if isinstance(gen, bundle2.unbundle20):
2060 if isinstance(gen, bundle2.unbundle20):
2058 raise error.Abort(_('use debugbundle2 for this file'))
2061 raise error.Abort(_('use debugbundle2 for this file'))
2059 chunkdata = gen.changelogheader()
2062 chunkdata = gen.changelogheader()
2060 chain = None
2063 chain = None
2061 while True:
2064 while True:
2062 chunkdata = gen.deltachunk(chain)
2065 chunkdata = gen.deltachunk(chain)
2063 if not chunkdata:
2066 if not chunkdata:
2064 break
2067 break
2065 node = chunkdata['node']
2068 node = chunkdata['node']
2066 ui.write("%s\n" % hex(node))
2069 ui.write("%s\n" % hex(node))
2067 chain = node
2070 chain = node
2068 finally:
2071 finally:
2069 f.close()
2072 f.close()
2070
2073
2071 def _debugbundle2(ui, gen, **opts):
2074 def _debugbundle2(ui, gen, **opts):
2072 """lists the contents of a bundle2"""
2075 """lists the contents of a bundle2"""
2073 if not isinstance(gen, bundle2.unbundle20):
2076 if not isinstance(gen, bundle2.unbundle20):
2074 raise error.Abort(_('not a bundle2 file'))
2077 raise error.Abort(_('not a bundle2 file'))
2075 ui.write(('Stream params: %s\n' % repr(gen.params)))
2078 ui.write(('Stream params: %s\n' % repr(gen.params)))
2076 for part in gen.iterparts():
2079 for part in gen.iterparts():
2077 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2080 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2078 if part.type == 'changegroup':
2081 if part.type == 'changegroup':
2079 version = part.params.get('version', '01')
2082 version = part.params.get('version', '01')
2080 cg = changegroup.packermap[version][1](part, 'UN')
2083 cg = changegroup.packermap[version][1](part, 'UN')
2081 chunkdata = cg.changelogheader()
2084 chunkdata = cg.changelogheader()
2082 chain = None
2085 chain = None
2083 while True:
2086 while True:
2084 chunkdata = cg.deltachunk(chain)
2087 chunkdata = cg.deltachunk(chain)
2085 if not chunkdata:
2088 if not chunkdata:
2086 break
2089 break
2087 node = chunkdata['node']
2090 node = chunkdata['node']
2088 ui.write(" %s\n" % hex(node))
2091 ui.write(" %s\n" % hex(node))
2089 chain = node
2092 chain = node
2090
2093
2091 @command('debugcreatestreamclonebundle', [], 'FILE')
2094 @command('debugcreatestreamclonebundle', [], 'FILE')
2092 def debugcreatestreamclonebundle(ui, repo, fname):
2095 def debugcreatestreamclonebundle(ui, repo, fname):
2093 """create a stream clone bundle file
2096 """create a stream clone bundle file
2094
2097
2095 Stream bundles are special bundles that are essentially archives of
2098 Stream bundles are special bundles that are essentially archives of
2096 revlog files. They are commonly used for cloning very quickly.
2099 revlog files. They are commonly used for cloning very quickly.
2097 """
2100 """
2098 requirements, gen = streamclone.generatebundlev1(repo)
2101 requirements, gen = streamclone.generatebundlev1(repo)
2099 changegroup.writechunks(ui, gen, fname)
2102 changegroup.writechunks(ui, gen, fname)
2100
2103
2101 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2104 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2102
2105
2103 @command('debugapplystreamclonebundle', [], 'FILE')
2106 @command('debugapplystreamclonebundle', [], 'FILE')
2104 def debugapplystreamclonebundle(ui, repo, fname):
2107 def debugapplystreamclonebundle(ui, repo, fname):
2105 """apply a stream clone bundle file"""
2108 """apply a stream clone bundle file"""
2106 f = hg.openpath(ui, fname)
2109 f = hg.openpath(ui, fname)
2107 gen = exchange.readbundle(ui, f, fname)
2110 gen = exchange.readbundle(ui, f, fname)
2108 gen.apply(repo)
2111 gen.apply(repo)
2109
2112
2110 @command('debugcheckstate', [], '')
2113 @command('debugcheckstate', [], '')
2111 def debugcheckstate(ui, repo):
2114 def debugcheckstate(ui, repo):
2112 """validate the correctness of the current dirstate"""
2115 """validate the correctness of the current dirstate"""
2113 parent1, parent2 = repo.dirstate.parents()
2116 parent1, parent2 = repo.dirstate.parents()
2114 m1 = repo[parent1].manifest()
2117 m1 = repo[parent1].manifest()
2115 m2 = repo[parent2].manifest()
2118 m2 = repo[parent2].manifest()
2116 errors = 0
2119 errors = 0
2117 for f in repo.dirstate:
2120 for f in repo.dirstate:
2118 state = repo.dirstate[f]
2121 state = repo.dirstate[f]
2119 if state in "nr" and f not in m1:
2122 if state in "nr" and f not in m1:
2120 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2123 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2121 errors += 1
2124 errors += 1
2122 if state in "a" and f in m1:
2125 if state in "a" and f in m1:
2123 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2126 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2124 errors += 1
2127 errors += 1
2125 if state in "m" and f not in m1 and f not in m2:
2128 if state in "m" and f not in m1 and f not in m2:
2126 ui.warn(_("%s in state %s, but not in either manifest\n") %
2129 ui.warn(_("%s in state %s, but not in either manifest\n") %
2127 (f, state))
2130 (f, state))
2128 errors += 1
2131 errors += 1
2129 for f in m1:
2132 for f in m1:
2130 state = repo.dirstate[f]
2133 state = repo.dirstate[f]
2131 if state not in "nrm":
2134 if state not in "nrm":
2132 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2135 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2133 errors += 1
2136 errors += 1
2134 if errors:
2137 if errors:
2135 error = _(".hg/dirstate inconsistent with current parent's manifest")
2138 error = _(".hg/dirstate inconsistent with current parent's manifest")
2136 raise error.Abort(error)
2139 raise error.Abort(error)
2137
2140
2138 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2141 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2139 def debugcommands(ui, cmd='', *args):
2142 def debugcommands(ui, cmd='', *args):
2140 """list all available commands and options"""
2143 """list all available commands and options"""
2141 for cmd, vals in sorted(table.iteritems()):
2144 for cmd, vals in sorted(table.iteritems()):
2142 cmd = cmd.split('|')[0].strip('^')
2145 cmd = cmd.split('|')[0].strip('^')
2143 opts = ', '.join([i[1] for i in vals[1]])
2146 opts = ', '.join([i[1] for i in vals[1]])
2144 ui.write('%s: %s\n' % (cmd, opts))
2147 ui.write('%s: %s\n' % (cmd, opts))
2145
2148
2146 @command('debugcomplete',
2149 @command('debugcomplete',
2147 [('o', 'options', None, _('show the command options'))],
2150 [('o', 'options', None, _('show the command options'))],
2148 _('[-o] CMD'),
2151 _('[-o] CMD'),
2149 norepo=True)
2152 norepo=True)
2150 def debugcomplete(ui, cmd='', **opts):
2153 def debugcomplete(ui, cmd='', **opts):
2151 """returns the completion list associated with the given command"""
2154 """returns the completion list associated with the given command"""
2152
2155
2153 if opts.get('options'):
2156 if opts.get('options'):
2154 options = []
2157 options = []
2155 otables = [globalopts]
2158 otables = [globalopts]
2156 if cmd:
2159 if cmd:
2157 aliases, entry = cmdutil.findcmd(cmd, table, False)
2160 aliases, entry = cmdutil.findcmd(cmd, table, False)
2158 otables.append(entry[1])
2161 otables.append(entry[1])
2159 for t in otables:
2162 for t in otables:
2160 for o in t:
2163 for o in t:
2161 if "(DEPRECATED)" in o[3]:
2164 if "(DEPRECATED)" in o[3]:
2162 continue
2165 continue
2163 if o[0]:
2166 if o[0]:
2164 options.append('-%s' % o[0])
2167 options.append('-%s' % o[0])
2165 options.append('--%s' % o[1])
2168 options.append('--%s' % o[1])
2166 ui.write("%s\n" % "\n".join(options))
2169 ui.write("%s\n" % "\n".join(options))
2167 return
2170 return
2168
2171
2169 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2172 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2170 if ui.verbose:
2173 if ui.verbose:
2171 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2174 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2172 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2175 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2173
2176
2174 @command('debugdag',
2177 @command('debugdag',
2175 [('t', 'tags', None, _('use tags as labels')),
2178 [('t', 'tags', None, _('use tags as labels')),
2176 ('b', 'branches', None, _('annotate with branch names')),
2179 ('b', 'branches', None, _('annotate with branch names')),
2177 ('', 'dots', None, _('use dots for runs')),
2180 ('', 'dots', None, _('use dots for runs')),
2178 ('s', 'spaces', None, _('separate elements by spaces'))],
2181 ('s', 'spaces', None, _('separate elements by spaces'))],
2179 _('[OPTION]... [FILE [REV]...]'),
2182 _('[OPTION]... [FILE [REV]...]'),
2180 optionalrepo=True)
2183 optionalrepo=True)
2181 def debugdag(ui, repo, file_=None, *revs, **opts):
2184 def debugdag(ui, repo, file_=None, *revs, **opts):
2182 """format the changelog or an index DAG as a concise textual description
2185 """format the changelog or an index DAG as a concise textual description
2183
2186
2184 If you pass a revlog index, the revlog's DAG is emitted. If you list
2187 If you pass a revlog index, the revlog's DAG is emitted. If you list
2185 revision numbers, they get labeled in the output as rN.
2188 revision numbers, they get labeled in the output as rN.
2186
2189
2187 Otherwise, the changelog DAG of the current repo is emitted.
2190 Otherwise, the changelog DAG of the current repo is emitted.
2188 """
2191 """
2189 spaces = opts.get('spaces')
2192 spaces = opts.get('spaces')
2190 dots = opts.get('dots')
2193 dots = opts.get('dots')
2191 if file_:
2194 if file_:
2192 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2195 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2193 revs = set((int(r) for r in revs))
2196 revs = set((int(r) for r in revs))
2194 def events():
2197 def events():
2195 for r in rlog:
2198 for r in rlog:
2196 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2199 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2197 if p != -1))
2200 if p != -1))
2198 if r in revs:
2201 if r in revs:
2199 yield 'l', (r, "r%i" % r)
2202 yield 'l', (r, "r%i" % r)
2200 elif repo:
2203 elif repo:
2201 cl = repo.changelog
2204 cl = repo.changelog
2202 tags = opts.get('tags')
2205 tags = opts.get('tags')
2203 branches = opts.get('branches')
2206 branches = opts.get('branches')
2204 if tags:
2207 if tags:
2205 labels = {}
2208 labels = {}
2206 for l, n in repo.tags().items():
2209 for l, n in repo.tags().items():
2207 labels.setdefault(cl.rev(n), []).append(l)
2210 labels.setdefault(cl.rev(n), []).append(l)
2208 def events():
2211 def events():
2209 b = "default"
2212 b = "default"
2210 for r in cl:
2213 for r in cl:
2211 if branches:
2214 if branches:
2212 newb = cl.read(cl.node(r))[5]['branch']
2215 newb = cl.read(cl.node(r))[5]['branch']
2213 if newb != b:
2216 if newb != b:
2214 yield 'a', newb
2217 yield 'a', newb
2215 b = newb
2218 b = newb
2216 yield 'n', (r, list(p for p in cl.parentrevs(r)
2219 yield 'n', (r, list(p for p in cl.parentrevs(r)
2217 if p != -1))
2220 if p != -1))
2218 if tags:
2221 if tags:
2219 ls = labels.get(r)
2222 ls = labels.get(r)
2220 if ls:
2223 if ls:
2221 for l in ls:
2224 for l in ls:
2222 yield 'l', (r, l)
2225 yield 'l', (r, l)
2223 else:
2226 else:
2224 raise error.Abort(_('need repo for changelog dag'))
2227 raise error.Abort(_('need repo for changelog dag'))
2225
2228
2226 for line in dagparser.dagtextlines(events(),
2229 for line in dagparser.dagtextlines(events(),
2227 addspaces=spaces,
2230 addspaces=spaces,
2228 wraplabels=True,
2231 wraplabels=True,
2229 wrapannotations=True,
2232 wrapannotations=True,
2230 wrapnonlinear=dots,
2233 wrapnonlinear=dots,
2231 usedots=dots,
2234 usedots=dots,
2232 maxlinewidth=70):
2235 maxlinewidth=70):
2233 ui.write(line)
2236 ui.write(line)
2234 ui.write("\n")
2237 ui.write("\n")
2235
2238
2236 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2239 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2237 def debugdata(ui, repo, file_, rev=None, **opts):
2240 def debugdata(ui, repo, file_, rev=None, **opts):
2238 """dump the contents of a data file revision"""
2241 """dump the contents of a data file revision"""
2239 if opts.get('changelog') or opts.get('manifest'):
2242 if opts.get('changelog') or opts.get('manifest'):
2240 file_, rev = None, file_
2243 file_, rev = None, file_
2241 elif rev is None:
2244 elif rev is None:
2242 raise error.CommandError('debugdata', _('invalid arguments'))
2245 raise error.CommandError('debugdata', _('invalid arguments'))
2243 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2246 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2244 try:
2247 try:
2245 ui.write(r.revision(r.lookup(rev)))
2248 ui.write(r.revision(r.lookup(rev)))
2246 except KeyError:
2249 except KeyError:
2247 raise error.Abort(_('invalid revision identifier %s') % rev)
2250 raise error.Abort(_('invalid revision identifier %s') % rev)
2248
2251
2249 @command('debugdate',
2252 @command('debugdate',
2250 [('e', 'extended', None, _('try extended date formats'))],
2253 [('e', 'extended', None, _('try extended date formats'))],
2251 _('[-e] DATE [RANGE]'),
2254 _('[-e] DATE [RANGE]'),
2252 norepo=True, optionalrepo=True)
2255 norepo=True, optionalrepo=True)
2253 def debugdate(ui, date, range=None, **opts):
2256 def debugdate(ui, date, range=None, **opts):
2254 """parse and display a date"""
2257 """parse and display a date"""
2255 if opts["extended"]:
2258 if opts["extended"]:
2256 d = util.parsedate(date, util.extendeddateformats)
2259 d = util.parsedate(date, util.extendeddateformats)
2257 else:
2260 else:
2258 d = util.parsedate(date)
2261 d = util.parsedate(date)
2259 ui.write(("internal: %s %s\n") % d)
2262 ui.write(("internal: %s %s\n") % d)
2260 ui.write(("standard: %s\n") % util.datestr(d))
2263 ui.write(("standard: %s\n") % util.datestr(d))
2261 if range:
2264 if range:
2262 m = util.matchdate(range)
2265 m = util.matchdate(range)
2263 ui.write(("match: %s\n") % m(d[0]))
2266 ui.write(("match: %s\n") % m(d[0]))
2264
2267
2265 @command('debugdiscovery',
2268 @command('debugdiscovery',
2266 [('', 'old', None, _('use old-style discovery')),
2269 [('', 'old', None, _('use old-style discovery')),
2267 ('', 'nonheads', None,
2270 ('', 'nonheads', None,
2268 _('use old-style discovery with non-heads included')),
2271 _('use old-style discovery with non-heads included')),
2269 ] + remoteopts,
2272 ] + remoteopts,
2270 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2273 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2271 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2274 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2272 """runs the changeset discovery protocol in isolation"""
2275 """runs the changeset discovery protocol in isolation"""
2273 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2276 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2274 opts.get('branch'))
2277 opts.get('branch'))
2275 remote = hg.peer(repo, opts, remoteurl)
2278 remote = hg.peer(repo, opts, remoteurl)
2276 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2279 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2277
2280
2278 # make sure tests are repeatable
2281 # make sure tests are repeatable
2279 random.seed(12323)
2282 random.seed(12323)
2280
2283
2281 def doit(localheads, remoteheads, remote=remote):
2284 def doit(localheads, remoteheads, remote=remote):
2282 if opts.get('old'):
2285 if opts.get('old'):
2283 if localheads:
2286 if localheads:
2284 raise error.Abort('cannot use localheads with old style '
2287 raise error.Abort('cannot use localheads with old style '
2285 'discovery')
2288 'discovery')
2286 if not util.safehasattr(remote, 'branches'):
2289 if not util.safehasattr(remote, 'branches'):
2287 # enable in-client legacy support
2290 # enable in-client legacy support
2288 remote = localrepo.locallegacypeer(remote.local())
2291 remote = localrepo.locallegacypeer(remote.local())
2289 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2292 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2290 force=True)
2293 force=True)
2291 common = set(common)
2294 common = set(common)
2292 if not opts.get('nonheads'):
2295 if not opts.get('nonheads'):
2293 ui.write(("unpruned common: %s\n") %
2296 ui.write(("unpruned common: %s\n") %
2294 " ".join(sorted(short(n) for n in common)))
2297 " ".join(sorted(short(n) for n in common)))
2295 dag = dagutil.revlogdag(repo.changelog)
2298 dag = dagutil.revlogdag(repo.changelog)
2296 all = dag.ancestorset(dag.internalizeall(common))
2299 all = dag.ancestorset(dag.internalizeall(common))
2297 common = dag.externalizeall(dag.headsetofconnecteds(all))
2300 common = dag.externalizeall(dag.headsetofconnecteds(all))
2298 else:
2301 else:
2299 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2302 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2300 common = set(common)
2303 common = set(common)
2301 rheads = set(hds)
2304 rheads = set(hds)
2302 lheads = set(repo.heads())
2305 lheads = set(repo.heads())
2303 ui.write(("common heads: %s\n") %
2306 ui.write(("common heads: %s\n") %
2304 " ".join(sorted(short(n) for n in common)))
2307 " ".join(sorted(short(n) for n in common)))
2305 if lheads <= common:
2308 if lheads <= common:
2306 ui.write(("local is subset\n"))
2309 ui.write(("local is subset\n"))
2307 elif rheads <= common:
2310 elif rheads <= common:
2308 ui.write(("remote is subset\n"))
2311 ui.write(("remote is subset\n"))
2309
2312
2310 serverlogs = opts.get('serverlog')
2313 serverlogs = opts.get('serverlog')
2311 if serverlogs:
2314 if serverlogs:
2312 for filename in serverlogs:
2315 for filename in serverlogs:
2313 logfile = open(filename, 'r')
2316 logfile = open(filename, 'r')
2314 try:
2317 try:
2315 line = logfile.readline()
2318 line = logfile.readline()
2316 while line:
2319 while line:
2317 parts = line.strip().split(';')
2320 parts = line.strip().split(';')
2318 op = parts[1]
2321 op = parts[1]
2319 if op == 'cg':
2322 if op == 'cg':
2320 pass
2323 pass
2321 elif op == 'cgss':
2324 elif op == 'cgss':
2322 doit(parts[2].split(' '), parts[3].split(' '))
2325 doit(parts[2].split(' '), parts[3].split(' '))
2323 elif op == 'unb':
2326 elif op == 'unb':
2324 doit(parts[3].split(' '), parts[2].split(' '))
2327 doit(parts[3].split(' '), parts[2].split(' '))
2325 line = logfile.readline()
2328 line = logfile.readline()
2326 finally:
2329 finally:
2327 logfile.close()
2330 logfile.close()
2328
2331
2329 else:
2332 else:
2330 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2333 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2331 opts.get('remote_head'))
2334 opts.get('remote_head'))
2332 localrevs = opts.get('local_head')
2335 localrevs = opts.get('local_head')
2333 doit(localrevs, remoterevs)
2336 doit(localrevs, remoterevs)
2334
2337
2335 @command('debugextensions', formatteropts, [], norepo=True)
2338 @command('debugextensions', formatteropts, [], norepo=True)
2336 def debugextensions(ui, **opts):
2339 def debugextensions(ui, **opts):
2337 '''show information about active extensions'''
2340 '''show information about active extensions'''
2338 exts = extensions.extensions(ui)
2341 exts = extensions.extensions(ui)
2339 fm = ui.formatter('debugextensions', opts)
2342 fm = ui.formatter('debugextensions', opts)
2340 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2343 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2341 extsource = extmod.__file__
2344 extsource = extmod.__file__
2342 exttestedwith = getattr(extmod, 'testedwith', None)
2345 exttestedwith = getattr(extmod, 'testedwith', None)
2343 if exttestedwith is not None:
2346 if exttestedwith is not None:
2344 exttestedwith = exttestedwith.split()
2347 exttestedwith = exttestedwith.split()
2345 extbuglink = getattr(extmod, 'buglink', None)
2348 extbuglink = getattr(extmod, 'buglink', None)
2346
2349
2347 fm.startitem()
2350 fm.startitem()
2348
2351
2349 if ui.quiet or ui.verbose:
2352 if ui.quiet or ui.verbose:
2350 fm.write('name', '%s\n', extname)
2353 fm.write('name', '%s\n', extname)
2351 else:
2354 else:
2352 fm.write('name', '%s', extname)
2355 fm.write('name', '%s', extname)
2353 if not exttestedwith:
2356 if not exttestedwith:
2354 fm.plain(_(' (untested!)\n'))
2357 fm.plain(_(' (untested!)\n'))
2355 else:
2358 else:
2356 if exttestedwith == ['internal'] or \
2359 if exttestedwith == ['internal'] or \
2357 util.version() in exttestedwith:
2360 util.version() in exttestedwith:
2358 fm.plain('\n')
2361 fm.plain('\n')
2359 else:
2362 else:
2360 lasttestedversion = exttestedwith[-1]
2363 lasttestedversion = exttestedwith[-1]
2361 fm.plain(' (%s!)\n' % lasttestedversion)
2364 fm.plain(' (%s!)\n' % lasttestedversion)
2362
2365
2363 fm.condwrite(ui.verbose and extsource, 'source',
2366 fm.condwrite(ui.verbose and extsource, 'source',
2364 _(' location: %s\n'), extsource or "")
2367 _(' location: %s\n'), extsource or "")
2365
2368
2366 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2369 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2367 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2370 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2368
2371
2369 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2372 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2370 _(' bug reporting: %s\n'), extbuglink or "")
2373 _(' bug reporting: %s\n'), extbuglink or "")
2371
2374
2372 fm.end()
2375 fm.end()
2373
2376
2374 @command('debugfileset',
2377 @command('debugfileset',
2375 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2378 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2376 _('[-r REV] FILESPEC'))
2379 _('[-r REV] FILESPEC'))
2377 def debugfileset(ui, repo, expr, **opts):
2380 def debugfileset(ui, repo, expr, **opts):
2378 '''parse and apply a fileset specification'''
2381 '''parse and apply a fileset specification'''
2379 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2382 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2380 if ui.verbose:
2383 if ui.verbose:
2381 tree = fileset.parse(expr)
2384 tree = fileset.parse(expr)
2382 ui.note(fileset.prettyformat(tree), "\n")
2385 ui.note(fileset.prettyformat(tree), "\n")
2383
2386
2384 for f in ctx.getfileset(expr):
2387 for f in ctx.getfileset(expr):
2385 ui.write("%s\n" % f)
2388 ui.write("%s\n" % f)
2386
2389
2387 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2390 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2388 def debugfsinfo(ui, path="."):
2391 def debugfsinfo(ui, path="."):
2389 """show information detected about current filesystem"""
2392 """show information detected about current filesystem"""
2390 util.writefile('.debugfsinfo', '')
2393 util.writefile('.debugfsinfo', '')
2391 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2394 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2392 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2395 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2393 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2396 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2394 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2397 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2395 and 'yes' or 'no'))
2398 and 'yes' or 'no'))
2396 os.unlink('.debugfsinfo')
2399 os.unlink('.debugfsinfo')
2397
2400
2398 @command('debuggetbundle',
2401 @command('debuggetbundle',
2399 [('H', 'head', [], _('id of head node'), _('ID')),
2402 [('H', 'head', [], _('id of head node'), _('ID')),
2400 ('C', 'common', [], _('id of common node'), _('ID')),
2403 ('C', 'common', [], _('id of common node'), _('ID')),
2401 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2404 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2402 _('REPO FILE [-H|-C ID]...'),
2405 _('REPO FILE [-H|-C ID]...'),
2403 norepo=True)
2406 norepo=True)
2404 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2407 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2405 """retrieves a bundle from a repo
2408 """retrieves a bundle from a repo
2406
2409
2407 Every ID must be a full-length hex node id string. Saves the bundle to the
2410 Every ID must be a full-length hex node id string. Saves the bundle to the
2408 given file.
2411 given file.
2409 """
2412 """
2410 repo = hg.peer(ui, opts, repopath)
2413 repo = hg.peer(ui, opts, repopath)
2411 if not repo.capable('getbundle'):
2414 if not repo.capable('getbundle'):
2412 raise error.Abort("getbundle() not supported by target repository")
2415 raise error.Abort("getbundle() not supported by target repository")
2413 args = {}
2416 args = {}
2414 if common:
2417 if common:
2415 args['common'] = [bin(s) for s in common]
2418 args['common'] = [bin(s) for s in common]
2416 if head:
2419 if head:
2417 args['heads'] = [bin(s) for s in head]
2420 args['heads'] = [bin(s) for s in head]
2418 # TODO: get desired bundlecaps from command line.
2421 # TODO: get desired bundlecaps from command line.
2419 args['bundlecaps'] = None
2422 args['bundlecaps'] = None
2420 bundle = repo.getbundle('debug', **args)
2423 bundle = repo.getbundle('debug', **args)
2421
2424
2422 bundletype = opts.get('type', 'bzip2').lower()
2425 bundletype = opts.get('type', 'bzip2').lower()
2423 btypes = {'none': 'HG10UN',
2426 btypes = {'none': 'HG10UN',
2424 'bzip2': 'HG10BZ',
2427 'bzip2': 'HG10BZ',
2425 'gzip': 'HG10GZ',
2428 'gzip': 'HG10GZ',
2426 'bundle2': 'HG20'}
2429 'bundle2': 'HG20'}
2427 bundletype = btypes.get(bundletype)
2430 bundletype = btypes.get(bundletype)
2428 if bundletype not in changegroup.bundletypes:
2431 if bundletype not in changegroup.bundletypes:
2429 raise error.Abort(_('unknown bundle type specified with --type'))
2432 raise error.Abort(_('unknown bundle type specified with --type'))
2430 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2433 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2431
2434
2432 @command('debugignore', [], '')
2435 @command('debugignore', [], '')
2433 def debugignore(ui, repo, *values, **opts):
2436 def debugignore(ui, repo, *values, **opts):
2434 """display the combined ignore pattern"""
2437 """display the combined ignore pattern"""
2435 ignore = repo.dirstate._ignore
2438 ignore = repo.dirstate._ignore
2436 includepat = getattr(ignore, 'includepat', None)
2439 includepat = getattr(ignore, 'includepat', None)
2437 if includepat is not None:
2440 if includepat is not None:
2438 ui.write("%s\n" % includepat)
2441 ui.write("%s\n" % includepat)
2439 else:
2442 else:
2440 raise error.Abort(_("no ignore patterns found"))
2443 raise error.Abort(_("no ignore patterns found"))
2441
2444
2442 @command('debugindex', debugrevlogopts +
2445 @command('debugindex', debugrevlogopts +
2443 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2446 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2444 _('[-f FORMAT] -c|-m|FILE'),
2447 _('[-f FORMAT] -c|-m|FILE'),
2445 optionalrepo=True)
2448 optionalrepo=True)
2446 def debugindex(ui, repo, file_=None, **opts):
2449 def debugindex(ui, repo, file_=None, **opts):
2447 """dump the contents of an index file"""
2450 """dump the contents of an index file"""
2448 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2451 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2449 format = opts.get('format', 0)
2452 format = opts.get('format', 0)
2450 if format not in (0, 1):
2453 if format not in (0, 1):
2451 raise error.Abort(_("unknown format %d") % format)
2454 raise error.Abort(_("unknown format %d") % format)
2452
2455
2453 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2456 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2454 if generaldelta:
2457 if generaldelta:
2455 basehdr = ' delta'
2458 basehdr = ' delta'
2456 else:
2459 else:
2457 basehdr = ' base'
2460 basehdr = ' base'
2458
2461
2459 if ui.debugflag:
2462 if ui.debugflag:
2460 shortfn = hex
2463 shortfn = hex
2461 else:
2464 else:
2462 shortfn = short
2465 shortfn = short
2463
2466
2464 # There might not be anything in r, so have a sane default
2467 # There might not be anything in r, so have a sane default
2465 idlen = 12
2468 idlen = 12
2466 for i in r:
2469 for i in r:
2467 idlen = len(shortfn(r.node(i)))
2470 idlen = len(shortfn(r.node(i)))
2468 break
2471 break
2469
2472
2470 if format == 0:
2473 if format == 0:
2471 ui.write(" rev offset length " + basehdr + " linkrev"
2474 ui.write(" rev offset length " + basehdr + " linkrev"
2472 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2475 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2473 elif format == 1:
2476 elif format == 1:
2474 ui.write(" rev flag offset length"
2477 ui.write(" rev flag offset length"
2475 " size " + basehdr + " link p1 p2"
2478 " size " + basehdr + " link p1 p2"
2476 " %s\n" % "nodeid".rjust(idlen))
2479 " %s\n" % "nodeid".rjust(idlen))
2477
2480
2478 for i in r:
2481 for i in r:
2479 node = r.node(i)
2482 node = r.node(i)
2480 if generaldelta:
2483 if generaldelta:
2481 base = r.deltaparent(i)
2484 base = r.deltaparent(i)
2482 else:
2485 else:
2483 base = r.chainbase(i)
2486 base = r.chainbase(i)
2484 if format == 0:
2487 if format == 0:
2485 try:
2488 try:
2486 pp = r.parents(node)
2489 pp = r.parents(node)
2487 except Exception:
2490 except Exception:
2488 pp = [nullid, nullid]
2491 pp = [nullid, nullid]
2489 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2492 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2490 i, r.start(i), r.length(i), base, r.linkrev(i),
2493 i, r.start(i), r.length(i), base, r.linkrev(i),
2491 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2494 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2492 elif format == 1:
2495 elif format == 1:
2493 pr = r.parentrevs(i)
2496 pr = r.parentrevs(i)
2494 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2497 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2495 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2498 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2496 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2499 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2497
2500
2498 @command('debugindexdot', debugrevlogopts,
2501 @command('debugindexdot', debugrevlogopts,
2499 _('-c|-m|FILE'), optionalrepo=True)
2502 _('-c|-m|FILE'), optionalrepo=True)
2500 def debugindexdot(ui, repo, file_=None, **opts):
2503 def debugindexdot(ui, repo, file_=None, **opts):
2501 """dump an index DAG as a graphviz dot file"""
2504 """dump an index DAG as a graphviz dot file"""
2502 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2505 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2503 ui.write(("digraph G {\n"))
2506 ui.write(("digraph G {\n"))
2504 for i in r:
2507 for i in r:
2505 node = r.node(i)
2508 node = r.node(i)
2506 pp = r.parents(node)
2509 pp = r.parents(node)
2507 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2510 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2508 if pp[1] != nullid:
2511 if pp[1] != nullid:
2509 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2512 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2510 ui.write("}\n")
2513 ui.write("}\n")
2511
2514
2512 @command('debugdeltachain',
2515 @command('debugdeltachain',
2513 debugrevlogopts + formatteropts,
2516 debugrevlogopts + formatteropts,
2514 _('-c|-m|FILE'),
2517 _('-c|-m|FILE'),
2515 optionalrepo=True)
2518 optionalrepo=True)
2516 def debugdeltachain(ui, repo, file_=None, **opts):
2519 def debugdeltachain(ui, repo, file_=None, **opts):
2517 """dump information about delta chains in a revlog
2520 """dump information about delta chains in a revlog
2518
2521
2519 Output can be templatized. Available template keywords are:
2522 Output can be templatized. Available template keywords are:
2520
2523
2521 rev revision number
2524 rev revision number
2522 chainid delta chain identifier (numbered by unique base)
2525 chainid delta chain identifier (numbered by unique base)
2523 chainlen delta chain length to this revision
2526 chainlen delta chain length to this revision
2524 prevrev previous revision in delta chain
2527 prevrev previous revision in delta chain
2525 deltatype role of delta / how it was computed
2528 deltatype role of delta / how it was computed
2526 compsize compressed size of revision
2529 compsize compressed size of revision
2527 uncompsize uncompressed size of revision
2530 uncompsize uncompressed size of revision
2528 chainsize total size of compressed revisions in chain
2531 chainsize total size of compressed revisions in chain
2529 chainratio total chain size divided by uncompressed revision size
2532 chainratio total chain size divided by uncompressed revision size
2530 (new delta chains typically start at ratio 2.00)
2533 (new delta chains typically start at ratio 2.00)
2531 lindist linear distance from base revision in delta chain to end
2534 lindist linear distance from base revision in delta chain to end
2532 of this revision
2535 of this revision
2533 extradist total size of revisions not part of this delta chain from
2536 extradist total size of revisions not part of this delta chain from
2534 base of delta chain to end of this revision; a measurement
2537 base of delta chain to end of this revision; a measurement
2535 of how much extra data we need to read/seek across to read
2538 of how much extra data we need to read/seek across to read
2536 the delta chain for this revision
2539 the delta chain for this revision
2537 extraratio extradist divided by chainsize; another representation of
2540 extraratio extradist divided by chainsize; another representation of
2538 how much unrelated data is needed to load this delta chain
2541 how much unrelated data is needed to load this delta chain
2539 """
2542 """
2540 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2543 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2541 index = r.index
2544 index = r.index
2542 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2545 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2543
2546
2544 def revinfo(rev):
2547 def revinfo(rev):
2545 e = index[rev]
2548 e = index[rev]
2546 compsize = e[1]
2549 compsize = e[1]
2547 uncompsize = e[2]
2550 uncompsize = e[2]
2548 chainsize = 0
2551 chainsize = 0
2549
2552
2550 if generaldelta:
2553 if generaldelta:
2551 if e[3] == e[5]:
2554 if e[3] == e[5]:
2552 deltatype = 'p1'
2555 deltatype = 'p1'
2553 elif e[3] == e[6]:
2556 elif e[3] == e[6]:
2554 deltatype = 'p2'
2557 deltatype = 'p2'
2555 elif e[3] == rev - 1:
2558 elif e[3] == rev - 1:
2556 deltatype = 'prev'
2559 deltatype = 'prev'
2557 elif e[3] == rev:
2560 elif e[3] == rev:
2558 deltatype = 'base'
2561 deltatype = 'base'
2559 else:
2562 else:
2560 deltatype = 'other'
2563 deltatype = 'other'
2561 else:
2564 else:
2562 if e[3] == rev:
2565 if e[3] == rev:
2563 deltatype = 'base'
2566 deltatype = 'base'
2564 else:
2567 else:
2565 deltatype = 'prev'
2568 deltatype = 'prev'
2566
2569
2567 chain = r._deltachain(rev)[0]
2570 chain = r._deltachain(rev)[0]
2568 for iterrev in chain:
2571 for iterrev in chain:
2569 e = index[iterrev]
2572 e = index[iterrev]
2570 chainsize += e[1]
2573 chainsize += e[1]
2571
2574
2572 return compsize, uncompsize, deltatype, chain, chainsize
2575 return compsize, uncompsize, deltatype, chain, chainsize
2573
2576
2574 fm = ui.formatter('debugdeltachain', opts)
2577 fm = ui.formatter('debugdeltachain', opts)
2575
2578
2576 fm.plain(' rev chain# chainlen prev delta '
2579 fm.plain(' rev chain# chainlen prev delta '
2577 'size rawsize chainsize ratio lindist extradist '
2580 'size rawsize chainsize ratio lindist extradist '
2578 'extraratio\n')
2581 'extraratio\n')
2579
2582
2580 chainbases = {}
2583 chainbases = {}
2581 for rev in r:
2584 for rev in r:
2582 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2585 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2583 chainbase = chain[0]
2586 chainbase = chain[0]
2584 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2587 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2585 basestart = r.start(chainbase)
2588 basestart = r.start(chainbase)
2586 revstart = r.start(rev)
2589 revstart = r.start(rev)
2587 lineardist = revstart + comp - basestart
2590 lineardist = revstart + comp - basestart
2588 extradist = lineardist - chainsize
2591 extradist = lineardist - chainsize
2589 try:
2592 try:
2590 prevrev = chain[-2]
2593 prevrev = chain[-2]
2591 except IndexError:
2594 except IndexError:
2592 prevrev = -1
2595 prevrev = -1
2593
2596
2594 chainratio = float(chainsize) / float(uncomp)
2597 chainratio = float(chainsize) / float(uncomp)
2595 extraratio = float(extradist) / float(chainsize)
2598 extraratio = float(extradist) / float(chainsize)
2596
2599
2597 fm.startitem()
2600 fm.startitem()
2598 fm.write('rev chainid chainlen prevrev deltatype compsize '
2601 fm.write('rev chainid chainlen prevrev deltatype compsize '
2599 'uncompsize chainsize chainratio lindist extradist '
2602 'uncompsize chainsize chainratio lindist extradist '
2600 'extraratio',
2603 'extraratio',
2601 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2604 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2602 rev, chainid, len(chain), prevrev, deltatype, comp,
2605 rev, chainid, len(chain), prevrev, deltatype, comp,
2603 uncomp, chainsize, chainratio, lineardist, extradist,
2606 uncomp, chainsize, chainratio, lineardist, extradist,
2604 extraratio,
2607 extraratio,
2605 rev=rev, chainid=chainid, chainlen=len(chain),
2608 rev=rev, chainid=chainid, chainlen=len(chain),
2606 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2609 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2607 uncompsize=uncomp, chainsize=chainsize,
2610 uncompsize=uncomp, chainsize=chainsize,
2608 chainratio=chainratio, lindist=lineardist,
2611 chainratio=chainratio, lindist=lineardist,
2609 extradist=extradist, extraratio=extraratio)
2612 extradist=extradist, extraratio=extraratio)
2610
2613
2611 fm.end()
2614 fm.end()
2612
2615
2613 @command('debuginstall', [], '', norepo=True)
2616 @command('debuginstall', [], '', norepo=True)
2614 def debuginstall(ui):
2617 def debuginstall(ui):
2615 '''test Mercurial installation
2618 '''test Mercurial installation
2616
2619
2617 Returns 0 on success.
2620 Returns 0 on success.
2618 '''
2621 '''
2619
2622
2620 def writetemp(contents):
2623 def writetemp(contents):
2621 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2624 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2622 f = os.fdopen(fd, "wb")
2625 f = os.fdopen(fd, "wb")
2623 f.write(contents)
2626 f.write(contents)
2624 f.close()
2627 f.close()
2625 return name
2628 return name
2626
2629
2627 problems = 0
2630 problems = 0
2628
2631
2629 # encoding
2632 # encoding
2630 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2633 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2631 try:
2634 try:
2632 encoding.fromlocal("test")
2635 encoding.fromlocal("test")
2633 except error.Abort as inst:
2636 except error.Abort as inst:
2634 ui.write(" %s\n" % inst)
2637 ui.write(" %s\n" % inst)
2635 ui.write(_(" (check that your locale is properly set)\n"))
2638 ui.write(_(" (check that your locale is properly set)\n"))
2636 problems += 1
2639 problems += 1
2637
2640
2638 # Python
2641 # Python
2639 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2642 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2640 ui.status(_("checking Python version (%s)\n")
2643 ui.status(_("checking Python version (%s)\n")
2641 % ("%s.%s.%s" % sys.version_info[:3]))
2644 % ("%s.%s.%s" % sys.version_info[:3]))
2642 ui.status(_("checking Python lib (%s)...\n")
2645 ui.status(_("checking Python lib (%s)...\n")
2643 % os.path.dirname(os.__file__))
2646 % os.path.dirname(os.__file__))
2644
2647
2645 # compiled modules
2648 # compiled modules
2646 ui.status(_("checking installed modules (%s)...\n")
2649 ui.status(_("checking installed modules (%s)...\n")
2647 % os.path.dirname(__file__))
2650 % os.path.dirname(__file__))
2648 try:
2651 try:
2649 import bdiff, mpatch, base85, osutil
2652 import bdiff, mpatch, base85, osutil
2650 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2653 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2651 except Exception as inst:
2654 except Exception as inst:
2652 ui.write(" %s\n" % inst)
2655 ui.write(" %s\n" % inst)
2653 ui.write(_(" One or more extensions could not be found"))
2656 ui.write(_(" One or more extensions could not be found"))
2654 ui.write(_(" (check that you compiled the extensions)\n"))
2657 ui.write(_(" (check that you compiled the extensions)\n"))
2655 problems += 1
2658 problems += 1
2656
2659
2657 # templates
2660 # templates
2658 import templater
2661 import templater
2659 p = templater.templatepaths()
2662 p = templater.templatepaths()
2660 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2663 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2661 if p:
2664 if p:
2662 m = templater.templatepath("map-cmdline.default")
2665 m = templater.templatepath("map-cmdline.default")
2663 if m:
2666 if m:
2664 # template found, check if it is working
2667 # template found, check if it is working
2665 try:
2668 try:
2666 templater.templater(m)
2669 templater.templater(m)
2667 except Exception as inst:
2670 except Exception as inst:
2668 ui.write(" %s\n" % inst)
2671 ui.write(" %s\n" % inst)
2669 p = None
2672 p = None
2670 else:
2673 else:
2671 ui.write(_(" template 'default' not found\n"))
2674 ui.write(_(" template 'default' not found\n"))
2672 p = None
2675 p = None
2673 else:
2676 else:
2674 ui.write(_(" no template directories found\n"))
2677 ui.write(_(" no template directories found\n"))
2675 if not p:
2678 if not p:
2676 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2679 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2677 problems += 1
2680 problems += 1
2678
2681
2679 # editor
2682 # editor
2680 ui.status(_("checking commit editor...\n"))
2683 ui.status(_("checking commit editor...\n"))
2681 editor = ui.geteditor()
2684 editor = ui.geteditor()
2682 editor = util.expandpath(editor)
2685 editor = util.expandpath(editor)
2683 cmdpath = util.findexe(shlex.split(editor)[0])
2686 cmdpath = util.findexe(shlex.split(editor)[0])
2684 if not cmdpath:
2687 if not cmdpath:
2685 if editor == 'vi':
2688 if editor == 'vi':
2686 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2689 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2687 ui.write(_(" (specify a commit editor in your configuration"
2690 ui.write(_(" (specify a commit editor in your configuration"
2688 " file)\n"))
2691 " file)\n"))
2689 else:
2692 else:
2690 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2693 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2691 ui.write(_(" (specify a commit editor in your configuration"
2694 ui.write(_(" (specify a commit editor in your configuration"
2692 " file)\n"))
2695 " file)\n"))
2693 problems += 1
2696 problems += 1
2694
2697
2695 # check username
2698 # check username
2696 ui.status(_("checking username...\n"))
2699 ui.status(_("checking username...\n"))
2697 try:
2700 try:
2698 ui.username()
2701 ui.username()
2699 except error.Abort as e:
2702 except error.Abort as e:
2700 ui.write(" %s\n" % e)
2703 ui.write(" %s\n" % e)
2701 ui.write(_(" (specify a username in your configuration file)\n"))
2704 ui.write(_(" (specify a username in your configuration file)\n"))
2702 problems += 1
2705 problems += 1
2703
2706
2704 if not problems:
2707 if not problems:
2705 ui.status(_("no problems detected\n"))
2708 ui.status(_("no problems detected\n"))
2706 else:
2709 else:
2707 ui.write(_("%s problems detected,"
2710 ui.write(_("%s problems detected,"
2708 " please check your install!\n") % problems)
2711 " please check your install!\n") % problems)
2709
2712
2710 return problems
2713 return problems
2711
2714
2712 @command('debugknown', [], _('REPO ID...'), norepo=True)
2715 @command('debugknown', [], _('REPO ID...'), norepo=True)
2713 def debugknown(ui, repopath, *ids, **opts):
2716 def debugknown(ui, repopath, *ids, **opts):
2714 """test whether node ids are known to a repo
2717 """test whether node ids are known to a repo
2715
2718
2716 Every ID must be a full-length hex node id string. Returns a list of 0s
2719 Every ID must be a full-length hex node id string. Returns a list of 0s
2717 and 1s indicating unknown/known.
2720 and 1s indicating unknown/known.
2718 """
2721 """
2719 repo = hg.peer(ui, opts, repopath)
2722 repo = hg.peer(ui, opts, repopath)
2720 if not repo.capable('known'):
2723 if not repo.capable('known'):
2721 raise error.Abort("known() not supported by target repository")
2724 raise error.Abort("known() not supported by target repository")
2722 flags = repo.known([bin(s) for s in ids])
2725 flags = repo.known([bin(s) for s in ids])
2723 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2726 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2724
2727
2725 @command('debuglabelcomplete', [], _('LABEL...'))
2728 @command('debuglabelcomplete', [], _('LABEL...'))
2726 def debuglabelcomplete(ui, repo, *args):
2729 def debuglabelcomplete(ui, repo, *args):
2727 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2730 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2728 debugnamecomplete(ui, repo, *args)
2731 debugnamecomplete(ui, repo, *args)
2729
2732
2730 @command('debugmergestate', [], '')
2733 @command('debugmergestate', [], '')
2731 def debugmergestate(ui, repo, *args):
2734 def debugmergestate(ui, repo, *args):
2732 """print merge state
2735 """print merge state
2733
2736
2734 Use --verbose to print out information about whether v1 or v2 merge state
2737 Use --verbose to print out information about whether v1 or v2 merge state
2735 was chosen."""
2738 was chosen."""
2736 def _hashornull(h):
2739 def _hashornull(h):
2737 if h == nullhex:
2740 if h == nullhex:
2738 return 'null'
2741 return 'null'
2739 else:
2742 else:
2740 return h
2743 return h
2741
2744
2742 def printrecords(version):
2745 def printrecords(version):
2743 ui.write(('* version %s records\n') % version)
2746 ui.write(('* version %s records\n') % version)
2744 if version == 1:
2747 if version == 1:
2745 records = v1records
2748 records = v1records
2746 else:
2749 else:
2747 records = v2records
2750 records = v2records
2748
2751
2749 for rtype, record in records:
2752 for rtype, record in records:
2750 # pretty print some record types
2753 # pretty print some record types
2751 if rtype == 'L':
2754 if rtype == 'L':
2752 ui.write(('local: %s\n') % record)
2755 ui.write(('local: %s\n') % record)
2753 elif rtype == 'O':
2756 elif rtype == 'O':
2754 ui.write(('other: %s\n') % record)
2757 ui.write(('other: %s\n') % record)
2755 elif rtype == 'm':
2758 elif rtype == 'm':
2756 driver, mdstate = record.split('\0', 1)
2759 driver, mdstate = record.split('\0', 1)
2757 ui.write(('merge driver: %s (state "%s")\n')
2760 ui.write(('merge driver: %s (state "%s")\n')
2758 % (driver, mdstate))
2761 % (driver, mdstate))
2759 elif rtype in 'FDC':
2762 elif rtype in 'FDC':
2760 r = record.split('\0')
2763 r = record.split('\0')
2761 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2764 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2762 if version == 1:
2765 if version == 1:
2763 onode = 'not stored in v1 format'
2766 onode = 'not stored in v1 format'
2764 flags = r[7]
2767 flags = r[7]
2765 else:
2768 else:
2766 onode, flags = r[7:9]
2769 onode, flags = r[7:9]
2767 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2770 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2768 % (f, rtype, state, _hashornull(hash)))
2771 % (f, rtype, state, _hashornull(hash)))
2769 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2772 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2770 ui.write((' ancestor path: %s (node %s)\n')
2773 ui.write((' ancestor path: %s (node %s)\n')
2771 % (afile, _hashornull(anode)))
2774 % (afile, _hashornull(anode)))
2772 ui.write((' other path: %s (node %s)\n')
2775 ui.write((' other path: %s (node %s)\n')
2773 % (ofile, _hashornull(onode)))
2776 % (ofile, _hashornull(onode)))
2774 else:
2777 else:
2775 ui.write(('unrecognized entry: %s\t%s\n')
2778 ui.write(('unrecognized entry: %s\t%s\n')
2776 % (rtype, record.replace('\0', '\t')))
2779 % (rtype, record.replace('\0', '\t')))
2777
2780
2778 # Avoid mergestate.read() since it may raise an exception for unsupported
2781 # Avoid mergestate.read() since it may raise an exception for unsupported
2779 # merge state records. We shouldn't be doing this, but this is OK since this
2782 # merge state records. We shouldn't be doing this, but this is OK since this
2780 # command is pretty low-level.
2783 # command is pretty low-level.
2781 ms = mergemod.mergestate(repo)
2784 ms = mergemod.mergestate(repo)
2782
2785
2783 # sort so that reasonable information is on top
2786 # sort so that reasonable information is on top
2784 v1records = ms._readrecordsv1()
2787 v1records = ms._readrecordsv1()
2785 v2records = ms._readrecordsv2()
2788 v2records = ms._readrecordsv2()
2786 order = 'LOm'
2789 order = 'LOm'
2787 def key(r):
2790 def key(r):
2788 idx = order.find(r[0])
2791 idx = order.find(r[0])
2789 if idx == -1:
2792 if idx == -1:
2790 return (1, r[1])
2793 return (1, r[1])
2791 else:
2794 else:
2792 return (0, idx)
2795 return (0, idx)
2793 v1records.sort(key=key)
2796 v1records.sort(key=key)
2794 v2records.sort(key=key)
2797 v2records.sort(key=key)
2795
2798
2796 if not v1records and not v2records:
2799 if not v1records and not v2records:
2797 ui.write(('no merge state found\n'))
2800 ui.write(('no merge state found\n'))
2798 elif not v2records:
2801 elif not v2records:
2799 ui.note(('no version 2 merge state\n'))
2802 ui.note(('no version 2 merge state\n'))
2800 printrecords(1)
2803 printrecords(1)
2801 elif ms._v1v2match(v1records, v2records):
2804 elif ms._v1v2match(v1records, v2records):
2802 ui.note(('v1 and v2 states match: using v2\n'))
2805 ui.note(('v1 and v2 states match: using v2\n'))
2803 printrecords(2)
2806 printrecords(2)
2804 else:
2807 else:
2805 ui.note(('v1 and v2 states mismatch: using v1\n'))
2808 ui.note(('v1 and v2 states mismatch: using v1\n'))
2806 printrecords(1)
2809 printrecords(1)
2807 if ui.verbose:
2810 if ui.verbose:
2808 printrecords(2)
2811 printrecords(2)
2809
2812
2810 @command('debugnamecomplete', [], _('NAME...'))
2813 @command('debugnamecomplete', [], _('NAME...'))
2811 def debugnamecomplete(ui, repo, *args):
2814 def debugnamecomplete(ui, repo, *args):
2812 '''complete "names" - tags, open branch names, bookmark names'''
2815 '''complete "names" - tags, open branch names, bookmark names'''
2813
2816
2814 names = set()
2817 names = set()
2815 # since we previously only listed open branches, we will handle that
2818 # since we previously only listed open branches, we will handle that
2816 # specially (after this for loop)
2819 # specially (after this for loop)
2817 for name, ns in repo.names.iteritems():
2820 for name, ns in repo.names.iteritems():
2818 if name != 'branches':
2821 if name != 'branches':
2819 names.update(ns.listnames(repo))
2822 names.update(ns.listnames(repo))
2820 names.update(tag for (tag, heads, tip, closed)
2823 names.update(tag for (tag, heads, tip, closed)
2821 in repo.branchmap().iterbranches() if not closed)
2824 in repo.branchmap().iterbranches() if not closed)
2822 completions = set()
2825 completions = set()
2823 if not args:
2826 if not args:
2824 args = ['']
2827 args = ['']
2825 for a in args:
2828 for a in args:
2826 completions.update(n for n in names if n.startswith(a))
2829 completions.update(n for n in names if n.startswith(a))
2827 ui.write('\n'.join(sorted(completions)))
2830 ui.write('\n'.join(sorted(completions)))
2828 ui.write('\n')
2831 ui.write('\n')
2829
2832
2830 @command('debuglocks',
2833 @command('debuglocks',
2831 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2834 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2832 ('W', 'force-wlock', None,
2835 ('W', 'force-wlock', None,
2833 _('free the working state lock (DANGEROUS)'))],
2836 _('free the working state lock (DANGEROUS)'))],
2834 _('[OPTION]...'))
2837 _('[OPTION]...'))
2835 def debuglocks(ui, repo, **opts):
2838 def debuglocks(ui, repo, **opts):
2836 """show or modify state of locks
2839 """show or modify state of locks
2837
2840
2838 By default, this command will show which locks are held. This
2841 By default, this command will show which locks are held. This
2839 includes the user and process holding the lock, the amount of time
2842 includes the user and process holding the lock, the amount of time
2840 the lock has been held, and the machine name where the process is
2843 the lock has been held, and the machine name where the process is
2841 running if it's not local.
2844 running if it's not local.
2842
2845
2843 Locks protect the integrity of Mercurial's data, so should be
2846 Locks protect the integrity of Mercurial's data, so should be
2844 treated with care. System crashes or other interruptions may cause
2847 treated with care. System crashes or other interruptions may cause
2845 locks to not be properly released, though Mercurial will usually
2848 locks to not be properly released, though Mercurial will usually
2846 detect and remove such stale locks automatically.
2849 detect and remove such stale locks automatically.
2847
2850
2848 However, detecting stale locks may not always be possible (for
2851 However, detecting stale locks may not always be possible (for
2849 instance, on a shared filesystem). Removing locks may also be
2852 instance, on a shared filesystem). Removing locks may also be
2850 blocked by filesystem permissions.
2853 blocked by filesystem permissions.
2851
2854
2852 Returns 0 if no locks are held.
2855 Returns 0 if no locks are held.
2853
2856
2854 """
2857 """
2855
2858
2856 if opts.get('force_lock'):
2859 if opts.get('force_lock'):
2857 repo.svfs.unlink('lock')
2860 repo.svfs.unlink('lock')
2858 if opts.get('force_wlock'):
2861 if opts.get('force_wlock'):
2859 repo.vfs.unlink('wlock')
2862 repo.vfs.unlink('wlock')
2860 if opts.get('force_lock') or opts.get('force_lock'):
2863 if opts.get('force_lock') or opts.get('force_lock'):
2861 return 0
2864 return 0
2862
2865
2863 now = time.time()
2866 now = time.time()
2864 held = 0
2867 held = 0
2865
2868
2866 def report(vfs, name, method):
2869 def report(vfs, name, method):
2867 # this causes stale locks to get reaped for more accurate reporting
2870 # this causes stale locks to get reaped for more accurate reporting
2868 try:
2871 try:
2869 l = method(False)
2872 l = method(False)
2870 except error.LockHeld:
2873 except error.LockHeld:
2871 l = None
2874 l = None
2872
2875
2873 if l:
2876 if l:
2874 l.release()
2877 l.release()
2875 else:
2878 else:
2876 try:
2879 try:
2877 stat = vfs.lstat(name)
2880 stat = vfs.lstat(name)
2878 age = now - stat.st_mtime
2881 age = now - stat.st_mtime
2879 user = util.username(stat.st_uid)
2882 user = util.username(stat.st_uid)
2880 locker = vfs.readlock(name)
2883 locker = vfs.readlock(name)
2881 if ":" in locker:
2884 if ":" in locker:
2882 host, pid = locker.split(':')
2885 host, pid = locker.split(':')
2883 if host == socket.gethostname():
2886 if host == socket.gethostname():
2884 locker = 'user %s, process %s' % (user, pid)
2887 locker = 'user %s, process %s' % (user, pid)
2885 else:
2888 else:
2886 locker = 'user %s, process %s, host %s' \
2889 locker = 'user %s, process %s, host %s' \
2887 % (user, pid, host)
2890 % (user, pid, host)
2888 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2891 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2889 return 1
2892 return 1
2890 except OSError as e:
2893 except OSError as e:
2891 if e.errno != errno.ENOENT:
2894 if e.errno != errno.ENOENT:
2892 raise
2895 raise
2893
2896
2894 ui.write("%-6s free\n" % (name + ":"))
2897 ui.write("%-6s free\n" % (name + ":"))
2895 return 0
2898 return 0
2896
2899
2897 held += report(repo.svfs, "lock", repo.lock)
2900 held += report(repo.svfs, "lock", repo.lock)
2898 held += report(repo.vfs, "wlock", repo.wlock)
2901 held += report(repo.vfs, "wlock", repo.wlock)
2899
2902
2900 return held
2903 return held
2901
2904
2902 @command('debugobsolete',
2905 @command('debugobsolete',
2903 [('', 'flags', 0, _('markers flag')),
2906 [('', 'flags', 0, _('markers flag')),
2904 ('', 'record-parents', False,
2907 ('', 'record-parents', False,
2905 _('record parent information for the precursor')),
2908 _('record parent information for the precursor')),
2906 ('r', 'rev', [], _('display markers relevant to REV')),
2909 ('r', 'rev', [], _('display markers relevant to REV')),
2907 ] + commitopts2,
2910 ] + commitopts2,
2908 _('[OBSOLETED [REPLACEMENT ...]]'))
2911 _('[OBSOLETED [REPLACEMENT ...]]'))
2909 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2912 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2910 """create arbitrary obsolete marker
2913 """create arbitrary obsolete marker
2911
2914
2912 With no arguments, displays the list of obsolescence markers."""
2915 With no arguments, displays the list of obsolescence markers."""
2913
2916
2914 def parsenodeid(s):
2917 def parsenodeid(s):
2915 try:
2918 try:
2916 # We do not use revsingle/revrange functions here to accept
2919 # We do not use revsingle/revrange functions here to accept
2917 # arbitrary node identifiers, possibly not present in the
2920 # arbitrary node identifiers, possibly not present in the
2918 # local repository.
2921 # local repository.
2919 n = bin(s)
2922 n = bin(s)
2920 if len(n) != len(nullid):
2923 if len(n) != len(nullid):
2921 raise TypeError()
2924 raise TypeError()
2922 return n
2925 return n
2923 except TypeError:
2926 except TypeError:
2924 raise error.Abort('changeset references must be full hexadecimal '
2927 raise error.Abort('changeset references must be full hexadecimal '
2925 'node identifiers')
2928 'node identifiers')
2926
2929
2927 if precursor is not None:
2930 if precursor is not None:
2928 if opts['rev']:
2931 if opts['rev']:
2929 raise error.Abort('cannot select revision when creating marker')
2932 raise error.Abort('cannot select revision when creating marker')
2930 metadata = {}
2933 metadata = {}
2931 metadata['user'] = opts['user'] or ui.username()
2934 metadata['user'] = opts['user'] or ui.username()
2932 succs = tuple(parsenodeid(succ) for succ in successors)
2935 succs = tuple(parsenodeid(succ) for succ in successors)
2933 l = repo.lock()
2936 l = repo.lock()
2934 try:
2937 try:
2935 tr = repo.transaction('debugobsolete')
2938 tr = repo.transaction('debugobsolete')
2936 try:
2939 try:
2937 date = opts.get('date')
2940 date = opts.get('date')
2938 if date:
2941 if date:
2939 date = util.parsedate(date)
2942 date = util.parsedate(date)
2940 else:
2943 else:
2941 date = None
2944 date = None
2942 prec = parsenodeid(precursor)
2945 prec = parsenodeid(precursor)
2943 parents = None
2946 parents = None
2944 if opts['record_parents']:
2947 if opts['record_parents']:
2945 if prec not in repo.unfiltered():
2948 if prec not in repo.unfiltered():
2946 raise error.Abort('cannot used --record-parents on '
2949 raise error.Abort('cannot used --record-parents on '
2947 'unknown changesets')
2950 'unknown changesets')
2948 parents = repo.unfiltered()[prec].parents()
2951 parents = repo.unfiltered()[prec].parents()
2949 parents = tuple(p.node() for p in parents)
2952 parents = tuple(p.node() for p in parents)
2950 repo.obsstore.create(tr, prec, succs, opts['flags'],
2953 repo.obsstore.create(tr, prec, succs, opts['flags'],
2951 parents=parents, date=date,
2954 parents=parents, date=date,
2952 metadata=metadata)
2955 metadata=metadata)
2953 tr.close()
2956 tr.close()
2954 except ValueError as exc:
2957 except ValueError as exc:
2955 raise error.Abort(_('bad obsmarker input: %s') % exc)
2958 raise error.Abort(_('bad obsmarker input: %s') % exc)
2956 finally:
2959 finally:
2957 tr.release()
2960 tr.release()
2958 finally:
2961 finally:
2959 l.release()
2962 l.release()
2960 else:
2963 else:
2961 if opts['rev']:
2964 if opts['rev']:
2962 revs = scmutil.revrange(repo, opts['rev'])
2965 revs = scmutil.revrange(repo, opts['rev'])
2963 nodes = [repo[r].node() for r in revs]
2966 nodes = [repo[r].node() for r in revs]
2964 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2967 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2965 markers.sort(key=lambda x: x._data)
2968 markers.sort(key=lambda x: x._data)
2966 else:
2969 else:
2967 markers = obsolete.getmarkers(repo)
2970 markers = obsolete.getmarkers(repo)
2968
2971
2969 for m in markers:
2972 for m in markers:
2970 cmdutil.showmarker(ui, m)
2973 cmdutil.showmarker(ui, m)
2971
2974
2972 @command('debugpathcomplete',
2975 @command('debugpathcomplete',
2973 [('f', 'full', None, _('complete an entire path')),
2976 [('f', 'full', None, _('complete an entire path')),
2974 ('n', 'normal', None, _('show only normal files')),
2977 ('n', 'normal', None, _('show only normal files')),
2975 ('a', 'added', None, _('show only added files')),
2978 ('a', 'added', None, _('show only added files')),
2976 ('r', 'removed', None, _('show only removed files'))],
2979 ('r', 'removed', None, _('show only removed files'))],
2977 _('FILESPEC...'))
2980 _('FILESPEC...'))
2978 def debugpathcomplete(ui, repo, *specs, **opts):
2981 def debugpathcomplete(ui, repo, *specs, **opts):
2979 '''complete part or all of a tracked path
2982 '''complete part or all of a tracked path
2980
2983
2981 This command supports shells that offer path name completion. It
2984 This command supports shells that offer path name completion. It
2982 currently completes only files already known to the dirstate.
2985 currently completes only files already known to the dirstate.
2983
2986
2984 Completion extends only to the next path segment unless
2987 Completion extends only to the next path segment unless
2985 --full is specified, in which case entire paths are used.'''
2988 --full is specified, in which case entire paths are used.'''
2986
2989
2987 def complete(path, acceptable):
2990 def complete(path, acceptable):
2988 dirstate = repo.dirstate
2991 dirstate = repo.dirstate
2989 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2992 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2990 rootdir = repo.root + os.sep
2993 rootdir = repo.root + os.sep
2991 if spec != repo.root and not spec.startswith(rootdir):
2994 if spec != repo.root and not spec.startswith(rootdir):
2992 return [], []
2995 return [], []
2993 if os.path.isdir(spec):
2996 if os.path.isdir(spec):
2994 spec += '/'
2997 spec += '/'
2995 spec = spec[len(rootdir):]
2998 spec = spec[len(rootdir):]
2996 fixpaths = os.sep != '/'
2999 fixpaths = os.sep != '/'
2997 if fixpaths:
3000 if fixpaths:
2998 spec = spec.replace(os.sep, '/')
3001 spec = spec.replace(os.sep, '/')
2999 speclen = len(spec)
3002 speclen = len(spec)
3000 fullpaths = opts['full']
3003 fullpaths = opts['full']
3001 files, dirs = set(), set()
3004 files, dirs = set(), set()
3002 adddir, addfile = dirs.add, files.add
3005 adddir, addfile = dirs.add, files.add
3003 for f, st in dirstate.iteritems():
3006 for f, st in dirstate.iteritems():
3004 if f.startswith(spec) and st[0] in acceptable:
3007 if f.startswith(spec) and st[0] in acceptable:
3005 if fixpaths:
3008 if fixpaths:
3006 f = f.replace('/', os.sep)
3009 f = f.replace('/', os.sep)
3007 if fullpaths:
3010 if fullpaths:
3008 addfile(f)
3011 addfile(f)
3009 continue
3012 continue
3010 s = f.find(os.sep, speclen)
3013 s = f.find(os.sep, speclen)
3011 if s >= 0:
3014 if s >= 0:
3012 adddir(f[:s])
3015 adddir(f[:s])
3013 else:
3016 else:
3014 addfile(f)
3017 addfile(f)
3015 return files, dirs
3018 return files, dirs
3016
3019
3017 acceptable = ''
3020 acceptable = ''
3018 if opts['normal']:
3021 if opts['normal']:
3019 acceptable += 'nm'
3022 acceptable += 'nm'
3020 if opts['added']:
3023 if opts['added']:
3021 acceptable += 'a'
3024 acceptable += 'a'
3022 if opts['removed']:
3025 if opts['removed']:
3023 acceptable += 'r'
3026 acceptable += 'r'
3024 cwd = repo.getcwd()
3027 cwd = repo.getcwd()
3025 if not specs:
3028 if not specs:
3026 specs = ['.']
3029 specs = ['.']
3027
3030
3028 files, dirs = set(), set()
3031 files, dirs = set(), set()
3029 for spec in specs:
3032 for spec in specs:
3030 f, d = complete(spec, acceptable or 'nmar')
3033 f, d = complete(spec, acceptable or 'nmar')
3031 files.update(f)
3034 files.update(f)
3032 dirs.update(d)
3035 dirs.update(d)
3033 files.update(dirs)
3036 files.update(dirs)
3034 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3037 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3035 ui.write('\n')
3038 ui.write('\n')
3036
3039
3037 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3040 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3038 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3041 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3039 '''access the pushkey key/value protocol
3042 '''access the pushkey key/value protocol
3040
3043
3041 With two args, list the keys in the given namespace.
3044 With two args, list the keys in the given namespace.
3042
3045
3043 With five args, set a key to new if it currently is set to old.
3046 With five args, set a key to new if it currently is set to old.
3044 Reports success or failure.
3047 Reports success or failure.
3045 '''
3048 '''
3046
3049
3047 target = hg.peer(ui, {}, repopath)
3050 target = hg.peer(ui, {}, repopath)
3048 if keyinfo:
3051 if keyinfo:
3049 key, old, new = keyinfo
3052 key, old, new = keyinfo
3050 r = target.pushkey(namespace, key, old, new)
3053 r = target.pushkey(namespace, key, old, new)
3051 ui.status(str(r) + '\n')
3054 ui.status(str(r) + '\n')
3052 return not r
3055 return not r
3053 else:
3056 else:
3054 for k, v in sorted(target.listkeys(namespace).iteritems()):
3057 for k, v in sorted(target.listkeys(namespace).iteritems()):
3055 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3058 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3056 v.encode('string-escape')))
3059 v.encode('string-escape')))
3057
3060
3058 @command('debugpvec', [], _('A B'))
3061 @command('debugpvec', [], _('A B'))
3059 def debugpvec(ui, repo, a, b=None):
3062 def debugpvec(ui, repo, a, b=None):
3060 ca = scmutil.revsingle(repo, a)
3063 ca = scmutil.revsingle(repo, a)
3061 cb = scmutil.revsingle(repo, b)
3064 cb = scmutil.revsingle(repo, b)
3062 pa = pvec.ctxpvec(ca)
3065 pa = pvec.ctxpvec(ca)
3063 pb = pvec.ctxpvec(cb)
3066 pb = pvec.ctxpvec(cb)
3064 if pa == pb:
3067 if pa == pb:
3065 rel = "="
3068 rel = "="
3066 elif pa > pb:
3069 elif pa > pb:
3067 rel = ">"
3070 rel = ">"
3068 elif pa < pb:
3071 elif pa < pb:
3069 rel = "<"
3072 rel = "<"
3070 elif pa | pb:
3073 elif pa | pb:
3071 rel = "|"
3074 rel = "|"
3072 ui.write(_("a: %s\n") % pa)
3075 ui.write(_("a: %s\n") % pa)
3073 ui.write(_("b: %s\n") % pb)
3076 ui.write(_("b: %s\n") % pb)
3074 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3077 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3075 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3078 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3076 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3079 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3077 pa.distance(pb), rel))
3080 pa.distance(pb), rel))
3078
3081
3079 @command('debugrebuilddirstate|debugrebuildstate',
3082 @command('debugrebuilddirstate|debugrebuildstate',
3080 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3083 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3081 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3084 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3082 'the working copy parent')),
3085 'the working copy parent')),
3083 ],
3086 ],
3084 _('[-r REV]'))
3087 _('[-r REV]'))
3085 def debugrebuilddirstate(ui, repo, rev, **opts):
3088 def debugrebuilddirstate(ui, repo, rev, **opts):
3086 """rebuild the dirstate as it would look like for the given revision
3089 """rebuild the dirstate as it would look like for the given revision
3087
3090
3088 If no revision is specified the first current parent will be used.
3091 If no revision is specified the first current parent will be used.
3089
3092
3090 The dirstate will be set to the files of the given revision.
3093 The dirstate will be set to the files of the given revision.
3091 The actual working directory content or existing dirstate
3094 The actual working directory content or existing dirstate
3092 information such as adds or removes is not considered.
3095 information such as adds or removes is not considered.
3093
3096
3094 ``minimal`` will only rebuild the dirstate status for files that claim to be
3097 ``minimal`` will only rebuild the dirstate status for files that claim to be
3095 tracked but are not in the parent manifest, or that exist in the parent
3098 tracked but are not in the parent manifest, or that exist in the parent
3096 manifest but are not in the dirstate. It will not change adds, removes, or
3099 manifest but are not in the dirstate. It will not change adds, removes, or
3097 modified files that are in the working copy parent.
3100 modified files that are in the working copy parent.
3098
3101
3099 One use of this command is to make the next :hg:`status` invocation
3102 One use of this command is to make the next :hg:`status` invocation
3100 check the actual file content.
3103 check the actual file content.
3101 """
3104 """
3102 ctx = scmutil.revsingle(repo, rev)
3105 ctx = scmutil.revsingle(repo, rev)
3103 wlock = repo.wlock()
3106 wlock = repo.wlock()
3104 try:
3107 try:
3105 dirstate = repo.dirstate
3108 dirstate = repo.dirstate
3106 changedfiles = None
3109 changedfiles = None
3107 # See command doc for what minimal does.
3110 # See command doc for what minimal does.
3108 if opts.get('minimal'):
3111 if opts.get('minimal'):
3109 manifestfiles = set(ctx.manifest().keys())
3112 manifestfiles = set(ctx.manifest().keys())
3110 dirstatefiles = set(dirstate)
3113 dirstatefiles = set(dirstate)
3111 manifestonly = manifestfiles - dirstatefiles
3114 manifestonly = manifestfiles - dirstatefiles
3112 dsonly = dirstatefiles - manifestfiles
3115 dsonly = dirstatefiles - manifestfiles
3113 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3116 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3114 changedfiles = manifestonly | dsnotadded
3117 changedfiles = manifestonly | dsnotadded
3115
3118
3116 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3119 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3117 finally:
3120 finally:
3118 wlock.release()
3121 wlock.release()
3119
3122
3120 @command('debugrebuildfncache', [], '')
3123 @command('debugrebuildfncache', [], '')
3121 def debugrebuildfncache(ui, repo):
3124 def debugrebuildfncache(ui, repo):
3122 """rebuild the fncache file"""
3125 """rebuild the fncache file"""
3123 repair.rebuildfncache(ui, repo)
3126 repair.rebuildfncache(ui, repo)
3124
3127
3125 @command('debugrename',
3128 @command('debugrename',
3126 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3129 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3127 _('[-r REV] FILE'))
3130 _('[-r REV] FILE'))
3128 def debugrename(ui, repo, file1, *pats, **opts):
3131 def debugrename(ui, repo, file1, *pats, **opts):
3129 """dump rename information"""
3132 """dump rename information"""
3130
3133
3131 ctx = scmutil.revsingle(repo, opts.get('rev'))
3134 ctx = scmutil.revsingle(repo, opts.get('rev'))
3132 m = scmutil.match(ctx, (file1,) + pats, opts)
3135 m = scmutil.match(ctx, (file1,) + pats, opts)
3133 for abs in ctx.walk(m):
3136 for abs in ctx.walk(m):
3134 fctx = ctx[abs]
3137 fctx = ctx[abs]
3135 o = fctx.filelog().renamed(fctx.filenode())
3138 o = fctx.filelog().renamed(fctx.filenode())
3136 rel = m.rel(abs)
3139 rel = m.rel(abs)
3137 if o:
3140 if o:
3138 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3141 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3139 else:
3142 else:
3140 ui.write(_("%s not renamed\n") % rel)
3143 ui.write(_("%s not renamed\n") % rel)
3141
3144
3142 @command('debugrevlog', debugrevlogopts +
3145 @command('debugrevlog', debugrevlogopts +
3143 [('d', 'dump', False, _('dump index data'))],
3146 [('d', 'dump', False, _('dump index data'))],
3144 _('-c|-m|FILE'),
3147 _('-c|-m|FILE'),
3145 optionalrepo=True)
3148 optionalrepo=True)
3146 def debugrevlog(ui, repo, file_=None, **opts):
3149 def debugrevlog(ui, repo, file_=None, **opts):
3147 """show data and statistics about a revlog"""
3150 """show data and statistics about a revlog"""
3148 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3151 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3149
3152
3150 if opts.get("dump"):
3153 if opts.get("dump"):
3151 numrevs = len(r)
3154 numrevs = len(r)
3152 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3155 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3153 " rawsize totalsize compression heads chainlen\n")
3156 " rawsize totalsize compression heads chainlen\n")
3154 ts = 0
3157 ts = 0
3155 heads = set()
3158 heads = set()
3156
3159
3157 for rev in xrange(numrevs):
3160 for rev in xrange(numrevs):
3158 dbase = r.deltaparent(rev)
3161 dbase = r.deltaparent(rev)
3159 if dbase == -1:
3162 if dbase == -1:
3160 dbase = rev
3163 dbase = rev
3161 cbase = r.chainbase(rev)
3164 cbase = r.chainbase(rev)
3162 clen = r.chainlen(rev)
3165 clen = r.chainlen(rev)
3163 p1, p2 = r.parentrevs(rev)
3166 p1, p2 = r.parentrevs(rev)
3164 rs = r.rawsize(rev)
3167 rs = r.rawsize(rev)
3165 ts = ts + rs
3168 ts = ts + rs
3166 heads -= set(r.parentrevs(rev))
3169 heads -= set(r.parentrevs(rev))
3167 heads.add(rev)
3170 heads.add(rev)
3168 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3171 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3169 "%11d %5d %8d\n" %
3172 "%11d %5d %8d\n" %
3170 (rev, p1, p2, r.start(rev), r.end(rev),
3173 (rev, p1, p2, r.start(rev), r.end(rev),
3171 r.start(dbase), r.start(cbase),
3174 r.start(dbase), r.start(cbase),
3172 r.start(p1), r.start(p2),
3175 r.start(p1), r.start(p2),
3173 rs, ts, ts / r.end(rev), len(heads), clen))
3176 rs, ts, ts / r.end(rev), len(heads), clen))
3174 return 0
3177 return 0
3175
3178
3176 v = r.version
3179 v = r.version
3177 format = v & 0xFFFF
3180 format = v & 0xFFFF
3178 flags = []
3181 flags = []
3179 gdelta = False
3182 gdelta = False
3180 if v & revlog.REVLOGNGINLINEDATA:
3183 if v & revlog.REVLOGNGINLINEDATA:
3181 flags.append('inline')
3184 flags.append('inline')
3182 if v & revlog.REVLOGGENERALDELTA:
3185 if v & revlog.REVLOGGENERALDELTA:
3183 gdelta = True
3186 gdelta = True
3184 flags.append('generaldelta')
3187 flags.append('generaldelta')
3185 if not flags:
3188 if not flags:
3186 flags = ['(none)']
3189 flags = ['(none)']
3187
3190
3188 nummerges = 0
3191 nummerges = 0
3189 numfull = 0
3192 numfull = 0
3190 numprev = 0
3193 numprev = 0
3191 nump1 = 0
3194 nump1 = 0
3192 nump2 = 0
3195 nump2 = 0
3193 numother = 0
3196 numother = 0
3194 nump1prev = 0
3197 nump1prev = 0
3195 nump2prev = 0
3198 nump2prev = 0
3196 chainlengths = []
3199 chainlengths = []
3197
3200
3198 datasize = [None, 0, 0L]
3201 datasize = [None, 0, 0L]
3199 fullsize = [None, 0, 0L]
3202 fullsize = [None, 0, 0L]
3200 deltasize = [None, 0, 0L]
3203 deltasize = [None, 0, 0L]
3201
3204
3202 def addsize(size, l):
3205 def addsize(size, l):
3203 if l[0] is None or size < l[0]:
3206 if l[0] is None or size < l[0]:
3204 l[0] = size
3207 l[0] = size
3205 if size > l[1]:
3208 if size > l[1]:
3206 l[1] = size
3209 l[1] = size
3207 l[2] += size
3210 l[2] += size
3208
3211
3209 numrevs = len(r)
3212 numrevs = len(r)
3210 for rev in xrange(numrevs):
3213 for rev in xrange(numrevs):
3211 p1, p2 = r.parentrevs(rev)
3214 p1, p2 = r.parentrevs(rev)
3212 delta = r.deltaparent(rev)
3215 delta = r.deltaparent(rev)
3213 if format > 0:
3216 if format > 0:
3214 addsize(r.rawsize(rev), datasize)
3217 addsize(r.rawsize(rev), datasize)
3215 if p2 != nullrev:
3218 if p2 != nullrev:
3216 nummerges += 1
3219 nummerges += 1
3217 size = r.length(rev)
3220 size = r.length(rev)
3218 if delta == nullrev:
3221 if delta == nullrev:
3219 chainlengths.append(0)
3222 chainlengths.append(0)
3220 numfull += 1
3223 numfull += 1
3221 addsize(size, fullsize)
3224 addsize(size, fullsize)
3222 else:
3225 else:
3223 chainlengths.append(chainlengths[delta] + 1)
3226 chainlengths.append(chainlengths[delta] + 1)
3224 addsize(size, deltasize)
3227 addsize(size, deltasize)
3225 if delta == rev - 1:
3228 if delta == rev - 1:
3226 numprev += 1
3229 numprev += 1
3227 if delta == p1:
3230 if delta == p1:
3228 nump1prev += 1
3231 nump1prev += 1
3229 elif delta == p2:
3232 elif delta == p2:
3230 nump2prev += 1
3233 nump2prev += 1
3231 elif delta == p1:
3234 elif delta == p1:
3232 nump1 += 1
3235 nump1 += 1
3233 elif delta == p2:
3236 elif delta == p2:
3234 nump2 += 1
3237 nump2 += 1
3235 elif delta != nullrev:
3238 elif delta != nullrev:
3236 numother += 1
3239 numother += 1
3237
3240
3238 # Adjust size min value for empty cases
3241 # Adjust size min value for empty cases
3239 for size in (datasize, fullsize, deltasize):
3242 for size in (datasize, fullsize, deltasize):
3240 if size[0] is None:
3243 if size[0] is None:
3241 size[0] = 0
3244 size[0] = 0
3242
3245
3243 numdeltas = numrevs - numfull
3246 numdeltas = numrevs - numfull
3244 numoprev = numprev - nump1prev - nump2prev
3247 numoprev = numprev - nump1prev - nump2prev
3245 totalrawsize = datasize[2]
3248 totalrawsize = datasize[2]
3246 datasize[2] /= numrevs
3249 datasize[2] /= numrevs
3247 fulltotal = fullsize[2]
3250 fulltotal = fullsize[2]
3248 fullsize[2] /= numfull
3251 fullsize[2] /= numfull
3249 deltatotal = deltasize[2]
3252 deltatotal = deltasize[2]
3250 if numrevs - numfull > 0:
3253 if numrevs - numfull > 0:
3251 deltasize[2] /= numrevs - numfull
3254 deltasize[2] /= numrevs - numfull
3252 totalsize = fulltotal + deltatotal
3255 totalsize = fulltotal + deltatotal
3253 avgchainlen = sum(chainlengths) / numrevs
3256 avgchainlen = sum(chainlengths) / numrevs
3254 maxchainlen = max(chainlengths)
3257 maxchainlen = max(chainlengths)
3255 compratio = 1
3258 compratio = 1
3256 if totalsize:
3259 if totalsize:
3257 compratio = totalrawsize / totalsize
3260 compratio = totalrawsize / totalsize
3258
3261
3259 basedfmtstr = '%%%dd\n'
3262 basedfmtstr = '%%%dd\n'
3260 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3263 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3261
3264
3262 def dfmtstr(max):
3265 def dfmtstr(max):
3263 return basedfmtstr % len(str(max))
3266 return basedfmtstr % len(str(max))
3264 def pcfmtstr(max, padding=0):
3267 def pcfmtstr(max, padding=0):
3265 return basepcfmtstr % (len(str(max)), ' ' * padding)
3268 return basepcfmtstr % (len(str(max)), ' ' * padding)
3266
3269
3267 def pcfmt(value, total):
3270 def pcfmt(value, total):
3268 if total:
3271 if total:
3269 return (value, 100 * float(value) / total)
3272 return (value, 100 * float(value) / total)
3270 else:
3273 else:
3271 return value, 100.0
3274 return value, 100.0
3272
3275
3273 ui.write(('format : %d\n') % format)
3276 ui.write(('format : %d\n') % format)
3274 ui.write(('flags : %s\n') % ', '.join(flags))
3277 ui.write(('flags : %s\n') % ', '.join(flags))
3275
3278
3276 ui.write('\n')
3279 ui.write('\n')
3277 fmt = pcfmtstr(totalsize)
3280 fmt = pcfmtstr(totalsize)
3278 fmt2 = dfmtstr(totalsize)
3281 fmt2 = dfmtstr(totalsize)
3279 ui.write(('revisions : ') + fmt2 % numrevs)
3282 ui.write(('revisions : ') + fmt2 % numrevs)
3280 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3283 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3281 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3284 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3282 ui.write(('revisions : ') + fmt2 % numrevs)
3285 ui.write(('revisions : ') + fmt2 % numrevs)
3283 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3286 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3284 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3287 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3285 ui.write(('revision size : ') + fmt2 % totalsize)
3288 ui.write(('revision size : ') + fmt2 % totalsize)
3286 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3289 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3287 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3290 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3288
3291
3289 ui.write('\n')
3292 ui.write('\n')
3290 fmt = dfmtstr(max(avgchainlen, compratio))
3293 fmt = dfmtstr(max(avgchainlen, compratio))
3291 ui.write(('avg chain length : ') + fmt % avgchainlen)
3294 ui.write(('avg chain length : ') + fmt % avgchainlen)
3292 ui.write(('max chain length : ') + fmt % maxchainlen)
3295 ui.write(('max chain length : ') + fmt % maxchainlen)
3293 ui.write(('compression ratio : ') + fmt % compratio)
3296 ui.write(('compression ratio : ') + fmt % compratio)
3294
3297
3295 if format > 0:
3298 if format > 0:
3296 ui.write('\n')
3299 ui.write('\n')
3297 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3300 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3298 % tuple(datasize))
3301 % tuple(datasize))
3299 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3302 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3300 % tuple(fullsize))
3303 % tuple(fullsize))
3301 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3304 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3302 % tuple(deltasize))
3305 % tuple(deltasize))
3303
3306
3304 if numdeltas > 0:
3307 if numdeltas > 0:
3305 ui.write('\n')
3308 ui.write('\n')
3306 fmt = pcfmtstr(numdeltas)
3309 fmt = pcfmtstr(numdeltas)
3307 fmt2 = pcfmtstr(numdeltas, 4)
3310 fmt2 = pcfmtstr(numdeltas, 4)
3308 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3311 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3309 if numprev > 0:
3312 if numprev > 0:
3310 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3313 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3311 numprev))
3314 numprev))
3312 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3315 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3313 numprev))
3316 numprev))
3314 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3317 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3315 numprev))
3318 numprev))
3316 if gdelta:
3319 if gdelta:
3317 ui.write(('deltas against p1 : ')
3320 ui.write(('deltas against p1 : ')
3318 + fmt % pcfmt(nump1, numdeltas))
3321 + fmt % pcfmt(nump1, numdeltas))
3319 ui.write(('deltas against p2 : ')
3322 ui.write(('deltas against p2 : ')
3320 + fmt % pcfmt(nump2, numdeltas))
3323 + fmt % pcfmt(nump2, numdeltas))
3321 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3324 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3322 numdeltas))
3325 numdeltas))
3323
3326
3324 @command('debugrevspec',
3327 @command('debugrevspec',
3325 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3328 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3326 ('REVSPEC'))
3329 ('REVSPEC'))
3327 def debugrevspec(ui, repo, expr, **opts):
3330 def debugrevspec(ui, repo, expr, **opts):
3328 """parse and apply a revision specification
3331 """parse and apply a revision specification
3329
3332
3330 Use --verbose to print the parsed tree before and after aliases
3333 Use --verbose to print the parsed tree before and after aliases
3331 expansion.
3334 expansion.
3332 """
3335 """
3333 if ui.verbose:
3336 if ui.verbose:
3334 tree = revset.parse(expr, lookup=repo.__contains__)
3337 tree = revset.parse(expr, lookup=repo.__contains__)
3335 ui.note(revset.prettyformat(tree), "\n")
3338 ui.note(revset.prettyformat(tree), "\n")
3336 newtree = revset.findaliases(ui, tree)
3339 newtree = revset.findaliases(ui, tree)
3337 if newtree != tree:
3340 if newtree != tree:
3338 ui.note(revset.prettyformat(newtree), "\n")
3341 ui.note(revset.prettyformat(newtree), "\n")
3339 tree = newtree
3342 tree = newtree
3340 newtree = revset.foldconcat(tree)
3343 newtree = revset.foldconcat(tree)
3341 if newtree != tree:
3344 if newtree != tree:
3342 ui.note(revset.prettyformat(newtree), "\n")
3345 ui.note(revset.prettyformat(newtree), "\n")
3343 if opts["optimize"]:
3346 if opts["optimize"]:
3344 weight, optimizedtree = revset.optimize(newtree, True)
3347 weight, optimizedtree = revset.optimize(newtree, True)
3345 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3348 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3346 func = revset.match(ui, expr, repo)
3349 func = revset.match(ui, expr, repo)
3347 revs = func(repo)
3350 revs = func(repo)
3348 if ui.verbose:
3351 if ui.verbose:
3349 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3352 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3350 for c in revs:
3353 for c in revs:
3351 ui.write("%s\n" % c)
3354 ui.write("%s\n" % c)
3352
3355
3353 @command('debugsetparents', [], _('REV1 [REV2]'))
3356 @command('debugsetparents', [], _('REV1 [REV2]'))
3354 def debugsetparents(ui, repo, rev1, rev2=None):
3357 def debugsetparents(ui, repo, rev1, rev2=None):
3355 """manually set the parents of the current working directory
3358 """manually set the parents of the current working directory
3356
3359
3357 This is useful for writing repository conversion tools, but should
3360 This is useful for writing repository conversion tools, but should
3358 be used with care. For example, neither the working directory nor the
3361 be used with care. For example, neither the working directory nor the
3359 dirstate is updated, so file status may be incorrect after running this
3362 dirstate is updated, so file status may be incorrect after running this
3360 command.
3363 command.
3361
3364
3362 Returns 0 on success.
3365 Returns 0 on success.
3363 """
3366 """
3364
3367
3365 r1 = scmutil.revsingle(repo, rev1).node()
3368 r1 = scmutil.revsingle(repo, rev1).node()
3366 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3369 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3367
3370
3368 wlock = repo.wlock()
3371 wlock = repo.wlock()
3369 try:
3372 try:
3370 repo.dirstate.beginparentchange()
3373 repo.dirstate.beginparentchange()
3371 repo.setparents(r1, r2)
3374 repo.setparents(r1, r2)
3372 repo.dirstate.endparentchange()
3375 repo.dirstate.endparentchange()
3373 finally:
3376 finally:
3374 wlock.release()
3377 wlock.release()
3375
3378
3376 @command('debugdirstate|debugstate',
3379 @command('debugdirstate|debugstate',
3377 [('', 'nodates', None, _('do not display the saved mtime')),
3380 [('', 'nodates', None, _('do not display the saved mtime')),
3378 ('', 'datesort', None, _('sort by saved mtime'))],
3381 ('', 'datesort', None, _('sort by saved mtime'))],
3379 _('[OPTION]...'))
3382 _('[OPTION]...'))
3380 def debugstate(ui, repo, **opts):
3383 def debugstate(ui, repo, **opts):
3381 """show the contents of the current dirstate"""
3384 """show the contents of the current dirstate"""
3382
3385
3383 nodates = opts.get('nodates')
3386 nodates = opts.get('nodates')
3384 datesort = opts.get('datesort')
3387 datesort = opts.get('datesort')
3385
3388
3386 timestr = ""
3389 timestr = ""
3387 if datesort:
3390 if datesort:
3388 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3391 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3389 else:
3392 else:
3390 keyfunc = None # sort by filename
3393 keyfunc = None # sort by filename
3391 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3394 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3392 if ent[3] == -1:
3395 if ent[3] == -1:
3393 timestr = 'unset '
3396 timestr = 'unset '
3394 elif nodates:
3397 elif nodates:
3395 timestr = 'set '
3398 timestr = 'set '
3396 else:
3399 else:
3397 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3400 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3398 time.localtime(ent[3]))
3401 time.localtime(ent[3]))
3399 if ent[1] & 0o20000:
3402 if ent[1] & 0o20000:
3400 mode = 'lnk'
3403 mode = 'lnk'
3401 else:
3404 else:
3402 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3405 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3403 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3406 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3404 for f in repo.dirstate.copies():
3407 for f in repo.dirstate.copies():
3405 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3408 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3406
3409
3407 @command('debugsub',
3410 @command('debugsub',
3408 [('r', 'rev', '',
3411 [('r', 'rev', '',
3409 _('revision to check'), _('REV'))],
3412 _('revision to check'), _('REV'))],
3410 _('[-r REV] [REV]'))
3413 _('[-r REV] [REV]'))
3411 def debugsub(ui, repo, rev=None):
3414 def debugsub(ui, repo, rev=None):
3412 ctx = scmutil.revsingle(repo, rev, None)
3415 ctx = scmutil.revsingle(repo, rev, None)
3413 for k, v in sorted(ctx.substate.items()):
3416 for k, v in sorted(ctx.substate.items()):
3414 ui.write(('path %s\n') % k)
3417 ui.write(('path %s\n') % k)
3415 ui.write((' source %s\n') % v[0])
3418 ui.write((' source %s\n') % v[0])
3416 ui.write((' revision %s\n') % v[1])
3419 ui.write((' revision %s\n') % v[1])
3417
3420
3418 @command('debugsuccessorssets',
3421 @command('debugsuccessorssets',
3419 [],
3422 [],
3420 _('[REV]'))
3423 _('[REV]'))
3421 def debugsuccessorssets(ui, repo, *revs):
3424 def debugsuccessorssets(ui, repo, *revs):
3422 """show set of successors for revision
3425 """show set of successors for revision
3423
3426
3424 A successors set of changeset A is a consistent group of revisions that
3427 A successors set of changeset A is a consistent group of revisions that
3425 succeed A. It contains non-obsolete changesets only.
3428 succeed A. It contains non-obsolete changesets only.
3426
3429
3427 In most cases a changeset A has a single successors set containing a single
3430 In most cases a changeset A has a single successors set containing a single
3428 successor (changeset A replaced by A').
3431 successor (changeset A replaced by A').
3429
3432
3430 A changeset that is made obsolete with no successors are called "pruned".
3433 A changeset that is made obsolete with no successors are called "pruned".
3431 Such changesets have no successors sets at all.
3434 Such changesets have no successors sets at all.
3432
3435
3433 A changeset that has been "split" will have a successors set containing
3436 A changeset that has been "split" will have a successors set containing
3434 more than one successor.
3437 more than one successor.
3435
3438
3436 A changeset that has been rewritten in multiple different ways is called
3439 A changeset that has been rewritten in multiple different ways is called
3437 "divergent". Such changesets have multiple successor sets (each of which
3440 "divergent". Such changesets have multiple successor sets (each of which
3438 may also be split, i.e. have multiple successors).
3441 may also be split, i.e. have multiple successors).
3439
3442
3440 Results are displayed as follows::
3443 Results are displayed as follows::
3441
3444
3442 <rev1>
3445 <rev1>
3443 <successors-1A>
3446 <successors-1A>
3444 <rev2>
3447 <rev2>
3445 <successors-2A>
3448 <successors-2A>
3446 <successors-2B1> <successors-2B2> <successors-2B3>
3449 <successors-2B1> <successors-2B2> <successors-2B3>
3447
3450
3448 Here rev2 has two possible (i.e. divergent) successors sets. The first
3451 Here rev2 has two possible (i.e. divergent) successors sets. The first
3449 holds one element, whereas the second holds three (i.e. the changeset has
3452 holds one element, whereas the second holds three (i.e. the changeset has
3450 been split).
3453 been split).
3451 """
3454 """
3452 # passed to successorssets caching computation from one call to another
3455 # passed to successorssets caching computation from one call to another
3453 cache = {}
3456 cache = {}
3454 ctx2str = str
3457 ctx2str = str
3455 node2str = short
3458 node2str = short
3456 if ui.debug():
3459 if ui.debug():
3457 def ctx2str(ctx):
3460 def ctx2str(ctx):
3458 return ctx.hex()
3461 return ctx.hex()
3459 node2str = hex
3462 node2str = hex
3460 for rev in scmutil.revrange(repo, revs):
3463 for rev in scmutil.revrange(repo, revs):
3461 ctx = repo[rev]
3464 ctx = repo[rev]
3462 ui.write('%s\n'% ctx2str(ctx))
3465 ui.write('%s\n'% ctx2str(ctx))
3463 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3466 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3464 if succsset:
3467 if succsset:
3465 ui.write(' ')
3468 ui.write(' ')
3466 ui.write(node2str(succsset[0]))
3469 ui.write(node2str(succsset[0]))
3467 for node in succsset[1:]:
3470 for node in succsset[1:]:
3468 ui.write(' ')
3471 ui.write(' ')
3469 ui.write(node2str(node))
3472 ui.write(node2str(node))
3470 ui.write('\n')
3473 ui.write('\n')
3471
3474
3472 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3475 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3473 def debugwalk(ui, repo, *pats, **opts):
3476 def debugwalk(ui, repo, *pats, **opts):
3474 """show how files match on given patterns"""
3477 """show how files match on given patterns"""
3475 m = scmutil.match(repo[None], pats, opts)
3478 m = scmutil.match(repo[None], pats, opts)
3476 items = list(repo.walk(m))
3479 items = list(repo.walk(m))
3477 if not items:
3480 if not items:
3478 return
3481 return
3479 f = lambda fn: fn
3482 f = lambda fn: fn
3480 if ui.configbool('ui', 'slash') and os.sep != '/':
3483 if ui.configbool('ui', 'slash') and os.sep != '/':
3481 f = lambda fn: util.normpath(fn)
3484 f = lambda fn: util.normpath(fn)
3482 fmt = 'f %%-%ds %%-%ds %%s' % (
3485 fmt = 'f %%-%ds %%-%ds %%s' % (
3483 max([len(abs) for abs in items]),
3486 max([len(abs) for abs in items]),
3484 max([len(m.rel(abs)) for abs in items]))
3487 max([len(m.rel(abs)) for abs in items]))
3485 for abs in items:
3488 for abs in items:
3486 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3489 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3487 ui.write("%s\n" % line.rstrip())
3490 ui.write("%s\n" % line.rstrip())
3488
3491
3489 @command('debugwireargs',
3492 @command('debugwireargs',
3490 [('', 'three', '', 'three'),
3493 [('', 'three', '', 'three'),
3491 ('', 'four', '', 'four'),
3494 ('', 'four', '', 'four'),
3492 ('', 'five', '', 'five'),
3495 ('', 'five', '', 'five'),
3493 ] + remoteopts,
3496 ] + remoteopts,
3494 _('REPO [OPTIONS]... [ONE [TWO]]'),
3497 _('REPO [OPTIONS]... [ONE [TWO]]'),
3495 norepo=True)
3498 norepo=True)
3496 def debugwireargs(ui, repopath, *vals, **opts):
3499 def debugwireargs(ui, repopath, *vals, **opts):
3497 repo = hg.peer(ui, opts, repopath)
3500 repo = hg.peer(ui, opts, repopath)
3498 for opt in remoteopts:
3501 for opt in remoteopts:
3499 del opts[opt[1]]
3502 del opts[opt[1]]
3500 args = {}
3503 args = {}
3501 for k, v in opts.iteritems():
3504 for k, v in opts.iteritems():
3502 if v:
3505 if v:
3503 args[k] = v
3506 args[k] = v
3504 # run twice to check that we don't mess up the stream for the next command
3507 # run twice to check that we don't mess up the stream for the next command
3505 res1 = repo.debugwireargs(*vals, **args)
3508 res1 = repo.debugwireargs(*vals, **args)
3506 res2 = repo.debugwireargs(*vals, **args)
3509 res2 = repo.debugwireargs(*vals, **args)
3507 ui.write("%s\n" % res1)
3510 ui.write("%s\n" % res1)
3508 if res1 != res2:
3511 if res1 != res2:
3509 ui.warn("%s\n" % res2)
3512 ui.warn("%s\n" % res2)
3510
3513
3511 @command('^diff',
3514 @command('^diff',
3512 [('r', 'rev', [], _('revision'), _('REV')),
3515 [('r', 'rev', [], _('revision'), _('REV')),
3513 ('c', 'change', '', _('change made by revision'), _('REV'))
3516 ('c', 'change', '', _('change made by revision'), _('REV'))
3514 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3517 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3515 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3518 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3516 inferrepo=True)
3519 inferrepo=True)
3517 def diff(ui, repo, *pats, **opts):
3520 def diff(ui, repo, *pats, **opts):
3518 """diff repository (or selected files)
3521 """diff repository (or selected files)
3519
3522
3520 Show differences between revisions for the specified files.
3523 Show differences between revisions for the specified files.
3521
3524
3522 Differences between files are shown using the unified diff format.
3525 Differences between files are shown using the unified diff format.
3523
3526
3524 .. note::
3527 .. note::
3525
3528
3526 :hg:`diff` may generate unexpected results for merges, as it will
3529 :hg:`diff` may generate unexpected results for merges, as it will
3527 default to comparing against the working directory's first
3530 default to comparing against the working directory's first
3528 parent changeset if no revisions are specified.
3531 parent changeset if no revisions are specified.
3529
3532
3530 When two revision arguments are given, then changes are shown
3533 When two revision arguments are given, then changes are shown
3531 between those revisions. If only one revision is specified then
3534 between those revisions. If only one revision is specified then
3532 that revision is compared to the working directory, and, when no
3535 that revision is compared to the working directory, and, when no
3533 revisions are specified, the working directory files are compared
3536 revisions are specified, the working directory files are compared
3534 to its first parent.
3537 to its first parent.
3535
3538
3536 Alternatively you can specify -c/--change with a revision to see
3539 Alternatively you can specify -c/--change with a revision to see
3537 the changes in that changeset relative to its first parent.
3540 the changes in that changeset relative to its first parent.
3538
3541
3539 Without the -a/--text option, diff will avoid generating diffs of
3542 Without the -a/--text option, diff will avoid generating diffs of
3540 files it detects as binary. With -a, diff will generate a diff
3543 files it detects as binary. With -a, diff will generate a diff
3541 anyway, probably with undesirable results.
3544 anyway, probably with undesirable results.
3542
3545
3543 Use the -g/--git option to generate diffs in the git extended diff
3546 Use the -g/--git option to generate diffs in the git extended diff
3544 format. For more information, read :hg:`help diffs`.
3547 format. For more information, read :hg:`help diffs`.
3545
3548
3546 .. container:: verbose
3549 .. container:: verbose
3547
3550
3548 Examples:
3551 Examples:
3549
3552
3550 - compare a file in the current working directory to its parent::
3553 - compare a file in the current working directory to its parent::
3551
3554
3552 hg diff foo.c
3555 hg diff foo.c
3553
3556
3554 - compare two historical versions of a directory, with rename info::
3557 - compare two historical versions of a directory, with rename info::
3555
3558
3556 hg diff --git -r 1.0:1.2 lib/
3559 hg diff --git -r 1.0:1.2 lib/
3557
3560
3558 - get change stats relative to the last change on some date::
3561 - get change stats relative to the last change on some date::
3559
3562
3560 hg diff --stat -r "date('may 2')"
3563 hg diff --stat -r "date('may 2')"
3561
3564
3562 - diff all newly-added files that contain a keyword::
3565 - diff all newly-added files that contain a keyword::
3563
3566
3564 hg diff "set:added() and grep(GNU)"
3567 hg diff "set:added() and grep(GNU)"
3565
3568
3566 - compare a revision and its parents::
3569 - compare a revision and its parents::
3567
3570
3568 hg diff -c 9353 # compare against first parent
3571 hg diff -c 9353 # compare against first parent
3569 hg diff -r 9353^:9353 # same using revset syntax
3572 hg diff -r 9353^:9353 # same using revset syntax
3570 hg diff -r 9353^2:9353 # compare against the second parent
3573 hg diff -r 9353^2:9353 # compare against the second parent
3571
3574
3572 Returns 0 on success.
3575 Returns 0 on success.
3573 """
3576 """
3574
3577
3575 revs = opts.get('rev')
3578 revs = opts.get('rev')
3576 change = opts.get('change')
3579 change = opts.get('change')
3577 stat = opts.get('stat')
3580 stat = opts.get('stat')
3578 reverse = opts.get('reverse')
3581 reverse = opts.get('reverse')
3579
3582
3580 if revs and change:
3583 if revs and change:
3581 msg = _('cannot specify --rev and --change at the same time')
3584 msg = _('cannot specify --rev and --change at the same time')
3582 raise error.Abort(msg)
3585 raise error.Abort(msg)
3583 elif change:
3586 elif change:
3584 node2 = scmutil.revsingle(repo, change, None).node()
3587 node2 = scmutil.revsingle(repo, change, None).node()
3585 node1 = repo[node2].p1().node()
3588 node1 = repo[node2].p1().node()
3586 else:
3589 else:
3587 node1, node2 = scmutil.revpair(repo, revs)
3590 node1, node2 = scmutil.revpair(repo, revs)
3588
3591
3589 if reverse:
3592 if reverse:
3590 node1, node2 = node2, node1
3593 node1, node2 = node2, node1
3591
3594
3592 diffopts = patch.diffallopts(ui, opts)
3595 diffopts = patch.diffallopts(ui, opts)
3593 m = scmutil.match(repo[node2], pats, opts)
3596 m = scmutil.match(repo[node2], pats, opts)
3594 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3597 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3595 listsubrepos=opts.get('subrepos'),
3598 listsubrepos=opts.get('subrepos'),
3596 root=opts.get('root'))
3599 root=opts.get('root'))
3597
3600
3598 @command('^export',
3601 @command('^export',
3599 [('o', 'output', '',
3602 [('o', 'output', '',
3600 _('print output to file with formatted name'), _('FORMAT')),
3603 _('print output to file with formatted name'), _('FORMAT')),
3601 ('', 'switch-parent', None, _('diff against the second parent')),
3604 ('', 'switch-parent', None, _('diff against the second parent')),
3602 ('r', 'rev', [], _('revisions to export'), _('REV')),
3605 ('r', 'rev', [], _('revisions to export'), _('REV')),
3603 ] + diffopts,
3606 ] + diffopts,
3604 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3607 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3605 def export(ui, repo, *changesets, **opts):
3608 def export(ui, repo, *changesets, **opts):
3606 """dump the header and diffs for one or more changesets
3609 """dump the header and diffs for one or more changesets
3607
3610
3608 Print the changeset header and diffs for one or more revisions.
3611 Print the changeset header and diffs for one or more revisions.
3609 If no revision is given, the parent of the working directory is used.
3612 If no revision is given, the parent of the working directory is used.
3610
3613
3611 The information shown in the changeset header is: author, date,
3614 The information shown in the changeset header is: author, date,
3612 branch name (if non-default), changeset hash, parent(s) and commit
3615 branch name (if non-default), changeset hash, parent(s) and commit
3613 comment.
3616 comment.
3614
3617
3615 .. note::
3618 .. note::
3616
3619
3617 :hg:`export` may generate unexpected diff output for merge
3620 :hg:`export` may generate unexpected diff output for merge
3618 changesets, as it will compare the merge changeset against its
3621 changesets, as it will compare the merge changeset against its
3619 first parent only.
3622 first parent only.
3620
3623
3621 Output may be to a file, in which case the name of the file is
3624 Output may be to a file, in which case the name of the file is
3622 given using a format string. The formatting rules are as follows:
3625 given using a format string. The formatting rules are as follows:
3623
3626
3624 :``%%``: literal "%" character
3627 :``%%``: literal "%" character
3625 :``%H``: changeset hash (40 hexadecimal digits)
3628 :``%H``: changeset hash (40 hexadecimal digits)
3626 :``%N``: number of patches being generated
3629 :``%N``: number of patches being generated
3627 :``%R``: changeset revision number
3630 :``%R``: changeset revision number
3628 :``%b``: basename of the exporting repository
3631 :``%b``: basename of the exporting repository
3629 :``%h``: short-form changeset hash (12 hexadecimal digits)
3632 :``%h``: short-form changeset hash (12 hexadecimal digits)
3630 :``%m``: first line of the commit message (only alphanumeric characters)
3633 :``%m``: first line of the commit message (only alphanumeric characters)
3631 :``%n``: zero-padded sequence number, starting at 1
3634 :``%n``: zero-padded sequence number, starting at 1
3632 :``%r``: zero-padded changeset revision number
3635 :``%r``: zero-padded changeset revision number
3633
3636
3634 Without the -a/--text option, export will avoid generating diffs
3637 Without the -a/--text option, export will avoid generating diffs
3635 of files it detects as binary. With -a, export will generate a
3638 of files it detects as binary. With -a, export will generate a
3636 diff anyway, probably with undesirable results.
3639 diff anyway, probably with undesirable results.
3637
3640
3638 Use the -g/--git option to generate diffs in the git extended diff
3641 Use the -g/--git option to generate diffs in the git extended diff
3639 format. See :hg:`help diffs` for more information.
3642 format. See :hg:`help diffs` for more information.
3640
3643
3641 With the --switch-parent option, the diff will be against the
3644 With the --switch-parent option, the diff will be against the
3642 second parent. It can be useful to review a merge.
3645 second parent. It can be useful to review a merge.
3643
3646
3644 .. container:: verbose
3647 .. container:: verbose
3645
3648
3646 Examples:
3649 Examples:
3647
3650
3648 - use export and import to transplant a bugfix to the current
3651 - use export and import to transplant a bugfix to the current
3649 branch::
3652 branch::
3650
3653
3651 hg export -r 9353 | hg import -
3654 hg export -r 9353 | hg import -
3652
3655
3653 - export all the changesets between two revisions to a file with
3656 - export all the changesets between two revisions to a file with
3654 rename information::
3657 rename information::
3655
3658
3656 hg export --git -r 123:150 > changes.txt
3659 hg export --git -r 123:150 > changes.txt
3657
3660
3658 - split outgoing changes into a series of patches with
3661 - split outgoing changes into a series of patches with
3659 descriptive names::
3662 descriptive names::
3660
3663
3661 hg export -r "outgoing()" -o "%n-%m.patch"
3664 hg export -r "outgoing()" -o "%n-%m.patch"
3662
3665
3663 Returns 0 on success.
3666 Returns 0 on success.
3664 """
3667 """
3665 changesets += tuple(opts.get('rev', []))
3668 changesets += tuple(opts.get('rev', []))
3666 if not changesets:
3669 if not changesets:
3667 changesets = ['.']
3670 changesets = ['.']
3668 revs = scmutil.revrange(repo, changesets)
3671 revs = scmutil.revrange(repo, changesets)
3669 if not revs:
3672 if not revs:
3670 raise error.Abort(_("export requires at least one changeset"))
3673 raise error.Abort(_("export requires at least one changeset"))
3671 if len(revs) > 1:
3674 if len(revs) > 1:
3672 ui.note(_('exporting patches:\n'))
3675 ui.note(_('exporting patches:\n'))
3673 else:
3676 else:
3674 ui.note(_('exporting patch:\n'))
3677 ui.note(_('exporting patch:\n'))
3675 cmdutil.export(repo, revs, template=opts.get('output'),
3678 cmdutil.export(repo, revs, template=opts.get('output'),
3676 switch_parent=opts.get('switch_parent'),
3679 switch_parent=opts.get('switch_parent'),
3677 opts=patch.diffallopts(ui, opts))
3680 opts=patch.diffallopts(ui, opts))
3678
3681
3679 @command('files',
3682 @command('files',
3680 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3683 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3681 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3684 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3682 ] + walkopts + formatteropts + subrepoopts,
3685 ] + walkopts + formatteropts + subrepoopts,
3683 _('[OPTION]... [PATTERN]...'))
3686 _('[OPTION]... [PATTERN]...'))
3684 def files(ui, repo, *pats, **opts):
3687 def files(ui, repo, *pats, **opts):
3685 """list tracked files
3688 """list tracked files
3686
3689
3687 Print files under Mercurial control in the working directory or
3690 Print files under Mercurial control in the working directory or
3688 specified revision whose names match the given patterns (excluding
3691 specified revision whose names match the given patterns (excluding
3689 removed files).
3692 removed files).
3690
3693
3691 If no patterns are given to match, this command prints the names
3694 If no patterns are given to match, this command prints the names
3692 of all files under Mercurial control in the working directory.
3695 of all files under Mercurial control in the working directory.
3693
3696
3694 .. container:: verbose
3697 .. container:: verbose
3695
3698
3696 Examples:
3699 Examples:
3697
3700
3698 - list all files under the current directory::
3701 - list all files under the current directory::
3699
3702
3700 hg files .
3703 hg files .
3701
3704
3702 - shows sizes and flags for current revision::
3705 - shows sizes and flags for current revision::
3703
3706
3704 hg files -vr .
3707 hg files -vr .
3705
3708
3706 - list all files named README::
3709 - list all files named README::
3707
3710
3708 hg files -I "**/README"
3711 hg files -I "**/README"
3709
3712
3710 - list all binary files::
3713 - list all binary files::
3711
3714
3712 hg files "set:binary()"
3715 hg files "set:binary()"
3713
3716
3714 - find files containing a regular expression::
3717 - find files containing a regular expression::
3715
3718
3716 hg files "set:grep('bob')"
3719 hg files "set:grep('bob')"
3717
3720
3718 - search tracked file contents with xargs and grep::
3721 - search tracked file contents with xargs and grep::
3719
3722
3720 hg files -0 | xargs -0 grep foo
3723 hg files -0 | xargs -0 grep foo
3721
3724
3722 See :hg:`help patterns` and :hg:`help filesets` for more information
3725 See :hg:`help patterns` and :hg:`help filesets` for more information
3723 on specifying file patterns.
3726 on specifying file patterns.
3724
3727
3725 Returns 0 if a match is found, 1 otherwise.
3728 Returns 0 if a match is found, 1 otherwise.
3726
3729
3727 """
3730 """
3728 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3731 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3729
3732
3730 end = '\n'
3733 end = '\n'
3731 if opts.get('print0'):
3734 if opts.get('print0'):
3732 end = '\0'
3735 end = '\0'
3733 fm = ui.formatter('files', opts)
3736 fm = ui.formatter('files', opts)
3734 fmt = '%s' + end
3737 fmt = '%s' + end
3735
3738
3736 m = scmutil.match(ctx, pats, opts)
3739 m = scmutil.match(ctx, pats, opts)
3737 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3740 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3738
3741
3739 fm.end()
3742 fm.end()
3740
3743
3741 return ret
3744 return ret
3742
3745
3743 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3746 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3744 def forget(ui, repo, *pats, **opts):
3747 def forget(ui, repo, *pats, **opts):
3745 """forget the specified files on the next commit
3748 """forget the specified files on the next commit
3746
3749
3747 Mark the specified files so they will no longer be tracked
3750 Mark the specified files so they will no longer be tracked
3748 after the next commit.
3751 after the next commit.
3749
3752
3750 This only removes files from the current branch, not from the
3753 This only removes files from the current branch, not from the
3751 entire project history, and it does not delete them from the
3754 entire project history, and it does not delete them from the
3752 working directory.
3755 working directory.
3753
3756
3754 To delete the file from the working directory, see :hg:`remove`.
3757 To delete the file from the working directory, see :hg:`remove`.
3755
3758
3756 To undo a forget before the next commit, see :hg:`add`.
3759 To undo a forget before the next commit, see :hg:`add`.
3757
3760
3758 .. container:: verbose
3761 .. container:: verbose
3759
3762
3760 Examples:
3763 Examples:
3761
3764
3762 - forget newly-added binary files::
3765 - forget newly-added binary files::
3763
3766
3764 hg forget "set:added() and binary()"
3767 hg forget "set:added() and binary()"
3765
3768
3766 - forget files that would be excluded by .hgignore::
3769 - forget files that would be excluded by .hgignore::
3767
3770
3768 hg forget "set:hgignore()"
3771 hg forget "set:hgignore()"
3769
3772
3770 Returns 0 on success.
3773 Returns 0 on success.
3771 """
3774 """
3772
3775
3773 if not pats:
3776 if not pats:
3774 raise error.Abort(_('no files specified'))
3777 raise error.Abort(_('no files specified'))
3775
3778
3776 m = scmutil.match(repo[None], pats, opts)
3779 m = scmutil.match(repo[None], pats, opts)
3777 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3780 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3778 return rejected and 1 or 0
3781 return rejected and 1 or 0
3779
3782
3780 @command(
3783 @command(
3781 'graft',
3784 'graft',
3782 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3785 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3783 ('c', 'continue', False, _('resume interrupted graft')),
3786 ('c', 'continue', False, _('resume interrupted graft')),
3784 ('e', 'edit', False, _('invoke editor on commit messages')),
3787 ('e', 'edit', False, _('invoke editor on commit messages')),
3785 ('', 'log', None, _('append graft info to log message')),
3788 ('', 'log', None, _('append graft info to log message')),
3786 ('f', 'force', False, _('force graft')),
3789 ('f', 'force', False, _('force graft')),
3787 ('D', 'currentdate', False,
3790 ('D', 'currentdate', False,
3788 _('record the current date as commit date')),
3791 _('record the current date as commit date')),
3789 ('U', 'currentuser', False,
3792 ('U', 'currentuser', False,
3790 _('record the current user as committer'), _('DATE'))]
3793 _('record the current user as committer'), _('DATE'))]
3791 + commitopts2 + mergetoolopts + dryrunopts,
3794 + commitopts2 + mergetoolopts + dryrunopts,
3792 _('[OPTION]... [-r] REV...'))
3795 _('[OPTION]... [-r] REV...'))
3793 def graft(ui, repo, *revs, **opts):
3796 def graft(ui, repo, *revs, **opts):
3794 '''copy changes from other branches onto the current branch
3797 '''copy changes from other branches onto the current branch
3795
3798
3796 This command uses Mercurial's merge logic to copy individual
3799 This command uses Mercurial's merge logic to copy individual
3797 changes from other branches without merging branches in the
3800 changes from other branches without merging branches in the
3798 history graph. This is sometimes known as 'backporting' or
3801 history graph. This is sometimes known as 'backporting' or
3799 'cherry-picking'. By default, graft will copy user, date, and
3802 'cherry-picking'. By default, graft will copy user, date, and
3800 description from the source changesets.
3803 description from the source changesets.
3801
3804
3802 Changesets that are ancestors of the current revision, that have
3805 Changesets that are ancestors of the current revision, that have
3803 already been grafted, or that are merges will be skipped.
3806 already been grafted, or that are merges will be skipped.
3804
3807
3805 If --log is specified, log messages will have a comment appended
3808 If --log is specified, log messages will have a comment appended
3806 of the form::
3809 of the form::
3807
3810
3808 (grafted from CHANGESETHASH)
3811 (grafted from CHANGESETHASH)
3809
3812
3810 If --force is specified, revisions will be grafted even if they
3813 If --force is specified, revisions will be grafted even if they
3811 are already ancestors of or have been grafted to the destination.
3814 are already ancestors of or have been grafted to the destination.
3812 This is useful when the revisions have since been backed out.
3815 This is useful when the revisions have since been backed out.
3813
3816
3814 If a graft merge results in conflicts, the graft process is
3817 If a graft merge results in conflicts, the graft process is
3815 interrupted so that the current merge can be manually resolved.
3818 interrupted so that the current merge can be manually resolved.
3816 Once all conflicts are addressed, the graft process can be
3819 Once all conflicts are addressed, the graft process can be
3817 continued with the -c/--continue option.
3820 continued with the -c/--continue option.
3818
3821
3819 .. note::
3822 .. note::
3820
3823
3821 The -c/--continue option does not reapply earlier options, except
3824 The -c/--continue option does not reapply earlier options, except
3822 for --force.
3825 for --force.
3823
3826
3824 .. container:: verbose
3827 .. container:: verbose
3825
3828
3826 Examples:
3829 Examples:
3827
3830
3828 - copy a single change to the stable branch and edit its description::
3831 - copy a single change to the stable branch and edit its description::
3829
3832
3830 hg update stable
3833 hg update stable
3831 hg graft --edit 9393
3834 hg graft --edit 9393
3832
3835
3833 - graft a range of changesets with one exception, updating dates::
3836 - graft a range of changesets with one exception, updating dates::
3834
3837
3835 hg graft -D "2085::2093 and not 2091"
3838 hg graft -D "2085::2093 and not 2091"
3836
3839
3837 - continue a graft after resolving conflicts::
3840 - continue a graft after resolving conflicts::
3838
3841
3839 hg graft -c
3842 hg graft -c
3840
3843
3841 - show the source of a grafted changeset::
3844 - show the source of a grafted changeset::
3842
3845
3843 hg log --debug -r .
3846 hg log --debug -r .
3844
3847
3845 See :hg:`help revisions` and :hg:`help revsets` for more about
3848 See :hg:`help revisions` and :hg:`help revsets` for more about
3846 specifying revisions.
3849 specifying revisions.
3847
3850
3848 Returns 0 on successful completion.
3851 Returns 0 on successful completion.
3849 '''
3852 '''
3850 wlock = None
3853 wlock = None
3851 try:
3854 try:
3852 wlock = repo.wlock()
3855 wlock = repo.wlock()
3853 return _dograft(ui, repo, *revs, **opts)
3856 return _dograft(ui, repo, *revs, **opts)
3854 finally:
3857 finally:
3855 release(wlock)
3858 release(wlock)
3856
3859
3857 def _dograft(ui, repo, *revs, **opts):
3860 def _dograft(ui, repo, *revs, **opts):
3858 revs = list(revs)
3861 revs = list(revs)
3859 revs.extend(opts['rev'])
3862 revs.extend(opts['rev'])
3860
3863
3861 if not opts.get('user') and opts.get('currentuser'):
3864 if not opts.get('user') and opts.get('currentuser'):
3862 opts['user'] = ui.username()
3865 opts['user'] = ui.username()
3863 if not opts.get('date') and opts.get('currentdate'):
3866 if not opts.get('date') and opts.get('currentdate'):
3864 opts['date'] = "%d %d" % util.makedate()
3867 opts['date'] = "%d %d" % util.makedate()
3865
3868
3866 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3869 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3867
3870
3868 cont = False
3871 cont = False
3869 if opts['continue']:
3872 if opts['continue']:
3870 cont = True
3873 cont = True
3871 if revs:
3874 if revs:
3872 raise error.Abort(_("can't specify --continue and revisions"))
3875 raise error.Abort(_("can't specify --continue and revisions"))
3873 # read in unfinished revisions
3876 # read in unfinished revisions
3874 try:
3877 try:
3875 nodes = repo.vfs.read('graftstate').splitlines()
3878 nodes = repo.vfs.read('graftstate').splitlines()
3876 revs = [repo[node].rev() for node in nodes]
3879 revs = [repo[node].rev() for node in nodes]
3877 except IOError as inst:
3880 except IOError as inst:
3878 if inst.errno != errno.ENOENT:
3881 if inst.errno != errno.ENOENT:
3879 raise
3882 raise
3880 raise error.Abort(_("no graft state found, can't continue"))
3883 raise error.Abort(_("no graft state found, can't continue"))
3881 else:
3884 else:
3882 cmdutil.checkunfinished(repo)
3885 cmdutil.checkunfinished(repo)
3883 cmdutil.bailifchanged(repo)
3886 cmdutil.bailifchanged(repo)
3884 if not revs:
3887 if not revs:
3885 raise error.Abort(_('no revisions specified'))
3888 raise error.Abort(_('no revisions specified'))
3886 revs = scmutil.revrange(repo, revs)
3889 revs = scmutil.revrange(repo, revs)
3887
3890
3888 skipped = set()
3891 skipped = set()
3889 # check for merges
3892 # check for merges
3890 for rev in repo.revs('%ld and merge()', revs):
3893 for rev in repo.revs('%ld and merge()', revs):
3891 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3894 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3892 skipped.add(rev)
3895 skipped.add(rev)
3893 revs = [r for r in revs if r not in skipped]
3896 revs = [r for r in revs if r not in skipped]
3894 if not revs:
3897 if not revs:
3895 return -1
3898 return -1
3896
3899
3897 # Don't check in the --continue case, in effect retaining --force across
3900 # Don't check in the --continue case, in effect retaining --force across
3898 # --continues. That's because without --force, any revisions we decided to
3901 # --continues. That's because without --force, any revisions we decided to
3899 # skip would have been filtered out here, so they wouldn't have made their
3902 # skip would have been filtered out here, so they wouldn't have made their
3900 # way to the graftstate. With --force, any revisions we would have otherwise
3903 # way to the graftstate. With --force, any revisions we would have otherwise
3901 # skipped would not have been filtered out, and if they hadn't been applied
3904 # skipped would not have been filtered out, and if they hadn't been applied
3902 # already, they'd have been in the graftstate.
3905 # already, they'd have been in the graftstate.
3903 if not (cont or opts.get('force')):
3906 if not (cont or opts.get('force')):
3904 # check for ancestors of dest branch
3907 # check for ancestors of dest branch
3905 crev = repo['.'].rev()
3908 crev = repo['.'].rev()
3906 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3909 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3907 # Cannot use x.remove(y) on smart set, this has to be a list.
3910 # Cannot use x.remove(y) on smart set, this has to be a list.
3908 # XXX make this lazy in the future
3911 # XXX make this lazy in the future
3909 revs = list(revs)
3912 revs = list(revs)
3910 # don't mutate while iterating, create a copy
3913 # don't mutate while iterating, create a copy
3911 for rev in list(revs):
3914 for rev in list(revs):
3912 if rev in ancestors:
3915 if rev in ancestors:
3913 ui.warn(_('skipping ancestor revision %d:%s\n') %
3916 ui.warn(_('skipping ancestor revision %d:%s\n') %
3914 (rev, repo[rev]))
3917 (rev, repo[rev]))
3915 # XXX remove on list is slow
3918 # XXX remove on list is slow
3916 revs.remove(rev)
3919 revs.remove(rev)
3917 if not revs:
3920 if not revs:
3918 return -1
3921 return -1
3919
3922
3920 # analyze revs for earlier grafts
3923 # analyze revs for earlier grafts
3921 ids = {}
3924 ids = {}
3922 for ctx in repo.set("%ld", revs):
3925 for ctx in repo.set("%ld", revs):
3923 ids[ctx.hex()] = ctx.rev()
3926 ids[ctx.hex()] = ctx.rev()
3924 n = ctx.extra().get('source')
3927 n = ctx.extra().get('source')
3925 if n:
3928 if n:
3926 ids[n] = ctx.rev()
3929 ids[n] = ctx.rev()
3927
3930
3928 # check ancestors for earlier grafts
3931 # check ancestors for earlier grafts
3929 ui.debug('scanning for duplicate grafts\n')
3932 ui.debug('scanning for duplicate grafts\n')
3930
3933
3931 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3934 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3932 ctx = repo[rev]
3935 ctx = repo[rev]
3933 n = ctx.extra().get('source')
3936 n = ctx.extra().get('source')
3934 if n in ids:
3937 if n in ids:
3935 try:
3938 try:
3936 r = repo[n].rev()
3939 r = repo[n].rev()
3937 except error.RepoLookupError:
3940 except error.RepoLookupError:
3938 r = None
3941 r = None
3939 if r in revs:
3942 if r in revs:
3940 ui.warn(_('skipping revision %d:%s '
3943 ui.warn(_('skipping revision %d:%s '
3941 '(already grafted to %d:%s)\n')
3944 '(already grafted to %d:%s)\n')
3942 % (r, repo[r], rev, ctx))
3945 % (r, repo[r], rev, ctx))
3943 revs.remove(r)
3946 revs.remove(r)
3944 elif ids[n] in revs:
3947 elif ids[n] in revs:
3945 if r is None:
3948 if r is None:
3946 ui.warn(_('skipping already grafted revision %d:%s '
3949 ui.warn(_('skipping already grafted revision %d:%s '
3947 '(%d:%s also has unknown origin %s)\n')
3950 '(%d:%s also has unknown origin %s)\n')
3948 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3951 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3949 else:
3952 else:
3950 ui.warn(_('skipping already grafted revision %d:%s '
3953 ui.warn(_('skipping already grafted revision %d:%s '
3951 '(%d:%s also has origin %d:%s)\n')
3954 '(%d:%s also has origin %d:%s)\n')
3952 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3955 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3953 revs.remove(ids[n])
3956 revs.remove(ids[n])
3954 elif ctx.hex() in ids:
3957 elif ctx.hex() in ids:
3955 r = ids[ctx.hex()]
3958 r = ids[ctx.hex()]
3956 ui.warn(_('skipping already grafted revision %d:%s '
3959 ui.warn(_('skipping already grafted revision %d:%s '
3957 '(was grafted from %d:%s)\n') %
3960 '(was grafted from %d:%s)\n') %
3958 (r, repo[r], rev, ctx))
3961 (r, repo[r], rev, ctx))
3959 revs.remove(r)
3962 revs.remove(r)
3960 if not revs:
3963 if not revs:
3961 return -1
3964 return -1
3962
3965
3963 try:
3966 try:
3964 for pos, ctx in enumerate(repo.set("%ld", revs)):
3967 for pos, ctx in enumerate(repo.set("%ld", revs)):
3965 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3968 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3966 ctx.description().split('\n', 1)[0])
3969 ctx.description().split('\n', 1)[0])
3967 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3970 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3968 if names:
3971 if names:
3969 desc += ' (%s)' % ' '.join(names)
3972 desc += ' (%s)' % ' '.join(names)
3970 ui.status(_('grafting %s\n') % desc)
3973 ui.status(_('grafting %s\n') % desc)
3971 if opts.get('dry_run'):
3974 if opts.get('dry_run'):
3972 continue
3975 continue
3973
3976
3974 extra = ctx.extra().copy()
3977 extra = ctx.extra().copy()
3975 del extra['branch']
3978 del extra['branch']
3976 source = extra.get('source')
3979 source = extra.get('source')
3977 if source:
3980 if source:
3978 extra['intermediate-source'] = ctx.hex()
3981 extra['intermediate-source'] = ctx.hex()
3979 else:
3982 else:
3980 extra['source'] = ctx.hex()
3983 extra['source'] = ctx.hex()
3981 user = ctx.user()
3984 user = ctx.user()
3982 if opts.get('user'):
3985 if opts.get('user'):
3983 user = opts['user']
3986 user = opts['user']
3984 date = ctx.date()
3987 date = ctx.date()
3985 if opts.get('date'):
3988 if opts.get('date'):
3986 date = opts['date']
3989 date = opts['date']
3987 message = ctx.description()
3990 message = ctx.description()
3988 if opts.get('log'):
3991 if opts.get('log'):
3989 message += '\n(grafted from %s)' % ctx.hex()
3992 message += '\n(grafted from %s)' % ctx.hex()
3990
3993
3991 # we don't merge the first commit when continuing
3994 # we don't merge the first commit when continuing
3992 if not cont:
3995 if not cont:
3993 # perform the graft merge with p1(rev) as 'ancestor'
3996 # perform the graft merge with p1(rev) as 'ancestor'
3994 try:
3997 try:
3995 # ui.forcemerge is an internal variable, do not document
3998 # ui.forcemerge is an internal variable, do not document
3996 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3999 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3997 'graft')
4000 'graft')
3998 stats = mergemod.graft(repo, ctx, ctx.p1(),
4001 stats = mergemod.graft(repo, ctx, ctx.p1(),
3999 ['local', 'graft'])
4002 ['local', 'graft'])
4000 finally:
4003 finally:
4001 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4004 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4002 # report any conflicts
4005 # report any conflicts
4003 if stats and stats[3] > 0:
4006 if stats and stats[3] > 0:
4004 # write out state for --continue
4007 # write out state for --continue
4005 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4008 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4006 repo.vfs.write('graftstate', ''.join(nodelines))
4009 repo.vfs.write('graftstate', ''.join(nodelines))
4007 extra = ''
4010 extra = ''
4008 if opts.get('user'):
4011 if opts.get('user'):
4009 extra += ' --user %s' % opts['user']
4012 extra += ' --user %s' % opts['user']
4010 if opts.get('date'):
4013 if opts.get('date'):
4011 extra += ' --date %s' % opts['date']
4014 extra += ' --date %s' % opts['date']
4012 if opts.get('log'):
4015 if opts.get('log'):
4013 extra += ' --log'
4016 extra += ' --log'
4014 hint=_('use hg resolve and hg graft --continue%s') % extra
4017 hint=_('use hg resolve and hg graft --continue%s') % extra
4015 raise error.Abort(
4018 raise error.Abort(
4016 _("unresolved conflicts, can't continue"),
4019 _("unresolved conflicts, can't continue"),
4017 hint=hint)
4020 hint=hint)
4018 else:
4021 else:
4019 cont = False
4022 cont = False
4020
4023
4021 # commit
4024 # commit
4022 node = repo.commit(text=message, user=user,
4025 node = repo.commit(text=message, user=user,
4023 date=date, extra=extra, editor=editor)
4026 date=date, extra=extra, editor=editor)
4024 if node is None:
4027 if node is None:
4025 ui.warn(
4028 ui.warn(
4026 _('note: graft of %d:%s created no changes to commit\n') %
4029 _('note: graft of %d:%s created no changes to commit\n') %
4027 (ctx.rev(), ctx))
4030 (ctx.rev(), ctx))
4028 finally:
4031 finally:
4029 # TODO: get rid of this meaningless try/finally enclosing.
4032 # TODO: get rid of this meaningless try/finally enclosing.
4030 # this is kept only to reduce changes in a patch.
4033 # this is kept only to reduce changes in a patch.
4031 pass
4034 pass
4032
4035
4033 # remove state when we complete successfully
4036 # remove state when we complete successfully
4034 if not opts.get('dry_run'):
4037 if not opts.get('dry_run'):
4035 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4038 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4036
4039
4037 return 0
4040 return 0
4038
4041
4039 @command('grep',
4042 @command('grep',
4040 [('0', 'print0', None, _('end fields with NUL')),
4043 [('0', 'print0', None, _('end fields with NUL')),
4041 ('', 'all', None, _('print all revisions that match')),
4044 ('', 'all', None, _('print all revisions that match')),
4042 ('a', 'text', None, _('treat all files as text')),
4045 ('a', 'text', None, _('treat all files as text')),
4043 ('f', 'follow', None,
4046 ('f', 'follow', None,
4044 _('follow changeset history,'
4047 _('follow changeset history,'
4045 ' or file history across copies and renames')),
4048 ' or file history across copies and renames')),
4046 ('i', 'ignore-case', None, _('ignore case when matching')),
4049 ('i', 'ignore-case', None, _('ignore case when matching')),
4047 ('l', 'files-with-matches', None,
4050 ('l', 'files-with-matches', None,
4048 _('print only filenames and revisions that match')),
4051 _('print only filenames and revisions that match')),
4049 ('n', 'line-number', None, _('print matching line numbers')),
4052 ('n', 'line-number', None, _('print matching line numbers')),
4050 ('r', 'rev', [],
4053 ('r', 'rev', [],
4051 _('only search files changed within revision range'), _('REV')),
4054 _('only search files changed within revision range'), _('REV')),
4052 ('u', 'user', None, _('list the author (long with -v)')),
4055 ('u', 'user', None, _('list the author (long with -v)')),
4053 ('d', 'date', None, _('list the date (short with -q)')),
4056 ('d', 'date', None, _('list the date (short with -q)')),
4054 ] + walkopts,
4057 ] + walkopts,
4055 _('[OPTION]... PATTERN [FILE]...'),
4058 _('[OPTION]... PATTERN [FILE]...'),
4056 inferrepo=True)
4059 inferrepo=True)
4057 def grep(ui, repo, pattern, *pats, **opts):
4060 def grep(ui, repo, pattern, *pats, **opts):
4058 """search for a pattern in specified files and revisions
4061 """search for a pattern in specified files and revisions
4059
4062
4060 Search revisions of files for a regular expression.
4063 Search revisions of files for a regular expression.
4061
4064
4062 This command behaves differently than Unix grep. It only accepts
4065 This command behaves differently than Unix grep. It only accepts
4063 Python/Perl regexps. It searches repository history, not the
4066 Python/Perl regexps. It searches repository history, not the
4064 working directory. It always prints the revision number in which a
4067 working directory. It always prints the revision number in which a
4065 match appears.
4068 match appears.
4066
4069
4067 By default, grep only prints output for the first revision of a
4070 By default, grep only prints output for the first revision of a
4068 file in which it finds a match. To get it to print every revision
4071 file in which it finds a match. To get it to print every revision
4069 that contains a change in match status ("-" for a match that
4072 that contains a change in match status ("-" for a match that
4070 becomes a non-match, or "+" for a non-match that becomes a match),
4073 becomes a non-match, or "+" for a non-match that becomes a match),
4071 use the --all flag.
4074 use the --all flag.
4072
4075
4073 Returns 0 if a match is found, 1 otherwise.
4076 Returns 0 if a match is found, 1 otherwise.
4074 """
4077 """
4075 reflags = re.M
4078 reflags = re.M
4076 if opts.get('ignore_case'):
4079 if opts.get('ignore_case'):
4077 reflags |= re.I
4080 reflags |= re.I
4078 try:
4081 try:
4079 regexp = util.re.compile(pattern, reflags)
4082 regexp = util.re.compile(pattern, reflags)
4080 except re.error as inst:
4083 except re.error as inst:
4081 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4084 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4082 return 1
4085 return 1
4083 sep, eol = ':', '\n'
4086 sep, eol = ':', '\n'
4084 if opts.get('print0'):
4087 if opts.get('print0'):
4085 sep = eol = '\0'
4088 sep = eol = '\0'
4086
4089
4087 getfile = util.lrucachefunc(repo.file)
4090 getfile = util.lrucachefunc(repo.file)
4088
4091
4089 def matchlines(body):
4092 def matchlines(body):
4090 begin = 0
4093 begin = 0
4091 linenum = 0
4094 linenum = 0
4092 while begin < len(body):
4095 while begin < len(body):
4093 match = regexp.search(body, begin)
4096 match = regexp.search(body, begin)
4094 if not match:
4097 if not match:
4095 break
4098 break
4096 mstart, mend = match.span()
4099 mstart, mend = match.span()
4097 linenum += body.count('\n', begin, mstart) + 1
4100 linenum += body.count('\n', begin, mstart) + 1
4098 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4101 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4099 begin = body.find('\n', mend) + 1 or len(body) + 1
4102 begin = body.find('\n', mend) + 1 or len(body) + 1
4100 lend = begin - 1
4103 lend = begin - 1
4101 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4104 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4102
4105
4103 class linestate(object):
4106 class linestate(object):
4104 def __init__(self, line, linenum, colstart, colend):
4107 def __init__(self, line, linenum, colstart, colend):
4105 self.line = line
4108 self.line = line
4106 self.linenum = linenum
4109 self.linenum = linenum
4107 self.colstart = colstart
4110 self.colstart = colstart
4108 self.colend = colend
4111 self.colend = colend
4109
4112
4110 def __hash__(self):
4113 def __hash__(self):
4111 return hash((self.linenum, self.line))
4114 return hash((self.linenum, self.line))
4112
4115
4113 def __eq__(self, other):
4116 def __eq__(self, other):
4114 return self.line == other.line
4117 return self.line == other.line
4115
4118
4116 def __iter__(self):
4119 def __iter__(self):
4117 yield (self.line[:self.colstart], '')
4120 yield (self.line[:self.colstart], '')
4118 yield (self.line[self.colstart:self.colend], 'grep.match')
4121 yield (self.line[self.colstart:self.colend], 'grep.match')
4119 rest = self.line[self.colend:]
4122 rest = self.line[self.colend:]
4120 while rest != '':
4123 while rest != '':
4121 match = regexp.search(rest)
4124 match = regexp.search(rest)
4122 if not match:
4125 if not match:
4123 yield (rest, '')
4126 yield (rest, '')
4124 break
4127 break
4125 mstart, mend = match.span()
4128 mstart, mend = match.span()
4126 yield (rest[:mstart], '')
4129 yield (rest[:mstart], '')
4127 yield (rest[mstart:mend], 'grep.match')
4130 yield (rest[mstart:mend], 'grep.match')
4128 rest = rest[mend:]
4131 rest = rest[mend:]
4129
4132
4130 matches = {}
4133 matches = {}
4131 copies = {}
4134 copies = {}
4132 def grepbody(fn, rev, body):
4135 def grepbody(fn, rev, body):
4133 matches[rev].setdefault(fn, [])
4136 matches[rev].setdefault(fn, [])
4134 m = matches[rev][fn]
4137 m = matches[rev][fn]
4135 for lnum, cstart, cend, line in matchlines(body):
4138 for lnum, cstart, cend, line in matchlines(body):
4136 s = linestate(line, lnum, cstart, cend)
4139 s = linestate(line, lnum, cstart, cend)
4137 m.append(s)
4140 m.append(s)
4138
4141
4139 def difflinestates(a, b):
4142 def difflinestates(a, b):
4140 sm = difflib.SequenceMatcher(None, a, b)
4143 sm = difflib.SequenceMatcher(None, a, b)
4141 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4144 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4142 if tag == 'insert':
4145 if tag == 'insert':
4143 for i in xrange(blo, bhi):
4146 for i in xrange(blo, bhi):
4144 yield ('+', b[i])
4147 yield ('+', b[i])
4145 elif tag == 'delete':
4148 elif tag == 'delete':
4146 for i in xrange(alo, ahi):
4149 for i in xrange(alo, ahi):
4147 yield ('-', a[i])
4150 yield ('-', a[i])
4148 elif tag == 'replace':
4151 elif tag == 'replace':
4149 for i in xrange(alo, ahi):
4152 for i in xrange(alo, ahi):
4150 yield ('-', a[i])
4153 yield ('-', a[i])
4151 for i in xrange(blo, bhi):
4154 for i in xrange(blo, bhi):
4152 yield ('+', b[i])
4155 yield ('+', b[i])
4153
4156
4154 def display(fn, ctx, pstates, states):
4157 def display(fn, ctx, pstates, states):
4155 rev = ctx.rev()
4158 rev = ctx.rev()
4156 if ui.quiet:
4159 if ui.quiet:
4157 datefunc = util.shortdate
4160 datefunc = util.shortdate
4158 else:
4161 else:
4159 datefunc = util.datestr
4162 datefunc = util.datestr
4160 found = False
4163 found = False
4161 @util.cachefunc
4164 @util.cachefunc
4162 def binary():
4165 def binary():
4163 flog = getfile(fn)
4166 flog = getfile(fn)
4164 return util.binary(flog.read(ctx.filenode(fn)))
4167 return util.binary(flog.read(ctx.filenode(fn)))
4165
4168
4166 if opts.get('all'):
4169 if opts.get('all'):
4167 iter = difflinestates(pstates, states)
4170 iter = difflinestates(pstates, states)
4168 else:
4171 else:
4169 iter = [('', l) for l in states]
4172 iter = [('', l) for l in states]
4170 for change, l in iter:
4173 for change, l in iter:
4171 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4174 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4172
4175
4173 if opts.get('line_number'):
4176 if opts.get('line_number'):
4174 cols.append((str(l.linenum), 'grep.linenumber'))
4177 cols.append((str(l.linenum), 'grep.linenumber'))
4175 if opts.get('all'):
4178 if opts.get('all'):
4176 cols.append((change, 'grep.change'))
4179 cols.append((change, 'grep.change'))
4177 if opts.get('user'):
4180 if opts.get('user'):
4178 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4181 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4179 if opts.get('date'):
4182 if opts.get('date'):
4180 cols.append((datefunc(ctx.date()), 'grep.date'))
4183 cols.append((datefunc(ctx.date()), 'grep.date'))
4181 for col, label in cols[:-1]:
4184 for col, label in cols[:-1]:
4182 ui.write(col, label=label)
4185 ui.write(col, label=label)
4183 ui.write(sep, label='grep.sep')
4186 ui.write(sep, label='grep.sep')
4184 ui.write(cols[-1][0], label=cols[-1][1])
4187 ui.write(cols[-1][0], label=cols[-1][1])
4185 if not opts.get('files_with_matches'):
4188 if not opts.get('files_with_matches'):
4186 ui.write(sep, label='grep.sep')
4189 ui.write(sep, label='grep.sep')
4187 if not opts.get('text') and binary():
4190 if not opts.get('text') and binary():
4188 ui.write(" Binary file matches")
4191 ui.write(" Binary file matches")
4189 else:
4192 else:
4190 for s, label in l:
4193 for s, label in l:
4191 ui.write(s, label=label)
4194 ui.write(s, label=label)
4192 ui.write(eol)
4195 ui.write(eol)
4193 found = True
4196 found = True
4194 if opts.get('files_with_matches'):
4197 if opts.get('files_with_matches'):
4195 break
4198 break
4196 return found
4199 return found
4197
4200
4198 skip = {}
4201 skip = {}
4199 revfiles = {}
4202 revfiles = {}
4200 matchfn = scmutil.match(repo[None], pats, opts)
4203 matchfn = scmutil.match(repo[None], pats, opts)
4201 found = False
4204 found = False
4202 follow = opts.get('follow')
4205 follow = opts.get('follow')
4203
4206
4204 def prep(ctx, fns):
4207 def prep(ctx, fns):
4205 rev = ctx.rev()
4208 rev = ctx.rev()
4206 pctx = ctx.p1()
4209 pctx = ctx.p1()
4207 parent = pctx.rev()
4210 parent = pctx.rev()
4208 matches.setdefault(rev, {})
4211 matches.setdefault(rev, {})
4209 matches.setdefault(parent, {})
4212 matches.setdefault(parent, {})
4210 files = revfiles.setdefault(rev, [])
4213 files = revfiles.setdefault(rev, [])
4211 for fn in fns:
4214 for fn in fns:
4212 flog = getfile(fn)
4215 flog = getfile(fn)
4213 try:
4216 try:
4214 fnode = ctx.filenode(fn)
4217 fnode = ctx.filenode(fn)
4215 except error.LookupError:
4218 except error.LookupError:
4216 continue
4219 continue
4217
4220
4218 copied = flog.renamed(fnode)
4221 copied = flog.renamed(fnode)
4219 copy = follow and copied and copied[0]
4222 copy = follow and copied and copied[0]
4220 if copy:
4223 if copy:
4221 copies.setdefault(rev, {})[fn] = copy
4224 copies.setdefault(rev, {})[fn] = copy
4222 if fn in skip:
4225 if fn in skip:
4223 if copy:
4226 if copy:
4224 skip[copy] = True
4227 skip[copy] = True
4225 continue
4228 continue
4226 files.append(fn)
4229 files.append(fn)
4227
4230
4228 if fn not in matches[rev]:
4231 if fn not in matches[rev]:
4229 grepbody(fn, rev, flog.read(fnode))
4232 grepbody(fn, rev, flog.read(fnode))
4230
4233
4231 pfn = copy or fn
4234 pfn = copy or fn
4232 if pfn not in matches[parent]:
4235 if pfn not in matches[parent]:
4233 try:
4236 try:
4234 fnode = pctx.filenode(pfn)
4237 fnode = pctx.filenode(pfn)
4235 grepbody(pfn, parent, flog.read(fnode))
4238 grepbody(pfn, parent, flog.read(fnode))
4236 except error.LookupError:
4239 except error.LookupError:
4237 pass
4240 pass
4238
4241
4239 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4242 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4240 rev = ctx.rev()
4243 rev = ctx.rev()
4241 parent = ctx.p1().rev()
4244 parent = ctx.p1().rev()
4242 for fn in sorted(revfiles.get(rev, [])):
4245 for fn in sorted(revfiles.get(rev, [])):
4243 states = matches[rev][fn]
4246 states = matches[rev][fn]
4244 copy = copies.get(rev, {}).get(fn)
4247 copy = copies.get(rev, {}).get(fn)
4245 if fn in skip:
4248 if fn in skip:
4246 if copy:
4249 if copy:
4247 skip[copy] = True
4250 skip[copy] = True
4248 continue
4251 continue
4249 pstates = matches.get(parent, {}).get(copy or fn, [])
4252 pstates = matches.get(parent, {}).get(copy or fn, [])
4250 if pstates or states:
4253 if pstates or states:
4251 r = display(fn, ctx, pstates, states)
4254 r = display(fn, ctx, pstates, states)
4252 found = found or r
4255 found = found or r
4253 if r and not opts.get('all'):
4256 if r and not opts.get('all'):
4254 skip[fn] = True
4257 skip[fn] = True
4255 if copy:
4258 if copy:
4256 skip[copy] = True
4259 skip[copy] = True
4257 del matches[rev]
4260 del matches[rev]
4258 del revfiles[rev]
4261 del revfiles[rev]
4259
4262
4260 return not found
4263 return not found
4261
4264
4262 @command('heads',
4265 @command('heads',
4263 [('r', 'rev', '',
4266 [('r', 'rev', '',
4264 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4267 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4265 ('t', 'topo', False, _('show topological heads only')),
4268 ('t', 'topo', False, _('show topological heads only')),
4266 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4269 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4267 ('c', 'closed', False, _('show normal and closed branch heads')),
4270 ('c', 'closed', False, _('show normal and closed branch heads')),
4268 ] + templateopts,
4271 ] + templateopts,
4269 _('[-ct] [-r STARTREV] [REV]...'))
4272 _('[-ct] [-r STARTREV] [REV]...'))
4270 def heads(ui, repo, *branchrevs, **opts):
4273 def heads(ui, repo, *branchrevs, **opts):
4271 """show branch heads
4274 """show branch heads
4272
4275
4273 With no arguments, show all open branch heads in the repository.
4276 With no arguments, show all open branch heads in the repository.
4274 Branch heads are changesets that have no descendants on the
4277 Branch heads are changesets that have no descendants on the
4275 same branch. They are where development generally takes place and
4278 same branch. They are where development generally takes place and
4276 are the usual targets for update and merge operations.
4279 are the usual targets for update and merge operations.
4277
4280
4278 If one or more REVs are given, only open branch heads on the
4281 If one or more REVs are given, only open branch heads on the
4279 branches associated with the specified changesets are shown. This
4282 branches associated with the specified changesets are shown. This
4280 means that you can use :hg:`heads .` to see the heads on the
4283 means that you can use :hg:`heads .` to see the heads on the
4281 currently checked-out branch.
4284 currently checked-out branch.
4282
4285
4283 If -c/--closed is specified, also show branch heads marked closed
4286 If -c/--closed is specified, also show branch heads marked closed
4284 (see :hg:`commit --close-branch`).
4287 (see :hg:`commit --close-branch`).
4285
4288
4286 If STARTREV is specified, only those heads that are descendants of
4289 If STARTREV is specified, only those heads that are descendants of
4287 STARTREV will be displayed.
4290 STARTREV will be displayed.
4288
4291
4289 If -t/--topo is specified, named branch mechanics will be ignored and only
4292 If -t/--topo is specified, named branch mechanics will be ignored and only
4290 topological heads (changesets with no children) will be shown.
4293 topological heads (changesets with no children) will be shown.
4291
4294
4292 Returns 0 if matching heads are found, 1 if not.
4295 Returns 0 if matching heads are found, 1 if not.
4293 """
4296 """
4294
4297
4295 start = None
4298 start = None
4296 if 'rev' in opts:
4299 if 'rev' in opts:
4297 start = scmutil.revsingle(repo, opts['rev'], None).node()
4300 start = scmutil.revsingle(repo, opts['rev'], None).node()
4298
4301
4299 if opts.get('topo'):
4302 if opts.get('topo'):
4300 heads = [repo[h] for h in repo.heads(start)]
4303 heads = [repo[h] for h in repo.heads(start)]
4301 else:
4304 else:
4302 heads = []
4305 heads = []
4303 for branch in repo.branchmap():
4306 for branch in repo.branchmap():
4304 heads += repo.branchheads(branch, start, opts.get('closed'))
4307 heads += repo.branchheads(branch, start, opts.get('closed'))
4305 heads = [repo[h] for h in heads]
4308 heads = [repo[h] for h in heads]
4306
4309
4307 if branchrevs:
4310 if branchrevs:
4308 branches = set(repo[br].branch() for br in branchrevs)
4311 branches = set(repo[br].branch() for br in branchrevs)
4309 heads = [h for h in heads if h.branch() in branches]
4312 heads = [h for h in heads if h.branch() in branches]
4310
4313
4311 if opts.get('active') and branchrevs:
4314 if opts.get('active') and branchrevs:
4312 dagheads = repo.heads(start)
4315 dagheads = repo.heads(start)
4313 heads = [h for h in heads if h.node() in dagheads]
4316 heads = [h for h in heads if h.node() in dagheads]
4314
4317
4315 if branchrevs:
4318 if branchrevs:
4316 haveheads = set(h.branch() for h in heads)
4319 haveheads = set(h.branch() for h in heads)
4317 if branches - haveheads:
4320 if branches - haveheads:
4318 headless = ', '.join(b for b in branches - haveheads)
4321 headless = ', '.join(b for b in branches - haveheads)
4319 msg = _('no open branch heads found on branches %s')
4322 msg = _('no open branch heads found on branches %s')
4320 if opts.get('rev'):
4323 if opts.get('rev'):
4321 msg += _(' (started at %s)') % opts['rev']
4324 msg += _(' (started at %s)') % opts['rev']
4322 ui.warn((msg + '\n') % headless)
4325 ui.warn((msg + '\n') % headless)
4323
4326
4324 if not heads:
4327 if not heads:
4325 return 1
4328 return 1
4326
4329
4327 heads = sorted(heads, key=lambda x: -x.rev())
4330 heads = sorted(heads, key=lambda x: -x.rev())
4328 displayer = cmdutil.show_changeset(ui, repo, opts)
4331 displayer = cmdutil.show_changeset(ui, repo, opts)
4329 for ctx in heads:
4332 for ctx in heads:
4330 displayer.show(ctx)
4333 displayer.show(ctx)
4331 displayer.close()
4334 displayer.close()
4332
4335
4333 @command('help',
4336 @command('help',
4334 [('e', 'extension', None, _('show only help for extensions')),
4337 [('e', 'extension', None, _('show only help for extensions')),
4335 ('c', 'command', None, _('show only help for commands')),
4338 ('c', 'command', None, _('show only help for commands')),
4336 ('k', 'keyword', None, _('show topics matching keyword')),
4339 ('k', 'keyword', None, _('show topics matching keyword')),
4337 ],
4340 ],
4338 _('[-eck] [TOPIC]'),
4341 _('[-eck] [TOPIC]'),
4339 norepo=True)
4342 norepo=True)
4340 def help_(ui, name=None, **opts):
4343 def help_(ui, name=None, **opts):
4341 """show help for a given topic or a help overview
4344 """show help for a given topic or a help overview
4342
4345
4343 With no arguments, print a list of commands with short help messages.
4346 With no arguments, print a list of commands with short help messages.
4344
4347
4345 Given a topic, extension, or command name, print help for that
4348 Given a topic, extension, or command name, print help for that
4346 topic.
4349 topic.
4347
4350
4348 Returns 0 if successful.
4351 Returns 0 if successful.
4349 """
4352 """
4350
4353
4351 textwidth = min(ui.termwidth(), 80) - 2
4354 textwidth = min(ui.termwidth(), 80) - 2
4352
4355
4353 keep = []
4356 keep = []
4354 if ui.verbose:
4357 if ui.verbose:
4355 keep.append('verbose')
4358 keep.append('verbose')
4356 if sys.platform.startswith('win'):
4359 if sys.platform.startswith('win'):
4357 keep.append('windows')
4360 keep.append('windows')
4358 elif sys.platform == 'OpenVMS':
4361 elif sys.platform == 'OpenVMS':
4359 keep.append('vms')
4362 keep.append('vms')
4360 elif sys.platform == 'plan9':
4363 elif sys.platform == 'plan9':
4361 keep.append('plan9')
4364 keep.append('plan9')
4362 else:
4365 else:
4363 keep.append('unix')
4366 keep.append('unix')
4364 keep.append(sys.platform.lower())
4367 keep.append(sys.platform.lower())
4365
4368
4366 section = None
4369 section = None
4367 subtopic = None
4370 subtopic = None
4368 if name and '.' in name:
4371 if name and '.' in name:
4369 name, section = name.split('.', 1)
4372 name, section = name.split('.', 1)
4370 section = section.lower()
4373 section = section.lower()
4371 if '.' in section:
4374 if '.' in section:
4372 subtopic, section = section.split('.', 1)
4375 subtopic, section = section.split('.', 1)
4373 else:
4376 else:
4374 subtopic = section
4377 subtopic = section
4375
4378
4376 text = help.help_(ui, name, subtopic=subtopic, **opts)
4379 text = help.help_(ui, name, subtopic=subtopic, **opts)
4377
4380
4378 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4381 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4379 section=section)
4382 section=section)
4380
4383
4381 # We could have been given a weird ".foo" section without a name
4384 # We could have been given a weird ".foo" section without a name
4382 # to look for, or we could have simply failed to found "foo.bar"
4385 # to look for, or we could have simply failed to found "foo.bar"
4383 # because bar isn't a section of foo
4386 # because bar isn't a section of foo
4384 if section and not (formatted and name):
4387 if section and not (formatted and name):
4385 raise error.Abort(_("help section not found"))
4388 raise error.Abort(_("help section not found"))
4386
4389
4387 if 'verbose' in pruned:
4390 if 'verbose' in pruned:
4388 keep.append('omitted')
4391 keep.append('omitted')
4389 else:
4392 else:
4390 keep.append('notomitted')
4393 keep.append('notomitted')
4391 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4394 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4392 section=section)
4395 section=section)
4393 ui.write(formatted)
4396 ui.write(formatted)
4394
4397
4395
4398
4396 @command('identify|id',
4399 @command('identify|id',
4397 [('r', 'rev', '',
4400 [('r', 'rev', '',
4398 _('identify the specified revision'), _('REV')),
4401 _('identify the specified revision'), _('REV')),
4399 ('n', 'num', None, _('show local revision number')),
4402 ('n', 'num', None, _('show local revision number')),
4400 ('i', 'id', None, _('show global revision id')),
4403 ('i', 'id', None, _('show global revision id')),
4401 ('b', 'branch', None, _('show branch')),
4404 ('b', 'branch', None, _('show branch')),
4402 ('t', 'tags', None, _('show tags')),
4405 ('t', 'tags', None, _('show tags')),
4403 ('B', 'bookmarks', None, _('show bookmarks')),
4406 ('B', 'bookmarks', None, _('show bookmarks')),
4404 ] + remoteopts,
4407 ] + remoteopts,
4405 _('[-nibtB] [-r REV] [SOURCE]'),
4408 _('[-nibtB] [-r REV] [SOURCE]'),
4406 optionalrepo=True)
4409 optionalrepo=True)
4407 def identify(ui, repo, source=None, rev=None,
4410 def identify(ui, repo, source=None, rev=None,
4408 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4411 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4409 """identify the working directory or specified revision
4412 """identify the working directory or specified revision
4410
4413
4411 Print a summary identifying the repository state at REV using one or
4414 Print a summary identifying the repository state at REV using one or
4412 two parent hash identifiers, followed by a "+" if the working
4415 two parent hash identifiers, followed by a "+" if the working
4413 directory has uncommitted changes, the branch name (if not default),
4416 directory has uncommitted changes, the branch name (if not default),
4414 a list of tags, and a list of bookmarks.
4417 a list of tags, and a list of bookmarks.
4415
4418
4416 When REV is not given, print a summary of the current state of the
4419 When REV is not given, print a summary of the current state of the
4417 repository.
4420 repository.
4418
4421
4419 Specifying a path to a repository root or Mercurial bundle will
4422 Specifying a path to a repository root or Mercurial bundle will
4420 cause lookup to operate on that repository/bundle.
4423 cause lookup to operate on that repository/bundle.
4421
4424
4422 .. container:: verbose
4425 .. container:: verbose
4423
4426
4424 Examples:
4427 Examples:
4425
4428
4426 - generate a build identifier for the working directory::
4429 - generate a build identifier for the working directory::
4427
4430
4428 hg id --id > build-id.dat
4431 hg id --id > build-id.dat
4429
4432
4430 - find the revision corresponding to a tag::
4433 - find the revision corresponding to a tag::
4431
4434
4432 hg id -n -r 1.3
4435 hg id -n -r 1.3
4433
4436
4434 - check the most recent revision of a remote repository::
4437 - check the most recent revision of a remote repository::
4435
4438
4436 hg id -r tip http://selenic.com/hg/
4439 hg id -r tip http://selenic.com/hg/
4437
4440
4438 See :hg:`log` for generating more information about specific revisions,
4441 See :hg:`log` for generating more information about specific revisions,
4439 including full hash identifiers.
4442 including full hash identifiers.
4440
4443
4441 Returns 0 if successful.
4444 Returns 0 if successful.
4442 """
4445 """
4443
4446
4444 if not repo and not source:
4447 if not repo and not source:
4445 raise error.Abort(_("there is no Mercurial repository here "
4448 raise error.Abort(_("there is no Mercurial repository here "
4446 "(.hg not found)"))
4449 "(.hg not found)"))
4447
4450
4448 if ui.debugflag:
4451 if ui.debugflag:
4449 hexfunc = hex
4452 hexfunc = hex
4450 else:
4453 else:
4451 hexfunc = short
4454 hexfunc = short
4452 default = not (num or id or branch or tags or bookmarks)
4455 default = not (num or id or branch or tags or bookmarks)
4453 output = []
4456 output = []
4454 revs = []
4457 revs = []
4455
4458
4456 if source:
4459 if source:
4457 source, branches = hg.parseurl(ui.expandpath(source))
4460 source, branches = hg.parseurl(ui.expandpath(source))
4458 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4461 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4459 repo = peer.local()
4462 repo = peer.local()
4460 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4463 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4461
4464
4462 if not repo:
4465 if not repo:
4463 if num or branch or tags:
4466 if num or branch or tags:
4464 raise error.Abort(
4467 raise error.Abort(
4465 _("can't query remote revision number, branch, or tags"))
4468 _("can't query remote revision number, branch, or tags"))
4466 if not rev and revs:
4469 if not rev and revs:
4467 rev = revs[0]
4470 rev = revs[0]
4468 if not rev:
4471 if not rev:
4469 rev = "tip"
4472 rev = "tip"
4470
4473
4471 remoterev = peer.lookup(rev)
4474 remoterev = peer.lookup(rev)
4472 if default or id:
4475 if default or id:
4473 output = [hexfunc(remoterev)]
4476 output = [hexfunc(remoterev)]
4474
4477
4475 def getbms():
4478 def getbms():
4476 bms = []
4479 bms = []
4477
4480
4478 if 'bookmarks' in peer.listkeys('namespaces'):
4481 if 'bookmarks' in peer.listkeys('namespaces'):
4479 hexremoterev = hex(remoterev)
4482 hexremoterev = hex(remoterev)
4480 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4483 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4481 if bmr == hexremoterev]
4484 if bmr == hexremoterev]
4482
4485
4483 return sorted(bms)
4486 return sorted(bms)
4484
4487
4485 if bookmarks:
4488 if bookmarks:
4486 output.extend(getbms())
4489 output.extend(getbms())
4487 elif default and not ui.quiet:
4490 elif default and not ui.quiet:
4488 # multiple bookmarks for a single parent separated by '/'
4491 # multiple bookmarks for a single parent separated by '/'
4489 bm = '/'.join(getbms())
4492 bm = '/'.join(getbms())
4490 if bm:
4493 if bm:
4491 output.append(bm)
4494 output.append(bm)
4492 else:
4495 else:
4493 ctx = scmutil.revsingle(repo, rev, None)
4496 ctx = scmutil.revsingle(repo, rev, None)
4494
4497
4495 if ctx.rev() is None:
4498 if ctx.rev() is None:
4496 ctx = repo[None]
4499 ctx = repo[None]
4497 parents = ctx.parents()
4500 parents = ctx.parents()
4498 taglist = []
4501 taglist = []
4499 for p in parents:
4502 for p in parents:
4500 taglist.extend(p.tags())
4503 taglist.extend(p.tags())
4501
4504
4502 changed = ""
4505 changed = ""
4503 if default or id or num:
4506 if default or id or num:
4504 if (any(repo.status())
4507 if (any(repo.status())
4505 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4508 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4506 changed = '+'
4509 changed = '+'
4507 if default or id:
4510 if default or id:
4508 output = ["%s%s" %
4511 output = ["%s%s" %
4509 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4512 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4510 if num:
4513 if num:
4511 output.append("%s%s" %
4514 output.append("%s%s" %
4512 ('+'.join([str(p.rev()) for p in parents]), changed))
4515 ('+'.join([str(p.rev()) for p in parents]), changed))
4513 else:
4516 else:
4514 if default or id:
4517 if default or id:
4515 output = [hexfunc(ctx.node())]
4518 output = [hexfunc(ctx.node())]
4516 if num:
4519 if num:
4517 output.append(str(ctx.rev()))
4520 output.append(str(ctx.rev()))
4518 taglist = ctx.tags()
4521 taglist = ctx.tags()
4519
4522
4520 if default and not ui.quiet:
4523 if default and not ui.quiet:
4521 b = ctx.branch()
4524 b = ctx.branch()
4522 if b != 'default':
4525 if b != 'default':
4523 output.append("(%s)" % b)
4526 output.append("(%s)" % b)
4524
4527
4525 # multiple tags for a single parent separated by '/'
4528 # multiple tags for a single parent separated by '/'
4526 t = '/'.join(taglist)
4529 t = '/'.join(taglist)
4527 if t:
4530 if t:
4528 output.append(t)
4531 output.append(t)
4529
4532
4530 # multiple bookmarks for a single parent separated by '/'
4533 # multiple bookmarks for a single parent separated by '/'
4531 bm = '/'.join(ctx.bookmarks())
4534 bm = '/'.join(ctx.bookmarks())
4532 if bm:
4535 if bm:
4533 output.append(bm)
4536 output.append(bm)
4534 else:
4537 else:
4535 if branch:
4538 if branch:
4536 output.append(ctx.branch())
4539 output.append(ctx.branch())
4537
4540
4538 if tags:
4541 if tags:
4539 output.extend(taglist)
4542 output.extend(taglist)
4540
4543
4541 if bookmarks:
4544 if bookmarks:
4542 output.extend(ctx.bookmarks())
4545 output.extend(ctx.bookmarks())
4543
4546
4544 ui.write("%s\n" % ' '.join(output))
4547 ui.write("%s\n" % ' '.join(output))
4545
4548
4546 @command('import|patch',
4549 @command('import|patch',
4547 [('p', 'strip', 1,
4550 [('p', 'strip', 1,
4548 _('directory strip option for patch. This has the same '
4551 _('directory strip option for patch. This has the same '
4549 'meaning as the corresponding patch option'), _('NUM')),
4552 'meaning as the corresponding patch option'), _('NUM')),
4550 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4553 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4551 ('e', 'edit', False, _('invoke editor on commit messages')),
4554 ('e', 'edit', False, _('invoke editor on commit messages')),
4552 ('f', 'force', None,
4555 ('f', 'force', None,
4553 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4556 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4554 ('', 'no-commit', None,
4557 ('', 'no-commit', None,
4555 _("don't commit, just update the working directory")),
4558 _("don't commit, just update the working directory")),
4556 ('', 'bypass', None,
4559 ('', 'bypass', None,
4557 _("apply patch without touching the working directory")),
4560 _("apply patch without touching the working directory")),
4558 ('', 'partial', None,
4561 ('', 'partial', None,
4559 _('commit even if some hunks fail')),
4562 _('commit even if some hunks fail')),
4560 ('', 'exact', None,
4563 ('', 'exact', None,
4561 _('apply patch to the nodes from which it was generated')),
4564 _('apply patch to the nodes from which it was generated')),
4562 ('', 'prefix', '',
4565 ('', 'prefix', '',
4563 _('apply patch to subdirectory'), _('DIR')),
4566 _('apply patch to subdirectory'), _('DIR')),
4564 ('', 'import-branch', None,
4567 ('', 'import-branch', None,
4565 _('use any branch information in patch (implied by --exact)'))] +
4568 _('use any branch information in patch (implied by --exact)'))] +
4566 commitopts + commitopts2 + similarityopts,
4569 commitopts + commitopts2 + similarityopts,
4567 _('[OPTION]... PATCH...'))
4570 _('[OPTION]... PATCH...'))
4568 def import_(ui, repo, patch1=None, *patches, **opts):
4571 def import_(ui, repo, patch1=None, *patches, **opts):
4569 """import an ordered set of patches
4572 """import an ordered set of patches
4570
4573
4571 Import a list of patches and commit them individually (unless
4574 Import a list of patches and commit them individually (unless
4572 --no-commit is specified).
4575 --no-commit is specified).
4573
4576
4574 To read a patch from standard input, use "-" as the patch name. If
4577 To read a patch from standard input, use "-" as the patch name. If
4575 a URL is specified, the patch will be downloaded from there.
4578 a URL is specified, the patch will be downloaded from there.
4576
4579
4577 Import first applies changes to the working directory (unless
4580 Import first applies changes to the working directory (unless
4578 --bypass is specified), import will abort if there are outstanding
4581 --bypass is specified), import will abort if there are outstanding
4579 changes.
4582 changes.
4580
4583
4581 Use --bypass to apply and commit patches directly to the
4584 Use --bypass to apply and commit patches directly to the
4582 repository, without affecting the working directory. Without
4585 repository, without affecting the working directory. Without
4583 --exact, patches will be applied on top of the working directory
4586 --exact, patches will be applied on top of the working directory
4584 parent revision.
4587 parent revision.
4585
4588
4586 You can import a patch straight from a mail message. Even patches
4589 You can import a patch straight from a mail message. Even patches
4587 as attachments work (to use the body part, it must have type
4590 as attachments work (to use the body part, it must have type
4588 text/plain or text/x-patch). From and Subject headers of email
4591 text/plain or text/x-patch). From and Subject headers of email
4589 message are used as default committer and commit message. All
4592 message are used as default committer and commit message. All
4590 text/plain body parts before first diff are added to the commit
4593 text/plain body parts before first diff are added to the commit
4591 message.
4594 message.
4592
4595
4593 If the imported patch was generated by :hg:`export`, user and
4596 If the imported patch was generated by :hg:`export`, user and
4594 description from patch override values from message headers and
4597 description from patch override values from message headers and
4595 body. Values given on command line with -m/--message and -u/--user
4598 body. Values given on command line with -m/--message and -u/--user
4596 override these.
4599 override these.
4597
4600
4598 If --exact is specified, import will set the working directory to
4601 If --exact is specified, import will set the working directory to
4599 the parent of each patch before applying it, and will abort if the
4602 the parent of each patch before applying it, and will abort if the
4600 resulting changeset has a different ID than the one recorded in
4603 resulting changeset has a different ID than the one recorded in
4601 the patch. This may happen due to character set problems or other
4604 the patch. This may happen due to character set problems or other
4602 deficiencies in the text patch format.
4605 deficiencies in the text patch format.
4603
4606
4604 Use --partial to ensure a changeset will be created from the patch
4607 Use --partial to ensure a changeset will be created from the patch
4605 even if some hunks fail to apply. Hunks that fail to apply will be
4608 even if some hunks fail to apply. Hunks that fail to apply will be
4606 written to a <target-file>.rej file. Conflicts can then be resolved
4609 written to a <target-file>.rej file. Conflicts can then be resolved
4607 by hand before :hg:`commit --amend` is run to update the created
4610 by hand before :hg:`commit --amend` is run to update the created
4608 changeset. This flag exists to let people import patches that
4611 changeset. This flag exists to let people import patches that
4609 partially apply without losing the associated metadata (author,
4612 partially apply without losing the associated metadata (author,
4610 date, description, ...).
4613 date, description, ...).
4611
4614
4612 .. note::
4615 .. note::
4613
4616
4614 When no hunks apply cleanly, :hg:`import --partial` will create
4617 When no hunks apply cleanly, :hg:`import --partial` will create
4615 an empty changeset, importing only the patch metadata.
4618 an empty changeset, importing only the patch metadata.
4616
4619
4617 With -s/--similarity, hg will attempt to discover renames and
4620 With -s/--similarity, hg will attempt to discover renames and
4618 copies in the patch in the same way as :hg:`addremove`.
4621 copies in the patch in the same way as :hg:`addremove`.
4619
4622
4620 It is possible to use external patch programs to perform the patch
4623 It is possible to use external patch programs to perform the patch
4621 by setting the ``ui.patch`` configuration option. For the default
4624 by setting the ``ui.patch`` configuration option. For the default
4622 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4625 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4623 See :hg:`help config` for more information about configuration
4626 See :hg:`help config` for more information about configuration
4624 files and how to use these options.
4627 files and how to use these options.
4625
4628
4626 See :hg:`help dates` for a list of formats valid for -d/--date.
4629 See :hg:`help dates` for a list of formats valid for -d/--date.
4627
4630
4628 .. container:: verbose
4631 .. container:: verbose
4629
4632
4630 Examples:
4633 Examples:
4631
4634
4632 - import a traditional patch from a website and detect renames::
4635 - import a traditional patch from a website and detect renames::
4633
4636
4634 hg import -s 80 http://example.com/bugfix.patch
4637 hg import -s 80 http://example.com/bugfix.patch
4635
4638
4636 - import a changeset from an hgweb server::
4639 - import a changeset from an hgweb server::
4637
4640
4638 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4641 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4639
4642
4640 - import all the patches in an Unix-style mbox::
4643 - import all the patches in an Unix-style mbox::
4641
4644
4642 hg import incoming-patches.mbox
4645 hg import incoming-patches.mbox
4643
4646
4644 - attempt to exactly restore an exported changeset (not always
4647 - attempt to exactly restore an exported changeset (not always
4645 possible)::
4648 possible)::
4646
4649
4647 hg import --exact proposed-fix.patch
4650 hg import --exact proposed-fix.patch
4648
4651
4649 - use an external tool to apply a patch which is too fuzzy for
4652 - use an external tool to apply a patch which is too fuzzy for
4650 the default internal tool.
4653 the default internal tool.
4651
4654
4652 hg import --config ui.patch="patch --merge" fuzzy.patch
4655 hg import --config ui.patch="patch --merge" fuzzy.patch
4653
4656
4654 - change the default fuzzing from 2 to a less strict 7
4657 - change the default fuzzing from 2 to a less strict 7
4655
4658
4656 hg import --config ui.fuzz=7 fuzz.patch
4659 hg import --config ui.fuzz=7 fuzz.patch
4657
4660
4658 Returns 0 on success, 1 on partial success (see --partial).
4661 Returns 0 on success, 1 on partial success (see --partial).
4659 """
4662 """
4660
4663
4661 if not patch1:
4664 if not patch1:
4662 raise error.Abort(_('need at least one patch to import'))
4665 raise error.Abort(_('need at least one patch to import'))
4663
4666
4664 patches = (patch1,) + patches
4667 patches = (patch1,) + patches
4665
4668
4666 date = opts.get('date')
4669 date = opts.get('date')
4667 if date:
4670 if date:
4668 opts['date'] = util.parsedate(date)
4671 opts['date'] = util.parsedate(date)
4669
4672
4670 exact = opts.get('exact')
4673 exact = opts.get('exact')
4671 update = not opts.get('bypass')
4674 update = not opts.get('bypass')
4672 if not update and opts.get('no_commit'):
4675 if not update and opts.get('no_commit'):
4673 raise error.Abort(_('cannot use --no-commit with --bypass'))
4676 raise error.Abort(_('cannot use --no-commit with --bypass'))
4674 try:
4677 try:
4675 sim = float(opts.get('similarity') or 0)
4678 sim = float(opts.get('similarity') or 0)
4676 except ValueError:
4679 except ValueError:
4677 raise error.Abort(_('similarity must be a number'))
4680 raise error.Abort(_('similarity must be a number'))
4678 if sim < 0 or sim > 100:
4681 if sim < 0 or sim > 100:
4679 raise error.Abort(_('similarity must be between 0 and 100'))
4682 raise error.Abort(_('similarity must be between 0 and 100'))
4680 if sim and not update:
4683 if sim and not update:
4681 raise error.Abort(_('cannot use --similarity with --bypass'))
4684 raise error.Abort(_('cannot use --similarity with --bypass'))
4682 if exact:
4685 if exact:
4683 if opts.get('edit'):
4686 if opts.get('edit'):
4684 raise error.Abort(_('cannot use --exact with --edit'))
4687 raise error.Abort(_('cannot use --exact with --edit'))
4685 if opts.get('prefix'):
4688 if opts.get('prefix'):
4686 raise error.Abort(_('cannot use --exact with --prefix'))
4689 raise error.Abort(_('cannot use --exact with --prefix'))
4687
4690
4688 base = opts["base"]
4691 base = opts["base"]
4689 wlock = dsguard = lock = tr = None
4692 wlock = dsguard = lock = tr = None
4690 msgs = []
4693 msgs = []
4691 ret = 0
4694 ret = 0
4692
4695
4693
4696
4694 try:
4697 try:
4695 try:
4698 try:
4696 wlock = repo.wlock()
4699 wlock = repo.wlock()
4697
4700
4698 if update:
4701 if update:
4699 cmdutil.checkunfinished(repo)
4702 cmdutil.checkunfinished(repo)
4700 if (exact or not opts.get('force')):
4703 if (exact or not opts.get('force')):
4701 cmdutil.bailifchanged(repo)
4704 cmdutil.bailifchanged(repo)
4702
4705
4703 if not opts.get('no_commit'):
4706 if not opts.get('no_commit'):
4704 lock = repo.lock()
4707 lock = repo.lock()
4705 tr = repo.transaction('import')
4708 tr = repo.transaction('import')
4706 else:
4709 else:
4707 dsguard = cmdutil.dirstateguard(repo, 'import')
4710 dsguard = cmdutil.dirstateguard(repo, 'import')
4708 parents = repo[None].parents()
4711 parents = repo[None].parents()
4709 for patchurl in patches:
4712 for patchurl in patches:
4710 if patchurl == '-':
4713 if patchurl == '-':
4711 ui.status(_('applying patch from stdin\n'))
4714 ui.status(_('applying patch from stdin\n'))
4712 patchfile = ui.fin
4715 patchfile = ui.fin
4713 patchurl = 'stdin' # for error message
4716 patchurl = 'stdin' # for error message
4714 else:
4717 else:
4715 patchurl = os.path.join(base, patchurl)
4718 patchurl = os.path.join(base, patchurl)
4716 ui.status(_('applying %s\n') % patchurl)
4719 ui.status(_('applying %s\n') % patchurl)
4717 patchfile = hg.openpath(ui, patchurl)
4720 patchfile = hg.openpath(ui, patchurl)
4718
4721
4719 haspatch = False
4722 haspatch = False
4720 for hunk in patch.split(patchfile):
4723 for hunk in patch.split(patchfile):
4721 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4724 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4722 parents, opts,
4725 parents, opts,
4723 msgs, hg.clean)
4726 msgs, hg.clean)
4724 if msg:
4727 if msg:
4725 haspatch = True
4728 haspatch = True
4726 ui.note(msg + '\n')
4729 ui.note(msg + '\n')
4727 if update or exact:
4730 if update or exact:
4728 parents = repo[None].parents()
4731 parents = repo[None].parents()
4729 else:
4732 else:
4730 parents = [repo[node]]
4733 parents = [repo[node]]
4731 if rej:
4734 if rej:
4732 ui.write_err(_("patch applied partially\n"))
4735 ui.write_err(_("patch applied partially\n"))
4733 ui.write_err(_("(fix the .rej files and run "
4736 ui.write_err(_("(fix the .rej files and run "
4734 "`hg commit --amend`)\n"))
4737 "`hg commit --amend`)\n"))
4735 ret = 1
4738 ret = 1
4736 break
4739 break
4737
4740
4738 if not haspatch:
4741 if not haspatch:
4739 raise error.Abort(_('%s: no diffs found') % patchurl)
4742 raise error.Abort(_('%s: no diffs found') % patchurl)
4740
4743
4741 if tr:
4744 if tr:
4742 tr.close()
4745 tr.close()
4743 if msgs:
4746 if msgs:
4744 repo.savecommitmessage('\n* * *\n'.join(msgs))
4747 repo.savecommitmessage('\n* * *\n'.join(msgs))
4745 if dsguard:
4748 if dsguard:
4746 dsguard.close()
4749 dsguard.close()
4747 return ret
4750 return ret
4748 finally:
4751 finally:
4749 # TODO: get rid of this meaningless try/finally enclosing.
4752 # TODO: get rid of this meaningless try/finally enclosing.
4750 # this is kept only to reduce changes in a patch.
4753 # this is kept only to reduce changes in a patch.
4751 pass
4754 pass
4752 finally:
4755 finally:
4753 if tr:
4756 if tr:
4754 tr.release()
4757 tr.release()
4755 release(lock, dsguard, wlock)
4758 release(lock, dsguard, wlock)
4756
4759
4757 @command('incoming|in',
4760 @command('incoming|in',
4758 [('f', 'force', None,
4761 [('f', 'force', None,
4759 _('run even if remote repository is unrelated')),
4762 _('run even if remote repository is unrelated')),
4760 ('n', 'newest-first', None, _('show newest record first')),
4763 ('n', 'newest-first', None, _('show newest record first')),
4761 ('', 'bundle', '',
4764 ('', 'bundle', '',
4762 _('file to store the bundles into'), _('FILE')),
4765 _('file to store the bundles into'), _('FILE')),
4763 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4766 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4764 ('B', 'bookmarks', False, _("compare bookmarks")),
4767 ('B', 'bookmarks', False, _("compare bookmarks")),
4765 ('b', 'branch', [],
4768 ('b', 'branch', [],
4766 _('a specific branch you would like to pull'), _('BRANCH')),
4769 _('a specific branch you would like to pull'), _('BRANCH')),
4767 ] + logopts + remoteopts + subrepoopts,
4770 ] + logopts + remoteopts + subrepoopts,
4768 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4771 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4769 def incoming(ui, repo, source="default", **opts):
4772 def incoming(ui, repo, source="default", **opts):
4770 """show new changesets found in source
4773 """show new changesets found in source
4771
4774
4772 Show new changesets found in the specified path/URL or the default
4775 Show new changesets found in the specified path/URL or the default
4773 pull location. These are the changesets that would have been pulled
4776 pull location. These are the changesets that would have been pulled
4774 if a pull at the time you issued this command.
4777 if a pull at the time you issued this command.
4775
4778
4776 See pull for valid source format details.
4779 See pull for valid source format details.
4777
4780
4778 .. container:: verbose
4781 .. container:: verbose
4779
4782
4780 With -B/--bookmarks, the result of bookmark comparison between
4783 With -B/--bookmarks, the result of bookmark comparison between
4781 local and remote repositories is displayed. With -v/--verbose,
4784 local and remote repositories is displayed. With -v/--verbose,
4782 status is also displayed for each bookmark like below::
4785 status is also displayed for each bookmark like below::
4783
4786
4784 BM1 01234567890a added
4787 BM1 01234567890a added
4785 BM2 1234567890ab advanced
4788 BM2 1234567890ab advanced
4786 BM3 234567890abc diverged
4789 BM3 234567890abc diverged
4787 BM4 34567890abcd changed
4790 BM4 34567890abcd changed
4788
4791
4789 The action taken locally when pulling depends on the
4792 The action taken locally when pulling depends on the
4790 status of each bookmark:
4793 status of each bookmark:
4791
4794
4792 :``added``: pull will create it
4795 :``added``: pull will create it
4793 :``advanced``: pull will update it
4796 :``advanced``: pull will update it
4794 :``diverged``: pull will create a divergent bookmark
4797 :``diverged``: pull will create a divergent bookmark
4795 :``changed``: result depends on remote changesets
4798 :``changed``: result depends on remote changesets
4796
4799
4797 From the point of view of pulling behavior, bookmark
4800 From the point of view of pulling behavior, bookmark
4798 existing only in the remote repository are treated as ``added``,
4801 existing only in the remote repository are treated as ``added``,
4799 even if it is in fact locally deleted.
4802 even if it is in fact locally deleted.
4800
4803
4801 .. container:: verbose
4804 .. container:: verbose
4802
4805
4803 For remote repository, using --bundle avoids downloading the
4806 For remote repository, using --bundle avoids downloading the
4804 changesets twice if the incoming is followed by a pull.
4807 changesets twice if the incoming is followed by a pull.
4805
4808
4806 Examples:
4809 Examples:
4807
4810
4808 - show incoming changes with patches and full description::
4811 - show incoming changes with patches and full description::
4809
4812
4810 hg incoming -vp
4813 hg incoming -vp
4811
4814
4812 - show incoming changes excluding merges, store a bundle::
4815 - show incoming changes excluding merges, store a bundle::
4813
4816
4814 hg in -vpM --bundle incoming.hg
4817 hg in -vpM --bundle incoming.hg
4815 hg pull incoming.hg
4818 hg pull incoming.hg
4816
4819
4817 - briefly list changes inside a bundle::
4820 - briefly list changes inside a bundle::
4818
4821
4819 hg in changes.hg -T "{desc|firstline}\\n"
4822 hg in changes.hg -T "{desc|firstline}\\n"
4820
4823
4821 Returns 0 if there are incoming changes, 1 otherwise.
4824 Returns 0 if there are incoming changes, 1 otherwise.
4822 """
4825 """
4823 if opts.get('graph'):
4826 if opts.get('graph'):
4824 cmdutil.checkunsupportedgraphflags([], opts)
4827 cmdutil.checkunsupportedgraphflags([], opts)
4825 def display(other, chlist, displayer):
4828 def display(other, chlist, displayer):
4826 revdag = cmdutil.graphrevs(other, chlist, opts)
4829 revdag = cmdutil.graphrevs(other, chlist, opts)
4827 cmdutil.displaygraph(ui, repo, revdag, displayer,
4830 cmdutil.displaygraph(ui, repo, revdag, displayer,
4828 graphmod.asciiedges)
4831 graphmod.asciiedges)
4829
4832
4830 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4833 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4831 return 0
4834 return 0
4832
4835
4833 if opts.get('bundle') and opts.get('subrepos'):
4836 if opts.get('bundle') and opts.get('subrepos'):
4834 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4837 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4835
4838
4836 if opts.get('bookmarks'):
4839 if opts.get('bookmarks'):
4837 source, branches = hg.parseurl(ui.expandpath(source),
4840 source, branches = hg.parseurl(ui.expandpath(source),
4838 opts.get('branch'))
4841 opts.get('branch'))
4839 other = hg.peer(repo, opts, source)
4842 other = hg.peer(repo, opts, source)
4840 if 'bookmarks' not in other.listkeys('namespaces'):
4843 if 'bookmarks' not in other.listkeys('namespaces'):
4841 ui.warn(_("remote doesn't support bookmarks\n"))
4844 ui.warn(_("remote doesn't support bookmarks\n"))
4842 return 0
4845 return 0
4843 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4846 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4844 return bookmarks.incoming(ui, repo, other)
4847 return bookmarks.incoming(ui, repo, other)
4845
4848
4846 repo._subtoppath = ui.expandpath(source)
4849 repo._subtoppath = ui.expandpath(source)
4847 try:
4850 try:
4848 return hg.incoming(ui, repo, source, opts)
4851 return hg.incoming(ui, repo, source, opts)
4849 finally:
4852 finally:
4850 del repo._subtoppath
4853 del repo._subtoppath
4851
4854
4852
4855
4853 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4856 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4854 norepo=True)
4857 norepo=True)
4855 def init(ui, dest=".", **opts):
4858 def init(ui, dest=".", **opts):
4856 """create a new repository in the given directory
4859 """create a new repository in the given directory
4857
4860
4858 Initialize a new repository in the given directory. If the given
4861 Initialize a new repository in the given directory. If the given
4859 directory does not exist, it will be created.
4862 directory does not exist, it will be created.
4860
4863
4861 If no directory is given, the current directory is used.
4864 If no directory is given, the current directory is used.
4862
4865
4863 It is possible to specify an ``ssh://`` URL as the destination.
4866 It is possible to specify an ``ssh://`` URL as the destination.
4864 See :hg:`help urls` for more information.
4867 See :hg:`help urls` for more information.
4865
4868
4866 Returns 0 on success.
4869 Returns 0 on success.
4867 """
4870 """
4868 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4871 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4869
4872
4870 @command('locate',
4873 @command('locate',
4871 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4874 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4872 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4875 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4873 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4876 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4874 ] + walkopts,
4877 ] + walkopts,
4875 _('[OPTION]... [PATTERN]...'))
4878 _('[OPTION]... [PATTERN]...'))
4876 def locate(ui, repo, *pats, **opts):
4879 def locate(ui, repo, *pats, **opts):
4877 """locate files matching specific patterns (DEPRECATED)
4880 """locate files matching specific patterns (DEPRECATED)
4878
4881
4879 Print files under Mercurial control in the working directory whose
4882 Print files under Mercurial control in the working directory whose
4880 names match the given patterns.
4883 names match the given patterns.
4881
4884
4882 By default, this command searches all directories in the working
4885 By default, this command searches all directories in the working
4883 directory. To search just the current directory and its
4886 directory. To search just the current directory and its
4884 subdirectories, use "--include .".
4887 subdirectories, use "--include .".
4885
4888
4886 If no patterns are given to match, this command prints the names
4889 If no patterns are given to match, this command prints the names
4887 of all files under Mercurial control in the working directory.
4890 of all files under Mercurial control in the working directory.
4888
4891
4889 If you want to feed the output of this command into the "xargs"
4892 If you want to feed the output of this command into the "xargs"
4890 command, use the -0 option to both this command and "xargs". This
4893 command, use the -0 option to both this command and "xargs". This
4891 will avoid the problem of "xargs" treating single filenames that
4894 will avoid the problem of "xargs" treating single filenames that
4892 contain whitespace as multiple filenames.
4895 contain whitespace as multiple filenames.
4893
4896
4894 See :hg:`help files` for a more versatile command.
4897 See :hg:`help files` for a more versatile command.
4895
4898
4896 Returns 0 if a match is found, 1 otherwise.
4899 Returns 0 if a match is found, 1 otherwise.
4897 """
4900 """
4898 if opts.get('print0'):
4901 if opts.get('print0'):
4899 end = '\0'
4902 end = '\0'
4900 else:
4903 else:
4901 end = '\n'
4904 end = '\n'
4902 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4905 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4903
4906
4904 ret = 1
4907 ret = 1
4905 ctx = repo[rev]
4908 ctx = repo[rev]
4906 m = scmutil.match(ctx, pats, opts, default='relglob',
4909 m = scmutil.match(ctx, pats, opts, default='relglob',
4907 badfn=lambda x, y: False)
4910 badfn=lambda x, y: False)
4908
4911
4909 for abs in ctx.matches(m):
4912 for abs in ctx.matches(m):
4910 if opts.get('fullpath'):
4913 if opts.get('fullpath'):
4911 ui.write(repo.wjoin(abs), end)
4914 ui.write(repo.wjoin(abs), end)
4912 else:
4915 else:
4913 ui.write(((pats and m.rel(abs)) or abs), end)
4916 ui.write(((pats and m.rel(abs)) or abs), end)
4914 ret = 0
4917 ret = 0
4915
4918
4916 return ret
4919 return ret
4917
4920
4918 @command('^log|history',
4921 @command('^log|history',
4919 [('f', 'follow', None,
4922 [('f', 'follow', None,
4920 _('follow changeset history, or file history across copies and renames')),
4923 _('follow changeset history, or file history across copies and renames')),
4921 ('', 'follow-first', None,
4924 ('', 'follow-first', None,
4922 _('only follow the first parent of merge changesets (DEPRECATED)')),
4925 _('only follow the first parent of merge changesets (DEPRECATED)')),
4923 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4926 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4924 ('C', 'copies', None, _('show copied files')),
4927 ('C', 'copies', None, _('show copied files')),
4925 ('k', 'keyword', [],
4928 ('k', 'keyword', [],
4926 _('do case-insensitive search for a given text'), _('TEXT')),
4929 _('do case-insensitive search for a given text'), _('TEXT')),
4927 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4930 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4928 ('', 'removed', None, _('include revisions where files were removed')),
4931 ('', 'removed', None, _('include revisions where files were removed')),
4929 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4932 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4930 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4933 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4931 ('', 'only-branch', [],
4934 ('', 'only-branch', [],
4932 _('show only changesets within the given named branch (DEPRECATED)'),
4935 _('show only changesets within the given named branch (DEPRECATED)'),
4933 _('BRANCH')),
4936 _('BRANCH')),
4934 ('b', 'branch', [],
4937 ('b', 'branch', [],
4935 _('show changesets within the given named branch'), _('BRANCH')),
4938 _('show changesets within the given named branch'), _('BRANCH')),
4936 ('P', 'prune', [],
4939 ('P', 'prune', [],
4937 _('do not display revision or any of its ancestors'), _('REV')),
4940 _('do not display revision or any of its ancestors'), _('REV')),
4938 ] + logopts + walkopts,
4941 ] + logopts + walkopts,
4939 _('[OPTION]... [FILE]'),
4942 _('[OPTION]... [FILE]'),
4940 inferrepo=True)
4943 inferrepo=True)
4941 def log(ui, repo, *pats, **opts):
4944 def log(ui, repo, *pats, **opts):
4942 """show revision history of entire repository or files
4945 """show revision history of entire repository or files
4943
4946
4944 Print the revision history of the specified files or the entire
4947 Print the revision history of the specified files or the entire
4945 project.
4948 project.
4946
4949
4947 If no revision range is specified, the default is ``tip:0`` unless
4950 If no revision range is specified, the default is ``tip:0`` unless
4948 --follow is set, in which case the working directory parent is
4951 --follow is set, in which case the working directory parent is
4949 used as the starting revision.
4952 used as the starting revision.
4950
4953
4951 File history is shown without following rename or copy history of
4954 File history is shown without following rename or copy history of
4952 files. Use -f/--follow with a filename to follow history across
4955 files. Use -f/--follow with a filename to follow history across
4953 renames and copies. --follow without a filename will only show
4956 renames and copies. --follow without a filename will only show
4954 ancestors or descendants of the starting revision.
4957 ancestors or descendants of the starting revision.
4955
4958
4956 By default this command prints revision number and changeset id,
4959 By default this command prints revision number and changeset id,
4957 tags, non-trivial parents, user, date and time, and a summary for
4960 tags, non-trivial parents, user, date and time, and a summary for
4958 each commit. When the -v/--verbose switch is used, the list of
4961 each commit. When the -v/--verbose switch is used, the list of
4959 changed files and full commit message are shown.
4962 changed files and full commit message are shown.
4960
4963
4961 With --graph the revisions are shown as an ASCII art DAG with the most
4964 With --graph the revisions are shown as an ASCII art DAG with the most
4962 recent changeset at the top.
4965 recent changeset at the top.
4963 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4966 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4964 and '+' represents a fork where the changeset from the lines below is a
4967 and '+' represents a fork where the changeset from the lines below is a
4965 parent of the 'o' merge on the same line.
4968 parent of the 'o' merge on the same line.
4966
4969
4967 .. note::
4970 .. note::
4968
4971
4969 :hg:`log --patch` may generate unexpected diff output for merge
4972 :hg:`log --patch` may generate unexpected diff output for merge
4970 changesets, as it will only compare the merge changeset against
4973 changesets, as it will only compare the merge changeset against
4971 its first parent. Also, only files different from BOTH parents
4974 its first parent. Also, only files different from BOTH parents
4972 will appear in files:.
4975 will appear in files:.
4973
4976
4974 .. note::
4977 .. note::
4975
4978
4976 For performance reasons, :hg:`log FILE` may omit duplicate changes
4979 For performance reasons, :hg:`log FILE` may omit duplicate changes
4977 made on branches and will not show removals or mode changes. To
4980 made on branches and will not show removals or mode changes. To
4978 see all such changes, use the --removed switch.
4981 see all such changes, use the --removed switch.
4979
4982
4980 .. container:: verbose
4983 .. container:: verbose
4981
4984
4982 Some examples:
4985 Some examples:
4983
4986
4984 - changesets with full descriptions and file lists::
4987 - changesets with full descriptions and file lists::
4985
4988
4986 hg log -v
4989 hg log -v
4987
4990
4988 - changesets ancestral to the working directory::
4991 - changesets ancestral to the working directory::
4989
4992
4990 hg log -f
4993 hg log -f
4991
4994
4992 - last 10 commits on the current branch::
4995 - last 10 commits on the current branch::
4993
4996
4994 hg log -l 10 -b .
4997 hg log -l 10 -b .
4995
4998
4996 - changesets showing all modifications of a file, including removals::
4999 - changesets showing all modifications of a file, including removals::
4997
5000
4998 hg log --removed file.c
5001 hg log --removed file.c
4999
5002
5000 - all changesets that touch a directory, with diffs, excluding merges::
5003 - all changesets that touch a directory, with diffs, excluding merges::
5001
5004
5002 hg log -Mp lib/
5005 hg log -Mp lib/
5003
5006
5004 - all revision numbers that match a keyword::
5007 - all revision numbers that match a keyword::
5005
5008
5006 hg log -k bug --template "{rev}\\n"
5009 hg log -k bug --template "{rev}\\n"
5007
5010
5008 - the full hash identifier of the working directory parent::
5011 - the full hash identifier of the working directory parent::
5009
5012
5010 hg log -r . --template "{node}\\n"
5013 hg log -r . --template "{node}\\n"
5011
5014
5012 - list available log templates::
5015 - list available log templates::
5013
5016
5014 hg log -T list
5017 hg log -T list
5015
5018
5016 - check if a given changeset is included in a tagged release::
5019 - check if a given changeset is included in a tagged release::
5017
5020
5018 hg log -r "a21ccf and ancestor(1.9)"
5021 hg log -r "a21ccf and ancestor(1.9)"
5019
5022
5020 - find all changesets by some user in a date range::
5023 - find all changesets by some user in a date range::
5021
5024
5022 hg log -k alice -d "may 2008 to jul 2008"
5025 hg log -k alice -d "may 2008 to jul 2008"
5023
5026
5024 - summary of all changesets after the last tag::
5027 - summary of all changesets after the last tag::
5025
5028
5026 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5029 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5027
5030
5028 See :hg:`help dates` for a list of formats valid for -d/--date.
5031 See :hg:`help dates` for a list of formats valid for -d/--date.
5029
5032
5030 See :hg:`help revisions` and :hg:`help revsets` for more about
5033 See :hg:`help revisions` and :hg:`help revsets` for more about
5031 specifying revisions.
5034 specifying revisions.
5032
5035
5033 See :hg:`help templates` for more about pre-packaged styles and
5036 See :hg:`help templates` for more about pre-packaged styles and
5034 specifying custom templates.
5037 specifying custom templates.
5035
5038
5036 Returns 0 on success.
5039 Returns 0 on success.
5037
5040
5038 """
5041 """
5039 if opts.get('follow') and opts.get('rev'):
5042 if opts.get('follow') and opts.get('rev'):
5040 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5043 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5041 del opts['follow']
5044 del opts['follow']
5042
5045
5043 if opts.get('graph'):
5046 if opts.get('graph'):
5044 return cmdutil.graphlog(ui, repo, *pats, **opts)
5047 return cmdutil.graphlog(ui, repo, *pats, **opts)
5045
5048
5046 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5049 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5047 limit = cmdutil.loglimit(opts)
5050 limit = cmdutil.loglimit(opts)
5048 count = 0
5051 count = 0
5049
5052
5050 getrenamed = None
5053 getrenamed = None
5051 if opts.get('copies'):
5054 if opts.get('copies'):
5052 endrev = None
5055 endrev = None
5053 if opts.get('rev'):
5056 if opts.get('rev'):
5054 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5057 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5055 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5058 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5056
5059
5057 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5060 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5058 for rev in revs:
5061 for rev in revs:
5059 if count == limit:
5062 if count == limit:
5060 break
5063 break
5061 ctx = repo[rev]
5064 ctx = repo[rev]
5062 copies = None
5065 copies = None
5063 if getrenamed is not None and rev:
5066 if getrenamed is not None and rev:
5064 copies = []
5067 copies = []
5065 for fn in ctx.files():
5068 for fn in ctx.files():
5066 rename = getrenamed(fn, rev)
5069 rename = getrenamed(fn, rev)
5067 if rename:
5070 if rename:
5068 copies.append((fn, rename[0]))
5071 copies.append((fn, rename[0]))
5069 if filematcher:
5072 if filematcher:
5070 revmatchfn = filematcher(ctx.rev())
5073 revmatchfn = filematcher(ctx.rev())
5071 else:
5074 else:
5072 revmatchfn = None
5075 revmatchfn = None
5073 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5076 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5074 if displayer.flush(ctx):
5077 if displayer.flush(ctx):
5075 count += 1
5078 count += 1
5076
5079
5077 displayer.close()
5080 displayer.close()
5078
5081
5079 @command('manifest',
5082 @command('manifest',
5080 [('r', 'rev', '', _('revision to display'), _('REV')),
5083 [('r', 'rev', '', _('revision to display'), _('REV')),
5081 ('', 'all', False, _("list files from all revisions"))]
5084 ('', 'all', False, _("list files from all revisions"))]
5082 + formatteropts,
5085 + formatteropts,
5083 _('[-r REV]'))
5086 _('[-r REV]'))
5084 def manifest(ui, repo, node=None, rev=None, **opts):
5087 def manifest(ui, repo, node=None, rev=None, **opts):
5085 """output the current or given revision of the project manifest
5088 """output the current or given revision of the project manifest
5086
5089
5087 Print a list of version controlled files for the given revision.
5090 Print a list of version controlled files for the given revision.
5088 If no revision is given, the first parent of the working directory
5091 If no revision is given, the first parent of the working directory
5089 is used, or the null revision if no revision is checked out.
5092 is used, or the null revision if no revision is checked out.
5090
5093
5091 With -v, print file permissions, symlink and executable bits.
5094 With -v, print file permissions, symlink and executable bits.
5092 With --debug, print file revision hashes.
5095 With --debug, print file revision hashes.
5093
5096
5094 If option --all is specified, the list of all files from all revisions
5097 If option --all is specified, the list of all files from all revisions
5095 is printed. This includes deleted and renamed files.
5098 is printed. This includes deleted and renamed files.
5096
5099
5097 Returns 0 on success.
5100 Returns 0 on success.
5098 """
5101 """
5099
5102
5100 fm = ui.formatter('manifest', opts)
5103 fm = ui.formatter('manifest', opts)
5101
5104
5102 if opts.get('all'):
5105 if opts.get('all'):
5103 if rev or node:
5106 if rev or node:
5104 raise error.Abort(_("can't specify a revision with --all"))
5107 raise error.Abort(_("can't specify a revision with --all"))
5105
5108
5106 res = []
5109 res = []
5107 prefix = "data/"
5110 prefix = "data/"
5108 suffix = ".i"
5111 suffix = ".i"
5109 plen = len(prefix)
5112 plen = len(prefix)
5110 slen = len(suffix)
5113 slen = len(suffix)
5111 lock = repo.lock()
5114 lock = repo.lock()
5112 try:
5115 try:
5113 for fn, b, size in repo.store.datafiles():
5116 for fn, b, size in repo.store.datafiles():
5114 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5117 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5115 res.append(fn[plen:-slen])
5118 res.append(fn[plen:-slen])
5116 finally:
5119 finally:
5117 lock.release()
5120 lock.release()
5118 for f in res:
5121 for f in res:
5119 fm.startitem()
5122 fm.startitem()
5120 fm.write("path", '%s\n', f)
5123 fm.write("path", '%s\n', f)
5121 fm.end()
5124 fm.end()
5122 return
5125 return
5123
5126
5124 if rev and node:
5127 if rev and node:
5125 raise error.Abort(_("please specify just one revision"))
5128 raise error.Abort(_("please specify just one revision"))
5126
5129
5127 if not node:
5130 if not node:
5128 node = rev
5131 node = rev
5129
5132
5130 char = {'l': '@', 'x': '*', '': ''}
5133 char = {'l': '@', 'x': '*', '': ''}
5131 mode = {'l': '644', 'x': '755', '': '644'}
5134 mode = {'l': '644', 'x': '755', '': '644'}
5132 ctx = scmutil.revsingle(repo, node)
5135 ctx = scmutil.revsingle(repo, node)
5133 mf = ctx.manifest()
5136 mf = ctx.manifest()
5134 for f in ctx:
5137 for f in ctx:
5135 fm.startitem()
5138 fm.startitem()
5136 fl = ctx[f].flags()
5139 fl = ctx[f].flags()
5137 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5140 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5138 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5141 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5139 fm.write('path', '%s\n', f)
5142 fm.write('path', '%s\n', f)
5140 fm.end()
5143 fm.end()
5141
5144
5142 @command('^merge',
5145 @command('^merge',
5143 [('f', 'force', None,
5146 [('f', 'force', None,
5144 _('force a merge including outstanding changes (DEPRECATED)')),
5147 _('force a merge including outstanding changes (DEPRECATED)')),
5145 ('r', 'rev', '', _('revision to merge'), _('REV')),
5148 ('r', 'rev', '', _('revision to merge'), _('REV')),
5146 ('P', 'preview', None,
5149 ('P', 'preview', None,
5147 _('review revisions to merge (no merge is performed)'))
5150 _('review revisions to merge (no merge is performed)'))
5148 ] + mergetoolopts,
5151 ] + mergetoolopts,
5149 _('[-P] [-f] [[-r] REV]'))
5152 _('[-P] [-f] [[-r] REV]'))
5150 def merge(ui, repo, node=None, **opts):
5153 def merge(ui, repo, node=None, **opts):
5151 """merge another revision into working directory
5154 """merge another revision into working directory
5152
5155
5153 The current working directory is updated with all changes made in
5156 The current working directory is updated with all changes made in
5154 the requested revision since the last common predecessor revision.
5157 the requested revision since the last common predecessor revision.
5155
5158
5156 Files that changed between either parent are marked as changed for
5159 Files that changed between either parent are marked as changed for
5157 the next commit and a commit must be performed before any further
5160 the next commit and a commit must be performed before any further
5158 updates to the repository are allowed. The next commit will have
5161 updates to the repository are allowed. The next commit will have
5159 two parents.
5162 two parents.
5160
5163
5161 ``--tool`` can be used to specify the merge tool used for file
5164 ``--tool`` can be used to specify the merge tool used for file
5162 merges. It overrides the HGMERGE environment variable and your
5165 merges. It overrides the HGMERGE environment variable and your
5163 configuration files. See :hg:`help merge-tools` for options.
5166 configuration files. See :hg:`help merge-tools` for options.
5164
5167
5165 If no revision is specified, the working directory's parent is a
5168 If no revision is specified, the working directory's parent is a
5166 head revision, and the current branch contains exactly one other
5169 head revision, and the current branch contains exactly one other
5167 head, the other head is merged with by default. Otherwise, an
5170 head, the other head is merged with by default. Otherwise, an
5168 explicit revision with which to merge with must be provided.
5171 explicit revision with which to merge with must be provided.
5169
5172
5170 See :hg:`help resolve` for information on handling file conflicts.
5173 See :hg:`help resolve` for information on handling file conflicts.
5171
5174
5172 To undo an uncommitted merge, use :hg:`update --clean .` which
5175 To undo an uncommitted merge, use :hg:`update --clean .` which
5173 will check out a clean copy of the original merge parent, losing
5176 will check out a clean copy of the original merge parent, losing
5174 all changes.
5177 all changes.
5175
5178
5176 Returns 0 on success, 1 if there are unresolved files.
5179 Returns 0 on success, 1 if there are unresolved files.
5177 """
5180 """
5178
5181
5179 if opts.get('rev') and node:
5182 if opts.get('rev') and node:
5180 raise error.Abort(_("please specify just one revision"))
5183 raise error.Abort(_("please specify just one revision"))
5181 if not node:
5184 if not node:
5182 node = opts.get('rev')
5185 node = opts.get('rev')
5183
5186
5184 if node:
5187 if node:
5185 node = scmutil.revsingle(repo, node).node()
5188 node = scmutil.revsingle(repo, node).node()
5186
5189
5187 if not node:
5190 if not node:
5188 node = repo[destutil.destmerge(repo)].node()
5191 node = repo[destutil.destmerge(repo)].node()
5189
5192
5190 if opts.get('preview'):
5193 if opts.get('preview'):
5191 # find nodes that are ancestors of p2 but not of p1
5194 # find nodes that are ancestors of p2 but not of p1
5192 p1 = repo.lookup('.')
5195 p1 = repo.lookup('.')
5193 p2 = repo.lookup(node)
5196 p2 = repo.lookup(node)
5194 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5197 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5195
5198
5196 displayer = cmdutil.show_changeset(ui, repo, opts)
5199 displayer = cmdutil.show_changeset(ui, repo, opts)
5197 for node in nodes:
5200 for node in nodes:
5198 displayer.show(repo[node])
5201 displayer.show(repo[node])
5199 displayer.close()
5202 displayer.close()
5200 return 0
5203 return 0
5201
5204
5202 try:
5205 try:
5203 # ui.forcemerge is an internal variable, do not document
5206 # ui.forcemerge is an internal variable, do not document
5204 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5207 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5205 return hg.merge(repo, node, force=opts.get('force'))
5208 return hg.merge(repo, node, force=opts.get('force'))
5206 finally:
5209 finally:
5207 ui.setconfig('ui', 'forcemerge', '', 'merge')
5210 ui.setconfig('ui', 'forcemerge', '', 'merge')
5208
5211
5209 @command('outgoing|out',
5212 @command('outgoing|out',
5210 [('f', 'force', None, _('run even when the destination is unrelated')),
5213 [('f', 'force', None, _('run even when the destination is unrelated')),
5211 ('r', 'rev', [],
5214 ('r', 'rev', [],
5212 _('a changeset intended to be included in the destination'), _('REV')),
5215 _('a changeset intended to be included in the destination'), _('REV')),
5213 ('n', 'newest-first', None, _('show newest record first')),
5216 ('n', 'newest-first', None, _('show newest record first')),
5214 ('B', 'bookmarks', False, _('compare bookmarks')),
5217 ('B', 'bookmarks', False, _('compare bookmarks')),
5215 ('b', 'branch', [], _('a specific branch you would like to push'),
5218 ('b', 'branch', [], _('a specific branch you would like to push'),
5216 _('BRANCH')),
5219 _('BRANCH')),
5217 ] + logopts + remoteopts + subrepoopts,
5220 ] + logopts + remoteopts + subrepoopts,
5218 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5221 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5219 def outgoing(ui, repo, dest=None, **opts):
5222 def outgoing(ui, repo, dest=None, **opts):
5220 """show changesets not found in the destination
5223 """show changesets not found in the destination
5221
5224
5222 Show changesets not found in the specified destination repository
5225 Show changesets not found in the specified destination repository
5223 or the default push location. These are the changesets that would
5226 or the default push location. These are the changesets that would
5224 be pushed if a push was requested.
5227 be pushed if a push was requested.
5225
5228
5226 See pull for details of valid destination formats.
5229 See pull for details of valid destination formats.
5227
5230
5228 .. container:: verbose
5231 .. container:: verbose
5229
5232
5230 With -B/--bookmarks, the result of bookmark comparison between
5233 With -B/--bookmarks, the result of bookmark comparison between
5231 local and remote repositories is displayed. With -v/--verbose,
5234 local and remote repositories is displayed. With -v/--verbose,
5232 status is also displayed for each bookmark like below::
5235 status is also displayed for each bookmark like below::
5233
5236
5234 BM1 01234567890a added
5237 BM1 01234567890a added
5235 BM2 deleted
5238 BM2 deleted
5236 BM3 234567890abc advanced
5239 BM3 234567890abc advanced
5237 BM4 34567890abcd diverged
5240 BM4 34567890abcd diverged
5238 BM5 4567890abcde changed
5241 BM5 4567890abcde changed
5239
5242
5240 The action taken when pushing depends on the
5243 The action taken when pushing depends on the
5241 status of each bookmark:
5244 status of each bookmark:
5242
5245
5243 :``added``: push with ``-B`` will create it
5246 :``added``: push with ``-B`` will create it
5244 :``deleted``: push with ``-B`` will delete it
5247 :``deleted``: push with ``-B`` will delete it
5245 :``advanced``: push will update it
5248 :``advanced``: push will update it
5246 :``diverged``: push with ``-B`` will update it
5249 :``diverged``: push with ``-B`` will update it
5247 :``changed``: push with ``-B`` will update it
5250 :``changed``: push with ``-B`` will update it
5248
5251
5249 From the point of view of pushing behavior, bookmarks
5252 From the point of view of pushing behavior, bookmarks
5250 existing only in the remote repository are treated as
5253 existing only in the remote repository are treated as
5251 ``deleted``, even if it is in fact added remotely.
5254 ``deleted``, even if it is in fact added remotely.
5252
5255
5253 Returns 0 if there are outgoing changes, 1 otherwise.
5256 Returns 0 if there are outgoing changes, 1 otherwise.
5254 """
5257 """
5255 if opts.get('graph'):
5258 if opts.get('graph'):
5256 cmdutil.checkunsupportedgraphflags([], opts)
5259 cmdutil.checkunsupportedgraphflags([], opts)
5257 o, other = hg._outgoing(ui, repo, dest, opts)
5260 o, other = hg._outgoing(ui, repo, dest, opts)
5258 if not o:
5261 if not o:
5259 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5262 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5260 return
5263 return
5261
5264
5262 revdag = cmdutil.graphrevs(repo, o, opts)
5265 revdag = cmdutil.graphrevs(repo, o, opts)
5263 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5266 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5264 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5267 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5265 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5268 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5266 return 0
5269 return 0
5267
5270
5268 if opts.get('bookmarks'):
5271 if opts.get('bookmarks'):
5269 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5272 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5270 dest, branches = hg.parseurl(dest, opts.get('branch'))
5273 dest, branches = hg.parseurl(dest, opts.get('branch'))
5271 other = hg.peer(repo, opts, dest)
5274 other = hg.peer(repo, opts, dest)
5272 if 'bookmarks' not in other.listkeys('namespaces'):
5275 if 'bookmarks' not in other.listkeys('namespaces'):
5273 ui.warn(_("remote doesn't support bookmarks\n"))
5276 ui.warn(_("remote doesn't support bookmarks\n"))
5274 return 0
5277 return 0
5275 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5278 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5276 return bookmarks.outgoing(ui, repo, other)
5279 return bookmarks.outgoing(ui, repo, other)
5277
5280
5278 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5281 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5279 try:
5282 try:
5280 return hg.outgoing(ui, repo, dest, opts)
5283 return hg.outgoing(ui, repo, dest, opts)
5281 finally:
5284 finally:
5282 del repo._subtoppath
5285 del repo._subtoppath
5283
5286
5284 @command('parents',
5287 @command('parents',
5285 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5288 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5286 ] + templateopts,
5289 ] + templateopts,
5287 _('[-r REV] [FILE]'),
5290 _('[-r REV] [FILE]'),
5288 inferrepo=True)
5291 inferrepo=True)
5289 def parents(ui, repo, file_=None, **opts):
5292 def parents(ui, repo, file_=None, **opts):
5290 """show the parents of the working directory or revision (DEPRECATED)
5293 """show the parents of the working directory or revision (DEPRECATED)
5291
5294
5292 Print the working directory's parent revisions. If a revision is
5295 Print the working directory's parent revisions. If a revision is
5293 given via -r/--rev, the parent of that revision will be printed.
5296 given via -r/--rev, the parent of that revision will be printed.
5294 If a file argument is given, the revision in which the file was
5297 If a file argument is given, the revision in which the file was
5295 last changed (before the working directory revision or the
5298 last changed (before the working directory revision or the
5296 argument to --rev if given) is printed.
5299 argument to --rev if given) is printed.
5297
5300
5298 This command is equivalent to::
5301 This command is equivalent to::
5299
5302
5300 hg log -r "parents()" or
5303 hg log -r "parents()" or
5301 hg log -r "parents(REV)" or
5304 hg log -r "parents(REV)" or
5302 hg log -r "max(file(FILE))" or
5305 hg log -r "max(file(FILE))" or
5303 hg log -r "max(::REV and file(FILE))"
5306 hg log -r "max(::REV and file(FILE))"
5304
5307
5305 See :hg:`summary` and :hg:`help revsets` for related information.
5308 See :hg:`summary` and :hg:`help revsets` for related information.
5306
5309
5307 Returns 0 on success.
5310 Returns 0 on success.
5308 """
5311 """
5309
5312
5310 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5313 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5311
5314
5312 if file_:
5315 if file_:
5313 m = scmutil.match(ctx, (file_,), opts)
5316 m = scmutil.match(ctx, (file_,), opts)
5314 if m.anypats() or len(m.files()) != 1:
5317 if m.anypats() or len(m.files()) != 1:
5315 raise error.Abort(_('can only specify an explicit filename'))
5318 raise error.Abort(_('can only specify an explicit filename'))
5316 file_ = m.files()[0]
5319 file_ = m.files()[0]
5317 filenodes = []
5320 filenodes = []
5318 for cp in ctx.parents():
5321 for cp in ctx.parents():
5319 if not cp:
5322 if not cp:
5320 continue
5323 continue
5321 try:
5324 try:
5322 filenodes.append(cp.filenode(file_))
5325 filenodes.append(cp.filenode(file_))
5323 except error.LookupError:
5326 except error.LookupError:
5324 pass
5327 pass
5325 if not filenodes:
5328 if not filenodes:
5326 raise error.Abort(_("'%s' not found in manifest!") % file_)
5329 raise error.Abort(_("'%s' not found in manifest!") % file_)
5327 p = []
5330 p = []
5328 for fn in filenodes:
5331 for fn in filenodes:
5329 fctx = repo.filectx(file_, fileid=fn)
5332 fctx = repo.filectx(file_, fileid=fn)
5330 p.append(fctx.node())
5333 p.append(fctx.node())
5331 else:
5334 else:
5332 p = [cp.node() for cp in ctx.parents()]
5335 p = [cp.node() for cp in ctx.parents()]
5333
5336
5334 displayer = cmdutil.show_changeset(ui, repo, opts)
5337 displayer = cmdutil.show_changeset(ui, repo, opts)
5335 for n in p:
5338 for n in p:
5336 if n != nullid:
5339 if n != nullid:
5337 displayer.show(repo[n])
5340 displayer.show(repo[n])
5338 displayer.close()
5341 displayer.close()
5339
5342
5340 @command('paths', [], _('[NAME]'), optionalrepo=True)
5343 @command('paths', [], _('[NAME]'), optionalrepo=True)
5341 def paths(ui, repo, search=None):
5344 def paths(ui, repo, search=None):
5342 """show aliases for remote repositories
5345 """show aliases for remote repositories
5343
5346
5344 Show definition of symbolic path name NAME. If no name is given,
5347 Show definition of symbolic path name NAME. If no name is given,
5345 show definition of all available names.
5348 show definition of all available names.
5346
5349
5347 Option -q/--quiet suppresses all output when searching for NAME
5350 Option -q/--quiet suppresses all output when searching for NAME
5348 and shows only the path names when listing all definitions.
5351 and shows only the path names when listing all definitions.
5349
5352
5350 Path names are defined in the [paths] section of your
5353 Path names are defined in the [paths] section of your
5351 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5354 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5352 repository, ``.hg/hgrc`` is used, too.
5355 repository, ``.hg/hgrc`` is used, too.
5353
5356
5354 The path names ``default`` and ``default-push`` have a special
5357 The path names ``default`` and ``default-push`` have a special
5355 meaning. When performing a push or pull operation, they are used
5358 meaning. When performing a push or pull operation, they are used
5356 as fallbacks if no location is specified on the command-line.
5359 as fallbacks if no location is specified on the command-line.
5357 When ``default-push`` is set, it will be used for push and
5360 When ``default-push`` is set, it will be used for push and
5358 ``default`` will be used for pull; otherwise ``default`` is used
5361 ``default`` will be used for pull; otherwise ``default`` is used
5359 as the fallback for both. When cloning a repository, the clone
5362 as the fallback for both. When cloning a repository, the clone
5360 source is written as ``default`` in ``.hg/hgrc``. Note that
5363 source is written as ``default`` in ``.hg/hgrc``.
5361 ``default`` and ``default-push`` apply to all inbound (e.g.
5364
5362 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
5365 .. note::
5363 :hg:`bundle`) operations.
5366
5367 ``default`` and ``default-push`` apply to all inbound (e.g.
5368 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5369 and :hg:`bundle`) operations.
5364
5370
5365 See :hg:`help urls` for more information.
5371 See :hg:`help urls` for more information.
5366
5372
5367 Returns 0 on success.
5373 Returns 0 on success.
5368 """
5374 """
5369 if search:
5375 if search:
5370 for name, path in sorted(ui.paths.iteritems()):
5376 for name, path in sorted(ui.paths.iteritems()):
5371 if name == search:
5377 if name == search:
5372 ui.status("%s\n" % util.hidepassword(path.rawloc))
5378 ui.status("%s\n" % util.hidepassword(path.rawloc))
5373 return
5379 return
5374 if not ui.quiet:
5380 if not ui.quiet:
5375 ui.warn(_("not found!\n"))
5381 ui.warn(_("not found!\n"))
5376 return 1
5382 return 1
5377 else:
5383 else:
5378 for name, path in sorted(ui.paths.iteritems()):
5384 for name, path in sorted(ui.paths.iteritems()):
5379 if ui.quiet:
5385 if ui.quiet:
5380 ui.write("%s\n" % name)
5386 ui.write("%s\n" % name)
5381 else:
5387 else:
5382 ui.write("%s = %s\n" % (name,
5388 ui.write("%s = %s\n" % (name,
5383 util.hidepassword(path.rawloc)))
5389 util.hidepassword(path.rawloc)))
5384 for subopt, value in sorted(path.suboptions.items()):
5390 for subopt, value in sorted(path.suboptions.items()):
5385 ui.write('%s:%s = %s\n' % (name, subopt, value))
5391 ui.write('%s:%s = %s\n' % (name, subopt, value))
5386
5392
5387 @command('phase',
5393 @command('phase',
5388 [('p', 'public', False, _('set changeset phase to public')),
5394 [('p', 'public', False, _('set changeset phase to public')),
5389 ('d', 'draft', False, _('set changeset phase to draft')),
5395 ('d', 'draft', False, _('set changeset phase to draft')),
5390 ('s', 'secret', False, _('set changeset phase to secret')),
5396 ('s', 'secret', False, _('set changeset phase to secret')),
5391 ('f', 'force', False, _('allow to move boundary backward')),
5397 ('f', 'force', False, _('allow to move boundary backward')),
5392 ('r', 'rev', [], _('target revision'), _('REV')),
5398 ('r', 'rev', [], _('target revision'), _('REV')),
5393 ],
5399 ],
5394 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5400 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5395 def phase(ui, repo, *revs, **opts):
5401 def phase(ui, repo, *revs, **opts):
5396 """set or show the current phase name
5402 """set or show the current phase name
5397
5403
5398 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).
5399
5405
5400 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
5401 phase value of the specified revisions.
5407 phase value of the specified revisions.
5402
5408
5403 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
5404 lower phase to an higher phase. Phases are ordered as follows::
5410 lower phase to an higher phase. Phases are ordered as follows::
5405
5411
5406 public < draft < secret
5412 public < draft < secret
5407
5413
5408 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.
5409
5415
5410 (For more information about the phases concept, see :hg:`help phases`.)
5416 (For more information about the phases concept, see :hg:`help phases`.)
5411 """
5417 """
5412 # search for a unique phase argument
5418 # search for a unique phase argument
5413 targetphase = None
5419 targetphase = None
5414 for idx, name in enumerate(phases.phasenames):
5420 for idx, name in enumerate(phases.phasenames):
5415 if opts[name]:
5421 if opts[name]:
5416 if targetphase is not None:
5422 if targetphase is not None:
5417 raise error.Abort(_('only one phase can be specified'))
5423 raise error.Abort(_('only one phase can be specified'))
5418 targetphase = idx
5424 targetphase = idx
5419
5425
5420 # look for specified revision
5426 # look for specified revision
5421 revs = list(revs)
5427 revs = list(revs)
5422 revs.extend(opts['rev'])
5428 revs.extend(opts['rev'])
5423 if not revs:
5429 if not revs:
5424 # display both parents as the second parent phase can influence
5430 # display both parents as the second parent phase can influence
5425 # the phase of a merge commit
5431 # the phase of a merge commit
5426 revs = [c.rev() for c in repo[None].parents()]
5432 revs = [c.rev() for c in repo[None].parents()]
5427
5433
5428 revs = scmutil.revrange(repo, revs)
5434 revs = scmutil.revrange(repo, revs)
5429
5435
5430 lock = None
5436 lock = None
5431 ret = 0
5437 ret = 0
5432 if targetphase is None:
5438 if targetphase is None:
5433 # display
5439 # display
5434 for r in revs:
5440 for r in revs:
5435 ctx = repo[r]
5441 ctx = repo[r]
5436 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5442 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5437 else:
5443 else:
5438 tr = None
5444 tr = None
5439 lock = repo.lock()
5445 lock = repo.lock()
5440 try:
5446 try:
5441 tr = repo.transaction("phase")
5447 tr = repo.transaction("phase")
5442 # set phase
5448 # set phase
5443 if not revs:
5449 if not revs:
5444 raise error.Abort(_('empty revision set'))
5450 raise error.Abort(_('empty revision set'))
5445 nodes = [repo[r].node() for r in revs]
5451 nodes = [repo[r].node() for r in revs]
5446 # moving revision from public to draft may hide them
5452 # moving revision from public to draft may hide them
5447 # We have to check result on an unfiltered repository
5453 # We have to check result on an unfiltered repository
5448 unfi = repo.unfiltered()
5454 unfi = repo.unfiltered()
5449 getphase = unfi._phasecache.phase
5455 getphase = unfi._phasecache.phase
5450 olddata = [getphase(unfi, r) for r in unfi]
5456 olddata = [getphase(unfi, r) for r in unfi]
5451 phases.advanceboundary(repo, tr, targetphase, nodes)
5457 phases.advanceboundary(repo, tr, targetphase, nodes)
5452 if opts['force']:
5458 if opts['force']:
5453 phases.retractboundary(repo, tr, targetphase, nodes)
5459 phases.retractboundary(repo, tr, targetphase, nodes)
5454 tr.close()
5460 tr.close()
5455 finally:
5461 finally:
5456 if tr is not None:
5462 if tr is not None:
5457 tr.release()
5463 tr.release()
5458 lock.release()
5464 lock.release()
5459 getphase = unfi._phasecache.phase
5465 getphase = unfi._phasecache.phase
5460 newdata = [getphase(unfi, r) for r in unfi]
5466 newdata = [getphase(unfi, r) for r in unfi]
5461 changes = sum(newdata[r] != olddata[r] for r in unfi)
5467 changes = sum(newdata[r] != olddata[r] for r in unfi)
5462 cl = unfi.changelog
5468 cl = unfi.changelog
5463 rejected = [n for n in nodes
5469 rejected = [n for n in nodes
5464 if newdata[cl.rev(n)] < targetphase]
5470 if newdata[cl.rev(n)] < targetphase]
5465 if rejected:
5471 if rejected:
5466 ui.warn(_('cannot move %i changesets to a higher '
5472 ui.warn(_('cannot move %i changesets to a higher '
5467 'phase, use --force\n') % len(rejected))
5473 'phase, use --force\n') % len(rejected))
5468 ret = 1
5474 ret = 1
5469 if changes:
5475 if changes:
5470 msg = _('phase changed for %i changesets\n') % changes
5476 msg = _('phase changed for %i changesets\n') % changes
5471 if ret:
5477 if ret:
5472 ui.status(msg)
5478 ui.status(msg)
5473 else:
5479 else:
5474 ui.note(msg)
5480 ui.note(msg)
5475 else:
5481 else:
5476 ui.warn(_('no phases changed\n'))
5482 ui.warn(_('no phases changed\n'))
5477 return ret
5483 return ret
5478
5484
5479 def postincoming(ui, repo, modheads, optupdate, checkout):
5485 def postincoming(ui, repo, modheads, optupdate, checkout):
5480 if modheads == 0:
5486 if modheads == 0:
5481 return
5487 return
5482 if optupdate:
5488 if optupdate:
5483 try:
5489 try:
5484 brev = checkout
5490 brev = checkout
5485 movemarkfrom = None
5491 movemarkfrom = None
5486 if not checkout:
5492 if not checkout:
5487 updata = destutil.destupdate(repo)
5493 updata = destutil.destupdate(repo)
5488 checkout, movemarkfrom, brev = updata
5494 checkout, movemarkfrom, brev = updata
5489 ret = hg.update(repo, checkout)
5495 ret = hg.update(repo, checkout)
5490 except error.UpdateAbort as inst:
5496 except error.UpdateAbort as inst:
5491 msg = _("not updating: %s") % str(inst)
5497 msg = _("not updating: %s") % str(inst)
5492 hint = inst.hint
5498 hint = inst.hint
5493 raise error.UpdateAbort(msg, hint=hint)
5499 raise error.UpdateAbort(msg, hint=hint)
5494 if not ret and not checkout:
5500 if not ret and not checkout:
5495 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5501 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5496 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5502 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5497 return ret
5503 return ret
5498 if modheads > 1:
5504 if modheads > 1:
5499 currentbranchheads = len(repo.branchheads())
5505 currentbranchheads = len(repo.branchheads())
5500 if currentbranchheads == modheads:
5506 if currentbranchheads == modheads:
5501 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"))
5502 elif currentbranchheads > 1:
5508 elif currentbranchheads > 1:
5503 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5509 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5504 "merge)\n"))
5510 "merge)\n"))
5505 else:
5511 else:
5506 ui.status(_("(run 'hg heads' to see heads)\n"))
5512 ui.status(_("(run 'hg heads' to see heads)\n"))
5507 else:
5513 else:
5508 ui.status(_("(run 'hg update' to get a working copy)\n"))
5514 ui.status(_("(run 'hg update' to get a working copy)\n"))
5509
5515
5510 @command('^pull',
5516 @command('^pull',
5511 [('u', 'update', None,
5517 [('u', 'update', None,
5512 _('update to new branch head if changesets were pulled')),
5518 _('update to new branch head if changesets were pulled')),
5513 ('f', 'force', None, _('run even when remote repository is unrelated')),
5519 ('f', 'force', None, _('run even when remote repository is unrelated')),
5514 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5520 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5515 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5521 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5516 ('b', 'branch', [], _('a specific branch you would like to pull'),
5522 ('b', 'branch', [], _('a specific branch you would like to pull'),
5517 _('BRANCH')),
5523 _('BRANCH')),
5518 ] + remoteopts,
5524 ] + remoteopts,
5519 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5525 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5520 def pull(ui, repo, source="default", **opts):
5526 def pull(ui, repo, source="default", **opts):
5521 """pull changes from the specified source
5527 """pull changes from the specified source
5522
5528
5523 Pull changes from a remote repository to a local one.
5529 Pull changes from a remote repository to a local one.
5524
5530
5525 This finds all changes from the repository at the specified path
5531 This finds all changes from the repository at the specified path
5526 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
5527 -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
5528 project in the working directory.
5534 project in the working directory.
5529
5535
5530 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
5531 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
5532 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
5533 -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`.
5534
5540
5535 If SOURCE is omitted, the 'default' path will be used.
5541 If SOURCE is omitted, the 'default' path will be used.
5536 See :hg:`help urls` for more information.
5542 See :hg:`help urls` for more information.
5537
5543
5538 Returns 0 on success, 1 if an update had unresolved files.
5544 Returns 0 on success, 1 if an update had unresolved files.
5539 """
5545 """
5540 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5546 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5541 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5547 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5542 other = hg.peer(repo, opts, source)
5548 other = hg.peer(repo, opts, source)
5543 try:
5549 try:
5544 revs, checkout = hg.addbranchrevs(repo, other, branches,
5550 revs, checkout = hg.addbranchrevs(repo, other, branches,
5545 opts.get('rev'))
5551 opts.get('rev'))
5546
5552
5547
5553
5548 pullopargs = {}
5554 pullopargs = {}
5549 if opts.get('bookmark'):
5555 if opts.get('bookmark'):
5550 if not revs:
5556 if not revs:
5551 revs = []
5557 revs = []
5552 # 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
5553 # update the bookmark name. This can result in the revision pulled
5559 # update the bookmark name. This can result in the revision pulled
5554 # 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
5555 # condition on the server. (See issue 4689 for details)
5561 # condition on the server. (See issue 4689 for details)
5556 remotebookmarks = other.listkeys('bookmarks')
5562 remotebookmarks = other.listkeys('bookmarks')
5557 pullopargs['remotebookmarks'] = remotebookmarks
5563 pullopargs['remotebookmarks'] = remotebookmarks
5558 for b in opts['bookmark']:
5564 for b in opts['bookmark']:
5559 if b not in remotebookmarks:
5565 if b not in remotebookmarks:
5560 raise error.Abort(_('remote bookmark %s not found!') % b)
5566 raise error.Abort(_('remote bookmark %s not found!') % b)
5561 revs.append(remotebookmarks[b])
5567 revs.append(remotebookmarks[b])
5562
5568
5563 if revs:
5569 if revs:
5564 try:
5570 try:
5565 # When 'rev' is a bookmark name, we cannot guarantee that it
5571 # When 'rev' is a bookmark name, we cannot guarantee that it
5566 # will be updated with that name because of a race condition
5572 # will be updated with that name because of a race condition
5567 # server side. (See issue 4689 for details)
5573 # server side. (See issue 4689 for details)
5568 oldrevs = revs
5574 oldrevs = revs
5569 revs = [] # actually, nodes
5575 revs = [] # actually, nodes
5570 for r in oldrevs:
5576 for r in oldrevs:
5571 node = other.lookup(r)
5577 node = other.lookup(r)
5572 revs.append(node)
5578 revs.append(node)
5573 if r == checkout:
5579 if r == checkout:
5574 checkout = node
5580 checkout = node
5575 except error.CapabilityError:
5581 except error.CapabilityError:
5576 err = _("other repository doesn't support revision lookup, "
5582 err = _("other repository doesn't support revision lookup, "
5577 "so a rev cannot be specified.")
5583 "so a rev cannot be specified.")
5578 raise error.Abort(err)
5584 raise error.Abort(err)
5579
5585
5580 pullopargs.update(opts.get('opargs', {}))
5586 pullopargs.update(opts.get('opargs', {}))
5581 modheads = exchange.pull(repo, other, heads=revs,
5587 modheads = exchange.pull(repo, other, heads=revs,
5582 force=opts.get('force'),
5588 force=opts.get('force'),
5583 bookmarks=opts.get('bookmark', ()),
5589 bookmarks=opts.get('bookmark', ()),
5584 opargs=pullopargs).cgresult
5590 opargs=pullopargs).cgresult
5585 if checkout:
5591 if checkout:
5586 checkout = str(repo.changelog.rev(checkout))
5592 checkout = str(repo.changelog.rev(checkout))
5587 repo._subtoppath = source
5593 repo._subtoppath = source
5588 try:
5594 try:
5589 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5595 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5590
5596
5591 finally:
5597 finally:
5592 del repo._subtoppath
5598 del repo._subtoppath
5593
5599
5594 finally:
5600 finally:
5595 other.close()
5601 other.close()
5596 return ret
5602 return ret
5597
5603
5598 @command('^push',
5604 @command('^push',
5599 [('f', 'force', None, _('force push')),
5605 [('f', 'force', None, _('force push')),
5600 ('r', 'rev', [],
5606 ('r', 'rev', [],
5601 _('a changeset intended to be included in the destination'),
5607 _('a changeset intended to be included in the destination'),
5602 _('REV')),
5608 _('REV')),
5603 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5609 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5604 ('b', 'branch', [],
5610 ('b', 'branch', [],
5605 _('a specific branch you would like to push'), _('BRANCH')),
5611 _('a specific branch you would like to push'), _('BRANCH')),
5606 ('', 'new-branch', False, _('allow pushing a new branch')),
5612 ('', 'new-branch', False, _('allow pushing a new branch')),
5607 ] + remoteopts,
5613 ] + remoteopts,
5608 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5614 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5609 def push(ui, repo, dest=None, **opts):
5615 def push(ui, repo, dest=None, **opts):
5610 """push changes to the specified destination
5616 """push changes to the specified destination
5611
5617
5612 Push changesets from the local repository to the specified
5618 Push changesets from the local repository to the specified
5613 destination.
5619 destination.
5614
5620
5615 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
5616 in the destination repository from the current one.
5622 in the destination repository from the current one.
5617
5623
5618 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
5619 destination, since multiple heads would make it unclear which head
5625 destination, since multiple heads would make it unclear which head
5620 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
5621 before pushing.
5627 before pushing.
5622
5628
5623 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
5624 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
5625 only create a new branch without forcing other changes.
5631 only create a new branch without forcing other changes.
5626
5632
5627 .. note::
5633 .. note::
5628
5634
5629 Extra care should be taken with the -f/--force option,
5635 Extra care should be taken with the -f/--force option,
5630 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
5631 almost always cause confusion for collaborators.
5637 almost always cause confusion for collaborators.
5632
5638
5633 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
5634 will be pushed to the remote repository.
5640 will be pushed to the remote repository.
5635
5641
5636 If -B/--bookmark is used, the specified bookmarked revision, its
5642 If -B/--bookmark is used, the specified bookmarked revision, its
5637 ancestors, and the bookmark will be pushed to the remote
5643 ancestors, and the bookmark will be pushed to the remote
5638 repository.
5644 repository.
5639
5645
5640 Please see :hg:`help urls` for important details about ``ssh://``
5646 Please see :hg:`help urls` for important details about ``ssh://``
5641 URLs. If DESTINATION is omitted, a default path will be used.
5647 URLs. If DESTINATION is omitted, a default path will be used.
5642
5648
5643 Returns 0 if push was successful, 1 if nothing to push.
5649 Returns 0 if push was successful, 1 if nothing to push.
5644 """
5650 """
5645
5651
5646 if opts.get('bookmark'):
5652 if opts.get('bookmark'):
5647 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5653 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5648 for b in opts['bookmark']:
5654 for b in opts['bookmark']:
5649 # translate -B options to -r so changesets get pushed
5655 # translate -B options to -r so changesets get pushed
5650 if b in repo._bookmarks:
5656 if b in repo._bookmarks:
5651 opts.setdefault('rev', []).append(b)
5657 opts.setdefault('rev', []).append(b)
5652 else:
5658 else:
5653 # 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
5654 # this lets simultaneous -r, -b options continue working
5660 # this lets simultaneous -r, -b options continue working
5655 opts.setdefault('rev', []).append("null")
5661 opts.setdefault('rev', []).append("null")
5656
5662
5657 path = ui.paths.getpath(dest, default='default')
5663 path = ui.paths.getpath(dest, default='default')
5658 if not path:
5664 if not path:
5659 raise error.Abort(_('default repository not configured!'),
5665 raise error.Abort(_('default repository not configured!'),
5660 hint=_('see the "path" section in "hg help config"'))
5666 hint=_('see the "path" section in "hg help config"'))
5661 dest = path.pushloc or path.loc
5667 dest = path.pushloc or path.loc
5662 branches = (path.branch, opts.get('branch') or [])
5668 branches = (path.branch, opts.get('branch') or [])
5663 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5669 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5664 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5670 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5665 other = hg.peer(repo, opts, dest)
5671 other = hg.peer(repo, opts, dest)
5666
5672
5667 if revs:
5673 if revs:
5668 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5674 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5669 if not revs:
5675 if not revs:
5670 raise error.Abort(_("specified revisions evaluate to an empty set"),
5676 raise error.Abort(_("specified revisions evaluate to an empty set"),
5671 hint=_("use different revision arguments"))
5677 hint=_("use different revision arguments"))
5672
5678
5673 repo._subtoppath = dest
5679 repo._subtoppath = dest
5674 try:
5680 try:
5675 # push subrepos depth-first for coherent ordering
5681 # push subrepos depth-first for coherent ordering
5676 c = repo['']
5682 c = repo['']
5677 subs = c.substate # only repos that are committed
5683 subs = c.substate # only repos that are committed
5678 for s in sorted(subs):
5684 for s in sorted(subs):
5679 result = c.sub(s).push(opts)
5685 result = c.sub(s).push(opts)
5680 if result == 0:
5686 if result == 0:
5681 return not result
5687 return not result
5682 finally:
5688 finally:
5683 del repo._subtoppath
5689 del repo._subtoppath
5684 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5690 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5685 newbranch=opts.get('new_branch'),
5691 newbranch=opts.get('new_branch'),
5686 bookmarks=opts.get('bookmark', ()),
5692 bookmarks=opts.get('bookmark', ()),
5687 opargs=opts.get('opargs'))
5693 opargs=opts.get('opargs'))
5688
5694
5689 result = not pushop.cgresult
5695 result = not pushop.cgresult
5690
5696
5691 if pushop.bkresult is not None:
5697 if pushop.bkresult is not None:
5692 if pushop.bkresult == 2:
5698 if pushop.bkresult == 2:
5693 result = 2
5699 result = 2
5694 elif not result and pushop.bkresult:
5700 elif not result and pushop.bkresult:
5695 result = 2
5701 result = 2
5696
5702
5697 return result
5703 return result
5698
5704
5699 @command('recover', [])
5705 @command('recover', [])
5700 def recover(ui, repo):
5706 def recover(ui, repo):
5701 """roll back an interrupted transaction
5707 """roll back an interrupted transaction
5702
5708
5703 Recover from an interrupted commit or pull.
5709 Recover from an interrupted commit or pull.
5704
5710
5705 This command tries to fix the repository status after an
5711 This command tries to fix the repository status after an
5706 interrupted operation. It should only be necessary when Mercurial
5712 interrupted operation. It should only be necessary when Mercurial
5707 suggests it.
5713 suggests it.
5708
5714
5709 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.
5710 """
5716 """
5711 if repo.recover():
5717 if repo.recover():
5712 return hg.verify(repo)
5718 return hg.verify(repo)
5713 return 1
5719 return 1
5714
5720
5715 @command('^remove|rm',
5721 @command('^remove|rm',
5716 [('A', 'after', None, _('record delete for missing files')),
5722 [('A', 'after', None, _('record delete for missing files')),
5717 ('f', 'force', None,
5723 ('f', 'force', None,
5718 _('remove (and delete) file even if added or modified')),
5724 _('remove (and delete) file even if added or modified')),
5719 ] + subrepoopts + walkopts,
5725 ] + subrepoopts + walkopts,
5720 _('[OPTION]... FILE...'),
5726 _('[OPTION]... FILE...'),
5721 inferrepo=True)
5727 inferrepo=True)
5722 def remove(ui, repo, *pats, **opts):
5728 def remove(ui, repo, *pats, **opts):
5723 """remove the specified files on the next commit
5729 """remove the specified files on the next commit
5724
5730
5725 Schedule the indicated files for removal from the current branch.
5731 Schedule the indicated files for removal from the current branch.
5726
5732
5727 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.
5728 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
5729 files, see :hg:`forget`.
5735 files, see :hg:`forget`.
5730
5736
5731 .. container:: verbose
5737 .. container:: verbose
5732
5738
5733 -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
5734 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
5735 can be used to remove files from the next revision without
5741 can be used to remove files from the next revision without
5736 deleting them from the working directory.
5742 deleting them from the working directory.
5737
5743
5738 The following table details the behavior of remove for different
5744 The following table details the behavior of remove for different
5739 file states (columns) and option combinations (rows). The file
5745 file states (columns) and option combinations (rows). The file
5740 states are Added [A], Clean [C], Modified [M] and Missing [!]
5746 states are Added [A], Clean [C], Modified [M] and Missing [!]
5741 (as reported by :hg:`status`). The actions are Warn, Remove
5747 (as reported by :hg:`status`). The actions are Warn, Remove
5742 (from branch) and Delete (from disk):
5748 (from branch) and Delete (from disk):
5743
5749
5744 ========= == == == ==
5750 ========= == == == ==
5745 opt/state A C M !
5751 opt/state A C M !
5746 ========= == == == ==
5752 ========= == == == ==
5747 none W RD W R
5753 none W RD W R
5748 -f R RD RD R
5754 -f R RD RD R
5749 -A W W W R
5755 -A W W W R
5750 -Af R R R R
5756 -Af R R R R
5751 ========= == == == ==
5757 ========= == == == ==
5752
5758
5753 .. note::
5759 .. note::
5754
5760
5755 :hg:`remove` never deletes files in Added [A] state from the
5761 :hg:`remove` never deletes files in Added [A] state from the
5756 working directory, not even if ``--force`` is specified.
5762 working directory, not even if ``--force`` is specified.
5757
5763
5758 Returns 0 on success, 1 if any warnings encountered.
5764 Returns 0 on success, 1 if any warnings encountered.
5759 """
5765 """
5760
5766
5761 after, force = opts.get('after'), opts.get('force')
5767 after, force = opts.get('after'), opts.get('force')
5762 if not pats and not after:
5768 if not pats and not after:
5763 raise error.Abort(_('no files specified'))
5769 raise error.Abort(_('no files specified'))
5764
5770
5765 m = scmutil.match(repo[None], pats, opts)
5771 m = scmutil.match(repo[None], pats, opts)
5766 subrepos = opts.get('subrepos')
5772 subrepos = opts.get('subrepos')
5767 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5773 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5768
5774
5769 @command('rename|move|mv',
5775 @command('rename|move|mv',
5770 [('A', 'after', None, _('record a rename that has already occurred')),
5776 [('A', 'after', None, _('record a rename that has already occurred')),
5771 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5777 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5772 ] + walkopts + dryrunopts,
5778 ] + walkopts + dryrunopts,
5773 _('[OPTION]... SOURCE... DEST'))
5779 _('[OPTION]... SOURCE... DEST'))
5774 def rename(ui, repo, *pats, **opts):
5780 def rename(ui, repo, *pats, **opts):
5775 """rename files; equivalent of copy + remove
5781 """rename files; equivalent of copy + remove
5776
5782
5777 Mark dest as copies of sources; mark sources for deletion. If dest
5783 Mark dest as copies of sources; mark sources for deletion. If dest
5778 is a directory, copies are put in that directory. If dest is a
5784 is a directory, copies are put in that directory. If dest is a
5779 file, there can only be one source.
5785 file, there can only be one source.
5780
5786
5781 By default, this command copies the contents of files as they
5787 By default, this command copies the contents of files as they
5782 exist in the working directory. If invoked with -A/--after, the
5788 exist in the working directory. If invoked with -A/--after, the
5783 operation is recorded, but no copying is performed.
5789 operation is recorded, but no copying is performed.
5784
5790
5785 This command takes effect at the next commit. To undo a rename
5791 This command takes effect at the next commit. To undo a rename
5786 before that, see :hg:`revert`.
5792 before that, see :hg:`revert`.
5787
5793
5788 Returns 0 on success, 1 if errors are encountered.
5794 Returns 0 on success, 1 if errors are encountered.
5789 """
5795 """
5790 wlock = repo.wlock(False)
5796 wlock = repo.wlock(False)
5791 try:
5797 try:
5792 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5798 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5793 finally:
5799 finally:
5794 wlock.release()
5800 wlock.release()
5795
5801
5796 @command('resolve',
5802 @command('resolve',
5797 [('a', 'all', None, _('select all unresolved files')),
5803 [('a', 'all', None, _('select all unresolved files')),
5798 ('l', 'list', None, _('list state of files needing merge')),
5804 ('l', 'list', None, _('list state of files needing merge')),
5799 ('m', 'mark', None, _('mark files as resolved')),
5805 ('m', 'mark', None, _('mark files as resolved')),
5800 ('u', 'unmark', None, _('mark files as unresolved')),
5806 ('u', 'unmark', None, _('mark files as unresolved')),
5801 ('n', 'no-status', None, _('hide status prefix'))]
5807 ('n', 'no-status', None, _('hide status prefix'))]
5802 + mergetoolopts + walkopts + formatteropts,
5808 + mergetoolopts + walkopts + formatteropts,
5803 _('[OPTION]... [FILE]...'),
5809 _('[OPTION]... [FILE]...'),
5804 inferrepo=True)
5810 inferrepo=True)
5805 def resolve(ui, repo, *pats, **opts):
5811 def resolve(ui, repo, *pats, **opts):
5806 """redo merges or set/view the merge status of files
5812 """redo merges or set/view the merge status of files
5807
5813
5808 Merges with unresolved conflicts are often the result of
5814 Merges with unresolved conflicts are often the result of
5809 non-interactive merging using the ``internal:merge`` configuration
5815 non-interactive merging using the ``internal:merge`` configuration
5810 setting, or a command-line merge tool like ``diff3``. The resolve
5816 setting, or a command-line merge tool like ``diff3``. The resolve
5811 command is used to manage the files involved in a merge, after
5817 command is used to manage the files involved in a merge, after
5812 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5818 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5813 working directory must have two parents). See :hg:`help
5819 working directory must have two parents). See :hg:`help
5814 merge-tools` for information on configuring merge tools.
5820 merge-tools` for information on configuring merge tools.
5815
5821
5816 The resolve command can be used in the following ways:
5822 The resolve command can be used in the following ways:
5817
5823
5818 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5824 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5819 files, discarding any previous merge attempts. Re-merging is not
5825 files, discarding any previous merge attempts. Re-merging is not
5820 performed for files already marked as resolved. Use ``--all/-a``
5826 performed for files already marked as resolved. Use ``--all/-a``
5821 to select all unresolved files. ``--tool`` can be used to specify
5827 to select all unresolved files. ``--tool`` can be used to specify
5822 the merge tool used for the given files. It overrides the HGMERGE
5828 the merge tool used for the given files. It overrides the HGMERGE
5823 environment variable and your configuration files. Previous file
5829 environment variable and your configuration files. Previous file
5824 contents are saved with a ``.orig`` suffix.
5830 contents are saved with a ``.orig`` suffix.
5825
5831
5826 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5832 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5827 (e.g. after having manually fixed-up the files). The default is
5833 (e.g. after having manually fixed-up the files). The default is
5828 to mark all unresolved files.
5834 to mark all unresolved files.
5829
5835
5830 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5836 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5831 default is to mark all resolved files.
5837 default is to mark all resolved files.
5832
5838
5833 - :hg:`resolve -l`: list files which had or still have conflicts.
5839 - :hg:`resolve -l`: list files which had or still have conflicts.
5834 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5840 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5835
5841
5836 Note that Mercurial will not let you commit files with unresolved
5842 .. note::
5837 merge conflicts. You must use :hg:`resolve -m ...` before you can
5843
5838 commit after a conflicting merge.
5844 Mercurial will not let you commit files with unresolved merge
5845 conflicts. You must use :hg:`resolve -m ...` before you can
5846 commit after a conflicting merge.
5839
5847
5840 Returns 0 on success, 1 if any files fail a resolve attempt.
5848 Returns 0 on success, 1 if any files fail a resolve attempt.
5841 """
5849 """
5842
5850
5843 all, mark, unmark, show, nostatus = \
5851 all, mark, unmark, show, nostatus = \
5844 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5852 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5845
5853
5846 if (show and (mark or unmark)) or (mark and unmark):
5854 if (show and (mark or unmark)) or (mark and unmark):
5847 raise error.Abort(_("too many options specified"))
5855 raise error.Abort(_("too many options specified"))
5848 if pats and all:
5856 if pats and all:
5849 raise error.Abort(_("can't specify --all and patterns"))
5857 raise error.Abort(_("can't specify --all and patterns"))
5850 if not (all or pats or show or mark or unmark):
5858 if not (all or pats or show or mark or unmark):
5851 raise error.Abort(_('no files or directories specified'),
5859 raise error.Abort(_('no files or directories specified'),
5852 hint=('use --all to re-merge all unresolved files'))
5860 hint=('use --all to re-merge all unresolved files'))
5853
5861
5854 if show:
5862 if show:
5855 fm = ui.formatter('resolve', opts)
5863 fm = ui.formatter('resolve', opts)
5856 ms = mergemod.mergestate.read(repo)
5864 ms = mergemod.mergestate.read(repo)
5857 m = scmutil.match(repo[None], pats, opts)
5865 m = scmutil.match(repo[None], pats, opts)
5858 for f in ms:
5866 for f in ms:
5859 if not m(f):
5867 if not m(f):
5860 continue
5868 continue
5861 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5869 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5862 'd': 'driverresolved'}[ms[f]]
5870 'd': 'driverresolved'}[ms[f]]
5863 fm.startitem()
5871 fm.startitem()
5864 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5872 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5865 fm.write('path', '%s\n', f, label=l)
5873 fm.write('path', '%s\n', f, label=l)
5866 fm.end()
5874 fm.end()
5867 return 0
5875 return 0
5868
5876
5869 wlock = repo.wlock()
5877 wlock = repo.wlock()
5870 try:
5878 try:
5871 ms = mergemod.mergestate.read(repo)
5879 ms = mergemod.mergestate.read(repo)
5872
5880
5873 if not (ms.active() or repo.dirstate.p2() != nullid):
5881 if not (ms.active() or repo.dirstate.p2() != nullid):
5874 raise error.Abort(
5882 raise error.Abort(
5875 _('resolve command not applicable when not merging'))
5883 _('resolve command not applicable when not merging'))
5876
5884
5877 wctx = repo[None]
5885 wctx = repo[None]
5878
5886
5879 if ms.mergedriver and ms.mdstate() == 'u':
5887 if ms.mergedriver and ms.mdstate() == 'u':
5880 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5888 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5881 ms.commit()
5889 ms.commit()
5882 # allow mark and unmark to go through
5890 # allow mark and unmark to go through
5883 if not mark and not unmark and not proceed:
5891 if not mark and not unmark and not proceed:
5884 return 1
5892 return 1
5885
5893
5886 m = scmutil.match(wctx, pats, opts)
5894 m = scmutil.match(wctx, pats, opts)
5887 ret = 0
5895 ret = 0
5888 didwork = False
5896 didwork = False
5889 runconclude = False
5897 runconclude = False
5890
5898
5891 tocomplete = []
5899 tocomplete = []
5892 for f in ms:
5900 for f in ms:
5893 if not m(f):
5901 if not m(f):
5894 continue
5902 continue
5895
5903
5896 didwork = True
5904 didwork = True
5897
5905
5898 # don't let driver-resolved files be marked, and run the conclude
5906 # don't let driver-resolved files be marked, and run the conclude
5899 # step if asked to resolve
5907 # step if asked to resolve
5900 if ms[f] == "d":
5908 if ms[f] == "d":
5901 exact = m.exact(f)
5909 exact = m.exact(f)
5902 if mark:
5910 if mark:
5903 if exact:
5911 if exact:
5904 ui.warn(_('not marking %s as it is driver-resolved\n')
5912 ui.warn(_('not marking %s as it is driver-resolved\n')
5905 % f)
5913 % f)
5906 elif unmark:
5914 elif unmark:
5907 if exact:
5915 if exact:
5908 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5916 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5909 % f)
5917 % f)
5910 else:
5918 else:
5911 runconclude = True
5919 runconclude = True
5912 continue
5920 continue
5913
5921
5914 if mark:
5922 if mark:
5915 ms.mark(f, "r")
5923 ms.mark(f, "r")
5916 elif unmark:
5924 elif unmark:
5917 ms.mark(f, "u")
5925 ms.mark(f, "u")
5918 else:
5926 else:
5919 # backup pre-resolve (merge uses .orig for its own purposes)
5927 # backup pre-resolve (merge uses .orig for its own purposes)
5920 a = repo.wjoin(f)
5928 a = repo.wjoin(f)
5921 try:
5929 try:
5922 util.copyfile(a, a + ".resolve")
5930 util.copyfile(a, a + ".resolve")
5923 except (IOError, OSError) as inst:
5931 except (IOError, OSError) as inst:
5924 if inst.errno != errno.ENOENT:
5932 if inst.errno != errno.ENOENT:
5925 raise
5933 raise
5926
5934
5927 try:
5935 try:
5928 # preresolve file
5936 # preresolve file
5929 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5937 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5930 'resolve')
5938 'resolve')
5931 complete, r = ms.preresolve(f, wctx)
5939 complete, r = ms.preresolve(f, wctx)
5932 if not complete:
5940 if not complete:
5933 tocomplete.append(f)
5941 tocomplete.append(f)
5934 elif r:
5942 elif r:
5935 ret = 1
5943 ret = 1
5936 finally:
5944 finally:
5937 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5945 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5938 ms.commit()
5946 ms.commit()
5939
5947
5940 # replace filemerge's .orig file with our resolve file, but only
5948 # replace filemerge's .orig file with our resolve file, but only
5941 # for merges that are complete
5949 # for merges that are complete
5942 if complete:
5950 if complete:
5943 try:
5951 try:
5944 util.rename(a + ".resolve",
5952 util.rename(a + ".resolve",
5945 cmdutil.origpath(ui, repo, a))
5953 cmdutil.origpath(ui, repo, a))
5946 except OSError as inst:
5954 except OSError as inst:
5947 if inst.errno != errno.ENOENT:
5955 if inst.errno != errno.ENOENT:
5948 raise
5956 raise
5949
5957
5950 for f in tocomplete:
5958 for f in tocomplete:
5951 try:
5959 try:
5952 # resolve file
5960 # resolve file
5953 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5961 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5954 'resolve')
5962 'resolve')
5955 r = ms.resolve(f, wctx)
5963 r = ms.resolve(f, wctx)
5956 if r:
5964 if r:
5957 ret = 1
5965 ret = 1
5958 finally:
5966 finally:
5959 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5967 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5960 ms.commit()
5968 ms.commit()
5961
5969
5962 # replace filemerge's .orig file with our resolve file
5970 # replace filemerge's .orig file with our resolve file
5963 a = repo.wjoin(f)
5971 a = repo.wjoin(f)
5964 try:
5972 try:
5965 util.rename(a + ".resolve", cmdutil.origpath(ui, repo, a))
5973 util.rename(a + ".resolve", cmdutil.origpath(ui, repo, a))
5966 except OSError as inst:
5974 except OSError as inst:
5967 if inst.errno != errno.ENOENT:
5975 if inst.errno != errno.ENOENT:
5968 raise
5976 raise
5969
5977
5970 ms.commit()
5978 ms.commit()
5971 ms.recordactions()
5979 ms.recordactions()
5972
5980
5973 if not didwork and pats:
5981 if not didwork and pats:
5974 ui.warn(_("arguments do not match paths that need resolving\n"))
5982 ui.warn(_("arguments do not match paths that need resolving\n"))
5975 elif ms.mergedriver and ms.mdstate() != 's':
5983 elif ms.mergedriver and ms.mdstate() != 's':
5976 # run conclude step when either a driver-resolved file is requested
5984 # run conclude step when either a driver-resolved file is requested
5977 # or there are no driver-resolved files
5985 # or there are no driver-resolved files
5978 # we can't use 'ret' to determine whether any files are unresolved
5986 # we can't use 'ret' to determine whether any files are unresolved
5979 # because we might not have tried to resolve some
5987 # because we might not have tried to resolve some
5980 if ((runconclude or not list(ms.driverresolved()))
5988 if ((runconclude or not list(ms.driverresolved()))
5981 and not list(ms.unresolved())):
5989 and not list(ms.unresolved())):
5982 proceed = mergemod.driverconclude(repo, ms, wctx)
5990 proceed = mergemod.driverconclude(repo, ms, wctx)
5983 ms.commit()
5991 ms.commit()
5984 if not proceed:
5992 if not proceed:
5985 return 1
5993 return 1
5986
5994
5987 finally:
5995 finally:
5988 wlock.release()
5996 wlock.release()
5989
5997
5990 # Nudge users into finishing an unfinished operation
5998 # Nudge users into finishing an unfinished operation
5991 unresolvedf = list(ms.unresolved())
5999 unresolvedf = list(ms.unresolved())
5992 driverresolvedf = list(ms.driverresolved())
6000 driverresolvedf = list(ms.driverresolved())
5993 if not unresolvedf and not driverresolvedf:
6001 if not unresolvedf and not driverresolvedf:
5994 ui.status(_('(no more unresolved files)\n'))
6002 ui.status(_('(no more unresolved files)\n'))
5995 elif not unresolvedf:
6003 elif not unresolvedf:
5996 ui.status(_('(no more unresolved files -- '
6004 ui.status(_('(no more unresolved files -- '
5997 'run "hg resolve --all" to conclude)\n'))
6005 'run "hg resolve --all" to conclude)\n'))
5998
6006
5999 return ret
6007 return ret
6000
6008
6001 @command('revert',
6009 @command('revert',
6002 [('a', 'all', None, _('revert all changes when no arguments given')),
6010 [('a', 'all', None, _('revert all changes when no arguments given')),
6003 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6011 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6004 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6012 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6005 ('C', 'no-backup', None, _('do not save backup copies of files')),
6013 ('C', 'no-backup', None, _('do not save backup copies of files')),
6006 ('i', 'interactive', None,
6014 ('i', 'interactive', None,
6007 _('interactively select the changes (EXPERIMENTAL)')),
6015 _('interactively select the changes (EXPERIMENTAL)')),
6008 ] + walkopts + dryrunopts,
6016 ] + walkopts + dryrunopts,
6009 _('[OPTION]... [-r REV] [NAME]...'))
6017 _('[OPTION]... [-r REV] [NAME]...'))
6010 def revert(ui, repo, *pats, **opts):
6018 def revert(ui, repo, *pats, **opts):
6011 """restore files to their checkout state
6019 """restore files to their checkout state
6012
6020
6013 .. note::
6021 .. note::
6014
6022
6015 To check out earlier revisions, you should use :hg:`update REV`.
6023 To check out earlier revisions, you should use :hg:`update REV`.
6016 To cancel an uncommitted merge (and lose your changes),
6024 To cancel an uncommitted merge (and lose your changes),
6017 use :hg:`update --clean .`.
6025 use :hg:`update --clean .`.
6018
6026
6019 With no revision specified, revert the specified files or directories
6027 With no revision specified, revert the specified files or directories
6020 to the contents they had in the parent of the working directory.
6028 to the contents they had in the parent of the working directory.
6021 This restores the contents of files to an unmodified
6029 This restores the contents of files to an unmodified
6022 state and unschedules adds, removes, copies, and renames. If the
6030 state and unschedules adds, removes, copies, and renames. If the
6023 working directory has two parents, you must explicitly specify a
6031 working directory has two parents, you must explicitly specify a
6024 revision.
6032 revision.
6025
6033
6026 Using the -r/--rev or -d/--date options, revert the given files or
6034 Using the -r/--rev or -d/--date options, revert the given files or
6027 directories to their states as of a specific revision. Because
6035 directories to their states as of a specific revision. Because
6028 revert does not change the working directory parents, this will
6036 revert does not change the working directory parents, this will
6029 cause these files to appear modified. This can be helpful to "back
6037 cause these files to appear modified. This can be helpful to "back
6030 out" some or all of an earlier change. See :hg:`backout` for a
6038 out" some or all of an earlier change. See :hg:`backout` for a
6031 related method.
6039 related method.
6032
6040
6033 Modified files are saved with a .orig suffix before reverting.
6041 Modified files are saved with a .orig suffix before reverting.
6034 To disable these backups, use --no-backup.
6042 To disable these backups, use --no-backup.
6035
6043
6036 See :hg:`help dates` for a list of formats valid for -d/--date.
6044 See :hg:`help dates` for a list of formats valid for -d/--date.
6037
6045
6038 See :hg:`help backout` for a way to reverse the effect of an
6046 See :hg:`help backout` for a way to reverse the effect of an
6039 earlier changeset.
6047 earlier changeset.
6040
6048
6041 Returns 0 on success.
6049 Returns 0 on success.
6042 """
6050 """
6043
6051
6044 if opts.get("date"):
6052 if opts.get("date"):
6045 if opts.get("rev"):
6053 if opts.get("rev"):
6046 raise error.Abort(_("you can't specify a revision and a date"))
6054 raise error.Abort(_("you can't specify a revision and a date"))
6047 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6055 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6048
6056
6049 parent, p2 = repo.dirstate.parents()
6057 parent, p2 = repo.dirstate.parents()
6050 if not opts.get('rev') and p2 != nullid:
6058 if not opts.get('rev') and p2 != nullid:
6051 # revert after merge is a trap for new users (issue2915)
6059 # revert after merge is a trap for new users (issue2915)
6052 raise error.Abort(_('uncommitted merge with no revision specified'),
6060 raise error.Abort(_('uncommitted merge with no revision specified'),
6053 hint=_('use "hg update" or see "hg help revert"'))
6061 hint=_('use "hg update" or see "hg help revert"'))
6054
6062
6055 ctx = scmutil.revsingle(repo, opts.get('rev'))
6063 ctx = scmutil.revsingle(repo, opts.get('rev'))
6056
6064
6057 if (not (pats or opts.get('include') or opts.get('exclude') or
6065 if (not (pats or opts.get('include') or opts.get('exclude') or
6058 opts.get('all') or opts.get('interactive'))):
6066 opts.get('all') or opts.get('interactive'))):
6059 msg = _("no files or directories specified")
6067 msg = _("no files or directories specified")
6060 if p2 != nullid:
6068 if p2 != nullid:
6061 hint = _("uncommitted merge, use --all to discard all changes,"
6069 hint = _("uncommitted merge, use --all to discard all changes,"
6062 " or 'hg update -C .' to abort the merge")
6070 " or 'hg update -C .' to abort the merge")
6063 raise error.Abort(msg, hint=hint)
6071 raise error.Abort(msg, hint=hint)
6064 dirty = any(repo.status())
6072 dirty = any(repo.status())
6065 node = ctx.node()
6073 node = ctx.node()
6066 if node != parent:
6074 if node != parent:
6067 if dirty:
6075 if dirty:
6068 hint = _("uncommitted changes, use --all to discard all"
6076 hint = _("uncommitted changes, use --all to discard all"
6069 " changes, or 'hg update %s' to update") % ctx.rev()
6077 " changes, or 'hg update %s' to update") % ctx.rev()
6070 else:
6078 else:
6071 hint = _("use --all to revert all files,"
6079 hint = _("use --all to revert all files,"
6072 " or 'hg update %s' to update") % ctx.rev()
6080 " or 'hg update %s' to update") % ctx.rev()
6073 elif dirty:
6081 elif dirty:
6074 hint = _("uncommitted changes, use --all to discard all changes")
6082 hint = _("uncommitted changes, use --all to discard all changes")
6075 else:
6083 else:
6076 hint = _("use --all to revert all files")
6084 hint = _("use --all to revert all files")
6077 raise error.Abort(msg, hint=hint)
6085 raise error.Abort(msg, hint=hint)
6078
6086
6079 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6087 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6080
6088
6081 @command('rollback', dryrunopts +
6089 @command('rollback', dryrunopts +
6082 [('f', 'force', False, _('ignore safety measures'))])
6090 [('f', 'force', False, _('ignore safety measures'))])
6083 def rollback(ui, repo, **opts):
6091 def rollback(ui, repo, **opts):
6084 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6092 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6085
6093
6086 Please use :hg:`commit --amend` instead of rollback to correct
6094 Please use :hg:`commit --amend` instead of rollback to correct
6087 mistakes in the last commit.
6095 mistakes in the last commit.
6088
6096
6089 This command should be used with care. There is only one level of
6097 This command should be used with care. There is only one level of
6090 rollback, and there is no way to undo a rollback. It will also
6098 rollback, and there is no way to undo a rollback. It will also
6091 restore the dirstate at the time of the last transaction, losing
6099 restore the dirstate at the time of the last transaction, losing
6092 any dirstate changes since that time. This command does not alter
6100 any dirstate changes since that time. This command does not alter
6093 the working directory.
6101 the working directory.
6094
6102
6095 Transactions are used to encapsulate the effects of all commands
6103 Transactions are used to encapsulate the effects of all commands
6096 that create new changesets or propagate existing changesets into a
6104 that create new changesets or propagate existing changesets into a
6097 repository.
6105 repository.
6098
6106
6099 .. container:: verbose
6107 .. container:: verbose
6100
6108
6101 For example, the following commands are transactional, and their
6109 For example, the following commands are transactional, and their
6102 effects can be rolled back:
6110 effects can be rolled back:
6103
6111
6104 - commit
6112 - commit
6105 - import
6113 - import
6106 - pull
6114 - pull
6107 - push (with this repository as the destination)
6115 - push (with this repository as the destination)
6108 - unbundle
6116 - unbundle
6109
6117
6110 To avoid permanent data loss, rollback will refuse to rollback a
6118 To avoid permanent data loss, rollback will refuse to rollback a
6111 commit transaction if it isn't checked out. Use --force to
6119 commit transaction if it isn't checked out. Use --force to
6112 override this protection.
6120 override this protection.
6113
6121
6114 This command is not intended for use on public repositories. Once
6122 This command is not intended for use on public repositories. Once
6115 changes are visible for pull by other users, rolling a transaction
6123 changes are visible for pull by other users, rolling a transaction
6116 back locally is ineffective (someone else may already have pulled
6124 back locally is ineffective (someone else may already have pulled
6117 the changes). Furthermore, a race is possible with readers of the
6125 the changes). Furthermore, a race is possible with readers of the
6118 repository; for example an in-progress pull from the repository
6126 repository; for example an in-progress pull from the repository
6119 may fail if a rollback is performed.
6127 may fail if a rollback is performed.
6120
6128
6121 Returns 0 on success, 1 if no rollback data is available.
6129 Returns 0 on success, 1 if no rollback data is available.
6122 """
6130 """
6123 return repo.rollback(dryrun=opts.get('dry_run'),
6131 return repo.rollback(dryrun=opts.get('dry_run'),
6124 force=opts.get('force'))
6132 force=opts.get('force'))
6125
6133
6126 @command('root', [])
6134 @command('root', [])
6127 def root(ui, repo):
6135 def root(ui, repo):
6128 """print the root (top) of the current working directory
6136 """print the root (top) of the current working directory
6129
6137
6130 Print the root directory of the current repository.
6138 Print the root directory of the current repository.
6131
6139
6132 Returns 0 on success.
6140 Returns 0 on success.
6133 """
6141 """
6134 ui.write(repo.root + "\n")
6142 ui.write(repo.root + "\n")
6135
6143
6136 @command('^serve',
6144 @command('^serve',
6137 [('A', 'accesslog', '', _('name of access log file to write to'),
6145 [('A', 'accesslog', '', _('name of access log file to write to'),
6138 _('FILE')),
6146 _('FILE')),
6139 ('d', 'daemon', None, _('run server in background')),
6147 ('d', 'daemon', None, _('run server in background')),
6140 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6148 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6141 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6149 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6142 # use string type, then we can check if something was passed
6150 # use string type, then we can check if something was passed
6143 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6151 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6144 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6152 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6145 _('ADDR')),
6153 _('ADDR')),
6146 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6154 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6147 _('PREFIX')),
6155 _('PREFIX')),
6148 ('n', 'name', '',
6156 ('n', 'name', '',
6149 _('name to show in web pages (default: working directory)'), _('NAME')),
6157 _('name to show in web pages (default: working directory)'), _('NAME')),
6150 ('', 'web-conf', '',
6158 ('', 'web-conf', '',
6151 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6159 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6152 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6160 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6153 _('FILE')),
6161 _('FILE')),
6154 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6162 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6155 ('', 'stdio', None, _('for remote clients')),
6163 ('', 'stdio', None, _('for remote clients')),
6156 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6164 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6157 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6165 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6158 ('', 'style', '', _('template style to use'), _('STYLE')),
6166 ('', 'style', '', _('template style to use'), _('STYLE')),
6159 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6167 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6160 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6168 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6161 _('[OPTION]...'),
6169 _('[OPTION]...'),
6162 optionalrepo=True)
6170 optionalrepo=True)
6163 def serve(ui, repo, **opts):
6171 def serve(ui, repo, **opts):
6164 """start stand-alone webserver
6172 """start stand-alone webserver
6165
6173
6166 Start a local HTTP repository browser and pull server. You can use
6174 Start a local HTTP repository browser and pull server. You can use
6167 this for ad-hoc sharing and browsing of repositories. It is
6175 this for ad-hoc sharing and browsing of repositories. It is
6168 recommended to use a real web server to serve a repository for
6176 recommended to use a real web server to serve a repository for
6169 longer periods of time.
6177 longer periods of time.
6170
6178
6171 Please note that the server does not implement access control.
6179 Please note that the server does not implement access control.
6172 This means that, by default, anybody can read from the server and
6180 This means that, by default, anybody can read from the server and
6173 nobody can write to it by default. Set the ``web.allow_push``
6181 nobody can write to it by default. Set the ``web.allow_push``
6174 option to ``*`` to allow everybody to push to the server. You
6182 option to ``*`` to allow everybody to push to the server. You
6175 should use a real web server if you need to authenticate users.
6183 should use a real web server if you need to authenticate users.
6176
6184
6177 By default, the server logs accesses to stdout and errors to
6185 By default, the server logs accesses to stdout and errors to
6178 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6186 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6179 files.
6187 files.
6180
6188
6181 To have the server choose a free port number to listen on, specify
6189 To have the server choose a free port number to listen on, specify
6182 a port number of 0; in this case, the server will print the port
6190 a port number of 0; in this case, the server will print the port
6183 number it uses.
6191 number it uses.
6184
6192
6185 Returns 0 on success.
6193 Returns 0 on success.
6186 """
6194 """
6187
6195
6188 if opts["stdio"] and opts["cmdserver"]:
6196 if opts["stdio"] and opts["cmdserver"]:
6189 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6197 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6190
6198
6191 if opts["stdio"]:
6199 if opts["stdio"]:
6192 if repo is None:
6200 if repo is None:
6193 raise error.RepoError(_("there is no Mercurial repository here"
6201 raise error.RepoError(_("there is no Mercurial repository here"
6194 " (.hg not found)"))
6202 " (.hg not found)"))
6195 s = sshserver.sshserver(ui, repo)
6203 s = sshserver.sshserver(ui, repo)
6196 s.serve_forever()
6204 s.serve_forever()
6197
6205
6198 if opts["cmdserver"]:
6206 if opts["cmdserver"]:
6199 service = commandserver.createservice(ui, repo, opts)
6207 service = commandserver.createservice(ui, repo, opts)
6200 else:
6208 else:
6201 service = hgweb.createservice(ui, repo, opts)
6209 service = hgweb.createservice(ui, repo, opts)
6202 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6210 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6203
6211
6204 @command('^status|st',
6212 @command('^status|st',
6205 [('A', 'all', None, _('show status of all files')),
6213 [('A', 'all', None, _('show status of all files')),
6206 ('m', 'modified', None, _('show only modified files')),
6214 ('m', 'modified', None, _('show only modified files')),
6207 ('a', 'added', None, _('show only added files')),
6215 ('a', 'added', None, _('show only added files')),
6208 ('r', 'removed', None, _('show only removed files')),
6216 ('r', 'removed', None, _('show only removed files')),
6209 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6217 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6210 ('c', 'clean', None, _('show only files without changes')),
6218 ('c', 'clean', None, _('show only files without changes')),
6211 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6219 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6212 ('i', 'ignored', None, _('show only ignored files')),
6220 ('i', 'ignored', None, _('show only ignored files')),
6213 ('n', 'no-status', None, _('hide status prefix')),
6221 ('n', 'no-status', None, _('hide status prefix')),
6214 ('C', 'copies', None, _('show source of copied files')),
6222 ('C', 'copies', None, _('show source of copied files')),
6215 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6223 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6216 ('', 'rev', [], _('show difference from revision'), _('REV')),
6224 ('', 'rev', [], _('show difference from revision'), _('REV')),
6217 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6225 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6218 ] + walkopts + subrepoopts + formatteropts,
6226 ] + walkopts + subrepoopts + formatteropts,
6219 _('[OPTION]... [FILE]...'),
6227 _('[OPTION]... [FILE]...'),
6220 inferrepo=True)
6228 inferrepo=True)
6221 def status(ui, repo, *pats, **opts):
6229 def status(ui, repo, *pats, **opts):
6222 """show changed files in the working directory
6230 """show changed files in the working directory
6223
6231
6224 Show status of files in the repository. If names are given, only
6232 Show status of files in the repository. If names are given, only
6225 files that match are shown. Files that are clean or ignored or
6233 files that match are shown. Files that are clean or ignored or
6226 the source of a copy/move operation, are not listed unless
6234 the source of a copy/move operation, are not listed unless
6227 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6235 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6228 Unless options described with "show only ..." are given, the
6236 Unless options described with "show only ..." are given, the
6229 options -mardu are used.
6237 options -mardu are used.
6230
6238
6231 Option -q/--quiet hides untracked (unknown and ignored) files
6239 Option -q/--quiet hides untracked (unknown and ignored) files
6232 unless explicitly requested with -u/--unknown or -i/--ignored.
6240 unless explicitly requested with -u/--unknown or -i/--ignored.
6233
6241
6234 .. note::
6242 .. note::
6235
6243
6236 :hg:`status` may appear to disagree with diff if permissions have
6244 :hg:`status` may appear to disagree with diff if permissions have
6237 changed or a merge has occurred. The standard diff format does
6245 changed or a merge has occurred. The standard diff format does
6238 not report permission changes and diff only reports changes
6246 not report permission changes and diff only reports changes
6239 relative to one merge parent.
6247 relative to one merge parent.
6240
6248
6241 If one revision is given, it is used as the base revision.
6249 If one revision is given, it is used as the base revision.
6242 If two revisions are given, the differences between them are
6250 If two revisions are given, the differences between them are
6243 shown. The --change option can also be used as a shortcut to list
6251 shown. The --change option can also be used as a shortcut to list
6244 the changed files of a revision from its first parent.
6252 the changed files of a revision from its first parent.
6245
6253
6246 The codes used to show the status of files are::
6254 The codes used to show the status of files are::
6247
6255
6248 M = modified
6256 M = modified
6249 A = added
6257 A = added
6250 R = removed
6258 R = removed
6251 C = clean
6259 C = clean
6252 ! = missing (deleted by non-hg command, but still tracked)
6260 ! = missing (deleted by non-hg command, but still tracked)
6253 ? = not tracked
6261 ? = not tracked
6254 I = ignored
6262 I = ignored
6255 = origin of the previous file (with --copies)
6263 = origin of the previous file (with --copies)
6256
6264
6257 .. container:: verbose
6265 .. container:: verbose
6258
6266
6259 Examples:
6267 Examples:
6260
6268
6261 - show changes in the working directory relative to a
6269 - show changes in the working directory relative to a
6262 changeset::
6270 changeset::
6263
6271
6264 hg status --rev 9353
6272 hg status --rev 9353
6265
6273
6266 - show changes in the working directory relative to the
6274 - show changes in the working directory relative to the
6267 current directory (see :hg:`help patterns` for more information)::
6275 current directory (see :hg:`help patterns` for more information)::
6268
6276
6269 hg status re:
6277 hg status re:
6270
6278
6271 - show all changes including copies in an existing changeset::
6279 - show all changes including copies in an existing changeset::
6272
6280
6273 hg status --copies --change 9353
6281 hg status --copies --change 9353
6274
6282
6275 - get a NUL separated list of added files, suitable for xargs::
6283 - get a NUL separated list of added files, suitable for xargs::
6276
6284
6277 hg status -an0
6285 hg status -an0
6278
6286
6279 Returns 0 on success.
6287 Returns 0 on success.
6280 """
6288 """
6281
6289
6282 revs = opts.get('rev')
6290 revs = opts.get('rev')
6283 change = opts.get('change')
6291 change = opts.get('change')
6284
6292
6285 if revs and change:
6293 if revs and change:
6286 msg = _('cannot specify --rev and --change at the same time')
6294 msg = _('cannot specify --rev and --change at the same time')
6287 raise error.Abort(msg)
6295 raise error.Abort(msg)
6288 elif change:
6296 elif change:
6289 node2 = scmutil.revsingle(repo, change, None).node()
6297 node2 = scmutil.revsingle(repo, change, None).node()
6290 node1 = repo[node2].p1().node()
6298 node1 = repo[node2].p1().node()
6291 else:
6299 else:
6292 node1, node2 = scmutil.revpair(repo, revs)
6300 node1, node2 = scmutil.revpair(repo, revs)
6293
6301
6294 if pats:
6302 if pats:
6295 cwd = repo.getcwd()
6303 cwd = repo.getcwd()
6296 else:
6304 else:
6297 cwd = ''
6305 cwd = ''
6298
6306
6299 if opts.get('print0'):
6307 if opts.get('print0'):
6300 end = '\0'
6308 end = '\0'
6301 else:
6309 else:
6302 end = '\n'
6310 end = '\n'
6303 copy = {}
6311 copy = {}
6304 states = 'modified added removed deleted unknown ignored clean'.split()
6312 states = 'modified added removed deleted unknown ignored clean'.split()
6305 show = [k for k in states if opts.get(k)]
6313 show = [k for k in states if opts.get(k)]
6306 if opts.get('all'):
6314 if opts.get('all'):
6307 show += ui.quiet and (states[:4] + ['clean']) or states
6315 show += ui.quiet and (states[:4] + ['clean']) or states
6308 if not show:
6316 if not show:
6309 if ui.quiet:
6317 if ui.quiet:
6310 show = states[:4]
6318 show = states[:4]
6311 else:
6319 else:
6312 show = states[:5]
6320 show = states[:5]
6313
6321
6314 m = scmutil.match(repo[node2], pats, opts)
6322 m = scmutil.match(repo[node2], pats, opts)
6315 stat = repo.status(node1, node2, m,
6323 stat = repo.status(node1, node2, m,
6316 'ignored' in show, 'clean' in show, 'unknown' in show,
6324 'ignored' in show, 'clean' in show, 'unknown' in show,
6317 opts.get('subrepos'))
6325 opts.get('subrepos'))
6318 changestates = zip(states, 'MAR!?IC', stat)
6326 changestates = zip(states, 'MAR!?IC', stat)
6319
6327
6320 if (opts.get('all') or opts.get('copies')
6328 if (opts.get('all') or opts.get('copies')
6321 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6329 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6322 copy = copies.pathcopies(repo[node1], repo[node2], m)
6330 copy = copies.pathcopies(repo[node1], repo[node2], m)
6323
6331
6324 fm = ui.formatter('status', opts)
6332 fm = ui.formatter('status', opts)
6325 fmt = '%s' + end
6333 fmt = '%s' + end
6326 showchar = not opts.get('no_status')
6334 showchar = not opts.get('no_status')
6327
6335
6328 for state, char, files in changestates:
6336 for state, char, files in changestates:
6329 if state in show:
6337 if state in show:
6330 label = 'status.' + state
6338 label = 'status.' + state
6331 for f in files:
6339 for f in files:
6332 fm.startitem()
6340 fm.startitem()
6333 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6341 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6334 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6342 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6335 if f in copy:
6343 if f in copy:
6336 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6344 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6337 label='status.copied')
6345 label='status.copied')
6338 fm.end()
6346 fm.end()
6339
6347
6340 @command('^summary|sum',
6348 @command('^summary|sum',
6341 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6349 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6342 def summary(ui, repo, **opts):
6350 def summary(ui, repo, **opts):
6343 """summarize working directory state
6351 """summarize working directory state
6344
6352
6345 This generates a brief summary of the working directory state,
6353 This generates a brief summary of the working directory state,
6346 including parents, branch, commit status, phase and available updates.
6354 including parents, branch, commit status, phase and available updates.
6347
6355
6348 With the --remote option, this will check the default paths for
6356 With the --remote option, this will check the default paths for
6349 incoming and outgoing changes. This can be time-consuming.
6357 incoming and outgoing changes. This can be time-consuming.
6350
6358
6351 Returns 0 on success.
6359 Returns 0 on success.
6352 """
6360 """
6353
6361
6354 ctx = repo[None]
6362 ctx = repo[None]
6355 parents = ctx.parents()
6363 parents = ctx.parents()
6356 pnode = parents[0].node()
6364 pnode = parents[0].node()
6357 marks = []
6365 marks = []
6358
6366
6359 for p in parents:
6367 for p in parents:
6360 # label with log.changeset (instead of log.parent) since this
6368 # label with log.changeset (instead of log.parent) since this
6361 # shows a working directory parent *changeset*:
6369 # shows a working directory parent *changeset*:
6362 # i18n: column positioning for "hg summary"
6370 # i18n: column positioning for "hg summary"
6363 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6371 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6364 label='log.changeset changeset.%s' % p.phasestr())
6372 label='log.changeset changeset.%s' % p.phasestr())
6365 ui.write(' '.join(p.tags()), label='log.tag')
6373 ui.write(' '.join(p.tags()), label='log.tag')
6366 if p.bookmarks():
6374 if p.bookmarks():
6367 marks.extend(p.bookmarks())
6375 marks.extend(p.bookmarks())
6368 if p.rev() == -1:
6376 if p.rev() == -1:
6369 if not len(repo):
6377 if not len(repo):
6370 ui.write(_(' (empty repository)'))
6378 ui.write(_(' (empty repository)'))
6371 else:
6379 else:
6372 ui.write(_(' (no revision checked out)'))
6380 ui.write(_(' (no revision checked out)'))
6373 ui.write('\n')
6381 ui.write('\n')
6374 if p.description():
6382 if p.description():
6375 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6383 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6376 label='log.summary')
6384 label='log.summary')
6377
6385
6378 branch = ctx.branch()
6386 branch = ctx.branch()
6379 bheads = repo.branchheads(branch)
6387 bheads = repo.branchheads(branch)
6380 # i18n: column positioning for "hg summary"
6388 # i18n: column positioning for "hg summary"
6381 m = _('branch: %s\n') % branch
6389 m = _('branch: %s\n') % branch
6382 if branch != 'default':
6390 if branch != 'default':
6383 ui.write(m, label='log.branch')
6391 ui.write(m, label='log.branch')
6384 else:
6392 else:
6385 ui.status(m, label='log.branch')
6393 ui.status(m, label='log.branch')
6386
6394
6387 if marks:
6395 if marks:
6388 active = repo._activebookmark
6396 active = repo._activebookmark
6389 # i18n: column positioning for "hg summary"
6397 # i18n: column positioning for "hg summary"
6390 ui.write(_('bookmarks:'), label='log.bookmark')
6398 ui.write(_('bookmarks:'), label='log.bookmark')
6391 if active is not None:
6399 if active is not None:
6392 if active in marks:
6400 if active in marks:
6393 ui.write(' *' + active, label=activebookmarklabel)
6401 ui.write(' *' + active, label=activebookmarklabel)
6394 marks.remove(active)
6402 marks.remove(active)
6395 else:
6403 else:
6396 ui.write(' [%s]' % active, label=activebookmarklabel)
6404 ui.write(' [%s]' % active, label=activebookmarklabel)
6397 for m in marks:
6405 for m in marks:
6398 ui.write(' ' + m, label='log.bookmark')
6406 ui.write(' ' + m, label='log.bookmark')
6399 ui.write('\n', label='log.bookmark')
6407 ui.write('\n', label='log.bookmark')
6400
6408
6401 status = repo.status(unknown=True)
6409 status = repo.status(unknown=True)
6402
6410
6403 c = repo.dirstate.copies()
6411 c = repo.dirstate.copies()
6404 copied, renamed = [], []
6412 copied, renamed = [], []
6405 for d, s in c.iteritems():
6413 for d, s in c.iteritems():
6406 if s in status.removed:
6414 if s in status.removed:
6407 status.removed.remove(s)
6415 status.removed.remove(s)
6408 renamed.append(d)
6416 renamed.append(d)
6409 else:
6417 else:
6410 copied.append(d)
6418 copied.append(d)
6411 if d in status.added:
6419 if d in status.added:
6412 status.added.remove(d)
6420 status.added.remove(d)
6413
6421
6414 try:
6422 try:
6415 ms = mergemod.mergestate.read(repo)
6423 ms = mergemod.mergestate.read(repo)
6416 except error.UnsupportedMergeRecords as e:
6424 except error.UnsupportedMergeRecords as e:
6417 s = ' '.join(e.recordtypes)
6425 s = ' '.join(e.recordtypes)
6418 ui.warn(
6426 ui.warn(
6419 _('warning: merge state has unsupported record types: %s\n') % s)
6427 _('warning: merge state has unsupported record types: %s\n') % s)
6420 unresolved = 0
6428 unresolved = 0
6421 else:
6429 else:
6422 unresolved = [f for f in ms if ms[f] == 'u']
6430 unresolved = [f for f in ms if ms[f] == 'u']
6423
6431
6424 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6432 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6425
6433
6426 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6434 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6427 (ui.label(_('%d added'), 'status.added'), status.added),
6435 (ui.label(_('%d added'), 'status.added'), status.added),
6428 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6436 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6429 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6437 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6430 (ui.label(_('%d copied'), 'status.copied'), copied),
6438 (ui.label(_('%d copied'), 'status.copied'), copied),
6431 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6439 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6432 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6440 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6433 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6441 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6434 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6442 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6435 t = []
6443 t = []
6436 for l, s in labels:
6444 for l, s in labels:
6437 if s:
6445 if s:
6438 t.append(l % len(s))
6446 t.append(l % len(s))
6439
6447
6440 t = ', '.join(t)
6448 t = ', '.join(t)
6441 cleanworkdir = False
6449 cleanworkdir = False
6442
6450
6443 if repo.vfs.exists('graftstate'):
6451 if repo.vfs.exists('graftstate'):
6444 t += _(' (graft in progress)')
6452 t += _(' (graft in progress)')
6445 if repo.vfs.exists('updatestate'):
6453 if repo.vfs.exists('updatestate'):
6446 t += _(' (interrupted update)')
6454 t += _(' (interrupted update)')
6447 elif len(parents) > 1:
6455 elif len(parents) > 1:
6448 t += _(' (merge)')
6456 t += _(' (merge)')
6449 elif branch != parents[0].branch():
6457 elif branch != parents[0].branch():
6450 t += _(' (new branch)')
6458 t += _(' (new branch)')
6451 elif (parents[0].closesbranch() and
6459 elif (parents[0].closesbranch() and
6452 pnode in repo.branchheads(branch, closed=True)):
6460 pnode in repo.branchheads(branch, closed=True)):
6453 t += _(' (head closed)')
6461 t += _(' (head closed)')
6454 elif not (status.modified or status.added or status.removed or renamed or
6462 elif not (status.modified or status.added or status.removed or renamed or
6455 copied or subs):
6463 copied or subs):
6456 t += _(' (clean)')
6464 t += _(' (clean)')
6457 cleanworkdir = True
6465 cleanworkdir = True
6458 elif pnode not in bheads:
6466 elif pnode not in bheads:
6459 t += _(' (new branch head)')
6467 t += _(' (new branch head)')
6460
6468
6461 if parents:
6469 if parents:
6462 pendingphase = max(p.phase() for p in parents)
6470 pendingphase = max(p.phase() for p in parents)
6463 else:
6471 else:
6464 pendingphase = phases.public
6472 pendingphase = phases.public
6465
6473
6466 if pendingphase > phases.newcommitphase(ui):
6474 if pendingphase > phases.newcommitphase(ui):
6467 t += ' (%s)' % phases.phasenames[pendingphase]
6475 t += ' (%s)' % phases.phasenames[pendingphase]
6468
6476
6469 if cleanworkdir:
6477 if cleanworkdir:
6470 # i18n: column positioning for "hg summary"
6478 # i18n: column positioning for "hg summary"
6471 ui.status(_('commit: %s\n') % t.strip())
6479 ui.status(_('commit: %s\n') % t.strip())
6472 else:
6480 else:
6473 # i18n: column positioning for "hg summary"
6481 # i18n: column positioning for "hg summary"
6474 ui.write(_('commit: %s\n') % t.strip())
6482 ui.write(_('commit: %s\n') % t.strip())
6475
6483
6476 # all ancestors of branch heads - all ancestors of parent = new csets
6484 # all ancestors of branch heads - all ancestors of parent = new csets
6477 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6485 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6478 bheads))
6486 bheads))
6479
6487
6480 if new == 0:
6488 if new == 0:
6481 # i18n: column positioning for "hg summary"
6489 # i18n: column positioning for "hg summary"
6482 ui.status(_('update: (current)\n'))
6490 ui.status(_('update: (current)\n'))
6483 elif pnode not in bheads:
6491 elif pnode not in bheads:
6484 # i18n: column positioning for "hg summary"
6492 # i18n: column positioning for "hg summary"
6485 ui.write(_('update: %d new changesets (update)\n') % new)
6493 ui.write(_('update: %d new changesets (update)\n') % new)
6486 else:
6494 else:
6487 # i18n: column positioning for "hg summary"
6495 # i18n: column positioning for "hg summary"
6488 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6496 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6489 (new, len(bheads)))
6497 (new, len(bheads)))
6490
6498
6491 t = []
6499 t = []
6492 draft = len(repo.revs('draft()'))
6500 draft = len(repo.revs('draft()'))
6493 if draft:
6501 if draft:
6494 t.append(_('%d draft') % draft)
6502 t.append(_('%d draft') % draft)
6495 secret = len(repo.revs('secret()'))
6503 secret = len(repo.revs('secret()'))
6496 if secret:
6504 if secret:
6497 t.append(_('%d secret') % secret)
6505 t.append(_('%d secret') % secret)
6498
6506
6499 if draft or secret:
6507 if draft or secret:
6500 ui.status(_('phases: %s\n') % ', '.join(t))
6508 ui.status(_('phases: %s\n') % ', '.join(t))
6501
6509
6502 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6510 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6503 for trouble in ("unstable", "divergent", "bumped"):
6511 for trouble in ("unstable", "divergent", "bumped"):
6504 numtrouble = len(repo.revs(trouble + "()"))
6512 numtrouble = len(repo.revs(trouble + "()"))
6505 # We write all the possibilities to ease translation
6513 # We write all the possibilities to ease translation
6506 troublemsg = {
6514 troublemsg = {
6507 "unstable": _("unstable: %d changeset"),
6515 "unstable": _("unstable: %d changeset"),
6508 "divergent": _("divergent: %d changeset"),
6516 "divergent": _("divergent: %d changeset"),
6509 "bumped": _("bumped: %d changeset"),
6517 "bumped": _("bumped: %d changeset"),
6510 }
6518 }
6511 if numtrouble > 0:
6519 if numtrouble > 0:
6512 ui.status(troublemsg[trouble] % numtrouble + "\n")
6520 ui.status(troublemsg[trouble] % numtrouble + "\n")
6513
6521
6514 cmdutil.summaryhooks(ui, repo)
6522 cmdutil.summaryhooks(ui, repo)
6515
6523
6516 if opts.get('remote'):
6524 if opts.get('remote'):
6517 needsincoming, needsoutgoing = True, True
6525 needsincoming, needsoutgoing = True, True
6518 else:
6526 else:
6519 needsincoming, needsoutgoing = False, False
6527 needsincoming, needsoutgoing = False, False
6520 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6528 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6521 if i:
6529 if i:
6522 needsincoming = True
6530 needsincoming = True
6523 if o:
6531 if o:
6524 needsoutgoing = True
6532 needsoutgoing = True
6525 if not needsincoming and not needsoutgoing:
6533 if not needsincoming and not needsoutgoing:
6526 return
6534 return
6527
6535
6528 def getincoming():
6536 def getincoming():
6529 source, branches = hg.parseurl(ui.expandpath('default'))
6537 source, branches = hg.parseurl(ui.expandpath('default'))
6530 sbranch = branches[0]
6538 sbranch = branches[0]
6531 try:
6539 try:
6532 other = hg.peer(repo, {}, source)
6540 other = hg.peer(repo, {}, source)
6533 except error.RepoError:
6541 except error.RepoError:
6534 if opts.get('remote'):
6542 if opts.get('remote'):
6535 raise
6543 raise
6536 return source, sbranch, None, None, None
6544 return source, sbranch, None, None, None
6537 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6545 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6538 if revs:
6546 if revs:
6539 revs = [other.lookup(rev) for rev in revs]
6547 revs = [other.lookup(rev) for rev in revs]
6540 ui.debug('comparing with %s\n' % util.hidepassword(source))
6548 ui.debug('comparing with %s\n' % util.hidepassword(source))
6541 repo.ui.pushbuffer()
6549 repo.ui.pushbuffer()
6542 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6550 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6543 repo.ui.popbuffer()
6551 repo.ui.popbuffer()
6544 return source, sbranch, other, commoninc, commoninc[1]
6552 return source, sbranch, other, commoninc, commoninc[1]
6545
6553
6546 if needsincoming:
6554 if needsincoming:
6547 source, sbranch, sother, commoninc, incoming = getincoming()
6555 source, sbranch, sother, commoninc, incoming = getincoming()
6548 else:
6556 else:
6549 source = sbranch = sother = commoninc = incoming = None
6557 source = sbranch = sother = commoninc = incoming = None
6550
6558
6551 def getoutgoing():
6559 def getoutgoing():
6552 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6560 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6553 dbranch = branches[0]
6561 dbranch = branches[0]
6554 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6562 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6555 if source != dest:
6563 if source != dest:
6556 try:
6564 try:
6557 dother = hg.peer(repo, {}, dest)
6565 dother = hg.peer(repo, {}, dest)
6558 except error.RepoError:
6566 except error.RepoError:
6559 if opts.get('remote'):
6567 if opts.get('remote'):
6560 raise
6568 raise
6561 return dest, dbranch, None, None
6569 return dest, dbranch, None, None
6562 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6570 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6563 elif sother is None:
6571 elif sother is None:
6564 # there is no explicit destination peer, but source one is invalid
6572 # there is no explicit destination peer, but source one is invalid
6565 return dest, dbranch, None, None
6573 return dest, dbranch, None, None
6566 else:
6574 else:
6567 dother = sother
6575 dother = sother
6568 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6576 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6569 common = None
6577 common = None
6570 else:
6578 else:
6571 common = commoninc
6579 common = commoninc
6572 if revs:
6580 if revs:
6573 revs = [repo.lookup(rev) for rev in revs]
6581 revs = [repo.lookup(rev) for rev in revs]
6574 repo.ui.pushbuffer()
6582 repo.ui.pushbuffer()
6575 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6583 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6576 commoninc=common)
6584 commoninc=common)
6577 repo.ui.popbuffer()
6585 repo.ui.popbuffer()
6578 return dest, dbranch, dother, outgoing
6586 return dest, dbranch, dother, outgoing
6579
6587
6580 if needsoutgoing:
6588 if needsoutgoing:
6581 dest, dbranch, dother, outgoing = getoutgoing()
6589 dest, dbranch, dother, outgoing = getoutgoing()
6582 else:
6590 else:
6583 dest = dbranch = dother = outgoing = None
6591 dest = dbranch = dother = outgoing = None
6584
6592
6585 if opts.get('remote'):
6593 if opts.get('remote'):
6586 t = []
6594 t = []
6587 if incoming:
6595 if incoming:
6588 t.append(_('1 or more incoming'))
6596 t.append(_('1 or more incoming'))
6589 o = outgoing.missing
6597 o = outgoing.missing
6590 if o:
6598 if o:
6591 t.append(_('%d outgoing') % len(o))
6599 t.append(_('%d outgoing') % len(o))
6592 other = dother or sother
6600 other = dother or sother
6593 if 'bookmarks' in other.listkeys('namespaces'):
6601 if 'bookmarks' in other.listkeys('namespaces'):
6594 counts = bookmarks.summary(repo, other)
6602 counts = bookmarks.summary(repo, other)
6595 if counts[0] > 0:
6603 if counts[0] > 0:
6596 t.append(_('%d incoming bookmarks') % counts[0])
6604 t.append(_('%d incoming bookmarks') % counts[0])
6597 if counts[1] > 0:
6605 if counts[1] > 0:
6598 t.append(_('%d outgoing bookmarks') % counts[1])
6606 t.append(_('%d outgoing bookmarks') % counts[1])
6599
6607
6600 if t:
6608 if t:
6601 # i18n: column positioning for "hg summary"
6609 # i18n: column positioning for "hg summary"
6602 ui.write(_('remote: %s\n') % (', '.join(t)))
6610 ui.write(_('remote: %s\n') % (', '.join(t)))
6603 else:
6611 else:
6604 # i18n: column positioning for "hg summary"
6612 # i18n: column positioning for "hg summary"
6605 ui.status(_('remote: (synced)\n'))
6613 ui.status(_('remote: (synced)\n'))
6606
6614
6607 cmdutil.summaryremotehooks(ui, repo, opts,
6615 cmdutil.summaryremotehooks(ui, repo, opts,
6608 ((source, sbranch, sother, commoninc),
6616 ((source, sbranch, sother, commoninc),
6609 (dest, dbranch, dother, outgoing)))
6617 (dest, dbranch, dother, outgoing)))
6610
6618
6611 @command('tag',
6619 @command('tag',
6612 [('f', 'force', None, _('force tag')),
6620 [('f', 'force', None, _('force tag')),
6613 ('l', 'local', None, _('make the tag local')),
6621 ('l', 'local', None, _('make the tag local')),
6614 ('r', 'rev', '', _('revision to tag'), _('REV')),
6622 ('r', 'rev', '', _('revision to tag'), _('REV')),
6615 ('', 'remove', None, _('remove a tag')),
6623 ('', 'remove', None, _('remove a tag')),
6616 # -l/--local is already there, commitopts cannot be used
6624 # -l/--local is already there, commitopts cannot be used
6617 ('e', 'edit', None, _('invoke editor on commit messages')),
6625 ('e', 'edit', None, _('invoke editor on commit messages')),
6618 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6626 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6619 ] + commitopts2,
6627 ] + commitopts2,
6620 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6628 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6621 def tag(ui, repo, name1, *names, **opts):
6629 def tag(ui, repo, name1, *names, **opts):
6622 """add one or more tags for the current or given revision
6630 """add one or more tags for the current or given revision
6623
6631
6624 Name a particular revision using <name>.
6632 Name a particular revision using <name>.
6625
6633
6626 Tags are used to name particular revisions of the repository and are
6634 Tags are used to name particular revisions of the repository and are
6627 very useful to compare different revisions, to go back to significant
6635 very useful to compare different revisions, to go back to significant
6628 earlier versions or to mark branch points as releases, etc. Changing
6636 earlier versions or to mark branch points as releases, etc. Changing
6629 an existing tag is normally disallowed; use -f/--force to override.
6637 an existing tag is normally disallowed; use -f/--force to override.
6630
6638
6631 If no revision is given, the parent of the working directory is
6639 If no revision is given, the parent of the working directory is
6632 used.
6640 used.
6633
6641
6634 To facilitate version control, distribution, and merging of tags,
6642 To facilitate version control, distribution, and merging of tags,
6635 they are stored as a file named ".hgtags" which is managed similarly
6643 they are stored as a file named ".hgtags" which is managed similarly
6636 to other project files and can be hand-edited if necessary. This
6644 to other project files and can be hand-edited if necessary. This
6637 also means that tagging creates a new commit. The file
6645 also means that tagging creates a new commit. The file
6638 ".hg/localtags" is used for local tags (not shared among
6646 ".hg/localtags" is used for local tags (not shared among
6639 repositories).
6647 repositories).
6640
6648
6641 Tag commits are usually made at the head of a branch. If the parent
6649 Tag commits are usually made at the head of a branch. If the parent
6642 of the working directory is not a branch head, :hg:`tag` aborts; use
6650 of the working directory is not a branch head, :hg:`tag` aborts; use
6643 -f/--force to force the tag commit to be based on a non-head
6651 -f/--force to force the tag commit to be based on a non-head
6644 changeset.
6652 changeset.
6645
6653
6646 See :hg:`help dates` for a list of formats valid for -d/--date.
6654 See :hg:`help dates` for a list of formats valid for -d/--date.
6647
6655
6648 Since tag names have priority over branch names during revision
6656 Since tag names have priority over branch names during revision
6649 lookup, using an existing branch name as a tag name is discouraged.
6657 lookup, using an existing branch name as a tag name is discouraged.
6650
6658
6651 Returns 0 on success.
6659 Returns 0 on success.
6652 """
6660 """
6653 wlock = lock = None
6661 wlock = lock = None
6654 try:
6662 try:
6655 wlock = repo.wlock()
6663 wlock = repo.wlock()
6656 lock = repo.lock()
6664 lock = repo.lock()
6657 rev_ = "."
6665 rev_ = "."
6658 names = [t.strip() for t in (name1,) + names]
6666 names = [t.strip() for t in (name1,) + names]
6659 if len(names) != len(set(names)):
6667 if len(names) != len(set(names)):
6660 raise error.Abort(_('tag names must be unique'))
6668 raise error.Abort(_('tag names must be unique'))
6661 for n in names:
6669 for n in names:
6662 scmutil.checknewlabel(repo, n, 'tag')
6670 scmutil.checknewlabel(repo, n, 'tag')
6663 if not n:
6671 if not n:
6664 raise error.Abort(_('tag names cannot consist entirely of '
6672 raise error.Abort(_('tag names cannot consist entirely of '
6665 'whitespace'))
6673 'whitespace'))
6666 if opts.get('rev') and opts.get('remove'):
6674 if opts.get('rev') and opts.get('remove'):
6667 raise error.Abort(_("--rev and --remove are incompatible"))
6675 raise error.Abort(_("--rev and --remove are incompatible"))
6668 if opts.get('rev'):
6676 if opts.get('rev'):
6669 rev_ = opts['rev']
6677 rev_ = opts['rev']
6670 message = opts.get('message')
6678 message = opts.get('message')
6671 if opts.get('remove'):
6679 if opts.get('remove'):
6672 if opts.get('local'):
6680 if opts.get('local'):
6673 expectedtype = 'local'
6681 expectedtype = 'local'
6674 else:
6682 else:
6675 expectedtype = 'global'
6683 expectedtype = 'global'
6676
6684
6677 for n in names:
6685 for n in names:
6678 if not repo.tagtype(n):
6686 if not repo.tagtype(n):
6679 raise error.Abort(_("tag '%s' does not exist") % n)
6687 raise error.Abort(_("tag '%s' does not exist") % n)
6680 if repo.tagtype(n) != expectedtype:
6688 if repo.tagtype(n) != expectedtype:
6681 if expectedtype == 'global':
6689 if expectedtype == 'global':
6682 raise error.Abort(_("tag '%s' is not a global tag") % n)
6690 raise error.Abort(_("tag '%s' is not a global tag") % n)
6683 else:
6691 else:
6684 raise error.Abort(_("tag '%s' is not a local tag") % n)
6692 raise error.Abort(_("tag '%s' is not a local tag") % n)
6685 rev_ = 'null'
6693 rev_ = 'null'
6686 if not message:
6694 if not message:
6687 # we don't translate commit messages
6695 # we don't translate commit messages
6688 message = 'Removed tag %s' % ', '.join(names)
6696 message = 'Removed tag %s' % ', '.join(names)
6689 elif not opts.get('force'):
6697 elif not opts.get('force'):
6690 for n in names:
6698 for n in names:
6691 if n in repo.tags():
6699 if n in repo.tags():
6692 raise error.Abort(_("tag '%s' already exists "
6700 raise error.Abort(_("tag '%s' already exists "
6693 "(use -f to force)") % n)
6701 "(use -f to force)") % n)
6694 if not opts.get('local'):
6702 if not opts.get('local'):
6695 p1, p2 = repo.dirstate.parents()
6703 p1, p2 = repo.dirstate.parents()
6696 if p2 != nullid:
6704 if p2 != nullid:
6697 raise error.Abort(_('uncommitted merge'))
6705 raise error.Abort(_('uncommitted merge'))
6698 bheads = repo.branchheads()
6706 bheads = repo.branchheads()
6699 if not opts.get('force') and bheads and p1 not in bheads:
6707 if not opts.get('force') and bheads and p1 not in bheads:
6700 raise error.Abort(_('not at a branch head (use -f to force)'))
6708 raise error.Abort(_('not at a branch head (use -f to force)'))
6701 r = scmutil.revsingle(repo, rev_).node()
6709 r = scmutil.revsingle(repo, rev_).node()
6702
6710
6703 if not message:
6711 if not message:
6704 # we don't translate commit messages
6712 # we don't translate commit messages
6705 message = ('Added tag %s for changeset %s' %
6713 message = ('Added tag %s for changeset %s' %
6706 (', '.join(names), short(r)))
6714 (', '.join(names), short(r)))
6707
6715
6708 date = opts.get('date')
6716 date = opts.get('date')
6709 if date:
6717 if date:
6710 date = util.parsedate(date)
6718 date = util.parsedate(date)
6711
6719
6712 if opts.get('remove'):
6720 if opts.get('remove'):
6713 editform = 'tag.remove'
6721 editform = 'tag.remove'
6714 else:
6722 else:
6715 editform = 'tag.add'
6723 editform = 'tag.add'
6716 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6724 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6717
6725
6718 # don't allow tagging the null rev
6726 # don't allow tagging the null rev
6719 if (not opts.get('remove') and
6727 if (not opts.get('remove') and
6720 scmutil.revsingle(repo, rev_).rev() == nullrev):
6728 scmutil.revsingle(repo, rev_).rev() == nullrev):
6721 raise error.Abort(_("cannot tag null revision"))
6729 raise error.Abort(_("cannot tag null revision"))
6722
6730
6723 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6731 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6724 editor=editor)
6732 editor=editor)
6725 finally:
6733 finally:
6726 release(lock, wlock)
6734 release(lock, wlock)
6727
6735
6728 @command('tags', formatteropts, '')
6736 @command('tags', formatteropts, '')
6729 def tags(ui, repo, **opts):
6737 def tags(ui, repo, **opts):
6730 """list repository tags
6738 """list repository tags
6731
6739
6732 This lists both regular and local tags. When the -v/--verbose
6740 This lists both regular and local tags. When the -v/--verbose
6733 switch is used, a third column "local" is printed for local tags.
6741 switch is used, a third column "local" is printed for local tags.
6734 When the -q/--quiet switch is used, only the tag name is printed.
6742 When the -q/--quiet switch is used, only the tag name is printed.
6735
6743
6736 Returns 0 on success.
6744 Returns 0 on success.
6737 """
6745 """
6738
6746
6739 fm = ui.formatter('tags', opts)
6747 fm = ui.formatter('tags', opts)
6740 hexfunc = fm.hexfunc
6748 hexfunc = fm.hexfunc
6741 tagtype = ""
6749 tagtype = ""
6742
6750
6743 for t, n in reversed(repo.tagslist()):
6751 for t, n in reversed(repo.tagslist()):
6744 hn = hexfunc(n)
6752 hn = hexfunc(n)
6745 label = 'tags.normal'
6753 label = 'tags.normal'
6746 tagtype = ''
6754 tagtype = ''
6747 if repo.tagtype(t) == 'local':
6755 if repo.tagtype(t) == 'local':
6748 label = 'tags.local'
6756 label = 'tags.local'
6749 tagtype = 'local'
6757 tagtype = 'local'
6750
6758
6751 fm.startitem()
6759 fm.startitem()
6752 fm.write('tag', '%s', t, label=label)
6760 fm.write('tag', '%s', t, label=label)
6753 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6761 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6754 fm.condwrite(not ui.quiet, 'rev node', fmt,
6762 fm.condwrite(not ui.quiet, 'rev node', fmt,
6755 repo.changelog.rev(n), hn, label=label)
6763 repo.changelog.rev(n), hn, label=label)
6756 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6764 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6757 tagtype, label=label)
6765 tagtype, label=label)
6758 fm.plain('\n')
6766 fm.plain('\n')
6759 fm.end()
6767 fm.end()
6760
6768
6761 @command('tip',
6769 @command('tip',
6762 [('p', 'patch', None, _('show patch')),
6770 [('p', 'patch', None, _('show patch')),
6763 ('g', 'git', None, _('use git extended diff format')),
6771 ('g', 'git', None, _('use git extended diff format')),
6764 ] + templateopts,
6772 ] + templateopts,
6765 _('[-p] [-g]'))
6773 _('[-p] [-g]'))
6766 def tip(ui, repo, **opts):
6774 def tip(ui, repo, **opts):
6767 """show the tip revision (DEPRECATED)
6775 """show the tip revision (DEPRECATED)
6768
6776
6769 The tip revision (usually just called the tip) is the changeset
6777 The tip revision (usually just called the tip) is the changeset
6770 most recently added to the repository (and therefore the most
6778 most recently added to the repository (and therefore the most
6771 recently changed head).
6779 recently changed head).
6772
6780
6773 If you have just made a commit, that commit will be the tip. If
6781 If you have just made a commit, that commit will be the tip. If
6774 you have just pulled changes from another repository, the tip of
6782 you have just pulled changes from another repository, the tip of
6775 that repository becomes the current tip. The "tip" tag is special
6783 that repository becomes the current tip. The "tip" tag is special
6776 and cannot be renamed or assigned to a different changeset.
6784 and cannot be renamed or assigned to a different changeset.
6777
6785
6778 This command is deprecated, please use :hg:`heads` instead.
6786 This command is deprecated, please use :hg:`heads` instead.
6779
6787
6780 Returns 0 on success.
6788 Returns 0 on success.
6781 """
6789 """
6782 displayer = cmdutil.show_changeset(ui, repo, opts)
6790 displayer = cmdutil.show_changeset(ui, repo, opts)
6783 displayer.show(repo['tip'])
6791 displayer.show(repo['tip'])
6784 displayer.close()
6792 displayer.close()
6785
6793
6786 @command('unbundle',
6794 @command('unbundle',
6787 [('u', 'update', None,
6795 [('u', 'update', None,
6788 _('update to new branch head if changesets were unbundled'))],
6796 _('update to new branch head if changesets were unbundled'))],
6789 _('[-u] FILE...'))
6797 _('[-u] FILE...'))
6790 def unbundle(ui, repo, fname1, *fnames, **opts):
6798 def unbundle(ui, repo, fname1, *fnames, **opts):
6791 """apply one or more changegroup files
6799 """apply one or more changegroup files
6792
6800
6793 Apply one or more compressed changegroup files generated by the
6801 Apply one or more compressed changegroup files generated by the
6794 bundle command.
6802 bundle command.
6795
6803
6796 Returns 0 on success, 1 if an update has unresolved files.
6804 Returns 0 on success, 1 if an update has unresolved files.
6797 """
6805 """
6798 fnames = (fname1,) + fnames
6806 fnames = (fname1,) + fnames
6799
6807
6800 lock = repo.lock()
6808 lock = repo.lock()
6801 try:
6809 try:
6802 for fname in fnames:
6810 for fname in fnames:
6803 f = hg.openpath(ui, fname)
6811 f = hg.openpath(ui, fname)
6804 gen = exchange.readbundle(ui, f, fname)
6812 gen = exchange.readbundle(ui, f, fname)
6805 if isinstance(gen, bundle2.unbundle20):
6813 if isinstance(gen, bundle2.unbundle20):
6806 tr = repo.transaction('unbundle')
6814 tr = repo.transaction('unbundle')
6807 try:
6815 try:
6808 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6816 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6809 url='bundle:' + fname)
6817 url='bundle:' + fname)
6810 tr.close()
6818 tr.close()
6811 except error.BundleUnknownFeatureError as exc:
6819 except error.BundleUnknownFeatureError as exc:
6812 raise error.Abort(_('%s: unknown bundle feature, %s')
6820 raise error.Abort(_('%s: unknown bundle feature, %s')
6813 % (fname, exc),
6821 % (fname, exc),
6814 hint=_("see https://mercurial-scm.org/"
6822 hint=_("see https://mercurial-scm.org/"
6815 "wiki/BundleFeature for more "
6823 "wiki/BundleFeature for more "
6816 "information"))
6824 "information"))
6817 finally:
6825 finally:
6818 if tr:
6826 if tr:
6819 tr.release()
6827 tr.release()
6820 changes = [r.get('return', 0)
6828 changes = [r.get('return', 0)
6821 for r in op.records['changegroup']]
6829 for r in op.records['changegroup']]
6822 modheads = changegroup.combineresults(changes)
6830 modheads = changegroup.combineresults(changes)
6823 elif isinstance(gen, streamclone.streamcloneapplier):
6831 elif isinstance(gen, streamclone.streamcloneapplier):
6824 raise error.Abort(
6832 raise error.Abort(
6825 _('packed bundles cannot be applied with '
6833 _('packed bundles cannot be applied with '
6826 '"hg unbundle"'),
6834 '"hg unbundle"'),
6827 hint=_('use "hg debugapplystreamclonebundle"'))
6835 hint=_('use "hg debugapplystreamclonebundle"'))
6828 else:
6836 else:
6829 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6837 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6830 finally:
6838 finally:
6831 lock.release()
6839 lock.release()
6832
6840
6833 return postincoming(ui, repo, modheads, opts.get('update'), None)
6841 return postincoming(ui, repo, modheads, opts.get('update'), None)
6834
6842
6835 @command('^update|up|checkout|co',
6843 @command('^update|up|checkout|co',
6836 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6844 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6837 ('c', 'check', None,
6845 ('c', 'check', None,
6838 _('update across branches if no uncommitted changes')),
6846 _('update across branches if no uncommitted changes')),
6839 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6847 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6840 ('r', 'rev', '', _('revision'), _('REV'))
6848 ('r', 'rev', '', _('revision'), _('REV'))
6841 ] + mergetoolopts,
6849 ] + mergetoolopts,
6842 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6850 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6843 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6851 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6844 tool=None):
6852 tool=None):
6845 """update working directory (or switch revisions)
6853 """update working directory (or switch revisions)
6846
6854
6847 Update the repository's working directory to the specified
6855 Update the repository's working directory to the specified
6848 changeset. If no changeset is specified, update to the tip of the
6856 changeset. If no changeset is specified, update to the tip of the
6849 current named branch and move the active bookmark (see :hg:`help
6857 current named branch and move the active bookmark (see :hg:`help
6850 bookmarks`).
6858 bookmarks`).
6851
6859
6852 Update sets the working directory's parent revision to the specified
6860 Update sets the working directory's parent revision to the specified
6853 changeset (see :hg:`help parents`).
6861 changeset (see :hg:`help parents`).
6854
6862
6855 If the changeset is not a descendant or ancestor of the working
6863 If the changeset is not a descendant or ancestor of the working
6856 directory's parent, the update is aborted. With the -c/--check
6864 directory's parent, the update is aborted. With the -c/--check
6857 option, the working directory is checked for uncommitted changes; if
6865 option, the working directory is checked for uncommitted changes; if
6858 none are found, the working directory is updated to the specified
6866 none are found, the working directory is updated to the specified
6859 changeset.
6867 changeset.
6860
6868
6861 .. container:: verbose
6869 .. container:: verbose
6862
6870
6863 The following rules apply when the working directory contains
6871 The following rules apply when the working directory contains
6864 uncommitted changes:
6872 uncommitted changes:
6865
6873
6866 1. If neither -c/--check nor -C/--clean is specified, and if
6874 1. If neither -c/--check nor -C/--clean is specified, and if
6867 the requested changeset is an ancestor or descendant of
6875 the requested changeset is an ancestor or descendant of
6868 the working directory's parent, the uncommitted changes
6876 the working directory's parent, the uncommitted changes
6869 are merged into the requested changeset and the merged
6877 are merged into the requested changeset and the merged
6870 result is left uncommitted. If the requested changeset is
6878 result is left uncommitted. If the requested changeset is
6871 not an ancestor or descendant (that is, it is on another
6879 not an ancestor or descendant (that is, it is on another
6872 branch), the update is aborted and the uncommitted changes
6880 branch), the update is aborted and the uncommitted changes
6873 are preserved.
6881 are preserved.
6874
6882
6875 2. With the -c/--check option, the update is aborted and the
6883 2. With the -c/--check option, the update is aborted and the
6876 uncommitted changes are preserved.
6884 uncommitted changes are preserved.
6877
6885
6878 3. With the -C/--clean option, uncommitted changes are discarded and
6886 3. With the -C/--clean option, uncommitted changes are discarded and
6879 the working directory is updated to the requested changeset.
6887 the working directory is updated to the requested changeset.
6880
6888
6881 To cancel an uncommitted merge (and lose your changes), use
6889 To cancel an uncommitted merge (and lose your changes), use
6882 :hg:`update --clean .`.
6890 :hg:`update --clean .`.
6883
6891
6884 Use null as the changeset to remove the working directory (like
6892 Use null as the changeset to remove the working directory (like
6885 :hg:`clone -U`).
6893 :hg:`clone -U`).
6886
6894
6887 If you want to revert just one file to an older revision, use
6895 If you want to revert just one file to an older revision, use
6888 :hg:`revert [-r REV] NAME`.
6896 :hg:`revert [-r REV] NAME`.
6889
6897
6890 See :hg:`help dates` for a list of formats valid for -d/--date.
6898 See :hg:`help dates` for a list of formats valid for -d/--date.
6891
6899
6892 Returns 0 on success, 1 if there are unresolved files.
6900 Returns 0 on success, 1 if there are unresolved files.
6893 """
6901 """
6894 movemarkfrom = None
6902 movemarkfrom = None
6895 if rev and node:
6903 if rev and node:
6896 raise error.Abort(_("please specify just one revision"))
6904 raise error.Abort(_("please specify just one revision"))
6897
6905
6898 if rev is None or rev == '':
6906 if rev is None or rev == '':
6899 rev = node
6907 rev = node
6900
6908
6901 wlock = repo.wlock()
6909 wlock = repo.wlock()
6902 try:
6910 try:
6903 cmdutil.clearunfinished(repo)
6911 cmdutil.clearunfinished(repo)
6904
6912
6905 if date:
6913 if date:
6906 if rev is not None:
6914 if rev is not None:
6907 raise error.Abort(_("you can't specify a revision and a date"))
6915 raise error.Abort(_("you can't specify a revision and a date"))
6908 rev = cmdutil.finddate(ui, repo, date)
6916 rev = cmdutil.finddate(ui, repo, date)
6909
6917
6910 # if we defined a bookmark, we have to remember the original name
6918 # if we defined a bookmark, we have to remember the original name
6911 brev = rev
6919 brev = rev
6912 rev = scmutil.revsingle(repo, rev, rev).rev()
6920 rev = scmutil.revsingle(repo, rev, rev).rev()
6913
6921
6914 if check and clean:
6922 if check and clean:
6915 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6923 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6916 )
6924 )
6917
6925
6918 if check:
6926 if check:
6919 cmdutil.bailifchanged(repo, merge=False)
6927 cmdutil.bailifchanged(repo, merge=False)
6920 if rev is None:
6928 if rev is None:
6921 updata = destutil.destupdate(repo, clean=clean, check=check)
6929 updata = destutil.destupdate(repo, clean=clean, check=check)
6922 rev, movemarkfrom, brev = updata
6930 rev, movemarkfrom, brev = updata
6923
6931
6924 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6932 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6925
6933
6926 if clean:
6934 if clean:
6927 ret = hg.clean(repo, rev)
6935 ret = hg.clean(repo, rev)
6928 else:
6936 else:
6929 ret = hg.update(repo, rev)
6937 ret = hg.update(repo, rev)
6930
6938
6931 if not ret and movemarkfrom:
6939 if not ret and movemarkfrom:
6932 if movemarkfrom == repo['.'].node():
6940 if movemarkfrom == repo['.'].node():
6933 pass # no-op update
6941 pass # no-op update
6934 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6942 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6935 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6943 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6936 else:
6944 else:
6937 # this can happen with a non-linear update
6945 # this can happen with a non-linear update
6938 ui.status(_("(leaving bookmark %s)\n") %
6946 ui.status(_("(leaving bookmark %s)\n") %
6939 repo._activebookmark)
6947 repo._activebookmark)
6940 bookmarks.deactivate(repo)
6948 bookmarks.deactivate(repo)
6941 elif brev in repo._bookmarks:
6949 elif brev in repo._bookmarks:
6942 bookmarks.activate(repo, brev)
6950 bookmarks.activate(repo, brev)
6943 ui.status(_("(activating bookmark %s)\n") % brev)
6951 ui.status(_("(activating bookmark %s)\n") % brev)
6944 elif brev:
6952 elif brev:
6945 if repo._activebookmark:
6953 if repo._activebookmark:
6946 ui.status(_("(leaving bookmark %s)\n") %
6954 ui.status(_("(leaving bookmark %s)\n") %
6947 repo._activebookmark)
6955 repo._activebookmark)
6948 bookmarks.deactivate(repo)
6956 bookmarks.deactivate(repo)
6949 finally:
6957 finally:
6950 wlock.release()
6958 wlock.release()
6951
6959
6952 return ret
6960 return ret
6953
6961
6954 @command('verify', [])
6962 @command('verify', [])
6955 def verify(ui, repo):
6963 def verify(ui, repo):
6956 """verify the integrity of the repository
6964 """verify the integrity of the repository
6957
6965
6958 Verify the integrity of the current repository.
6966 Verify the integrity of the current repository.
6959
6967
6960 This will perform an extensive check of the repository's
6968 This will perform an extensive check of the repository's
6961 integrity, validating the hashes and checksums of each entry in
6969 integrity, validating the hashes and checksums of each entry in
6962 the changelog, manifest, and tracked files, as well as the
6970 the changelog, manifest, and tracked files, as well as the
6963 integrity of their crosslinks and indices.
6971 integrity of their crosslinks and indices.
6964
6972
6965 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6973 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6966 for more information about recovery from corruption of the
6974 for more information about recovery from corruption of the
6967 repository.
6975 repository.
6968
6976
6969 Returns 0 on success, 1 if errors are encountered.
6977 Returns 0 on success, 1 if errors are encountered.
6970 """
6978 """
6971 return hg.verify(repo)
6979 return hg.verify(repo)
6972
6980
6973 @command('version', [], norepo=True)
6981 @command('version', [], norepo=True)
6974 def version_(ui):
6982 def version_(ui):
6975 """output version and copyright information"""
6983 """output version and copyright information"""
6976 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6984 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6977 % util.version())
6985 % util.version())
6978 ui.status(_(
6986 ui.status(_(
6979 "(see https://mercurial-scm.org for more information)\n"
6987 "(see https://mercurial-scm.org for more information)\n"
6980 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6988 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6981 "This is free software; see the source for copying conditions. "
6989 "This is free software; see the source for copying conditions. "
6982 "There is NO\nwarranty; "
6990 "There is NO\nwarranty; "
6983 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6991 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6984 ))
6992 ))
6985
6993
6986 ui.note(_("\nEnabled extensions:\n\n"))
6994 ui.note(_("\nEnabled extensions:\n\n"))
6987 if ui.verbose:
6995 if ui.verbose:
6988 # format names and versions into columns
6996 # format names and versions into columns
6989 names = []
6997 names = []
6990 vers = []
6998 vers = []
6991 for name, module in extensions.extensions():
6999 for name, module in extensions.extensions():
6992 names.append(name)
7000 names.append(name)
6993 vers.append(extensions.moduleversion(module))
7001 vers.append(extensions.moduleversion(module))
6994 if names:
7002 if names:
6995 maxnamelen = max(len(n) for n in names)
7003 maxnamelen = max(len(n) for n in names)
6996 for i, name in enumerate(names):
7004 for i, name in enumerate(names):
6997 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7005 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now