##// END OF EJS Templates
log: help provide sort by date example
timeless -
r27664:84a9d7fc default
parent child Browse files
Show More
@@ -1,7009 +1,7013 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 If you include --file, --user, or --date, the revision number is
333 If you include --file, --user, or --date, the revision number is
334 suppressed unless you also include --number.
334 suppressed unless you also include --number.
335
335
336 Without the -a/--text option, annotate will avoid processing files
336 Without the -a/--text option, annotate will avoid processing files
337 it detects as binary. With -a, annotate will annotate the file
337 it detects as binary. With -a, annotate will annotate the file
338 anyway, although the results will probably be neither useful
338 anyway, although the results will probably be neither useful
339 nor desirable.
339 nor desirable.
340
340
341 Returns 0 on success.
341 Returns 0 on success.
342 """
342 """
343 if not pats:
343 if not pats:
344 raise error.Abort(_('at least one filename or pattern is required'))
344 raise error.Abort(_('at least one filename or pattern is required'))
345
345
346 if opts.get('follow'):
346 if opts.get('follow'):
347 # --follow is deprecated and now just an alias for -f/--file
347 # --follow is deprecated and now just an alias for -f/--file
348 # to mimic the behavior of Mercurial before version 1.5
348 # to mimic the behavior of Mercurial before version 1.5
349 opts['file'] = True
349 opts['file'] = True
350
350
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
352
352
353 fm = ui.formatter('annotate', opts)
353 fm = ui.formatter('annotate', opts)
354 if ui.quiet:
354 if ui.quiet:
355 datefunc = util.shortdate
355 datefunc = util.shortdate
356 else:
356 else:
357 datefunc = util.datestr
357 datefunc = util.datestr
358 if ctx.rev() is None:
358 if ctx.rev() is None:
359 def hexfn(node):
359 def hexfn(node):
360 if node is None:
360 if node is None:
361 return None
361 return None
362 else:
362 else:
363 return fm.hexfunc(node)
363 return fm.hexfunc(node)
364 if opts.get('changeset'):
364 if opts.get('changeset'):
365 # omit "+" suffix which is appended to node hex
365 # omit "+" suffix which is appended to node hex
366 def formatrev(rev):
366 def formatrev(rev):
367 if rev is None:
367 if rev is None:
368 return '%d' % ctx.p1().rev()
368 return '%d' % ctx.p1().rev()
369 else:
369 else:
370 return '%d' % rev
370 return '%d' % rev
371 else:
371 else:
372 def formatrev(rev):
372 def formatrev(rev):
373 if rev is None:
373 if rev is None:
374 return '%d+' % ctx.p1().rev()
374 return '%d+' % ctx.p1().rev()
375 else:
375 else:
376 return '%d ' % rev
376 return '%d ' % rev
377 def formathex(hex):
377 def formathex(hex):
378 if hex is None:
378 if hex is None:
379 return '%s+' % fm.hexfunc(ctx.p1().node())
379 return '%s+' % fm.hexfunc(ctx.p1().node())
380 else:
380 else:
381 return '%s ' % hex
381 return '%s ' % hex
382 else:
382 else:
383 hexfn = fm.hexfunc
383 hexfn = fm.hexfunc
384 formatrev = formathex = str
384 formatrev = formathex = str
385
385
386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
387 ('number', ' ', lambda x: x[0].rev(), formatrev),
387 ('number', ' ', lambda x: x[0].rev(), formatrev),
388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
390 ('file', ' ', lambda x: x[0].path(), str),
390 ('file', ' ', lambda x: x[0].path(), str),
391 ('line_number', ':', lambda x: x[1], str),
391 ('line_number', ':', lambda x: x[1], str),
392 ]
392 ]
393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
394
394
395 if (not opts.get('user') and not opts.get('changeset')
395 if (not opts.get('user') and not opts.get('changeset')
396 and not opts.get('date') and not opts.get('file')):
396 and not opts.get('date') and not opts.get('file')):
397 opts['number'] = True
397 opts['number'] = True
398
398
399 linenumber = opts.get('line_number') is not None
399 linenumber = opts.get('line_number') is not None
400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
401 raise error.Abort(_('at least one of -n/-c is required for -l'))
401 raise error.Abort(_('at least one of -n/-c is required for -l'))
402
402
403 if fm:
403 if fm:
404 def makefunc(get, fmt):
404 def makefunc(get, fmt):
405 return get
405 return get
406 else:
406 else:
407 def makefunc(get, fmt):
407 def makefunc(get, fmt):
408 return lambda x: fmt(get(x))
408 return lambda x: fmt(get(x))
409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
410 if opts.get(op)]
410 if opts.get(op)]
411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
413 if opts.get(op))
413 if opts.get(op))
414
414
415 def bad(x, y):
415 def bad(x, y):
416 raise error.Abort("%s: %s" % (x, y))
416 raise error.Abort("%s: %s" % (x, y))
417
417
418 m = scmutil.match(ctx, pats, opts, badfn=bad)
418 m = scmutil.match(ctx, pats, opts, badfn=bad)
419
419
420 follow = not opts.get('no_follow')
420 follow = not opts.get('no_follow')
421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
422 whitespace=True)
422 whitespace=True)
423 for abs in ctx.walk(m):
423 for abs in ctx.walk(m):
424 fctx = ctx[abs]
424 fctx = ctx[abs]
425 if not opts.get('text') and util.binary(fctx.data()):
425 if not opts.get('text') and util.binary(fctx.data()):
426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
427 continue
427 continue
428
428
429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
430 diffopts=diffopts)
430 diffopts=diffopts)
431 formats = []
431 formats = []
432 pieces = []
432 pieces = []
433
433
434 for f, sep in funcmap:
434 for f, sep in funcmap:
435 l = [f(n) for n, dummy in lines]
435 l = [f(n) for n, dummy in lines]
436 if l:
436 if l:
437 if fm:
437 if fm:
438 formats.append(['%s' for x in l])
438 formats.append(['%s' for x in l])
439 else:
439 else:
440 sizes = [encoding.colwidth(x) for x in l]
440 sizes = [encoding.colwidth(x) for x in l]
441 ml = max(sizes)
441 ml = max(sizes)
442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
443 pieces.append(l)
443 pieces.append(l)
444
444
445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
446 fm.startitem()
446 fm.startitem()
447 fm.write(fields, "".join(f), *p)
447 fm.write(fields, "".join(f), *p)
448 fm.write('line', ": %s", l[1])
448 fm.write('line', ": %s", l[1])
449
449
450 if lines and not lines[-1][1].endswith('\n'):
450 if lines and not lines[-1][1].endswith('\n'):
451 fm.plain('\n')
451 fm.plain('\n')
452
452
453 fm.end()
453 fm.end()
454
454
455 @command('archive',
455 @command('archive',
456 [('', 'no-decode', None, _('do not pass files through decoders')),
456 [('', 'no-decode', None, _('do not pass files through decoders')),
457 ('p', 'prefix', '', _('directory prefix for files in archive'),
457 ('p', 'prefix', '', _('directory prefix for files in archive'),
458 _('PREFIX')),
458 _('PREFIX')),
459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
461 ] + subrepoopts + walkopts,
461 ] + subrepoopts + walkopts,
462 _('[OPTION]... DEST'))
462 _('[OPTION]... DEST'))
463 def archive(ui, repo, dest, **opts):
463 def archive(ui, repo, dest, **opts):
464 '''create an unversioned archive of a repository revision
464 '''create an unversioned archive of a repository revision
465
465
466 By default, the revision used is the parent of the working
466 By default, the revision used is the parent of the working
467 directory; use -r/--rev to specify a different revision.
467 directory; use -r/--rev to specify a different revision.
468
468
469 The archive type is automatically detected based on file
469 The archive type is automatically detected based on file
470 extension (to override, use -t/--type).
470 extension (to override, use -t/--type).
471
471
472 .. container:: verbose
472 .. container:: verbose
473
473
474 Examples:
474 Examples:
475
475
476 - create a zip file containing the 1.0 release::
476 - create a zip file containing the 1.0 release::
477
477
478 hg archive -r 1.0 project-1.0.zip
478 hg archive -r 1.0 project-1.0.zip
479
479
480 - create a tarball excluding .hg files::
480 - create a tarball excluding .hg files::
481
481
482 hg archive project.tar.gz -X ".hg*"
482 hg archive project.tar.gz -X ".hg*"
483
483
484 Valid types are:
484 Valid types are:
485
485
486 :``files``: a directory full of files (default)
486 :``files``: a directory full of files (default)
487 :``tar``: tar archive, uncompressed
487 :``tar``: tar archive, uncompressed
488 :``tbz2``: tar archive, compressed using bzip2
488 :``tbz2``: tar archive, compressed using bzip2
489 :``tgz``: tar archive, compressed using gzip
489 :``tgz``: tar archive, compressed using gzip
490 :``uzip``: zip archive, uncompressed
490 :``uzip``: zip archive, uncompressed
491 :``zip``: zip archive, compressed using deflate
491 :``zip``: zip archive, compressed using deflate
492
492
493 The exact name of the destination archive or directory is given
493 The exact name of the destination archive or directory is given
494 using a format string; see :hg:`help export` for details.
494 using a format string; see :hg:`help export` for details.
495
495
496 Each member added to an archive file has a directory prefix
496 Each member added to an archive file has a directory prefix
497 prepended. Use -p/--prefix to specify a format string for the
497 prepended. Use -p/--prefix to specify a format string for the
498 prefix. The default is the basename of the archive, with suffixes
498 prefix. The default is the basename of the archive, with suffixes
499 removed.
499 removed.
500
500
501 Returns 0 on success.
501 Returns 0 on success.
502 '''
502 '''
503
503
504 ctx = scmutil.revsingle(repo, opts.get('rev'))
504 ctx = scmutil.revsingle(repo, opts.get('rev'))
505 if not ctx:
505 if not ctx:
506 raise error.Abort(_('no working directory: please specify a revision'))
506 raise error.Abort(_('no working directory: please specify a revision'))
507 node = ctx.node()
507 node = ctx.node()
508 dest = cmdutil.makefilename(repo, dest, node)
508 dest = cmdutil.makefilename(repo, dest, node)
509 if os.path.realpath(dest) == repo.root:
509 if os.path.realpath(dest) == repo.root:
510 raise error.Abort(_('repository root cannot be destination'))
510 raise error.Abort(_('repository root cannot be destination'))
511
511
512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
513 prefix = opts.get('prefix')
513 prefix = opts.get('prefix')
514
514
515 if dest == '-':
515 if dest == '-':
516 if kind == 'files':
516 if kind == 'files':
517 raise error.Abort(_('cannot archive plain files to stdout'))
517 raise error.Abort(_('cannot archive plain files to stdout'))
518 dest = cmdutil.makefileobj(repo, dest)
518 dest = cmdutil.makefileobj(repo, dest)
519 if not prefix:
519 if not prefix:
520 prefix = os.path.basename(repo.root) + '-%h'
520 prefix = os.path.basename(repo.root) + '-%h'
521
521
522 prefix = cmdutil.makefilename(repo, prefix, node)
522 prefix = cmdutil.makefilename(repo, prefix, node)
523 matchfn = scmutil.match(ctx, [], opts)
523 matchfn = scmutil.match(ctx, [], opts)
524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
525 matchfn, prefix, subrepos=opts.get('subrepos'))
525 matchfn, prefix, subrepos=opts.get('subrepos'))
526
526
527 @command('backout',
527 @command('backout',
528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
529 ('', 'commit', None, _('commit if no conflicts were encountered')),
529 ('', 'commit', None, _('commit if no conflicts were encountered')),
530 ('', 'parent', '',
530 ('', 'parent', '',
531 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
531 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
532 ('r', 'rev', '', _('revision to backout'), _('REV')),
532 ('r', 'rev', '', _('revision to backout'), _('REV')),
533 ('e', 'edit', False, _('invoke editor on commit messages')),
533 ('e', 'edit', False, _('invoke editor on commit messages')),
534 ] + mergetoolopts + walkopts + commitopts + commitopts2,
534 ] + mergetoolopts + walkopts + commitopts + commitopts2,
535 _('[OPTION]... [-r] REV'))
535 _('[OPTION]... [-r] REV'))
536 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
536 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
537 '''reverse effect of earlier changeset
537 '''reverse effect of earlier changeset
538
538
539 Prepare a new changeset with the effect of REV undone in the
539 Prepare a new changeset with the effect of REV undone in the
540 current working directory.
540 current working directory.
541
541
542 If REV is the parent of the working directory, then this new changeset
542 If REV is the parent of the working directory, then this new changeset
543 is committed automatically. Otherwise, hg needs to merge the
543 is committed automatically. Otherwise, hg needs to merge the
544 changes and the merged result is left uncommitted.
544 changes and the merged result is left uncommitted.
545
545
546 .. note::
546 .. note::
547
547
548 :hg:`backout` cannot be used to fix either an unwanted or
548 :hg:`backout` cannot be used to fix either an unwanted or
549 incorrect merge.
549 incorrect merge.
550
550
551 .. container:: verbose
551 .. container:: verbose
552
552
553 Examples:
553 Examples:
554
554
555 - Reverse the effect of the parent of the working directory.
555 - Reverse the effect of the parent of the working directory.
556 This backout will be committed immediately::
556 This backout will be committed immediately::
557
557
558 hg backout -r .
558 hg backout -r .
559
559
560 - Reverse the effect of previous bad revision 23::
560 - Reverse the effect of previous bad revision 23::
561
561
562 hg backout -r 23
562 hg backout -r 23
563 hg commit -m "Backout revision 23"
563 hg commit -m "Backout revision 23"
564
564
565 - Reverse the effect of previous bad revision 23 and
565 - Reverse the effect of previous bad revision 23 and
566 commit the backout immediately::
566 commit the backout immediately::
567
567
568 hg backout -r 23 --commit
568 hg backout -r 23 --commit
569
569
570 By default, the pending changeset will have one parent,
570 By default, the pending changeset will have one parent,
571 maintaining a linear history. With --merge, the pending
571 maintaining a linear history. With --merge, the pending
572 changeset will instead have two parents: the old parent of the
572 changeset will instead have two parents: the old parent of the
573 working directory and a new child of REV that simply undoes REV.
573 working directory and a new child of REV that simply undoes REV.
574
574
575 Before version 1.7, the behavior without --merge was equivalent
575 Before version 1.7, the behavior without --merge was equivalent
576 to specifying --merge followed by :hg:`update --clean .` to
576 to specifying --merge followed by :hg:`update --clean .` to
577 cancel the merge and leave the child of REV as a head to be
577 cancel the merge and leave the child of REV as a head to be
578 merged separately.
578 merged separately.
579
579
580 See :hg:`help dates` for a list of formats valid for -d/--date.
580 See :hg:`help dates` for a list of formats valid for -d/--date.
581
581
582 See :hg:`help revert` for a way to restore files to the state
582 See :hg:`help revert` for a way to restore files to the state
583 of another revision.
583 of another revision.
584
584
585 Returns 0 on success, 1 if nothing to backout or there are unresolved
585 Returns 0 on success, 1 if nothing to backout or there are unresolved
586 files.
586 files.
587 '''
587 '''
588 wlock = lock = None
588 wlock = lock = None
589 try:
589 try:
590 wlock = repo.wlock()
590 wlock = repo.wlock()
591 lock = repo.lock()
591 lock = repo.lock()
592 return _dobackout(ui, repo, node, rev, commit, **opts)
592 return _dobackout(ui, repo, node, rev, commit, **opts)
593 finally:
593 finally:
594 release(lock, wlock)
594 release(lock, wlock)
595
595
596 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
596 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
597 if rev and node:
597 if rev and node:
598 raise error.Abort(_("please specify just one revision"))
598 raise error.Abort(_("please specify just one revision"))
599
599
600 if not rev:
600 if not rev:
601 rev = node
601 rev = node
602
602
603 if not rev:
603 if not rev:
604 raise error.Abort(_("please specify a revision to backout"))
604 raise error.Abort(_("please specify a revision to backout"))
605
605
606 date = opts.get('date')
606 date = opts.get('date')
607 if date:
607 if date:
608 opts['date'] = util.parsedate(date)
608 opts['date'] = util.parsedate(date)
609
609
610 cmdutil.checkunfinished(repo)
610 cmdutil.checkunfinished(repo)
611 cmdutil.bailifchanged(repo)
611 cmdutil.bailifchanged(repo)
612 node = scmutil.revsingle(repo, rev).node()
612 node = scmutil.revsingle(repo, rev).node()
613
613
614 op1, op2 = repo.dirstate.parents()
614 op1, op2 = repo.dirstate.parents()
615 if not repo.changelog.isancestor(node, op1):
615 if not repo.changelog.isancestor(node, op1):
616 raise error.Abort(_('cannot backout change that is not an ancestor'))
616 raise error.Abort(_('cannot backout change that is not an ancestor'))
617
617
618 p1, p2 = repo.changelog.parents(node)
618 p1, p2 = repo.changelog.parents(node)
619 if p1 == nullid:
619 if p1 == nullid:
620 raise error.Abort(_('cannot backout a change with no parents'))
620 raise error.Abort(_('cannot backout a change with no parents'))
621 if p2 != nullid:
621 if p2 != nullid:
622 if not opts.get('parent'):
622 if not opts.get('parent'):
623 raise error.Abort(_('cannot backout a merge changeset'))
623 raise error.Abort(_('cannot backout a merge changeset'))
624 p = repo.lookup(opts['parent'])
624 p = repo.lookup(opts['parent'])
625 if p not in (p1, p2):
625 if p not in (p1, p2):
626 raise error.Abort(_('%s is not a parent of %s') %
626 raise error.Abort(_('%s is not a parent of %s') %
627 (short(p), short(node)))
627 (short(p), short(node)))
628 parent = p
628 parent = p
629 else:
629 else:
630 if opts.get('parent'):
630 if opts.get('parent'):
631 raise error.Abort(_('cannot use --parent on non-merge changeset'))
631 raise error.Abort(_('cannot use --parent on non-merge changeset'))
632 parent = p1
632 parent = p1
633
633
634 # the backout should appear on the same branch
634 # the backout should appear on the same branch
635 try:
635 try:
636 branch = repo.dirstate.branch()
636 branch = repo.dirstate.branch()
637 bheads = repo.branchheads(branch)
637 bheads = repo.branchheads(branch)
638 rctx = scmutil.revsingle(repo, hex(parent))
638 rctx = scmutil.revsingle(repo, hex(parent))
639 if not opts.get('merge') and op1 != node:
639 if not opts.get('merge') and op1 != node:
640 dsguard = cmdutil.dirstateguard(repo, 'backout')
640 dsguard = cmdutil.dirstateguard(repo, 'backout')
641 try:
641 try:
642 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
642 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
643 'backout')
643 'backout')
644 stats = mergemod.update(repo, parent, True, True, node, False)
644 stats = mergemod.update(repo, parent, True, True, node, False)
645 repo.setparents(op1, op2)
645 repo.setparents(op1, op2)
646 dsguard.close()
646 dsguard.close()
647 hg._showstats(repo, stats)
647 hg._showstats(repo, stats)
648 if stats[3]:
648 if stats[3]:
649 repo.ui.status(_("use 'hg resolve' to retry unresolved "
649 repo.ui.status(_("use 'hg resolve' to retry unresolved "
650 "file merges\n"))
650 "file merges\n"))
651 return 1
651 return 1
652 elif not commit:
652 elif not commit:
653 msg = _("changeset %s backed out, "
653 msg = _("changeset %s backed out, "
654 "don't forget to commit.\n")
654 "don't forget to commit.\n")
655 ui.status(msg % short(node))
655 ui.status(msg % short(node))
656 return 0
656 return 0
657 finally:
657 finally:
658 ui.setconfig('ui', 'forcemerge', '', '')
658 ui.setconfig('ui', 'forcemerge', '', '')
659 lockmod.release(dsguard)
659 lockmod.release(dsguard)
660 else:
660 else:
661 hg.clean(repo, node, show_stats=False)
661 hg.clean(repo, node, show_stats=False)
662 repo.dirstate.setbranch(branch)
662 repo.dirstate.setbranch(branch)
663 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
663 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
664
664
665
665
666 def commitfunc(ui, repo, message, match, opts):
666 def commitfunc(ui, repo, message, match, opts):
667 editform = 'backout'
667 editform = 'backout'
668 e = cmdutil.getcommiteditor(editform=editform, **opts)
668 e = cmdutil.getcommiteditor(editform=editform, **opts)
669 if not message:
669 if not message:
670 # we don't translate commit messages
670 # we don't translate commit messages
671 message = "Backed out changeset %s" % short(node)
671 message = "Backed out changeset %s" % short(node)
672 e = cmdutil.getcommiteditor(edit=True, editform=editform)
672 e = cmdutil.getcommiteditor(edit=True, editform=editform)
673 return repo.commit(message, opts.get('user'), opts.get('date'),
673 return repo.commit(message, opts.get('user'), opts.get('date'),
674 match, editor=e)
674 match, editor=e)
675 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
675 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
676 if not newnode:
676 if not newnode:
677 ui.status(_("nothing changed\n"))
677 ui.status(_("nothing changed\n"))
678 return 1
678 return 1
679 cmdutil.commitstatus(repo, newnode, branch, bheads)
679 cmdutil.commitstatus(repo, newnode, branch, bheads)
680
680
681 def nice(node):
681 def nice(node):
682 return '%d:%s' % (repo.changelog.rev(node), short(node))
682 return '%d:%s' % (repo.changelog.rev(node), short(node))
683 ui.status(_('changeset %s backs out changeset %s\n') %
683 ui.status(_('changeset %s backs out changeset %s\n') %
684 (nice(repo.changelog.tip()), nice(node)))
684 (nice(repo.changelog.tip()), nice(node)))
685 if opts.get('merge') and op1 != node:
685 if opts.get('merge') and op1 != node:
686 hg.clean(repo, op1, show_stats=False)
686 hg.clean(repo, op1, show_stats=False)
687 ui.status(_('merging with changeset %s\n')
687 ui.status(_('merging with changeset %s\n')
688 % nice(repo.changelog.tip()))
688 % nice(repo.changelog.tip()))
689 try:
689 try:
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
691 'backout')
691 'backout')
692 return hg.merge(repo, hex(repo.changelog.tip()))
692 return hg.merge(repo, hex(repo.changelog.tip()))
693 finally:
693 finally:
694 ui.setconfig('ui', 'forcemerge', '', '')
694 ui.setconfig('ui', 'forcemerge', '', '')
695 finally:
695 finally:
696 # TODO: get rid of this meaningless try/finally enclosing.
696 # TODO: get rid of this meaningless try/finally enclosing.
697 # this is kept only to reduce changes in a patch.
697 # this is kept only to reduce changes in a patch.
698 pass
698 pass
699 return 0
699 return 0
700
700
701 @command('bisect',
701 @command('bisect',
702 [('r', 'reset', False, _('reset bisect state')),
702 [('r', 'reset', False, _('reset bisect state')),
703 ('g', 'good', False, _('mark changeset good')),
703 ('g', 'good', False, _('mark changeset good')),
704 ('b', 'bad', False, _('mark changeset bad')),
704 ('b', 'bad', False, _('mark changeset bad')),
705 ('s', 'skip', False, _('skip testing changeset')),
705 ('s', 'skip', False, _('skip testing changeset')),
706 ('e', 'extend', False, _('extend the bisect range')),
706 ('e', 'extend', False, _('extend the bisect range')),
707 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
707 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
708 ('U', 'noupdate', False, _('do not update to target'))],
708 ('U', 'noupdate', False, _('do not update to target'))],
709 _("[-gbsr] [-U] [-c CMD] [REV]"))
709 _("[-gbsr] [-U] [-c CMD] [REV]"))
710 def bisect(ui, repo, rev=None, extra=None, command=None,
710 def bisect(ui, repo, rev=None, extra=None, command=None,
711 reset=None, good=None, bad=None, skip=None, extend=None,
711 reset=None, good=None, bad=None, skip=None, extend=None,
712 noupdate=None):
712 noupdate=None):
713 """subdivision search of changesets
713 """subdivision search of changesets
714
714
715 This command helps to find changesets which introduce problems. To
715 This command helps to find changesets which introduce problems. To
716 use, mark the earliest changeset you know exhibits the problem as
716 use, mark the earliest changeset you know exhibits the problem as
717 bad, then mark the latest changeset which is free from the problem
717 bad, then mark the latest changeset which is free from the problem
718 as good. Bisect will update your working directory to a revision
718 as good. Bisect will update your working directory to a revision
719 for testing (unless the -U/--noupdate option is specified). Once
719 for testing (unless the -U/--noupdate option is specified). Once
720 you have performed tests, mark the working directory as good or
720 you have performed tests, mark the working directory as good or
721 bad, and bisect will either update to another candidate changeset
721 bad, and bisect will either update to another candidate changeset
722 or announce that it has found the bad revision.
722 or announce that it has found the bad revision.
723
723
724 As a shortcut, you can also use the revision argument to mark a
724 As a shortcut, you can also use the revision argument to mark a
725 revision as good or bad without checking it out first.
725 revision as good or bad without checking it out first.
726
726
727 If you supply a command, it will be used for automatic bisection.
727 If you supply a command, it will be used for automatic bisection.
728 The environment variable HG_NODE will contain the ID of the
728 The environment variable HG_NODE will contain the ID of the
729 changeset being tested. The exit status of the command will be
729 changeset being tested. The exit status of the command will be
730 used to mark revisions as good or bad: status 0 means good, 125
730 used to mark revisions as good or bad: status 0 means good, 125
731 means to skip the revision, 127 (command not found) will abort the
731 means to skip the revision, 127 (command not found) will abort the
732 bisection, and any other non-zero exit status means the revision
732 bisection, and any other non-zero exit status means the revision
733 is bad.
733 is bad.
734
734
735 .. container:: verbose
735 .. container:: verbose
736
736
737 Some examples:
737 Some examples:
738
738
739 - start a bisection with known bad revision 34, and good revision 12::
739 - start a bisection with known bad revision 34, and good revision 12::
740
740
741 hg bisect --bad 34
741 hg bisect --bad 34
742 hg bisect --good 12
742 hg bisect --good 12
743
743
744 - advance the current bisection by marking current revision as good or
744 - advance the current bisection by marking current revision as good or
745 bad::
745 bad::
746
746
747 hg bisect --good
747 hg bisect --good
748 hg bisect --bad
748 hg bisect --bad
749
749
750 - mark the current revision, or a known revision, to be skipped (e.g. if
750 - mark the current revision, or a known revision, to be skipped (e.g. if
751 that revision is not usable because of another issue)::
751 that revision is not usable because of another issue)::
752
752
753 hg bisect --skip
753 hg bisect --skip
754 hg bisect --skip 23
754 hg bisect --skip 23
755
755
756 - skip all revisions that do not touch directories ``foo`` or ``bar``::
756 - skip all revisions that do not touch directories ``foo`` or ``bar``::
757
757
758 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
758 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
759
759
760 - forget the current bisection::
760 - forget the current bisection::
761
761
762 hg bisect --reset
762 hg bisect --reset
763
763
764 - use 'make && make tests' to automatically find the first broken
764 - use 'make && make tests' to automatically find the first broken
765 revision::
765 revision::
766
766
767 hg bisect --reset
767 hg bisect --reset
768 hg bisect --bad 34
768 hg bisect --bad 34
769 hg bisect --good 12
769 hg bisect --good 12
770 hg bisect --command "make && make tests"
770 hg bisect --command "make && make tests"
771
771
772 - see all changesets whose states are already known in the current
772 - see all changesets whose states are already known in the current
773 bisection::
773 bisection::
774
774
775 hg log -r "bisect(pruned)"
775 hg log -r "bisect(pruned)"
776
776
777 - see the changeset currently being bisected (especially useful
777 - see the changeset currently being bisected (especially useful
778 if running with -U/--noupdate)::
778 if running with -U/--noupdate)::
779
779
780 hg log -r "bisect(current)"
780 hg log -r "bisect(current)"
781
781
782 - see all changesets that took part in the current bisection::
782 - see all changesets that took part in the current bisection::
783
783
784 hg log -r "bisect(range)"
784 hg log -r "bisect(range)"
785
785
786 - you can even get a nice graph::
786 - you can even get a nice graph::
787
787
788 hg log --graph -r "bisect(range)"
788 hg log --graph -r "bisect(range)"
789
789
790 See :hg:`help revsets` for more about the `bisect()` keyword.
790 See :hg:`help revsets` for more about the `bisect()` keyword.
791
791
792 Returns 0 on success.
792 Returns 0 on success.
793 """
793 """
794 def extendbisectrange(nodes, good):
794 def extendbisectrange(nodes, good):
795 # bisect is incomplete when it ends on a merge node and
795 # bisect is incomplete when it ends on a merge node and
796 # one of the parent was not checked.
796 # one of the parent was not checked.
797 parents = repo[nodes[0]].parents()
797 parents = repo[nodes[0]].parents()
798 if len(parents) > 1:
798 if len(parents) > 1:
799 if good:
799 if good:
800 side = state['bad']
800 side = state['bad']
801 else:
801 else:
802 side = state['good']
802 side = state['good']
803 num = len(set(i.node() for i in parents) & set(side))
803 num = len(set(i.node() for i in parents) & set(side))
804 if num == 1:
804 if num == 1:
805 return parents[0].ancestor(parents[1])
805 return parents[0].ancestor(parents[1])
806 return None
806 return None
807
807
808 def print_result(nodes, good):
808 def print_result(nodes, good):
809 displayer = cmdutil.show_changeset(ui, repo, {})
809 displayer = cmdutil.show_changeset(ui, repo, {})
810 if len(nodes) == 1:
810 if len(nodes) == 1:
811 # narrowed it down to a single revision
811 # narrowed it down to a single revision
812 if good:
812 if good:
813 ui.write(_("The first good revision is:\n"))
813 ui.write(_("The first good revision is:\n"))
814 else:
814 else:
815 ui.write(_("The first bad revision is:\n"))
815 ui.write(_("The first bad revision is:\n"))
816 displayer.show(repo[nodes[0]])
816 displayer.show(repo[nodes[0]])
817 extendnode = extendbisectrange(nodes, good)
817 extendnode = extendbisectrange(nodes, good)
818 if extendnode is not None:
818 if extendnode is not None:
819 ui.write(_('Not all ancestors of this changeset have been'
819 ui.write(_('Not all ancestors of this changeset have been'
820 ' checked.\nUse bisect --extend to continue the '
820 ' checked.\nUse bisect --extend to continue the '
821 'bisection from\nthe common ancestor, %s.\n')
821 'bisection from\nthe common ancestor, %s.\n')
822 % extendnode)
822 % extendnode)
823 else:
823 else:
824 # multiple possible revisions
824 # multiple possible revisions
825 if good:
825 if good:
826 ui.write(_("Due to skipped revisions, the first "
826 ui.write(_("Due to skipped revisions, the first "
827 "good revision could be any of:\n"))
827 "good revision could be any of:\n"))
828 else:
828 else:
829 ui.write(_("Due to skipped revisions, the first "
829 ui.write(_("Due to skipped revisions, the first "
830 "bad revision could be any of:\n"))
830 "bad revision could be any of:\n"))
831 for n in nodes:
831 for n in nodes:
832 displayer.show(repo[n])
832 displayer.show(repo[n])
833 displayer.close()
833 displayer.close()
834
834
835 def check_state(state, interactive=True):
835 def check_state(state, interactive=True):
836 if not state['good'] or not state['bad']:
836 if not state['good'] or not state['bad']:
837 if (good or bad or skip or reset) and interactive:
837 if (good or bad or skip or reset) and interactive:
838 return
838 return
839 if not state['good']:
839 if not state['good']:
840 raise error.Abort(_('cannot bisect (no known good revisions)'))
840 raise error.Abort(_('cannot bisect (no known good revisions)'))
841 else:
841 else:
842 raise error.Abort(_('cannot bisect (no known bad revisions)'))
842 raise error.Abort(_('cannot bisect (no known bad revisions)'))
843 return True
843 return True
844
844
845 # backward compatibility
845 # backward compatibility
846 if rev in "good bad reset init".split():
846 if rev in "good bad reset init".split():
847 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
847 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
848 cmd, rev, extra = rev, extra, None
848 cmd, rev, extra = rev, extra, None
849 if cmd == "good":
849 if cmd == "good":
850 good = True
850 good = True
851 elif cmd == "bad":
851 elif cmd == "bad":
852 bad = True
852 bad = True
853 else:
853 else:
854 reset = True
854 reset = True
855 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
855 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
856 raise error.Abort(_('incompatible arguments'))
856 raise error.Abort(_('incompatible arguments'))
857
857
858 cmdutil.checkunfinished(repo)
858 cmdutil.checkunfinished(repo)
859
859
860 if reset:
860 if reset:
861 p = repo.join("bisect.state")
861 p = repo.join("bisect.state")
862 if os.path.exists(p):
862 if os.path.exists(p):
863 os.unlink(p)
863 os.unlink(p)
864 return
864 return
865
865
866 state = hbisect.load_state(repo)
866 state = hbisect.load_state(repo)
867
867
868 if command:
868 if command:
869 changesets = 1
869 changesets = 1
870 if noupdate:
870 if noupdate:
871 try:
871 try:
872 node = state['current'][0]
872 node = state['current'][0]
873 except LookupError:
873 except LookupError:
874 raise error.Abort(_('current bisect revision is unknown - '
874 raise error.Abort(_('current bisect revision is unknown - '
875 'start a new bisect to fix'))
875 'start a new bisect to fix'))
876 else:
876 else:
877 node, p2 = repo.dirstate.parents()
877 node, p2 = repo.dirstate.parents()
878 if p2 != nullid:
878 if p2 != nullid:
879 raise error.Abort(_('current bisect revision is a merge'))
879 raise error.Abort(_('current bisect revision is a merge'))
880 try:
880 try:
881 while changesets:
881 while changesets:
882 # update state
882 # update state
883 state['current'] = [node]
883 state['current'] = [node]
884 hbisect.save_state(repo, state)
884 hbisect.save_state(repo, state)
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
886 if status == 125:
886 if status == 125:
887 transition = "skip"
887 transition = "skip"
888 elif status == 0:
888 elif status == 0:
889 transition = "good"
889 transition = "good"
890 # status < 0 means process was killed
890 # status < 0 means process was killed
891 elif status == 127:
891 elif status == 127:
892 raise error.Abort(_("failed to execute %s") % command)
892 raise error.Abort(_("failed to execute %s") % command)
893 elif status < 0:
893 elif status < 0:
894 raise error.Abort(_("%s killed") % command)
894 raise error.Abort(_("%s killed") % command)
895 else:
895 else:
896 transition = "bad"
896 transition = "bad"
897 ctx = scmutil.revsingle(repo, rev, node)
897 ctx = scmutil.revsingle(repo, rev, node)
898 rev = None # clear for future iterations
898 rev = None # clear for future iterations
899 state[transition].append(ctx.node())
899 state[transition].append(ctx.node())
900 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
900 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
901 check_state(state, interactive=False)
901 check_state(state, interactive=False)
902 # bisect
902 # bisect
903 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
903 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
904 # update to next check
904 # update to next check
905 node = nodes[0]
905 node = nodes[0]
906 if not noupdate:
906 if not noupdate:
907 cmdutil.bailifchanged(repo)
907 cmdutil.bailifchanged(repo)
908 hg.clean(repo, node, show_stats=False)
908 hg.clean(repo, node, show_stats=False)
909 finally:
909 finally:
910 state['current'] = [node]
910 state['current'] = [node]
911 hbisect.save_state(repo, state)
911 hbisect.save_state(repo, state)
912 print_result(nodes, bgood)
912 print_result(nodes, bgood)
913 return
913 return
914
914
915 # update state
915 # update state
916
916
917 if rev:
917 if rev:
918 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
918 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
919 else:
919 else:
920 nodes = [repo.lookup('.')]
920 nodes = [repo.lookup('.')]
921
921
922 if good or bad or skip:
922 if good or bad or skip:
923 if good:
923 if good:
924 state['good'] += nodes
924 state['good'] += nodes
925 elif bad:
925 elif bad:
926 state['bad'] += nodes
926 state['bad'] += nodes
927 elif skip:
927 elif skip:
928 state['skip'] += nodes
928 state['skip'] += nodes
929 hbisect.save_state(repo, state)
929 hbisect.save_state(repo, state)
930
930
931 if not check_state(state):
931 if not check_state(state):
932 return
932 return
933
933
934 # actually bisect
934 # actually bisect
935 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
935 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
936 if extend:
936 if extend:
937 if not changesets:
937 if not changesets:
938 extendnode = extendbisectrange(nodes, good)
938 extendnode = extendbisectrange(nodes, good)
939 if extendnode is not None:
939 if extendnode is not None:
940 ui.write(_("Extending search to changeset %d:%s\n")
940 ui.write(_("Extending search to changeset %d:%s\n")
941 % (extendnode.rev(), extendnode))
941 % (extendnode.rev(), extendnode))
942 state['current'] = [extendnode.node()]
942 state['current'] = [extendnode.node()]
943 hbisect.save_state(repo, state)
943 hbisect.save_state(repo, state)
944 if noupdate:
944 if noupdate:
945 return
945 return
946 cmdutil.bailifchanged(repo)
946 cmdutil.bailifchanged(repo)
947 return hg.clean(repo, extendnode.node())
947 return hg.clean(repo, extendnode.node())
948 raise error.Abort(_("nothing to extend"))
948 raise error.Abort(_("nothing to extend"))
949
949
950 if changesets == 0:
950 if changesets == 0:
951 print_result(nodes, good)
951 print_result(nodes, good)
952 else:
952 else:
953 assert len(nodes) == 1 # only a single node can be tested next
953 assert len(nodes) == 1 # only a single node can be tested next
954 node = nodes[0]
954 node = nodes[0]
955 # compute the approximate number of remaining tests
955 # compute the approximate number of remaining tests
956 tests, size = 0, 2
956 tests, size = 0, 2
957 while size <= changesets:
957 while size <= changesets:
958 tests, size = tests + 1, size * 2
958 tests, size = tests + 1, size * 2
959 rev = repo.changelog.rev(node)
959 rev = repo.changelog.rev(node)
960 ui.write(_("Testing changeset %d:%s "
960 ui.write(_("Testing changeset %d:%s "
961 "(%d changesets remaining, ~%d tests)\n")
961 "(%d changesets remaining, ~%d tests)\n")
962 % (rev, short(node), changesets, tests))
962 % (rev, short(node), changesets, tests))
963 state['current'] = [node]
963 state['current'] = [node]
964 hbisect.save_state(repo, state)
964 hbisect.save_state(repo, state)
965 if not noupdate:
965 if not noupdate:
966 cmdutil.bailifchanged(repo)
966 cmdutil.bailifchanged(repo)
967 return hg.clean(repo, node)
967 return hg.clean(repo, node)
968
968
969 @command('bookmarks|bookmark',
969 @command('bookmarks|bookmark',
970 [('f', 'force', False, _('force')),
970 [('f', 'force', False, _('force')),
971 ('r', 'rev', '', _('revision'), _('REV')),
971 ('r', 'rev', '', _('revision'), _('REV')),
972 ('d', 'delete', False, _('delete a given bookmark')),
972 ('d', 'delete', False, _('delete a given bookmark')),
973 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
973 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
974 ('i', 'inactive', False, _('mark a bookmark inactive')),
974 ('i', 'inactive', False, _('mark a bookmark inactive')),
975 ] + formatteropts,
975 ] + formatteropts,
976 _('hg bookmarks [OPTIONS]... [NAME]...'))
976 _('hg bookmarks [OPTIONS]... [NAME]...'))
977 def bookmark(ui, repo, *names, **opts):
977 def bookmark(ui, repo, *names, **opts):
978 '''create a new bookmark or list existing bookmarks
978 '''create a new bookmark or list existing bookmarks
979
979
980 Bookmarks are labels on changesets to help track lines of development.
980 Bookmarks are labels on changesets to help track lines of development.
981 Bookmarks are unversioned and can be moved, renamed and deleted.
981 Bookmarks are unversioned and can be moved, renamed and deleted.
982 Deleting or moving a bookmark has no effect on the associated changesets.
982 Deleting or moving a bookmark has no effect on the associated changesets.
983
983
984 Creating or updating to a bookmark causes it to be marked as 'active'.
984 Creating or updating to a bookmark causes it to be marked as 'active'.
985 The active bookmark is indicated with a '*'.
985 The active bookmark is indicated with a '*'.
986 When a commit is made, the active bookmark will advance to the new commit.
986 When a commit is made, the active bookmark will advance to the new commit.
987 A plain :hg:`update` will also advance an active bookmark, if possible.
987 A plain :hg:`update` will also advance an active bookmark, if possible.
988 Updating away from a bookmark will cause it to be deactivated.
988 Updating away from a bookmark will cause it to be deactivated.
989
989
990 Bookmarks can be pushed and pulled between repositories (see
990 Bookmarks can be pushed and pulled between repositories (see
991 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
991 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
992 diverged, a new 'divergent bookmark' of the form 'name@path' will
992 diverged, a new 'divergent bookmark' of the form 'name@path' will
993 be created. Using :hg:`merge` will resolve the divergence.
993 be created. Using :hg:`merge` will resolve the divergence.
994
994
995 A bookmark named '@' has the special property that :hg:`clone` will
995 A bookmark named '@' has the special property that :hg:`clone` will
996 check it out by default if it exists.
996 check it out by default if it exists.
997
997
998 .. container:: verbose
998 .. container:: verbose
999
999
1000 Examples:
1000 Examples:
1001
1001
1002 - create an active bookmark for a new line of development::
1002 - create an active bookmark for a new line of development::
1003
1003
1004 hg book new-feature
1004 hg book new-feature
1005
1005
1006 - create an inactive bookmark as a place marker::
1006 - create an inactive bookmark as a place marker::
1007
1007
1008 hg book -i reviewed
1008 hg book -i reviewed
1009
1009
1010 - create an inactive bookmark on another changeset::
1010 - create an inactive bookmark on another changeset::
1011
1011
1012 hg book -r .^ tested
1012 hg book -r .^ tested
1013
1013
1014 - rename bookmark turkey to dinner::
1014 - rename bookmark turkey to dinner::
1015
1015
1016 hg book -m turkey dinner
1016 hg book -m turkey dinner
1017
1017
1018 - move the '@' bookmark from another branch::
1018 - move the '@' bookmark from another branch::
1019
1019
1020 hg book -f @
1020 hg book -f @
1021 '''
1021 '''
1022 force = opts.get('force')
1022 force = opts.get('force')
1023 rev = opts.get('rev')
1023 rev = opts.get('rev')
1024 delete = opts.get('delete')
1024 delete = opts.get('delete')
1025 rename = opts.get('rename')
1025 rename = opts.get('rename')
1026 inactive = opts.get('inactive')
1026 inactive = opts.get('inactive')
1027
1027
1028 def checkformat(mark):
1028 def checkformat(mark):
1029 mark = mark.strip()
1029 mark = mark.strip()
1030 if not mark:
1030 if not mark:
1031 raise error.Abort(_("bookmark names cannot consist entirely of "
1031 raise error.Abort(_("bookmark names cannot consist entirely of "
1032 "whitespace"))
1032 "whitespace"))
1033 scmutil.checknewlabel(repo, mark, 'bookmark')
1033 scmutil.checknewlabel(repo, mark, 'bookmark')
1034 return mark
1034 return mark
1035
1035
1036 def checkconflict(repo, mark, cur, force=False, target=None):
1036 def checkconflict(repo, mark, cur, force=False, target=None):
1037 if mark in marks and not force:
1037 if mark in marks and not force:
1038 if target:
1038 if target:
1039 if marks[mark] == target and target == cur:
1039 if marks[mark] == target and target == cur:
1040 # re-activating a bookmark
1040 # re-activating a bookmark
1041 return
1041 return
1042 anc = repo.changelog.ancestors([repo[target].rev()])
1042 anc = repo.changelog.ancestors([repo[target].rev()])
1043 bmctx = repo[marks[mark]]
1043 bmctx = repo[marks[mark]]
1044 divs = [repo[b].node() for b in marks
1044 divs = [repo[b].node() for b in marks
1045 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1045 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1046
1046
1047 # allow resolving a single divergent bookmark even if moving
1047 # allow resolving a single divergent bookmark even if moving
1048 # the bookmark across branches when a revision is specified
1048 # the bookmark across branches when a revision is specified
1049 # that contains a divergent bookmark
1049 # that contains a divergent bookmark
1050 if bmctx.rev() not in anc and target in divs:
1050 if bmctx.rev() not in anc and target in divs:
1051 bookmarks.deletedivergent(repo, [target], mark)
1051 bookmarks.deletedivergent(repo, [target], mark)
1052 return
1052 return
1053
1053
1054 deletefrom = [b for b in divs
1054 deletefrom = [b for b in divs
1055 if repo[b].rev() in anc or b == target]
1055 if repo[b].rev() in anc or b == target]
1056 bookmarks.deletedivergent(repo, deletefrom, mark)
1056 bookmarks.deletedivergent(repo, deletefrom, mark)
1057 if bookmarks.validdest(repo, bmctx, repo[target]):
1057 if bookmarks.validdest(repo, bmctx, repo[target]):
1058 ui.status(_("moving bookmark '%s' forward from %s\n") %
1058 ui.status(_("moving bookmark '%s' forward from %s\n") %
1059 (mark, short(bmctx.node())))
1059 (mark, short(bmctx.node())))
1060 return
1060 return
1061 raise error.Abort(_("bookmark '%s' already exists "
1061 raise error.Abort(_("bookmark '%s' already exists "
1062 "(use -f to force)") % mark)
1062 "(use -f to force)") % mark)
1063 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1063 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1064 and not force):
1064 and not force):
1065 raise error.Abort(
1065 raise error.Abort(
1066 _("a bookmark cannot have the name of an existing branch"))
1066 _("a bookmark cannot have the name of an existing branch"))
1067
1067
1068 if delete and rename:
1068 if delete and rename:
1069 raise error.Abort(_("--delete and --rename are incompatible"))
1069 raise error.Abort(_("--delete and --rename are incompatible"))
1070 if delete and rev:
1070 if delete and rev:
1071 raise error.Abort(_("--rev is incompatible with --delete"))
1071 raise error.Abort(_("--rev is incompatible with --delete"))
1072 if rename and rev:
1072 if rename and rev:
1073 raise error.Abort(_("--rev is incompatible with --rename"))
1073 raise error.Abort(_("--rev is incompatible with --rename"))
1074 if not names and (delete or rev):
1074 if not names and (delete or rev):
1075 raise error.Abort(_("bookmark name required"))
1075 raise error.Abort(_("bookmark name required"))
1076
1076
1077 if delete or rename or names or inactive:
1077 if delete or rename or names or inactive:
1078 wlock = lock = tr = None
1078 wlock = lock = tr = None
1079 try:
1079 try:
1080 wlock = repo.wlock()
1080 wlock = repo.wlock()
1081 lock = repo.lock()
1081 lock = repo.lock()
1082 cur = repo.changectx('.').node()
1082 cur = repo.changectx('.').node()
1083 marks = repo._bookmarks
1083 marks = repo._bookmarks
1084 if delete:
1084 if delete:
1085 tr = repo.transaction('bookmark')
1085 tr = repo.transaction('bookmark')
1086 for mark in names:
1086 for mark in names:
1087 if mark not in marks:
1087 if mark not in marks:
1088 raise error.Abort(_("bookmark '%s' does not exist") %
1088 raise error.Abort(_("bookmark '%s' does not exist") %
1089 mark)
1089 mark)
1090 if mark == repo._activebookmark:
1090 if mark == repo._activebookmark:
1091 bookmarks.deactivate(repo)
1091 bookmarks.deactivate(repo)
1092 del marks[mark]
1092 del marks[mark]
1093
1093
1094 elif rename:
1094 elif rename:
1095 tr = repo.transaction('bookmark')
1095 tr = repo.transaction('bookmark')
1096 if not names:
1096 if not names:
1097 raise error.Abort(_("new bookmark name required"))
1097 raise error.Abort(_("new bookmark name required"))
1098 elif len(names) > 1:
1098 elif len(names) > 1:
1099 raise error.Abort(_("only one new bookmark name allowed"))
1099 raise error.Abort(_("only one new bookmark name allowed"))
1100 mark = checkformat(names[0])
1100 mark = checkformat(names[0])
1101 if rename not in marks:
1101 if rename not in marks:
1102 raise error.Abort(_("bookmark '%s' does not exist")
1102 raise error.Abort(_("bookmark '%s' does not exist")
1103 % rename)
1103 % rename)
1104 checkconflict(repo, mark, cur, force)
1104 checkconflict(repo, mark, cur, force)
1105 marks[mark] = marks[rename]
1105 marks[mark] = marks[rename]
1106 if repo._activebookmark == rename and not inactive:
1106 if repo._activebookmark == rename and not inactive:
1107 bookmarks.activate(repo, mark)
1107 bookmarks.activate(repo, mark)
1108 del marks[rename]
1108 del marks[rename]
1109 elif names:
1109 elif names:
1110 tr = repo.transaction('bookmark')
1110 tr = repo.transaction('bookmark')
1111 newact = None
1111 newact = None
1112 for mark in names:
1112 for mark in names:
1113 mark = checkformat(mark)
1113 mark = checkformat(mark)
1114 if newact is None:
1114 if newact is None:
1115 newact = mark
1115 newact = mark
1116 if inactive and mark == repo._activebookmark:
1116 if inactive and mark == repo._activebookmark:
1117 bookmarks.deactivate(repo)
1117 bookmarks.deactivate(repo)
1118 return
1118 return
1119 tgt = cur
1119 tgt = cur
1120 if rev:
1120 if rev:
1121 tgt = scmutil.revsingle(repo, rev).node()
1121 tgt = scmutil.revsingle(repo, rev).node()
1122 checkconflict(repo, mark, cur, force, tgt)
1122 checkconflict(repo, mark, cur, force, tgt)
1123 marks[mark] = tgt
1123 marks[mark] = tgt
1124 if not inactive and cur == marks[newact] and not rev:
1124 if not inactive and cur == marks[newact] and not rev:
1125 bookmarks.activate(repo, newact)
1125 bookmarks.activate(repo, newact)
1126 elif cur != tgt and newact == repo._activebookmark:
1126 elif cur != tgt and newact == repo._activebookmark:
1127 bookmarks.deactivate(repo)
1127 bookmarks.deactivate(repo)
1128 elif inactive:
1128 elif inactive:
1129 if len(marks) == 0:
1129 if len(marks) == 0:
1130 ui.status(_("no bookmarks set\n"))
1130 ui.status(_("no bookmarks set\n"))
1131 elif not repo._activebookmark:
1131 elif not repo._activebookmark:
1132 ui.status(_("no active bookmark\n"))
1132 ui.status(_("no active bookmark\n"))
1133 else:
1133 else:
1134 bookmarks.deactivate(repo)
1134 bookmarks.deactivate(repo)
1135 if tr is not None:
1135 if tr is not None:
1136 marks.recordchange(tr)
1136 marks.recordchange(tr)
1137 tr.close()
1137 tr.close()
1138 finally:
1138 finally:
1139 lockmod.release(tr, lock, wlock)
1139 lockmod.release(tr, lock, wlock)
1140 else: # show bookmarks
1140 else: # show bookmarks
1141 fm = ui.formatter('bookmarks', opts)
1141 fm = ui.formatter('bookmarks', opts)
1142 hexfn = fm.hexfunc
1142 hexfn = fm.hexfunc
1143 marks = repo._bookmarks
1143 marks = repo._bookmarks
1144 if len(marks) == 0 and not fm:
1144 if len(marks) == 0 and not fm:
1145 ui.status(_("no bookmarks set\n"))
1145 ui.status(_("no bookmarks set\n"))
1146 for bmark, n in sorted(marks.iteritems()):
1146 for bmark, n in sorted(marks.iteritems()):
1147 active = repo._activebookmark
1147 active = repo._activebookmark
1148 if bmark == active:
1148 if bmark == active:
1149 prefix, label = '*', activebookmarklabel
1149 prefix, label = '*', activebookmarklabel
1150 else:
1150 else:
1151 prefix, label = ' ', ''
1151 prefix, label = ' ', ''
1152
1152
1153 fm.startitem()
1153 fm.startitem()
1154 if not ui.quiet:
1154 if not ui.quiet:
1155 fm.plain(' %s ' % prefix, label=label)
1155 fm.plain(' %s ' % prefix, label=label)
1156 fm.write('bookmark', '%s', bmark, label=label)
1156 fm.write('bookmark', '%s', bmark, label=label)
1157 pad = " " * (25 - encoding.colwidth(bmark))
1157 pad = " " * (25 - encoding.colwidth(bmark))
1158 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1158 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1159 repo.changelog.rev(n), hexfn(n), label=label)
1159 repo.changelog.rev(n), hexfn(n), label=label)
1160 fm.data(active=(bmark == active))
1160 fm.data(active=(bmark == active))
1161 fm.plain('\n')
1161 fm.plain('\n')
1162 fm.end()
1162 fm.end()
1163
1163
1164 @command('branch',
1164 @command('branch',
1165 [('f', 'force', None,
1165 [('f', 'force', None,
1166 _('set branch name even if it shadows an existing branch')),
1166 _('set branch name even if it shadows an existing branch')),
1167 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1167 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1168 _('[-fC] [NAME]'))
1168 _('[-fC] [NAME]'))
1169 def branch(ui, repo, label=None, **opts):
1169 def branch(ui, repo, label=None, **opts):
1170 """set or show the current branch name
1170 """set or show the current branch name
1171
1171
1172 .. note::
1172 .. note::
1173
1173
1174 Branch names are permanent and global. Use :hg:`bookmark` to create a
1174 Branch names are permanent and global. Use :hg:`bookmark` to create a
1175 light-weight bookmark instead. See :hg:`help glossary` for more
1175 light-weight bookmark instead. See :hg:`help glossary` for more
1176 information about named branches and bookmarks.
1176 information about named branches and bookmarks.
1177
1177
1178 With no argument, show the current branch name. With one argument,
1178 With no argument, show the current branch name. With one argument,
1179 set the working directory branch name (the branch will not exist
1179 set the working directory branch name (the branch will not exist
1180 in the repository until the next commit). Standard practice
1180 in the repository until the next commit). Standard practice
1181 recommends that primary development take place on the 'default'
1181 recommends that primary development take place on the 'default'
1182 branch.
1182 branch.
1183
1183
1184 Unless -f/--force is specified, branch will not let you set a
1184 Unless -f/--force is specified, branch will not let you set a
1185 branch name that already exists.
1185 branch name that already exists.
1186
1186
1187 Use -C/--clean to reset the working directory branch to that of
1187 Use -C/--clean to reset the working directory branch to that of
1188 the parent of the working directory, negating a previous branch
1188 the parent of the working directory, negating a previous branch
1189 change.
1189 change.
1190
1190
1191 Use the command :hg:`update` to switch to an existing branch. Use
1191 Use the command :hg:`update` to switch to an existing branch. Use
1192 :hg:`commit --close-branch` to mark this branch head as closed.
1192 :hg:`commit --close-branch` to mark this branch head as closed.
1193 When all heads of a branch are closed, the branch will be
1193 When all heads of a branch are closed, the branch will be
1194 considered closed.
1194 considered closed.
1195
1195
1196 Returns 0 on success.
1196 Returns 0 on success.
1197 """
1197 """
1198 if label:
1198 if label:
1199 label = label.strip()
1199 label = label.strip()
1200
1200
1201 if not opts.get('clean') and not label:
1201 if not opts.get('clean') and not label:
1202 ui.write("%s\n" % repo.dirstate.branch())
1202 ui.write("%s\n" % repo.dirstate.branch())
1203 return
1203 return
1204
1204
1205 wlock = repo.wlock()
1205 wlock = repo.wlock()
1206 try:
1206 try:
1207 if opts.get('clean'):
1207 if opts.get('clean'):
1208 label = repo[None].p1().branch()
1208 label = repo[None].p1().branch()
1209 repo.dirstate.setbranch(label)
1209 repo.dirstate.setbranch(label)
1210 ui.status(_('reset working directory to branch %s\n') % label)
1210 ui.status(_('reset working directory to branch %s\n') % label)
1211 elif label:
1211 elif label:
1212 if not opts.get('force') and label in repo.branchmap():
1212 if not opts.get('force') and label in repo.branchmap():
1213 if label not in [p.branch() for p in repo[None].parents()]:
1213 if label not in [p.branch() for p in repo[None].parents()]:
1214 raise error.Abort(_('a branch of the same name already'
1214 raise error.Abort(_('a branch of the same name already'
1215 ' exists'),
1215 ' exists'),
1216 # i18n: "it" refers to an existing branch
1216 # i18n: "it" refers to an existing branch
1217 hint=_("use 'hg update' to switch to it"))
1217 hint=_("use 'hg update' to switch to it"))
1218 scmutil.checknewlabel(repo, label, 'branch')
1218 scmutil.checknewlabel(repo, label, 'branch')
1219 repo.dirstate.setbranch(label)
1219 repo.dirstate.setbranch(label)
1220 ui.status(_('marked working directory as branch %s\n') % label)
1220 ui.status(_('marked working directory as branch %s\n') % label)
1221
1221
1222 # find any open named branches aside from default
1222 # find any open named branches aside from default
1223 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1223 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1224 if n != "default" and not c]
1224 if n != "default" and not c]
1225 if not others:
1225 if not others:
1226 ui.status(_('(branches are permanent and global, '
1226 ui.status(_('(branches are permanent and global, '
1227 'did you want a bookmark?)\n'))
1227 'did you want a bookmark?)\n'))
1228 finally:
1228 finally:
1229 wlock.release()
1229 wlock.release()
1230
1230
1231 @command('branches',
1231 @command('branches',
1232 [('a', 'active', False,
1232 [('a', 'active', False,
1233 _('show only branches that have unmerged heads (DEPRECATED)')),
1233 _('show only branches that have unmerged heads (DEPRECATED)')),
1234 ('c', 'closed', False, _('show normal and closed branches')),
1234 ('c', 'closed', False, _('show normal and closed branches')),
1235 ] + formatteropts,
1235 ] + formatteropts,
1236 _('[-ac]'))
1236 _('[-ac]'))
1237 def branches(ui, repo, active=False, closed=False, **opts):
1237 def branches(ui, repo, active=False, closed=False, **opts):
1238 """list repository named branches
1238 """list repository named branches
1239
1239
1240 List the repository's named branches, indicating which ones are
1240 List the repository's named branches, indicating which ones are
1241 inactive. If -c/--closed is specified, also list branches which have
1241 inactive. If -c/--closed is specified, also list branches which have
1242 been marked closed (see :hg:`commit --close-branch`).
1242 been marked closed (see :hg:`commit --close-branch`).
1243
1243
1244 Use the command :hg:`update` to switch to an existing branch.
1244 Use the command :hg:`update` to switch to an existing branch.
1245
1245
1246 Returns 0.
1246 Returns 0.
1247 """
1247 """
1248
1248
1249 fm = ui.formatter('branches', opts)
1249 fm = ui.formatter('branches', opts)
1250 hexfunc = fm.hexfunc
1250 hexfunc = fm.hexfunc
1251
1251
1252 allheads = set(repo.heads())
1252 allheads = set(repo.heads())
1253 branches = []
1253 branches = []
1254 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1254 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1255 isactive = not isclosed and bool(set(heads) & allheads)
1255 isactive = not isclosed and bool(set(heads) & allheads)
1256 branches.append((tag, repo[tip], isactive, not isclosed))
1256 branches.append((tag, repo[tip], isactive, not isclosed))
1257 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1257 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1258 reverse=True)
1258 reverse=True)
1259
1259
1260 for tag, ctx, isactive, isopen in branches:
1260 for tag, ctx, isactive, isopen in branches:
1261 if active and not isactive:
1261 if active and not isactive:
1262 continue
1262 continue
1263 if isactive:
1263 if isactive:
1264 label = 'branches.active'
1264 label = 'branches.active'
1265 notice = ''
1265 notice = ''
1266 elif not isopen:
1266 elif not isopen:
1267 if not closed:
1267 if not closed:
1268 continue
1268 continue
1269 label = 'branches.closed'
1269 label = 'branches.closed'
1270 notice = _(' (closed)')
1270 notice = _(' (closed)')
1271 else:
1271 else:
1272 label = 'branches.inactive'
1272 label = 'branches.inactive'
1273 notice = _(' (inactive)')
1273 notice = _(' (inactive)')
1274 current = (tag == repo.dirstate.branch())
1274 current = (tag == repo.dirstate.branch())
1275 if current:
1275 if current:
1276 label = 'branches.current'
1276 label = 'branches.current'
1277
1277
1278 fm.startitem()
1278 fm.startitem()
1279 fm.write('branch', '%s', tag, label=label)
1279 fm.write('branch', '%s', tag, label=label)
1280 rev = ctx.rev()
1280 rev = ctx.rev()
1281 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1281 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1282 fmt = ' ' * padsize + ' %d:%s'
1282 fmt = ' ' * padsize + ' %d:%s'
1283 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1283 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1284 label='log.changeset changeset.%s' % ctx.phasestr())
1284 label='log.changeset changeset.%s' % ctx.phasestr())
1285 fm.data(active=isactive, closed=not isopen, current=current)
1285 fm.data(active=isactive, closed=not isopen, current=current)
1286 if not ui.quiet:
1286 if not ui.quiet:
1287 fm.plain(notice)
1287 fm.plain(notice)
1288 fm.plain('\n')
1288 fm.plain('\n')
1289 fm.end()
1289 fm.end()
1290
1290
1291 @command('bundle',
1291 @command('bundle',
1292 [('f', 'force', None, _('run even when the destination is unrelated')),
1292 [('f', 'force', None, _('run even when the destination is unrelated')),
1293 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1293 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1294 _('REV')),
1294 _('REV')),
1295 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1295 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1296 _('BRANCH')),
1296 _('BRANCH')),
1297 ('', 'base', [],
1297 ('', 'base', [],
1298 _('a base changeset assumed to be available at the destination'),
1298 _('a base changeset assumed to be available at the destination'),
1299 _('REV')),
1299 _('REV')),
1300 ('a', 'all', None, _('bundle all changesets in the repository')),
1300 ('a', 'all', None, _('bundle all changesets in the repository')),
1301 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1301 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1302 ] + remoteopts,
1302 ] + remoteopts,
1303 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1303 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1304 def bundle(ui, repo, fname, dest=None, **opts):
1304 def bundle(ui, repo, fname, dest=None, **opts):
1305 """create a changegroup file
1305 """create a changegroup file
1306
1306
1307 Generate a changegroup file collecting changesets to be added
1307 Generate a changegroup file collecting changesets to be added
1308 to a repository.
1308 to a repository.
1309
1309
1310 To create a bundle containing all changesets, use -a/--all
1310 To create a bundle containing all changesets, use -a/--all
1311 (or --base null). Otherwise, hg assumes the destination will have
1311 (or --base null). Otherwise, hg assumes the destination will have
1312 all the nodes you specify with --base parameters. Otherwise, hg
1312 all the nodes you specify with --base parameters. Otherwise, hg
1313 will assume the repository has all the nodes in destination, or
1313 will assume the repository has all the nodes in destination, or
1314 default-push/default if no destination is specified.
1314 default-push/default if no destination is specified.
1315
1315
1316 You can change bundle format with the -t/--type option. You can
1316 You can change bundle format with the -t/--type option. You can
1317 specify a compression, a bundle version or both using a dash
1317 specify a compression, a bundle version or both using a dash
1318 (comp-version). The available compression methods are: none, bzip2,
1318 (comp-version). The available compression methods are: none, bzip2,
1319 and gzip (by default, bundles are compressed using bzip2). The
1319 and gzip (by default, bundles are compressed using bzip2). The
1320 available formats are: v1, v2 (default to most suitable).
1320 available formats are: v1, v2 (default to most suitable).
1321
1321
1322 The bundle file can then be transferred using conventional means
1322 The bundle file can then be transferred using conventional means
1323 and applied to another repository with the unbundle or pull
1323 and applied to another repository with the unbundle or pull
1324 command. This is useful when direct push and pull are not
1324 command. This is useful when direct push and pull are not
1325 available or when exporting an entire repository is undesirable.
1325 available or when exporting an entire repository is undesirable.
1326
1326
1327 Applying bundles preserves all changeset contents including
1327 Applying bundles preserves all changeset contents including
1328 permissions, copy/rename information, and revision history.
1328 permissions, copy/rename information, and revision history.
1329
1329
1330 Returns 0 on success, 1 if no changes found.
1330 Returns 0 on success, 1 if no changes found.
1331 """
1331 """
1332 revs = None
1332 revs = None
1333 if 'rev' in opts:
1333 if 'rev' in opts:
1334 revs = scmutil.revrange(repo, opts['rev'])
1334 revs = scmutil.revrange(repo, opts['rev'])
1335
1335
1336 bundletype = opts.get('type', 'bzip2').lower()
1336 bundletype = opts.get('type', 'bzip2').lower()
1337 try:
1337 try:
1338 bcompression, cgversion, params = exchange.parsebundlespec(
1338 bcompression, cgversion, params = exchange.parsebundlespec(
1339 repo, bundletype, strict=False)
1339 repo, bundletype, strict=False)
1340 except error.UnsupportedBundleSpecification as e:
1340 except error.UnsupportedBundleSpecification as e:
1341 raise error.Abort(str(e),
1341 raise error.Abort(str(e),
1342 hint=_('see "hg help bundle" for supported '
1342 hint=_('see "hg help bundle" for supported '
1343 'values for --type'))
1343 'values for --type'))
1344
1344
1345 # Packed bundles are a pseudo bundle format for now.
1345 # Packed bundles are a pseudo bundle format for now.
1346 if cgversion == 's1':
1346 if cgversion == 's1':
1347 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1347 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1348 hint=_('use "hg debugcreatestreamclonebundle"'))
1348 hint=_('use "hg debugcreatestreamclonebundle"'))
1349
1349
1350 if opts.get('all'):
1350 if opts.get('all'):
1351 if dest:
1351 if dest:
1352 raise error.Abort(_("--all is incompatible with specifying "
1352 raise error.Abort(_("--all is incompatible with specifying "
1353 "a destination"))
1353 "a destination"))
1354 if opts.get('base'):
1354 if opts.get('base'):
1355 ui.warn(_("ignoring --base because --all was specified\n"))
1355 ui.warn(_("ignoring --base because --all was specified\n"))
1356 base = ['null']
1356 base = ['null']
1357 else:
1357 else:
1358 base = scmutil.revrange(repo, opts.get('base'))
1358 base = scmutil.revrange(repo, opts.get('base'))
1359 # TODO: get desired bundlecaps from command line.
1359 # TODO: get desired bundlecaps from command line.
1360 bundlecaps = None
1360 bundlecaps = None
1361 if base:
1361 if base:
1362 if dest:
1362 if dest:
1363 raise error.Abort(_("--base is incompatible with specifying "
1363 raise error.Abort(_("--base is incompatible with specifying "
1364 "a destination"))
1364 "a destination"))
1365 common = [repo.lookup(rev) for rev in base]
1365 common = [repo.lookup(rev) for rev in base]
1366 heads = revs and map(repo.lookup, revs) or revs
1366 heads = revs and map(repo.lookup, revs) or revs
1367 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1367 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1368 common=common, bundlecaps=bundlecaps,
1368 common=common, bundlecaps=bundlecaps,
1369 version=cgversion)
1369 version=cgversion)
1370 outgoing = None
1370 outgoing = None
1371 else:
1371 else:
1372 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1372 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1373 dest, branches = hg.parseurl(dest, opts.get('branch'))
1373 dest, branches = hg.parseurl(dest, opts.get('branch'))
1374 other = hg.peer(repo, opts, dest)
1374 other = hg.peer(repo, opts, dest)
1375 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1375 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1376 heads = revs and map(repo.lookup, revs) or revs
1376 heads = revs and map(repo.lookup, revs) or revs
1377 outgoing = discovery.findcommonoutgoing(repo, other,
1377 outgoing = discovery.findcommonoutgoing(repo, other,
1378 onlyheads=heads,
1378 onlyheads=heads,
1379 force=opts.get('force'),
1379 force=opts.get('force'),
1380 portable=True)
1380 portable=True)
1381 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1381 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1382 bundlecaps, version=cgversion)
1382 bundlecaps, version=cgversion)
1383 if not cg:
1383 if not cg:
1384 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1384 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1385 return 1
1385 return 1
1386
1386
1387 if cgversion == '01': #bundle1
1387 if cgversion == '01': #bundle1
1388 if bcompression is None:
1388 if bcompression is None:
1389 bcompression = 'UN'
1389 bcompression = 'UN'
1390 bversion = 'HG10' + bcompression
1390 bversion = 'HG10' + bcompression
1391 bcompression = None
1391 bcompression = None
1392 else:
1392 else:
1393 assert cgversion == '02'
1393 assert cgversion == '02'
1394 bversion = 'HG20'
1394 bversion = 'HG20'
1395
1395
1396
1396
1397 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1397 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1398
1398
1399 @command('cat',
1399 @command('cat',
1400 [('o', 'output', '',
1400 [('o', 'output', '',
1401 _('print output to file with formatted name'), _('FORMAT')),
1401 _('print output to file with formatted name'), _('FORMAT')),
1402 ('r', 'rev', '', _('print the given revision'), _('REV')),
1402 ('r', 'rev', '', _('print the given revision'), _('REV')),
1403 ('', 'decode', None, _('apply any matching decode filter')),
1403 ('', 'decode', None, _('apply any matching decode filter')),
1404 ] + walkopts,
1404 ] + walkopts,
1405 _('[OPTION]... FILE...'),
1405 _('[OPTION]... FILE...'),
1406 inferrepo=True)
1406 inferrepo=True)
1407 def cat(ui, repo, file1, *pats, **opts):
1407 def cat(ui, repo, file1, *pats, **opts):
1408 """output the current or given revision of files
1408 """output the current or given revision of files
1409
1409
1410 Print the specified files as they were at the given revision. If
1410 Print the specified files as they were at the given revision. If
1411 no revision is given, the parent of the working directory is used.
1411 no revision is given, the parent of the working directory is used.
1412
1412
1413 Output may be to a file, in which case the name of the file is
1413 Output may be to a file, in which case the name of the file is
1414 given using a format string. The formatting rules as follows:
1414 given using a format string. The formatting rules as follows:
1415
1415
1416 :``%%``: literal "%" character
1416 :``%%``: literal "%" character
1417 :``%s``: basename of file being printed
1417 :``%s``: basename of file being printed
1418 :``%d``: dirname of file being printed, or '.' if in repository root
1418 :``%d``: dirname of file being printed, or '.' if in repository root
1419 :``%p``: root-relative path name of file being printed
1419 :``%p``: root-relative path name of file being printed
1420 :``%H``: changeset hash (40 hexadecimal digits)
1420 :``%H``: changeset hash (40 hexadecimal digits)
1421 :``%R``: changeset revision number
1421 :``%R``: changeset revision number
1422 :``%h``: short-form changeset hash (12 hexadecimal digits)
1422 :``%h``: short-form changeset hash (12 hexadecimal digits)
1423 :``%r``: zero-padded changeset revision number
1423 :``%r``: zero-padded changeset revision number
1424 :``%b``: basename of the exporting repository
1424 :``%b``: basename of the exporting repository
1425
1425
1426 Returns 0 on success.
1426 Returns 0 on success.
1427 """
1427 """
1428 ctx = scmutil.revsingle(repo, opts.get('rev'))
1428 ctx = scmutil.revsingle(repo, opts.get('rev'))
1429 m = scmutil.match(ctx, (file1,) + pats, opts)
1429 m = scmutil.match(ctx, (file1,) + pats, opts)
1430
1430
1431 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1431 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1432
1432
1433 @command('^clone',
1433 @command('^clone',
1434 [('U', 'noupdate', None, _('the clone will include an empty working '
1434 [('U', 'noupdate', None, _('the clone will include an empty working '
1435 'directory (only a repository)')),
1435 'directory (only a repository)')),
1436 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1436 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1437 _('REV')),
1437 _('REV')),
1438 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1438 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1439 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1439 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1440 ('', 'pull', None, _('use pull protocol to copy metadata')),
1440 ('', 'pull', None, _('use pull protocol to copy metadata')),
1441 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1441 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1442 ] + remoteopts,
1442 ] + remoteopts,
1443 _('[OPTION]... SOURCE [DEST]'),
1443 _('[OPTION]... SOURCE [DEST]'),
1444 norepo=True)
1444 norepo=True)
1445 def clone(ui, source, dest=None, **opts):
1445 def clone(ui, source, dest=None, **opts):
1446 """make a copy of an existing repository
1446 """make a copy of an existing repository
1447
1447
1448 Create a copy of an existing repository in a new directory.
1448 Create a copy of an existing repository in a new directory.
1449
1449
1450 If no destination directory name is specified, it defaults to the
1450 If no destination directory name is specified, it defaults to the
1451 basename of the source.
1451 basename of the source.
1452
1452
1453 The location of the source is added to the new repository's
1453 The location of the source is added to the new repository's
1454 ``.hg/hgrc`` file, as the default to be used for future pulls.
1454 ``.hg/hgrc`` file, as the default to be used for future pulls.
1455
1455
1456 Only local paths and ``ssh://`` URLs are supported as
1456 Only local paths and ``ssh://`` URLs are supported as
1457 destinations. For ``ssh://`` destinations, no working directory or
1457 destinations. For ``ssh://`` destinations, no working directory or
1458 ``.hg/hgrc`` will be created on the remote side.
1458 ``.hg/hgrc`` will be created on the remote side.
1459
1459
1460 To pull only a subset of changesets, specify one or more revisions
1460 To pull only a subset of changesets, specify one or more revisions
1461 identifiers with -r/--rev or branches with -b/--branch. The
1461 identifiers with -r/--rev or branches with -b/--branch. The
1462 resulting clone will contain only the specified changesets and
1462 resulting clone will contain only the specified changesets and
1463 their ancestors. These options (or 'clone src#rev dest') imply
1463 their ancestors. These options (or 'clone src#rev dest') imply
1464 --pull, even for local source repositories.
1464 --pull, even for local source repositories.
1465
1465
1466 .. note::
1466 .. note::
1467
1467
1468 Specifying a tag will include the tagged changeset but not the
1468 Specifying a tag will include the tagged changeset but not the
1469 changeset containing the tag.
1469 changeset containing the tag.
1470
1470
1471 If the source repository has a bookmark called '@' set, that
1471 If the source repository has a bookmark called '@' set, that
1472 revision will be checked out in the new repository by default.
1472 revision will be checked out in the new repository by default.
1473
1473
1474 To check out a particular version, use -u/--update, or
1474 To check out a particular version, use -u/--update, or
1475 -U/--noupdate to create a clone with no working directory.
1475 -U/--noupdate to create a clone with no working directory.
1476
1476
1477 .. container:: verbose
1477 .. container:: verbose
1478
1478
1479 For efficiency, hardlinks are used for cloning whenever the
1479 For efficiency, hardlinks are used for cloning whenever the
1480 source and destination are on the same filesystem (note this
1480 source and destination are on the same filesystem (note this
1481 applies only to the repository data, not to the working
1481 applies only to the repository data, not to the working
1482 directory). Some filesystems, such as AFS, implement hardlinking
1482 directory). Some filesystems, such as AFS, implement hardlinking
1483 incorrectly, but do not report errors. In these cases, use the
1483 incorrectly, but do not report errors. In these cases, use the
1484 --pull option to avoid hardlinking.
1484 --pull option to avoid hardlinking.
1485
1485
1486 In some cases, you can clone repositories and the working
1486 In some cases, you can clone repositories and the working
1487 directory using full hardlinks with ::
1487 directory using full hardlinks with ::
1488
1488
1489 $ cp -al REPO REPOCLONE
1489 $ cp -al REPO REPOCLONE
1490
1490
1491 This is the fastest way to clone, but it is not always safe. The
1491 This is the fastest way to clone, but it is not always safe. The
1492 operation is not atomic (making sure REPO is not modified during
1492 operation is not atomic (making sure REPO is not modified during
1493 the operation is up to you) and you have to make sure your
1493 the operation is up to you) and you have to make sure your
1494 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1494 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1495 so). Also, this is not compatible with certain extensions that
1495 so). Also, this is not compatible with certain extensions that
1496 place their metadata under the .hg directory, such as mq.
1496 place their metadata under the .hg directory, such as mq.
1497
1497
1498 Mercurial will update the working directory to the first applicable
1498 Mercurial will update the working directory to the first applicable
1499 revision from this list:
1499 revision from this list:
1500
1500
1501 a) null if -U or the source repository has no changesets
1501 a) null if -U or the source repository has no changesets
1502 b) if -u . and the source repository is local, the first parent of
1502 b) if -u . and the source repository is local, the first parent of
1503 the source repository's working directory
1503 the source repository's working directory
1504 c) the changeset specified with -u (if a branch name, this means the
1504 c) the changeset specified with -u (if a branch name, this means the
1505 latest head of that branch)
1505 latest head of that branch)
1506 d) the changeset specified with -r
1506 d) the changeset specified with -r
1507 e) the tipmost head specified with -b
1507 e) the tipmost head specified with -b
1508 f) the tipmost head specified with the url#branch source syntax
1508 f) the tipmost head specified with the url#branch source syntax
1509 g) the revision marked with the '@' bookmark, if present
1509 g) the revision marked with the '@' bookmark, if present
1510 h) the tipmost head of the default branch
1510 h) the tipmost head of the default branch
1511 i) tip
1511 i) tip
1512
1512
1513 Examples:
1513 Examples:
1514
1514
1515 - clone a remote repository to a new directory named hg/::
1515 - clone a remote repository to a new directory named hg/::
1516
1516
1517 hg clone http://selenic.com/hg
1517 hg clone http://selenic.com/hg
1518
1518
1519 - create a lightweight local clone::
1519 - create a lightweight local clone::
1520
1520
1521 hg clone project/ project-feature/
1521 hg clone project/ project-feature/
1522
1522
1523 - clone from an absolute path on an ssh server (note double-slash)::
1523 - clone from an absolute path on an ssh server (note double-slash)::
1524
1524
1525 hg clone ssh://user@server//home/projects/alpha/
1525 hg clone ssh://user@server//home/projects/alpha/
1526
1526
1527 - do a high-speed clone over a LAN while checking out a
1527 - do a high-speed clone over a LAN while checking out a
1528 specified version::
1528 specified version::
1529
1529
1530 hg clone --uncompressed http://server/repo -u 1.5
1530 hg clone --uncompressed http://server/repo -u 1.5
1531
1531
1532 - create a repository without changesets after a particular revision::
1532 - create a repository without changesets after a particular revision::
1533
1533
1534 hg clone -r 04e544 experimental/ good/
1534 hg clone -r 04e544 experimental/ good/
1535
1535
1536 - clone (and track) a particular named branch::
1536 - clone (and track) a particular named branch::
1537
1537
1538 hg clone http://selenic.com/hg#stable
1538 hg clone http://selenic.com/hg#stable
1539
1539
1540 See :hg:`help urls` for details on specifying URLs.
1540 See :hg:`help urls` for details on specifying URLs.
1541
1541
1542 Returns 0 on success.
1542 Returns 0 on success.
1543 """
1543 """
1544 if opts.get('noupdate') and opts.get('updaterev'):
1544 if opts.get('noupdate') and opts.get('updaterev'):
1545 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1545 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1546
1546
1547 r = hg.clone(ui, opts, source, dest,
1547 r = hg.clone(ui, opts, source, dest,
1548 pull=opts.get('pull'),
1548 pull=opts.get('pull'),
1549 stream=opts.get('uncompressed'),
1549 stream=opts.get('uncompressed'),
1550 rev=opts.get('rev'),
1550 rev=opts.get('rev'),
1551 update=opts.get('updaterev') or not opts.get('noupdate'),
1551 update=opts.get('updaterev') or not opts.get('noupdate'),
1552 branch=opts.get('branch'),
1552 branch=opts.get('branch'),
1553 shareopts=opts.get('shareopts'))
1553 shareopts=opts.get('shareopts'))
1554
1554
1555 return r is None
1555 return r is None
1556
1556
1557 @command('^commit|ci',
1557 @command('^commit|ci',
1558 [('A', 'addremove', None,
1558 [('A', 'addremove', None,
1559 _('mark new/missing files as added/removed before committing')),
1559 _('mark new/missing files as added/removed before committing')),
1560 ('', 'close-branch', None,
1560 ('', 'close-branch', None,
1561 _('mark a branch head as closed')),
1561 _('mark a branch head as closed')),
1562 ('', 'amend', None, _('amend the parent of the working directory')),
1562 ('', 'amend', None, _('amend the parent of the working directory')),
1563 ('s', 'secret', None, _('use the secret phase for committing')),
1563 ('s', 'secret', None, _('use the secret phase for committing')),
1564 ('e', 'edit', None, _('invoke editor on commit messages')),
1564 ('e', 'edit', None, _('invoke editor on commit messages')),
1565 ('i', 'interactive', None, _('use interactive mode')),
1565 ('i', 'interactive', None, _('use interactive mode')),
1566 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1566 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1567 _('[OPTION]... [FILE]...'),
1567 _('[OPTION]... [FILE]...'),
1568 inferrepo=True)
1568 inferrepo=True)
1569 def commit(ui, repo, *pats, **opts):
1569 def commit(ui, repo, *pats, **opts):
1570 """commit the specified files or all outstanding changes
1570 """commit the specified files or all outstanding changes
1571
1571
1572 Commit changes to the given files into the repository. Unlike a
1572 Commit changes to the given files into the repository. Unlike a
1573 centralized SCM, this operation is a local operation. See
1573 centralized SCM, this operation is a local operation. See
1574 :hg:`push` for a way to actively distribute your changes.
1574 :hg:`push` for a way to actively distribute your changes.
1575
1575
1576 If a list of files is omitted, all changes reported by :hg:`status`
1576 If a list of files is omitted, all changes reported by :hg:`status`
1577 will be committed.
1577 will be committed.
1578
1578
1579 If you are committing the result of a merge, do not provide any
1579 If you are committing the result of a merge, do not provide any
1580 filenames or -I/-X filters.
1580 filenames or -I/-X filters.
1581
1581
1582 If no commit message is specified, Mercurial starts your
1582 If no commit message is specified, Mercurial starts your
1583 configured editor where you can enter a message. In case your
1583 configured editor where you can enter a message. In case your
1584 commit fails, you will find a backup of your message in
1584 commit fails, you will find a backup of your message in
1585 ``.hg/last-message.txt``.
1585 ``.hg/last-message.txt``.
1586
1586
1587 The --close-branch flag can be used to mark the current branch
1587 The --close-branch flag can be used to mark the current branch
1588 head closed. When all heads of a branch are closed, the branch
1588 head closed. When all heads of a branch are closed, the branch
1589 will be considered closed and no longer listed.
1589 will be considered closed and no longer listed.
1590
1590
1591 The --amend flag can be used to amend the parent of the
1591 The --amend flag can be used to amend the parent of the
1592 working directory with a new commit that contains the changes
1592 working directory with a new commit that contains the changes
1593 in the parent in addition to those currently reported by :hg:`status`,
1593 in the parent in addition to those currently reported by :hg:`status`,
1594 if there are any. The old commit is stored in a backup bundle in
1594 if there are any. The old commit is stored in a backup bundle in
1595 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1595 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1596 on how to restore it).
1596 on how to restore it).
1597
1597
1598 Message, user and date are taken from the amended commit unless
1598 Message, user and date are taken from the amended commit unless
1599 specified. When a message isn't specified on the command line,
1599 specified. When a message isn't specified on the command line,
1600 the editor will open with the message of the amended commit.
1600 the editor will open with the message of the amended commit.
1601
1601
1602 It is not possible to amend public changesets (see :hg:`help phases`)
1602 It is not possible to amend public changesets (see :hg:`help phases`)
1603 or changesets that have children.
1603 or changesets that have children.
1604
1604
1605 See :hg:`help dates` for a list of formats valid for -d/--date.
1605 See :hg:`help dates` for a list of formats valid for -d/--date.
1606
1606
1607 Returns 0 on success, 1 if nothing changed.
1607 Returns 0 on success, 1 if nothing changed.
1608
1608
1609 .. container:: verbose
1609 .. container:: verbose
1610
1610
1611 Examples:
1611 Examples:
1612
1612
1613 - commit all files ending in .py::
1613 - commit all files ending in .py::
1614
1614
1615 hg commit --include "set:**.py"
1615 hg commit --include "set:**.py"
1616
1616
1617 - commit all non-binary files::
1617 - commit all non-binary files::
1618
1618
1619 hg commit --exclude "set:binary()"
1619 hg commit --exclude "set:binary()"
1620
1620
1621 - amend the current commit and set the date to now::
1621 - amend the current commit and set the date to now::
1622
1622
1623 hg commit --amend --date now
1623 hg commit --amend --date now
1624 """
1624 """
1625 wlock = lock = None
1625 wlock = lock = None
1626 try:
1626 try:
1627 wlock = repo.wlock()
1627 wlock = repo.wlock()
1628 lock = repo.lock()
1628 lock = repo.lock()
1629 return _docommit(ui, repo, *pats, **opts)
1629 return _docommit(ui, repo, *pats, **opts)
1630 finally:
1630 finally:
1631 release(lock, wlock)
1631 release(lock, wlock)
1632
1632
1633 def _docommit(ui, repo, *pats, **opts):
1633 def _docommit(ui, repo, *pats, **opts):
1634 if opts.get('interactive'):
1634 if opts.get('interactive'):
1635 opts.pop('interactive')
1635 opts.pop('interactive')
1636 cmdutil.dorecord(ui, repo, commit, None, False,
1636 cmdutil.dorecord(ui, repo, commit, None, False,
1637 cmdutil.recordfilter, *pats, **opts)
1637 cmdutil.recordfilter, *pats, **opts)
1638 return
1638 return
1639
1639
1640 if opts.get('subrepos'):
1640 if opts.get('subrepos'):
1641 if opts.get('amend'):
1641 if opts.get('amend'):
1642 raise error.Abort(_('cannot amend with --subrepos'))
1642 raise error.Abort(_('cannot amend with --subrepos'))
1643 # Let --subrepos on the command line override config setting.
1643 # Let --subrepos on the command line override config setting.
1644 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1644 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1645
1645
1646 cmdutil.checkunfinished(repo, commit=True)
1646 cmdutil.checkunfinished(repo, commit=True)
1647
1647
1648 branch = repo[None].branch()
1648 branch = repo[None].branch()
1649 bheads = repo.branchheads(branch)
1649 bheads = repo.branchheads(branch)
1650
1650
1651 extra = {}
1651 extra = {}
1652 if opts.get('close_branch'):
1652 if opts.get('close_branch'):
1653 extra['close'] = 1
1653 extra['close'] = 1
1654
1654
1655 if not bheads:
1655 if not bheads:
1656 raise error.Abort(_('can only close branch heads'))
1656 raise error.Abort(_('can only close branch heads'))
1657 elif opts.get('amend'):
1657 elif opts.get('amend'):
1658 if repo[None].parents()[0].p1().branch() != branch and \
1658 if repo[None].parents()[0].p1().branch() != branch and \
1659 repo[None].parents()[0].p2().branch() != branch:
1659 repo[None].parents()[0].p2().branch() != branch:
1660 raise error.Abort(_('can only close branch heads'))
1660 raise error.Abort(_('can only close branch heads'))
1661
1661
1662 if opts.get('amend'):
1662 if opts.get('amend'):
1663 if ui.configbool('ui', 'commitsubrepos'):
1663 if ui.configbool('ui', 'commitsubrepos'):
1664 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1664 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1665
1665
1666 old = repo['.']
1666 old = repo['.']
1667 if not old.mutable():
1667 if not old.mutable():
1668 raise error.Abort(_('cannot amend public changesets'))
1668 raise error.Abort(_('cannot amend public changesets'))
1669 if len(repo[None].parents()) > 1:
1669 if len(repo[None].parents()) > 1:
1670 raise error.Abort(_('cannot amend while merging'))
1670 raise error.Abort(_('cannot amend while merging'))
1671 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1671 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1672 if not allowunstable and old.children():
1672 if not allowunstable and old.children():
1673 raise error.Abort(_('cannot amend changeset with children'))
1673 raise error.Abort(_('cannot amend changeset with children'))
1674
1674
1675 newextra = extra.copy()
1675 newextra = extra.copy()
1676 newextra['branch'] = branch
1676 newextra['branch'] = branch
1677 extra = newextra
1677 extra = newextra
1678 # commitfunc is used only for temporary amend commit by cmdutil.amend
1678 # commitfunc is used only for temporary amend commit by cmdutil.amend
1679 def commitfunc(ui, repo, message, match, opts):
1679 def commitfunc(ui, repo, message, match, opts):
1680 return repo.commit(message,
1680 return repo.commit(message,
1681 opts.get('user') or old.user(),
1681 opts.get('user') or old.user(),
1682 opts.get('date') or old.date(),
1682 opts.get('date') or old.date(),
1683 match,
1683 match,
1684 extra=extra)
1684 extra=extra)
1685
1685
1686 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1686 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1687 if node == old.node():
1687 if node == old.node():
1688 ui.status(_("nothing changed\n"))
1688 ui.status(_("nothing changed\n"))
1689 return 1
1689 return 1
1690 else:
1690 else:
1691 def commitfunc(ui, repo, message, match, opts):
1691 def commitfunc(ui, repo, message, match, opts):
1692 backup = ui.backupconfig('phases', 'new-commit')
1692 backup = ui.backupconfig('phases', 'new-commit')
1693 baseui = repo.baseui
1693 baseui = repo.baseui
1694 basebackup = baseui.backupconfig('phases', 'new-commit')
1694 basebackup = baseui.backupconfig('phases', 'new-commit')
1695 try:
1695 try:
1696 if opts.get('secret'):
1696 if opts.get('secret'):
1697 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1697 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1698 # Propagate to subrepos
1698 # Propagate to subrepos
1699 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1699 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1700
1700
1701 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1701 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1702 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1702 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1703 return repo.commit(message, opts.get('user'), opts.get('date'),
1703 return repo.commit(message, opts.get('user'), opts.get('date'),
1704 match,
1704 match,
1705 editor=editor,
1705 editor=editor,
1706 extra=extra)
1706 extra=extra)
1707 finally:
1707 finally:
1708 ui.restoreconfig(backup)
1708 ui.restoreconfig(backup)
1709 repo.baseui.restoreconfig(basebackup)
1709 repo.baseui.restoreconfig(basebackup)
1710
1710
1711
1711
1712 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1712 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1713
1713
1714 if not node:
1714 if not node:
1715 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1715 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1716 if stat[3]:
1716 if stat[3]:
1717 ui.status(_("nothing changed (%d missing files, see "
1717 ui.status(_("nothing changed (%d missing files, see "
1718 "'hg status')\n") % len(stat[3]))
1718 "'hg status')\n") % len(stat[3]))
1719 else:
1719 else:
1720 ui.status(_("nothing changed\n"))
1720 ui.status(_("nothing changed\n"))
1721 return 1
1721 return 1
1722
1722
1723 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1723 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1724
1724
1725 @command('config|showconfig|debugconfig',
1725 @command('config|showconfig|debugconfig',
1726 [('u', 'untrusted', None, _('show untrusted configuration options')),
1726 [('u', 'untrusted', None, _('show untrusted configuration options')),
1727 ('e', 'edit', None, _('edit user config')),
1727 ('e', 'edit', None, _('edit user config')),
1728 ('l', 'local', None, _('edit repository config')),
1728 ('l', 'local', None, _('edit repository config')),
1729 ('g', 'global', None, _('edit global config'))],
1729 ('g', 'global', None, _('edit global config'))],
1730 _('[-u] [NAME]...'),
1730 _('[-u] [NAME]...'),
1731 optionalrepo=True)
1731 optionalrepo=True)
1732 def config(ui, repo, *values, **opts):
1732 def config(ui, repo, *values, **opts):
1733 """show combined config settings from all hgrc files
1733 """show combined config settings from all hgrc files
1734
1734
1735 With no arguments, print names and values of all config items.
1735 With no arguments, print names and values of all config items.
1736
1736
1737 With one argument of the form section.name, print just the value
1737 With one argument of the form section.name, print just the value
1738 of that config item.
1738 of that config item.
1739
1739
1740 With multiple arguments, print names and values of all config
1740 With multiple arguments, print names and values of all config
1741 items with matching section names.
1741 items with matching section names.
1742
1742
1743 With --edit, start an editor on the user-level config file. With
1743 With --edit, start an editor on the user-level config file. With
1744 --global, edit the system-wide config file. With --local, edit the
1744 --global, edit the system-wide config file. With --local, edit the
1745 repository-level config file.
1745 repository-level config file.
1746
1746
1747 With --debug, the source (filename and line number) is printed
1747 With --debug, the source (filename and line number) is printed
1748 for each config item.
1748 for each config item.
1749
1749
1750 See :hg:`help config` for more information about config files.
1750 See :hg:`help config` for more information about config files.
1751
1751
1752 Returns 0 on success, 1 if NAME does not exist.
1752 Returns 0 on success, 1 if NAME does not exist.
1753
1753
1754 """
1754 """
1755
1755
1756 if opts.get('edit') or opts.get('local') or opts.get('global'):
1756 if opts.get('edit') or opts.get('local') or opts.get('global'):
1757 if opts.get('local') and opts.get('global'):
1757 if opts.get('local') and opts.get('global'):
1758 raise error.Abort(_("can't use --local and --global together"))
1758 raise error.Abort(_("can't use --local and --global together"))
1759
1759
1760 if opts.get('local'):
1760 if opts.get('local'):
1761 if not repo:
1761 if not repo:
1762 raise error.Abort(_("can't use --local outside a repository"))
1762 raise error.Abort(_("can't use --local outside a repository"))
1763 paths = [repo.join('hgrc')]
1763 paths = [repo.join('hgrc')]
1764 elif opts.get('global'):
1764 elif opts.get('global'):
1765 paths = scmutil.systemrcpath()
1765 paths = scmutil.systemrcpath()
1766 else:
1766 else:
1767 paths = scmutil.userrcpath()
1767 paths = scmutil.userrcpath()
1768
1768
1769 for f in paths:
1769 for f in paths:
1770 if os.path.exists(f):
1770 if os.path.exists(f):
1771 break
1771 break
1772 else:
1772 else:
1773 if opts.get('global'):
1773 if opts.get('global'):
1774 samplehgrc = uimod.samplehgrcs['global']
1774 samplehgrc = uimod.samplehgrcs['global']
1775 elif opts.get('local'):
1775 elif opts.get('local'):
1776 samplehgrc = uimod.samplehgrcs['local']
1776 samplehgrc = uimod.samplehgrcs['local']
1777 else:
1777 else:
1778 samplehgrc = uimod.samplehgrcs['user']
1778 samplehgrc = uimod.samplehgrcs['user']
1779
1779
1780 f = paths[0]
1780 f = paths[0]
1781 fp = open(f, "w")
1781 fp = open(f, "w")
1782 fp.write(samplehgrc)
1782 fp.write(samplehgrc)
1783 fp.close()
1783 fp.close()
1784
1784
1785 editor = ui.geteditor()
1785 editor = ui.geteditor()
1786 ui.system("%s \"%s\"" % (editor, f),
1786 ui.system("%s \"%s\"" % (editor, f),
1787 onerr=error.Abort, errprefix=_("edit failed"))
1787 onerr=error.Abort, errprefix=_("edit failed"))
1788 return
1788 return
1789
1789
1790 for f in scmutil.rcpath():
1790 for f in scmutil.rcpath():
1791 ui.debug('read config from: %s\n' % f)
1791 ui.debug('read config from: %s\n' % f)
1792 untrusted = bool(opts.get('untrusted'))
1792 untrusted = bool(opts.get('untrusted'))
1793 if values:
1793 if values:
1794 sections = [v for v in values if '.' not in v]
1794 sections = [v for v in values if '.' not in v]
1795 items = [v for v in values if '.' in v]
1795 items = [v for v in values if '.' in v]
1796 if len(items) > 1 or items and sections:
1796 if len(items) > 1 or items and sections:
1797 raise error.Abort(_('only one config item permitted'))
1797 raise error.Abort(_('only one config item permitted'))
1798 matched = False
1798 matched = False
1799 for section, name, value in ui.walkconfig(untrusted=untrusted):
1799 for section, name, value in ui.walkconfig(untrusted=untrusted):
1800 value = str(value).replace('\n', '\\n')
1800 value = str(value).replace('\n', '\\n')
1801 sectname = section + '.' + name
1801 sectname = section + '.' + name
1802 if values:
1802 if values:
1803 for v in values:
1803 for v in values:
1804 if v == section:
1804 if v == section:
1805 ui.debug('%s: ' %
1805 ui.debug('%s: ' %
1806 ui.configsource(section, name, untrusted))
1806 ui.configsource(section, name, untrusted))
1807 ui.write('%s=%s\n' % (sectname, value))
1807 ui.write('%s=%s\n' % (sectname, value))
1808 matched = True
1808 matched = True
1809 elif v == sectname:
1809 elif v == sectname:
1810 ui.debug('%s: ' %
1810 ui.debug('%s: ' %
1811 ui.configsource(section, name, untrusted))
1811 ui.configsource(section, name, untrusted))
1812 ui.write(value, '\n')
1812 ui.write(value, '\n')
1813 matched = True
1813 matched = True
1814 else:
1814 else:
1815 ui.debug('%s: ' %
1815 ui.debug('%s: ' %
1816 ui.configsource(section, name, untrusted))
1816 ui.configsource(section, name, untrusted))
1817 ui.write('%s=%s\n' % (sectname, value))
1817 ui.write('%s=%s\n' % (sectname, value))
1818 matched = True
1818 matched = True
1819 if matched:
1819 if matched:
1820 return 0
1820 return 0
1821 return 1
1821 return 1
1822
1822
1823 @command('copy|cp',
1823 @command('copy|cp',
1824 [('A', 'after', None, _('record a copy that has already occurred')),
1824 [('A', 'after', None, _('record a copy that has already occurred')),
1825 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1825 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1826 ] + walkopts + dryrunopts,
1826 ] + walkopts + dryrunopts,
1827 _('[OPTION]... [SOURCE]... DEST'))
1827 _('[OPTION]... [SOURCE]... DEST'))
1828 def copy(ui, repo, *pats, **opts):
1828 def copy(ui, repo, *pats, **opts):
1829 """mark files as copied for the next commit
1829 """mark files as copied for the next commit
1830
1830
1831 Mark dest as having copies of source files. If dest is a
1831 Mark dest as having copies of source files. If dest is a
1832 directory, copies are put in that directory. If dest is a file,
1832 directory, copies are put in that directory. If dest is a file,
1833 the source must be a single file.
1833 the source must be a single file.
1834
1834
1835 By default, this command copies the contents of files as they
1835 By default, this command copies the contents of files as they
1836 exist in the working directory. If invoked with -A/--after, the
1836 exist in the working directory. If invoked with -A/--after, the
1837 operation is recorded, but no copying is performed.
1837 operation is recorded, but no copying is performed.
1838
1838
1839 This command takes effect with the next commit. To undo a copy
1839 This command takes effect with the next commit. To undo a copy
1840 before that, see :hg:`revert`.
1840 before that, see :hg:`revert`.
1841
1841
1842 Returns 0 on success, 1 if errors are encountered.
1842 Returns 0 on success, 1 if errors are encountered.
1843 """
1843 """
1844 wlock = repo.wlock(False)
1844 wlock = repo.wlock(False)
1845 try:
1845 try:
1846 return cmdutil.copy(ui, repo, pats, opts)
1846 return cmdutil.copy(ui, repo, pats, opts)
1847 finally:
1847 finally:
1848 wlock.release()
1848 wlock.release()
1849
1849
1850 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1850 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1851 def debugancestor(ui, repo, *args):
1851 def debugancestor(ui, repo, *args):
1852 """find the ancestor revision of two revisions in a given index"""
1852 """find the ancestor revision of two revisions in a given index"""
1853 if len(args) == 3:
1853 if len(args) == 3:
1854 index, rev1, rev2 = args
1854 index, rev1, rev2 = args
1855 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1855 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1856 lookup = r.lookup
1856 lookup = r.lookup
1857 elif len(args) == 2:
1857 elif len(args) == 2:
1858 if not repo:
1858 if not repo:
1859 raise error.Abort(_("there is no Mercurial repository here "
1859 raise error.Abort(_("there is no Mercurial repository here "
1860 "(.hg not found)"))
1860 "(.hg not found)"))
1861 rev1, rev2 = args
1861 rev1, rev2 = args
1862 r = repo.changelog
1862 r = repo.changelog
1863 lookup = repo.lookup
1863 lookup = repo.lookup
1864 else:
1864 else:
1865 raise error.Abort(_('either two or three arguments required'))
1865 raise error.Abort(_('either two or three arguments required'))
1866 a = r.ancestor(lookup(rev1), lookup(rev2))
1866 a = r.ancestor(lookup(rev1), lookup(rev2))
1867 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1867 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1868
1868
1869 @command('debugbuilddag',
1869 @command('debugbuilddag',
1870 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1870 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1871 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1871 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1872 ('n', 'new-file', None, _('add new file at each rev'))],
1872 ('n', 'new-file', None, _('add new file at each rev'))],
1873 _('[OPTION]... [TEXT]'))
1873 _('[OPTION]... [TEXT]'))
1874 def debugbuilddag(ui, repo, text=None,
1874 def debugbuilddag(ui, repo, text=None,
1875 mergeable_file=False,
1875 mergeable_file=False,
1876 overwritten_file=False,
1876 overwritten_file=False,
1877 new_file=False):
1877 new_file=False):
1878 """builds a repo with a given DAG from scratch in the current empty repo
1878 """builds a repo with a given DAG from scratch in the current empty repo
1879
1879
1880 The description of the DAG is read from stdin if not given on the
1880 The description of the DAG is read from stdin if not given on the
1881 command line.
1881 command line.
1882
1882
1883 Elements:
1883 Elements:
1884
1884
1885 - "+n" is a linear run of n nodes based on the current default parent
1885 - "+n" is a linear run of n nodes based on the current default parent
1886 - "." is a single node based on the current default parent
1886 - "." is a single node based on the current default parent
1887 - "$" resets the default parent to null (implied at the start);
1887 - "$" resets the default parent to null (implied at the start);
1888 otherwise the default parent is always the last node created
1888 otherwise the default parent is always the last node created
1889 - "<p" sets the default parent to the backref p
1889 - "<p" sets the default parent to the backref p
1890 - "*p" is a fork at parent p, which is a backref
1890 - "*p" is a fork at parent p, which is a backref
1891 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1891 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1892 - "/p2" is a merge of the preceding node and p2
1892 - "/p2" is a merge of the preceding node and p2
1893 - ":tag" defines a local tag for the preceding node
1893 - ":tag" defines a local tag for the preceding node
1894 - "@branch" sets the named branch for subsequent nodes
1894 - "@branch" sets the named branch for subsequent nodes
1895 - "#...\\n" is a comment up to the end of the line
1895 - "#...\\n" is a comment up to the end of the line
1896
1896
1897 Whitespace between the above elements is ignored.
1897 Whitespace between the above elements is ignored.
1898
1898
1899 A backref is either
1899 A backref is either
1900
1900
1901 - a number n, which references the node curr-n, where curr is the current
1901 - a number n, which references the node curr-n, where curr is the current
1902 node, or
1902 node, or
1903 - the name of a local tag you placed earlier using ":tag", or
1903 - the name of a local tag you placed earlier using ":tag", or
1904 - empty to denote the default parent.
1904 - empty to denote the default parent.
1905
1905
1906 All string valued-elements are either strictly alphanumeric, or must
1906 All string valued-elements are either strictly alphanumeric, or must
1907 be enclosed in double quotes ("..."), with "\\" as escape character.
1907 be enclosed in double quotes ("..."), with "\\" as escape character.
1908 """
1908 """
1909
1909
1910 if text is None:
1910 if text is None:
1911 ui.status(_("reading DAG from stdin\n"))
1911 ui.status(_("reading DAG from stdin\n"))
1912 text = ui.fin.read()
1912 text = ui.fin.read()
1913
1913
1914 cl = repo.changelog
1914 cl = repo.changelog
1915 if len(cl) > 0:
1915 if len(cl) > 0:
1916 raise error.Abort(_('repository is not empty'))
1916 raise error.Abort(_('repository is not empty'))
1917
1917
1918 # determine number of revs in DAG
1918 # determine number of revs in DAG
1919 total = 0
1919 total = 0
1920 for type, data in dagparser.parsedag(text):
1920 for type, data in dagparser.parsedag(text):
1921 if type == 'n':
1921 if type == 'n':
1922 total += 1
1922 total += 1
1923
1923
1924 if mergeable_file:
1924 if mergeable_file:
1925 linesperrev = 2
1925 linesperrev = 2
1926 # make a file with k lines per rev
1926 # make a file with k lines per rev
1927 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1927 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1928 initialmergedlines.append("")
1928 initialmergedlines.append("")
1929
1929
1930 tags = []
1930 tags = []
1931
1931
1932 lock = tr = None
1932 lock = tr = None
1933 try:
1933 try:
1934 lock = repo.lock()
1934 lock = repo.lock()
1935 tr = repo.transaction("builddag")
1935 tr = repo.transaction("builddag")
1936
1936
1937 at = -1
1937 at = -1
1938 atbranch = 'default'
1938 atbranch = 'default'
1939 nodeids = []
1939 nodeids = []
1940 id = 0
1940 id = 0
1941 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1941 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1942 for type, data in dagparser.parsedag(text):
1942 for type, data in dagparser.parsedag(text):
1943 if type == 'n':
1943 if type == 'n':
1944 ui.note(('node %s\n' % str(data)))
1944 ui.note(('node %s\n' % str(data)))
1945 id, ps = data
1945 id, ps = data
1946
1946
1947 files = []
1947 files = []
1948 fctxs = {}
1948 fctxs = {}
1949
1949
1950 p2 = None
1950 p2 = None
1951 if mergeable_file:
1951 if mergeable_file:
1952 fn = "mf"
1952 fn = "mf"
1953 p1 = repo[ps[0]]
1953 p1 = repo[ps[0]]
1954 if len(ps) > 1:
1954 if len(ps) > 1:
1955 p2 = repo[ps[1]]
1955 p2 = repo[ps[1]]
1956 pa = p1.ancestor(p2)
1956 pa = p1.ancestor(p2)
1957 base, local, other = [x[fn].data() for x in (pa, p1,
1957 base, local, other = [x[fn].data() for x in (pa, p1,
1958 p2)]
1958 p2)]
1959 m3 = simplemerge.Merge3Text(base, local, other)
1959 m3 = simplemerge.Merge3Text(base, local, other)
1960 ml = [l.strip() for l in m3.merge_lines()]
1960 ml = [l.strip() for l in m3.merge_lines()]
1961 ml.append("")
1961 ml.append("")
1962 elif at > 0:
1962 elif at > 0:
1963 ml = p1[fn].data().split("\n")
1963 ml = p1[fn].data().split("\n")
1964 else:
1964 else:
1965 ml = initialmergedlines
1965 ml = initialmergedlines
1966 ml[id * linesperrev] += " r%i" % id
1966 ml[id * linesperrev] += " r%i" % id
1967 mergedtext = "\n".join(ml)
1967 mergedtext = "\n".join(ml)
1968 files.append(fn)
1968 files.append(fn)
1969 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1969 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1970
1970
1971 if overwritten_file:
1971 if overwritten_file:
1972 fn = "of"
1972 fn = "of"
1973 files.append(fn)
1973 files.append(fn)
1974 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1974 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1975
1975
1976 if new_file:
1976 if new_file:
1977 fn = "nf%i" % id
1977 fn = "nf%i" % id
1978 files.append(fn)
1978 files.append(fn)
1979 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1979 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1980 if len(ps) > 1:
1980 if len(ps) > 1:
1981 if not p2:
1981 if not p2:
1982 p2 = repo[ps[1]]
1982 p2 = repo[ps[1]]
1983 for fn in p2:
1983 for fn in p2:
1984 if fn.startswith("nf"):
1984 if fn.startswith("nf"):
1985 files.append(fn)
1985 files.append(fn)
1986 fctxs[fn] = p2[fn]
1986 fctxs[fn] = p2[fn]
1987
1987
1988 def fctxfn(repo, cx, path):
1988 def fctxfn(repo, cx, path):
1989 return fctxs.get(path)
1989 return fctxs.get(path)
1990
1990
1991 if len(ps) == 0 or ps[0] < 0:
1991 if len(ps) == 0 or ps[0] < 0:
1992 pars = [None, None]
1992 pars = [None, None]
1993 elif len(ps) == 1:
1993 elif len(ps) == 1:
1994 pars = [nodeids[ps[0]], None]
1994 pars = [nodeids[ps[0]], None]
1995 else:
1995 else:
1996 pars = [nodeids[p] for p in ps]
1996 pars = [nodeids[p] for p in ps]
1997 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1997 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1998 date=(id, 0),
1998 date=(id, 0),
1999 user="debugbuilddag",
1999 user="debugbuilddag",
2000 extra={'branch': atbranch})
2000 extra={'branch': atbranch})
2001 nodeid = repo.commitctx(cx)
2001 nodeid = repo.commitctx(cx)
2002 nodeids.append(nodeid)
2002 nodeids.append(nodeid)
2003 at = id
2003 at = id
2004 elif type == 'l':
2004 elif type == 'l':
2005 id, name = data
2005 id, name = data
2006 ui.note(('tag %s\n' % name))
2006 ui.note(('tag %s\n' % name))
2007 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2007 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2008 elif type == 'a':
2008 elif type == 'a':
2009 ui.note(('branch %s\n' % data))
2009 ui.note(('branch %s\n' % data))
2010 atbranch = data
2010 atbranch = data
2011 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2011 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2012 tr.close()
2012 tr.close()
2013
2013
2014 if tags:
2014 if tags:
2015 repo.vfs.write("localtags", "".join(tags))
2015 repo.vfs.write("localtags", "".join(tags))
2016 finally:
2016 finally:
2017 ui.progress(_('building'), None)
2017 ui.progress(_('building'), None)
2018 release(tr, lock)
2018 release(tr, lock)
2019
2019
2020 @command('debugbundle',
2020 @command('debugbundle',
2021 [('a', 'all', None, _('show all details'))],
2021 [('a', 'all', None, _('show all details'))],
2022 _('FILE'),
2022 _('FILE'),
2023 norepo=True)
2023 norepo=True)
2024 def debugbundle(ui, bundlepath, all=None, **opts):
2024 def debugbundle(ui, bundlepath, all=None, **opts):
2025 """lists the contents of a bundle"""
2025 """lists the contents of a bundle"""
2026 f = hg.openpath(ui, bundlepath)
2026 f = hg.openpath(ui, bundlepath)
2027 try:
2027 try:
2028 gen = exchange.readbundle(ui, f, bundlepath)
2028 gen = exchange.readbundle(ui, f, bundlepath)
2029 if isinstance(gen, bundle2.unbundle20):
2029 if isinstance(gen, bundle2.unbundle20):
2030 return _debugbundle2(ui, gen, all=all, **opts)
2030 return _debugbundle2(ui, gen, all=all, **opts)
2031 if all:
2031 if all:
2032 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2032 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2033
2033
2034 def showchunks(named):
2034 def showchunks(named):
2035 ui.write("\n%s\n" % named)
2035 ui.write("\n%s\n" % named)
2036 chain = None
2036 chain = None
2037 while True:
2037 while True:
2038 chunkdata = gen.deltachunk(chain)
2038 chunkdata = gen.deltachunk(chain)
2039 if not chunkdata:
2039 if not chunkdata:
2040 break
2040 break
2041 node = chunkdata['node']
2041 node = chunkdata['node']
2042 p1 = chunkdata['p1']
2042 p1 = chunkdata['p1']
2043 p2 = chunkdata['p2']
2043 p2 = chunkdata['p2']
2044 cs = chunkdata['cs']
2044 cs = chunkdata['cs']
2045 deltabase = chunkdata['deltabase']
2045 deltabase = chunkdata['deltabase']
2046 delta = chunkdata['delta']
2046 delta = chunkdata['delta']
2047 ui.write("%s %s %s %s %s %s\n" %
2047 ui.write("%s %s %s %s %s %s\n" %
2048 (hex(node), hex(p1), hex(p2),
2048 (hex(node), hex(p1), hex(p2),
2049 hex(cs), hex(deltabase), len(delta)))
2049 hex(cs), hex(deltabase), len(delta)))
2050 chain = node
2050 chain = node
2051
2051
2052 chunkdata = gen.changelogheader()
2052 chunkdata = gen.changelogheader()
2053 showchunks("changelog")
2053 showchunks("changelog")
2054 chunkdata = gen.manifestheader()
2054 chunkdata = gen.manifestheader()
2055 showchunks("manifest")
2055 showchunks("manifest")
2056 while True:
2056 while True:
2057 chunkdata = gen.filelogheader()
2057 chunkdata = gen.filelogheader()
2058 if not chunkdata:
2058 if not chunkdata:
2059 break
2059 break
2060 fname = chunkdata['filename']
2060 fname = chunkdata['filename']
2061 showchunks(fname)
2061 showchunks(fname)
2062 else:
2062 else:
2063 if isinstance(gen, bundle2.unbundle20):
2063 if isinstance(gen, bundle2.unbundle20):
2064 raise error.Abort(_('use debugbundle2 for this file'))
2064 raise error.Abort(_('use debugbundle2 for this file'))
2065 chunkdata = gen.changelogheader()
2065 chunkdata = gen.changelogheader()
2066 chain = None
2066 chain = None
2067 while True:
2067 while True:
2068 chunkdata = gen.deltachunk(chain)
2068 chunkdata = gen.deltachunk(chain)
2069 if not chunkdata:
2069 if not chunkdata:
2070 break
2070 break
2071 node = chunkdata['node']
2071 node = chunkdata['node']
2072 ui.write("%s\n" % hex(node))
2072 ui.write("%s\n" % hex(node))
2073 chain = node
2073 chain = node
2074 finally:
2074 finally:
2075 f.close()
2075 f.close()
2076
2076
2077 def _debugbundle2(ui, gen, **opts):
2077 def _debugbundle2(ui, gen, **opts):
2078 """lists the contents of a bundle2"""
2078 """lists the contents of a bundle2"""
2079 if not isinstance(gen, bundle2.unbundle20):
2079 if not isinstance(gen, bundle2.unbundle20):
2080 raise error.Abort(_('not a bundle2 file'))
2080 raise error.Abort(_('not a bundle2 file'))
2081 ui.write(('Stream params: %s\n' % repr(gen.params)))
2081 ui.write(('Stream params: %s\n' % repr(gen.params)))
2082 for part in gen.iterparts():
2082 for part in gen.iterparts():
2083 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2083 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2084 if part.type == 'changegroup':
2084 if part.type == 'changegroup':
2085 version = part.params.get('version', '01')
2085 version = part.params.get('version', '01')
2086 cg = changegroup.packermap[version][1](part, 'UN')
2086 cg = changegroup.packermap[version][1](part, 'UN')
2087 chunkdata = cg.changelogheader()
2087 chunkdata = cg.changelogheader()
2088 chain = None
2088 chain = None
2089 while True:
2089 while True:
2090 chunkdata = cg.deltachunk(chain)
2090 chunkdata = cg.deltachunk(chain)
2091 if not chunkdata:
2091 if not chunkdata:
2092 break
2092 break
2093 node = chunkdata['node']
2093 node = chunkdata['node']
2094 ui.write(" %s\n" % hex(node))
2094 ui.write(" %s\n" % hex(node))
2095 chain = node
2095 chain = node
2096
2096
2097 @command('debugcreatestreamclonebundle', [], 'FILE')
2097 @command('debugcreatestreamclonebundle', [], 'FILE')
2098 def debugcreatestreamclonebundle(ui, repo, fname):
2098 def debugcreatestreamclonebundle(ui, repo, fname):
2099 """create a stream clone bundle file
2099 """create a stream clone bundle file
2100
2100
2101 Stream bundles are special bundles that are essentially archives of
2101 Stream bundles are special bundles that are essentially archives of
2102 revlog files. They are commonly used for cloning very quickly.
2102 revlog files. They are commonly used for cloning very quickly.
2103 """
2103 """
2104 requirements, gen = streamclone.generatebundlev1(repo)
2104 requirements, gen = streamclone.generatebundlev1(repo)
2105 changegroup.writechunks(ui, gen, fname)
2105 changegroup.writechunks(ui, gen, fname)
2106
2106
2107 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2107 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2108
2108
2109 @command('debugapplystreamclonebundle', [], 'FILE')
2109 @command('debugapplystreamclonebundle', [], 'FILE')
2110 def debugapplystreamclonebundle(ui, repo, fname):
2110 def debugapplystreamclonebundle(ui, repo, fname):
2111 """apply a stream clone bundle file"""
2111 """apply a stream clone bundle file"""
2112 f = hg.openpath(ui, fname)
2112 f = hg.openpath(ui, fname)
2113 gen = exchange.readbundle(ui, f, fname)
2113 gen = exchange.readbundle(ui, f, fname)
2114 gen.apply(repo)
2114 gen.apply(repo)
2115
2115
2116 @command('debugcheckstate', [], '')
2116 @command('debugcheckstate', [], '')
2117 def debugcheckstate(ui, repo):
2117 def debugcheckstate(ui, repo):
2118 """validate the correctness of the current dirstate"""
2118 """validate the correctness of the current dirstate"""
2119 parent1, parent2 = repo.dirstate.parents()
2119 parent1, parent2 = repo.dirstate.parents()
2120 m1 = repo[parent1].manifest()
2120 m1 = repo[parent1].manifest()
2121 m2 = repo[parent2].manifest()
2121 m2 = repo[parent2].manifest()
2122 errors = 0
2122 errors = 0
2123 for f in repo.dirstate:
2123 for f in repo.dirstate:
2124 state = repo.dirstate[f]
2124 state = repo.dirstate[f]
2125 if state in "nr" and f not in m1:
2125 if state in "nr" and f not in m1:
2126 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2126 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2127 errors += 1
2127 errors += 1
2128 if state in "a" and f in m1:
2128 if state in "a" and f in m1:
2129 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2129 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2130 errors += 1
2130 errors += 1
2131 if state in "m" and f not in m1 and f not in m2:
2131 if state in "m" and f not in m1 and f not in m2:
2132 ui.warn(_("%s in state %s, but not in either manifest\n") %
2132 ui.warn(_("%s in state %s, but not in either manifest\n") %
2133 (f, state))
2133 (f, state))
2134 errors += 1
2134 errors += 1
2135 for f in m1:
2135 for f in m1:
2136 state = repo.dirstate[f]
2136 state = repo.dirstate[f]
2137 if state not in "nrm":
2137 if state not in "nrm":
2138 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2138 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2139 errors += 1
2139 errors += 1
2140 if errors:
2140 if errors:
2141 error = _(".hg/dirstate inconsistent with current parent's manifest")
2141 error = _(".hg/dirstate inconsistent with current parent's manifest")
2142 raise error.Abort(error)
2142 raise error.Abort(error)
2143
2143
2144 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2144 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2145 def debugcommands(ui, cmd='', *args):
2145 def debugcommands(ui, cmd='', *args):
2146 """list all available commands and options"""
2146 """list all available commands and options"""
2147 for cmd, vals in sorted(table.iteritems()):
2147 for cmd, vals in sorted(table.iteritems()):
2148 cmd = cmd.split('|')[0].strip('^')
2148 cmd = cmd.split('|')[0].strip('^')
2149 opts = ', '.join([i[1] for i in vals[1]])
2149 opts = ', '.join([i[1] for i in vals[1]])
2150 ui.write('%s: %s\n' % (cmd, opts))
2150 ui.write('%s: %s\n' % (cmd, opts))
2151
2151
2152 @command('debugcomplete',
2152 @command('debugcomplete',
2153 [('o', 'options', None, _('show the command options'))],
2153 [('o', 'options', None, _('show the command options'))],
2154 _('[-o] CMD'),
2154 _('[-o] CMD'),
2155 norepo=True)
2155 norepo=True)
2156 def debugcomplete(ui, cmd='', **opts):
2156 def debugcomplete(ui, cmd='', **opts):
2157 """returns the completion list associated with the given command"""
2157 """returns the completion list associated with the given command"""
2158
2158
2159 if opts.get('options'):
2159 if opts.get('options'):
2160 options = []
2160 options = []
2161 otables = [globalopts]
2161 otables = [globalopts]
2162 if cmd:
2162 if cmd:
2163 aliases, entry = cmdutil.findcmd(cmd, table, False)
2163 aliases, entry = cmdutil.findcmd(cmd, table, False)
2164 otables.append(entry[1])
2164 otables.append(entry[1])
2165 for t in otables:
2165 for t in otables:
2166 for o in t:
2166 for o in t:
2167 if "(DEPRECATED)" in o[3]:
2167 if "(DEPRECATED)" in o[3]:
2168 continue
2168 continue
2169 if o[0]:
2169 if o[0]:
2170 options.append('-%s' % o[0])
2170 options.append('-%s' % o[0])
2171 options.append('--%s' % o[1])
2171 options.append('--%s' % o[1])
2172 ui.write("%s\n" % "\n".join(options))
2172 ui.write("%s\n" % "\n".join(options))
2173 return
2173 return
2174
2174
2175 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2175 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2176 if ui.verbose:
2176 if ui.verbose:
2177 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2177 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2178 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2178 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2179
2179
2180 @command('debugdag',
2180 @command('debugdag',
2181 [('t', 'tags', None, _('use tags as labels')),
2181 [('t', 'tags', None, _('use tags as labels')),
2182 ('b', 'branches', None, _('annotate with branch names')),
2182 ('b', 'branches', None, _('annotate with branch names')),
2183 ('', 'dots', None, _('use dots for runs')),
2183 ('', 'dots', None, _('use dots for runs')),
2184 ('s', 'spaces', None, _('separate elements by spaces'))],
2184 ('s', 'spaces', None, _('separate elements by spaces'))],
2185 _('[OPTION]... [FILE [REV]...]'),
2185 _('[OPTION]... [FILE [REV]...]'),
2186 optionalrepo=True)
2186 optionalrepo=True)
2187 def debugdag(ui, repo, file_=None, *revs, **opts):
2187 def debugdag(ui, repo, file_=None, *revs, **opts):
2188 """format the changelog or an index DAG as a concise textual description
2188 """format the changelog or an index DAG as a concise textual description
2189
2189
2190 If you pass a revlog index, the revlog's DAG is emitted. If you list
2190 If you pass a revlog index, the revlog's DAG is emitted. If you list
2191 revision numbers, they get labeled in the output as rN.
2191 revision numbers, they get labeled in the output as rN.
2192
2192
2193 Otherwise, the changelog DAG of the current repo is emitted.
2193 Otherwise, the changelog DAG of the current repo is emitted.
2194 """
2194 """
2195 spaces = opts.get('spaces')
2195 spaces = opts.get('spaces')
2196 dots = opts.get('dots')
2196 dots = opts.get('dots')
2197 if file_:
2197 if file_:
2198 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2198 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2199 revs = set((int(r) for r in revs))
2199 revs = set((int(r) for r in revs))
2200 def events():
2200 def events():
2201 for r in rlog:
2201 for r in rlog:
2202 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2202 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2203 if p != -1))
2203 if p != -1))
2204 if r in revs:
2204 if r in revs:
2205 yield 'l', (r, "r%i" % r)
2205 yield 'l', (r, "r%i" % r)
2206 elif repo:
2206 elif repo:
2207 cl = repo.changelog
2207 cl = repo.changelog
2208 tags = opts.get('tags')
2208 tags = opts.get('tags')
2209 branches = opts.get('branches')
2209 branches = opts.get('branches')
2210 if tags:
2210 if tags:
2211 labels = {}
2211 labels = {}
2212 for l, n in repo.tags().items():
2212 for l, n in repo.tags().items():
2213 labels.setdefault(cl.rev(n), []).append(l)
2213 labels.setdefault(cl.rev(n), []).append(l)
2214 def events():
2214 def events():
2215 b = "default"
2215 b = "default"
2216 for r in cl:
2216 for r in cl:
2217 if branches:
2217 if branches:
2218 newb = cl.read(cl.node(r))[5]['branch']
2218 newb = cl.read(cl.node(r))[5]['branch']
2219 if newb != b:
2219 if newb != b:
2220 yield 'a', newb
2220 yield 'a', newb
2221 b = newb
2221 b = newb
2222 yield 'n', (r, list(p for p in cl.parentrevs(r)
2222 yield 'n', (r, list(p for p in cl.parentrevs(r)
2223 if p != -1))
2223 if p != -1))
2224 if tags:
2224 if tags:
2225 ls = labels.get(r)
2225 ls = labels.get(r)
2226 if ls:
2226 if ls:
2227 for l in ls:
2227 for l in ls:
2228 yield 'l', (r, l)
2228 yield 'l', (r, l)
2229 else:
2229 else:
2230 raise error.Abort(_('need repo for changelog dag'))
2230 raise error.Abort(_('need repo for changelog dag'))
2231
2231
2232 for line in dagparser.dagtextlines(events(),
2232 for line in dagparser.dagtextlines(events(),
2233 addspaces=spaces,
2233 addspaces=spaces,
2234 wraplabels=True,
2234 wraplabels=True,
2235 wrapannotations=True,
2235 wrapannotations=True,
2236 wrapnonlinear=dots,
2236 wrapnonlinear=dots,
2237 usedots=dots,
2237 usedots=dots,
2238 maxlinewidth=70):
2238 maxlinewidth=70):
2239 ui.write(line)
2239 ui.write(line)
2240 ui.write("\n")
2240 ui.write("\n")
2241
2241
2242 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2242 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2243 def debugdata(ui, repo, file_, rev=None, **opts):
2243 def debugdata(ui, repo, file_, rev=None, **opts):
2244 """dump the contents of a data file revision"""
2244 """dump the contents of a data file revision"""
2245 if opts.get('changelog') or opts.get('manifest'):
2245 if opts.get('changelog') or opts.get('manifest'):
2246 file_, rev = None, file_
2246 file_, rev = None, file_
2247 elif rev is None:
2247 elif rev is None:
2248 raise error.CommandError('debugdata', _('invalid arguments'))
2248 raise error.CommandError('debugdata', _('invalid arguments'))
2249 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2249 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2250 try:
2250 try:
2251 ui.write(r.revision(r.lookup(rev)))
2251 ui.write(r.revision(r.lookup(rev)))
2252 except KeyError:
2252 except KeyError:
2253 raise error.Abort(_('invalid revision identifier %s') % rev)
2253 raise error.Abort(_('invalid revision identifier %s') % rev)
2254
2254
2255 @command('debugdate',
2255 @command('debugdate',
2256 [('e', 'extended', None, _('try extended date formats'))],
2256 [('e', 'extended', None, _('try extended date formats'))],
2257 _('[-e] DATE [RANGE]'),
2257 _('[-e] DATE [RANGE]'),
2258 norepo=True, optionalrepo=True)
2258 norepo=True, optionalrepo=True)
2259 def debugdate(ui, date, range=None, **opts):
2259 def debugdate(ui, date, range=None, **opts):
2260 """parse and display a date"""
2260 """parse and display a date"""
2261 if opts["extended"]:
2261 if opts["extended"]:
2262 d = util.parsedate(date, util.extendeddateformats)
2262 d = util.parsedate(date, util.extendeddateformats)
2263 else:
2263 else:
2264 d = util.parsedate(date)
2264 d = util.parsedate(date)
2265 ui.write(("internal: %s %s\n") % d)
2265 ui.write(("internal: %s %s\n") % d)
2266 ui.write(("standard: %s\n") % util.datestr(d))
2266 ui.write(("standard: %s\n") % util.datestr(d))
2267 if range:
2267 if range:
2268 m = util.matchdate(range)
2268 m = util.matchdate(range)
2269 ui.write(("match: %s\n") % m(d[0]))
2269 ui.write(("match: %s\n") % m(d[0]))
2270
2270
2271 @command('debugdiscovery',
2271 @command('debugdiscovery',
2272 [('', 'old', None, _('use old-style discovery')),
2272 [('', 'old', None, _('use old-style discovery')),
2273 ('', 'nonheads', None,
2273 ('', 'nonheads', None,
2274 _('use old-style discovery with non-heads included')),
2274 _('use old-style discovery with non-heads included')),
2275 ] + remoteopts,
2275 ] + remoteopts,
2276 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2276 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2277 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2277 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2278 """runs the changeset discovery protocol in isolation"""
2278 """runs the changeset discovery protocol in isolation"""
2279 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2279 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2280 opts.get('branch'))
2280 opts.get('branch'))
2281 remote = hg.peer(repo, opts, remoteurl)
2281 remote = hg.peer(repo, opts, remoteurl)
2282 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2282 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2283
2283
2284 # make sure tests are repeatable
2284 # make sure tests are repeatable
2285 random.seed(12323)
2285 random.seed(12323)
2286
2286
2287 def doit(localheads, remoteheads, remote=remote):
2287 def doit(localheads, remoteheads, remote=remote):
2288 if opts.get('old'):
2288 if opts.get('old'):
2289 if localheads:
2289 if localheads:
2290 raise error.Abort('cannot use localheads with old style '
2290 raise error.Abort('cannot use localheads with old style '
2291 'discovery')
2291 'discovery')
2292 if not util.safehasattr(remote, 'branches'):
2292 if not util.safehasattr(remote, 'branches'):
2293 # enable in-client legacy support
2293 # enable in-client legacy support
2294 remote = localrepo.locallegacypeer(remote.local())
2294 remote = localrepo.locallegacypeer(remote.local())
2295 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2295 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2296 force=True)
2296 force=True)
2297 common = set(common)
2297 common = set(common)
2298 if not opts.get('nonheads'):
2298 if not opts.get('nonheads'):
2299 ui.write(("unpruned common: %s\n") %
2299 ui.write(("unpruned common: %s\n") %
2300 " ".join(sorted(short(n) for n in common)))
2300 " ".join(sorted(short(n) for n in common)))
2301 dag = dagutil.revlogdag(repo.changelog)
2301 dag = dagutil.revlogdag(repo.changelog)
2302 all = dag.ancestorset(dag.internalizeall(common))
2302 all = dag.ancestorset(dag.internalizeall(common))
2303 common = dag.externalizeall(dag.headsetofconnecteds(all))
2303 common = dag.externalizeall(dag.headsetofconnecteds(all))
2304 else:
2304 else:
2305 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2305 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2306 common = set(common)
2306 common = set(common)
2307 rheads = set(hds)
2307 rheads = set(hds)
2308 lheads = set(repo.heads())
2308 lheads = set(repo.heads())
2309 ui.write(("common heads: %s\n") %
2309 ui.write(("common heads: %s\n") %
2310 " ".join(sorted(short(n) for n in common)))
2310 " ".join(sorted(short(n) for n in common)))
2311 if lheads <= common:
2311 if lheads <= common:
2312 ui.write(("local is subset\n"))
2312 ui.write(("local is subset\n"))
2313 elif rheads <= common:
2313 elif rheads <= common:
2314 ui.write(("remote is subset\n"))
2314 ui.write(("remote is subset\n"))
2315
2315
2316 serverlogs = opts.get('serverlog')
2316 serverlogs = opts.get('serverlog')
2317 if serverlogs:
2317 if serverlogs:
2318 for filename in serverlogs:
2318 for filename in serverlogs:
2319 logfile = open(filename, 'r')
2319 logfile = open(filename, 'r')
2320 try:
2320 try:
2321 line = logfile.readline()
2321 line = logfile.readline()
2322 while line:
2322 while line:
2323 parts = line.strip().split(';')
2323 parts = line.strip().split(';')
2324 op = parts[1]
2324 op = parts[1]
2325 if op == 'cg':
2325 if op == 'cg':
2326 pass
2326 pass
2327 elif op == 'cgss':
2327 elif op == 'cgss':
2328 doit(parts[2].split(' '), parts[3].split(' '))
2328 doit(parts[2].split(' '), parts[3].split(' '))
2329 elif op == 'unb':
2329 elif op == 'unb':
2330 doit(parts[3].split(' '), parts[2].split(' '))
2330 doit(parts[3].split(' '), parts[2].split(' '))
2331 line = logfile.readline()
2331 line = logfile.readline()
2332 finally:
2332 finally:
2333 logfile.close()
2333 logfile.close()
2334
2334
2335 else:
2335 else:
2336 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2336 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2337 opts.get('remote_head'))
2337 opts.get('remote_head'))
2338 localrevs = opts.get('local_head')
2338 localrevs = opts.get('local_head')
2339 doit(localrevs, remoterevs)
2339 doit(localrevs, remoterevs)
2340
2340
2341 @command('debugextensions', formatteropts, [], norepo=True)
2341 @command('debugextensions', formatteropts, [], norepo=True)
2342 def debugextensions(ui, **opts):
2342 def debugextensions(ui, **opts):
2343 '''show information about active extensions'''
2343 '''show information about active extensions'''
2344 exts = extensions.extensions(ui)
2344 exts = extensions.extensions(ui)
2345 fm = ui.formatter('debugextensions', opts)
2345 fm = ui.formatter('debugextensions', opts)
2346 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2346 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2347 extsource = extmod.__file__
2347 extsource = extmod.__file__
2348 exttestedwith = getattr(extmod, 'testedwith', None)
2348 exttestedwith = getattr(extmod, 'testedwith', None)
2349 if exttestedwith is not None:
2349 if exttestedwith is not None:
2350 exttestedwith = exttestedwith.split()
2350 exttestedwith = exttestedwith.split()
2351 extbuglink = getattr(extmod, 'buglink', None)
2351 extbuglink = getattr(extmod, 'buglink', None)
2352
2352
2353 fm.startitem()
2353 fm.startitem()
2354
2354
2355 if ui.quiet or ui.verbose:
2355 if ui.quiet or ui.verbose:
2356 fm.write('name', '%s\n', extname)
2356 fm.write('name', '%s\n', extname)
2357 else:
2357 else:
2358 fm.write('name', '%s', extname)
2358 fm.write('name', '%s', extname)
2359 if not exttestedwith:
2359 if not exttestedwith:
2360 fm.plain(_(' (untested!)\n'))
2360 fm.plain(_(' (untested!)\n'))
2361 else:
2361 else:
2362 if exttestedwith == ['internal'] or \
2362 if exttestedwith == ['internal'] or \
2363 util.version() in exttestedwith:
2363 util.version() in exttestedwith:
2364 fm.plain('\n')
2364 fm.plain('\n')
2365 else:
2365 else:
2366 lasttestedversion = exttestedwith[-1]
2366 lasttestedversion = exttestedwith[-1]
2367 fm.plain(' (%s!)\n' % lasttestedversion)
2367 fm.plain(' (%s!)\n' % lasttestedversion)
2368
2368
2369 fm.condwrite(ui.verbose and extsource, 'source',
2369 fm.condwrite(ui.verbose and extsource, 'source',
2370 _(' location: %s\n'), extsource or "")
2370 _(' location: %s\n'), extsource or "")
2371
2371
2372 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2372 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2373 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2373 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2374
2374
2375 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2375 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2376 _(' bug reporting: %s\n'), extbuglink or "")
2376 _(' bug reporting: %s\n'), extbuglink or "")
2377
2377
2378 fm.end()
2378 fm.end()
2379
2379
2380 @command('debugfileset',
2380 @command('debugfileset',
2381 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2381 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2382 _('[-r REV] FILESPEC'))
2382 _('[-r REV] FILESPEC'))
2383 def debugfileset(ui, repo, expr, **opts):
2383 def debugfileset(ui, repo, expr, **opts):
2384 '''parse and apply a fileset specification'''
2384 '''parse and apply a fileset specification'''
2385 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2385 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2386 if ui.verbose:
2386 if ui.verbose:
2387 tree = fileset.parse(expr)
2387 tree = fileset.parse(expr)
2388 ui.note(fileset.prettyformat(tree), "\n")
2388 ui.note(fileset.prettyformat(tree), "\n")
2389
2389
2390 for f in ctx.getfileset(expr):
2390 for f in ctx.getfileset(expr):
2391 ui.write("%s\n" % f)
2391 ui.write("%s\n" % f)
2392
2392
2393 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2393 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2394 def debugfsinfo(ui, path="."):
2394 def debugfsinfo(ui, path="."):
2395 """show information detected about current filesystem"""
2395 """show information detected about current filesystem"""
2396 util.writefile('.debugfsinfo', '')
2396 util.writefile('.debugfsinfo', '')
2397 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2397 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2398 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2398 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2399 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2399 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2400 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2400 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2401 and 'yes' or 'no'))
2401 and 'yes' or 'no'))
2402 os.unlink('.debugfsinfo')
2402 os.unlink('.debugfsinfo')
2403
2403
2404 @command('debuggetbundle',
2404 @command('debuggetbundle',
2405 [('H', 'head', [], _('id of head node'), _('ID')),
2405 [('H', 'head', [], _('id of head node'), _('ID')),
2406 ('C', 'common', [], _('id of common node'), _('ID')),
2406 ('C', 'common', [], _('id of common node'), _('ID')),
2407 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2407 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2408 _('REPO FILE [-H|-C ID]...'),
2408 _('REPO FILE [-H|-C ID]...'),
2409 norepo=True)
2409 norepo=True)
2410 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2410 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2411 """retrieves a bundle from a repo
2411 """retrieves a bundle from a repo
2412
2412
2413 Every ID must be a full-length hex node id string. Saves the bundle to the
2413 Every ID must be a full-length hex node id string. Saves the bundle to the
2414 given file.
2414 given file.
2415 """
2415 """
2416 repo = hg.peer(ui, opts, repopath)
2416 repo = hg.peer(ui, opts, repopath)
2417 if not repo.capable('getbundle'):
2417 if not repo.capable('getbundle'):
2418 raise error.Abort("getbundle() not supported by target repository")
2418 raise error.Abort("getbundle() not supported by target repository")
2419 args = {}
2419 args = {}
2420 if common:
2420 if common:
2421 args['common'] = [bin(s) for s in common]
2421 args['common'] = [bin(s) for s in common]
2422 if head:
2422 if head:
2423 args['heads'] = [bin(s) for s in head]
2423 args['heads'] = [bin(s) for s in head]
2424 # TODO: get desired bundlecaps from command line.
2424 # TODO: get desired bundlecaps from command line.
2425 args['bundlecaps'] = None
2425 args['bundlecaps'] = None
2426 bundle = repo.getbundle('debug', **args)
2426 bundle = repo.getbundle('debug', **args)
2427
2427
2428 bundletype = opts.get('type', 'bzip2').lower()
2428 bundletype = opts.get('type', 'bzip2').lower()
2429 btypes = {'none': 'HG10UN',
2429 btypes = {'none': 'HG10UN',
2430 'bzip2': 'HG10BZ',
2430 'bzip2': 'HG10BZ',
2431 'gzip': 'HG10GZ',
2431 'gzip': 'HG10GZ',
2432 'bundle2': 'HG20'}
2432 'bundle2': 'HG20'}
2433 bundletype = btypes.get(bundletype)
2433 bundletype = btypes.get(bundletype)
2434 if bundletype not in changegroup.bundletypes:
2434 if bundletype not in changegroup.bundletypes:
2435 raise error.Abort(_('unknown bundle type specified with --type'))
2435 raise error.Abort(_('unknown bundle type specified with --type'))
2436 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2436 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2437
2437
2438 @command('debugignore', [], '')
2438 @command('debugignore', [], '')
2439 def debugignore(ui, repo, *values, **opts):
2439 def debugignore(ui, repo, *values, **opts):
2440 """display the combined ignore pattern"""
2440 """display the combined ignore pattern"""
2441 ignore = repo.dirstate._ignore
2441 ignore = repo.dirstate._ignore
2442 includepat = getattr(ignore, 'includepat', None)
2442 includepat = getattr(ignore, 'includepat', None)
2443 if includepat is not None:
2443 if includepat is not None:
2444 ui.write("%s\n" % includepat)
2444 ui.write("%s\n" % includepat)
2445 else:
2445 else:
2446 raise error.Abort(_("no ignore patterns found"))
2446 raise error.Abort(_("no ignore patterns found"))
2447
2447
2448 @command('debugindex', debugrevlogopts +
2448 @command('debugindex', debugrevlogopts +
2449 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2449 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2450 _('[-f FORMAT] -c|-m|FILE'),
2450 _('[-f FORMAT] -c|-m|FILE'),
2451 optionalrepo=True)
2451 optionalrepo=True)
2452 def debugindex(ui, repo, file_=None, **opts):
2452 def debugindex(ui, repo, file_=None, **opts):
2453 """dump the contents of an index file"""
2453 """dump the contents of an index file"""
2454 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2454 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2455 format = opts.get('format', 0)
2455 format = opts.get('format', 0)
2456 if format not in (0, 1):
2456 if format not in (0, 1):
2457 raise error.Abort(_("unknown format %d") % format)
2457 raise error.Abort(_("unknown format %d") % format)
2458
2458
2459 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2459 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2460 if generaldelta:
2460 if generaldelta:
2461 basehdr = ' delta'
2461 basehdr = ' delta'
2462 else:
2462 else:
2463 basehdr = ' base'
2463 basehdr = ' base'
2464
2464
2465 if ui.debugflag:
2465 if ui.debugflag:
2466 shortfn = hex
2466 shortfn = hex
2467 else:
2467 else:
2468 shortfn = short
2468 shortfn = short
2469
2469
2470 # There might not be anything in r, so have a sane default
2470 # There might not be anything in r, so have a sane default
2471 idlen = 12
2471 idlen = 12
2472 for i in r:
2472 for i in r:
2473 idlen = len(shortfn(r.node(i)))
2473 idlen = len(shortfn(r.node(i)))
2474 break
2474 break
2475
2475
2476 if format == 0:
2476 if format == 0:
2477 ui.write(" rev offset length " + basehdr + " linkrev"
2477 ui.write(" rev offset length " + basehdr + " linkrev"
2478 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2478 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2479 elif format == 1:
2479 elif format == 1:
2480 ui.write(" rev flag offset length"
2480 ui.write(" rev flag offset length"
2481 " size " + basehdr + " link p1 p2"
2481 " size " + basehdr + " link p1 p2"
2482 " %s\n" % "nodeid".rjust(idlen))
2482 " %s\n" % "nodeid".rjust(idlen))
2483
2483
2484 for i in r:
2484 for i in r:
2485 node = r.node(i)
2485 node = r.node(i)
2486 if generaldelta:
2486 if generaldelta:
2487 base = r.deltaparent(i)
2487 base = r.deltaparent(i)
2488 else:
2488 else:
2489 base = r.chainbase(i)
2489 base = r.chainbase(i)
2490 if format == 0:
2490 if format == 0:
2491 try:
2491 try:
2492 pp = r.parents(node)
2492 pp = r.parents(node)
2493 except Exception:
2493 except Exception:
2494 pp = [nullid, nullid]
2494 pp = [nullid, nullid]
2495 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2495 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2496 i, r.start(i), r.length(i), base, r.linkrev(i),
2496 i, r.start(i), r.length(i), base, r.linkrev(i),
2497 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2497 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2498 elif format == 1:
2498 elif format == 1:
2499 pr = r.parentrevs(i)
2499 pr = r.parentrevs(i)
2500 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2500 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2501 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2501 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2502 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2502 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2503
2503
2504 @command('debugindexdot', debugrevlogopts,
2504 @command('debugindexdot', debugrevlogopts,
2505 _('-c|-m|FILE'), optionalrepo=True)
2505 _('-c|-m|FILE'), optionalrepo=True)
2506 def debugindexdot(ui, repo, file_=None, **opts):
2506 def debugindexdot(ui, repo, file_=None, **opts):
2507 """dump an index DAG as a graphviz dot file"""
2507 """dump an index DAG as a graphviz dot file"""
2508 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2508 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2509 ui.write(("digraph G {\n"))
2509 ui.write(("digraph G {\n"))
2510 for i in r:
2510 for i in r:
2511 node = r.node(i)
2511 node = r.node(i)
2512 pp = r.parents(node)
2512 pp = r.parents(node)
2513 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2513 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2514 if pp[1] != nullid:
2514 if pp[1] != nullid:
2515 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2515 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2516 ui.write("}\n")
2516 ui.write("}\n")
2517
2517
2518 @command('debugdeltachain',
2518 @command('debugdeltachain',
2519 debugrevlogopts + formatteropts,
2519 debugrevlogopts + formatteropts,
2520 _('-c|-m|FILE'),
2520 _('-c|-m|FILE'),
2521 optionalrepo=True)
2521 optionalrepo=True)
2522 def debugdeltachain(ui, repo, file_=None, **opts):
2522 def debugdeltachain(ui, repo, file_=None, **opts):
2523 """dump information about delta chains in a revlog
2523 """dump information about delta chains in a revlog
2524
2524
2525 Output can be templatized. Available template keywords are:
2525 Output can be templatized. Available template keywords are:
2526
2526
2527 rev revision number
2527 rev revision number
2528 chainid delta chain identifier (numbered by unique base)
2528 chainid delta chain identifier (numbered by unique base)
2529 chainlen delta chain length to this revision
2529 chainlen delta chain length to this revision
2530 prevrev previous revision in delta chain
2530 prevrev previous revision in delta chain
2531 deltatype role of delta / how it was computed
2531 deltatype role of delta / how it was computed
2532 compsize compressed size of revision
2532 compsize compressed size of revision
2533 uncompsize uncompressed size of revision
2533 uncompsize uncompressed size of revision
2534 chainsize total size of compressed revisions in chain
2534 chainsize total size of compressed revisions in chain
2535 chainratio total chain size divided by uncompressed revision size
2535 chainratio total chain size divided by uncompressed revision size
2536 (new delta chains typically start at ratio 2.00)
2536 (new delta chains typically start at ratio 2.00)
2537 lindist linear distance from base revision in delta chain to end
2537 lindist linear distance from base revision in delta chain to end
2538 of this revision
2538 of this revision
2539 extradist total size of revisions not part of this delta chain from
2539 extradist total size of revisions not part of this delta chain from
2540 base of delta chain to end of this revision; a measurement
2540 base of delta chain to end of this revision; a measurement
2541 of how much extra data we need to read/seek across to read
2541 of how much extra data we need to read/seek across to read
2542 the delta chain for this revision
2542 the delta chain for this revision
2543 extraratio extradist divided by chainsize; another representation of
2543 extraratio extradist divided by chainsize; another representation of
2544 how much unrelated data is needed to load this delta chain
2544 how much unrelated data is needed to load this delta chain
2545 """
2545 """
2546 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2546 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2547 index = r.index
2547 index = r.index
2548 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2548 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2549
2549
2550 def revinfo(rev):
2550 def revinfo(rev):
2551 e = index[rev]
2551 e = index[rev]
2552 compsize = e[1]
2552 compsize = e[1]
2553 uncompsize = e[2]
2553 uncompsize = e[2]
2554 chainsize = 0
2554 chainsize = 0
2555
2555
2556 if generaldelta:
2556 if generaldelta:
2557 if e[3] == e[5]:
2557 if e[3] == e[5]:
2558 deltatype = 'p1'
2558 deltatype = 'p1'
2559 elif e[3] == e[6]:
2559 elif e[3] == e[6]:
2560 deltatype = 'p2'
2560 deltatype = 'p2'
2561 elif e[3] == rev - 1:
2561 elif e[3] == rev - 1:
2562 deltatype = 'prev'
2562 deltatype = 'prev'
2563 elif e[3] == rev:
2563 elif e[3] == rev:
2564 deltatype = 'base'
2564 deltatype = 'base'
2565 else:
2565 else:
2566 deltatype = 'other'
2566 deltatype = 'other'
2567 else:
2567 else:
2568 if e[3] == rev:
2568 if e[3] == rev:
2569 deltatype = 'base'
2569 deltatype = 'base'
2570 else:
2570 else:
2571 deltatype = 'prev'
2571 deltatype = 'prev'
2572
2572
2573 chain = r._deltachain(rev)[0]
2573 chain = r._deltachain(rev)[0]
2574 for iterrev in chain:
2574 for iterrev in chain:
2575 e = index[iterrev]
2575 e = index[iterrev]
2576 chainsize += e[1]
2576 chainsize += e[1]
2577
2577
2578 return compsize, uncompsize, deltatype, chain, chainsize
2578 return compsize, uncompsize, deltatype, chain, chainsize
2579
2579
2580 fm = ui.formatter('debugdeltachain', opts)
2580 fm = ui.formatter('debugdeltachain', opts)
2581
2581
2582 fm.plain(' rev chain# chainlen prev delta '
2582 fm.plain(' rev chain# chainlen prev delta '
2583 'size rawsize chainsize ratio lindist extradist '
2583 'size rawsize chainsize ratio lindist extradist '
2584 'extraratio\n')
2584 'extraratio\n')
2585
2585
2586 chainbases = {}
2586 chainbases = {}
2587 for rev in r:
2587 for rev in r:
2588 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2588 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2589 chainbase = chain[0]
2589 chainbase = chain[0]
2590 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2590 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2591 basestart = r.start(chainbase)
2591 basestart = r.start(chainbase)
2592 revstart = r.start(rev)
2592 revstart = r.start(rev)
2593 lineardist = revstart + comp - basestart
2593 lineardist = revstart + comp - basestart
2594 extradist = lineardist - chainsize
2594 extradist = lineardist - chainsize
2595 try:
2595 try:
2596 prevrev = chain[-2]
2596 prevrev = chain[-2]
2597 except IndexError:
2597 except IndexError:
2598 prevrev = -1
2598 prevrev = -1
2599
2599
2600 chainratio = float(chainsize) / float(uncomp)
2600 chainratio = float(chainsize) / float(uncomp)
2601 extraratio = float(extradist) / float(chainsize)
2601 extraratio = float(extradist) / float(chainsize)
2602
2602
2603 fm.startitem()
2603 fm.startitem()
2604 fm.write('rev chainid chainlen prevrev deltatype compsize '
2604 fm.write('rev chainid chainlen prevrev deltatype compsize '
2605 'uncompsize chainsize chainratio lindist extradist '
2605 'uncompsize chainsize chainratio lindist extradist '
2606 'extraratio',
2606 'extraratio',
2607 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2607 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2608 rev, chainid, len(chain), prevrev, deltatype, comp,
2608 rev, chainid, len(chain), prevrev, deltatype, comp,
2609 uncomp, chainsize, chainratio, lineardist, extradist,
2609 uncomp, chainsize, chainratio, lineardist, extradist,
2610 extraratio,
2610 extraratio,
2611 rev=rev, chainid=chainid, chainlen=len(chain),
2611 rev=rev, chainid=chainid, chainlen=len(chain),
2612 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2612 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2613 uncompsize=uncomp, chainsize=chainsize,
2613 uncompsize=uncomp, chainsize=chainsize,
2614 chainratio=chainratio, lindist=lineardist,
2614 chainratio=chainratio, lindist=lineardist,
2615 extradist=extradist, extraratio=extraratio)
2615 extradist=extradist, extraratio=extraratio)
2616
2616
2617 fm.end()
2617 fm.end()
2618
2618
2619 @command('debuginstall', [], '', norepo=True)
2619 @command('debuginstall', [], '', norepo=True)
2620 def debuginstall(ui):
2620 def debuginstall(ui):
2621 '''test Mercurial installation
2621 '''test Mercurial installation
2622
2622
2623 Returns 0 on success.
2623 Returns 0 on success.
2624 '''
2624 '''
2625
2625
2626 def writetemp(contents):
2626 def writetemp(contents):
2627 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2627 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2628 f = os.fdopen(fd, "wb")
2628 f = os.fdopen(fd, "wb")
2629 f.write(contents)
2629 f.write(contents)
2630 f.close()
2630 f.close()
2631 return name
2631 return name
2632
2632
2633 problems = 0
2633 problems = 0
2634
2634
2635 # encoding
2635 # encoding
2636 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2636 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2637 try:
2637 try:
2638 encoding.fromlocal("test")
2638 encoding.fromlocal("test")
2639 except error.Abort as inst:
2639 except error.Abort as inst:
2640 ui.write(" %s\n" % inst)
2640 ui.write(" %s\n" % inst)
2641 ui.write(_(" (check that your locale is properly set)\n"))
2641 ui.write(_(" (check that your locale is properly set)\n"))
2642 problems += 1
2642 problems += 1
2643
2643
2644 # Python
2644 # Python
2645 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2645 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2646 ui.status(_("checking Python version (%s)\n")
2646 ui.status(_("checking Python version (%s)\n")
2647 % ("%s.%s.%s" % sys.version_info[:3]))
2647 % ("%s.%s.%s" % sys.version_info[:3]))
2648 ui.status(_("checking Python lib (%s)...\n")
2648 ui.status(_("checking Python lib (%s)...\n")
2649 % os.path.dirname(os.__file__))
2649 % os.path.dirname(os.__file__))
2650
2650
2651 # compiled modules
2651 # compiled modules
2652 ui.status(_("checking installed modules (%s)...\n")
2652 ui.status(_("checking installed modules (%s)...\n")
2653 % os.path.dirname(__file__))
2653 % os.path.dirname(__file__))
2654 try:
2654 try:
2655 import bdiff, mpatch, base85, osutil
2655 import bdiff, mpatch, base85, osutil
2656 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2656 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2657 except Exception as inst:
2657 except Exception as inst:
2658 ui.write(" %s\n" % inst)
2658 ui.write(" %s\n" % inst)
2659 ui.write(_(" One or more extensions could not be found"))
2659 ui.write(_(" One or more extensions could not be found"))
2660 ui.write(_(" (check that you compiled the extensions)\n"))
2660 ui.write(_(" (check that you compiled the extensions)\n"))
2661 problems += 1
2661 problems += 1
2662
2662
2663 # templates
2663 # templates
2664 import templater
2664 import templater
2665 p = templater.templatepaths()
2665 p = templater.templatepaths()
2666 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2666 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2667 if p:
2667 if p:
2668 m = templater.templatepath("map-cmdline.default")
2668 m = templater.templatepath("map-cmdline.default")
2669 if m:
2669 if m:
2670 # template found, check if it is working
2670 # template found, check if it is working
2671 try:
2671 try:
2672 templater.templater(m)
2672 templater.templater(m)
2673 except Exception as inst:
2673 except Exception as inst:
2674 ui.write(" %s\n" % inst)
2674 ui.write(" %s\n" % inst)
2675 p = None
2675 p = None
2676 else:
2676 else:
2677 ui.write(_(" template 'default' not found\n"))
2677 ui.write(_(" template 'default' not found\n"))
2678 p = None
2678 p = None
2679 else:
2679 else:
2680 ui.write(_(" no template directories found\n"))
2680 ui.write(_(" no template directories found\n"))
2681 if not p:
2681 if not p:
2682 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2682 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2683 problems += 1
2683 problems += 1
2684
2684
2685 # editor
2685 # editor
2686 ui.status(_("checking commit editor...\n"))
2686 ui.status(_("checking commit editor...\n"))
2687 editor = ui.geteditor()
2687 editor = ui.geteditor()
2688 editor = util.expandpath(editor)
2688 editor = util.expandpath(editor)
2689 cmdpath = util.findexe(shlex.split(editor)[0])
2689 cmdpath = util.findexe(shlex.split(editor)[0])
2690 if not cmdpath:
2690 if not cmdpath:
2691 if editor == 'vi':
2691 if editor == 'vi':
2692 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2692 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2693 ui.write(_(" (specify a commit editor in your configuration"
2693 ui.write(_(" (specify a commit editor in your configuration"
2694 " file)\n"))
2694 " file)\n"))
2695 else:
2695 else:
2696 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2696 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2697 ui.write(_(" (specify a commit editor in your configuration"
2697 ui.write(_(" (specify a commit editor in your configuration"
2698 " file)\n"))
2698 " file)\n"))
2699 problems += 1
2699 problems += 1
2700
2700
2701 # check username
2701 # check username
2702 ui.status(_("checking username...\n"))
2702 ui.status(_("checking username...\n"))
2703 try:
2703 try:
2704 ui.username()
2704 ui.username()
2705 except error.Abort as e:
2705 except error.Abort as e:
2706 ui.write(" %s\n" % e)
2706 ui.write(" %s\n" % e)
2707 ui.write(_(" (specify a username in your configuration file)\n"))
2707 ui.write(_(" (specify a username in your configuration file)\n"))
2708 problems += 1
2708 problems += 1
2709
2709
2710 if not problems:
2710 if not problems:
2711 ui.status(_("no problems detected\n"))
2711 ui.status(_("no problems detected\n"))
2712 else:
2712 else:
2713 ui.write(_("%s problems detected,"
2713 ui.write(_("%s problems detected,"
2714 " please check your install!\n") % problems)
2714 " please check your install!\n") % problems)
2715
2715
2716 return problems
2716 return problems
2717
2717
2718 @command('debugknown', [], _('REPO ID...'), norepo=True)
2718 @command('debugknown', [], _('REPO ID...'), norepo=True)
2719 def debugknown(ui, repopath, *ids, **opts):
2719 def debugknown(ui, repopath, *ids, **opts):
2720 """test whether node ids are known to a repo
2720 """test whether node ids are known to a repo
2721
2721
2722 Every ID must be a full-length hex node id string. Returns a list of 0s
2722 Every ID must be a full-length hex node id string. Returns a list of 0s
2723 and 1s indicating unknown/known.
2723 and 1s indicating unknown/known.
2724 """
2724 """
2725 repo = hg.peer(ui, opts, repopath)
2725 repo = hg.peer(ui, opts, repopath)
2726 if not repo.capable('known'):
2726 if not repo.capable('known'):
2727 raise error.Abort("known() not supported by target repository")
2727 raise error.Abort("known() not supported by target repository")
2728 flags = repo.known([bin(s) for s in ids])
2728 flags = repo.known([bin(s) for s in ids])
2729 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2729 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2730
2730
2731 @command('debuglabelcomplete', [], _('LABEL...'))
2731 @command('debuglabelcomplete', [], _('LABEL...'))
2732 def debuglabelcomplete(ui, repo, *args):
2732 def debuglabelcomplete(ui, repo, *args):
2733 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2733 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2734 debugnamecomplete(ui, repo, *args)
2734 debugnamecomplete(ui, repo, *args)
2735
2735
2736 @command('debugmergestate', [], '')
2736 @command('debugmergestate', [], '')
2737 def debugmergestate(ui, repo, *args):
2737 def debugmergestate(ui, repo, *args):
2738 """print merge state
2738 """print merge state
2739
2739
2740 Use --verbose to print out information about whether v1 or v2 merge state
2740 Use --verbose to print out information about whether v1 or v2 merge state
2741 was chosen."""
2741 was chosen."""
2742 def _hashornull(h):
2742 def _hashornull(h):
2743 if h == nullhex:
2743 if h == nullhex:
2744 return 'null'
2744 return 'null'
2745 else:
2745 else:
2746 return h
2746 return h
2747
2747
2748 def printrecords(version):
2748 def printrecords(version):
2749 ui.write(('* version %s records\n') % version)
2749 ui.write(('* version %s records\n') % version)
2750 if version == 1:
2750 if version == 1:
2751 records = v1records
2751 records = v1records
2752 else:
2752 else:
2753 records = v2records
2753 records = v2records
2754
2754
2755 for rtype, record in records:
2755 for rtype, record in records:
2756 # pretty print some record types
2756 # pretty print some record types
2757 if rtype == 'L':
2757 if rtype == 'L':
2758 ui.write(('local: %s\n') % record)
2758 ui.write(('local: %s\n') % record)
2759 elif rtype == 'O':
2759 elif rtype == 'O':
2760 ui.write(('other: %s\n') % record)
2760 ui.write(('other: %s\n') % record)
2761 elif rtype == 'm':
2761 elif rtype == 'm':
2762 driver, mdstate = record.split('\0', 1)
2762 driver, mdstate = record.split('\0', 1)
2763 ui.write(('merge driver: %s (state "%s")\n')
2763 ui.write(('merge driver: %s (state "%s")\n')
2764 % (driver, mdstate))
2764 % (driver, mdstate))
2765 elif rtype in 'FDC':
2765 elif rtype in 'FDC':
2766 r = record.split('\0')
2766 r = record.split('\0')
2767 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2767 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2768 if version == 1:
2768 if version == 1:
2769 onode = 'not stored in v1 format'
2769 onode = 'not stored in v1 format'
2770 flags = r[7]
2770 flags = r[7]
2771 else:
2771 else:
2772 onode, flags = r[7:9]
2772 onode, flags = r[7:9]
2773 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2773 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2774 % (f, rtype, state, _hashornull(hash)))
2774 % (f, rtype, state, _hashornull(hash)))
2775 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2775 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2776 ui.write((' ancestor path: %s (node %s)\n')
2776 ui.write((' ancestor path: %s (node %s)\n')
2777 % (afile, _hashornull(anode)))
2777 % (afile, _hashornull(anode)))
2778 ui.write((' other path: %s (node %s)\n')
2778 ui.write((' other path: %s (node %s)\n')
2779 % (ofile, _hashornull(onode)))
2779 % (ofile, _hashornull(onode)))
2780 else:
2780 else:
2781 ui.write(('unrecognized entry: %s\t%s\n')
2781 ui.write(('unrecognized entry: %s\t%s\n')
2782 % (rtype, record.replace('\0', '\t')))
2782 % (rtype, record.replace('\0', '\t')))
2783
2783
2784 # Avoid mergestate.read() since it may raise an exception for unsupported
2784 # Avoid mergestate.read() since it may raise an exception for unsupported
2785 # merge state records. We shouldn't be doing this, but this is OK since this
2785 # merge state records. We shouldn't be doing this, but this is OK since this
2786 # command is pretty low-level.
2786 # command is pretty low-level.
2787 ms = mergemod.mergestate(repo)
2787 ms = mergemod.mergestate(repo)
2788
2788
2789 # sort so that reasonable information is on top
2789 # sort so that reasonable information is on top
2790 v1records = ms._readrecordsv1()
2790 v1records = ms._readrecordsv1()
2791 v2records = ms._readrecordsv2()
2791 v2records = ms._readrecordsv2()
2792 order = 'LOm'
2792 order = 'LOm'
2793 def key(r):
2793 def key(r):
2794 idx = order.find(r[0])
2794 idx = order.find(r[0])
2795 if idx == -1:
2795 if idx == -1:
2796 return (1, r[1])
2796 return (1, r[1])
2797 else:
2797 else:
2798 return (0, idx)
2798 return (0, idx)
2799 v1records.sort(key=key)
2799 v1records.sort(key=key)
2800 v2records.sort(key=key)
2800 v2records.sort(key=key)
2801
2801
2802 if not v1records and not v2records:
2802 if not v1records and not v2records:
2803 ui.write(('no merge state found\n'))
2803 ui.write(('no merge state found\n'))
2804 elif not v2records:
2804 elif not v2records:
2805 ui.note(('no version 2 merge state\n'))
2805 ui.note(('no version 2 merge state\n'))
2806 printrecords(1)
2806 printrecords(1)
2807 elif ms._v1v2match(v1records, v2records):
2807 elif ms._v1v2match(v1records, v2records):
2808 ui.note(('v1 and v2 states match: using v2\n'))
2808 ui.note(('v1 and v2 states match: using v2\n'))
2809 printrecords(2)
2809 printrecords(2)
2810 else:
2810 else:
2811 ui.note(('v1 and v2 states mismatch: using v1\n'))
2811 ui.note(('v1 and v2 states mismatch: using v1\n'))
2812 printrecords(1)
2812 printrecords(1)
2813 if ui.verbose:
2813 if ui.verbose:
2814 printrecords(2)
2814 printrecords(2)
2815
2815
2816 @command('debugnamecomplete', [], _('NAME...'))
2816 @command('debugnamecomplete', [], _('NAME...'))
2817 def debugnamecomplete(ui, repo, *args):
2817 def debugnamecomplete(ui, repo, *args):
2818 '''complete "names" - tags, open branch names, bookmark names'''
2818 '''complete "names" - tags, open branch names, bookmark names'''
2819
2819
2820 names = set()
2820 names = set()
2821 # since we previously only listed open branches, we will handle that
2821 # since we previously only listed open branches, we will handle that
2822 # specially (after this for loop)
2822 # specially (after this for loop)
2823 for name, ns in repo.names.iteritems():
2823 for name, ns in repo.names.iteritems():
2824 if name != 'branches':
2824 if name != 'branches':
2825 names.update(ns.listnames(repo))
2825 names.update(ns.listnames(repo))
2826 names.update(tag for (tag, heads, tip, closed)
2826 names.update(tag for (tag, heads, tip, closed)
2827 in repo.branchmap().iterbranches() if not closed)
2827 in repo.branchmap().iterbranches() if not closed)
2828 completions = set()
2828 completions = set()
2829 if not args:
2829 if not args:
2830 args = ['']
2830 args = ['']
2831 for a in args:
2831 for a in args:
2832 completions.update(n for n in names if n.startswith(a))
2832 completions.update(n for n in names if n.startswith(a))
2833 ui.write('\n'.join(sorted(completions)))
2833 ui.write('\n'.join(sorted(completions)))
2834 ui.write('\n')
2834 ui.write('\n')
2835
2835
2836 @command('debuglocks',
2836 @command('debuglocks',
2837 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2837 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2838 ('W', 'force-wlock', None,
2838 ('W', 'force-wlock', None,
2839 _('free the working state lock (DANGEROUS)'))],
2839 _('free the working state lock (DANGEROUS)'))],
2840 _('[OPTION]...'))
2840 _('[OPTION]...'))
2841 def debuglocks(ui, repo, **opts):
2841 def debuglocks(ui, repo, **opts):
2842 """show or modify state of locks
2842 """show or modify state of locks
2843
2843
2844 By default, this command will show which locks are held. This
2844 By default, this command will show which locks are held. This
2845 includes the user and process holding the lock, the amount of time
2845 includes the user and process holding the lock, the amount of time
2846 the lock has been held, and the machine name where the process is
2846 the lock has been held, and the machine name where the process is
2847 running if it's not local.
2847 running if it's not local.
2848
2848
2849 Locks protect the integrity of Mercurial's data, so should be
2849 Locks protect the integrity of Mercurial's data, so should be
2850 treated with care. System crashes or other interruptions may cause
2850 treated with care. System crashes or other interruptions may cause
2851 locks to not be properly released, though Mercurial will usually
2851 locks to not be properly released, though Mercurial will usually
2852 detect and remove such stale locks automatically.
2852 detect and remove such stale locks automatically.
2853
2853
2854 However, detecting stale locks may not always be possible (for
2854 However, detecting stale locks may not always be possible (for
2855 instance, on a shared filesystem). Removing locks may also be
2855 instance, on a shared filesystem). Removing locks may also be
2856 blocked by filesystem permissions.
2856 blocked by filesystem permissions.
2857
2857
2858 Returns 0 if no locks are held.
2858 Returns 0 if no locks are held.
2859
2859
2860 """
2860 """
2861
2861
2862 if opts.get('force_lock'):
2862 if opts.get('force_lock'):
2863 repo.svfs.unlink('lock')
2863 repo.svfs.unlink('lock')
2864 if opts.get('force_wlock'):
2864 if opts.get('force_wlock'):
2865 repo.vfs.unlink('wlock')
2865 repo.vfs.unlink('wlock')
2866 if opts.get('force_lock') or opts.get('force_lock'):
2866 if opts.get('force_lock') or opts.get('force_lock'):
2867 return 0
2867 return 0
2868
2868
2869 now = time.time()
2869 now = time.time()
2870 held = 0
2870 held = 0
2871
2871
2872 def report(vfs, name, method):
2872 def report(vfs, name, method):
2873 # this causes stale locks to get reaped for more accurate reporting
2873 # this causes stale locks to get reaped for more accurate reporting
2874 try:
2874 try:
2875 l = method(False)
2875 l = method(False)
2876 except error.LockHeld:
2876 except error.LockHeld:
2877 l = None
2877 l = None
2878
2878
2879 if l:
2879 if l:
2880 l.release()
2880 l.release()
2881 else:
2881 else:
2882 try:
2882 try:
2883 stat = vfs.lstat(name)
2883 stat = vfs.lstat(name)
2884 age = now - stat.st_mtime
2884 age = now - stat.st_mtime
2885 user = util.username(stat.st_uid)
2885 user = util.username(stat.st_uid)
2886 locker = vfs.readlock(name)
2886 locker = vfs.readlock(name)
2887 if ":" in locker:
2887 if ":" in locker:
2888 host, pid = locker.split(':')
2888 host, pid = locker.split(':')
2889 if host == socket.gethostname():
2889 if host == socket.gethostname():
2890 locker = 'user %s, process %s' % (user, pid)
2890 locker = 'user %s, process %s' % (user, pid)
2891 else:
2891 else:
2892 locker = 'user %s, process %s, host %s' \
2892 locker = 'user %s, process %s, host %s' \
2893 % (user, pid, host)
2893 % (user, pid, host)
2894 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2894 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2895 return 1
2895 return 1
2896 except OSError as e:
2896 except OSError as e:
2897 if e.errno != errno.ENOENT:
2897 if e.errno != errno.ENOENT:
2898 raise
2898 raise
2899
2899
2900 ui.write("%-6s free\n" % (name + ":"))
2900 ui.write("%-6s free\n" % (name + ":"))
2901 return 0
2901 return 0
2902
2902
2903 held += report(repo.svfs, "lock", repo.lock)
2903 held += report(repo.svfs, "lock", repo.lock)
2904 held += report(repo.vfs, "wlock", repo.wlock)
2904 held += report(repo.vfs, "wlock", repo.wlock)
2905
2905
2906 return held
2906 return held
2907
2907
2908 @command('debugobsolete',
2908 @command('debugobsolete',
2909 [('', 'flags', 0, _('markers flag')),
2909 [('', 'flags', 0, _('markers flag')),
2910 ('', 'record-parents', False,
2910 ('', 'record-parents', False,
2911 _('record parent information for the precursor')),
2911 _('record parent information for the precursor')),
2912 ('r', 'rev', [], _('display markers relevant to REV')),
2912 ('r', 'rev', [], _('display markers relevant to REV')),
2913 ] + commitopts2,
2913 ] + commitopts2,
2914 _('[OBSOLETED [REPLACEMENT ...]]'))
2914 _('[OBSOLETED [REPLACEMENT ...]]'))
2915 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2915 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2916 """create arbitrary obsolete marker
2916 """create arbitrary obsolete marker
2917
2917
2918 With no arguments, displays the list of obsolescence markers."""
2918 With no arguments, displays the list of obsolescence markers."""
2919
2919
2920 def parsenodeid(s):
2920 def parsenodeid(s):
2921 try:
2921 try:
2922 # We do not use revsingle/revrange functions here to accept
2922 # We do not use revsingle/revrange functions here to accept
2923 # arbitrary node identifiers, possibly not present in the
2923 # arbitrary node identifiers, possibly not present in the
2924 # local repository.
2924 # local repository.
2925 n = bin(s)
2925 n = bin(s)
2926 if len(n) != len(nullid):
2926 if len(n) != len(nullid):
2927 raise TypeError()
2927 raise TypeError()
2928 return n
2928 return n
2929 except TypeError:
2929 except TypeError:
2930 raise error.Abort('changeset references must be full hexadecimal '
2930 raise error.Abort('changeset references must be full hexadecimal '
2931 'node identifiers')
2931 'node identifiers')
2932
2932
2933 if precursor is not None:
2933 if precursor is not None:
2934 if opts['rev']:
2934 if opts['rev']:
2935 raise error.Abort('cannot select revision when creating marker')
2935 raise error.Abort('cannot select revision when creating marker')
2936 metadata = {}
2936 metadata = {}
2937 metadata['user'] = opts['user'] or ui.username()
2937 metadata['user'] = opts['user'] or ui.username()
2938 succs = tuple(parsenodeid(succ) for succ in successors)
2938 succs = tuple(parsenodeid(succ) for succ in successors)
2939 l = repo.lock()
2939 l = repo.lock()
2940 try:
2940 try:
2941 tr = repo.transaction('debugobsolete')
2941 tr = repo.transaction('debugobsolete')
2942 try:
2942 try:
2943 date = opts.get('date')
2943 date = opts.get('date')
2944 if date:
2944 if date:
2945 date = util.parsedate(date)
2945 date = util.parsedate(date)
2946 else:
2946 else:
2947 date = None
2947 date = None
2948 prec = parsenodeid(precursor)
2948 prec = parsenodeid(precursor)
2949 parents = None
2949 parents = None
2950 if opts['record_parents']:
2950 if opts['record_parents']:
2951 if prec not in repo.unfiltered():
2951 if prec not in repo.unfiltered():
2952 raise error.Abort('cannot used --record-parents on '
2952 raise error.Abort('cannot used --record-parents on '
2953 'unknown changesets')
2953 'unknown changesets')
2954 parents = repo.unfiltered()[prec].parents()
2954 parents = repo.unfiltered()[prec].parents()
2955 parents = tuple(p.node() for p in parents)
2955 parents = tuple(p.node() for p in parents)
2956 repo.obsstore.create(tr, prec, succs, opts['flags'],
2956 repo.obsstore.create(tr, prec, succs, opts['flags'],
2957 parents=parents, date=date,
2957 parents=parents, date=date,
2958 metadata=metadata)
2958 metadata=metadata)
2959 tr.close()
2959 tr.close()
2960 except ValueError as exc:
2960 except ValueError as exc:
2961 raise error.Abort(_('bad obsmarker input: %s') % exc)
2961 raise error.Abort(_('bad obsmarker input: %s') % exc)
2962 finally:
2962 finally:
2963 tr.release()
2963 tr.release()
2964 finally:
2964 finally:
2965 l.release()
2965 l.release()
2966 else:
2966 else:
2967 if opts['rev']:
2967 if opts['rev']:
2968 revs = scmutil.revrange(repo, opts['rev'])
2968 revs = scmutil.revrange(repo, opts['rev'])
2969 nodes = [repo[r].node() for r in revs]
2969 nodes = [repo[r].node() for r in revs]
2970 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2970 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2971 markers.sort(key=lambda x: x._data)
2971 markers.sort(key=lambda x: x._data)
2972 else:
2972 else:
2973 markers = obsolete.getmarkers(repo)
2973 markers = obsolete.getmarkers(repo)
2974
2974
2975 for m in markers:
2975 for m in markers:
2976 cmdutil.showmarker(ui, m)
2976 cmdutil.showmarker(ui, m)
2977
2977
2978 @command('debugpathcomplete',
2978 @command('debugpathcomplete',
2979 [('f', 'full', None, _('complete an entire path')),
2979 [('f', 'full', None, _('complete an entire path')),
2980 ('n', 'normal', None, _('show only normal files')),
2980 ('n', 'normal', None, _('show only normal files')),
2981 ('a', 'added', None, _('show only added files')),
2981 ('a', 'added', None, _('show only added files')),
2982 ('r', 'removed', None, _('show only removed files'))],
2982 ('r', 'removed', None, _('show only removed files'))],
2983 _('FILESPEC...'))
2983 _('FILESPEC...'))
2984 def debugpathcomplete(ui, repo, *specs, **opts):
2984 def debugpathcomplete(ui, repo, *specs, **opts):
2985 '''complete part or all of a tracked path
2985 '''complete part or all of a tracked path
2986
2986
2987 This command supports shells that offer path name completion. It
2987 This command supports shells that offer path name completion. It
2988 currently completes only files already known to the dirstate.
2988 currently completes only files already known to the dirstate.
2989
2989
2990 Completion extends only to the next path segment unless
2990 Completion extends only to the next path segment unless
2991 --full is specified, in which case entire paths are used.'''
2991 --full is specified, in which case entire paths are used.'''
2992
2992
2993 def complete(path, acceptable):
2993 def complete(path, acceptable):
2994 dirstate = repo.dirstate
2994 dirstate = repo.dirstate
2995 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2995 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2996 rootdir = repo.root + os.sep
2996 rootdir = repo.root + os.sep
2997 if spec != repo.root and not spec.startswith(rootdir):
2997 if spec != repo.root and not spec.startswith(rootdir):
2998 return [], []
2998 return [], []
2999 if os.path.isdir(spec):
2999 if os.path.isdir(spec):
3000 spec += '/'
3000 spec += '/'
3001 spec = spec[len(rootdir):]
3001 spec = spec[len(rootdir):]
3002 fixpaths = os.sep != '/'
3002 fixpaths = os.sep != '/'
3003 if fixpaths:
3003 if fixpaths:
3004 spec = spec.replace(os.sep, '/')
3004 spec = spec.replace(os.sep, '/')
3005 speclen = len(spec)
3005 speclen = len(spec)
3006 fullpaths = opts['full']
3006 fullpaths = opts['full']
3007 files, dirs = set(), set()
3007 files, dirs = set(), set()
3008 adddir, addfile = dirs.add, files.add
3008 adddir, addfile = dirs.add, files.add
3009 for f, st in dirstate.iteritems():
3009 for f, st in dirstate.iteritems():
3010 if f.startswith(spec) and st[0] in acceptable:
3010 if f.startswith(spec) and st[0] in acceptable:
3011 if fixpaths:
3011 if fixpaths:
3012 f = f.replace('/', os.sep)
3012 f = f.replace('/', os.sep)
3013 if fullpaths:
3013 if fullpaths:
3014 addfile(f)
3014 addfile(f)
3015 continue
3015 continue
3016 s = f.find(os.sep, speclen)
3016 s = f.find(os.sep, speclen)
3017 if s >= 0:
3017 if s >= 0:
3018 adddir(f[:s])
3018 adddir(f[:s])
3019 else:
3019 else:
3020 addfile(f)
3020 addfile(f)
3021 return files, dirs
3021 return files, dirs
3022
3022
3023 acceptable = ''
3023 acceptable = ''
3024 if opts['normal']:
3024 if opts['normal']:
3025 acceptable += 'nm'
3025 acceptable += 'nm'
3026 if opts['added']:
3026 if opts['added']:
3027 acceptable += 'a'
3027 acceptable += 'a'
3028 if opts['removed']:
3028 if opts['removed']:
3029 acceptable += 'r'
3029 acceptable += 'r'
3030 cwd = repo.getcwd()
3030 cwd = repo.getcwd()
3031 if not specs:
3031 if not specs:
3032 specs = ['.']
3032 specs = ['.']
3033
3033
3034 files, dirs = set(), set()
3034 files, dirs = set(), set()
3035 for spec in specs:
3035 for spec in specs:
3036 f, d = complete(spec, acceptable or 'nmar')
3036 f, d = complete(spec, acceptable or 'nmar')
3037 files.update(f)
3037 files.update(f)
3038 dirs.update(d)
3038 dirs.update(d)
3039 files.update(dirs)
3039 files.update(dirs)
3040 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3040 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3041 ui.write('\n')
3041 ui.write('\n')
3042
3042
3043 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3043 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3044 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3044 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3045 '''access the pushkey key/value protocol
3045 '''access the pushkey key/value protocol
3046
3046
3047 With two args, list the keys in the given namespace.
3047 With two args, list the keys in the given namespace.
3048
3048
3049 With five args, set a key to new if it currently is set to old.
3049 With five args, set a key to new if it currently is set to old.
3050 Reports success or failure.
3050 Reports success or failure.
3051 '''
3051 '''
3052
3052
3053 target = hg.peer(ui, {}, repopath)
3053 target = hg.peer(ui, {}, repopath)
3054 if keyinfo:
3054 if keyinfo:
3055 key, old, new = keyinfo
3055 key, old, new = keyinfo
3056 r = target.pushkey(namespace, key, old, new)
3056 r = target.pushkey(namespace, key, old, new)
3057 ui.status(str(r) + '\n')
3057 ui.status(str(r) + '\n')
3058 return not r
3058 return not r
3059 else:
3059 else:
3060 for k, v in sorted(target.listkeys(namespace).iteritems()):
3060 for k, v in sorted(target.listkeys(namespace).iteritems()):
3061 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3061 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3062 v.encode('string-escape')))
3062 v.encode('string-escape')))
3063
3063
3064 @command('debugpvec', [], _('A B'))
3064 @command('debugpvec', [], _('A B'))
3065 def debugpvec(ui, repo, a, b=None):
3065 def debugpvec(ui, repo, a, b=None):
3066 ca = scmutil.revsingle(repo, a)
3066 ca = scmutil.revsingle(repo, a)
3067 cb = scmutil.revsingle(repo, b)
3067 cb = scmutil.revsingle(repo, b)
3068 pa = pvec.ctxpvec(ca)
3068 pa = pvec.ctxpvec(ca)
3069 pb = pvec.ctxpvec(cb)
3069 pb = pvec.ctxpvec(cb)
3070 if pa == pb:
3070 if pa == pb:
3071 rel = "="
3071 rel = "="
3072 elif pa > pb:
3072 elif pa > pb:
3073 rel = ">"
3073 rel = ">"
3074 elif pa < pb:
3074 elif pa < pb:
3075 rel = "<"
3075 rel = "<"
3076 elif pa | pb:
3076 elif pa | pb:
3077 rel = "|"
3077 rel = "|"
3078 ui.write(_("a: %s\n") % pa)
3078 ui.write(_("a: %s\n") % pa)
3079 ui.write(_("b: %s\n") % pb)
3079 ui.write(_("b: %s\n") % pb)
3080 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3080 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3081 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3081 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3082 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3082 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3083 pa.distance(pb), rel))
3083 pa.distance(pb), rel))
3084
3084
3085 @command('debugrebuilddirstate|debugrebuildstate',
3085 @command('debugrebuilddirstate|debugrebuildstate',
3086 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3086 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3087 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3087 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3088 'the working copy parent')),
3088 'the working copy parent')),
3089 ],
3089 ],
3090 _('[-r REV]'))
3090 _('[-r REV]'))
3091 def debugrebuilddirstate(ui, repo, rev, **opts):
3091 def debugrebuilddirstate(ui, repo, rev, **opts):
3092 """rebuild the dirstate as it would look like for the given revision
3092 """rebuild the dirstate as it would look like for the given revision
3093
3093
3094 If no revision is specified the first current parent will be used.
3094 If no revision is specified the first current parent will be used.
3095
3095
3096 The dirstate will be set to the files of the given revision.
3096 The dirstate will be set to the files of the given revision.
3097 The actual working directory content or existing dirstate
3097 The actual working directory content or existing dirstate
3098 information such as adds or removes is not considered.
3098 information such as adds or removes is not considered.
3099
3099
3100 ``minimal`` will only rebuild the dirstate status for files that claim to be
3100 ``minimal`` will only rebuild the dirstate status for files that claim to be
3101 tracked but are not in the parent manifest, or that exist in the parent
3101 tracked but are not in the parent manifest, or that exist in the parent
3102 manifest but are not in the dirstate. It will not change adds, removes, or
3102 manifest but are not in the dirstate. It will not change adds, removes, or
3103 modified files that are in the working copy parent.
3103 modified files that are in the working copy parent.
3104
3104
3105 One use of this command is to make the next :hg:`status` invocation
3105 One use of this command is to make the next :hg:`status` invocation
3106 check the actual file content.
3106 check the actual file content.
3107 """
3107 """
3108 ctx = scmutil.revsingle(repo, rev)
3108 ctx = scmutil.revsingle(repo, rev)
3109 wlock = repo.wlock()
3109 wlock = repo.wlock()
3110 try:
3110 try:
3111 dirstate = repo.dirstate
3111 dirstate = repo.dirstate
3112 changedfiles = None
3112 changedfiles = None
3113 # See command doc for what minimal does.
3113 # See command doc for what minimal does.
3114 if opts.get('minimal'):
3114 if opts.get('minimal'):
3115 manifestfiles = set(ctx.manifest().keys())
3115 manifestfiles = set(ctx.manifest().keys())
3116 dirstatefiles = set(dirstate)
3116 dirstatefiles = set(dirstate)
3117 manifestonly = manifestfiles - dirstatefiles
3117 manifestonly = manifestfiles - dirstatefiles
3118 dsonly = dirstatefiles - manifestfiles
3118 dsonly = dirstatefiles - manifestfiles
3119 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3119 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3120 changedfiles = manifestonly | dsnotadded
3120 changedfiles = manifestonly | dsnotadded
3121
3121
3122 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3122 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3123 finally:
3123 finally:
3124 wlock.release()
3124 wlock.release()
3125
3125
3126 @command('debugrebuildfncache', [], '')
3126 @command('debugrebuildfncache', [], '')
3127 def debugrebuildfncache(ui, repo):
3127 def debugrebuildfncache(ui, repo):
3128 """rebuild the fncache file"""
3128 """rebuild the fncache file"""
3129 repair.rebuildfncache(ui, repo)
3129 repair.rebuildfncache(ui, repo)
3130
3130
3131 @command('debugrename',
3131 @command('debugrename',
3132 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3132 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3133 _('[-r REV] FILE'))
3133 _('[-r REV] FILE'))
3134 def debugrename(ui, repo, file1, *pats, **opts):
3134 def debugrename(ui, repo, file1, *pats, **opts):
3135 """dump rename information"""
3135 """dump rename information"""
3136
3136
3137 ctx = scmutil.revsingle(repo, opts.get('rev'))
3137 ctx = scmutil.revsingle(repo, opts.get('rev'))
3138 m = scmutil.match(ctx, (file1,) + pats, opts)
3138 m = scmutil.match(ctx, (file1,) + pats, opts)
3139 for abs in ctx.walk(m):
3139 for abs in ctx.walk(m):
3140 fctx = ctx[abs]
3140 fctx = ctx[abs]
3141 o = fctx.filelog().renamed(fctx.filenode())
3141 o = fctx.filelog().renamed(fctx.filenode())
3142 rel = m.rel(abs)
3142 rel = m.rel(abs)
3143 if o:
3143 if o:
3144 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3144 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3145 else:
3145 else:
3146 ui.write(_("%s not renamed\n") % rel)
3146 ui.write(_("%s not renamed\n") % rel)
3147
3147
3148 @command('debugrevlog', debugrevlogopts +
3148 @command('debugrevlog', debugrevlogopts +
3149 [('d', 'dump', False, _('dump index data'))],
3149 [('d', 'dump', False, _('dump index data'))],
3150 _('-c|-m|FILE'),
3150 _('-c|-m|FILE'),
3151 optionalrepo=True)
3151 optionalrepo=True)
3152 def debugrevlog(ui, repo, file_=None, **opts):
3152 def debugrevlog(ui, repo, file_=None, **opts):
3153 """show data and statistics about a revlog"""
3153 """show data and statistics about a revlog"""
3154 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3154 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3155
3155
3156 if opts.get("dump"):
3156 if opts.get("dump"):
3157 numrevs = len(r)
3157 numrevs = len(r)
3158 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3158 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3159 " rawsize totalsize compression heads chainlen\n")
3159 " rawsize totalsize compression heads chainlen\n")
3160 ts = 0
3160 ts = 0
3161 heads = set()
3161 heads = set()
3162
3162
3163 for rev in xrange(numrevs):
3163 for rev in xrange(numrevs):
3164 dbase = r.deltaparent(rev)
3164 dbase = r.deltaparent(rev)
3165 if dbase == -1:
3165 if dbase == -1:
3166 dbase = rev
3166 dbase = rev
3167 cbase = r.chainbase(rev)
3167 cbase = r.chainbase(rev)
3168 clen = r.chainlen(rev)
3168 clen = r.chainlen(rev)
3169 p1, p2 = r.parentrevs(rev)
3169 p1, p2 = r.parentrevs(rev)
3170 rs = r.rawsize(rev)
3170 rs = r.rawsize(rev)
3171 ts = ts + rs
3171 ts = ts + rs
3172 heads -= set(r.parentrevs(rev))
3172 heads -= set(r.parentrevs(rev))
3173 heads.add(rev)
3173 heads.add(rev)
3174 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3174 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3175 "%11d %5d %8d\n" %
3175 "%11d %5d %8d\n" %
3176 (rev, p1, p2, r.start(rev), r.end(rev),
3176 (rev, p1, p2, r.start(rev), r.end(rev),
3177 r.start(dbase), r.start(cbase),
3177 r.start(dbase), r.start(cbase),
3178 r.start(p1), r.start(p2),
3178 r.start(p1), r.start(p2),
3179 rs, ts, ts / r.end(rev), len(heads), clen))
3179 rs, ts, ts / r.end(rev), len(heads), clen))
3180 return 0
3180 return 0
3181
3181
3182 v = r.version
3182 v = r.version
3183 format = v & 0xFFFF
3183 format = v & 0xFFFF
3184 flags = []
3184 flags = []
3185 gdelta = False
3185 gdelta = False
3186 if v & revlog.REVLOGNGINLINEDATA:
3186 if v & revlog.REVLOGNGINLINEDATA:
3187 flags.append('inline')
3187 flags.append('inline')
3188 if v & revlog.REVLOGGENERALDELTA:
3188 if v & revlog.REVLOGGENERALDELTA:
3189 gdelta = True
3189 gdelta = True
3190 flags.append('generaldelta')
3190 flags.append('generaldelta')
3191 if not flags:
3191 if not flags:
3192 flags = ['(none)']
3192 flags = ['(none)']
3193
3193
3194 nummerges = 0
3194 nummerges = 0
3195 numfull = 0
3195 numfull = 0
3196 numprev = 0
3196 numprev = 0
3197 nump1 = 0
3197 nump1 = 0
3198 nump2 = 0
3198 nump2 = 0
3199 numother = 0
3199 numother = 0
3200 nump1prev = 0
3200 nump1prev = 0
3201 nump2prev = 0
3201 nump2prev = 0
3202 chainlengths = []
3202 chainlengths = []
3203
3203
3204 datasize = [None, 0, 0L]
3204 datasize = [None, 0, 0L]
3205 fullsize = [None, 0, 0L]
3205 fullsize = [None, 0, 0L]
3206 deltasize = [None, 0, 0L]
3206 deltasize = [None, 0, 0L]
3207
3207
3208 def addsize(size, l):
3208 def addsize(size, l):
3209 if l[0] is None or size < l[0]:
3209 if l[0] is None or size < l[0]:
3210 l[0] = size
3210 l[0] = size
3211 if size > l[1]:
3211 if size > l[1]:
3212 l[1] = size
3212 l[1] = size
3213 l[2] += size
3213 l[2] += size
3214
3214
3215 numrevs = len(r)
3215 numrevs = len(r)
3216 for rev in xrange(numrevs):
3216 for rev in xrange(numrevs):
3217 p1, p2 = r.parentrevs(rev)
3217 p1, p2 = r.parentrevs(rev)
3218 delta = r.deltaparent(rev)
3218 delta = r.deltaparent(rev)
3219 if format > 0:
3219 if format > 0:
3220 addsize(r.rawsize(rev), datasize)
3220 addsize(r.rawsize(rev), datasize)
3221 if p2 != nullrev:
3221 if p2 != nullrev:
3222 nummerges += 1
3222 nummerges += 1
3223 size = r.length(rev)
3223 size = r.length(rev)
3224 if delta == nullrev:
3224 if delta == nullrev:
3225 chainlengths.append(0)
3225 chainlengths.append(0)
3226 numfull += 1
3226 numfull += 1
3227 addsize(size, fullsize)
3227 addsize(size, fullsize)
3228 else:
3228 else:
3229 chainlengths.append(chainlengths[delta] + 1)
3229 chainlengths.append(chainlengths[delta] + 1)
3230 addsize(size, deltasize)
3230 addsize(size, deltasize)
3231 if delta == rev - 1:
3231 if delta == rev - 1:
3232 numprev += 1
3232 numprev += 1
3233 if delta == p1:
3233 if delta == p1:
3234 nump1prev += 1
3234 nump1prev += 1
3235 elif delta == p2:
3235 elif delta == p2:
3236 nump2prev += 1
3236 nump2prev += 1
3237 elif delta == p1:
3237 elif delta == p1:
3238 nump1 += 1
3238 nump1 += 1
3239 elif delta == p2:
3239 elif delta == p2:
3240 nump2 += 1
3240 nump2 += 1
3241 elif delta != nullrev:
3241 elif delta != nullrev:
3242 numother += 1
3242 numother += 1
3243
3243
3244 # Adjust size min value for empty cases
3244 # Adjust size min value for empty cases
3245 for size in (datasize, fullsize, deltasize):
3245 for size in (datasize, fullsize, deltasize):
3246 if size[0] is None:
3246 if size[0] is None:
3247 size[0] = 0
3247 size[0] = 0
3248
3248
3249 numdeltas = numrevs - numfull
3249 numdeltas = numrevs - numfull
3250 numoprev = numprev - nump1prev - nump2prev
3250 numoprev = numprev - nump1prev - nump2prev
3251 totalrawsize = datasize[2]
3251 totalrawsize = datasize[2]
3252 datasize[2] /= numrevs
3252 datasize[2] /= numrevs
3253 fulltotal = fullsize[2]
3253 fulltotal = fullsize[2]
3254 fullsize[2] /= numfull
3254 fullsize[2] /= numfull
3255 deltatotal = deltasize[2]
3255 deltatotal = deltasize[2]
3256 if numrevs - numfull > 0:
3256 if numrevs - numfull > 0:
3257 deltasize[2] /= numrevs - numfull
3257 deltasize[2] /= numrevs - numfull
3258 totalsize = fulltotal + deltatotal
3258 totalsize = fulltotal + deltatotal
3259 avgchainlen = sum(chainlengths) / numrevs
3259 avgchainlen = sum(chainlengths) / numrevs
3260 maxchainlen = max(chainlengths)
3260 maxchainlen = max(chainlengths)
3261 compratio = 1
3261 compratio = 1
3262 if totalsize:
3262 if totalsize:
3263 compratio = totalrawsize / totalsize
3263 compratio = totalrawsize / totalsize
3264
3264
3265 basedfmtstr = '%%%dd\n'
3265 basedfmtstr = '%%%dd\n'
3266 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3266 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3267
3267
3268 def dfmtstr(max):
3268 def dfmtstr(max):
3269 return basedfmtstr % len(str(max))
3269 return basedfmtstr % len(str(max))
3270 def pcfmtstr(max, padding=0):
3270 def pcfmtstr(max, padding=0):
3271 return basepcfmtstr % (len(str(max)), ' ' * padding)
3271 return basepcfmtstr % (len(str(max)), ' ' * padding)
3272
3272
3273 def pcfmt(value, total):
3273 def pcfmt(value, total):
3274 if total:
3274 if total:
3275 return (value, 100 * float(value) / total)
3275 return (value, 100 * float(value) / total)
3276 else:
3276 else:
3277 return value, 100.0
3277 return value, 100.0
3278
3278
3279 ui.write(('format : %d\n') % format)
3279 ui.write(('format : %d\n') % format)
3280 ui.write(('flags : %s\n') % ', '.join(flags))
3280 ui.write(('flags : %s\n') % ', '.join(flags))
3281
3281
3282 ui.write('\n')
3282 ui.write('\n')
3283 fmt = pcfmtstr(totalsize)
3283 fmt = pcfmtstr(totalsize)
3284 fmt2 = dfmtstr(totalsize)
3284 fmt2 = dfmtstr(totalsize)
3285 ui.write(('revisions : ') + fmt2 % numrevs)
3285 ui.write(('revisions : ') + fmt2 % numrevs)
3286 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3286 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3287 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3287 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3288 ui.write(('revisions : ') + fmt2 % numrevs)
3288 ui.write(('revisions : ') + fmt2 % numrevs)
3289 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3289 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3290 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3290 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3291 ui.write(('revision size : ') + fmt2 % totalsize)
3291 ui.write(('revision size : ') + fmt2 % totalsize)
3292 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3292 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3293 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3293 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3294
3294
3295 ui.write('\n')
3295 ui.write('\n')
3296 fmt = dfmtstr(max(avgchainlen, compratio))
3296 fmt = dfmtstr(max(avgchainlen, compratio))
3297 ui.write(('avg chain length : ') + fmt % avgchainlen)
3297 ui.write(('avg chain length : ') + fmt % avgchainlen)
3298 ui.write(('max chain length : ') + fmt % maxchainlen)
3298 ui.write(('max chain length : ') + fmt % maxchainlen)
3299 ui.write(('compression ratio : ') + fmt % compratio)
3299 ui.write(('compression ratio : ') + fmt % compratio)
3300
3300
3301 if format > 0:
3301 if format > 0:
3302 ui.write('\n')
3302 ui.write('\n')
3303 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3303 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3304 % tuple(datasize))
3304 % tuple(datasize))
3305 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3305 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3306 % tuple(fullsize))
3306 % tuple(fullsize))
3307 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3307 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3308 % tuple(deltasize))
3308 % tuple(deltasize))
3309
3309
3310 if numdeltas > 0:
3310 if numdeltas > 0:
3311 ui.write('\n')
3311 ui.write('\n')
3312 fmt = pcfmtstr(numdeltas)
3312 fmt = pcfmtstr(numdeltas)
3313 fmt2 = pcfmtstr(numdeltas, 4)
3313 fmt2 = pcfmtstr(numdeltas, 4)
3314 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3314 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3315 if numprev > 0:
3315 if numprev > 0:
3316 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3316 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3317 numprev))
3317 numprev))
3318 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3318 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3319 numprev))
3319 numprev))
3320 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3320 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3321 numprev))
3321 numprev))
3322 if gdelta:
3322 if gdelta:
3323 ui.write(('deltas against p1 : ')
3323 ui.write(('deltas against p1 : ')
3324 + fmt % pcfmt(nump1, numdeltas))
3324 + fmt % pcfmt(nump1, numdeltas))
3325 ui.write(('deltas against p2 : ')
3325 ui.write(('deltas against p2 : ')
3326 + fmt % pcfmt(nump2, numdeltas))
3326 + fmt % pcfmt(nump2, numdeltas))
3327 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3327 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3328 numdeltas))
3328 numdeltas))
3329
3329
3330 @command('debugrevspec',
3330 @command('debugrevspec',
3331 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3331 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3332 ('REVSPEC'))
3332 ('REVSPEC'))
3333 def debugrevspec(ui, repo, expr, **opts):
3333 def debugrevspec(ui, repo, expr, **opts):
3334 """parse and apply a revision specification
3334 """parse and apply a revision specification
3335
3335
3336 Use --verbose to print the parsed tree before and after aliases
3336 Use --verbose to print the parsed tree before and after aliases
3337 expansion.
3337 expansion.
3338 """
3338 """
3339 if ui.verbose:
3339 if ui.verbose:
3340 tree = revset.parse(expr, lookup=repo.__contains__)
3340 tree = revset.parse(expr, lookup=repo.__contains__)
3341 ui.note(revset.prettyformat(tree), "\n")
3341 ui.note(revset.prettyformat(tree), "\n")
3342 newtree = revset.findaliases(ui, tree)
3342 newtree = revset.findaliases(ui, tree)
3343 if newtree != tree:
3343 if newtree != tree:
3344 ui.note(revset.prettyformat(newtree), "\n")
3344 ui.note(revset.prettyformat(newtree), "\n")
3345 tree = newtree
3345 tree = newtree
3346 newtree = revset.foldconcat(tree)
3346 newtree = revset.foldconcat(tree)
3347 if newtree != tree:
3347 if newtree != tree:
3348 ui.note(revset.prettyformat(newtree), "\n")
3348 ui.note(revset.prettyformat(newtree), "\n")
3349 if opts["optimize"]:
3349 if opts["optimize"]:
3350 weight, optimizedtree = revset.optimize(newtree, True)
3350 weight, optimizedtree = revset.optimize(newtree, True)
3351 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3351 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3352 func = revset.match(ui, expr, repo)
3352 func = revset.match(ui, expr, repo)
3353 revs = func(repo)
3353 revs = func(repo)
3354 if ui.verbose:
3354 if ui.verbose:
3355 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3355 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3356 for c in revs:
3356 for c in revs:
3357 ui.write("%s\n" % c)
3357 ui.write("%s\n" % c)
3358
3358
3359 @command('debugsetparents', [], _('REV1 [REV2]'))
3359 @command('debugsetparents', [], _('REV1 [REV2]'))
3360 def debugsetparents(ui, repo, rev1, rev2=None):
3360 def debugsetparents(ui, repo, rev1, rev2=None):
3361 """manually set the parents of the current working directory
3361 """manually set the parents of the current working directory
3362
3362
3363 This is useful for writing repository conversion tools, but should
3363 This is useful for writing repository conversion tools, but should
3364 be used with care. For example, neither the working directory nor the
3364 be used with care. For example, neither the working directory nor the
3365 dirstate is updated, so file status may be incorrect after running this
3365 dirstate is updated, so file status may be incorrect after running this
3366 command.
3366 command.
3367
3367
3368 Returns 0 on success.
3368 Returns 0 on success.
3369 """
3369 """
3370
3370
3371 r1 = scmutil.revsingle(repo, rev1).node()
3371 r1 = scmutil.revsingle(repo, rev1).node()
3372 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3372 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3373
3373
3374 wlock = repo.wlock()
3374 wlock = repo.wlock()
3375 try:
3375 try:
3376 repo.dirstate.beginparentchange()
3376 repo.dirstate.beginparentchange()
3377 repo.setparents(r1, r2)
3377 repo.setparents(r1, r2)
3378 repo.dirstate.endparentchange()
3378 repo.dirstate.endparentchange()
3379 finally:
3379 finally:
3380 wlock.release()
3380 wlock.release()
3381
3381
3382 @command('debugdirstate|debugstate',
3382 @command('debugdirstate|debugstate',
3383 [('', 'nodates', None, _('do not display the saved mtime')),
3383 [('', 'nodates', None, _('do not display the saved mtime')),
3384 ('', 'datesort', None, _('sort by saved mtime'))],
3384 ('', 'datesort', None, _('sort by saved mtime'))],
3385 _('[OPTION]...'))
3385 _('[OPTION]...'))
3386 def debugstate(ui, repo, **opts):
3386 def debugstate(ui, repo, **opts):
3387 """show the contents of the current dirstate"""
3387 """show the contents of the current dirstate"""
3388
3388
3389 nodates = opts.get('nodates')
3389 nodates = opts.get('nodates')
3390 datesort = opts.get('datesort')
3390 datesort = opts.get('datesort')
3391
3391
3392 timestr = ""
3392 timestr = ""
3393 if datesort:
3393 if datesort:
3394 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3394 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3395 else:
3395 else:
3396 keyfunc = None # sort by filename
3396 keyfunc = None # sort by filename
3397 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3397 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3398 if ent[3] == -1:
3398 if ent[3] == -1:
3399 timestr = 'unset '
3399 timestr = 'unset '
3400 elif nodates:
3400 elif nodates:
3401 timestr = 'set '
3401 timestr = 'set '
3402 else:
3402 else:
3403 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3403 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3404 time.localtime(ent[3]))
3404 time.localtime(ent[3]))
3405 if ent[1] & 0o20000:
3405 if ent[1] & 0o20000:
3406 mode = 'lnk'
3406 mode = 'lnk'
3407 else:
3407 else:
3408 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3408 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3409 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3409 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3410 for f in repo.dirstate.copies():
3410 for f in repo.dirstate.copies():
3411 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3411 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3412
3412
3413 @command('debugsub',
3413 @command('debugsub',
3414 [('r', 'rev', '',
3414 [('r', 'rev', '',
3415 _('revision to check'), _('REV'))],
3415 _('revision to check'), _('REV'))],
3416 _('[-r REV] [REV]'))
3416 _('[-r REV] [REV]'))
3417 def debugsub(ui, repo, rev=None):
3417 def debugsub(ui, repo, rev=None):
3418 ctx = scmutil.revsingle(repo, rev, None)
3418 ctx = scmutil.revsingle(repo, rev, None)
3419 for k, v in sorted(ctx.substate.items()):
3419 for k, v in sorted(ctx.substate.items()):
3420 ui.write(('path %s\n') % k)
3420 ui.write(('path %s\n') % k)
3421 ui.write((' source %s\n') % v[0])
3421 ui.write((' source %s\n') % v[0])
3422 ui.write((' revision %s\n') % v[1])
3422 ui.write((' revision %s\n') % v[1])
3423
3423
3424 @command('debugsuccessorssets',
3424 @command('debugsuccessorssets',
3425 [],
3425 [],
3426 _('[REV]'))
3426 _('[REV]'))
3427 def debugsuccessorssets(ui, repo, *revs):
3427 def debugsuccessorssets(ui, repo, *revs):
3428 """show set of successors for revision
3428 """show set of successors for revision
3429
3429
3430 A successors set of changeset A is a consistent group of revisions that
3430 A successors set of changeset A is a consistent group of revisions that
3431 succeed A. It contains non-obsolete changesets only.
3431 succeed A. It contains non-obsolete changesets only.
3432
3432
3433 In most cases a changeset A has a single successors set containing a single
3433 In most cases a changeset A has a single successors set containing a single
3434 successor (changeset A replaced by A').
3434 successor (changeset A replaced by A').
3435
3435
3436 A changeset that is made obsolete with no successors are called "pruned".
3436 A changeset that is made obsolete with no successors are called "pruned".
3437 Such changesets have no successors sets at all.
3437 Such changesets have no successors sets at all.
3438
3438
3439 A changeset that has been "split" will have a successors set containing
3439 A changeset that has been "split" will have a successors set containing
3440 more than one successor.
3440 more than one successor.
3441
3441
3442 A changeset that has been rewritten in multiple different ways is called
3442 A changeset that has been rewritten in multiple different ways is called
3443 "divergent". Such changesets have multiple successor sets (each of which
3443 "divergent". Such changesets have multiple successor sets (each of which
3444 may also be split, i.e. have multiple successors).
3444 may also be split, i.e. have multiple successors).
3445
3445
3446 Results are displayed as follows::
3446 Results are displayed as follows::
3447
3447
3448 <rev1>
3448 <rev1>
3449 <successors-1A>
3449 <successors-1A>
3450 <rev2>
3450 <rev2>
3451 <successors-2A>
3451 <successors-2A>
3452 <successors-2B1> <successors-2B2> <successors-2B3>
3452 <successors-2B1> <successors-2B2> <successors-2B3>
3453
3453
3454 Here rev2 has two possible (i.e. divergent) successors sets. The first
3454 Here rev2 has two possible (i.e. divergent) successors sets. The first
3455 holds one element, whereas the second holds three (i.e. the changeset has
3455 holds one element, whereas the second holds three (i.e. the changeset has
3456 been split).
3456 been split).
3457 """
3457 """
3458 # passed to successorssets caching computation from one call to another
3458 # passed to successorssets caching computation from one call to another
3459 cache = {}
3459 cache = {}
3460 ctx2str = str
3460 ctx2str = str
3461 node2str = short
3461 node2str = short
3462 if ui.debug():
3462 if ui.debug():
3463 def ctx2str(ctx):
3463 def ctx2str(ctx):
3464 return ctx.hex()
3464 return ctx.hex()
3465 node2str = hex
3465 node2str = hex
3466 for rev in scmutil.revrange(repo, revs):
3466 for rev in scmutil.revrange(repo, revs):
3467 ctx = repo[rev]
3467 ctx = repo[rev]
3468 ui.write('%s\n'% ctx2str(ctx))
3468 ui.write('%s\n'% ctx2str(ctx))
3469 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3469 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3470 if succsset:
3470 if succsset:
3471 ui.write(' ')
3471 ui.write(' ')
3472 ui.write(node2str(succsset[0]))
3472 ui.write(node2str(succsset[0]))
3473 for node in succsset[1:]:
3473 for node in succsset[1:]:
3474 ui.write(' ')
3474 ui.write(' ')
3475 ui.write(node2str(node))
3475 ui.write(node2str(node))
3476 ui.write('\n')
3476 ui.write('\n')
3477
3477
3478 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3478 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3479 def debugwalk(ui, repo, *pats, **opts):
3479 def debugwalk(ui, repo, *pats, **opts):
3480 """show how files match on given patterns"""
3480 """show how files match on given patterns"""
3481 m = scmutil.match(repo[None], pats, opts)
3481 m = scmutil.match(repo[None], pats, opts)
3482 items = list(repo.walk(m))
3482 items = list(repo.walk(m))
3483 if not items:
3483 if not items:
3484 return
3484 return
3485 f = lambda fn: fn
3485 f = lambda fn: fn
3486 if ui.configbool('ui', 'slash') and os.sep != '/':
3486 if ui.configbool('ui', 'slash') and os.sep != '/':
3487 f = lambda fn: util.normpath(fn)
3487 f = lambda fn: util.normpath(fn)
3488 fmt = 'f %%-%ds %%-%ds %%s' % (
3488 fmt = 'f %%-%ds %%-%ds %%s' % (
3489 max([len(abs) for abs in items]),
3489 max([len(abs) for abs in items]),
3490 max([len(m.rel(abs)) for abs in items]))
3490 max([len(m.rel(abs)) for abs in items]))
3491 for abs in items:
3491 for abs in items:
3492 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3492 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3493 ui.write("%s\n" % line.rstrip())
3493 ui.write("%s\n" % line.rstrip())
3494
3494
3495 @command('debugwireargs',
3495 @command('debugwireargs',
3496 [('', 'three', '', 'three'),
3496 [('', 'three', '', 'three'),
3497 ('', 'four', '', 'four'),
3497 ('', 'four', '', 'four'),
3498 ('', 'five', '', 'five'),
3498 ('', 'five', '', 'five'),
3499 ] + remoteopts,
3499 ] + remoteopts,
3500 _('REPO [OPTIONS]... [ONE [TWO]]'),
3500 _('REPO [OPTIONS]... [ONE [TWO]]'),
3501 norepo=True)
3501 norepo=True)
3502 def debugwireargs(ui, repopath, *vals, **opts):
3502 def debugwireargs(ui, repopath, *vals, **opts):
3503 repo = hg.peer(ui, opts, repopath)
3503 repo = hg.peer(ui, opts, repopath)
3504 for opt in remoteopts:
3504 for opt in remoteopts:
3505 del opts[opt[1]]
3505 del opts[opt[1]]
3506 args = {}
3506 args = {}
3507 for k, v in opts.iteritems():
3507 for k, v in opts.iteritems():
3508 if v:
3508 if v:
3509 args[k] = v
3509 args[k] = v
3510 # run twice to check that we don't mess up the stream for the next command
3510 # run twice to check that we don't mess up the stream for the next command
3511 res1 = repo.debugwireargs(*vals, **args)
3511 res1 = repo.debugwireargs(*vals, **args)
3512 res2 = repo.debugwireargs(*vals, **args)
3512 res2 = repo.debugwireargs(*vals, **args)
3513 ui.write("%s\n" % res1)
3513 ui.write("%s\n" % res1)
3514 if res1 != res2:
3514 if res1 != res2:
3515 ui.warn("%s\n" % res2)
3515 ui.warn("%s\n" % res2)
3516
3516
3517 @command('^diff',
3517 @command('^diff',
3518 [('r', 'rev', [], _('revision'), _('REV')),
3518 [('r', 'rev', [], _('revision'), _('REV')),
3519 ('c', 'change', '', _('change made by revision'), _('REV'))
3519 ('c', 'change', '', _('change made by revision'), _('REV'))
3520 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3520 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3521 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3521 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3522 inferrepo=True)
3522 inferrepo=True)
3523 def diff(ui, repo, *pats, **opts):
3523 def diff(ui, repo, *pats, **opts):
3524 """diff repository (or selected files)
3524 """diff repository (or selected files)
3525
3525
3526 Show differences between revisions for the specified files.
3526 Show differences between revisions for the specified files.
3527
3527
3528 Differences between files are shown using the unified diff format.
3528 Differences between files are shown using the unified diff format.
3529
3529
3530 .. note::
3530 .. note::
3531
3531
3532 :hg:`diff` may generate unexpected results for merges, as it will
3532 :hg:`diff` may generate unexpected results for merges, as it will
3533 default to comparing against the working directory's first
3533 default to comparing against the working directory's first
3534 parent changeset if no revisions are specified.
3534 parent changeset if no revisions are specified.
3535
3535
3536 When two revision arguments are given, then changes are shown
3536 When two revision arguments are given, then changes are shown
3537 between those revisions. If only one revision is specified then
3537 between those revisions. If only one revision is specified then
3538 that revision is compared to the working directory, and, when no
3538 that revision is compared to the working directory, and, when no
3539 revisions are specified, the working directory files are compared
3539 revisions are specified, the working directory files are compared
3540 to its first parent.
3540 to its first parent.
3541
3541
3542 Alternatively you can specify -c/--change with a revision to see
3542 Alternatively you can specify -c/--change with a revision to see
3543 the changes in that changeset relative to its first parent.
3543 the changes in that changeset relative to its first parent.
3544
3544
3545 Without the -a/--text option, diff will avoid generating diffs of
3545 Without the -a/--text option, diff will avoid generating diffs of
3546 files it detects as binary. With -a, diff will generate a diff
3546 files it detects as binary. With -a, diff will generate a diff
3547 anyway, probably with undesirable results.
3547 anyway, probably with undesirable results.
3548
3548
3549 Use the -g/--git option to generate diffs in the git extended diff
3549 Use the -g/--git option to generate diffs in the git extended diff
3550 format. For more information, read :hg:`help diffs`.
3550 format. For more information, read :hg:`help diffs`.
3551
3551
3552 .. container:: verbose
3552 .. container:: verbose
3553
3553
3554 Examples:
3554 Examples:
3555
3555
3556 - compare a file in the current working directory to its parent::
3556 - compare a file in the current working directory to its parent::
3557
3557
3558 hg diff foo.c
3558 hg diff foo.c
3559
3559
3560 - compare two historical versions of a directory, with rename info::
3560 - compare two historical versions of a directory, with rename info::
3561
3561
3562 hg diff --git -r 1.0:1.2 lib/
3562 hg diff --git -r 1.0:1.2 lib/
3563
3563
3564 - get change stats relative to the last change on some date::
3564 - get change stats relative to the last change on some date::
3565
3565
3566 hg diff --stat -r "date('may 2')"
3566 hg diff --stat -r "date('may 2')"
3567
3567
3568 - diff all newly-added files that contain a keyword::
3568 - diff all newly-added files that contain a keyword::
3569
3569
3570 hg diff "set:added() and grep(GNU)"
3570 hg diff "set:added() and grep(GNU)"
3571
3571
3572 - compare a revision and its parents::
3572 - compare a revision and its parents::
3573
3573
3574 hg diff -c 9353 # compare against first parent
3574 hg diff -c 9353 # compare against first parent
3575 hg diff -r 9353^:9353 # same using revset syntax
3575 hg diff -r 9353^:9353 # same using revset syntax
3576 hg diff -r 9353^2:9353 # compare against the second parent
3576 hg diff -r 9353^2:9353 # compare against the second parent
3577
3577
3578 Returns 0 on success.
3578 Returns 0 on success.
3579 """
3579 """
3580
3580
3581 revs = opts.get('rev')
3581 revs = opts.get('rev')
3582 change = opts.get('change')
3582 change = opts.get('change')
3583 stat = opts.get('stat')
3583 stat = opts.get('stat')
3584 reverse = opts.get('reverse')
3584 reverse = opts.get('reverse')
3585
3585
3586 if revs and change:
3586 if revs and change:
3587 msg = _('cannot specify --rev and --change at the same time')
3587 msg = _('cannot specify --rev and --change at the same time')
3588 raise error.Abort(msg)
3588 raise error.Abort(msg)
3589 elif change:
3589 elif change:
3590 node2 = scmutil.revsingle(repo, change, None).node()
3590 node2 = scmutil.revsingle(repo, change, None).node()
3591 node1 = repo[node2].p1().node()
3591 node1 = repo[node2].p1().node()
3592 else:
3592 else:
3593 node1, node2 = scmutil.revpair(repo, revs)
3593 node1, node2 = scmutil.revpair(repo, revs)
3594
3594
3595 if reverse:
3595 if reverse:
3596 node1, node2 = node2, node1
3596 node1, node2 = node2, node1
3597
3597
3598 diffopts = patch.diffallopts(ui, opts)
3598 diffopts = patch.diffallopts(ui, opts)
3599 m = scmutil.match(repo[node2], pats, opts)
3599 m = scmutil.match(repo[node2], pats, opts)
3600 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3600 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3601 listsubrepos=opts.get('subrepos'),
3601 listsubrepos=opts.get('subrepos'),
3602 root=opts.get('root'))
3602 root=opts.get('root'))
3603
3603
3604 @command('^export',
3604 @command('^export',
3605 [('o', 'output', '',
3605 [('o', 'output', '',
3606 _('print output to file with formatted name'), _('FORMAT')),
3606 _('print output to file with formatted name'), _('FORMAT')),
3607 ('', 'switch-parent', None, _('diff against the second parent')),
3607 ('', 'switch-parent', None, _('diff against the second parent')),
3608 ('r', 'rev', [], _('revisions to export'), _('REV')),
3608 ('r', 'rev', [], _('revisions to export'), _('REV')),
3609 ] + diffopts,
3609 ] + diffopts,
3610 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3610 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3611 def export(ui, repo, *changesets, **opts):
3611 def export(ui, repo, *changesets, **opts):
3612 """dump the header and diffs for one or more changesets
3612 """dump the header and diffs for one or more changesets
3613
3613
3614 Print the changeset header and diffs for one or more revisions.
3614 Print the changeset header and diffs for one or more revisions.
3615 If no revision is given, the parent of the working directory is used.
3615 If no revision is given, the parent of the working directory is used.
3616
3616
3617 The information shown in the changeset header is: author, date,
3617 The information shown in the changeset header is: author, date,
3618 branch name (if non-default), changeset hash, parent(s) and commit
3618 branch name (if non-default), changeset hash, parent(s) and commit
3619 comment.
3619 comment.
3620
3620
3621 .. note::
3621 .. note::
3622
3622
3623 :hg:`export` may generate unexpected diff output for merge
3623 :hg:`export` may generate unexpected diff output for merge
3624 changesets, as it will compare the merge changeset against its
3624 changesets, as it will compare the merge changeset against its
3625 first parent only.
3625 first parent only.
3626
3626
3627 Output may be to a file, in which case the name of the file is
3627 Output may be to a file, in which case the name of the file is
3628 given using a format string. The formatting rules are as follows:
3628 given using a format string. The formatting rules are as follows:
3629
3629
3630 :``%%``: literal "%" character
3630 :``%%``: literal "%" character
3631 :``%H``: changeset hash (40 hexadecimal digits)
3631 :``%H``: changeset hash (40 hexadecimal digits)
3632 :``%N``: number of patches being generated
3632 :``%N``: number of patches being generated
3633 :``%R``: changeset revision number
3633 :``%R``: changeset revision number
3634 :``%b``: basename of the exporting repository
3634 :``%b``: basename of the exporting repository
3635 :``%h``: short-form changeset hash (12 hexadecimal digits)
3635 :``%h``: short-form changeset hash (12 hexadecimal digits)
3636 :``%m``: first line of the commit message (only alphanumeric characters)
3636 :``%m``: first line of the commit message (only alphanumeric characters)
3637 :``%n``: zero-padded sequence number, starting at 1
3637 :``%n``: zero-padded sequence number, starting at 1
3638 :``%r``: zero-padded changeset revision number
3638 :``%r``: zero-padded changeset revision number
3639
3639
3640 Without the -a/--text option, export will avoid generating diffs
3640 Without the -a/--text option, export will avoid generating diffs
3641 of files it detects as binary. With -a, export will generate a
3641 of files it detects as binary. With -a, export will generate a
3642 diff anyway, probably with undesirable results.
3642 diff anyway, probably with undesirable results.
3643
3643
3644 Use the -g/--git option to generate diffs in the git extended diff
3644 Use the -g/--git option to generate diffs in the git extended diff
3645 format. See :hg:`help diffs` for more information.
3645 format. See :hg:`help diffs` for more information.
3646
3646
3647 With the --switch-parent option, the diff will be against the
3647 With the --switch-parent option, the diff will be against the
3648 second parent. It can be useful to review a merge.
3648 second parent. It can be useful to review a merge.
3649
3649
3650 .. container:: verbose
3650 .. container:: verbose
3651
3651
3652 Examples:
3652 Examples:
3653
3653
3654 - use export and import to transplant a bugfix to the current
3654 - use export and import to transplant a bugfix to the current
3655 branch::
3655 branch::
3656
3656
3657 hg export -r 9353 | hg import -
3657 hg export -r 9353 | hg import -
3658
3658
3659 - export all the changesets between two revisions to a file with
3659 - export all the changesets between two revisions to a file with
3660 rename information::
3660 rename information::
3661
3661
3662 hg export --git -r 123:150 > changes.txt
3662 hg export --git -r 123:150 > changes.txt
3663
3663
3664 - split outgoing changes into a series of patches with
3664 - split outgoing changes into a series of patches with
3665 descriptive names::
3665 descriptive names::
3666
3666
3667 hg export -r "outgoing()" -o "%n-%m.patch"
3667 hg export -r "outgoing()" -o "%n-%m.patch"
3668
3668
3669 Returns 0 on success.
3669 Returns 0 on success.
3670 """
3670 """
3671 changesets += tuple(opts.get('rev', []))
3671 changesets += tuple(opts.get('rev', []))
3672 if not changesets:
3672 if not changesets:
3673 changesets = ['.']
3673 changesets = ['.']
3674 revs = scmutil.revrange(repo, changesets)
3674 revs = scmutil.revrange(repo, changesets)
3675 if not revs:
3675 if not revs:
3676 raise error.Abort(_("export requires at least one changeset"))
3676 raise error.Abort(_("export requires at least one changeset"))
3677 if len(revs) > 1:
3677 if len(revs) > 1:
3678 ui.note(_('exporting patches:\n'))
3678 ui.note(_('exporting patches:\n'))
3679 else:
3679 else:
3680 ui.note(_('exporting patch:\n'))
3680 ui.note(_('exporting patch:\n'))
3681 cmdutil.export(repo, revs, template=opts.get('output'),
3681 cmdutil.export(repo, revs, template=opts.get('output'),
3682 switch_parent=opts.get('switch_parent'),
3682 switch_parent=opts.get('switch_parent'),
3683 opts=patch.diffallopts(ui, opts))
3683 opts=patch.diffallopts(ui, opts))
3684
3684
3685 @command('files',
3685 @command('files',
3686 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3686 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3687 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3687 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3688 ] + walkopts + formatteropts + subrepoopts,
3688 ] + walkopts + formatteropts + subrepoopts,
3689 _('[OPTION]... [PATTERN]...'))
3689 _('[OPTION]... [PATTERN]...'))
3690 def files(ui, repo, *pats, **opts):
3690 def files(ui, repo, *pats, **opts):
3691 """list tracked files
3691 """list tracked files
3692
3692
3693 Print files under Mercurial control in the working directory or
3693 Print files under Mercurial control in the working directory or
3694 specified revision whose names match the given patterns (excluding
3694 specified revision whose names match the given patterns (excluding
3695 removed files).
3695 removed files).
3696
3696
3697 If no patterns are given to match, this command prints the names
3697 If no patterns are given to match, this command prints the names
3698 of all files under Mercurial control in the working directory.
3698 of all files under Mercurial control in the working directory.
3699
3699
3700 .. container:: verbose
3700 .. container:: verbose
3701
3701
3702 Examples:
3702 Examples:
3703
3703
3704 - list all files under the current directory::
3704 - list all files under the current directory::
3705
3705
3706 hg files .
3706 hg files .
3707
3707
3708 - shows sizes and flags for current revision::
3708 - shows sizes and flags for current revision::
3709
3709
3710 hg files -vr .
3710 hg files -vr .
3711
3711
3712 - list all files named README::
3712 - list all files named README::
3713
3713
3714 hg files -I "**/README"
3714 hg files -I "**/README"
3715
3715
3716 - list all binary files::
3716 - list all binary files::
3717
3717
3718 hg files "set:binary()"
3718 hg files "set:binary()"
3719
3719
3720 - find files containing a regular expression::
3720 - find files containing a regular expression::
3721
3721
3722 hg files "set:grep('bob')"
3722 hg files "set:grep('bob')"
3723
3723
3724 - search tracked file contents with xargs and grep::
3724 - search tracked file contents with xargs and grep::
3725
3725
3726 hg files -0 | xargs -0 grep foo
3726 hg files -0 | xargs -0 grep foo
3727
3727
3728 See :hg:`help patterns` and :hg:`help filesets` for more information
3728 See :hg:`help patterns` and :hg:`help filesets` for more information
3729 on specifying file patterns.
3729 on specifying file patterns.
3730
3730
3731 Returns 0 if a match is found, 1 otherwise.
3731 Returns 0 if a match is found, 1 otherwise.
3732
3732
3733 """
3733 """
3734 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3734 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3735
3735
3736 end = '\n'
3736 end = '\n'
3737 if opts.get('print0'):
3737 if opts.get('print0'):
3738 end = '\0'
3738 end = '\0'
3739 fm = ui.formatter('files', opts)
3739 fm = ui.formatter('files', opts)
3740 fmt = '%s' + end
3740 fmt = '%s' + end
3741
3741
3742 m = scmutil.match(ctx, pats, opts)
3742 m = scmutil.match(ctx, pats, opts)
3743 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3743 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3744
3744
3745 fm.end()
3745 fm.end()
3746
3746
3747 return ret
3747 return ret
3748
3748
3749 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3749 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3750 def forget(ui, repo, *pats, **opts):
3750 def forget(ui, repo, *pats, **opts):
3751 """forget the specified files on the next commit
3751 """forget the specified files on the next commit
3752
3752
3753 Mark the specified files so they will no longer be tracked
3753 Mark the specified files so they will no longer be tracked
3754 after the next commit.
3754 after the next commit.
3755
3755
3756 This only removes files from the current branch, not from the
3756 This only removes files from the current branch, not from the
3757 entire project history, and it does not delete them from the
3757 entire project history, and it does not delete them from the
3758 working directory.
3758 working directory.
3759
3759
3760 To delete the file from the working directory, see :hg:`remove`.
3760 To delete the file from the working directory, see :hg:`remove`.
3761
3761
3762 To undo a forget before the next commit, see :hg:`add`.
3762 To undo a forget before the next commit, see :hg:`add`.
3763
3763
3764 .. container:: verbose
3764 .. container:: verbose
3765
3765
3766 Examples:
3766 Examples:
3767
3767
3768 - forget newly-added binary files::
3768 - forget newly-added binary files::
3769
3769
3770 hg forget "set:added() and binary()"
3770 hg forget "set:added() and binary()"
3771
3771
3772 - forget files that would be excluded by .hgignore::
3772 - forget files that would be excluded by .hgignore::
3773
3773
3774 hg forget "set:hgignore()"
3774 hg forget "set:hgignore()"
3775
3775
3776 Returns 0 on success.
3776 Returns 0 on success.
3777 """
3777 """
3778
3778
3779 if not pats:
3779 if not pats:
3780 raise error.Abort(_('no files specified'))
3780 raise error.Abort(_('no files specified'))
3781
3781
3782 m = scmutil.match(repo[None], pats, opts)
3782 m = scmutil.match(repo[None], pats, opts)
3783 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3783 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3784 return rejected and 1 or 0
3784 return rejected and 1 or 0
3785
3785
3786 @command(
3786 @command(
3787 'graft',
3787 'graft',
3788 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3788 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3789 ('c', 'continue', False, _('resume interrupted graft')),
3789 ('c', 'continue', False, _('resume interrupted graft')),
3790 ('e', 'edit', False, _('invoke editor on commit messages')),
3790 ('e', 'edit', False, _('invoke editor on commit messages')),
3791 ('', 'log', None, _('append graft info to log message')),
3791 ('', 'log', None, _('append graft info to log message')),
3792 ('f', 'force', False, _('force graft')),
3792 ('f', 'force', False, _('force graft')),
3793 ('D', 'currentdate', False,
3793 ('D', 'currentdate', False,
3794 _('record the current date as commit date')),
3794 _('record the current date as commit date')),
3795 ('U', 'currentuser', False,
3795 ('U', 'currentuser', False,
3796 _('record the current user as committer'), _('DATE'))]
3796 _('record the current user as committer'), _('DATE'))]
3797 + commitopts2 + mergetoolopts + dryrunopts,
3797 + commitopts2 + mergetoolopts + dryrunopts,
3798 _('[OPTION]... [-r] REV...'))
3798 _('[OPTION]... [-r] REV...'))
3799 def graft(ui, repo, *revs, **opts):
3799 def graft(ui, repo, *revs, **opts):
3800 '''copy changes from other branches onto the current branch
3800 '''copy changes from other branches onto the current branch
3801
3801
3802 This command uses Mercurial's merge logic to copy individual
3802 This command uses Mercurial's merge logic to copy individual
3803 changes from other branches without merging branches in the
3803 changes from other branches without merging branches in the
3804 history graph. This is sometimes known as 'backporting' or
3804 history graph. This is sometimes known as 'backporting' or
3805 'cherry-picking'. By default, graft will copy user, date, and
3805 'cherry-picking'. By default, graft will copy user, date, and
3806 description from the source changesets.
3806 description from the source changesets.
3807
3807
3808 Changesets that are ancestors of the current revision, that have
3808 Changesets that are ancestors of the current revision, that have
3809 already been grafted, or that are merges will be skipped.
3809 already been grafted, or that are merges will be skipped.
3810
3810
3811 If --log is specified, log messages will have a comment appended
3811 If --log is specified, log messages will have a comment appended
3812 of the form::
3812 of the form::
3813
3813
3814 (grafted from CHANGESETHASH)
3814 (grafted from CHANGESETHASH)
3815
3815
3816 If --force is specified, revisions will be grafted even if they
3816 If --force is specified, revisions will be grafted even if they
3817 are already ancestors of or have been grafted to the destination.
3817 are already ancestors of or have been grafted to the destination.
3818 This is useful when the revisions have since been backed out.
3818 This is useful when the revisions have since been backed out.
3819
3819
3820 If a graft merge results in conflicts, the graft process is
3820 If a graft merge results in conflicts, the graft process is
3821 interrupted so that the current merge can be manually resolved.
3821 interrupted so that the current merge can be manually resolved.
3822 Once all conflicts are addressed, the graft process can be
3822 Once all conflicts are addressed, the graft process can be
3823 continued with the -c/--continue option.
3823 continued with the -c/--continue option.
3824
3824
3825 .. note::
3825 .. note::
3826
3826
3827 The -c/--continue option does not reapply earlier options, except
3827 The -c/--continue option does not reapply earlier options, except
3828 for --force.
3828 for --force.
3829
3829
3830 .. container:: verbose
3830 .. container:: verbose
3831
3831
3832 Examples:
3832 Examples:
3833
3833
3834 - copy a single change to the stable branch and edit its description::
3834 - copy a single change to the stable branch and edit its description::
3835
3835
3836 hg update stable
3836 hg update stable
3837 hg graft --edit 9393
3837 hg graft --edit 9393
3838
3838
3839 - graft a range of changesets with one exception, updating dates::
3839 - graft a range of changesets with one exception, updating dates::
3840
3840
3841 hg graft -D "2085::2093 and not 2091"
3841 hg graft -D "2085::2093 and not 2091"
3842
3842
3843 - continue a graft after resolving conflicts::
3843 - continue a graft after resolving conflicts::
3844
3844
3845 hg graft -c
3845 hg graft -c
3846
3846
3847 - show the source of a grafted changeset::
3847 - show the source of a grafted changeset::
3848
3848
3849 hg log --debug -r .
3849 hg log --debug -r .
3850
3850
3851 - show revisions sorted by date::
3852
3853 hg log -r 'sort(all(), date)'
3854
3851 See :hg:`help revisions` and :hg:`help revsets` for more about
3855 See :hg:`help revisions` and :hg:`help revsets` for more about
3852 specifying revisions.
3856 specifying revisions.
3853
3857
3854 Returns 0 on successful completion.
3858 Returns 0 on successful completion.
3855 '''
3859 '''
3856 wlock = None
3860 wlock = None
3857 try:
3861 try:
3858 wlock = repo.wlock()
3862 wlock = repo.wlock()
3859 return _dograft(ui, repo, *revs, **opts)
3863 return _dograft(ui, repo, *revs, **opts)
3860 finally:
3864 finally:
3861 release(wlock)
3865 release(wlock)
3862
3866
3863 def _dograft(ui, repo, *revs, **opts):
3867 def _dograft(ui, repo, *revs, **opts):
3864 revs = list(revs)
3868 revs = list(revs)
3865 revs.extend(opts['rev'])
3869 revs.extend(opts['rev'])
3866
3870
3867 if not opts.get('user') and opts.get('currentuser'):
3871 if not opts.get('user') and opts.get('currentuser'):
3868 opts['user'] = ui.username()
3872 opts['user'] = ui.username()
3869 if not opts.get('date') and opts.get('currentdate'):
3873 if not opts.get('date') and opts.get('currentdate'):
3870 opts['date'] = "%d %d" % util.makedate()
3874 opts['date'] = "%d %d" % util.makedate()
3871
3875
3872 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3876 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3873
3877
3874 cont = False
3878 cont = False
3875 if opts['continue']:
3879 if opts['continue']:
3876 cont = True
3880 cont = True
3877 if revs:
3881 if revs:
3878 raise error.Abort(_("can't specify --continue and revisions"))
3882 raise error.Abort(_("can't specify --continue and revisions"))
3879 # read in unfinished revisions
3883 # read in unfinished revisions
3880 try:
3884 try:
3881 nodes = repo.vfs.read('graftstate').splitlines()
3885 nodes = repo.vfs.read('graftstate').splitlines()
3882 revs = [repo[node].rev() for node in nodes]
3886 revs = [repo[node].rev() for node in nodes]
3883 except IOError as inst:
3887 except IOError as inst:
3884 if inst.errno != errno.ENOENT:
3888 if inst.errno != errno.ENOENT:
3885 raise
3889 raise
3886 raise error.Abort(_("no graft state found, can't continue"))
3890 raise error.Abort(_("no graft state found, can't continue"))
3887 else:
3891 else:
3888 cmdutil.checkunfinished(repo)
3892 cmdutil.checkunfinished(repo)
3889 cmdutil.bailifchanged(repo)
3893 cmdutil.bailifchanged(repo)
3890 if not revs:
3894 if not revs:
3891 raise error.Abort(_('no revisions specified'))
3895 raise error.Abort(_('no revisions specified'))
3892 revs = scmutil.revrange(repo, revs)
3896 revs = scmutil.revrange(repo, revs)
3893
3897
3894 skipped = set()
3898 skipped = set()
3895 # check for merges
3899 # check for merges
3896 for rev in repo.revs('%ld and merge()', revs):
3900 for rev in repo.revs('%ld and merge()', revs):
3897 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3901 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3898 skipped.add(rev)
3902 skipped.add(rev)
3899 revs = [r for r in revs if r not in skipped]
3903 revs = [r for r in revs if r not in skipped]
3900 if not revs:
3904 if not revs:
3901 return -1
3905 return -1
3902
3906
3903 # Don't check in the --continue case, in effect retaining --force across
3907 # Don't check in the --continue case, in effect retaining --force across
3904 # --continues. That's because without --force, any revisions we decided to
3908 # --continues. That's because without --force, any revisions we decided to
3905 # skip would have been filtered out here, so they wouldn't have made their
3909 # skip would have been filtered out here, so they wouldn't have made their
3906 # way to the graftstate. With --force, any revisions we would have otherwise
3910 # way to the graftstate. With --force, any revisions we would have otherwise
3907 # skipped would not have been filtered out, and if they hadn't been applied
3911 # skipped would not have been filtered out, and if they hadn't been applied
3908 # already, they'd have been in the graftstate.
3912 # already, they'd have been in the graftstate.
3909 if not (cont or opts.get('force')):
3913 if not (cont or opts.get('force')):
3910 # check for ancestors of dest branch
3914 # check for ancestors of dest branch
3911 crev = repo['.'].rev()
3915 crev = repo['.'].rev()
3912 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3916 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3913 # Cannot use x.remove(y) on smart set, this has to be a list.
3917 # Cannot use x.remove(y) on smart set, this has to be a list.
3914 # XXX make this lazy in the future
3918 # XXX make this lazy in the future
3915 revs = list(revs)
3919 revs = list(revs)
3916 # don't mutate while iterating, create a copy
3920 # don't mutate while iterating, create a copy
3917 for rev in list(revs):
3921 for rev in list(revs):
3918 if rev in ancestors:
3922 if rev in ancestors:
3919 ui.warn(_('skipping ancestor revision %d:%s\n') %
3923 ui.warn(_('skipping ancestor revision %d:%s\n') %
3920 (rev, repo[rev]))
3924 (rev, repo[rev]))
3921 # XXX remove on list is slow
3925 # XXX remove on list is slow
3922 revs.remove(rev)
3926 revs.remove(rev)
3923 if not revs:
3927 if not revs:
3924 return -1
3928 return -1
3925
3929
3926 # analyze revs for earlier grafts
3930 # analyze revs for earlier grafts
3927 ids = {}
3931 ids = {}
3928 for ctx in repo.set("%ld", revs):
3932 for ctx in repo.set("%ld", revs):
3929 ids[ctx.hex()] = ctx.rev()
3933 ids[ctx.hex()] = ctx.rev()
3930 n = ctx.extra().get('source')
3934 n = ctx.extra().get('source')
3931 if n:
3935 if n:
3932 ids[n] = ctx.rev()
3936 ids[n] = ctx.rev()
3933
3937
3934 # check ancestors for earlier grafts
3938 # check ancestors for earlier grafts
3935 ui.debug('scanning for duplicate grafts\n')
3939 ui.debug('scanning for duplicate grafts\n')
3936
3940
3937 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3941 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3938 ctx = repo[rev]
3942 ctx = repo[rev]
3939 n = ctx.extra().get('source')
3943 n = ctx.extra().get('source')
3940 if n in ids:
3944 if n in ids:
3941 try:
3945 try:
3942 r = repo[n].rev()
3946 r = repo[n].rev()
3943 except error.RepoLookupError:
3947 except error.RepoLookupError:
3944 r = None
3948 r = None
3945 if r in revs:
3949 if r in revs:
3946 ui.warn(_('skipping revision %d:%s '
3950 ui.warn(_('skipping revision %d:%s '
3947 '(already grafted to %d:%s)\n')
3951 '(already grafted to %d:%s)\n')
3948 % (r, repo[r], rev, ctx))
3952 % (r, repo[r], rev, ctx))
3949 revs.remove(r)
3953 revs.remove(r)
3950 elif ids[n] in revs:
3954 elif ids[n] in revs:
3951 if r is None:
3955 if r is None:
3952 ui.warn(_('skipping already grafted revision %d:%s '
3956 ui.warn(_('skipping already grafted revision %d:%s '
3953 '(%d:%s also has unknown origin %s)\n')
3957 '(%d:%s also has unknown origin %s)\n')
3954 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3958 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3955 else:
3959 else:
3956 ui.warn(_('skipping already grafted revision %d:%s '
3960 ui.warn(_('skipping already grafted revision %d:%s '
3957 '(%d:%s also has origin %d:%s)\n')
3961 '(%d:%s also has origin %d:%s)\n')
3958 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3962 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3959 revs.remove(ids[n])
3963 revs.remove(ids[n])
3960 elif ctx.hex() in ids:
3964 elif ctx.hex() in ids:
3961 r = ids[ctx.hex()]
3965 r = ids[ctx.hex()]
3962 ui.warn(_('skipping already grafted revision %d:%s '
3966 ui.warn(_('skipping already grafted revision %d:%s '
3963 '(was grafted from %d:%s)\n') %
3967 '(was grafted from %d:%s)\n') %
3964 (r, repo[r], rev, ctx))
3968 (r, repo[r], rev, ctx))
3965 revs.remove(r)
3969 revs.remove(r)
3966 if not revs:
3970 if not revs:
3967 return -1
3971 return -1
3968
3972
3969 try:
3973 try:
3970 for pos, ctx in enumerate(repo.set("%ld", revs)):
3974 for pos, ctx in enumerate(repo.set("%ld", revs)):
3971 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3975 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3972 ctx.description().split('\n', 1)[0])
3976 ctx.description().split('\n', 1)[0])
3973 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3977 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3974 if names:
3978 if names:
3975 desc += ' (%s)' % ' '.join(names)
3979 desc += ' (%s)' % ' '.join(names)
3976 ui.status(_('grafting %s\n') % desc)
3980 ui.status(_('grafting %s\n') % desc)
3977 if opts.get('dry_run'):
3981 if opts.get('dry_run'):
3978 continue
3982 continue
3979
3983
3980 extra = ctx.extra().copy()
3984 extra = ctx.extra().copy()
3981 del extra['branch']
3985 del extra['branch']
3982 source = extra.get('source')
3986 source = extra.get('source')
3983 if source:
3987 if source:
3984 extra['intermediate-source'] = ctx.hex()
3988 extra['intermediate-source'] = ctx.hex()
3985 else:
3989 else:
3986 extra['source'] = ctx.hex()
3990 extra['source'] = ctx.hex()
3987 user = ctx.user()
3991 user = ctx.user()
3988 if opts.get('user'):
3992 if opts.get('user'):
3989 user = opts['user']
3993 user = opts['user']
3990 date = ctx.date()
3994 date = ctx.date()
3991 if opts.get('date'):
3995 if opts.get('date'):
3992 date = opts['date']
3996 date = opts['date']
3993 message = ctx.description()
3997 message = ctx.description()
3994 if opts.get('log'):
3998 if opts.get('log'):
3995 message += '\n(grafted from %s)' % ctx.hex()
3999 message += '\n(grafted from %s)' % ctx.hex()
3996
4000
3997 # we don't merge the first commit when continuing
4001 # we don't merge the first commit when continuing
3998 if not cont:
4002 if not cont:
3999 # perform the graft merge with p1(rev) as 'ancestor'
4003 # perform the graft merge with p1(rev) as 'ancestor'
4000 try:
4004 try:
4001 # ui.forcemerge is an internal variable, do not document
4005 # ui.forcemerge is an internal variable, do not document
4002 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4006 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4003 'graft')
4007 'graft')
4004 stats = mergemod.graft(repo, ctx, ctx.p1(),
4008 stats = mergemod.graft(repo, ctx, ctx.p1(),
4005 ['local', 'graft'])
4009 ['local', 'graft'])
4006 finally:
4010 finally:
4007 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4011 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4008 # report any conflicts
4012 # report any conflicts
4009 if stats and stats[3] > 0:
4013 if stats and stats[3] > 0:
4010 # write out state for --continue
4014 # write out state for --continue
4011 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4015 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4012 repo.vfs.write('graftstate', ''.join(nodelines))
4016 repo.vfs.write('graftstate', ''.join(nodelines))
4013 extra = ''
4017 extra = ''
4014 if opts.get('user'):
4018 if opts.get('user'):
4015 extra += ' --user %s' % opts['user']
4019 extra += ' --user %s' % opts['user']
4016 if opts.get('date'):
4020 if opts.get('date'):
4017 extra += ' --date %s' % opts['date']
4021 extra += ' --date %s' % opts['date']
4018 if opts.get('log'):
4022 if opts.get('log'):
4019 extra += ' --log'
4023 extra += ' --log'
4020 hint=_('use hg resolve and hg graft --continue%s') % extra
4024 hint=_('use hg resolve and hg graft --continue%s') % extra
4021 raise error.Abort(
4025 raise error.Abort(
4022 _("unresolved conflicts, can't continue"),
4026 _("unresolved conflicts, can't continue"),
4023 hint=hint)
4027 hint=hint)
4024 else:
4028 else:
4025 cont = False
4029 cont = False
4026
4030
4027 # commit
4031 # commit
4028 node = repo.commit(text=message, user=user,
4032 node = repo.commit(text=message, user=user,
4029 date=date, extra=extra, editor=editor)
4033 date=date, extra=extra, editor=editor)
4030 if node is None:
4034 if node is None:
4031 ui.warn(
4035 ui.warn(
4032 _('note: graft of %d:%s created no changes to commit\n') %
4036 _('note: graft of %d:%s created no changes to commit\n') %
4033 (ctx.rev(), ctx))
4037 (ctx.rev(), ctx))
4034 finally:
4038 finally:
4035 # TODO: get rid of this meaningless try/finally enclosing.
4039 # TODO: get rid of this meaningless try/finally enclosing.
4036 # this is kept only to reduce changes in a patch.
4040 # this is kept only to reduce changes in a patch.
4037 pass
4041 pass
4038
4042
4039 # remove state when we complete successfully
4043 # remove state when we complete successfully
4040 if not opts.get('dry_run'):
4044 if not opts.get('dry_run'):
4041 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4045 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4042
4046
4043 return 0
4047 return 0
4044
4048
4045 @command('grep',
4049 @command('grep',
4046 [('0', 'print0', None, _('end fields with NUL')),
4050 [('0', 'print0', None, _('end fields with NUL')),
4047 ('', 'all', None, _('print all revisions that match')),
4051 ('', 'all', None, _('print all revisions that match')),
4048 ('a', 'text', None, _('treat all files as text')),
4052 ('a', 'text', None, _('treat all files as text')),
4049 ('f', 'follow', None,
4053 ('f', 'follow', None,
4050 _('follow changeset history,'
4054 _('follow changeset history,'
4051 ' or file history across copies and renames')),
4055 ' or file history across copies and renames')),
4052 ('i', 'ignore-case', None, _('ignore case when matching')),
4056 ('i', 'ignore-case', None, _('ignore case when matching')),
4053 ('l', 'files-with-matches', None,
4057 ('l', 'files-with-matches', None,
4054 _('print only filenames and revisions that match')),
4058 _('print only filenames and revisions that match')),
4055 ('n', 'line-number', None, _('print matching line numbers')),
4059 ('n', 'line-number', None, _('print matching line numbers')),
4056 ('r', 'rev', [],
4060 ('r', 'rev', [],
4057 _('only search files changed within revision range'), _('REV')),
4061 _('only search files changed within revision range'), _('REV')),
4058 ('u', 'user', None, _('list the author (long with -v)')),
4062 ('u', 'user', None, _('list the author (long with -v)')),
4059 ('d', 'date', None, _('list the date (short with -q)')),
4063 ('d', 'date', None, _('list the date (short with -q)')),
4060 ] + walkopts,
4064 ] + walkopts,
4061 _('[OPTION]... PATTERN [FILE]...'),
4065 _('[OPTION]... PATTERN [FILE]...'),
4062 inferrepo=True)
4066 inferrepo=True)
4063 def grep(ui, repo, pattern, *pats, **opts):
4067 def grep(ui, repo, pattern, *pats, **opts):
4064 """search for a pattern in specified files and revisions
4068 """search for a pattern in specified files and revisions
4065
4069
4066 Search revisions of files for a regular expression.
4070 Search revisions of files for a regular expression.
4067
4071
4068 This command behaves differently than Unix grep. It only accepts
4072 This command behaves differently than Unix grep. It only accepts
4069 Python/Perl regexps. It searches repository history, not the
4073 Python/Perl regexps. It searches repository history, not the
4070 working directory. It always prints the revision number in which a
4074 working directory. It always prints the revision number in which a
4071 match appears.
4075 match appears.
4072
4076
4073 By default, grep only prints output for the first revision of a
4077 By default, grep only prints output for the first revision of a
4074 file in which it finds a match. To get it to print every revision
4078 file in which it finds a match. To get it to print every revision
4075 that contains a change in match status ("-" for a match that
4079 that contains a change in match status ("-" for a match that
4076 becomes a non-match, or "+" for a non-match that becomes a match),
4080 becomes a non-match, or "+" for a non-match that becomes a match),
4077 use the --all flag.
4081 use the --all flag.
4078
4082
4079 Returns 0 if a match is found, 1 otherwise.
4083 Returns 0 if a match is found, 1 otherwise.
4080 """
4084 """
4081 reflags = re.M
4085 reflags = re.M
4082 if opts.get('ignore_case'):
4086 if opts.get('ignore_case'):
4083 reflags |= re.I
4087 reflags |= re.I
4084 try:
4088 try:
4085 regexp = util.re.compile(pattern, reflags)
4089 regexp = util.re.compile(pattern, reflags)
4086 except re.error as inst:
4090 except re.error as inst:
4087 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4091 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4088 return 1
4092 return 1
4089 sep, eol = ':', '\n'
4093 sep, eol = ':', '\n'
4090 if opts.get('print0'):
4094 if opts.get('print0'):
4091 sep = eol = '\0'
4095 sep = eol = '\0'
4092
4096
4093 getfile = util.lrucachefunc(repo.file)
4097 getfile = util.lrucachefunc(repo.file)
4094
4098
4095 def matchlines(body):
4099 def matchlines(body):
4096 begin = 0
4100 begin = 0
4097 linenum = 0
4101 linenum = 0
4098 while begin < len(body):
4102 while begin < len(body):
4099 match = regexp.search(body, begin)
4103 match = regexp.search(body, begin)
4100 if not match:
4104 if not match:
4101 break
4105 break
4102 mstart, mend = match.span()
4106 mstart, mend = match.span()
4103 linenum += body.count('\n', begin, mstart) + 1
4107 linenum += body.count('\n', begin, mstart) + 1
4104 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4108 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4105 begin = body.find('\n', mend) + 1 or len(body) + 1
4109 begin = body.find('\n', mend) + 1 or len(body) + 1
4106 lend = begin - 1
4110 lend = begin - 1
4107 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4111 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4108
4112
4109 class linestate(object):
4113 class linestate(object):
4110 def __init__(self, line, linenum, colstart, colend):
4114 def __init__(self, line, linenum, colstart, colend):
4111 self.line = line
4115 self.line = line
4112 self.linenum = linenum
4116 self.linenum = linenum
4113 self.colstart = colstart
4117 self.colstart = colstart
4114 self.colend = colend
4118 self.colend = colend
4115
4119
4116 def __hash__(self):
4120 def __hash__(self):
4117 return hash((self.linenum, self.line))
4121 return hash((self.linenum, self.line))
4118
4122
4119 def __eq__(self, other):
4123 def __eq__(self, other):
4120 return self.line == other.line
4124 return self.line == other.line
4121
4125
4122 def __iter__(self):
4126 def __iter__(self):
4123 yield (self.line[:self.colstart], '')
4127 yield (self.line[:self.colstart], '')
4124 yield (self.line[self.colstart:self.colend], 'grep.match')
4128 yield (self.line[self.colstart:self.colend], 'grep.match')
4125 rest = self.line[self.colend:]
4129 rest = self.line[self.colend:]
4126 while rest != '':
4130 while rest != '':
4127 match = regexp.search(rest)
4131 match = regexp.search(rest)
4128 if not match:
4132 if not match:
4129 yield (rest, '')
4133 yield (rest, '')
4130 break
4134 break
4131 mstart, mend = match.span()
4135 mstart, mend = match.span()
4132 yield (rest[:mstart], '')
4136 yield (rest[:mstart], '')
4133 yield (rest[mstart:mend], 'grep.match')
4137 yield (rest[mstart:mend], 'grep.match')
4134 rest = rest[mend:]
4138 rest = rest[mend:]
4135
4139
4136 matches = {}
4140 matches = {}
4137 copies = {}
4141 copies = {}
4138 def grepbody(fn, rev, body):
4142 def grepbody(fn, rev, body):
4139 matches[rev].setdefault(fn, [])
4143 matches[rev].setdefault(fn, [])
4140 m = matches[rev][fn]
4144 m = matches[rev][fn]
4141 for lnum, cstart, cend, line in matchlines(body):
4145 for lnum, cstart, cend, line in matchlines(body):
4142 s = linestate(line, lnum, cstart, cend)
4146 s = linestate(line, lnum, cstart, cend)
4143 m.append(s)
4147 m.append(s)
4144
4148
4145 def difflinestates(a, b):
4149 def difflinestates(a, b):
4146 sm = difflib.SequenceMatcher(None, a, b)
4150 sm = difflib.SequenceMatcher(None, a, b)
4147 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4151 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4148 if tag == 'insert':
4152 if tag == 'insert':
4149 for i in xrange(blo, bhi):
4153 for i in xrange(blo, bhi):
4150 yield ('+', b[i])
4154 yield ('+', b[i])
4151 elif tag == 'delete':
4155 elif tag == 'delete':
4152 for i in xrange(alo, ahi):
4156 for i in xrange(alo, ahi):
4153 yield ('-', a[i])
4157 yield ('-', a[i])
4154 elif tag == 'replace':
4158 elif tag == 'replace':
4155 for i in xrange(alo, ahi):
4159 for i in xrange(alo, ahi):
4156 yield ('-', a[i])
4160 yield ('-', a[i])
4157 for i in xrange(blo, bhi):
4161 for i in xrange(blo, bhi):
4158 yield ('+', b[i])
4162 yield ('+', b[i])
4159
4163
4160 def display(fn, ctx, pstates, states):
4164 def display(fn, ctx, pstates, states):
4161 rev = ctx.rev()
4165 rev = ctx.rev()
4162 if ui.quiet:
4166 if ui.quiet:
4163 datefunc = util.shortdate
4167 datefunc = util.shortdate
4164 else:
4168 else:
4165 datefunc = util.datestr
4169 datefunc = util.datestr
4166 found = False
4170 found = False
4167 @util.cachefunc
4171 @util.cachefunc
4168 def binary():
4172 def binary():
4169 flog = getfile(fn)
4173 flog = getfile(fn)
4170 return util.binary(flog.read(ctx.filenode(fn)))
4174 return util.binary(flog.read(ctx.filenode(fn)))
4171
4175
4172 if opts.get('all'):
4176 if opts.get('all'):
4173 iter = difflinestates(pstates, states)
4177 iter = difflinestates(pstates, states)
4174 else:
4178 else:
4175 iter = [('', l) for l in states]
4179 iter = [('', l) for l in states]
4176 for change, l in iter:
4180 for change, l in iter:
4177 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4181 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4178
4182
4179 if opts.get('line_number'):
4183 if opts.get('line_number'):
4180 cols.append((str(l.linenum), 'grep.linenumber'))
4184 cols.append((str(l.linenum), 'grep.linenumber'))
4181 if opts.get('all'):
4185 if opts.get('all'):
4182 cols.append((change, 'grep.change'))
4186 cols.append((change, 'grep.change'))
4183 if opts.get('user'):
4187 if opts.get('user'):
4184 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4188 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4185 if opts.get('date'):
4189 if opts.get('date'):
4186 cols.append((datefunc(ctx.date()), 'grep.date'))
4190 cols.append((datefunc(ctx.date()), 'grep.date'))
4187 for col, label in cols[:-1]:
4191 for col, label in cols[:-1]:
4188 ui.write(col, label=label)
4192 ui.write(col, label=label)
4189 ui.write(sep, label='grep.sep')
4193 ui.write(sep, label='grep.sep')
4190 ui.write(cols[-1][0], label=cols[-1][1])
4194 ui.write(cols[-1][0], label=cols[-1][1])
4191 if not opts.get('files_with_matches'):
4195 if not opts.get('files_with_matches'):
4192 ui.write(sep, label='grep.sep')
4196 ui.write(sep, label='grep.sep')
4193 if not opts.get('text') and binary():
4197 if not opts.get('text') and binary():
4194 ui.write(" Binary file matches")
4198 ui.write(" Binary file matches")
4195 else:
4199 else:
4196 for s, label in l:
4200 for s, label in l:
4197 ui.write(s, label=label)
4201 ui.write(s, label=label)
4198 ui.write(eol)
4202 ui.write(eol)
4199 found = True
4203 found = True
4200 if opts.get('files_with_matches'):
4204 if opts.get('files_with_matches'):
4201 break
4205 break
4202 return found
4206 return found
4203
4207
4204 skip = {}
4208 skip = {}
4205 revfiles = {}
4209 revfiles = {}
4206 matchfn = scmutil.match(repo[None], pats, opts)
4210 matchfn = scmutil.match(repo[None], pats, opts)
4207 found = False
4211 found = False
4208 follow = opts.get('follow')
4212 follow = opts.get('follow')
4209
4213
4210 def prep(ctx, fns):
4214 def prep(ctx, fns):
4211 rev = ctx.rev()
4215 rev = ctx.rev()
4212 pctx = ctx.p1()
4216 pctx = ctx.p1()
4213 parent = pctx.rev()
4217 parent = pctx.rev()
4214 matches.setdefault(rev, {})
4218 matches.setdefault(rev, {})
4215 matches.setdefault(parent, {})
4219 matches.setdefault(parent, {})
4216 files = revfiles.setdefault(rev, [])
4220 files = revfiles.setdefault(rev, [])
4217 for fn in fns:
4221 for fn in fns:
4218 flog = getfile(fn)
4222 flog = getfile(fn)
4219 try:
4223 try:
4220 fnode = ctx.filenode(fn)
4224 fnode = ctx.filenode(fn)
4221 except error.LookupError:
4225 except error.LookupError:
4222 continue
4226 continue
4223
4227
4224 copied = flog.renamed(fnode)
4228 copied = flog.renamed(fnode)
4225 copy = follow and copied and copied[0]
4229 copy = follow and copied and copied[0]
4226 if copy:
4230 if copy:
4227 copies.setdefault(rev, {})[fn] = copy
4231 copies.setdefault(rev, {})[fn] = copy
4228 if fn in skip:
4232 if fn in skip:
4229 if copy:
4233 if copy:
4230 skip[copy] = True
4234 skip[copy] = True
4231 continue
4235 continue
4232 files.append(fn)
4236 files.append(fn)
4233
4237
4234 if fn not in matches[rev]:
4238 if fn not in matches[rev]:
4235 grepbody(fn, rev, flog.read(fnode))
4239 grepbody(fn, rev, flog.read(fnode))
4236
4240
4237 pfn = copy or fn
4241 pfn = copy or fn
4238 if pfn not in matches[parent]:
4242 if pfn not in matches[parent]:
4239 try:
4243 try:
4240 fnode = pctx.filenode(pfn)
4244 fnode = pctx.filenode(pfn)
4241 grepbody(pfn, parent, flog.read(fnode))
4245 grepbody(pfn, parent, flog.read(fnode))
4242 except error.LookupError:
4246 except error.LookupError:
4243 pass
4247 pass
4244
4248
4245 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4249 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4246 rev = ctx.rev()
4250 rev = ctx.rev()
4247 parent = ctx.p1().rev()
4251 parent = ctx.p1().rev()
4248 for fn in sorted(revfiles.get(rev, [])):
4252 for fn in sorted(revfiles.get(rev, [])):
4249 states = matches[rev][fn]
4253 states = matches[rev][fn]
4250 copy = copies.get(rev, {}).get(fn)
4254 copy = copies.get(rev, {}).get(fn)
4251 if fn in skip:
4255 if fn in skip:
4252 if copy:
4256 if copy:
4253 skip[copy] = True
4257 skip[copy] = True
4254 continue
4258 continue
4255 pstates = matches.get(parent, {}).get(copy or fn, [])
4259 pstates = matches.get(parent, {}).get(copy or fn, [])
4256 if pstates or states:
4260 if pstates or states:
4257 r = display(fn, ctx, pstates, states)
4261 r = display(fn, ctx, pstates, states)
4258 found = found or r
4262 found = found or r
4259 if r and not opts.get('all'):
4263 if r and not opts.get('all'):
4260 skip[fn] = True
4264 skip[fn] = True
4261 if copy:
4265 if copy:
4262 skip[copy] = True
4266 skip[copy] = True
4263 del matches[rev]
4267 del matches[rev]
4264 del revfiles[rev]
4268 del revfiles[rev]
4265
4269
4266 return not found
4270 return not found
4267
4271
4268 @command('heads',
4272 @command('heads',
4269 [('r', 'rev', '',
4273 [('r', 'rev', '',
4270 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4274 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4271 ('t', 'topo', False, _('show topological heads only')),
4275 ('t', 'topo', False, _('show topological heads only')),
4272 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4276 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4273 ('c', 'closed', False, _('show normal and closed branch heads')),
4277 ('c', 'closed', False, _('show normal and closed branch heads')),
4274 ] + templateopts,
4278 ] + templateopts,
4275 _('[-ct] [-r STARTREV] [REV]...'))
4279 _('[-ct] [-r STARTREV] [REV]...'))
4276 def heads(ui, repo, *branchrevs, **opts):
4280 def heads(ui, repo, *branchrevs, **opts):
4277 """show branch heads
4281 """show branch heads
4278
4282
4279 With no arguments, show all open branch heads in the repository.
4283 With no arguments, show all open branch heads in the repository.
4280 Branch heads are changesets that have no descendants on the
4284 Branch heads are changesets that have no descendants on the
4281 same branch. They are where development generally takes place and
4285 same branch. They are where development generally takes place and
4282 are the usual targets for update and merge operations.
4286 are the usual targets for update and merge operations.
4283
4287
4284 If one or more REVs are given, only open branch heads on the
4288 If one or more REVs are given, only open branch heads on the
4285 branches associated with the specified changesets are shown. This
4289 branches associated with the specified changesets are shown. This
4286 means that you can use :hg:`heads .` to see the heads on the
4290 means that you can use :hg:`heads .` to see the heads on the
4287 currently checked-out branch.
4291 currently checked-out branch.
4288
4292
4289 If -c/--closed is specified, also show branch heads marked closed
4293 If -c/--closed is specified, also show branch heads marked closed
4290 (see :hg:`commit --close-branch`).
4294 (see :hg:`commit --close-branch`).
4291
4295
4292 If STARTREV is specified, only those heads that are descendants of
4296 If STARTREV is specified, only those heads that are descendants of
4293 STARTREV will be displayed.
4297 STARTREV will be displayed.
4294
4298
4295 If -t/--topo is specified, named branch mechanics will be ignored and only
4299 If -t/--topo is specified, named branch mechanics will be ignored and only
4296 topological heads (changesets with no children) will be shown.
4300 topological heads (changesets with no children) will be shown.
4297
4301
4298 Returns 0 if matching heads are found, 1 if not.
4302 Returns 0 if matching heads are found, 1 if not.
4299 """
4303 """
4300
4304
4301 start = None
4305 start = None
4302 if 'rev' in opts:
4306 if 'rev' in opts:
4303 start = scmutil.revsingle(repo, opts['rev'], None).node()
4307 start = scmutil.revsingle(repo, opts['rev'], None).node()
4304
4308
4305 if opts.get('topo'):
4309 if opts.get('topo'):
4306 heads = [repo[h] for h in repo.heads(start)]
4310 heads = [repo[h] for h in repo.heads(start)]
4307 else:
4311 else:
4308 heads = []
4312 heads = []
4309 for branch in repo.branchmap():
4313 for branch in repo.branchmap():
4310 heads += repo.branchheads(branch, start, opts.get('closed'))
4314 heads += repo.branchheads(branch, start, opts.get('closed'))
4311 heads = [repo[h] for h in heads]
4315 heads = [repo[h] for h in heads]
4312
4316
4313 if branchrevs:
4317 if branchrevs:
4314 branches = set(repo[br].branch() for br in branchrevs)
4318 branches = set(repo[br].branch() for br in branchrevs)
4315 heads = [h for h in heads if h.branch() in branches]
4319 heads = [h for h in heads if h.branch() in branches]
4316
4320
4317 if opts.get('active') and branchrevs:
4321 if opts.get('active') and branchrevs:
4318 dagheads = repo.heads(start)
4322 dagheads = repo.heads(start)
4319 heads = [h for h in heads if h.node() in dagheads]
4323 heads = [h for h in heads if h.node() in dagheads]
4320
4324
4321 if branchrevs:
4325 if branchrevs:
4322 haveheads = set(h.branch() for h in heads)
4326 haveheads = set(h.branch() for h in heads)
4323 if branches - haveheads:
4327 if branches - haveheads:
4324 headless = ', '.join(b for b in branches - haveheads)
4328 headless = ', '.join(b for b in branches - haveheads)
4325 msg = _('no open branch heads found on branches %s')
4329 msg = _('no open branch heads found on branches %s')
4326 if opts.get('rev'):
4330 if opts.get('rev'):
4327 msg += _(' (started at %s)') % opts['rev']
4331 msg += _(' (started at %s)') % opts['rev']
4328 ui.warn((msg + '\n') % headless)
4332 ui.warn((msg + '\n') % headless)
4329
4333
4330 if not heads:
4334 if not heads:
4331 return 1
4335 return 1
4332
4336
4333 heads = sorted(heads, key=lambda x: -x.rev())
4337 heads = sorted(heads, key=lambda x: -x.rev())
4334 displayer = cmdutil.show_changeset(ui, repo, opts)
4338 displayer = cmdutil.show_changeset(ui, repo, opts)
4335 for ctx in heads:
4339 for ctx in heads:
4336 displayer.show(ctx)
4340 displayer.show(ctx)
4337 displayer.close()
4341 displayer.close()
4338
4342
4339 @command('help',
4343 @command('help',
4340 [('e', 'extension', None, _('show only help for extensions')),
4344 [('e', 'extension', None, _('show only help for extensions')),
4341 ('c', 'command', None, _('show only help for commands')),
4345 ('c', 'command', None, _('show only help for commands')),
4342 ('k', 'keyword', None, _('show topics matching keyword')),
4346 ('k', 'keyword', None, _('show topics matching keyword')),
4343 ],
4347 ],
4344 _('[-eck] [TOPIC]'),
4348 _('[-eck] [TOPIC]'),
4345 norepo=True)
4349 norepo=True)
4346 def help_(ui, name=None, **opts):
4350 def help_(ui, name=None, **opts):
4347 """show help for a given topic or a help overview
4351 """show help for a given topic or a help overview
4348
4352
4349 With no arguments, print a list of commands with short help messages.
4353 With no arguments, print a list of commands with short help messages.
4350
4354
4351 Given a topic, extension, or command name, print help for that
4355 Given a topic, extension, or command name, print help for that
4352 topic.
4356 topic.
4353
4357
4354 Returns 0 if successful.
4358 Returns 0 if successful.
4355 """
4359 """
4356
4360
4357 textwidth = min(ui.termwidth(), 80) - 2
4361 textwidth = min(ui.termwidth(), 80) - 2
4358
4362
4359 keep = []
4363 keep = []
4360 if ui.verbose:
4364 if ui.verbose:
4361 keep.append('verbose')
4365 keep.append('verbose')
4362 if sys.platform.startswith('win'):
4366 if sys.platform.startswith('win'):
4363 keep.append('windows')
4367 keep.append('windows')
4364 elif sys.platform == 'OpenVMS':
4368 elif sys.platform == 'OpenVMS':
4365 keep.append('vms')
4369 keep.append('vms')
4366 elif sys.platform == 'plan9':
4370 elif sys.platform == 'plan9':
4367 keep.append('plan9')
4371 keep.append('plan9')
4368 else:
4372 else:
4369 keep.append('unix')
4373 keep.append('unix')
4370 keep.append(sys.platform.lower())
4374 keep.append(sys.platform.lower())
4371
4375
4372 section = None
4376 section = None
4373 subtopic = None
4377 subtopic = None
4374 if name and '.' in name:
4378 if name and '.' in name:
4375 name, section = name.split('.', 1)
4379 name, section = name.split('.', 1)
4376 section = section.lower()
4380 section = section.lower()
4377 if '.' in section:
4381 if '.' in section:
4378 subtopic, section = section.split('.', 1)
4382 subtopic, section = section.split('.', 1)
4379 else:
4383 else:
4380 subtopic = section
4384 subtopic = section
4381
4385
4382 text = help.help_(ui, name, subtopic=subtopic, **opts)
4386 text = help.help_(ui, name, subtopic=subtopic, **opts)
4383
4387
4384 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4388 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4385 section=section)
4389 section=section)
4386
4390
4387 # We could have been given a weird ".foo" section without a name
4391 # We could have been given a weird ".foo" section without a name
4388 # to look for, or we could have simply failed to found "foo.bar"
4392 # to look for, or we could have simply failed to found "foo.bar"
4389 # because bar isn't a section of foo
4393 # because bar isn't a section of foo
4390 if section and not (formatted and name):
4394 if section and not (formatted and name):
4391 raise error.Abort(_("help section not found"))
4395 raise error.Abort(_("help section not found"))
4392
4396
4393 if 'verbose' in pruned:
4397 if 'verbose' in pruned:
4394 keep.append('omitted')
4398 keep.append('omitted')
4395 else:
4399 else:
4396 keep.append('notomitted')
4400 keep.append('notomitted')
4397 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4401 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4398 section=section)
4402 section=section)
4399 ui.write(formatted)
4403 ui.write(formatted)
4400
4404
4401
4405
4402 @command('identify|id',
4406 @command('identify|id',
4403 [('r', 'rev', '',
4407 [('r', 'rev', '',
4404 _('identify the specified revision'), _('REV')),
4408 _('identify the specified revision'), _('REV')),
4405 ('n', 'num', None, _('show local revision number')),
4409 ('n', 'num', None, _('show local revision number')),
4406 ('i', 'id', None, _('show global revision id')),
4410 ('i', 'id', None, _('show global revision id')),
4407 ('b', 'branch', None, _('show branch')),
4411 ('b', 'branch', None, _('show branch')),
4408 ('t', 'tags', None, _('show tags')),
4412 ('t', 'tags', None, _('show tags')),
4409 ('B', 'bookmarks', None, _('show bookmarks')),
4413 ('B', 'bookmarks', None, _('show bookmarks')),
4410 ] + remoteopts,
4414 ] + remoteopts,
4411 _('[-nibtB] [-r REV] [SOURCE]'),
4415 _('[-nibtB] [-r REV] [SOURCE]'),
4412 optionalrepo=True)
4416 optionalrepo=True)
4413 def identify(ui, repo, source=None, rev=None,
4417 def identify(ui, repo, source=None, rev=None,
4414 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4418 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4415 """identify the working directory or specified revision
4419 """identify the working directory or specified revision
4416
4420
4417 Print a summary identifying the repository state at REV using one or
4421 Print a summary identifying the repository state at REV using one or
4418 two parent hash identifiers, followed by a "+" if the working
4422 two parent hash identifiers, followed by a "+" if the working
4419 directory has uncommitted changes, the branch name (if not default),
4423 directory has uncommitted changes, the branch name (if not default),
4420 a list of tags, and a list of bookmarks.
4424 a list of tags, and a list of bookmarks.
4421
4425
4422 When REV is not given, print a summary of the current state of the
4426 When REV is not given, print a summary of the current state of the
4423 repository.
4427 repository.
4424
4428
4425 Specifying a path to a repository root or Mercurial bundle will
4429 Specifying a path to a repository root or Mercurial bundle will
4426 cause lookup to operate on that repository/bundle.
4430 cause lookup to operate on that repository/bundle.
4427
4431
4428 .. container:: verbose
4432 .. container:: verbose
4429
4433
4430 Examples:
4434 Examples:
4431
4435
4432 - generate a build identifier for the working directory::
4436 - generate a build identifier for the working directory::
4433
4437
4434 hg id --id > build-id.dat
4438 hg id --id > build-id.dat
4435
4439
4436 - find the revision corresponding to a tag::
4440 - find the revision corresponding to a tag::
4437
4441
4438 hg id -n -r 1.3
4442 hg id -n -r 1.3
4439
4443
4440 - check the most recent revision of a remote repository::
4444 - check the most recent revision of a remote repository::
4441
4445
4442 hg id -r tip http://selenic.com/hg/
4446 hg id -r tip http://selenic.com/hg/
4443
4447
4444 See :hg:`log` for generating more information about specific revisions,
4448 See :hg:`log` for generating more information about specific revisions,
4445 including full hash identifiers.
4449 including full hash identifiers.
4446
4450
4447 Returns 0 if successful.
4451 Returns 0 if successful.
4448 """
4452 """
4449
4453
4450 if not repo and not source:
4454 if not repo and not source:
4451 raise error.Abort(_("there is no Mercurial repository here "
4455 raise error.Abort(_("there is no Mercurial repository here "
4452 "(.hg not found)"))
4456 "(.hg not found)"))
4453
4457
4454 if ui.debugflag:
4458 if ui.debugflag:
4455 hexfunc = hex
4459 hexfunc = hex
4456 else:
4460 else:
4457 hexfunc = short
4461 hexfunc = short
4458 default = not (num or id or branch or tags or bookmarks)
4462 default = not (num or id or branch or tags or bookmarks)
4459 output = []
4463 output = []
4460 revs = []
4464 revs = []
4461
4465
4462 if source:
4466 if source:
4463 source, branches = hg.parseurl(ui.expandpath(source))
4467 source, branches = hg.parseurl(ui.expandpath(source))
4464 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4468 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4465 repo = peer.local()
4469 repo = peer.local()
4466 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4470 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4467
4471
4468 if not repo:
4472 if not repo:
4469 if num or branch or tags:
4473 if num or branch or tags:
4470 raise error.Abort(
4474 raise error.Abort(
4471 _("can't query remote revision number, branch, or tags"))
4475 _("can't query remote revision number, branch, or tags"))
4472 if not rev and revs:
4476 if not rev and revs:
4473 rev = revs[0]
4477 rev = revs[0]
4474 if not rev:
4478 if not rev:
4475 rev = "tip"
4479 rev = "tip"
4476
4480
4477 remoterev = peer.lookup(rev)
4481 remoterev = peer.lookup(rev)
4478 if default or id:
4482 if default or id:
4479 output = [hexfunc(remoterev)]
4483 output = [hexfunc(remoterev)]
4480
4484
4481 def getbms():
4485 def getbms():
4482 bms = []
4486 bms = []
4483
4487
4484 if 'bookmarks' in peer.listkeys('namespaces'):
4488 if 'bookmarks' in peer.listkeys('namespaces'):
4485 hexremoterev = hex(remoterev)
4489 hexremoterev = hex(remoterev)
4486 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4490 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4487 if bmr == hexremoterev]
4491 if bmr == hexremoterev]
4488
4492
4489 return sorted(bms)
4493 return sorted(bms)
4490
4494
4491 if bookmarks:
4495 if bookmarks:
4492 output.extend(getbms())
4496 output.extend(getbms())
4493 elif default and not ui.quiet:
4497 elif default and not ui.quiet:
4494 # multiple bookmarks for a single parent separated by '/'
4498 # multiple bookmarks for a single parent separated by '/'
4495 bm = '/'.join(getbms())
4499 bm = '/'.join(getbms())
4496 if bm:
4500 if bm:
4497 output.append(bm)
4501 output.append(bm)
4498 else:
4502 else:
4499 ctx = scmutil.revsingle(repo, rev, None)
4503 ctx = scmutil.revsingle(repo, rev, None)
4500
4504
4501 if ctx.rev() is None:
4505 if ctx.rev() is None:
4502 ctx = repo[None]
4506 ctx = repo[None]
4503 parents = ctx.parents()
4507 parents = ctx.parents()
4504 taglist = []
4508 taglist = []
4505 for p in parents:
4509 for p in parents:
4506 taglist.extend(p.tags())
4510 taglist.extend(p.tags())
4507
4511
4508 changed = ""
4512 changed = ""
4509 if default or id or num:
4513 if default or id or num:
4510 if (any(repo.status())
4514 if (any(repo.status())
4511 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4515 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4512 changed = '+'
4516 changed = '+'
4513 if default or id:
4517 if default or id:
4514 output = ["%s%s" %
4518 output = ["%s%s" %
4515 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4519 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4516 if num:
4520 if num:
4517 output.append("%s%s" %
4521 output.append("%s%s" %
4518 ('+'.join([str(p.rev()) for p in parents]), changed))
4522 ('+'.join([str(p.rev()) for p in parents]), changed))
4519 else:
4523 else:
4520 if default or id:
4524 if default or id:
4521 output = [hexfunc(ctx.node())]
4525 output = [hexfunc(ctx.node())]
4522 if num:
4526 if num:
4523 output.append(str(ctx.rev()))
4527 output.append(str(ctx.rev()))
4524 taglist = ctx.tags()
4528 taglist = ctx.tags()
4525
4529
4526 if default and not ui.quiet:
4530 if default and not ui.quiet:
4527 b = ctx.branch()
4531 b = ctx.branch()
4528 if b != 'default':
4532 if b != 'default':
4529 output.append("(%s)" % b)
4533 output.append("(%s)" % b)
4530
4534
4531 # multiple tags for a single parent separated by '/'
4535 # multiple tags for a single parent separated by '/'
4532 t = '/'.join(taglist)
4536 t = '/'.join(taglist)
4533 if t:
4537 if t:
4534 output.append(t)
4538 output.append(t)
4535
4539
4536 # multiple bookmarks for a single parent separated by '/'
4540 # multiple bookmarks for a single parent separated by '/'
4537 bm = '/'.join(ctx.bookmarks())
4541 bm = '/'.join(ctx.bookmarks())
4538 if bm:
4542 if bm:
4539 output.append(bm)
4543 output.append(bm)
4540 else:
4544 else:
4541 if branch:
4545 if branch:
4542 output.append(ctx.branch())
4546 output.append(ctx.branch())
4543
4547
4544 if tags:
4548 if tags:
4545 output.extend(taglist)
4549 output.extend(taglist)
4546
4550
4547 if bookmarks:
4551 if bookmarks:
4548 output.extend(ctx.bookmarks())
4552 output.extend(ctx.bookmarks())
4549
4553
4550 ui.write("%s\n" % ' '.join(output))
4554 ui.write("%s\n" % ' '.join(output))
4551
4555
4552 @command('import|patch',
4556 @command('import|patch',
4553 [('p', 'strip', 1,
4557 [('p', 'strip', 1,
4554 _('directory strip option for patch. This has the same '
4558 _('directory strip option for patch. This has the same '
4555 'meaning as the corresponding patch option'), _('NUM')),
4559 'meaning as the corresponding patch option'), _('NUM')),
4556 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4560 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4557 ('e', 'edit', False, _('invoke editor on commit messages')),
4561 ('e', 'edit', False, _('invoke editor on commit messages')),
4558 ('f', 'force', None,
4562 ('f', 'force', None,
4559 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4563 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4560 ('', 'no-commit', None,
4564 ('', 'no-commit', None,
4561 _("don't commit, just update the working directory")),
4565 _("don't commit, just update the working directory")),
4562 ('', 'bypass', None,
4566 ('', 'bypass', None,
4563 _("apply patch without touching the working directory")),
4567 _("apply patch without touching the working directory")),
4564 ('', 'partial', None,
4568 ('', 'partial', None,
4565 _('commit even if some hunks fail')),
4569 _('commit even if some hunks fail')),
4566 ('', 'exact', None,
4570 ('', 'exact', None,
4567 _('apply patch to the nodes from which it was generated')),
4571 _('apply patch to the nodes from which it was generated')),
4568 ('', 'prefix', '',
4572 ('', 'prefix', '',
4569 _('apply patch to subdirectory'), _('DIR')),
4573 _('apply patch to subdirectory'), _('DIR')),
4570 ('', 'import-branch', None,
4574 ('', 'import-branch', None,
4571 _('use any branch information in patch (implied by --exact)'))] +
4575 _('use any branch information in patch (implied by --exact)'))] +
4572 commitopts + commitopts2 + similarityopts,
4576 commitopts + commitopts2 + similarityopts,
4573 _('[OPTION]... PATCH...'))
4577 _('[OPTION]... PATCH...'))
4574 def import_(ui, repo, patch1=None, *patches, **opts):
4578 def import_(ui, repo, patch1=None, *patches, **opts):
4575 """import an ordered set of patches
4579 """import an ordered set of patches
4576
4580
4577 Import a list of patches and commit them individually (unless
4581 Import a list of patches and commit them individually (unless
4578 --no-commit is specified).
4582 --no-commit is specified).
4579
4583
4580 To read a patch from standard input, use "-" as the patch name. If
4584 To read a patch from standard input, use "-" as the patch name. If
4581 a URL is specified, the patch will be downloaded from there.
4585 a URL is specified, the patch will be downloaded from there.
4582
4586
4583 Import first applies changes to the working directory (unless
4587 Import first applies changes to the working directory (unless
4584 --bypass is specified), import will abort if there are outstanding
4588 --bypass is specified), import will abort if there are outstanding
4585 changes.
4589 changes.
4586
4590
4587 Use --bypass to apply and commit patches directly to the
4591 Use --bypass to apply and commit patches directly to the
4588 repository, without affecting the working directory. Without
4592 repository, without affecting the working directory. Without
4589 --exact, patches will be applied on top of the working directory
4593 --exact, patches will be applied on top of the working directory
4590 parent revision.
4594 parent revision.
4591
4595
4592 You can import a patch straight from a mail message. Even patches
4596 You can import a patch straight from a mail message. Even patches
4593 as attachments work (to use the body part, it must have type
4597 as attachments work (to use the body part, it must have type
4594 text/plain or text/x-patch). From and Subject headers of email
4598 text/plain or text/x-patch). From and Subject headers of email
4595 message are used as default committer and commit message. All
4599 message are used as default committer and commit message. All
4596 text/plain body parts before first diff are added to the commit
4600 text/plain body parts before first diff are added to the commit
4597 message.
4601 message.
4598
4602
4599 If the imported patch was generated by :hg:`export`, user and
4603 If the imported patch was generated by :hg:`export`, user and
4600 description from patch override values from message headers and
4604 description from patch override values from message headers and
4601 body. Values given on command line with -m/--message and -u/--user
4605 body. Values given on command line with -m/--message and -u/--user
4602 override these.
4606 override these.
4603
4607
4604 If --exact is specified, import will set the working directory to
4608 If --exact is specified, import will set the working directory to
4605 the parent of each patch before applying it, and will abort if the
4609 the parent of each patch before applying it, and will abort if the
4606 resulting changeset has a different ID than the one recorded in
4610 resulting changeset has a different ID than the one recorded in
4607 the patch. This may happen due to character set problems or other
4611 the patch. This may happen due to character set problems or other
4608 deficiencies in the text patch format.
4612 deficiencies in the text patch format.
4609
4613
4610 Use --partial to ensure a changeset will be created from the patch
4614 Use --partial to ensure a changeset will be created from the patch
4611 even if some hunks fail to apply. Hunks that fail to apply will be
4615 even if some hunks fail to apply. Hunks that fail to apply will be
4612 written to a <target-file>.rej file. Conflicts can then be resolved
4616 written to a <target-file>.rej file. Conflicts can then be resolved
4613 by hand before :hg:`commit --amend` is run to update the created
4617 by hand before :hg:`commit --amend` is run to update the created
4614 changeset. This flag exists to let people import patches that
4618 changeset. This flag exists to let people import patches that
4615 partially apply without losing the associated metadata (author,
4619 partially apply without losing the associated metadata (author,
4616 date, description, ...).
4620 date, description, ...).
4617
4621
4618 .. note::
4622 .. note::
4619
4623
4620 When no hunks apply cleanly, :hg:`import --partial` will create
4624 When no hunks apply cleanly, :hg:`import --partial` will create
4621 an empty changeset, importing only the patch metadata.
4625 an empty changeset, importing only the patch metadata.
4622
4626
4623 With -s/--similarity, hg will attempt to discover renames and
4627 With -s/--similarity, hg will attempt to discover renames and
4624 copies in the patch in the same way as :hg:`addremove`.
4628 copies in the patch in the same way as :hg:`addremove`.
4625
4629
4626 It is possible to use external patch programs to perform the patch
4630 It is possible to use external patch programs to perform the patch
4627 by setting the ``ui.patch`` configuration option. For the default
4631 by setting the ``ui.patch`` configuration option. For the default
4628 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4632 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4629 See :hg:`help config` for more information about configuration
4633 See :hg:`help config` for more information about configuration
4630 files and how to use these options.
4634 files and how to use these options.
4631
4635
4632 See :hg:`help dates` for a list of formats valid for -d/--date.
4636 See :hg:`help dates` for a list of formats valid for -d/--date.
4633
4637
4634 .. container:: verbose
4638 .. container:: verbose
4635
4639
4636 Examples:
4640 Examples:
4637
4641
4638 - import a traditional patch from a website and detect renames::
4642 - import a traditional patch from a website and detect renames::
4639
4643
4640 hg import -s 80 http://example.com/bugfix.patch
4644 hg import -s 80 http://example.com/bugfix.patch
4641
4645
4642 - import a changeset from an hgweb server::
4646 - import a changeset from an hgweb server::
4643
4647
4644 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4648 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4645
4649
4646 - import all the patches in an Unix-style mbox::
4650 - import all the patches in an Unix-style mbox::
4647
4651
4648 hg import incoming-patches.mbox
4652 hg import incoming-patches.mbox
4649
4653
4650 - attempt to exactly restore an exported changeset (not always
4654 - attempt to exactly restore an exported changeset (not always
4651 possible)::
4655 possible)::
4652
4656
4653 hg import --exact proposed-fix.patch
4657 hg import --exact proposed-fix.patch
4654
4658
4655 - use an external tool to apply a patch which is too fuzzy for
4659 - use an external tool to apply a patch which is too fuzzy for
4656 the default internal tool.
4660 the default internal tool.
4657
4661
4658 hg import --config ui.patch="patch --merge" fuzzy.patch
4662 hg import --config ui.patch="patch --merge" fuzzy.patch
4659
4663
4660 - change the default fuzzing from 2 to a less strict 7
4664 - change the default fuzzing from 2 to a less strict 7
4661
4665
4662 hg import --config ui.fuzz=7 fuzz.patch
4666 hg import --config ui.fuzz=7 fuzz.patch
4663
4667
4664 Returns 0 on success, 1 on partial success (see --partial).
4668 Returns 0 on success, 1 on partial success (see --partial).
4665 """
4669 """
4666
4670
4667 if not patch1:
4671 if not patch1:
4668 raise error.Abort(_('need at least one patch to import'))
4672 raise error.Abort(_('need at least one patch to import'))
4669
4673
4670 patches = (patch1,) + patches
4674 patches = (patch1,) + patches
4671
4675
4672 date = opts.get('date')
4676 date = opts.get('date')
4673 if date:
4677 if date:
4674 opts['date'] = util.parsedate(date)
4678 opts['date'] = util.parsedate(date)
4675
4679
4676 exact = opts.get('exact')
4680 exact = opts.get('exact')
4677 update = not opts.get('bypass')
4681 update = not opts.get('bypass')
4678 if not update and opts.get('no_commit'):
4682 if not update and opts.get('no_commit'):
4679 raise error.Abort(_('cannot use --no-commit with --bypass'))
4683 raise error.Abort(_('cannot use --no-commit with --bypass'))
4680 try:
4684 try:
4681 sim = float(opts.get('similarity') or 0)
4685 sim = float(opts.get('similarity') or 0)
4682 except ValueError:
4686 except ValueError:
4683 raise error.Abort(_('similarity must be a number'))
4687 raise error.Abort(_('similarity must be a number'))
4684 if sim < 0 or sim > 100:
4688 if sim < 0 or sim > 100:
4685 raise error.Abort(_('similarity must be between 0 and 100'))
4689 raise error.Abort(_('similarity must be between 0 and 100'))
4686 if sim and not update:
4690 if sim and not update:
4687 raise error.Abort(_('cannot use --similarity with --bypass'))
4691 raise error.Abort(_('cannot use --similarity with --bypass'))
4688 if exact:
4692 if exact:
4689 if opts.get('edit'):
4693 if opts.get('edit'):
4690 raise error.Abort(_('cannot use --exact with --edit'))
4694 raise error.Abort(_('cannot use --exact with --edit'))
4691 if opts.get('prefix'):
4695 if opts.get('prefix'):
4692 raise error.Abort(_('cannot use --exact with --prefix'))
4696 raise error.Abort(_('cannot use --exact with --prefix'))
4693
4697
4694 base = opts["base"]
4698 base = opts["base"]
4695 wlock = dsguard = lock = tr = None
4699 wlock = dsguard = lock = tr = None
4696 msgs = []
4700 msgs = []
4697 ret = 0
4701 ret = 0
4698
4702
4699
4703
4700 try:
4704 try:
4701 try:
4705 try:
4702 wlock = repo.wlock()
4706 wlock = repo.wlock()
4703
4707
4704 if update:
4708 if update:
4705 cmdutil.checkunfinished(repo)
4709 cmdutil.checkunfinished(repo)
4706 if (exact or not opts.get('force')):
4710 if (exact or not opts.get('force')):
4707 cmdutil.bailifchanged(repo)
4711 cmdutil.bailifchanged(repo)
4708
4712
4709 if not opts.get('no_commit'):
4713 if not opts.get('no_commit'):
4710 lock = repo.lock()
4714 lock = repo.lock()
4711 tr = repo.transaction('import')
4715 tr = repo.transaction('import')
4712 else:
4716 else:
4713 dsguard = cmdutil.dirstateguard(repo, 'import')
4717 dsguard = cmdutil.dirstateguard(repo, 'import')
4714 parents = repo[None].parents()
4718 parents = repo[None].parents()
4715 for patchurl in patches:
4719 for patchurl in patches:
4716 if patchurl == '-':
4720 if patchurl == '-':
4717 ui.status(_('applying patch from stdin\n'))
4721 ui.status(_('applying patch from stdin\n'))
4718 patchfile = ui.fin
4722 patchfile = ui.fin
4719 patchurl = 'stdin' # for error message
4723 patchurl = 'stdin' # for error message
4720 else:
4724 else:
4721 patchurl = os.path.join(base, patchurl)
4725 patchurl = os.path.join(base, patchurl)
4722 ui.status(_('applying %s\n') % patchurl)
4726 ui.status(_('applying %s\n') % patchurl)
4723 patchfile = hg.openpath(ui, patchurl)
4727 patchfile = hg.openpath(ui, patchurl)
4724
4728
4725 haspatch = False
4729 haspatch = False
4726 for hunk in patch.split(patchfile):
4730 for hunk in patch.split(patchfile):
4727 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4731 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4728 parents, opts,
4732 parents, opts,
4729 msgs, hg.clean)
4733 msgs, hg.clean)
4730 if msg:
4734 if msg:
4731 haspatch = True
4735 haspatch = True
4732 ui.note(msg + '\n')
4736 ui.note(msg + '\n')
4733 if update or exact:
4737 if update or exact:
4734 parents = repo[None].parents()
4738 parents = repo[None].parents()
4735 else:
4739 else:
4736 parents = [repo[node]]
4740 parents = [repo[node]]
4737 if rej:
4741 if rej:
4738 ui.write_err(_("patch applied partially\n"))
4742 ui.write_err(_("patch applied partially\n"))
4739 ui.write_err(_("(fix the .rej files and run "
4743 ui.write_err(_("(fix the .rej files and run "
4740 "`hg commit --amend`)\n"))
4744 "`hg commit --amend`)\n"))
4741 ret = 1
4745 ret = 1
4742 break
4746 break
4743
4747
4744 if not haspatch:
4748 if not haspatch:
4745 raise error.Abort(_('%s: no diffs found') % patchurl)
4749 raise error.Abort(_('%s: no diffs found') % patchurl)
4746
4750
4747 if tr:
4751 if tr:
4748 tr.close()
4752 tr.close()
4749 if msgs:
4753 if msgs:
4750 repo.savecommitmessage('\n* * *\n'.join(msgs))
4754 repo.savecommitmessage('\n* * *\n'.join(msgs))
4751 if dsguard:
4755 if dsguard:
4752 dsguard.close()
4756 dsguard.close()
4753 return ret
4757 return ret
4754 finally:
4758 finally:
4755 # TODO: get rid of this meaningless try/finally enclosing.
4759 # TODO: get rid of this meaningless try/finally enclosing.
4756 # this is kept only to reduce changes in a patch.
4760 # this is kept only to reduce changes in a patch.
4757 pass
4761 pass
4758 finally:
4762 finally:
4759 if tr:
4763 if tr:
4760 tr.release()
4764 tr.release()
4761 release(lock, dsguard, wlock)
4765 release(lock, dsguard, wlock)
4762
4766
4763 @command('incoming|in',
4767 @command('incoming|in',
4764 [('f', 'force', None,
4768 [('f', 'force', None,
4765 _('run even if remote repository is unrelated')),
4769 _('run even if remote repository is unrelated')),
4766 ('n', 'newest-first', None, _('show newest record first')),
4770 ('n', 'newest-first', None, _('show newest record first')),
4767 ('', 'bundle', '',
4771 ('', 'bundle', '',
4768 _('file to store the bundles into'), _('FILE')),
4772 _('file to store the bundles into'), _('FILE')),
4769 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4773 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4770 ('B', 'bookmarks', False, _("compare bookmarks")),
4774 ('B', 'bookmarks', False, _("compare bookmarks")),
4771 ('b', 'branch', [],
4775 ('b', 'branch', [],
4772 _('a specific branch you would like to pull'), _('BRANCH')),
4776 _('a specific branch you would like to pull'), _('BRANCH')),
4773 ] + logopts + remoteopts + subrepoopts,
4777 ] + logopts + remoteopts + subrepoopts,
4774 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4778 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4775 def incoming(ui, repo, source="default", **opts):
4779 def incoming(ui, repo, source="default", **opts):
4776 """show new changesets found in source
4780 """show new changesets found in source
4777
4781
4778 Show new changesets found in the specified path/URL or the default
4782 Show new changesets found in the specified path/URL or the default
4779 pull location. These are the changesets that would have been pulled
4783 pull location. These are the changesets that would have been pulled
4780 if a pull at the time you issued this command.
4784 if a pull at the time you issued this command.
4781
4785
4782 See pull for valid source format details.
4786 See pull for valid source format details.
4783
4787
4784 .. container:: verbose
4788 .. container:: verbose
4785
4789
4786 With -B/--bookmarks, the result of bookmark comparison between
4790 With -B/--bookmarks, the result of bookmark comparison between
4787 local and remote repositories is displayed. With -v/--verbose,
4791 local and remote repositories is displayed. With -v/--verbose,
4788 status is also displayed for each bookmark like below::
4792 status is also displayed for each bookmark like below::
4789
4793
4790 BM1 01234567890a added
4794 BM1 01234567890a added
4791 BM2 1234567890ab advanced
4795 BM2 1234567890ab advanced
4792 BM3 234567890abc diverged
4796 BM3 234567890abc diverged
4793 BM4 34567890abcd changed
4797 BM4 34567890abcd changed
4794
4798
4795 The action taken locally when pulling depends on the
4799 The action taken locally when pulling depends on the
4796 status of each bookmark:
4800 status of each bookmark:
4797
4801
4798 :``added``: pull will create it
4802 :``added``: pull will create it
4799 :``advanced``: pull will update it
4803 :``advanced``: pull will update it
4800 :``diverged``: pull will create a divergent bookmark
4804 :``diverged``: pull will create a divergent bookmark
4801 :``changed``: result depends on remote changesets
4805 :``changed``: result depends on remote changesets
4802
4806
4803 From the point of view of pulling behavior, bookmark
4807 From the point of view of pulling behavior, bookmark
4804 existing only in the remote repository are treated as ``added``,
4808 existing only in the remote repository are treated as ``added``,
4805 even if it is in fact locally deleted.
4809 even if it is in fact locally deleted.
4806
4810
4807 .. container:: verbose
4811 .. container:: verbose
4808
4812
4809 For remote repository, using --bundle avoids downloading the
4813 For remote repository, using --bundle avoids downloading the
4810 changesets twice if the incoming is followed by a pull.
4814 changesets twice if the incoming is followed by a pull.
4811
4815
4812 Examples:
4816 Examples:
4813
4817
4814 - show incoming changes with patches and full description::
4818 - show incoming changes with patches and full description::
4815
4819
4816 hg incoming -vp
4820 hg incoming -vp
4817
4821
4818 - show incoming changes excluding merges, store a bundle::
4822 - show incoming changes excluding merges, store a bundle::
4819
4823
4820 hg in -vpM --bundle incoming.hg
4824 hg in -vpM --bundle incoming.hg
4821 hg pull incoming.hg
4825 hg pull incoming.hg
4822
4826
4823 - briefly list changes inside a bundle::
4827 - briefly list changes inside a bundle::
4824
4828
4825 hg in changes.hg -T "{desc|firstline}\\n"
4829 hg in changes.hg -T "{desc|firstline}\\n"
4826
4830
4827 Returns 0 if there are incoming changes, 1 otherwise.
4831 Returns 0 if there are incoming changes, 1 otherwise.
4828 """
4832 """
4829 if opts.get('graph'):
4833 if opts.get('graph'):
4830 cmdutil.checkunsupportedgraphflags([], opts)
4834 cmdutil.checkunsupportedgraphflags([], opts)
4831 def display(other, chlist, displayer):
4835 def display(other, chlist, displayer):
4832 revdag = cmdutil.graphrevs(other, chlist, opts)
4836 revdag = cmdutil.graphrevs(other, chlist, opts)
4833 cmdutil.displaygraph(ui, repo, revdag, displayer,
4837 cmdutil.displaygraph(ui, repo, revdag, displayer,
4834 graphmod.asciiedges)
4838 graphmod.asciiedges)
4835
4839
4836 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4840 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4837 return 0
4841 return 0
4838
4842
4839 if opts.get('bundle') and opts.get('subrepos'):
4843 if opts.get('bundle') and opts.get('subrepos'):
4840 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4844 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4841
4845
4842 if opts.get('bookmarks'):
4846 if opts.get('bookmarks'):
4843 source, branches = hg.parseurl(ui.expandpath(source),
4847 source, branches = hg.parseurl(ui.expandpath(source),
4844 opts.get('branch'))
4848 opts.get('branch'))
4845 other = hg.peer(repo, opts, source)
4849 other = hg.peer(repo, opts, source)
4846 if 'bookmarks' not in other.listkeys('namespaces'):
4850 if 'bookmarks' not in other.listkeys('namespaces'):
4847 ui.warn(_("remote doesn't support bookmarks\n"))
4851 ui.warn(_("remote doesn't support bookmarks\n"))
4848 return 0
4852 return 0
4849 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4853 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4850 return bookmarks.incoming(ui, repo, other)
4854 return bookmarks.incoming(ui, repo, other)
4851
4855
4852 repo._subtoppath = ui.expandpath(source)
4856 repo._subtoppath = ui.expandpath(source)
4853 try:
4857 try:
4854 return hg.incoming(ui, repo, source, opts)
4858 return hg.incoming(ui, repo, source, opts)
4855 finally:
4859 finally:
4856 del repo._subtoppath
4860 del repo._subtoppath
4857
4861
4858
4862
4859 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4863 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4860 norepo=True)
4864 norepo=True)
4861 def init(ui, dest=".", **opts):
4865 def init(ui, dest=".", **opts):
4862 """create a new repository in the given directory
4866 """create a new repository in the given directory
4863
4867
4864 Initialize a new repository in the given directory. If the given
4868 Initialize a new repository in the given directory. If the given
4865 directory does not exist, it will be created.
4869 directory does not exist, it will be created.
4866
4870
4867 If no directory is given, the current directory is used.
4871 If no directory is given, the current directory is used.
4868
4872
4869 It is possible to specify an ``ssh://`` URL as the destination.
4873 It is possible to specify an ``ssh://`` URL as the destination.
4870 See :hg:`help urls` for more information.
4874 See :hg:`help urls` for more information.
4871
4875
4872 Returns 0 on success.
4876 Returns 0 on success.
4873 """
4877 """
4874 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4878 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4875
4879
4876 @command('locate',
4880 @command('locate',
4877 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4881 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4878 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4882 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4879 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4883 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4880 ] + walkopts,
4884 ] + walkopts,
4881 _('[OPTION]... [PATTERN]...'))
4885 _('[OPTION]... [PATTERN]...'))
4882 def locate(ui, repo, *pats, **opts):
4886 def locate(ui, repo, *pats, **opts):
4883 """locate files matching specific patterns (DEPRECATED)
4887 """locate files matching specific patterns (DEPRECATED)
4884
4888
4885 Print files under Mercurial control in the working directory whose
4889 Print files under Mercurial control in the working directory whose
4886 names match the given patterns.
4890 names match the given patterns.
4887
4891
4888 By default, this command searches all directories in the working
4892 By default, this command searches all directories in the working
4889 directory. To search just the current directory and its
4893 directory. To search just the current directory and its
4890 subdirectories, use "--include .".
4894 subdirectories, use "--include .".
4891
4895
4892 If no patterns are given to match, this command prints the names
4896 If no patterns are given to match, this command prints the names
4893 of all files under Mercurial control in the working directory.
4897 of all files under Mercurial control in the working directory.
4894
4898
4895 If you want to feed the output of this command into the "xargs"
4899 If you want to feed the output of this command into the "xargs"
4896 command, use the -0 option to both this command and "xargs". This
4900 command, use the -0 option to both this command and "xargs". This
4897 will avoid the problem of "xargs" treating single filenames that
4901 will avoid the problem of "xargs" treating single filenames that
4898 contain whitespace as multiple filenames.
4902 contain whitespace as multiple filenames.
4899
4903
4900 See :hg:`help files` for a more versatile command.
4904 See :hg:`help files` for a more versatile command.
4901
4905
4902 Returns 0 if a match is found, 1 otherwise.
4906 Returns 0 if a match is found, 1 otherwise.
4903 """
4907 """
4904 if opts.get('print0'):
4908 if opts.get('print0'):
4905 end = '\0'
4909 end = '\0'
4906 else:
4910 else:
4907 end = '\n'
4911 end = '\n'
4908 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4912 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4909
4913
4910 ret = 1
4914 ret = 1
4911 ctx = repo[rev]
4915 ctx = repo[rev]
4912 m = scmutil.match(ctx, pats, opts, default='relglob',
4916 m = scmutil.match(ctx, pats, opts, default='relglob',
4913 badfn=lambda x, y: False)
4917 badfn=lambda x, y: False)
4914
4918
4915 for abs in ctx.matches(m):
4919 for abs in ctx.matches(m):
4916 if opts.get('fullpath'):
4920 if opts.get('fullpath'):
4917 ui.write(repo.wjoin(abs), end)
4921 ui.write(repo.wjoin(abs), end)
4918 else:
4922 else:
4919 ui.write(((pats and m.rel(abs)) or abs), end)
4923 ui.write(((pats and m.rel(abs)) or abs), end)
4920 ret = 0
4924 ret = 0
4921
4925
4922 return ret
4926 return ret
4923
4927
4924 @command('^log|history',
4928 @command('^log|history',
4925 [('f', 'follow', None,
4929 [('f', 'follow', None,
4926 _('follow changeset history, or file history across copies and renames')),
4930 _('follow changeset history, or file history across copies and renames')),
4927 ('', 'follow-first', None,
4931 ('', 'follow-first', None,
4928 _('only follow the first parent of merge changesets (DEPRECATED)')),
4932 _('only follow the first parent of merge changesets (DEPRECATED)')),
4929 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4933 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4930 ('C', 'copies', None, _('show copied files')),
4934 ('C', 'copies', None, _('show copied files')),
4931 ('k', 'keyword', [],
4935 ('k', 'keyword', [],
4932 _('do case-insensitive search for a given text'), _('TEXT')),
4936 _('do case-insensitive search for a given text'), _('TEXT')),
4933 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4937 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4934 ('', 'removed', None, _('include revisions where files were removed')),
4938 ('', 'removed', None, _('include revisions where files were removed')),
4935 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4939 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4936 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4940 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4937 ('', 'only-branch', [],
4941 ('', 'only-branch', [],
4938 _('show only changesets within the given named branch (DEPRECATED)'),
4942 _('show only changesets within the given named branch (DEPRECATED)'),
4939 _('BRANCH')),
4943 _('BRANCH')),
4940 ('b', 'branch', [],
4944 ('b', 'branch', [],
4941 _('show changesets within the given named branch'), _('BRANCH')),
4945 _('show changesets within the given named branch'), _('BRANCH')),
4942 ('P', 'prune', [],
4946 ('P', 'prune', [],
4943 _('do not display revision or any of its ancestors'), _('REV')),
4947 _('do not display revision or any of its ancestors'), _('REV')),
4944 ] + logopts + walkopts,
4948 ] + logopts + walkopts,
4945 _('[OPTION]... [FILE]'),
4949 _('[OPTION]... [FILE]'),
4946 inferrepo=True)
4950 inferrepo=True)
4947 def log(ui, repo, *pats, **opts):
4951 def log(ui, repo, *pats, **opts):
4948 """show revision history of entire repository or files
4952 """show revision history of entire repository or files
4949
4953
4950 Print the revision history of the specified files or the entire
4954 Print the revision history of the specified files or the entire
4951 project.
4955 project.
4952
4956
4953 If no revision range is specified, the default is ``tip:0`` unless
4957 If no revision range is specified, the default is ``tip:0`` unless
4954 --follow is set, in which case the working directory parent is
4958 --follow is set, in which case the working directory parent is
4955 used as the starting revision.
4959 used as the starting revision.
4956
4960
4957 File history is shown without following rename or copy history of
4961 File history is shown without following rename or copy history of
4958 files. Use -f/--follow with a filename to follow history across
4962 files. Use -f/--follow with a filename to follow history across
4959 renames and copies. --follow without a filename will only show
4963 renames and copies. --follow without a filename will only show
4960 ancestors or descendants of the starting revision.
4964 ancestors or descendants of the starting revision.
4961
4965
4962 By default this command prints revision number and changeset id,
4966 By default this command prints revision number and changeset id,
4963 tags, non-trivial parents, user, date and time, and a summary for
4967 tags, non-trivial parents, user, date and time, and a summary for
4964 each commit. When the -v/--verbose switch is used, the list of
4968 each commit. When the -v/--verbose switch is used, the list of
4965 changed files and full commit message are shown.
4969 changed files and full commit message are shown.
4966
4970
4967 With --graph the revisions are shown as an ASCII art DAG with the most
4971 With --graph the revisions are shown as an ASCII art DAG with the most
4968 recent changeset at the top.
4972 recent changeset at the top.
4969 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4973 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4970 and '+' represents a fork where the changeset from the lines below is a
4974 and '+' represents a fork where the changeset from the lines below is a
4971 parent of the 'o' merge on the same line.
4975 parent of the 'o' merge on the same line.
4972
4976
4973 .. note::
4977 .. note::
4974
4978
4975 :hg:`log --patch` may generate unexpected diff output for merge
4979 :hg:`log --patch` may generate unexpected diff output for merge
4976 changesets, as it will only compare the merge changeset against
4980 changesets, as it will only compare the merge changeset against
4977 its first parent. Also, only files different from BOTH parents
4981 its first parent. Also, only files different from BOTH parents
4978 will appear in files:.
4982 will appear in files:.
4979
4983
4980 .. note::
4984 .. note::
4981
4985
4982 For performance reasons, :hg:`log FILE` may omit duplicate changes
4986 For performance reasons, :hg:`log FILE` may omit duplicate changes
4983 made on branches and will not show removals or mode changes. To
4987 made on branches and will not show removals or mode changes. To
4984 see all such changes, use the --removed switch.
4988 see all such changes, use the --removed switch.
4985
4989
4986 .. container:: verbose
4990 .. container:: verbose
4987
4991
4988 Some examples:
4992 Some examples:
4989
4993
4990 - changesets with full descriptions and file lists::
4994 - changesets with full descriptions and file lists::
4991
4995
4992 hg log -v
4996 hg log -v
4993
4997
4994 - changesets ancestral to the working directory::
4998 - changesets ancestral to the working directory::
4995
4999
4996 hg log -f
5000 hg log -f
4997
5001
4998 - last 10 commits on the current branch::
5002 - last 10 commits on the current branch::
4999
5003
5000 hg log -l 10 -b .
5004 hg log -l 10 -b .
5001
5005
5002 - changesets showing all modifications of a file, including removals::
5006 - changesets showing all modifications of a file, including removals::
5003
5007
5004 hg log --removed file.c
5008 hg log --removed file.c
5005
5009
5006 - all changesets that touch a directory, with diffs, excluding merges::
5010 - all changesets that touch a directory, with diffs, excluding merges::
5007
5011
5008 hg log -Mp lib/
5012 hg log -Mp lib/
5009
5013
5010 - all revision numbers that match a keyword::
5014 - all revision numbers that match a keyword::
5011
5015
5012 hg log -k bug --template "{rev}\\n"
5016 hg log -k bug --template "{rev}\\n"
5013
5017
5014 - the full hash identifier of the working directory parent::
5018 - the full hash identifier of the working directory parent::
5015
5019
5016 hg log -r . --template "{node}\\n"
5020 hg log -r . --template "{node}\\n"
5017
5021
5018 - list available log templates::
5022 - list available log templates::
5019
5023
5020 hg log -T list
5024 hg log -T list
5021
5025
5022 - check if a given changeset is included in a tagged release::
5026 - check if a given changeset is included in a tagged release::
5023
5027
5024 hg log -r "a21ccf and ancestor(1.9)"
5028 hg log -r "a21ccf and ancestor(1.9)"
5025
5029
5026 - find all changesets by some user in a date range::
5030 - find all changesets by some user in a date range::
5027
5031
5028 hg log -k alice -d "may 2008 to jul 2008"
5032 hg log -k alice -d "may 2008 to jul 2008"
5029
5033
5030 - summary of all changesets after the last tag::
5034 - summary of all changesets after the last tag::
5031
5035
5032 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5036 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5033
5037
5034 See :hg:`help dates` for a list of formats valid for -d/--date.
5038 See :hg:`help dates` for a list of formats valid for -d/--date.
5035
5039
5036 See :hg:`help revisions` and :hg:`help revsets` for more about
5040 See :hg:`help revisions` and :hg:`help revsets` for more about
5037 specifying and ordering revisions.
5041 specifying and ordering revisions.
5038
5042
5039 See :hg:`help templates` for more about pre-packaged styles and
5043 See :hg:`help templates` for more about pre-packaged styles and
5040 specifying custom templates.
5044 specifying custom templates.
5041
5045
5042 Returns 0 on success.
5046 Returns 0 on success.
5043
5047
5044 """
5048 """
5045 if opts.get('follow') and opts.get('rev'):
5049 if opts.get('follow') and opts.get('rev'):
5046 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5050 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5047 del opts['follow']
5051 del opts['follow']
5048
5052
5049 if opts.get('graph'):
5053 if opts.get('graph'):
5050 return cmdutil.graphlog(ui, repo, *pats, **opts)
5054 return cmdutil.graphlog(ui, repo, *pats, **opts)
5051
5055
5052 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5056 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5053 limit = cmdutil.loglimit(opts)
5057 limit = cmdutil.loglimit(opts)
5054 count = 0
5058 count = 0
5055
5059
5056 getrenamed = None
5060 getrenamed = None
5057 if opts.get('copies'):
5061 if opts.get('copies'):
5058 endrev = None
5062 endrev = None
5059 if opts.get('rev'):
5063 if opts.get('rev'):
5060 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5064 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5061 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5065 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5062
5066
5063 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5067 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5064 for rev in revs:
5068 for rev in revs:
5065 if count == limit:
5069 if count == limit:
5066 break
5070 break
5067 ctx = repo[rev]
5071 ctx = repo[rev]
5068 copies = None
5072 copies = None
5069 if getrenamed is not None and rev:
5073 if getrenamed is not None and rev:
5070 copies = []
5074 copies = []
5071 for fn in ctx.files():
5075 for fn in ctx.files():
5072 rename = getrenamed(fn, rev)
5076 rename = getrenamed(fn, rev)
5073 if rename:
5077 if rename:
5074 copies.append((fn, rename[0]))
5078 copies.append((fn, rename[0]))
5075 if filematcher:
5079 if filematcher:
5076 revmatchfn = filematcher(ctx.rev())
5080 revmatchfn = filematcher(ctx.rev())
5077 else:
5081 else:
5078 revmatchfn = None
5082 revmatchfn = None
5079 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5083 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5080 if displayer.flush(ctx):
5084 if displayer.flush(ctx):
5081 count += 1
5085 count += 1
5082
5086
5083 displayer.close()
5087 displayer.close()
5084
5088
5085 @command('manifest',
5089 @command('manifest',
5086 [('r', 'rev', '', _('revision to display'), _('REV')),
5090 [('r', 'rev', '', _('revision to display'), _('REV')),
5087 ('', 'all', False, _("list files from all revisions"))]
5091 ('', 'all', False, _("list files from all revisions"))]
5088 + formatteropts,
5092 + formatteropts,
5089 _('[-r REV]'))
5093 _('[-r REV]'))
5090 def manifest(ui, repo, node=None, rev=None, **opts):
5094 def manifest(ui, repo, node=None, rev=None, **opts):
5091 """output the current or given revision of the project manifest
5095 """output the current or given revision of the project manifest
5092
5096
5093 Print a list of version controlled files for the given revision.
5097 Print a list of version controlled files for the given revision.
5094 If no revision is given, the first parent of the working directory
5098 If no revision is given, the first parent of the working directory
5095 is used, or the null revision if no revision is checked out.
5099 is used, or the null revision if no revision is checked out.
5096
5100
5097 With -v, print file permissions, symlink and executable bits.
5101 With -v, print file permissions, symlink and executable bits.
5098 With --debug, print file revision hashes.
5102 With --debug, print file revision hashes.
5099
5103
5100 If option --all is specified, the list of all files from all revisions
5104 If option --all is specified, the list of all files from all revisions
5101 is printed. This includes deleted and renamed files.
5105 is printed. This includes deleted and renamed files.
5102
5106
5103 Returns 0 on success.
5107 Returns 0 on success.
5104 """
5108 """
5105
5109
5106 fm = ui.formatter('manifest', opts)
5110 fm = ui.formatter('manifest', opts)
5107
5111
5108 if opts.get('all'):
5112 if opts.get('all'):
5109 if rev or node:
5113 if rev or node:
5110 raise error.Abort(_("can't specify a revision with --all"))
5114 raise error.Abort(_("can't specify a revision with --all"))
5111
5115
5112 res = []
5116 res = []
5113 prefix = "data/"
5117 prefix = "data/"
5114 suffix = ".i"
5118 suffix = ".i"
5115 plen = len(prefix)
5119 plen = len(prefix)
5116 slen = len(suffix)
5120 slen = len(suffix)
5117 lock = repo.lock()
5121 lock = repo.lock()
5118 try:
5122 try:
5119 for fn, b, size in repo.store.datafiles():
5123 for fn, b, size in repo.store.datafiles():
5120 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5124 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5121 res.append(fn[plen:-slen])
5125 res.append(fn[plen:-slen])
5122 finally:
5126 finally:
5123 lock.release()
5127 lock.release()
5124 for f in res:
5128 for f in res:
5125 fm.startitem()
5129 fm.startitem()
5126 fm.write("path", '%s\n', f)
5130 fm.write("path", '%s\n', f)
5127 fm.end()
5131 fm.end()
5128 return
5132 return
5129
5133
5130 if rev and node:
5134 if rev and node:
5131 raise error.Abort(_("please specify just one revision"))
5135 raise error.Abort(_("please specify just one revision"))
5132
5136
5133 if not node:
5137 if not node:
5134 node = rev
5138 node = rev
5135
5139
5136 char = {'l': '@', 'x': '*', '': ''}
5140 char = {'l': '@', 'x': '*', '': ''}
5137 mode = {'l': '644', 'x': '755', '': '644'}
5141 mode = {'l': '644', 'x': '755', '': '644'}
5138 ctx = scmutil.revsingle(repo, node)
5142 ctx = scmutil.revsingle(repo, node)
5139 mf = ctx.manifest()
5143 mf = ctx.manifest()
5140 for f in ctx:
5144 for f in ctx:
5141 fm.startitem()
5145 fm.startitem()
5142 fl = ctx[f].flags()
5146 fl = ctx[f].flags()
5143 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5147 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5144 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5148 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5145 fm.write('path', '%s\n', f)
5149 fm.write('path', '%s\n', f)
5146 fm.end()
5150 fm.end()
5147
5151
5148 @command('^merge',
5152 @command('^merge',
5149 [('f', 'force', None,
5153 [('f', 'force', None,
5150 _('force a merge including outstanding changes (DEPRECATED)')),
5154 _('force a merge including outstanding changes (DEPRECATED)')),
5151 ('r', 'rev', '', _('revision to merge'), _('REV')),
5155 ('r', 'rev', '', _('revision to merge'), _('REV')),
5152 ('P', 'preview', None,
5156 ('P', 'preview', None,
5153 _('review revisions to merge (no merge is performed)'))
5157 _('review revisions to merge (no merge is performed)'))
5154 ] + mergetoolopts,
5158 ] + mergetoolopts,
5155 _('[-P] [-f] [[-r] REV]'))
5159 _('[-P] [-f] [[-r] REV]'))
5156 def merge(ui, repo, node=None, **opts):
5160 def merge(ui, repo, node=None, **opts):
5157 """merge another revision into working directory
5161 """merge another revision into working directory
5158
5162
5159 The current working directory is updated with all changes made in
5163 The current working directory is updated with all changes made in
5160 the requested revision since the last common predecessor revision.
5164 the requested revision since the last common predecessor revision.
5161
5165
5162 Files that changed between either parent are marked as changed for
5166 Files that changed between either parent are marked as changed for
5163 the next commit and a commit must be performed before any further
5167 the next commit and a commit must be performed before any further
5164 updates to the repository are allowed. The next commit will have
5168 updates to the repository are allowed. The next commit will have
5165 two parents.
5169 two parents.
5166
5170
5167 ``--tool`` can be used to specify the merge tool used for file
5171 ``--tool`` can be used to specify the merge tool used for file
5168 merges. It overrides the HGMERGE environment variable and your
5172 merges. It overrides the HGMERGE environment variable and your
5169 configuration files. See :hg:`help merge-tools` for options.
5173 configuration files. See :hg:`help merge-tools` for options.
5170
5174
5171 If no revision is specified, the working directory's parent is a
5175 If no revision is specified, the working directory's parent is a
5172 head revision, and the current branch contains exactly one other
5176 head revision, and the current branch contains exactly one other
5173 head, the other head is merged with by default. Otherwise, an
5177 head, the other head is merged with by default. Otherwise, an
5174 explicit revision with which to merge with must be provided.
5178 explicit revision with which to merge with must be provided.
5175
5179
5176 See :hg:`help resolve` for information on handling file conflicts.
5180 See :hg:`help resolve` for information on handling file conflicts.
5177
5181
5178 To undo an uncommitted merge, use :hg:`update --clean .` which
5182 To undo an uncommitted merge, use :hg:`update --clean .` which
5179 will check out a clean copy of the original merge parent, losing
5183 will check out a clean copy of the original merge parent, losing
5180 all changes.
5184 all changes.
5181
5185
5182 Returns 0 on success, 1 if there are unresolved files.
5186 Returns 0 on success, 1 if there are unresolved files.
5183 """
5187 """
5184
5188
5185 if opts.get('rev') and node:
5189 if opts.get('rev') and node:
5186 raise error.Abort(_("please specify just one revision"))
5190 raise error.Abort(_("please specify just one revision"))
5187 if not node:
5191 if not node:
5188 node = opts.get('rev')
5192 node = opts.get('rev')
5189
5193
5190 if node:
5194 if node:
5191 node = scmutil.revsingle(repo, node).node()
5195 node = scmutil.revsingle(repo, node).node()
5192
5196
5193 if not node:
5197 if not node:
5194 node = repo[destutil.destmerge(repo)].node()
5198 node = repo[destutil.destmerge(repo)].node()
5195
5199
5196 if opts.get('preview'):
5200 if opts.get('preview'):
5197 # find nodes that are ancestors of p2 but not of p1
5201 # find nodes that are ancestors of p2 but not of p1
5198 p1 = repo.lookup('.')
5202 p1 = repo.lookup('.')
5199 p2 = repo.lookup(node)
5203 p2 = repo.lookup(node)
5200 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5204 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5201
5205
5202 displayer = cmdutil.show_changeset(ui, repo, opts)
5206 displayer = cmdutil.show_changeset(ui, repo, opts)
5203 for node in nodes:
5207 for node in nodes:
5204 displayer.show(repo[node])
5208 displayer.show(repo[node])
5205 displayer.close()
5209 displayer.close()
5206 return 0
5210 return 0
5207
5211
5208 try:
5212 try:
5209 # ui.forcemerge is an internal variable, do not document
5213 # ui.forcemerge is an internal variable, do not document
5210 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5214 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5211 return hg.merge(repo, node, force=opts.get('force'))
5215 return hg.merge(repo, node, force=opts.get('force'))
5212 finally:
5216 finally:
5213 ui.setconfig('ui', 'forcemerge', '', 'merge')
5217 ui.setconfig('ui', 'forcemerge', '', 'merge')
5214
5218
5215 @command('outgoing|out',
5219 @command('outgoing|out',
5216 [('f', 'force', None, _('run even when the destination is unrelated')),
5220 [('f', 'force', None, _('run even when the destination is unrelated')),
5217 ('r', 'rev', [],
5221 ('r', 'rev', [],
5218 _('a changeset intended to be included in the destination'), _('REV')),
5222 _('a changeset intended to be included in the destination'), _('REV')),
5219 ('n', 'newest-first', None, _('show newest record first')),
5223 ('n', 'newest-first', None, _('show newest record first')),
5220 ('B', 'bookmarks', False, _('compare bookmarks')),
5224 ('B', 'bookmarks', False, _('compare bookmarks')),
5221 ('b', 'branch', [], _('a specific branch you would like to push'),
5225 ('b', 'branch', [], _('a specific branch you would like to push'),
5222 _('BRANCH')),
5226 _('BRANCH')),
5223 ] + logopts + remoteopts + subrepoopts,
5227 ] + logopts + remoteopts + subrepoopts,
5224 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5228 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5225 def outgoing(ui, repo, dest=None, **opts):
5229 def outgoing(ui, repo, dest=None, **opts):
5226 """show changesets not found in the destination
5230 """show changesets not found in the destination
5227
5231
5228 Show changesets not found in the specified destination repository
5232 Show changesets not found in the specified destination repository
5229 or the default push location. These are the changesets that would
5233 or the default push location. These are the changesets that would
5230 be pushed if a push was requested.
5234 be pushed if a push was requested.
5231
5235
5232 See pull for details of valid destination formats.
5236 See pull for details of valid destination formats.
5233
5237
5234 .. container:: verbose
5238 .. container:: verbose
5235
5239
5236 With -B/--bookmarks, the result of bookmark comparison between
5240 With -B/--bookmarks, the result of bookmark comparison between
5237 local and remote repositories is displayed. With -v/--verbose,
5241 local and remote repositories is displayed. With -v/--verbose,
5238 status is also displayed for each bookmark like below::
5242 status is also displayed for each bookmark like below::
5239
5243
5240 BM1 01234567890a added
5244 BM1 01234567890a added
5241 BM2 deleted
5245 BM2 deleted
5242 BM3 234567890abc advanced
5246 BM3 234567890abc advanced
5243 BM4 34567890abcd diverged
5247 BM4 34567890abcd diverged
5244 BM5 4567890abcde changed
5248 BM5 4567890abcde changed
5245
5249
5246 The action taken when pushing depends on the
5250 The action taken when pushing depends on the
5247 status of each bookmark:
5251 status of each bookmark:
5248
5252
5249 :``added``: push with ``-B`` will create it
5253 :``added``: push with ``-B`` will create it
5250 :``deleted``: push with ``-B`` will delete it
5254 :``deleted``: push with ``-B`` will delete it
5251 :``advanced``: push will update it
5255 :``advanced``: push will update it
5252 :``diverged``: push with ``-B`` will update it
5256 :``diverged``: push with ``-B`` will update it
5253 :``changed``: push with ``-B`` will update it
5257 :``changed``: push with ``-B`` will update it
5254
5258
5255 From the point of view of pushing behavior, bookmarks
5259 From the point of view of pushing behavior, bookmarks
5256 existing only in the remote repository are treated as
5260 existing only in the remote repository are treated as
5257 ``deleted``, even if it is in fact added remotely.
5261 ``deleted``, even if it is in fact added remotely.
5258
5262
5259 Returns 0 if there are outgoing changes, 1 otherwise.
5263 Returns 0 if there are outgoing changes, 1 otherwise.
5260 """
5264 """
5261 if opts.get('graph'):
5265 if opts.get('graph'):
5262 cmdutil.checkunsupportedgraphflags([], opts)
5266 cmdutil.checkunsupportedgraphflags([], opts)
5263 o, other = hg._outgoing(ui, repo, dest, opts)
5267 o, other = hg._outgoing(ui, repo, dest, opts)
5264 if not o:
5268 if not o:
5265 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5269 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5266 return
5270 return
5267
5271
5268 revdag = cmdutil.graphrevs(repo, o, opts)
5272 revdag = cmdutil.graphrevs(repo, o, opts)
5269 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5273 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5270 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5274 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5271 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5275 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5272 return 0
5276 return 0
5273
5277
5274 if opts.get('bookmarks'):
5278 if opts.get('bookmarks'):
5275 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5279 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5276 dest, branches = hg.parseurl(dest, opts.get('branch'))
5280 dest, branches = hg.parseurl(dest, opts.get('branch'))
5277 other = hg.peer(repo, opts, dest)
5281 other = hg.peer(repo, opts, dest)
5278 if 'bookmarks' not in other.listkeys('namespaces'):
5282 if 'bookmarks' not in other.listkeys('namespaces'):
5279 ui.warn(_("remote doesn't support bookmarks\n"))
5283 ui.warn(_("remote doesn't support bookmarks\n"))
5280 return 0
5284 return 0
5281 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5285 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5282 return bookmarks.outgoing(ui, repo, other)
5286 return bookmarks.outgoing(ui, repo, other)
5283
5287
5284 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5288 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5285 try:
5289 try:
5286 return hg.outgoing(ui, repo, dest, opts)
5290 return hg.outgoing(ui, repo, dest, opts)
5287 finally:
5291 finally:
5288 del repo._subtoppath
5292 del repo._subtoppath
5289
5293
5290 @command('parents',
5294 @command('parents',
5291 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5295 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5292 ] + templateopts,
5296 ] + templateopts,
5293 _('[-r REV] [FILE]'),
5297 _('[-r REV] [FILE]'),
5294 inferrepo=True)
5298 inferrepo=True)
5295 def parents(ui, repo, file_=None, **opts):
5299 def parents(ui, repo, file_=None, **opts):
5296 """show the parents of the working directory or revision (DEPRECATED)
5300 """show the parents of the working directory or revision (DEPRECATED)
5297
5301
5298 Print the working directory's parent revisions. If a revision is
5302 Print the working directory's parent revisions. If a revision is
5299 given via -r/--rev, the parent of that revision will be printed.
5303 given via -r/--rev, the parent of that revision will be printed.
5300 If a file argument is given, the revision in which the file was
5304 If a file argument is given, the revision in which the file was
5301 last changed (before the working directory revision or the
5305 last changed (before the working directory revision or the
5302 argument to --rev if given) is printed.
5306 argument to --rev if given) is printed.
5303
5307
5304 This command is equivalent to::
5308 This command is equivalent to::
5305
5309
5306 hg log -r "p1()+p2()" or
5310 hg log -r "p1()+p2()" or
5307 hg log -r "p1(REV)+p2(REV)" or
5311 hg log -r "p1(REV)+p2(REV)" or
5308 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5312 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5309 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5313 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5310
5314
5311 See :hg:`summary` and :hg:`help revsets` for related information.
5315 See :hg:`summary` and :hg:`help revsets` for related information.
5312
5316
5313 Returns 0 on success.
5317 Returns 0 on success.
5314 """
5318 """
5315
5319
5316 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5320 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5317
5321
5318 if file_:
5322 if file_:
5319 m = scmutil.match(ctx, (file_,), opts)
5323 m = scmutil.match(ctx, (file_,), opts)
5320 if m.anypats() or len(m.files()) != 1:
5324 if m.anypats() or len(m.files()) != 1:
5321 raise error.Abort(_('can only specify an explicit filename'))
5325 raise error.Abort(_('can only specify an explicit filename'))
5322 file_ = m.files()[0]
5326 file_ = m.files()[0]
5323 filenodes = []
5327 filenodes = []
5324 for cp in ctx.parents():
5328 for cp in ctx.parents():
5325 if not cp:
5329 if not cp:
5326 continue
5330 continue
5327 try:
5331 try:
5328 filenodes.append(cp.filenode(file_))
5332 filenodes.append(cp.filenode(file_))
5329 except error.LookupError:
5333 except error.LookupError:
5330 pass
5334 pass
5331 if not filenodes:
5335 if not filenodes:
5332 raise error.Abort(_("'%s' not found in manifest!") % file_)
5336 raise error.Abort(_("'%s' not found in manifest!") % file_)
5333 p = []
5337 p = []
5334 for fn in filenodes:
5338 for fn in filenodes:
5335 fctx = repo.filectx(file_, fileid=fn)
5339 fctx = repo.filectx(file_, fileid=fn)
5336 p.append(fctx.node())
5340 p.append(fctx.node())
5337 else:
5341 else:
5338 p = [cp.node() for cp in ctx.parents()]
5342 p = [cp.node() for cp in ctx.parents()]
5339
5343
5340 displayer = cmdutil.show_changeset(ui, repo, opts)
5344 displayer = cmdutil.show_changeset(ui, repo, opts)
5341 for n in p:
5345 for n in p:
5342 if n != nullid:
5346 if n != nullid:
5343 displayer.show(repo[n])
5347 displayer.show(repo[n])
5344 displayer.close()
5348 displayer.close()
5345
5349
5346 @command('paths', [], _('[NAME]'), optionalrepo=True)
5350 @command('paths', [], _('[NAME]'), optionalrepo=True)
5347 def paths(ui, repo, search=None):
5351 def paths(ui, repo, search=None):
5348 """show aliases for remote repositories
5352 """show aliases for remote repositories
5349
5353
5350 Show definition of symbolic path name NAME. If no name is given,
5354 Show definition of symbolic path name NAME. If no name is given,
5351 show definition of all available names.
5355 show definition of all available names.
5352
5356
5353 Option -q/--quiet suppresses all output when searching for NAME
5357 Option -q/--quiet suppresses all output when searching for NAME
5354 and shows only the path names when listing all definitions.
5358 and shows only the path names when listing all definitions.
5355
5359
5356 Path names are defined in the [paths] section of your
5360 Path names are defined in the [paths] section of your
5357 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5361 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5358 repository, ``.hg/hgrc`` is used, too.
5362 repository, ``.hg/hgrc`` is used, too.
5359
5363
5360 The path names ``default`` and ``default-push`` have a special
5364 The path names ``default`` and ``default-push`` have a special
5361 meaning. When performing a push or pull operation, they are used
5365 meaning. When performing a push or pull operation, they are used
5362 as fallbacks if no location is specified on the command-line.
5366 as fallbacks if no location is specified on the command-line.
5363 When ``default-push`` is set, it will be used for push and
5367 When ``default-push`` is set, it will be used for push and
5364 ``default`` will be used for pull; otherwise ``default`` is used
5368 ``default`` will be used for pull; otherwise ``default`` is used
5365 as the fallback for both. When cloning a repository, the clone
5369 as the fallback for both. When cloning a repository, the clone
5366 source is written as ``default`` in ``.hg/hgrc``.
5370 source is written as ``default`` in ``.hg/hgrc``.
5367
5371
5368 .. note::
5372 .. note::
5369
5373
5370 ``default`` and ``default-push`` apply to all inbound (e.g.
5374 ``default`` and ``default-push`` apply to all inbound (e.g.
5371 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5375 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5372 and :hg:`bundle`) operations.
5376 and :hg:`bundle`) operations.
5373
5377
5374 See :hg:`help urls` for more information.
5378 See :hg:`help urls` for more information.
5375
5379
5376 Returns 0 on success.
5380 Returns 0 on success.
5377 """
5381 """
5378 if search:
5382 if search:
5379 for name, path in sorted(ui.paths.iteritems()):
5383 for name, path in sorted(ui.paths.iteritems()):
5380 if name == search:
5384 if name == search:
5381 ui.status("%s\n" % util.hidepassword(path.rawloc))
5385 ui.status("%s\n" % util.hidepassword(path.rawloc))
5382 return
5386 return
5383 if not ui.quiet:
5387 if not ui.quiet:
5384 ui.warn(_("not found!\n"))
5388 ui.warn(_("not found!\n"))
5385 return 1
5389 return 1
5386 else:
5390 else:
5387 for name, path in sorted(ui.paths.iteritems()):
5391 for name, path in sorted(ui.paths.iteritems()):
5388 if ui.quiet:
5392 if ui.quiet:
5389 ui.write("%s\n" % name)
5393 ui.write("%s\n" % name)
5390 else:
5394 else:
5391 ui.write("%s = %s\n" % (name,
5395 ui.write("%s = %s\n" % (name,
5392 util.hidepassword(path.rawloc)))
5396 util.hidepassword(path.rawloc)))
5393 for subopt, value in sorted(path.suboptions.items()):
5397 for subopt, value in sorted(path.suboptions.items()):
5394 ui.write('%s:%s = %s\n' % (name, subopt, value))
5398 ui.write('%s:%s = %s\n' % (name, subopt, value))
5395
5399
5396 @command('phase',
5400 @command('phase',
5397 [('p', 'public', False, _('set changeset phase to public')),
5401 [('p', 'public', False, _('set changeset phase to public')),
5398 ('d', 'draft', False, _('set changeset phase to draft')),
5402 ('d', 'draft', False, _('set changeset phase to draft')),
5399 ('s', 'secret', False, _('set changeset phase to secret')),
5403 ('s', 'secret', False, _('set changeset phase to secret')),
5400 ('f', 'force', False, _('allow to move boundary backward')),
5404 ('f', 'force', False, _('allow to move boundary backward')),
5401 ('r', 'rev', [], _('target revision'), _('REV')),
5405 ('r', 'rev', [], _('target revision'), _('REV')),
5402 ],
5406 ],
5403 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5407 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5404 def phase(ui, repo, *revs, **opts):
5408 def phase(ui, repo, *revs, **opts):
5405 """set or show the current phase name
5409 """set or show the current phase name
5406
5410
5407 With no argument, show the phase name of the current revision(s).
5411 With no argument, show the phase name of the current revision(s).
5408
5412
5409 With one of -p/--public, -d/--draft or -s/--secret, change the
5413 With one of -p/--public, -d/--draft or -s/--secret, change the
5410 phase value of the specified revisions.
5414 phase value of the specified revisions.
5411
5415
5412 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5416 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5413 lower phase to an higher phase. Phases are ordered as follows::
5417 lower phase to an higher phase. Phases are ordered as follows::
5414
5418
5415 public < draft < secret
5419 public < draft < secret
5416
5420
5417 Returns 0 on success, 1 if some phases could not be changed.
5421 Returns 0 on success, 1 if some phases could not be changed.
5418
5422
5419 (For more information about the phases concept, see :hg:`help phases`.)
5423 (For more information about the phases concept, see :hg:`help phases`.)
5420 """
5424 """
5421 # search for a unique phase argument
5425 # search for a unique phase argument
5422 targetphase = None
5426 targetphase = None
5423 for idx, name in enumerate(phases.phasenames):
5427 for idx, name in enumerate(phases.phasenames):
5424 if opts[name]:
5428 if opts[name]:
5425 if targetphase is not None:
5429 if targetphase is not None:
5426 raise error.Abort(_('only one phase can be specified'))
5430 raise error.Abort(_('only one phase can be specified'))
5427 targetphase = idx
5431 targetphase = idx
5428
5432
5429 # look for specified revision
5433 # look for specified revision
5430 revs = list(revs)
5434 revs = list(revs)
5431 revs.extend(opts['rev'])
5435 revs.extend(opts['rev'])
5432 if not revs:
5436 if not revs:
5433 # display both parents as the second parent phase can influence
5437 # display both parents as the second parent phase can influence
5434 # the phase of a merge commit
5438 # the phase of a merge commit
5435 revs = [c.rev() for c in repo[None].parents()]
5439 revs = [c.rev() for c in repo[None].parents()]
5436
5440
5437 revs = scmutil.revrange(repo, revs)
5441 revs = scmutil.revrange(repo, revs)
5438
5442
5439 lock = None
5443 lock = None
5440 ret = 0
5444 ret = 0
5441 if targetphase is None:
5445 if targetphase is None:
5442 # display
5446 # display
5443 for r in revs:
5447 for r in revs:
5444 ctx = repo[r]
5448 ctx = repo[r]
5445 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5449 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5446 else:
5450 else:
5447 tr = None
5451 tr = None
5448 lock = repo.lock()
5452 lock = repo.lock()
5449 try:
5453 try:
5450 tr = repo.transaction("phase")
5454 tr = repo.transaction("phase")
5451 # set phase
5455 # set phase
5452 if not revs:
5456 if not revs:
5453 raise error.Abort(_('empty revision set'))
5457 raise error.Abort(_('empty revision set'))
5454 nodes = [repo[r].node() for r in revs]
5458 nodes = [repo[r].node() for r in revs]
5455 # moving revision from public to draft may hide them
5459 # moving revision from public to draft may hide them
5456 # We have to check result on an unfiltered repository
5460 # We have to check result on an unfiltered repository
5457 unfi = repo.unfiltered()
5461 unfi = repo.unfiltered()
5458 getphase = unfi._phasecache.phase
5462 getphase = unfi._phasecache.phase
5459 olddata = [getphase(unfi, r) for r in unfi]
5463 olddata = [getphase(unfi, r) for r in unfi]
5460 phases.advanceboundary(repo, tr, targetphase, nodes)
5464 phases.advanceboundary(repo, tr, targetphase, nodes)
5461 if opts['force']:
5465 if opts['force']:
5462 phases.retractboundary(repo, tr, targetphase, nodes)
5466 phases.retractboundary(repo, tr, targetphase, nodes)
5463 tr.close()
5467 tr.close()
5464 finally:
5468 finally:
5465 if tr is not None:
5469 if tr is not None:
5466 tr.release()
5470 tr.release()
5467 lock.release()
5471 lock.release()
5468 getphase = unfi._phasecache.phase
5472 getphase = unfi._phasecache.phase
5469 newdata = [getphase(unfi, r) for r in unfi]
5473 newdata = [getphase(unfi, r) for r in unfi]
5470 changes = sum(newdata[r] != olddata[r] for r in unfi)
5474 changes = sum(newdata[r] != olddata[r] for r in unfi)
5471 cl = unfi.changelog
5475 cl = unfi.changelog
5472 rejected = [n for n in nodes
5476 rejected = [n for n in nodes
5473 if newdata[cl.rev(n)] < targetphase]
5477 if newdata[cl.rev(n)] < targetphase]
5474 if rejected:
5478 if rejected:
5475 ui.warn(_('cannot move %i changesets to a higher '
5479 ui.warn(_('cannot move %i changesets to a higher '
5476 'phase, use --force\n') % len(rejected))
5480 'phase, use --force\n') % len(rejected))
5477 ret = 1
5481 ret = 1
5478 if changes:
5482 if changes:
5479 msg = _('phase changed for %i changesets\n') % changes
5483 msg = _('phase changed for %i changesets\n') % changes
5480 if ret:
5484 if ret:
5481 ui.status(msg)
5485 ui.status(msg)
5482 else:
5486 else:
5483 ui.note(msg)
5487 ui.note(msg)
5484 else:
5488 else:
5485 ui.warn(_('no phases changed\n'))
5489 ui.warn(_('no phases changed\n'))
5486 return ret
5490 return ret
5487
5491
5488 def postincoming(ui, repo, modheads, optupdate, checkout):
5492 def postincoming(ui, repo, modheads, optupdate, checkout):
5489 if modheads == 0:
5493 if modheads == 0:
5490 return
5494 return
5491 if optupdate:
5495 if optupdate:
5492 try:
5496 try:
5493 brev = checkout
5497 brev = checkout
5494 movemarkfrom = None
5498 movemarkfrom = None
5495 if not checkout:
5499 if not checkout:
5496 updata = destutil.destupdate(repo)
5500 updata = destutil.destupdate(repo)
5497 checkout, movemarkfrom, brev = updata
5501 checkout, movemarkfrom, brev = updata
5498 ret = hg.update(repo, checkout)
5502 ret = hg.update(repo, checkout)
5499 except error.UpdateAbort as inst:
5503 except error.UpdateAbort as inst:
5500 msg = _("not updating: %s") % str(inst)
5504 msg = _("not updating: %s") % str(inst)
5501 hint = inst.hint
5505 hint = inst.hint
5502 raise error.UpdateAbort(msg, hint=hint)
5506 raise error.UpdateAbort(msg, hint=hint)
5503 if not ret and not checkout:
5507 if not ret and not checkout:
5504 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5508 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5505 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5509 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5506 return ret
5510 return ret
5507 if modheads > 1:
5511 if modheads > 1:
5508 currentbranchheads = len(repo.branchheads())
5512 currentbranchheads = len(repo.branchheads())
5509 if currentbranchheads == modheads:
5513 if currentbranchheads == modheads:
5510 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5514 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5511 elif currentbranchheads > 1:
5515 elif currentbranchheads > 1:
5512 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5516 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5513 "merge)\n"))
5517 "merge)\n"))
5514 else:
5518 else:
5515 ui.status(_("(run 'hg heads' to see heads)\n"))
5519 ui.status(_("(run 'hg heads' to see heads)\n"))
5516 else:
5520 else:
5517 ui.status(_("(run 'hg update' to get a working copy)\n"))
5521 ui.status(_("(run 'hg update' to get a working copy)\n"))
5518
5522
5519 @command('^pull',
5523 @command('^pull',
5520 [('u', 'update', None,
5524 [('u', 'update', None,
5521 _('update to new branch head if changesets were pulled')),
5525 _('update to new branch head if changesets were pulled')),
5522 ('f', 'force', None, _('run even when remote repository is unrelated')),
5526 ('f', 'force', None, _('run even when remote repository is unrelated')),
5523 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5527 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5524 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5528 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5525 ('b', 'branch', [], _('a specific branch you would like to pull'),
5529 ('b', 'branch', [], _('a specific branch you would like to pull'),
5526 _('BRANCH')),
5530 _('BRANCH')),
5527 ] + remoteopts,
5531 ] + remoteopts,
5528 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5532 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5529 def pull(ui, repo, source="default", **opts):
5533 def pull(ui, repo, source="default", **opts):
5530 """pull changes from the specified source
5534 """pull changes from the specified source
5531
5535
5532 Pull changes from a remote repository to a local one.
5536 Pull changes from a remote repository to a local one.
5533
5537
5534 This finds all changes from the repository at the specified path
5538 This finds all changes from the repository at the specified path
5535 or URL and adds them to a local repository (the current one unless
5539 or URL and adds them to a local repository (the current one unless
5536 -R is specified). By default, this does not update the copy of the
5540 -R is specified). By default, this does not update the copy of the
5537 project in the working directory.
5541 project in the working directory.
5538
5542
5539 Use :hg:`incoming` if you want to see what would have been added
5543 Use :hg:`incoming` if you want to see what would have been added
5540 by a pull at the time you issued this command. If you then decide
5544 by a pull at the time you issued this command. If you then decide
5541 to add those changes to the repository, you should use :hg:`pull
5545 to add those changes to the repository, you should use :hg:`pull
5542 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5546 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5543
5547
5544 If SOURCE is omitted, the 'default' path will be used.
5548 If SOURCE is omitted, the 'default' path will be used.
5545 See :hg:`help urls` for more information.
5549 See :hg:`help urls` for more information.
5546
5550
5547 Returns 0 on success, 1 if an update had unresolved files.
5551 Returns 0 on success, 1 if an update had unresolved files.
5548 """
5552 """
5549 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5553 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5550 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5554 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5551 other = hg.peer(repo, opts, source)
5555 other = hg.peer(repo, opts, source)
5552 try:
5556 try:
5553 revs, checkout = hg.addbranchrevs(repo, other, branches,
5557 revs, checkout = hg.addbranchrevs(repo, other, branches,
5554 opts.get('rev'))
5558 opts.get('rev'))
5555
5559
5556
5560
5557 pullopargs = {}
5561 pullopargs = {}
5558 if opts.get('bookmark'):
5562 if opts.get('bookmark'):
5559 if not revs:
5563 if not revs:
5560 revs = []
5564 revs = []
5561 # The list of bookmark used here is not the one used to actually
5565 # The list of bookmark used here is not the one used to actually
5562 # update the bookmark name. This can result in the revision pulled
5566 # update the bookmark name. This can result in the revision pulled
5563 # not ending up with the name of the bookmark because of a race
5567 # not ending up with the name of the bookmark because of a race
5564 # condition on the server. (See issue 4689 for details)
5568 # condition on the server. (See issue 4689 for details)
5565 remotebookmarks = other.listkeys('bookmarks')
5569 remotebookmarks = other.listkeys('bookmarks')
5566 pullopargs['remotebookmarks'] = remotebookmarks
5570 pullopargs['remotebookmarks'] = remotebookmarks
5567 for b in opts['bookmark']:
5571 for b in opts['bookmark']:
5568 if b not in remotebookmarks:
5572 if b not in remotebookmarks:
5569 raise error.Abort(_('remote bookmark %s not found!') % b)
5573 raise error.Abort(_('remote bookmark %s not found!') % b)
5570 revs.append(remotebookmarks[b])
5574 revs.append(remotebookmarks[b])
5571
5575
5572 if revs:
5576 if revs:
5573 try:
5577 try:
5574 # When 'rev' is a bookmark name, we cannot guarantee that it
5578 # When 'rev' is a bookmark name, we cannot guarantee that it
5575 # will be updated with that name because of a race condition
5579 # will be updated with that name because of a race condition
5576 # server side. (See issue 4689 for details)
5580 # server side. (See issue 4689 for details)
5577 oldrevs = revs
5581 oldrevs = revs
5578 revs = [] # actually, nodes
5582 revs = [] # actually, nodes
5579 for r in oldrevs:
5583 for r in oldrevs:
5580 node = other.lookup(r)
5584 node = other.lookup(r)
5581 revs.append(node)
5585 revs.append(node)
5582 if r == checkout:
5586 if r == checkout:
5583 checkout = node
5587 checkout = node
5584 except error.CapabilityError:
5588 except error.CapabilityError:
5585 err = _("other repository doesn't support revision lookup, "
5589 err = _("other repository doesn't support revision lookup, "
5586 "so a rev cannot be specified.")
5590 "so a rev cannot be specified.")
5587 raise error.Abort(err)
5591 raise error.Abort(err)
5588
5592
5589 pullopargs.update(opts.get('opargs', {}))
5593 pullopargs.update(opts.get('opargs', {}))
5590 modheads = exchange.pull(repo, other, heads=revs,
5594 modheads = exchange.pull(repo, other, heads=revs,
5591 force=opts.get('force'),
5595 force=opts.get('force'),
5592 bookmarks=opts.get('bookmark', ()),
5596 bookmarks=opts.get('bookmark', ()),
5593 opargs=pullopargs).cgresult
5597 opargs=pullopargs).cgresult
5594 if checkout:
5598 if checkout:
5595 checkout = str(repo.changelog.rev(checkout))
5599 checkout = str(repo.changelog.rev(checkout))
5596 repo._subtoppath = source
5600 repo._subtoppath = source
5597 try:
5601 try:
5598 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5602 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5599
5603
5600 finally:
5604 finally:
5601 del repo._subtoppath
5605 del repo._subtoppath
5602
5606
5603 finally:
5607 finally:
5604 other.close()
5608 other.close()
5605 return ret
5609 return ret
5606
5610
5607 @command('^push',
5611 @command('^push',
5608 [('f', 'force', None, _('force push')),
5612 [('f', 'force', None, _('force push')),
5609 ('r', 'rev', [],
5613 ('r', 'rev', [],
5610 _('a changeset intended to be included in the destination'),
5614 _('a changeset intended to be included in the destination'),
5611 _('REV')),
5615 _('REV')),
5612 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5616 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5613 ('b', 'branch', [],
5617 ('b', 'branch', [],
5614 _('a specific branch you would like to push'), _('BRANCH')),
5618 _('a specific branch you would like to push'), _('BRANCH')),
5615 ('', 'new-branch', False, _('allow pushing a new branch')),
5619 ('', 'new-branch', False, _('allow pushing a new branch')),
5616 ] + remoteopts,
5620 ] + remoteopts,
5617 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5621 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5618 def push(ui, repo, dest=None, **opts):
5622 def push(ui, repo, dest=None, **opts):
5619 """push changes to the specified destination
5623 """push changes to the specified destination
5620
5624
5621 Push changesets from the local repository to the specified
5625 Push changesets from the local repository to the specified
5622 destination.
5626 destination.
5623
5627
5624 This operation is symmetrical to pull: it is identical to a pull
5628 This operation is symmetrical to pull: it is identical to a pull
5625 in the destination repository from the current one.
5629 in the destination repository from the current one.
5626
5630
5627 By default, push will not allow creation of new heads at the
5631 By default, push will not allow creation of new heads at the
5628 destination, since multiple heads would make it unclear which head
5632 destination, since multiple heads would make it unclear which head
5629 to use. In this situation, it is recommended to pull and merge
5633 to use. In this situation, it is recommended to pull and merge
5630 before pushing.
5634 before pushing.
5631
5635
5632 Use --new-branch if you want to allow push to create a new named
5636 Use --new-branch if you want to allow push to create a new named
5633 branch that is not present at the destination. This allows you to
5637 branch that is not present at the destination. This allows you to
5634 only create a new branch without forcing other changes.
5638 only create a new branch without forcing other changes.
5635
5639
5636 .. note::
5640 .. note::
5637
5641
5638 Extra care should be taken with the -f/--force option,
5642 Extra care should be taken with the -f/--force option,
5639 which will push all new heads on all branches, an action which will
5643 which will push all new heads on all branches, an action which will
5640 almost always cause confusion for collaborators.
5644 almost always cause confusion for collaborators.
5641
5645
5642 If -r/--rev is used, the specified revision and all its ancestors
5646 If -r/--rev is used, the specified revision and all its ancestors
5643 will be pushed to the remote repository.
5647 will be pushed to the remote repository.
5644
5648
5645 If -B/--bookmark is used, the specified bookmarked revision, its
5649 If -B/--bookmark is used, the specified bookmarked revision, its
5646 ancestors, and the bookmark will be pushed to the remote
5650 ancestors, and the bookmark will be pushed to the remote
5647 repository.
5651 repository.
5648
5652
5649 Please see :hg:`help urls` for important details about ``ssh://``
5653 Please see :hg:`help urls` for important details about ``ssh://``
5650 URLs. If DESTINATION is omitted, a default path will be used.
5654 URLs. If DESTINATION is omitted, a default path will be used.
5651
5655
5652 Returns 0 if push was successful, 1 if nothing to push.
5656 Returns 0 if push was successful, 1 if nothing to push.
5653 """
5657 """
5654
5658
5655 if opts.get('bookmark'):
5659 if opts.get('bookmark'):
5656 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5660 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5657 for b in opts['bookmark']:
5661 for b in opts['bookmark']:
5658 # translate -B options to -r so changesets get pushed
5662 # translate -B options to -r so changesets get pushed
5659 if b in repo._bookmarks:
5663 if b in repo._bookmarks:
5660 opts.setdefault('rev', []).append(b)
5664 opts.setdefault('rev', []).append(b)
5661 else:
5665 else:
5662 # if we try to push a deleted bookmark, translate it to null
5666 # if we try to push a deleted bookmark, translate it to null
5663 # this lets simultaneous -r, -b options continue working
5667 # this lets simultaneous -r, -b options continue working
5664 opts.setdefault('rev', []).append("null")
5668 opts.setdefault('rev', []).append("null")
5665
5669
5666 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5670 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5667 if not path:
5671 if not path:
5668 raise error.Abort(_('default repository not configured!'),
5672 raise error.Abort(_('default repository not configured!'),
5669 hint=_('see the "path" section in "hg help config"'))
5673 hint=_('see the "path" section in "hg help config"'))
5670 dest = path.pushloc or path.loc
5674 dest = path.pushloc or path.loc
5671 branches = (path.branch, opts.get('branch') or [])
5675 branches = (path.branch, opts.get('branch') or [])
5672 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5676 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5673 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5677 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5674 other = hg.peer(repo, opts, dest)
5678 other = hg.peer(repo, opts, dest)
5675
5679
5676 if revs:
5680 if revs:
5677 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5681 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5678 if not revs:
5682 if not revs:
5679 raise error.Abort(_("specified revisions evaluate to an empty set"),
5683 raise error.Abort(_("specified revisions evaluate to an empty set"),
5680 hint=_("use different revision arguments"))
5684 hint=_("use different revision arguments"))
5681
5685
5682 repo._subtoppath = dest
5686 repo._subtoppath = dest
5683 try:
5687 try:
5684 # push subrepos depth-first for coherent ordering
5688 # push subrepos depth-first for coherent ordering
5685 c = repo['']
5689 c = repo['']
5686 subs = c.substate # only repos that are committed
5690 subs = c.substate # only repos that are committed
5687 for s in sorted(subs):
5691 for s in sorted(subs):
5688 result = c.sub(s).push(opts)
5692 result = c.sub(s).push(opts)
5689 if result == 0:
5693 if result == 0:
5690 return not result
5694 return not result
5691 finally:
5695 finally:
5692 del repo._subtoppath
5696 del repo._subtoppath
5693 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5697 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5694 newbranch=opts.get('new_branch'),
5698 newbranch=opts.get('new_branch'),
5695 bookmarks=opts.get('bookmark', ()),
5699 bookmarks=opts.get('bookmark', ()),
5696 opargs=opts.get('opargs'))
5700 opargs=opts.get('opargs'))
5697
5701
5698 result = not pushop.cgresult
5702 result = not pushop.cgresult
5699
5703
5700 if pushop.bkresult is not None:
5704 if pushop.bkresult is not None:
5701 if pushop.bkresult == 2:
5705 if pushop.bkresult == 2:
5702 result = 2
5706 result = 2
5703 elif not result and pushop.bkresult:
5707 elif not result and pushop.bkresult:
5704 result = 2
5708 result = 2
5705
5709
5706 return result
5710 return result
5707
5711
5708 @command('recover', [])
5712 @command('recover', [])
5709 def recover(ui, repo):
5713 def recover(ui, repo):
5710 """roll back an interrupted transaction
5714 """roll back an interrupted transaction
5711
5715
5712 Recover from an interrupted commit or pull.
5716 Recover from an interrupted commit or pull.
5713
5717
5714 This command tries to fix the repository status after an
5718 This command tries to fix the repository status after an
5715 interrupted operation. It should only be necessary when Mercurial
5719 interrupted operation. It should only be necessary when Mercurial
5716 suggests it.
5720 suggests it.
5717
5721
5718 Returns 0 if successful, 1 if nothing to recover or verify fails.
5722 Returns 0 if successful, 1 if nothing to recover or verify fails.
5719 """
5723 """
5720 if repo.recover():
5724 if repo.recover():
5721 return hg.verify(repo)
5725 return hg.verify(repo)
5722 return 1
5726 return 1
5723
5727
5724 @command('^remove|rm',
5728 @command('^remove|rm',
5725 [('A', 'after', None, _('record delete for missing files')),
5729 [('A', 'after', None, _('record delete for missing files')),
5726 ('f', 'force', None,
5730 ('f', 'force', None,
5727 _('remove (and delete) file even if added or modified')),
5731 _('remove (and delete) file even if added or modified')),
5728 ] + subrepoopts + walkopts,
5732 ] + subrepoopts + walkopts,
5729 _('[OPTION]... FILE...'),
5733 _('[OPTION]... FILE...'),
5730 inferrepo=True)
5734 inferrepo=True)
5731 def remove(ui, repo, *pats, **opts):
5735 def remove(ui, repo, *pats, **opts):
5732 """remove the specified files on the next commit
5736 """remove the specified files on the next commit
5733
5737
5734 Schedule the indicated files for removal from the current branch.
5738 Schedule the indicated files for removal from the current branch.
5735
5739
5736 This command schedules the files to be removed at the next commit.
5740 This command schedules the files to be removed at the next commit.
5737 To undo a remove before that, see :hg:`revert`. To undo added
5741 To undo a remove before that, see :hg:`revert`. To undo added
5738 files, see :hg:`forget`.
5742 files, see :hg:`forget`.
5739
5743
5740 .. container:: verbose
5744 .. container:: verbose
5741
5745
5742 -A/--after can be used to remove only files that have already
5746 -A/--after can be used to remove only files that have already
5743 been deleted, -f/--force can be used to force deletion, and -Af
5747 been deleted, -f/--force can be used to force deletion, and -Af
5744 can be used to remove files from the next revision without
5748 can be used to remove files from the next revision without
5745 deleting them from the working directory.
5749 deleting them from the working directory.
5746
5750
5747 The following table details the behavior of remove for different
5751 The following table details the behavior of remove for different
5748 file states (columns) and option combinations (rows). The file
5752 file states (columns) and option combinations (rows). The file
5749 states are Added [A], Clean [C], Modified [M] and Missing [!]
5753 states are Added [A], Clean [C], Modified [M] and Missing [!]
5750 (as reported by :hg:`status`). The actions are Warn, Remove
5754 (as reported by :hg:`status`). The actions are Warn, Remove
5751 (from branch) and Delete (from disk):
5755 (from branch) and Delete (from disk):
5752
5756
5753 ========= == == == ==
5757 ========= == == == ==
5754 opt/state A C M !
5758 opt/state A C M !
5755 ========= == == == ==
5759 ========= == == == ==
5756 none W RD W R
5760 none W RD W R
5757 -f R RD RD R
5761 -f R RD RD R
5758 -A W W W R
5762 -A W W W R
5759 -Af R R R R
5763 -Af R R R R
5760 ========= == == == ==
5764 ========= == == == ==
5761
5765
5762 .. note::
5766 .. note::
5763
5767
5764 :hg:`remove` never deletes files in Added [A] state from the
5768 :hg:`remove` never deletes files in Added [A] state from the
5765 working directory, not even if ``--force`` is specified.
5769 working directory, not even if ``--force`` is specified.
5766
5770
5767 Returns 0 on success, 1 if any warnings encountered.
5771 Returns 0 on success, 1 if any warnings encountered.
5768 """
5772 """
5769
5773
5770 after, force = opts.get('after'), opts.get('force')
5774 after, force = opts.get('after'), opts.get('force')
5771 if not pats and not after:
5775 if not pats and not after:
5772 raise error.Abort(_('no files specified'))
5776 raise error.Abort(_('no files specified'))
5773
5777
5774 m = scmutil.match(repo[None], pats, opts)
5778 m = scmutil.match(repo[None], pats, opts)
5775 subrepos = opts.get('subrepos')
5779 subrepos = opts.get('subrepos')
5776 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5780 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5777
5781
5778 @command('rename|move|mv',
5782 @command('rename|move|mv',
5779 [('A', 'after', None, _('record a rename that has already occurred')),
5783 [('A', 'after', None, _('record a rename that has already occurred')),
5780 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5784 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5781 ] + walkopts + dryrunopts,
5785 ] + walkopts + dryrunopts,
5782 _('[OPTION]... SOURCE... DEST'))
5786 _('[OPTION]... SOURCE... DEST'))
5783 def rename(ui, repo, *pats, **opts):
5787 def rename(ui, repo, *pats, **opts):
5784 """rename files; equivalent of copy + remove
5788 """rename files; equivalent of copy + remove
5785
5789
5786 Mark dest as copies of sources; mark sources for deletion. If dest
5790 Mark dest as copies of sources; mark sources for deletion. If dest
5787 is a directory, copies are put in that directory. If dest is a
5791 is a directory, copies are put in that directory. If dest is a
5788 file, there can only be one source.
5792 file, there can only be one source.
5789
5793
5790 By default, this command copies the contents of files as they
5794 By default, this command copies the contents of files as they
5791 exist in the working directory. If invoked with -A/--after, the
5795 exist in the working directory. If invoked with -A/--after, the
5792 operation is recorded, but no copying is performed.
5796 operation is recorded, but no copying is performed.
5793
5797
5794 This command takes effect at the next commit. To undo a rename
5798 This command takes effect at the next commit. To undo a rename
5795 before that, see :hg:`revert`.
5799 before that, see :hg:`revert`.
5796
5800
5797 Returns 0 on success, 1 if errors are encountered.
5801 Returns 0 on success, 1 if errors are encountered.
5798 """
5802 """
5799 wlock = repo.wlock(False)
5803 wlock = repo.wlock(False)
5800 try:
5804 try:
5801 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5805 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5802 finally:
5806 finally:
5803 wlock.release()
5807 wlock.release()
5804
5808
5805 @command('resolve',
5809 @command('resolve',
5806 [('a', 'all', None, _('select all unresolved files')),
5810 [('a', 'all', None, _('select all unresolved files')),
5807 ('l', 'list', None, _('list state of files needing merge')),
5811 ('l', 'list', None, _('list state of files needing merge')),
5808 ('m', 'mark', None, _('mark files as resolved')),
5812 ('m', 'mark', None, _('mark files as resolved')),
5809 ('u', 'unmark', None, _('mark files as unresolved')),
5813 ('u', 'unmark', None, _('mark files as unresolved')),
5810 ('n', 'no-status', None, _('hide status prefix'))]
5814 ('n', 'no-status', None, _('hide status prefix'))]
5811 + mergetoolopts + walkopts + formatteropts,
5815 + mergetoolopts + walkopts + formatteropts,
5812 _('[OPTION]... [FILE]...'),
5816 _('[OPTION]... [FILE]...'),
5813 inferrepo=True)
5817 inferrepo=True)
5814 def resolve(ui, repo, *pats, **opts):
5818 def resolve(ui, repo, *pats, **opts):
5815 """redo merges or set/view the merge status of files
5819 """redo merges or set/view the merge status of files
5816
5820
5817 Merges with unresolved conflicts are often the result of
5821 Merges with unresolved conflicts are often the result of
5818 non-interactive merging using the ``internal:merge`` configuration
5822 non-interactive merging using the ``internal:merge`` configuration
5819 setting, or a command-line merge tool like ``diff3``. The resolve
5823 setting, or a command-line merge tool like ``diff3``. The resolve
5820 command is used to manage the files involved in a merge, after
5824 command is used to manage the files involved in a merge, after
5821 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5825 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5822 working directory must have two parents). See :hg:`help
5826 working directory must have two parents). See :hg:`help
5823 merge-tools` for information on configuring merge tools.
5827 merge-tools` for information on configuring merge tools.
5824
5828
5825 The resolve command can be used in the following ways:
5829 The resolve command can be used in the following ways:
5826
5830
5827 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5831 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5828 files, discarding any previous merge attempts. Re-merging is not
5832 files, discarding any previous merge attempts. Re-merging is not
5829 performed for files already marked as resolved. Use ``--all/-a``
5833 performed for files already marked as resolved. Use ``--all/-a``
5830 to select all unresolved files. ``--tool`` can be used to specify
5834 to select all unresolved files. ``--tool`` can be used to specify
5831 the merge tool used for the given files. It overrides the HGMERGE
5835 the merge tool used for the given files. It overrides the HGMERGE
5832 environment variable and your configuration files. Previous file
5836 environment variable and your configuration files. Previous file
5833 contents are saved with a ``.orig`` suffix.
5837 contents are saved with a ``.orig`` suffix.
5834
5838
5835 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5839 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5836 (e.g. after having manually fixed-up the files). The default is
5840 (e.g. after having manually fixed-up the files). The default is
5837 to mark all unresolved files.
5841 to mark all unresolved files.
5838
5842
5839 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5843 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5840 default is to mark all resolved files.
5844 default is to mark all resolved files.
5841
5845
5842 - :hg:`resolve -l`: list files which had or still have conflicts.
5846 - :hg:`resolve -l`: list files which had or still have conflicts.
5843 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5847 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5844
5848
5845 .. note::
5849 .. note::
5846
5850
5847 Mercurial will not let you commit files with unresolved merge
5851 Mercurial will not let you commit files with unresolved merge
5848 conflicts. You must use :hg:`resolve -m ...` before you can
5852 conflicts. You must use :hg:`resolve -m ...` before you can
5849 commit after a conflicting merge.
5853 commit after a conflicting merge.
5850
5854
5851 Returns 0 on success, 1 if any files fail a resolve attempt.
5855 Returns 0 on success, 1 if any files fail a resolve attempt.
5852 """
5856 """
5853
5857
5854 all, mark, unmark, show, nostatus = \
5858 all, mark, unmark, show, nostatus = \
5855 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5859 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5856
5860
5857 if (show and (mark or unmark)) or (mark and unmark):
5861 if (show and (mark or unmark)) or (mark and unmark):
5858 raise error.Abort(_("too many options specified"))
5862 raise error.Abort(_("too many options specified"))
5859 if pats and all:
5863 if pats and all:
5860 raise error.Abort(_("can't specify --all and patterns"))
5864 raise error.Abort(_("can't specify --all and patterns"))
5861 if not (all or pats or show or mark or unmark):
5865 if not (all or pats or show or mark or unmark):
5862 raise error.Abort(_('no files or directories specified'),
5866 raise error.Abort(_('no files or directories specified'),
5863 hint=('use --all to re-merge all unresolved files'))
5867 hint=('use --all to re-merge all unresolved files'))
5864
5868
5865 if show:
5869 if show:
5866 fm = ui.formatter('resolve', opts)
5870 fm = ui.formatter('resolve', opts)
5867 ms = mergemod.mergestate.read(repo)
5871 ms = mergemod.mergestate.read(repo)
5868 m = scmutil.match(repo[None], pats, opts)
5872 m = scmutil.match(repo[None], pats, opts)
5869 for f in ms:
5873 for f in ms:
5870 if not m(f):
5874 if not m(f):
5871 continue
5875 continue
5872 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5876 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5873 'd': 'driverresolved'}[ms[f]]
5877 'd': 'driverresolved'}[ms[f]]
5874 fm.startitem()
5878 fm.startitem()
5875 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5879 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5876 fm.write('path', '%s\n', f, label=l)
5880 fm.write('path', '%s\n', f, label=l)
5877 fm.end()
5881 fm.end()
5878 return 0
5882 return 0
5879
5883
5880 wlock = repo.wlock()
5884 wlock = repo.wlock()
5881 try:
5885 try:
5882 ms = mergemod.mergestate.read(repo)
5886 ms = mergemod.mergestate.read(repo)
5883
5887
5884 if not (ms.active() or repo.dirstate.p2() != nullid):
5888 if not (ms.active() or repo.dirstate.p2() != nullid):
5885 raise error.Abort(
5889 raise error.Abort(
5886 _('resolve command not applicable when not merging'))
5890 _('resolve command not applicable when not merging'))
5887
5891
5888 wctx = repo[None]
5892 wctx = repo[None]
5889
5893
5890 if ms.mergedriver and ms.mdstate() == 'u':
5894 if ms.mergedriver and ms.mdstate() == 'u':
5891 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5895 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5892 ms.commit()
5896 ms.commit()
5893 # allow mark and unmark to go through
5897 # allow mark and unmark to go through
5894 if not mark and not unmark and not proceed:
5898 if not mark and not unmark and not proceed:
5895 return 1
5899 return 1
5896
5900
5897 m = scmutil.match(wctx, pats, opts)
5901 m = scmutil.match(wctx, pats, opts)
5898 ret = 0
5902 ret = 0
5899 didwork = False
5903 didwork = False
5900 runconclude = False
5904 runconclude = False
5901
5905
5902 tocomplete = []
5906 tocomplete = []
5903 for f in ms:
5907 for f in ms:
5904 if not m(f):
5908 if not m(f):
5905 continue
5909 continue
5906
5910
5907 didwork = True
5911 didwork = True
5908
5912
5909 # don't let driver-resolved files be marked, and run the conclude
5913 # don't let driver-resolved files be marked, and run the conclude
5910 # step if asked to resolve
5914 # step if asked to resolve
5911 if ms[f] == "d":
5915 if ms[f] == "d":
5912 exact = m.exact(f)
5916 exact = m.exact(f)
5913 if mark:
5917 if mark:
5914 if exact:
5918 if exact:
5915 ui.warn(_('not marking %s as it is driver-resolved\n')
5919 ui.warn(_('not marking %s as it is driver-resolved\n')
5916 % f)
5920 % f)
5917 elif unmark:
5921 elif unmark:
5918 if exact:
5922 if exact:
5919 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5923 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5920 % f)
5924 % f)
5921 else:
5925 else:
5922 runconclude = True
5926 runconclude = True
5923 continue
5927 continue
5924
5928
5925 if mark:
5929 if mark:
5926 ms.mark(f, "r")
5930 ms.mark(f, "r")
5927 elif unmark:
5931 elif unmark:
5928 ms.mark(f, "u")
5932 ms.mark(f, "u")
5929 else:
5933 else:
5930 # backup pre-resolve (merge uses .orig for its own purposes)
5934 # backup pre-resolve (merge uses .orig for its own purposes)
5931 a = repo.wjoin(f)
5935 a = repo.wjoin(f)
5932 try:
5936 try:
5933 util.copyfile(a, a + ".resolve")
5937 util.copyfile(a, a + ".resolve")
5934 except (IOError, OSError) as inst:
5938 except (IOError, OSError) as inst:
5935 if inst.errno != errno.ENOENT:
5939 if inst.errno != errno.ENOENT:
5936 raise
5940 raise
5937
5941
5938 try:
5942 try:
5939 # preresolve file
5943 # preresolve file
5940 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5944 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5941 'resolve')
5945 'resolve')
5942 complete, r = ms.preresolve(f, wctx)
5946 complete, r = ms.preresolve(f, wctx)
5943 if not complete:
5947 if not complete:
5944 tocomplete.append(f)
5948 tocomplete.append(f)
5945 elif r:
5949 elif r:
5946 ret = 1
5950 ret = 1
5947 finally:
5951 finally:
5948 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5952 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5949 ms.commit()
5953 ms.commit()
5950
5954
5951 # replace filemerge's .orig file with our resolve file, but only
5955 # replace filemerge's .orig file with our resolve file, but only
5952 # for merges that are complete
5956 # for merges that are complete
5953 if complete:
5957 if complete:
5954 try:
5958 try:
5955 util.rename(a + ".resolve",
5959 util.rename(a + ".resolve",
5956 scmutil.origpath(ui, repo, a))
5960 scmutil.origpath(ui, repo, a))
5957 except OSError as inst:
5961 except OSError as inst:
5958 if inst.errno != errno.ENOENT:
5962 if inst.errno != errno.ENOENT:
5959 raise
5963 raise
5960
5964
5961 for f in tocomplete:
5965 for f in tocomplete:
5962 try:
5966 try:
5963 # resolve file
5967 # resolve file
5964 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5968 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5965 'resolve')
5969 'resolve')
5966 r = ms.resolve(f, wctx)
5970 r = ms.resolve(f, wctx)
5967 if r:
5971 if r:
5968 ret = 1
5972 ret = 1
5969 finally:
5973 finally:
5970 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5974 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5971 ms.commit()
5975 ms.commit()
5972
5976
5973 # replace filemerge's .orig file with our resolve file
5977 # replace filemerge's .orig file with our resolve file
5974 a = repo.wjoin(f)
5978 a = repo.wjoin(f)
5975 try:
5979 try:
5976 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5980 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5977 except OSError as inst:
5981 except OSError as inst:
5978 if inst.errno != errno.ENOENT:
5982 if inst.errno != errno.ENOENT:
5979 raise
5983 raise
5980
5984
5981 ms.commit()
5985 ms.commit()
5982 ms.recordactions()
5986 ms.recordactions()
5983
5987
5984 if not didwork and pats:
5988 if not didwork and pats:
5985 ui.warn(_("arguments do not match paths that need resolving\n"))
5989 ui.warn(_("arguments do not match paths that need resolving\n"))
5986 elif ms.mergedriver and ms.mdstate() != 's':
5990 elif ms.mergedriver and ms.mdstate() != 's':
5987 # run conclude step when either a driver-resolved file is requested
5991 # run conclude step when either a driver-resolved file is requested
5988 # or there are no driver-resolved files
5992 # or there are no driver-resolved files
5989 # we can't use 'ret' to determine whether any files are unresolved
5993 # we can't use 'ret' to determine whether any files are unresolved
5990 # because we might not have tried to resolve some
5994 # because we might not have tried to resolve some
5991 if ((runconclude or not list(ms.driverresolved()))
5995 if ((runconclude or not list(ms.driverresolved()))
5992 and not list(ms.unresolved())):
5996 and not list(ms.unresolved())):
5993 proceed = mergemod.driverconclude(repo, ms, wctx)
5997 proceed = mergemod.driverconclude(repo, ms, wctx)
5994 ms.commit()
5998 ms.commit()
5995 if not proceed:
5999 if not proceed:
5996 return 1
6000 return 1
5997
6001
5998 finally:
6002 finally:
5999 wlock.release()
6003 wlock.release()
6000
6004
6001 # Nudge users into finishing an unfinished operation
6005 # Nudge users into finishing an unfinished operation
6002 unresolvedf = list(ms.unresolved())
6006 unresolvedf = list(ms.unresolved())
6003 driverresolvedf = list(ms.driverresolved())
6007 driverresolvedf = list(ms.driverresolved())
6004 if not unresolvedf and not driverresolvedf:
6008 if not unresolvedf and not driverresolvedf:
6005 ui.status(_('(no more unresolved files)\n'))
6009 ui.status(_('(no more unresolved files)\n'))
6006 cmdutil.checkafterresolved(repo)
6010 cmdutil.checkafterresolved(repo)
6007 elif not unresolvedf:
6011 elif not unresolvedf:
6008 ui.status(_('(no more unresolved files -- '
6012 ui.status(_('(no more unresolved files -- '
6009 'run "hg resolve --all" to conclude)\n'))
6013 'run "hg resolve --all" to conclude)\n'))
6010
6014
6011 return ret
6015 return ret
6012
6016
6013 @command('revert',
6017 @command('revert',
6014 [('a', 'all', None, _('revert all changes when no arguments given')),
6018 [('a', 'all', None, _('revert all changes when no arguments given')),
6015 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6019 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6016 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6020 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6017 ('C', 'no-backup', None, _('do not save backup copies of files')),
6021 ('C', 'no-backup', None, _('do not save backup copies of files')),
6018 ('i', 'interactive', None,
6022 ('i', 'interactive', None,
6019 _('interactively select the changes (EXPERIMENTAL)')),
6023 _('interactively select the changes (EXPERIMENTAL)')),
6020 ] + walkopts + dryrunopts,
6024 ] + walkopts + dryrunopts,
6021 _('[OPTION]... [-r REV] [NAME]...'))
6025 _('[OPTION]... [-r REV] [NAME]...'))
6022 def revert(ui, repo, *pats, **opts):
6026 def revert(ui, repo, *pats, **opts):
6023 """restore files to their checkout state
6027 """restore files to their checkout state
6024
6028
6025 .. note::
6029 .. note::
6026
6030
6027 To check out earlier revisions, you should use :hg:`update REV`.
6031 To check out earlier revisions, you should use :hg:`update REV`.
6028 To cancel an uncommitted merge (and lose your changes),
6032 To cancel an uncommitted merge (and lose your changes),
6029 use :hg:`update --clean .`.
6033 use :hg:`update --clean .`.
6030
6034
6031 With no revision specified, revert the specified files or directories
6035 With no revision specified, revert the specified files or directories
6032 to the contents they had in the parent of the working directory.
6036 to the contents they had in the parent of the working directory.
6033 This restores the contents of files to an unmodified
6037 This restores the contents of files to an unmodified
6034 state and unschedules adds, removes, copies, and renames. If the
6038 state and unschedules adds, removes, copies, and renames. If the
6035 working directory has two parents, you must explicitly specify a
6039 working directory has two parents, you must explicitly specify a
6036 revision.
6040 revision.
6037
6041
6038 Using the -r/--rev or -d/--date options, revert the given files or
6042 Using the -r/--rev or -d/--date options, revert the given files or
6039 directories to their states as of a specific revision. Because
6043 directories to their states as of a specific revision. Because
6040 revert does not change the working directory parents, this will
6044 revert does not change the working directory parents, this will
6041 cause these files to appear modified. This can be helpful to "back
6045 cause these files to appear modified. This can be helpful to "back
6042 out" some or all of an earlier change. See :hg:`backout` for a
6046 out" some or all of an earlier change. See :hg:`backout` for a
6043 related method.
6047 related method.
6044
6048
6045 Modified files are saved with a .orig suffix before reverting.
6049 Modified files are saved with a .orig suffix before reverting.
6046 To disable these backups, use --no-backup.
6050 To disable these backups, use --no-backup.
6047
6051
6048 See :hg:`help dates` for a list of formats valid for -d/--date.
6052 See :hg:`help dates` for a list of formats valid for -d/--date.
6049
6053
6050 See :hg:`help backout` for a way to reverse the effect of an
6054 See :hg:`help backout` for a way to reverse the effect of an
6051 earlier changeset.
6055 earlier changeset.
6052
6056
6053 Returns 0 on success.
6057 Returns 0 on success.
6054 """
6058 """
6055
6059
6056 if opts.get("date"):
6060 if opts.get("date"):
6057 if opts.get("rev"):
6061 if opts.get("rev"):
6058 raise error.Abort(_("you can't specify a revision and a date"))
6062 raise error.Abort(_("you can't specify a revision and a date"))
6059 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6063 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6060
6064
6061 parent, p2 = repo.dirstate.parents()
6065 parent, p2 = repo.dirstate.parents()
6062 if not opts.get('rev') and p2 != nullid:
6066 if not opts.get('rev') and p2 != nullid:
6063 # revert after merge is a trap for new users (issue2915)
6067 # revert after merge is a trap for new users (issue2915)
6064 raise error.Abort(_('uncommitted merge with no revision specified'),
6068 raise error.Abort(_('uncommitted merge with no revision specified'),
6065 hint=_('use "hg update" or see "hg help revert"'))
6069 hint=_('use "hg update" or see "hg help revert"'))
6066
6070
6067 ctx = scmutil.revsingle(repo, opts.get('rev'))
6071 ctx = scmutil.revsingle(repo, opts.get('rev'))
6068
6072
6069 if (not (pats or opts.get('include') or opts.get('exclude') or
6073 if (not (pats or opts.get('include') or opts.get('exclude') or
6070 opts.get('all') or opts.get('interactive'))):
6074 opts.get('all') or opts.get('interactive'))):
6071 msg = _("no files or directories specified")
6075 msg = _("no files or directories specified")
6072 if p2 != nullid:
6076 if p2 != nullid:
6073 hint = _("uncommitted merge, use --all to discard all changes,"
6077 hint = _("uncommitted merge, use --all to discard all changes,"
6074 " or 'hg update -C .' to abort the merge")
6078 " or 'hg update -C .' to abort the merge")
6075 raise error.Abort(msg, hint=hint)
6079 raise error.Abort(msg, hint=hint)
6076 dirty = any(repo.status())
6080 dirty = any(repo.status())
6077 node = ctx.node()
6081 node = ctx.node()
6078 if node != parent:
6082 if node != parent:
6079 if dirty:
6083 if dirty:
6080 hint = _("uncommitted changes, use --all to discard all"
6084 hint = _("uncommitted changes, use --all to discard all"
6081 " changes, or 'hg update %s' to update") % ctx.rev()
6085 " changes, or 'hg update %s' to update") % ctx.rev()
6082 else:
6086 else:
6083 hint = _("use --all to revert all files,"
6087 hint = _("use --all to revert all files,"
6084 " or 'hg update %s' to update") % ctx.rev()
6088 " or 'hg update %s' to update") % ctx.rev()
6085 elif dirty:
6089 elif dirty:
6086 hint = _("uncommitted changes, use --all to discard all changes")
6090 hint = _("uncommitted changes, use --all to discard all changes")
6087 else:
6091 else:
6088 hint = _("use --all to revert all files")
6092 hint = _("use --all to revert all files")
6089 raise error.Abort(msg, hint=hint)
6093 raise error.Abort(msg, hint=hint)
6090
6094
6091 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6095 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6092
6096
6093 @command('rollback', dryrunopts +
6097 @command('rollback', dryrunopts +
6094 [('f', 'force', False, _('ignore safety measures'))])
6098 [('f', 'force', False, _('ignore safety measures'))])
6095 def rollback(ui, repo, **opts):
6099 def rollback(ui, repo, **opts):
6096 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6100 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6097
6101
6098 Please use :hg:`commit --amend` instead of rollback to correct
6102 Please use :hg:`commit --amend` instead of rollback to correct
6099 mistakes in the last commit.
6103 mistakes in the last commit.
6100
6104
6101 This command should be used with care. There is only one level of
6105 This command should be used with care. There is only one level of
6102 rollback, and there is no way to undo a rollback. It will also
6106 rollback, and there is no way to undo a rollback. It will also
6103 restore the dirstate at the time of the last transaction, losing
6107 restore the dirstate at the time of the last transaction, losing
6104 any dirstate changes since that time. This command does not alter
6108 any dirstate changes since that time. This command does not alter
6105 the working directory.
6109 the working directory.
6106
6110
6107 Transactions are used to encapsulate the effects of all commands
6111 Transactions are used to encapsulate the effects of all commands
6108 that create new changesets or propagate existing changesets into a
6112 that create new changesets or propagate existing changesets into a
6109 repository.
6113 repository.
6110
6114
6111 .. container:: verbose
6115 .. container:: verbose
6112
6116
6113 For example, the following commands are transactional, and their
6117 For example, the following commands are transactional, and their
6114 effects can be rolled back:
6118 effects can be rolled back:
6115
6119
6116 - commit
6120 - commit
6117 - import
6121 - import
6118 - pull
6122 - pull
6119 - push (with this repository as the destination)
6123 - push (with this repository as the destination)
6120 - unbundle
6124 - unbundle
6121
6125
6122 To avoid permanent data loss, rollback will refuse to rollback a
6126 To avoid permanent data loss, rollback will refuse to rollback a
6123 commit transaction if it isn't checked out. Use --force to
6127 commit transaction if it isn't checked out. Use --force to
6124 override this protection.
6128 override this protection.
6125
6129
6126 This command is not intended for use on public repositories. Once
6130 This command is not intended for use on public repositories. Once
6127 changes are visible for pull by other users, rolling a transaction
6131 changes are visible for pull by other users, rolling a transaction
6128 back locally is ineffective (someone else may already have pulled
6132 back locally is ineffective (someone else may already have pulled
6129 the changes). Furthermore, a race is possible with readers of the
6133 the changes). Furthermore, a race is possible with readers of the
6130 repository; for example an in-progress pull from the repository
6134 repository; for example an in-progress pull from the repository
6131 may fail if a rollback is performed.
6135 may fail if a rollback is performed.
6132
6136
6133 Returns 0 on success, 1 if no rollback data is available.
6137 Returns 0 on success, 1 if no rollback data is available.
6134 """
6138 """
6135 return repo.rollback(dryrun=opts.get('dry_run'),
6139 return repo.rollback(dryrun=opts.get('dry_run'),
6136 force=opts.get('force'))
6140 force=opts.get('force'))
6137
6141
6138 @command('root', [])
6142 @command('root', [])
6139 def root(ui, repo):
6143 def root(ui, repo):
6140 """print the root (top) of the current working directory
6144 """print the root (top) of the current working directory
6141
6145
6142 Print the root directory of the current repository.
6146 Print the root directory of the current repository.
6143
6147
6144 Returns 0 on success.
6148 Returns 0 on success.
6145 """
6149 """
6146 ui.write(repo.root + "\n")
6150 ui.write(repo.root + "\n")
6147
6151
6148 @command('^serve',
6152 @command('^serve',
6149 [('A', 'accesslog', '', _('name of access log file to write to'),
6153 [('A', 'accesslog', '', _('name of access log file to write to'),
6150 _('FILE')),
6154 _('FILE')),
6151 ('d', 'daemon', None, _('run server in background')),
6155 ('d', 'daemon', None, _('run server in background')),
6152 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6156 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6153 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6157 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6154 # use string type, then we can check if something was passed
6158 # use string type, then we can check if something was passed
6155 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6159 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6156 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6160 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6157 _('ADDR')),
6161 _('ADDR')),
6158 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6162 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6159 _('PREFIX')),
6163 _('PREFIX')),
6160 ('n', 'name', '',
6164 ('n', 'name', '',
6161 _('name to show in web pages (default: working directory)'), _('NAME')),
6165 _('name to show in web pages (default: working directory)'), _('NAME')),
6162 ('', 'web-conf', '',
6166 ('', 'web-conf', '',
6163 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6167 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6164 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6168 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6165 _('FILE')),
6169 _('FILE')),
6166 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6170 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6167 ('', 'stdio', None, _('for remote clients')),
6171 ('', 'stdio', None, _('for remote clients')),
6168 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6172 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6169 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6173 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6170 ('', 'style', '', _('template style to use'), _('STYLE')),
6174 ('', 'style', '', _('template style to use'), _('STYLE')),
6171 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6175 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6172 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6176 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6173 _('[OPTION]...'),
6177 _('[OPTION]...'),
6174 optionalrepo=True)
6178 optionalrepo=True)
6175 def serve(ui, repo, **opts):
6179 def serve(ui, repo, **opts):
6176 """start stand-alone webserver
6180 """start stand-alone webserver
6177
6181
6178 Start a local HTTP repository browser and pull server. You can use
6182 Start a local HTTP repository browser and pull server. You can use
6179 this for ad-hoc sharing and browsing of repositories. It is
6183 this for ad-hoc sharing and browsing of repositories. It is
6180 recommended to use a real web server to serve a repository for
6184 recommended to use a real web server to serve a repository for
6181 longer periods of time.
6185 longer periods of time.
6182
6186
6183 Please note that the server does not implement access control.
6187 Please note that the server does not implement access control.
6184 This means that, by default, anybody can read from the server and
6188 This means that, by default, anybody can read from the server and
6185 nobody can write to it by default. Set the ``web.allow_push``
6189 nobody can write to it by default. Set the ``web.allow_push``
6186 option to ``*`` to allow everybody to push to the server. You
6190 option to ``*`` to allow everybody to push to the server. You
6187 should use a real web server if you need to authenticate users.
6191 should use a real web server if you need to authenticate users.
6188
6192
6189 By default, the server logs accesses to stdout and errors to
6193 By default, the server logs accesses to stdout and errors to
6190 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6194 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6191 files.
6195 files.
6192
6196
6193 To have the server choose a free port number to listen on, specify
6197 To have the server choose a free port number to listen on, specify
6194 a port number of 0; in this case, the server will print the port
6198 a port number of 0; in this case, the server will print the port
6195 number it uses.
6199 number it uses.
6196
6200
6197 Returns 0 on success.
6201 Returns 0 on success.
6198 """
6202 """
6199
6203
6200 if opts["stdio"] and opts["cmdserver"]:
6204 if opts["stdio"] and opts["cmdserver"]:
6201 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6205 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6202
6206
6203 if opts["stdio"]:
6207 if opts["stdio"]:
6204 if repo is None:
6208 if repo is None:
6205 raise error.RepoError(_("there is no Mercurial repository here"
6209 raise error.RepoError(_("there is no Mercurial repository here"
6206 " (.hg not found)"))
6210 " (.hg not found)"))
6207 s = sshserver.sshserver(ui, repo)
6211 s = sshserver.sshserver(ui, repo)
6208 s.serve_forever()
6212 s.serve_forever()
6209
6213
6210 if opts["cmdserver"]:
6214 if opts["cmdserver"]:
6211 service = commandserver.createservice(ui, repo, opts)
6215 service = commandserver.createservice(ui, repo, opts)
6212 else:
6216 else:
6213 service = hgweb.createservice(ui, repo, opts)
6217 service = hgweb.createservice(ui, repo, opts)
6214 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6218 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6215
6219
6216 @command('^status|st',
6220 @command('^status|st',
6217 [('A', 'all', None, _('show status of all files')),
6221 [('A', 'all', None, _('show status of all files')),
6218 ('m', 'modified', None, _('show only modified files')),
6222 ('m', 'modified', None, _('show only modified files')),
6219 ('a', 'added', None, _('show only added files')),
6223 ('a', 'added', None, _('show only added files')),
6220 ('r', 'removed', None, _('show only removed files')),
6224 ('r', 'removed', None, _('show only removed files')),
6221 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6225 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6222 ('c', 'clean', None, _('show only files without changes')),
6226 ('c', 'clean', None, _('show only files without changes')),
6223 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6227 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6224 ('i', 'ignored', None, _('show only ignored files')),
6228 ('i', 'ignored', None, _('show only ignored files')),
6225 ('n', 'no-status', None, _('hide status prefix')),
6229 ('n', 'no-status', None, _('hide status prefix')),
6226 ('C', 'copies', None, _('show source of copied files')),
6230 ('C', 'copies', None, _('show source of copied files')),
6227 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6231 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6228 ('', 'rev', [], _('show difference from revision'), _('REV')),
6232 ('', 'rev', [], _('show difference from revision'), _('REV')),
6229 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6233 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6230 ] + walkopts + subrepoopts + formatteropts,
6234 ] + walkopts + subrepoopts + formatteropts,
6231 _('[OPTION]... [FILE]...'),
6235 _('[OPTION]... [FILE]...'),
6232 inferrepo=True)
6236 inferrepo=True)
6233 def status(ui, repo, *pats, **opts):
6237 def status(ui, repo, *pats, **opts):
6234 """show changed files in the working directory
6238 """show changed files in the working directory
6235
6239
6236 Show status of files in the repository. If names are given, only
6240 Show status of files in the repository. If names are given, only
6237 files that match are shown. Files that are clean or ignored or
6241 files that match are shown. Files that are clean or ignored or
6238 the source of a copy/move operation, are not listed unless
6242 the source of a copy/move operation, are not listed unless
6239 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6243 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6240 Unless options described with "show only ..." are given, the
6244 Unless options described with "show only ..." are given, the
6241 options -mardu are used.
6245 options -mardu are used.
6242
6246
6243 Option -q/--quiet hides untracked (unknown and ignored) files
6247 Option -q/--quiet hides untracked (unknown and ignored) files
6244 unless explicitly requested with -u/--unknown or -i/--ignored.
6248 unless explicitly requested with -u/--unknown or -i/--ignored.
6245
6249
6246 .. note::
6250 .. note::
6247
6251
6248 :hg:`status` may appear to disagree with diff if permissions have
6252 :hg:`status` may appear to disagree with diff if permissions have
6249 changed or a merge has occurred. The standard diff format does
6253 changed or a merge has occurred. The standard diff format does
6250 not report permission changes and diff only reports changes
6254 not report permission changes and diff only reports changes
6251 relative to one merge parent.
6255 relative to one merge parent.
6252
6256
6253 If one revision is given, it is used as the base revision.
6257 If one revision is given, it is used as the base revision.
6254 If two revisions are given, the differences between them are
6258 If two revisions are given, the differences between them are
6255 shown. The --change option can also be used as a shortcut to list
6259 shown. The --change option can also be used as a shortcut to list
6256 the changed files of a revision from its first parent.
6260 the changed files of a revision from its first parent.
6257
6261
6258 The codes used to show the status of files are::
6262 The codes used to show the status of files are::
6259
6263
6260 M = modified
6264 M = modified
6261 A = added
6265 A = added
6262 R = removed
6266 R = removed
6263 C = clean
6267 C = clean
6264 ! = missing (deleted by non-hg command, but still tracked)
6268 ! = missing (deleted by non-hg command, but still tracked)
6265 ? = not tracked
6269 ? = not tracked
6266 I = ignored
6270 I = ignored
6267 = origin of the previous file (with --copies)
6271 = origin of the previous file (with --copies)
6268
6272
6269 .. container:: verbose
6273 .. container:: verbose
6270
6274
6271 Examples:
6275 Examples:
6272
6276
6273 - show changes in the working directory relative to a
6277 - show changes in the working directory relative to a
6274 changeset::
6278 changeset::
6275
6279
6276 hg status --rev 9353
6280 hg status --rev 9353
6277
6281
6278 - show changes in the working directory relative to the
6282 - show changes in the working directory relative to the
6279 current directory (see :hg:`help patterns` for more information)::
6283 current directory (see :hg:`help patterns` for more information)::
6280
6284
6281 hg status re:
6285 hg status re:
6282
6286
6283 - show all changes including copies in an existing changeset::
6287 - show all changes including copies in an existing changeset::
6284
6288
6285 hg status --copies --change 9353
6289 hg status --copies --change 9353
6286
6290
6287 - get a NUL separated list of added files, suitable for xargs::
6291 - get a NUL separated list of added files, suitable for xargs::
6288
6292
6289 hg status -an0
6293 hg status -an0
6290
6294
6291 Returns 0 on success.
6295 Returns 0 on success.
6292 """
6296 """
6293
6297
6294 revs = opts.get('rev')
6298 revs = opts.get('rev')
6295 change = opts.get('change')
6299 change = opts.get('change')
6296
6300
6297 if revs and change:
6301 if revs and change:
6298 msg = _('cannot specify --rev and --change at the same time')
6302 msg = _('cannot specify --rev and --change at the same time')
6299 raise error.Abort(msg)
6303 raise error.Abort(msg)
6300 elif change:
6304 elif change:
6301 node2 = scmutil.revsingle(repo, change, None).node()
6305 node2 = scmutil.revsingle(repo, change, None).node()
6302 node1 = repo[node2].p1().node()
6306 node1 = repo[node2].p1().node()
6303 else:
6307 else:
6304 node1, node2 = scmutil.revpair(repo, revs)
6308 node1, node2 = scmutil.revpair(repo, revs)
6305
6309
6306 if pats:
6310 if pats:
6307 cwd = repo.getcwd()
6311 cwd = repo.getcwd()
6308 else:
6312 else:
6309 cwd = ''
6313 cwd = ''
6310
6314
6311 if opts.get('print0'):
6315 if opts.get('print0'):
6312 end = '\0'
6316 end = '\0'
6313 else:
6317 else:
6314 end = '\n'
6318 end = '\n'
6315 copy = {}
6319 copy = {}
6316 states = 'modified added removed deleted unknown ignored clean'.split()
6320 states = 'modified added removed deleted unknown ignored clean'.split()
6317 show = [k for k in states if opts.get(k)]
6321 show = [k for k in states if opts.get(k)]
6318 if opts.get('all'):
6322 if opts.get('all'):
6319 show += ui.quiet and (states[:4] + ['clean']) or states
6323 show += ui.quiet and (states[:4] + ['clean']) or states
6320 if not show:
6324 if not show:
6321 if ui.quiet:
6325 if ui.quiet:
6322 show = states[:4]
6326 show = states[:4]
6323 else:
6327 else:
6324 show = states[:5]
6328 show = states[:5]
6325
6329
6326 m = scmutil.match(repo[node2], pats, opts)
6330 m = scmutil.match(repo[node2], pats, opts)
6327 stat = repo.status(node1, node2, m,
6331 stat = repo.status(node1, node2, m,
6328 'ignored' in show, 'clean' in show, 'unknown' in show,
6332 'ignored' in show, 'clean' in show, 'unknown' in show,
6329 opts.get('subrepos'))
6333 opts.get('subrepos'))
6330 changestates = zip(states, 'MAR!?IC', stat)
6334 changestates = zip(states, 'MAR!?IC', stat)
6331
6335
6332 if (opts.get('all') or opts.get('copies')
6336 if (opts.get('all') or opts.get('copies')
6333 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6337 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6334 copy = copies.pathcopies(repo[node1], repo[node2], m)
6338 copy = copies.pathcopies(repo[node1], repo[node2], m)
6335
6339
6336 fm = ui.formatter('status', opts)
6340 fm = ui.formatter('status', opts)
6337 fmt = '%s' + end
6341 fmt = '%s' + end
6338 showchar = not opts.get('no_status')
6342 showchar = not opts.get('no_status')
6339
6343
6340 for state, char, files in changestates:
6344 for state, char, files in changestates:
6341 if state in show:
6345 if state in show:
6342 label = 'status.' + state
6346 label = 'status.' + state
6343 for f in files:
6347 for f in files:
6344 fm.startitem()
6348 fm.startitem()
6345 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6349 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6346 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6350 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6347 if f in copy:
6351 if f in copy:
6348 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6352 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6349 label='status.copied')
6353 label='status.copied')
6350 fm.end()
6354 fm.end()
6351
6355
6352 @command('^summary|sum',
6356 @command('^summary|sum',
6353 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6357 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6354 def summary(ui, repo, **opts):
6358 def summary(ui, repo, **opts):
6355 """summarize working directory state
6359 """summarize working directory state
6356
6360
6357 This generates a brief summary of the working directory state,
6361 This generates a brief summary of the working directory state,
6358 including parents, branch, commit status, phase and available updates.
6362 including parents, branch, commit status, phase and available updates.
6359
6363
6360 With the --remote option, this will check the default paths for
6364 With the --remote option, this will check the default paths for
6361 incoming and outgoing changes. This can be time-consuming.
6365 incoming and outgoing changes. This can be time-consuming.
6362
6366
6363 Returns 0 on success.
6367 Returns 0 on success.
6364 """
6368 """
6365
6369
6366 ctx = repo[None]
6370 ctx = repo[None]
6367 parents = ctx.parents()
6371 parents = ctx.parents()
6368 pnode = parents[0].node()
6372 pnode = parents[0].node()
6369 marks = []
6373 marks = []
6370
6374
6371 for p in parents:
6375 for p in parents:
6372 # label with log.changeset (instead of log.parent) since this
6376 # label with log.changeset (instead of log.parent) since this
6373 # shows a working directory parent *changeset*:
6377 # shows a working directory parent *changeset*:
6374 # i18n: column positioning for "hg summary"
6378 # i18n: column positioning for "hg summary"
6375 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6379 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6376 label='log.changeset changeset.%s' % p.phasestr())
6380 label='log.changeset changeset.%s' % p.phasestr())
6377 ui.write(' '.join(p.tags()), label='log.tag')
6381 ui.write(' '.join(p.tags()), label='log.tag')
6378 if p.bookmarks():
6382 if p.bookmarks():
6379 marks.extend(p.bookmarks())
6383 marks.extend(p.bookmarks())
6380 if p.rev() == -1:
6384 if p.rev() == -1:
6381 if not len(repo):
6385 if not len(repo):
6382 ui.write(_(' (empty repository)'))
6386 ui.write(_(' (empty repository)'))
6383 else:
6387 else:
6384 ui.write(_(' (no revision checked out)'))
6388 ui.write(_(' (no revision checked out)'))
6385 ui.write('\n')
6389 ui.write('\n')
6386 if p.description():
6390 if p.description():
6387 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6391 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6388 label='log.summary')
6392 label='log.summary')
6389
6393
6390 branch = ctx.branch()
6394 branch = ctx.branch()
6391 bheads = repo.branchheads(branch)
6395 bheads = repo.branchheads(branch)
6392 # i18n: column positioning for "hg summary"
6396 # i18n: column positioning for "hg summary"
6393 m = _('branch: %s\n') % branch
6397 m = _('branch: %s\n') % branch
6394 if branch != 'default':
6398 if branch != 'default':
6395 ui.write(m, label='log.branch')
6399 ui.write(m, label='log.branch')
6396 else:
6400 else:
6397 ui.status(m, label='log.branch')
6401 ui.status(m, label='log.branch')
6398
6402
6399 if marks:
6403 if marks:
6400 active = repo._activebookmark
6404 active = repo._activebookmark
6401 # i18n: column positioning for "hg summary"
6405 # i18n: column positioning for "hg summary"
6402 ui.write(_('bookmarks:'), label='log.bookmark')
6406 ui.write(_('bookmarks:'), label='log.bookmark')
6403 if active is not None:
6407 if active is not None:
6404 if active in marks:
6408 if active in marks:
6405 ui.write(' *' + active, label=activebookmarklabel)
6409 ui.write(' *' + active, label=activebookmarklabel)
6406 marks.remove(active)
6410 marks.remove(active)
6407 else:
6411 else:
6408 ui.write(' [%s]' % active, label=activebookmarklabel)
6412 ui.write(' [%s]' % active, label=activebookmarklabel)
6409 for m in marks:
6413 for m in marks:
6410 ui.write(' ' + m, label='log.bookmark')
6414 ui.write(' ' + m, label='log.bookmark')
6411 ui.write('\n', label='log.bookmark')
6415 ui.write('\n', label='log.bookmark')
6412
6416
6413 status = repo.status(unknown=True)
6417 status = repo.status(unknown=True)
6414
6418
6415 c = repo.dirstate.copies()
6419 c = repo.dirstate.copies()
6416 copied, renamed = [], []
6420 copied, renamed = [], []
6417 for d, s in c.iteritems():
6421 for d, s in c.iteritems():
6418 if s in status.removed:
6422 if s in status.removed:
6419 status.removed.remove(s)
6423 status.removed.remove(s)
6420 renamed.append(d)
6424 renamed.append(d)
6421 else:
6425 else:
6422 copied.append(d)
6426 copied.append(d)
6423 if d in status.added:
6427 if d in status.added:
6424 status.added.remove(d)
6428 status.added.remove(d)
6425
6429
6426 try:
6430 try:
6427 ms = mergemod.mergestate.read(repo)
6431 ms = mergemod.mergestate.read(repo)
6428 except error.UnsupportedMergeRecords as e:
6432 except error.UnsupportedMergeRecords as e:
6429 s = ' '.join(e.recordtypes)
6433 s = ' '.join(e.recordtypes)
6430 ui.warn(
6434 ui.warn(
6431 _('warning: merge state has unsupported record types: %s\n') % s)
6435 _('warning: merge state has unsupported record types: %s\n') % s)
6432 unresolved = 0
6436 unresolved = 0
6433 else:
6437 else:
6434 unresolved = [f for f in ms if ms[f] == 'u']
6438 unresolved = [f for f in ms if ms[f] == 'u']
6435
6439
6436 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6440 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6437
6441
6438 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6442 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6439 (ui.label(_('%d added'), 'status.added'), status.added),
6443 (ui.label(_('%d added'), 'status.added'), status.added),
6440 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6444 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6441 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6445 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6442 (ui.label(_('%d copied'), 'status.copied'), copied),
6446 (ui.label(_('%d copied'), 'status.copied'), copied),
6443 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6447 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6444 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6448 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6445 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6449 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6446 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6450 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6447 t = []
6451 t = []
6448 for l, s in labels:
6452 for l, s in labels:
6449 if s:
6453 if s:
6450 t.append(l % len(s))
6454 t.append(l % len(s))
6451
6455
6452 t = ', '.join(t)
6456 t = ', '.join(t)
6453 cleanworkdir = False
6457 cleanworkdir = False
6454
6458
6455 if repo.vfs.exists('graftstate'):
6459 if repo.vfs.exists('graftstate'):
6456 t += _(' (graft in progress)')
6460 t += _(' (graft in progress)')
6457 if repo.vfs.exists('updatestate'):
6461 if repo.vfs.exists('updatestate'):
6458 t += _(' (interrupted update)')
6462 t += _(' (interrupted update)')
6459 elif len(parents) > 1:
6463 elif len(parents) > 1:
6460 t += _(' (merge)')
6464 t += _(' (merge)')
6461 elif branch != parents[0].branch():
6465 elif branch != parents[0].branch():
6462 t += _(' (new branch)')
6466 t += _(' (new branch)')
6463 elif (parents[0].closesbranch() and
6467 elif (parents[0].closesbranch() and
6464 pnode in repo.branchheads(branch, closed=True)):
6468 pnode in repo.branchheads(branch, closed=True)):
6465 t += _(' (head closed)')
6469 t += _(' (head closed)')
6466 elif not (status.modified or status.added or status.removed or renamed or
6470 elif not (status.modified or status.added or status.removed or renamed or
6467 copied or subs):
6471 copied or subs):
6468 t += _(' (clean)')
6472 t += _(' (clean)')
6469 cleanworkdir = True
6473 cleanworkdir = True
6470 elif pnode not in bheads:
6474 elif pnode not in bheads:
6471 t += _(' (new branch head)')
6475 t += _(' (new branch head)')
6472
6476
6473 if parents:
6477 if parents:
6474 pendingphase = max(p.phase() for p in parents)
6478 pendingphase = max(p.phase() for p in parents)
6475 else:
6479 else:
6476 pendingphase = phases.public
6480 pendingphase = phases.public
6477
6481
6478 if pendingphase > phases.newcommitphase(ui):
6482 if pendingphase > phases.newcommitphase(ui):
6479 t += ' (%s)' % phases.phasenames[pendingphase]
6483 t += ' (%s)' % phases.phasenames[pendingphase]
6480
6484
6481 if cleanworkdir:
6485 if cleanworkdir:
6482 # i18n: column positioning for "hg summary"
6486 # i18n: column positioning for "hg summary"
6483 ui.status(_('commit: %s\n') % t.strip())
6487 ui.status(_('commit: %s\n') % t.strip())
6484 else:
6488 else:
6485 # i18n: column positioning for "hg summary"
6489 # i18n: column positioning for "hg summary"
6486 ui.write(_('commit: %s\n') % t.strip())
6490 ui.write(_('commit: %s\n') % t.strip())
6487
6491
6488 # all ancestors of branch heads - all ancestors of parent = new csets
6492 # all ancestors of branch heads - all ancestors of parent = new csets
6489 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6493 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6490 bheads))
6494 bheads))
6491
6495
6492 if new == 0:
6496 if new == 0:
6493 # i18n: column positioning for "hg summary"
6497 # i18n: column positioning for "hg summary"
6494 ui.status(_('update: (current)\n'))
6498 ui.status(_('update: (current)\n'))
6495 elif pnode not in bheads:
6499 elif pnode not in bheads:
6496 # i18n: column positioning for "hg summary"
6500 # i18n: column positioning for "hg summary"
6497 ui.write(_('update: %d new changesets (update)\n') % new)
6501 ui.write(_('update: %d new changesets (update)\n') % new)
6498 else:
6502 else:
6499 # i18n: column positioning for "hg summary"
6503 # i18n: column positioning for "hg summary"
6500 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6504 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6501 (new, len(bheads)))
6505 (new, len(bheads)))
6502
6506
6503 t = []
6507 t = []
6504 draft = len(repo.revs('draft()'))
6508 draft = len(repo.revs('draft()'))
6505 if draft:
6509 if draft:
6506 t.append(_('%d draft') % draft)
6510 t.append(_('%d draft') % draft)
6507 secret = len(repo.revs('secret()'))
6511 secret = len(repo.revs('secret()'))
6508 if secret:
6512 if secret:
6509 t.append(_('%d secret') % secret)
6513 t.append(_('%d secret') % secret)
6510
6514
6511 if draft or secret:
6515 if draft or secret:
6512 ui.status(_('phases: %s\n') % ', '.join(t))
6516 ui.status(_('phases: %s\n') % ', '.join(t))
6513
6517
6514 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6518 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6515 for trouble in ("unstable", "divergent", "bumped"):
6519 for trouble in ("unstable", "divergent", "bumped"):
6516 numtrouble = len(repo.revs(trouble + "()"))
6520 numtrouble = len(repo.revs(trouble + "()"))
6517 # We write all the possibilities to ease translation
6521 # We write all the possibilities to ease translation
6518 troublemsg = {
6522 troublemsg = {
6519 "unstable": _("unstable: %d changeset"),
6523 "unstable": _("unstable: %d changeset"),
6520 "divergent": _("divergent: %d changeset"),
6524 "divergent": _("divergent: %d changeset"),
6521 "bumped": _("bumped: %d changeset"),
6525 "bumped": _("bumped: %d changeset"),
6522 }
6526 }
6523 if numtrouble > 0:
6527 if numtrouble > 0:
6524 ui.status(troublemsg[trouble] % numtrouble + "\n")
6528 ui.status(troublemsg[trouble] % numtrouble + "\n")
6525
6529
6526 cmdutil.summaryhooks(ui, repo)
6530 cmdutil.summaryhooks(ui, repo)
6527
6531
6528 if opts.get('remote'):
6532 if opts.get('remote'):
6529 needsincoming, needsoutgoing = True, True
6533 needsincoming, needsoutgoing = True, True
6530 else:
6534 else:
6531 needsincoming, needsoutgoing = False, False
6535 needsincoming, needsoutgoing = False, False
6532 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6536 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6533 if i:
6537 if i:
6534 needsincoming = True
6538 needsincoming = True
6535 if o:
6539 if o:
6536 needsoutgoing = True
6540 needsoutgoing = True
6537 if not needsincoming and not needsoutgoing:
6541 if not needsincoming and not needsoutgoing:
6538 return
6542 return
6539
6543
6540 def getincoming():
6544 def getincoming():
6541 source, branches = hg.parseurl(ui.expandpath('default'))
6545 source, branches = hg.parseurl(ui.expandpath('default'))
6542 sbranch = branches[0]
6546 sbranch = branches[0]
6543 try:
6547 try:
6544 other = hg.peer(repo, {}, source)
6548 other = hg.peer(repo, {}, source)
6545 except error.RepoError:
6549 except error.RepoError:
6546 if opts.get('remote'):
6550 if opts.get('remote'):
6547 raise
6551 raise
6548 return source, sbranch, None, None, None
6552 return source, sbranch, None, None, None
6549 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6553 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6550 if revs:
6554 if revs:
6551 revs = [other.lookup(rev) for rev in revs]
6555 revs = [other.lookup(rev) for rev in revs]
6552 ui.debug('comparing with %s\n' % util.hidepassword(source))
6556 ui.debug('comparing with %s\n' % util.hidepassword(source))
6553 repo.ui.pushbuffer()
6557 repo.ui.pushbuffer()
6554 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6558 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6555 repo.ui.popbuffer()
6559 repo.ui.popbuffer()
6556 return source, sbranch, other, commoninc, commoninc[1]
6560 return source, sbranch, other, commoninc, commoninc[1]
6557
6561
6558 if needsincoming:
6562 if needsincoming:
6559 source, sbranch, sother, commoninc, incoming = getincoming()
6563 source, sbranch, sother, commoninc, incoming = getincoming()
6560 else:
6564 else:
6561 source = sbranch = sother = commoninc = incoming = None
6565 source = sbranch = sother = commoninc = incoming = None
6562
6566
6563 def getoutgoing():
6567 def getoutgoing():
6564 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6568 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6565 dbranch = branches[0]
6569 dbranch = branches[0]
6566 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6570 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6567 if source != dest:
6571 if source != dest:
6568 try:
6572 try:
6569 dother = hg.peer(repo, {}, dest)
6573 dother = hg.peer(repo, {}, dest)
6570 except error.RepoError:
6574 except error.RepoError:
6571 if opts.get('remote'):
6575 if opts.get('remote'):
6572 raise
6576 raise
6573 return dest, dbranch, None, None
6577 return dest, dbranch, None, None
6574 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6578 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6575 elif sother is None:
6579 elif sother is None:
6576 # there is no explicit destination peer, but source one is invalid
6580 # there is no explicit destination peer, but source one is invalid
6577 return dest, dbranch, None, None
6581 return dest, dbranch, None, None
6578 else:
6582 else:
6579 dother = sother
6583 dother = sother
6580 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6584 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6581 common = None
6585 common = None
6582 else:
6586 else:
6583 common = commoninc
6587 common = commoninc
6584 if revs:
6588 if revs:
6585 revs = [repo.lookup(rev) for rev in revs]
6589 revs = [repo.lookup(rev) for rev in revs]
6586 repo.ui.pushbuffer()
6590 repo.ui.pushbuffer()
6587 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6591 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6588 commoninc=common)
6592 commoninc=common)
6589 repo.ui.popbuffer()
6593 repo.ui.popbuffer()
6590 return dest, dbranch, dother, outgoing
6594 return dest, dbranch, dother, outgoing
6591
6595
6592 if needsoutgoing:
6596 if needsoutgoing:
6593 dest, dbranch, dother, outgoing = getoutgoing()
6597 dest, dbranch, dother, outgoing = getoutgoing()
6594 else:
6598 else:
6595 dest = dbranch = dother = outgoing = None
6599 dest = dbranch = dother = outgoing = None
6596
6600
6597 if opts.get('remote'):
6601 if opts.get('remote'):
6598 t = []
6602 t = []
6599 if incoming:
6603 if incoming:
6600 t.append(_('1 or more incoming'))
6604 t.append(_('1 or more incoming'))
6601 o = outgoing.missing
6605 o = outgoing.missing
6602 if o:
6606 if o:
6603 t.append(_('%d outgoing') % len(o))
6607 t.append(_('%d outgoing') % len(o))
6604 other = dother or sother
6608 other = dother or sother
6605 if 'bookmarks' in other.listkeys('namespaces'):
6609 if 'bookmarks' in other.listkeys('namespaces'):
6606 counts = bookmarks.summary(repo, other)
6610 counts = bookmarks.summary(repo, other)
6607 if counts[0] > 0:
6611 if counts[0] > 0:
6608 t.append(_('%d incoming bookmarks') % counts[0])
6612 t.append(_('%d incoming bookmarks') % counts[0])
6609 if counts[1] > 0:
6613 if counts[1] > 0:
6610 t.append(_('%d outgoing bookmarks') % counts[1])
6614 t.append(_('%d outgoing bookmarks') % counts[1])
6611
6615
6612 if t:
6616 if t:
6613 # i18n: column positioning for "hg summary"
6617 # i18n: column positioning for "hg summary"
6614 ui.write(_('remote: %s\n') % (', '.join(t)))
6618 ui.write(_('remote: %s\n') % (', '.join(t)))
6615 else:
6619 else:
6616 # i18n: column positioning for "hg summary"
6620 # i18n: column positioning for "hg summary"
6617 ui.status(_('remote: (synced)\n'))
6621 ui.status(_('remote: (synced)\n'))
6618
6622
6619 cmdutil.summaryremotehooks(ui, repo, opts,
6623 cmdutil.summaryremotehooks(ui, repo, opts,
6620 ((source, sbranch, sother, commoninc),
6624 ((source, sbranch, sother, commoninc),
6621 (dest, dbranch, dother, outgoing)))
6625 (dest, dbranch, dother, outgoing)))
6622
6626
6623 @command('tag',
6627 @command('tag',
6624 [('f', 'force', None, _('force tag')),
6628 [('f', 'force', None, _('force tag')),
6625 ('l', 'local', None, _('make the tag local')),
6629 ('l', 'local', None, _('make the tag local')),
6626 ('r', 'rev', '', _('revision to tag'), _('REV')),
6630 ('r', 'rev', '', _('revision to tag'), _('REV')),
6627 ('', 'remove', None, _('remove a tag')),
6631 ('', 'remove', None, _('remove a tag')),
6628 # -l/--local is already there, commitopts cannot be used
6632 # -l/--local is already there, commitopts cannot be used
6629 ('e', 'edit', None, _('invoke editor on commit messages')),
6633 ('e', 'edit', None, _('invoke editor on commit messages')),
6630 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6634 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6631 ] + commitopts2,
6635 ] + commitopts2,
6632 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6636 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6633 def tag(ui, repo, name1, *names, **opts):
6637 def tag(ui, repo, name1, *names, **opts):
6634 """add one or more tags for the current or given revision
6638 """add one or more tags for the current or given revision
6635
6639
6636 Name a particular revision using <name>.
6640 Name a particular revision using <name>.
6637
6641
6638 Tags are used to name particular revisions of the repository and are
6642 Tags are used to name particular revisions of the repository and are
6639 very useful to compare different revisions, to go back to significant
6643 very useful to compare different revisions, to go back to significant
6640 earlier versions or to mark branch points as releases, etc. Changing
6644 earlier versions or to mark branch points as releases, etc. Changing
6641 an existing tag is normally disallowed; use -f/--force to override.
6645 an existing tag is normally disallowed; use -f/--force to override.
6642
6646
6643 If no revision is given, the parent of the working directory is
6647 If no revision is given, the parent of the working directory is
6644 used.
6648 used.
6645
6649
6646 To facilitate version control, distribution, and merging of tags,
6650 To facilitate version control, distribution, and merging of tags,
6647 they are stored as a file named ".hgtags" which is managed similarly
6651 they are stored as a file named ".hgtags" which is managed similarly
6648 to other project files and can be hand-edited if necessary. This
6652 to other project files and can be hand-edited if necessary. This
6649 also means that tagging creates a new commit. The file
6653 also means that tagging creates a new commit. The file
6650 ".hg/localtags" is used for local tags (not shared among
6654 ".hg/localtags" is used for local tags (not shared among
6651 repositories).
6655 repositories).
6652
6656
6653 Tag commits are usually made at the head of a branch. If the parent
6657 Tag commits are usually made at the head of a branch. If the parent
6654 of the working directory is not a branch head, :hg:`tag` aborts; use
6658 of the working directory is not a branch head, :hg:`tag` aborts; use
6655 -f/--force to force the tag commit to be based on a non-head
6659 -f/--force to force the tag commit to be based on a non-head
6656 changeset.
6660 changeset.
6657
6661
6658 See :hg:`help dates` for a list of formats valid for -d/--date.
6662 See :hg:`help dates` for a list of formats valid for -d/--date.
6659
6663
6660 Since tag names have priority over branch names during revision
6664 Since tag names have priority over branch names during revision
6661 lookup, using an existing branch name as a tag name is discouraged.
6665 lookup, using an existing branch name as a tag name is discouraged.
6662
6666
6663 Returns 0 on success.
6667 Returns 0 on success.
6664 """
6668 """
6665 wlock = lock = None
6669 wlock = lock = None
6666 try:
6670 try:
6667 wlock = repo.wlock()
6671 wlock = repo.wlock()
6668 lock = repo.lock()
6672 lock = repo.lock()
6669 rev_ = "."
6673 rev_ = "."
6670 names = [t.strip() for t in (name1,) + names]
6674 names = [t.strip() for t in (name1,) + names]
6671 if len(names) != len(set(names)):
6675 if len(names) != len(set(names)):
6672 raise error.Abort(_('tag names must be unique'))
6676 raise error.Abort(_('tag names must be unique'))
6673 for n in names:
6677 for n in names:
6674 scmutil.checknewlabel(repo, n, 'tag')
6678 scmutil.checknewlabel(repo, n, 'tag')
6675 if not n:
6679 if not n:
6676 raise error.Abort(_('tag names cannot consist entirely of '
6680 raise error.Abort(_('tag names cannot consist entirely of '
6677 'whitespace'))
6681 'whitespace'))
6678 if opts.get('rev') and opts.get('remove'):
6682 if opts.get('rev') and opts.get('remove'):
6679 raise error.Abort(_("--rev and --remove are incompatible"))
6683 raise error.Abort(_("--rev and --remove are incompatible"))
6680 if opts.get('rev'):
6684 if opts.get('rev'):
6681 rev_ = opts['rev']
6685 rev_ = opts['rev']
6682 message = opts.get('message')
6686 message = opts.get('message')
6683 if opts.get('remove'):
6687 if opts.get('remove'):
6684 if opts.get('local'):
6688 if opts.get('local'):
6685 expectedtype = 'local'
6689 expectedtype = 'local'
6686 else:
6690 else:
6687 expectedtype = 'global'
6691 expectedtype = 'global'
6688
6692
6689 for n in names:
6693 for n in names:
6690 if not repo.tagtype(n):
6694 if not repo.tagtype(n):
6691 raise error.Abort(_("tag '%s' does not exist") % n)
6695 raise error.Abort(_("tag '%s' does not exist") % n)
6692 if repo.tagtype(n) != expectedtype:
6696 if repo.tagtype(n) != expectedtype:
6693 if expectedtype == 'global':
6697 if expectedtype == 'global':
6694 raise error.Abort(_("tag '%s' is not a global tag") % n)
6698 raise error.Abort(_("tag '%s' is not a global tag") % n)
6695 else:
6699 else:
6696 raise error.Abort(_("tag '%s' is not a local tag") % n)
6700 raise error.Abort(_("tag '%s' is not a local tag") % n)
6697 rev_ = 'null'
6701 rev_ = 'null'
6698 if not message:
6702 if not message:
6699 # we don't translate commit messages
6703 # we don't translate commit messages
6700 message = 'Removed tag %s' % ', '.join(names)
6704 message = 'Removed tag %s' % ', '.join(names)
6701 elif not opts.get('force'):
6705 elif not opts.get('force'):
6702 for n in names:
6706 for n in names:
6703 if n in repo.tags():
6707 if n in repo.tags():
6704 raise error.Abort(_("tag '%s' already exists "
6708 raise error.Abort(_("tag '%s' already exists "
6705 "(use -f to force)") % n)
6709 "(use -f to force)") % n)
6706 if not opts.get('local'):
6710 if not opts.get('local'):
6707 p1, p2 = repo.dirstate.parents()
6711 p1, p2 = repo.dirstate.parents()
6708 if p2 != nullid:
6712 if p2 != nullid:
6709 raise error.Abort(_('uncommitted merge'))
6713 raise error.Abort(_('uncommitted merge'))
6710 bheads = repo.branchheads()
6714 bheads = repo.branchheads()
6711 if not opts.get('force') and bheads and p1 not in bheads:
6715 if not opts.get('force') and bheads and p1 not in bheads:
6712 raise error.Abort(_('not at a branch head (use -f to force)'))
6716 raise error.Abort(_('not at a branch head (use -f to force)'))
6713 r = scmutil.revsingle(repo, rev_).node()
6717 r = scmutil.revsingle(repo, rev_).node()
6714
6718
6715 if not message:
6719 if not message:
6716 # we don't translate commit messages
6720 # we don't translate commit messages
6717 message = ('Added tag %s for changeset %s' %
6721 message = ('Added tag %s for changeset %s' %
6718 (', '.join(names), short(r)))
6722 (', '.join(names), short(r)))
6719
6723
6720 date = opts.get('date')
6724 date = opts.get('date')
6721 if date:
6725 if date:
6722 date = util.parsedate(date)
6726 date = util.parsedate(date)
6723
6727
6724 if opts.get('remove'):
6728 if opts.get('remove'):
6725 editform = 'tag.remove'
6729 editform = 'tag.remove'
6726 else:
6730 else:
6727 editform = 'tag.add'
6731 editform = 'tag.add'
6728 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6732 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6729
6733
6730 # don't allow tagging the null rev
6734 # don't allow tagging the null rev
6731 if (not opts.get('remove') and
6735 if (not opts.get('remove') and
6732 scmutil.revsingle(repo, rev_).rev() == nullrev):
6736 scmutil.revsingle(repo, rev_).rev() == nullrev):
6733 raise error.Abort(_("cannot tag null revision"))
6737 raise error.Abort(_("cannot tag null revision"))
6734
6738
6735 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6739 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6736 editor=editor)
6740 editor=editor)
6737 finally:
6741 finally:
6738 release(lock, wlock)
6742 release(lock, wlock)
6739
6743
6740 @command('tags', formatteropts, '')
6744 @command('tags', formatteropts, '')
6741 def tags(ui, repo, **opts):
6745 def tags(ui, repo, **opts):
6742 """list repository tags
6746 """list repository tags
6743
6747
6744 This lists both regular and local tags. When the -v/--verbose
6748 This lists both regular and local tags. When the -v/--verbose
6745 switch is used, a third column "local" is printed for local tags.
6749 switch is used, a third column "local" is printed for local tags.
6746 When the -q/--quiet switch is used, only the tag name is printed.
6750 When the -q/--quiet switch is used, only the tag name is printed.
6747
6751
6748 Returns 0 on success.
6752 Returns 0 on success.
6749 """
6753 """
6750
6754
6751 fm = ui.formatter('tags', opts)
6755 fm = ui.formatter('tags', opts)
6752 hexfunc = fm.hexfunc
6756 hexfunc = fm.hexfunc
6753 tagtype = ""
6757 tagtype = ""
6754
6758
6755 for t, n in reversed(repo.tagslist()):
6759 for t, n in reversed(repo.tagslist()):
6756 hn = hexfunc(n)
6760 hn = hexfunc(n)
6757 label = 'tags.normal'
6761 label = 'tags.normal'
6758 tagtype = ''
6762 tagtype = ''
6759 if repo.tagtype(t) == 'local':
6763 if repo.tagtype(t) == 'local':
6760 label = 'tags.local'
6764 label = 'tags.local'
6761 tagtype = 'local'
6765 tagtype = 'local'
6762
6766
6763 fm.startitem()
6767 fm.startitem()
6764 fm.write('tag', '%s', t, label=label)
6768 fm.write('tag', '%s', t, label=label)
6765 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6769 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6766 fm.condwrite(not ui.quiet, 'rev node', fmt,
6770 fm.condwrite(not ui.quiet, 'rev node', fmt,
6767 repo.changelog.rev(n), hn, label=label)
6771 repo.changelog.rev(n), hn, label=label)
6768 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6772 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6769 tagtype, label=label)
6773 tagtype, label=label)
6770 fm.plain('\n')
6774 fm.plain('\n')
6771 fm.end()
6775 fm.end()
6772
6776
6773 @command('tip',
6777 @command('tip',
6774 [('p', 'patch', None, _('show patch')),
6778 [('p', 'patch', None, _('show patch')),
6775 ('g', 'git', None, _('use git extended diff format')),
6779 ('g', 'git', None, _('use git extended diff format')),
6776 ] + templateopts,
6780 ] + templateopts,
6777 _('[-p] [-g]'))
6781 _('[-p] [-g]'))
6778 def tip(ui, repo, **opts):
6782 def tip(ui, repo, **opts):
6779 """show the tip revision (DEPRECATED)
6783 """show the tip revision (DEPRECATED)
6780
6784
6781 The tip revision (usually just called the tip) is the changeset
6785 The tip revision (usually just called the tip) is the changeset
6782 most recently added to the repository (and therefore the most
6786 most recently added to the repository (and therefore the most
6783 recently changed head).
6787 recently changed head).
6784
6788
6785 If you have just made a commit, that commit will be the tip. If
6789 If you have just made a commit, that commit will be the tip. If
6786 you have just pulled changes from another repository, the tip of
6790 you have just pulled changes from another repository, the tip of
6787 that repository becomes the current tip. The "tip" tag is special
6791 that repository becomes the current tip. The "tip" tag is special
6788 and cannot be renamed or assigned to a different changeset.
6792 and cannot be renamed or assigned to a different changeset.
6789
6793
6790 This command is deprecated, please use :hg:`heads` instead.
6794 This command is deprecated, please use :hg:`heads` instead.
6791
6795
6792 Returns 0 on success.
6796 Returns 0 on success.
6793 """
6797 """
6794 displayer = cmdutil.show_changeset(ui, repo, opts)
6798 displayer = cmdutil.show_changeset(ui, repo, opts)
6795 displayer.show(repo['tip'])
6799 displayer.show(repo['tip'])
6796 displayer.close()
6800 displayer.close()
6797
6801
6798 @command('unbundle',
6802 @command('unbundle',
6799 [('u', 'update', None,
6803 [('u', 'update', None,
6800 _('update to new branch head if changesets were unbundled'))],
6804 _('update to new branch head if changesets were unbundled'))],
6801 _('[-u] FILE...'))
6805 _('[-u] FILE...'))
6802 def unbundle(ui, repo, fname1, *fnames, **opts):
6806 def unbundle(ui, repo, fname1, *fnames, **opts):
6803 """apply one or more changegroup files
6807 """apply one or more changegroup files
6804
6808
6805 Apply one or more compressed changegroup files generated by the
6809 Apply one or more compressed changegroup files generated by the
6806 bundle command.
6810 bundle command.
6807
6811
6808 Returns 0 on success, 1 if an update has unresolved files.
6812 Returns 0 on success, 1 if an update has unresolved files.
6809 """
6813 """
6810 fnames = (fname1,) + fnames
6814 fnames = (fname1,) + fnames
6811
6815
6812 lock = repo.lock()
6816 lock = repo.lock()
6813 try:
6817 try:
6814 for fname in fnames:
6818 for fname in fnames:
6815 f = hg.openpath(ui, fname)
6819 f = hg.openpath(ui, fname)
6816 gen = exchange.readbundle(ui, f, fname)
6820 gen = exchange.readbundle(ui, f, fname)
6817 if isinstance(gen, bundle2.unbundle20):
6821 if isinstance(gen, bundle2.unbundle20):
6818 tr = repo.transaction('unbundle')
6822 tr = repo.transaction('unbundle')
6819 try:
6823 try:
6820 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6824 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6821 url='bundle:' + fname)
6825 url='bundle:' + fname)
6822 tr.close()
6826 tr.close()
6823 except error.BundleUnknownFeatureError as exc:
6827 except error.BundleUnknownFeatureError as exc:
6824 raise error.Abort(_('%s: unknown bundle feature, %s')
6828 raise error.Abort(_('%s: unknown bundle feature, %s')
6825 % (fname, exc),
6829 % (fname, exc),
6826 hint=_("see https://mercurial-scm.org/"
6830 hint=_("see https://mercurial-scm.org/"
6827 "wiki/BundleFeature for more "
6831 "wiki/BundleFeature for more "
6828 "information"))
6832 "information"))
6829 finally:
6833 finally:
6830 if tr:
6834 if tr:
6831 tr.release()
6835 tr.release()
6832 changes = [r.get('return', 0)
6836 changes = [r.get('return', 0)
6833 for r in op.records['changegroup']]
6837 for r in op.records['changegroup']]
6834 modheads = changegroup.combineresults(changes)
6838 modheads = changegroup.combineresults(changes)
6835 elif isinstance(gen, streamclone.streamcloneapplier):
6839 elif isinstance(gen, streamclone.streamcloneapplier):
6836 raise error.Abort(
6840 raise error.Abort(
6837 _('packed bundles cannot be applied with '
6841 _('packed bundles cannot be applied with '
6838 '"hg unbundle"'),
6842 '"hg unbundle"'),
6839 hint=_('use "hg debugapplystreamclonebundle"'))
6843 hint=_('use "hg debugapplystreamclonebundle"'))
6840 else:
6844 else:
6841 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6845 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6842 finally:
6846 finally:
6843 lock.release()
6847 lock.release()
6844
6848
6845 return postincoming(ui, repo, modheads, opts.get('update'), None)
6849 return postincoming(ui, repo, modheads, opts.get('update'), None)
6846
6850
6847 @command('^update|up|checkout|co',
6851 @command('^update|up|checkout|co',
6848 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6852 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6849 ('c', 'check', None,
6853 ('c', 'check', None,
6850 _('update across branches if no uncommitted changes')),
6854 _('update across branches if no uncommitted changes')),
6851 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6855 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6852 ('r', 'rev', '', _('revision'), _('REV'))
6856 ('r', 'rev', '', _('revision'), _('REV'))
6853 ] + mergetoolopts,
6857 ] + mergetoolopts,
6854 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6858 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6855 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6859 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6856 tool=None):
6860 tool=None):
6857 """update working directory (or switch revisions)
6861 """update working directory (or switch revisions)
6858
6862
6859 Update the repository's working directory to the specified
6863 Update the repository's working directory to the specified
6860 changeset. If no changeset is specified, update to the tip of the
6864 changeset. If no changeset is specified, update to the tip of the
6861 current named branch and move the active bookmark (see :hg:`help
6865 current named branch and move the active bookmark (see :hg:`help
6862 bookmarks`).
6866 bookmarks`).
6863
6867
6864 Update sets the working directory's parent revision to the specified
6868 Update sets the working directory's parent revision to the specified
6865 changeset (see :hg:`help parents`).
6869 changeset (see :hg:`help parents`).
6866
6870
6867 If the changeset is not a descendant or ancestor of the working
6871 If the changeset is not a descendant or ancestor of the working
6868 directory's parent, the update is aborted. With the -c/--check
6872 directory's parent, the update is aborted. With the -c/--check
6869 option, the working directory is checked for uncommitted changes; if
6873 option, the working directory is checked for uncommitted changes; if
6870 none are found, the working directory is updated to the specified
6874 none are found, the working directory is updated to the specified
6871 changeset.
6875 changeset.
6872
6876
6873 .. container:: verbose
6877 .. container:: verbose
6874
6878
6875 The following rules apply when the working directory contains
6879 The following rules apply when the working directory contains
6876 uncommitted changes:
6880 uncommitted changes:
6877
6881
6878 1. If neither -c/--check nor -C/--clean is specified, and if
6882 1. If neither -c/--check nor -C/--clean is specified, and if
6879 the requested changeset is an ancestor or descendant of
6883 the requested changeset is an ancestor or descendant of
6880 the working directory's parent, the uncommitted changes
6884 the working directory's parent, the uncommitted changes
6881 are merged into the requested changeset and the merged
6885 are merged into the requested changeset and the merged
6882 result is left uncommitted. If the requested changeset is
6886 result is left uncommitted. If the requested changeset is
6883 not an ancestor or descendant (that is, it is on another
6887 not an ancestor or descendant (that is, it is on another
6884 branch), the update is aborted and the uncommitted changes
6888 branch), the update is aborted and the uncommitted changes
6885 are preserved.
6889 are preserved.
6886
6890
6887 2. With the -c/--check option, the update is aborted and the
6891 2. With the -c/--check option, the update is aborted and the
6888 uncommitted changes are preserved.
6892 uncommitted changes are preserved.
6889
6893
6890 3. With the -C/--clean option, uncommitted changes are discarded and
6894 3. With the -C/--clean option, uncommitted changes are discarded and
6891 the working directory is updated to the requested changeset.
6895 the working directory is updated to the requested changeset.
6892
6896
6893 To cancel an uncommitted merge (and lose your changes), use
6897 To cancel an uncommitted merge (and lose your changes), use
6894 :hg:`update --clean .`.
6898 :hg:`update --clean .`.
6895
6899
6896 Use null as the changeset to remove the working directory (like
6900 Use null as the changeset to remove the working directory (like
6897 :hg:`clone -U`).
6901 :hg:`clone -U`).
6898
6902
6899 If you want to revert just one file to an older revision, use
6903 If you want to revert just one file to an older revision, use
6900 :hg:`revert [-r REV] NAME`.
6904 :hg:`revert [-r REV] NAME`.
6901
6905
6902 See :hg:`help dates` for a list of formats valid for -d/--date.
6906 See :hg:`help dates` for a list of formats valid for -d/--date.
6903
6907
6904 Returns 0 on success, 1 if there are unresolved files.
6908 Returns 0 on success, 1 if there are unresolved files.
6905 """
6909 """
6906 movemarkfrom = None
6910 movemarkfrom = None
6907 if rev and node:
6911 if rev and node:
6908 raise error.Abort(_("please specify just one revision"))
6912 raise error.Abort(_("please specify just one revision"))
6909
6913
6910 if rev is None or rev == '':
6914 if rev is None or rev == '':
6911 rev = node
6915 rev = node
6912
6916
6913 wlock = repo.wlock()
6917 wlock = repo.wlock()
6914 try:
6918 try:
6915 cmdutil.clearunfinished(repo)
6919 cmdutil.clearunfinished(repo)
6916
6920
6917 if date:
6921 if date:
6918 if rev is not None:
6922 if rev is not None:
6919 raise error.Abort(_("you can't specify a revision and a date"))
6923 raise error.Abort(_("you can't specify a revision and a date"))
6920 rev = cmdutil.finddate(ui, repo, date)
6924 rev = cmdutil.finddate(ui, repo, date)
6921
6925
6922 # if we defined a bookmark, we have to remember the original name
6926 # if we defined a bookmark, we have to remember the original name
6923 brev = rev
6927 brev = rev
6924 rev = scmutil.revsingle(repo, rev, rev).rev()
6928 rev = scmutil.revsingle(repo, rev, rev).rev()
6925
6929
6926 if check and clean:
6930 if check and clean:
6927 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6931 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6928 )
6932 )
6929
6933
6930 if check:
6934 if check:
6931 cmdutil.bailifchanged(repo, merge=False)
6935 cmdutil.bailifchanged(repo, merge=False)
6932 if rev is None:
6936 if rev is None:
6933 updata = destutil.destupdate(repo, clean=clean, check=check)
6937 updata = destutil.destupdate(repo, clean=clean, check=check)
6934 rev, movemarkfrom, brev = updata
6938 rev, movemarkfrom, brev = updata
6935
6939
6936 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6940 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6937
6941
6938 if clean:
6942 if clean:
6939 ret = hg.clean(repo, rev)
6943 ret = hg.clean(repo, rev)
6940 else:
6944 else:
6941 ret = hg.update(repo, rev)
6945 ret = hg.update(repo, rev)
6942
6946
6943 if not ret and movemarkfrom:
6947 if not ret and movemarkfrom:
6944 if movemarkfrom == repo['.'].node():
6948 if movemarkfrom == repo['.'].node():
6945 pass # no-op update
6949 pass # no-op update
6946 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6950 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6947 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6951 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6948 else:
6952 else:
6949 # this can happen with a non-linear update
6953 # this can happen with a non-linear update
6950 ui.status(_("(leaving bookmark %s)\n") %
6954 ui.status(_("(leaving bookmark %s)\n") %
6951 repo._activebookmark)
6955 repo._activebookmark)
6952 bookmarks.deactivate(repo)
6956 bookmarks.deactivate(repo)
6953 elif brev in repo._bookmarks:
6957 elif brev in repo._bookmarks:
6954 bookmarks.activate(repo, brev)
6958 bookmarks.activate(repo, brev)
6955 ui.status(_("(activating bookmark %s)\n") % brev)
6959 ui.status(_("(activating bookmark %s)\n") % brev)
6956 elif brev:
6960 elif brev:
6957 if repo._activebookmark:
6961 if repo._activebookmark:
6958 ui.status(_("(leaving bookmark %s)\n") %
6962 ui.status(_("(leaving bookmark %s)\n") %
6959 repo._activebookmark)
6963 repo._activebookmark)
6960 bookmarks.deactivate(repo)
6964 bookmarks.deactivate(repo)
6961 finally:
6965 finally:
6962 wlock.release()
6966 wlock.release()
6963
6967
6964 return ret
6968 return ret
6965
6969
6966 @command('verify', [])
6970 @command('verify', [])
6967 def verify(ui, repo):
6971 def verify(ui, repo):
6968 """verify the integrity of the repository
6972 """verify the integrity of the repository
6969
6973
6970 Verify the integrity of the current repository.
6974 Verify the integrity of the current repository.
6971
6975
6972 This will perform an extensive check of the repository's
6976 This will perform an extensive check of the repository's
6973 integrity, validating the hashes and checksums of each entry in
6977 integrity, validating the hashes and checksums of each entry in
6974 the changelog, manifest, and tracked files, as well as the
6978 the changelog, manifest, and tracked files, as well as the
6975 integrity of their crosslinks and indices.
6979 integrity of their crosslinks and indices.
6976
6980
6977 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6981 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6978 for more information about recovery from corruption of the
6982 for more information about recovery from corruption of the
6979 repository.
6983 repository.
6980
6984
6981 Returns 0 on success, 1 if errors are encountered.
6985 Returns 0 on success, 1 if errors are encountered.
6982 """
6986 """
6983 return hg.verify(repo)
6987 return hg.verify(repo)
6984
6988
6985 @command('version', [], norepo=True)
6989 @command('version', [], norepo=True)
6986 def version_(ui):
6990 def version_(ui):
6987 """output version and copyright information"""
6991 """output version and copyright information"""
6988 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6992 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6989 % util.version())
6993 % util.version())
6990 ui.status(_(
6994 ui.status(_(
6991 "(see https://mercurial-scm.org for more information)\n"
6995 "(see https://mercurial-scm.org for more information)\n"
6992 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6996 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6993 "This is free software; see the source for copying conditions. "
6997 "This is free software; see the source for copying conditions. "
6994 "There is NO\nwarranty; "
6998 "There is NO\nwarranty; "
6995 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6999 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6996 ))
7000 ))
6997
7001
6998 ui.note(_("\nEnabled extensions:\n\n"))
7002 ui.note(_("\nEnabled extensions:\n\n"))
6999 if ui.verbose:
7003 if ui.verbose:
7000 # format names and versions into columns
7004 # format names and versions into columns
7001 names = []
7005 names = []
7002 vers = []
7006 vers = []
7003 for name, module in extensions.extensions():
7007 for name, module in extensions.extensions():
7004 names.append(name)
7008 names.append(name)
7005 vers.append(extensions.moduleversion(module))
7009 vers.append(extensions.moduleversion(module))
7006 if names:
7010 if names:
7007 maxnamelen = max(len(n) for n in names)
7011 maxnamelen = max(len(n) for n in names)
7008 for i, name in enumerate(names):
7012 for i, name in enumerate(names):
7009 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7013 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now