##// END OF EJS Templates
commands: use context manager for opened bundle file
Gregory Szorc -
r27884:acfe40eb default
parent child Browse files
Show More
@@ -1,7015 +1,7012 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 branch = repo.dirstate.branch()
635 branch = repo.dirstate.branch()
636 bheads = repo.branchheads(branch)
636 bheads = repo.branchheads(branch)
637 rctx = scmutil.revsingle(repo, hex(parent))
637 rctx = scmutil.revsingle(repo, hex(parent))
638 if not opts.get('merge') and op1 != node:
638 if not opts.get('merge') and op1 != node:
639 dsguard = cmdutil.dirstateguard(repo, 'backout')
639 dsguard = cmdutil.dirstateguard(repo, 'backout')
640 try:
640 try:
641 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
641 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
642 'backout')
642 'backout')
643 stats = mergemod.update(repo, parent, True, True, node, False)
643 stats = mergemod.update(repo, parent, True, True, node, False)
644 repo.setparents(op1, op2)
644 repo.setparents(op1, op2)
645 dsguard.close()
645 dsguard.close()
646 hg._showstats(repo, stats)
646 hg._showstats(repo, stats)
647 if stats[3]:
647 if stats[3]:
648 repo.ui.status(_("use 'hg resolve' to retry unresolved "
648 repo.ui.status(_("use 'hg resolve' to retry unresolved "
649 "file merges\n"))
649 "file merges\n"))
650 return 1
650 return 1
651 elif not commit:
651 elif not commit:
652 msg = _("changeset %s backed out, "
652 msg = _("changeset %s backed out, "
653 "don't forget to commit.\n")
653 "don't forget to commit.\n")
654 ui.status(msg % short(node))
654 ui.status(msg % short(node))
655 return 0
655 return 0
656 finally:
656 finally:
657 ui.setconfig('ui', 'forcemerge', '', '')
657 ui.setconfig('ui', 'forcemerge', '', '')
658 lockmod.release(dsguard)
658 lockmod.release(dsguard)
659 else:
659 else:
660 hg.clean(repo, node, show_stats=False)
660 hg.clean(repo, node, show_stats=False)
661 repo.dirstate.setbranch(branch)
661 repo.dirstate.setbranch(branch)
662 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
662 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
663
663
664
664
665 def commitfunc(ui, repo, message, match, opts):
665 def commitfunc(ui, repo, message, match, opts):
666 editform = 'backout'
666 editform = 'backout'
667 e = cmdutil.getcommiteditor(editform=editform, **opts)
667 e = cmdutil.getcommiteditor(editform=editform, **opts)
668 if not message:
668 if not message:
669 # we don't translate commit messages
669 # we don't translate commit messages
670 message = "Backed out changeset %s" % short(node)
670 message = "Backed out changeset %s" % short(node)
671 e = cmdutil.getcommiteditor(edit=True, editform=editform)
671 e = cmdutil.getcommiteditor(edit=True, editform=editform)
672 return repo.commit(message, opts.get('user'), opts.get('date'),
672 return repo.commit(message, opts.get('user'), opts.get('date'),
673 match, editor=e)
673 match, editor=e)
674 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
674 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
675 if not newnode:
675 if not newnode:
676 ui.status(_("nothing changed\n"))
676 ui.status(_("nothing changed\n"))
677 return 1
677 return 1
678 cmdutil.commitstatus(repo, newnode, branch, bheads)
678 cmdutil.commitstatus(repo, newnode, branch, bheads)
679
679
680 def nice(node):
680 def nice(node):
681 return '%d:%s' % (repo.changelog.rev(node), short(node))
681 return '%d:%s' % (repo.changelog.rev(node), short(node))
682 ui.status(_('changeset %s backs out changeset %s\n') %
682 ui.status(_('changeset %s backs out changeset %s\n') %
683 (nice(repo.changelog.tip()), nice(node)))
683 (nice(repo.changelog.tip()), nice(node)))
684 if opts.get('merge') and op1 != node:
684 if opts.get('merge') and op1 != node:
685 hg.clean(repo, op1, show_stats=False)
685 hg.clean(repo, op1, show_stats=False)
686 ui.status(_('merging with changeset %s\n')
686 ui.status(_('merging with changeset %s\n')
687 % nice(repo.changelog.tip()))
687 % nice(repo.changelog.tip()))
688 try:
688 try:
689 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
689 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
690 'backout')
690 'backout')
691 return hg.merge(repo, hex(repo.changelog.tip()))
691 return hg.merge(repo, hex(repo.changelog.tip()))
692 finally:
692 finally:
693 ui.setconfig('ui', 'forcemerge', '', '')
693 ui.setconfig('ui', 'forcemerge', '', '')
694 return 0
694 return 0
695
695
696 @command('bisect',
696 @command('bisect',
697 [('r', 'reset', False, _('reset bisect state')),
697 [('r', 'reset', False, _('reset bisect state')),
698 ('g', 'good', False, _('mark changeset good')),
698 ('g', 'good', False, _('mark changeset good')),
699 ('b', 'bad', False, _('mark changeset bad')),
699 ('b', 'bad', False, _('mark changeset bad')),
700 ('s', 'skip', False, _('skip testing changeset')),
700 ('s', 'skip', False, _('skip testing changeset')),
701 ('e', 'extend', False, _('extend the bisect range')),
701 ('e', 'extend', False, _('extend the bisect range')),
702 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
702 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
703 ('U', 'noupdate', False, _('do not update to target'))],
703 ('U', 'noupdate', False, _('do not update to target'))],
704 _("[-gbsr] [-U] [-c CMD] [REV]"))
704 _("[-gbsr] [-U] [-c CMD] [REV]"))
705 def bisect(ui, repo, rev=None, extra=None, command=None,
705 def bisect(ui, repo, rev=None, extra=None, command=None,
706 reset=None, good=None, bad=None, skip=None, extend=None,
706 reset=None, good=None, bad=None, skip=None, extend=None,
707 noupdate=None):
707 noupdate=None):
708 """subdivision search of changesets
708 """subdivision search of changesets
709
709
710 This command helps to find changesets which introduce problems. To
710 This command helps to find changesets which introduce problems. To
711 use, mark the earliest changeset you know exhibits the problem as
711 use, mark the earliest changeset you know exhibits the problem as
712 bad, then mark the latest changeset which is free from the problem
712 bad, then mark the latest changeset which is free from the problem
713 as good. Bisect will update your working directory to a revision
713 as good. Bisect will update your working directory to a revision
714 for testing (unless the -U/--noupdate option is specified). Once
714 for testing (unless the -U/--noupdate option is specified). Once
715 you have performed tests, mark the working directory as good or
715 you have performed tests, mark the working directory as good or
716 bad, and bisect will either update to another candidate changeset
716 bad, and bisect will either update to another candidate changeset
717 or announce that it has found the bad revision.
717 or announce that it has found the bad revision.
718
718
719 As a shortcut, you can also use the revision argument to mark a
719 As a shortcut, you can also use the revision argument to mark a
720 revision as good or bad without checking it out first.
720 revision as good or bad without checking it out first.
721
721
722 If you supply a command, it will be used for automatic bisection.
722 If you supply a command, it will be used for automatic bisection.
723 The environment variable HG_NODE will contain the ID of the
723 The environment variable HG_NODE will contain the ID of the
724 changeset being tested. The exit status of the command will be
724 changeset being tested. The exit status of the command will be
725 used to mark revisions as good or bad: status 0 means good, 125
725 used to mark revisions as good or bad: status 0 means good, 125
726 means to skip the revision, 127 (command not found) will abort the
726 means to skip the revision, 127 (command not found) will abort the
727 bisection, and any other non-zero exit status means the revision
727 bisection, and any other non-zero exit status means the revision
728 is bad.
728 is bad.
729
729
730 .. container:: verbose
730 .. container:: verbose
731
731
732 Some examples:
732 Some examples:
733
733
734 - start a bisection with known bad revision 34, and good revision 12::
734 - start a bisection with known bad revision 34, and good revision 12::
735
735
736 hg bisect --bad 34
736 hg bisect --bad 34
737 hg bisect --good 12
737 hg bisect --good 12
738
738
739 - advance the current bisection by marking current revision as good or
739 - advance the current bisection by marking current revision as good or
740 bad::
740 bad::
741
741
742 hg bisect --good
742 hg bisect --good
743 hg bisect --bad
743 hg bisect --bad
744
744
745 - mark the current revision, or a known revision, to be skipped (e.g. if
745 - mark the current revision, or a known revision, to be skipped (e.g. if
746 that revision is not usable because of another issue)::
746 that revision is not usable because of another issue)::
747
747
748 hg bisect --skip
748 hg bisect --skip
749 hg bisect --skip 23
749 hg bisect --skip 23
750
750
751 - skip all revisions that do not touch directories ``foo`` or ``bar``::
751 - skip all revisions that do not touch directories ``foo`` or ``bar``::
752
752
753 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
753 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
754
754
755 - forget the current bisection::
755 - forget the current bisection::
756
756
757 hg bisect --reset
757 hg bisect --reset
758
758
759 - use 'make && make tests' to automatically find the first broken
759 - use 'make && make tests' to automatically find the first broken
760 revision::
760 revision::
761
761
762 hg bisect --reset
762 hg bisect --reset
763 hg bisect --bad 34
763 hg bisect --bad 34
764 hg bisect --good 12
764 hg bisect --good 12
765 hg bisect --command "make && make tests"
765 hg bisect --command "make && make tests"
766
766
767 - see all changesets whose states are already known in the current
767 - see all changesets whose states are already known in the current
768 bisection::
768 bisection::
769
769
770 hg log -r "bisect(pruned)"
770 hg log -r "bisect(pruned)"
771
771
772 - see the changeset currently being bisected (especially useful
772 - see the changeset currently being bisected (especially useful
773 if running with -U/--noupdate)::
773 if running with -U/--noupdate)::
774
774
775 hg log -r "bisect(current)"
775 hg log -r "bisect(current)"
776
776
777 - see all changesets that took part in the current bisection::
777 - see all changesets that took part in the current bisection::
778
778
779 hg log -r "bisect(range)"
779 hg log -r "bisect(range)"
780
780
781 - you can even get a nice graph::
781 - you can even get a nice graph::
782
782
783 hg log --graph -r "bisect(range)"
783 hg log --graph -r "bisect(range)"
784
784
785 See :hg:`help revsets` for more about the `bisect()` keyword.
785 See :hg:`help revsets` for more about the `bisect()` keyword.
786
786
787 Returns 0 on success.
787 Returns 0 on success.
788 """
788 """
789 def extendbisectrange(nodes, good):
789 def extendbisectrange(nodes, good):
790 # bisect is incomplete when it ends on a merge node and
790 # bisect is incomplete when it ends on a merge node and
791 # one of the parent was not checked.
791 # one of the parent was not checked.
792 parents = repo[nodes[0]].parents()
792 parents = repo[nodes[0]].parents()
793 if len(parents) > 1:
793 if len(parents) > 1:
794 if good:
794 if good:
795 side = state['bad']
795 side = state['bad']
796 else:
796 else:
797 side = state['good']
797 side = state['good']
798 num = len(set(i.node() for i in parents) & set(side))
798 num = len(set(i.node() for i in parents) & set(side))
799 if num == 1:
799 if num == 1:
800 return parents[0].ancestor(parents[1])
800 return parents[0].ancestor(parents[1])
801 return None
801 return None
802
802
803 def print_result(nodes, good):
803 def print_result(nodes, good):
804 displayer = cmdutil.show_changeset(ui, repo, {})
804 displayer = cmdutil.show_changeset(ui, repo, {})
805 if len(nodes) == 1:
805 if len(nodes) == 1:
806 # narrowed it down to a single revision
806 # narrowed it down to a single revision
807 if good:
807 if good:
808 ui.write(_("The first good revision is:\n"))
808 ui.write(_("The first good revision is:\n"))
809 else:
809 else:
810 ui.write(_("The first bad revision is:\n"))
810 ui.write(_("The first bad revision is:\n"))
811 displayer.show(repo[nodes[0]])
811 displayer.show(repo[nodes[0]])
812 extendnode = extendbisectrange(nodes, good)
812 extendnode = extendbisectrange(nodes, good)
813 if extendnode is not None:
813 if extendnode is not None:
814 ui.write(_('Not all ancestors of this changeset have been'
814 ui.write(_('Not all ancestors of this changeset have been'
815 ' checked.\nUse bisect --extend to continue the '
815 ' checked.\nUse bisect --extend to continue the '
816 'bisection from\nthe common ancestor, %s.\n')
816 'bisection from\nthe common ancestor, %s.\n')
817 % extendnode)
817 % extendnode)
818 else:
818 else:
819 # multiple possible revisions
819 # multiple possible revisions
820 if good:
820 if good:
821 ui.write(_("Due to skipped revisions, the first "
821 ui.write(_("Due to skipped revisions, the first "
822 "good revision could be any of:\n"))
822 "good revision could be any of:\n"))
823 else:
823 else:
824 ui.write(_("Due to skipped revisions, the first "
824 ui.write(_("Due to skipped revisions, the first "
825 "bad revision could be any of:\n"))
825 "bad revision could be any of:\n"))
826 for n in nodes:
826 for n in nodes:
827 displayer.show(repo[n])
827 displayer.show(repo[n])
828 displayer.close()
828 displayer.close()
829
829
830 def check_state(state, interactive=True):
830 def check_state(state, interactive=True):
831 if not state['good'] or not state['bad']:
831 if not state['good'] or not state['bad']:
832 if (good or bad or skip or reset) and interactive:
832 if (good or bad or skip or reset) and interactive:
833 return
833 return
834 if not state['good']:
834 if not state['good']:
835 raise error.Abort(_('cannot bisect (no known good revisions)'))
835 raise error.Abort(_('cannot bisect (no known good revisions)'))
836 else:
836 else:
837 raise error.Abort(_('cannot bisect (no known bad revisions)'))
837 raise error.Abort(_('cannot bisect (no known bad revisions)'))
838 return True
838 return True
839
839
840 # backward compatibility
840 # backward compatibility
841 if rev in "good bad reset init".split():
841 if rev in "good bad reset init".split():
842 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
842 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
843 cmd, rev, extra = rev, extra, None
843 cmd, rev, extra = rev, extra, None
844 if cmd == "good":
844 if cmd == "good":
845 good = True
845 good = True
846 elif cmd == "bad":
846 elif cmd == "bad":
847 bad = True
847 bad = True
848 else:
848 else:
849 reset = True
849 reset = True
850 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
850 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
851 raise error.Abort(_('incompatible arguments'))
851 raise error.Abort(_('incompatible arguments'))
852
852
853 cmdutil.checkunfinished(repo)
853 cmdutil.checkunfinished(repo)
854
854
855 if reset:
855 if reset:
856 p = repo.join("bisect.state")
856 p = repo.join("bisect.state")
857 if os.path.exists(p):
857 if os.path.exists(p):
858 os.unlink(p)
858 os.unlink(p)
859 return
859 return
860
860
861 state = hbisect.load_state(repo)
861 state = hbisect.load_state(repo)
862
862
863 if command:
863 if command:
864 changesets = 1
864 changesets = 1
865 if noupdate:
865 if noupdate:
866 try:
866 try:
867 node = state['current'][0]
867 node = state['current'][0]
868 except LookupError:
868 except LookupError:
869 raise error.Abort(_('current bisect revision is unknown - '
869 raise error.Abort(_('current bisect revision is unknown - '
870 'start a new bisect to fix'))
870 'start a new bisect to fix'))
871 else:
871 else:
872 node, p2 = repo.dirstate.parents()
872 node, p2 = repo.dirstate.parents()
873 if p2 != nullid:
873 if p2 != nullid:
874 raise error.Abort(_('current bisect revision is a merge'))
874 raise error.Abort(_('current bisect revision is a merge'))
875 try:
875 try:
876 while changesets:
876 while changesets:
877 # update state
877 # update state
878 state['current'] = [node]
878 state['current'] = [node]
879 hbisect.save_state(repo, state)
879 hbisect.save_state(repo, state)
880 status = ui.system(command, environ={'HG_NODE': hex(node)})
880 status = ui.system(command, environ={'HG_NODE': hex(node)})
881 if status == 125:
881 if status == 125:
882 transition = "skip"
882 transition = "skip"
883 elif status == 0:
883 elif status == 0:
884 transition = "good"
884 transition = "good"
885 # status < 0 means process was killed
885 # status < 0 means process was killed
886 elif status == 127:
886 elif status == 127:
887 raise error.Abort(_("failed to execute %s") % command)
887 raise error.Abort(_("failed to execute %s") % command)
888 elif status < 0:
888 elif status < 0:
889 raise error.Abort(_("%s killed") % command)
889 raise error.Abort(_("%s killed") % command)
890 else:
890 else:
891 transition = "bad"
891 transition = "bad"
892 ctx = scmutil.revsingle(repo, rev, node)
892 ctx = scmutil.revsingle(repo, rev, node)
893 rev = None # clear for future iterations
893 rev = None # clear for future iterations
894 state[transition].append(ctx.node())
894 state[transition].append(ctx.node())
895 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
895 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
896 check_state(state, interactive=False)
896 check_state(state, interactive=False)
897 # bisect
897 # bisect
898 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
898 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
899 # update to next check
899 # update to next check
900 node = nodes[0]
900 node = nodes[0]
901 if not noupdate:
901 if not noupdate:
902 cmdutil.bailifchanged(repo)
902 cmdutil.bailifchanged(repo)
903 hg.clean(repo, node, show_stats=False)
903 hg.clean(repo, node, show_stats=False)
904 finally:
904 finally:
905 state['current'] = [node]
905 state['current'] = [node]
906 hbisect.save_state(repo, state)
906 hbisect.save_state(repo, state)
907 print_result(nodes, bgood)
907 print_result(nodes, bgood)
908 return
908 return
909
909
910 # update state
910 # update state
911
911
912 if rev:
912 if rev:
913 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
913 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
914 else:
914 else:
915 nodes = [repo.lookup('.')]
915 nodes = [repo.lookup('.')]
916
916
917 if good or bad or skip:
917 if good or bad or skip:
918 if good:
918 if good:
919 state['good'] += nodes
919 state['good'] += nodes
920 elif bad:
920 elif bad:
921 state['bad'] += nodes
921 state['bad'] += nodes
922 elif skip:
922 elif skip:
923 state['skip'] += nodes
923 state['skip'] += nodes
924 hbisect.save_state(repo, state)
924 hbisect.save_state(repo, state)
925
925
926 if not check_state(state):
926 if not check_state(state):
927 return
927 return
928
928
929 # actually bisect
929 # actually bisect
930 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
930 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
931 if extend:
931 if extend:
932 if not changesets:
932 if not changesets:
933 extendnode = extendbisectrange(nodes, good)
933 extendnode = extendbisectrange(nodes, good)
934 if extendnode is not None:
934 if extendnode is not None:
935 ui.write(_("Extending search to changeset %d:%s\n")
935 ui.write(_("Extending search to changeset %d:%s\n")
936 % (extendnode.rev(), extendnode))
936 % (extendnode.rev(), extendnode))
937 state['current'] = [extendnode.node()]
937 state['current'] = [extendnode.node()]
938 hbisect.save_state(repo, state)
938 hbisect.save_state(repo, state)
939 if noupdate:
939 if noupdate:
940 return
940 return
941 cmdutil.bailifchanged(repo)
941 cmdutil.bailifchanged(repo)
942 return hg.clean(repo, extendnode.node())
942 return hg.clean(repo, extendnode.node())
943 raise error.Abort(_("nothing to extend"))
943 raise error.Abort(_("nothing to extend"))
944
944
945 if changesets == 0:
945 if changesets == 0:
946 print_result(nodes, good)
946 print_result(nodes, good)
947 else:
947 else:
948 assert len(nodes) == 1 # only a single node can be tested next
948 assert len(nodes) == 1 # only a single node can be tested next
949 node = nodes[0]
949 node = nodes[0]
950 # compute the approximate number of remaining tests
950 # compute the approximate number of remaining tests
951 tests, size = 0, 2
951 tests, size = 0, 2
952 while size <= changesets:
952 while size <= changesets:
953 tests, size = tests + 1, size * 2
953 tests, size = tests + 1, size * 2
954 rev = repo.changelog.rev(node)
954 rev = repo.changelog.rev(node)
955 ui.write(_("Testing changeset %d:%s "
955 ui.write(_("Testing changeset %d:%s "
956 "(%d changesets remaining, ~%d tests)\n")
956 "(%d changesets remaining, ~%d tests)\n")
957 % (rev, short(node), changesets, tests))
957 % (rev, short(node), changesets, tests))
958 state['current'] = [node]
958 state['current'] = [node]
959 hbisect.save_state(repo, state)
959 hbisect.save_state(repo, state)
960 if not noupdate:
960 if not noupdate:
961 cmdutil.bailifchanged(repo)
961 cmdutil.bailifchanged(repo)
962 return hg.clean(repo, node)
962 return hg.clean(repo, node)
963
963
964 @command('bookmarks|bookmark',
964 @command('bookmarks|bookmark',
965 [('f', 'force', False, _('force')),
965 [('f', 'force', False, _('force')),
966 ('r', 'rev', '', _('revision'), _('REV')),
966 ('r', 'rev', '', _('revision'), _('REV')),
967 ('d', 'delete', False, _('delete a given bookmark')),
967 ('d', 'delete', False, _('delete a given bookmark')),
968 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
968 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
969 ('i', 'inactive', False, _('mark a bookmark inactive')),
969 ('i', 'inactive', False, _('mark a bookmark inactive')),
970 ] + formatteropts,
970 ] + formatteropts,
971 _('hg bookmarks [OPTIONS]... [NAME]...'))
971 _('hg bookmarks [OPTIONS]... [NAME]...'))
972 def bookmark(ui, repo, *names, **opts):
972 def bookmark(ui, repo, *names, **opts):
973 '''create a new bookmark or list existing bookmarks
973 '''create a new bookmark or list existing bookmarks
974
974
975 Bookmarks are labels on changesets to help track lines of development.
975 Bookmarks are labels on changesets to help track lines of development.
976 Bookmarks are unversioned and can be moved, renamed and deleted.
976 Bookmarks are unversioned and can be moved, renamed and deleted.
977 Deleting or moving a bookmark has no effect on the associated changesets.
977 Deleting or moving a bookmark has no effect on the associated changesets.
978
978
979 Creating or updating to a bookmark causes it to be marked as 'active'.
979 Creating or updating to a bookmark causes it to be marked as 'active'.
980 The active bookmark is indicated with a '*'.
980 The active bookmark is indicated with a '*'.
981 When a commit is made, the active bookmark will advance to the new commit.
981 When a commit is made, the active bookmark will advance to the new commit.
982 A plain :hg:`update` will also advance an active bookmark, if possible.
982 A plain :hg:`update` will also advance an active bookmark, if possible.
983 Updating away from a bookmark will cause it to be deactivated.
983 Updating away from a bookmark will cause it to be deactivated.
984
984
985 Bookmarks can be pushed and pulled between repositories (see
985 Bookmarks can be pushed and pulled between repositories (see
986 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
986 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
987 diverged, a new 'divergent bookmark' of the form 'name@path' will
987 diverged, a new 'divergent bookmark' of the form 'name@path' will
988 be created. Using :hg:`merge` will resolve the divergence.
988 be created. Using :hg:`merge` will resolve the divergence.
989
989
990 A bookmark named '@' has the special property that :hg:`clone` will
990 A bookmark named '@' has the special property that :hg:`clone` will
991 check it out by default if it exists.
991 check it out by default if it exists.
992
992
993 .. container:: verbose
993 .. container:: verbose
994
994
995 Examples:
995 Examples:
996
996
997 - create an active bookmark for a new line of development::
997 - create an active bookmark for a new line of development::
998
998
999 hg book new-feature
999 hg book new-feature
1000
1000
1001 - create an inactive bookmark as a place marker::
1001 - create an inactive bookmark as a place marker::
1002
1002
1003 hg book -i reviewed
1003 hg book -i reviewed
1004
1004
1005 - create an inactive bookmark on another changeset::
1005 - create an inactive bookmark on another changeset::
1006
1006
1007 hg book -r .^ tested
1007 hg book -r .^ tested
1008
1008
1009 - rename bookmark turkey to dinner::
1009 - rename bookmark turkey to dinner::
1010
1010
1011 hg book -m turkey dinner
1011 hg book -m turkey dinner
1012
1012
1013 - move the '@' bookmark from another branch::
1013 - move the '@' bookmark from another branch::
1014
1014
1015 hg book -f @
1015 hg book -f @
1016 '''
1016 '''
1017 force = opts.get('force')
1017 force = opts.get('force')
1018 rev = opts.get('rev')
1018 rev = opts.get('rev')
1019 delete = opts.get('delete')
1019 delete = opts.get('delete')
1020 rename = opts.get('rename')
1020 rename = opts.get('rename')
1021 inactive = opts.get('inactive')
1021 inactive = opts.get('inactive')
1022
1022
1023 def checkformat(mark):
1023 def checkformat(mark):
1024 mark = mark.strip()
1024 mark = mark.strip()
1025 if not mark:
1025 if not mark:
1026 raise error.Abort(_("bookmark names cannot consist entirely of "
1026 raise error.Abort(_("bookmark names cannot consist entirely of "
1027 "whitespace"))
1027 "whitespace"))
1028 scmutil.checknewlabel(repo, mark, 'bookmark')
1028 scmutil.checknewlabel(repo, mark, 'bookmark')
1029 return mark
1029 return mark
1030
1030
1031 def checkconflict(repo, mark, cur, force=False, target=None):
1031 def checkconflict(repo, mark, cur, force=False, target=None):
1032 if mark in marks and not force:
1032 if mark in marks and not force:
1033 if target:
1033 if target:
1034 if marks[mark] == target and target == cur:
1034 if marks[mark] == target and target == cur:
1035 # re-activating a bookmark
1035 # re-activating a bookmark
1036 return
1036 return
1037 anc = repo.changelog.ancestors([repo[target].rev()])
1037 anc = repo.changelog.ancestors([repo[target].rev()])
1038 bmctx = repo[marks[mark]]
1038 bmctx = repo[marks[mark]]
1039 divs = [repo[b].node() for b in marks
1039 divs = [repo[b].node() for b in marks
1040 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1040 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1041
1041
1042 # allow resolving a single divergent bookmark even if moving
1042 # allow resolving a single divergent bookmark even if moving
1043 # the bookmark across branches when a revision is specified
1043 # the bookmark across branches when a revision is specified
1044 # that contains a divergent bookmark
1044 # that contains a divergent bookmark
1045 if bmctx.rev() not in anc and target in divs:
1045 if bmctx.rev() not in anc and target in divs:
1046 bookmarks.deletedivergent(repo, [target], mark)
1046 bookmarks.deletedivergent(repo, [target], mark)
1047 return
1047 return
1048
1048
1049 deletefrom = [b for b in divs
1049 deletefrom = [b for b in divs
1050 if repo[b].rev() in anc or b == target]
1050 if repo[b].rev() in anc or b == target]
1051 bookmarks.deletedivergent(repo, deletefrom, mark)
1051 bookmarks.deletedivergent(repo, deletefrom, mark)
1052 if bookmarks.validdest(repo, bmctx, repo[target]):
1052 if bookmarks.validdest(repo, bmctx, repo[target]):
1053 ui.status(_("moving bookmark '%s' forward from %s\n") %
1053 ui.status(_("moving bookmark '%s' forward from %s\n") %
1054 (mark, short(bmctx.node())))
1054 (mark, short(bmctx.node())))
1055 return
1055 return
1056 raise error.Abort(_("bookmark '%s' already exists "
1056 raise error.Abort(_("bookmark '%s' already exists "
1057 "(use -f to force)") % mark)
1057 "(use -f to force)") % mark)
1058 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1058 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1059 and not force):
1059 and not force):
1060 raise error.Abort(
1060 raise error.Abort(
1061 _("a bookmark cannot have the name of an existing branch"))
1061 _("a bookmark cannot have the name of an existing branch"))
1062
1062
1063 if delete and rename:
1063 if delete and rename:
1064 raise error.Abort(_("--delete and --rename are incompatible"))
1064 raise error.Abort(_("--delete and --rename are incompatible"))
1065 if delete and rev:
1065 if delete and rev:
1066 raise error.Abort(_("--rev is incompatible with --delete"))
1066 raise error.Abort(_("--rev is incompatible with --delete"))
1067 if rename and rev:
1067 if rename and rev:
1068 raise error.Abort(_("--rev is incompatible with --rename"))
1068 raise error.Abort(_("--rev is incompatible with --rename"))
1069 if not names and (delete or rev):
1069 if not names and (delete or rev):
1070 raise error.Abort(_("bookmark name required"))
1070 raise error.Abort(_("bookmark name required"))
1071
1071
1072 if delete or rename or names or inactive:
1072 if delete or rename or names or inactive:
1073 wlock = lock = tr = None
1073 wlock = lock = tr = None
1074 try:
1074 try:
1075 wlock = repo.wlock()
1075 wlock = repo.wlock()
1076 lock = repo.lock()
1076 lock = repo.lock()
1077 cur = repo.changectx('.').node()
1077 cur = repo.changectx('.').node()
1078 marks = repo._bookmarks
1078 marks = repo._bookmarks
1079 if delete:
1079 if delete:
1080 tr = repo.transaction('bookmark')
1080 tr = repo.transaction('bookmark')
1081 for mark in names:
1081 for mark in names:
1082 if mark not in marks:
1082 if mark not in marks:
1083 raise error.Abort(_("bookmark '%s' does not exist") %
1083 raise error.Abort(_("bookmark '%s' does not exist") %
1084 mark)
1084 mark)
1085 if mark == repo._activebookmark:
1085 if mark == repo._activebookmark:
1086 bookmarks.deactivate(repo)
1086 bookmarks.deactivate(repo)
1087 del marks[mark]
1087 del marks[mark]
1088
1088
1089 elif rename:
1089 elif rename:
1090 tr = repo.transaction('bookmark')
1090 tr = repo.transaction('bookmark')
1091 if not names:
1091 if not names:
1092 raise error.Abort(_("new bookmark name required"))
1092 raise error.Abort(_("new bookmark name required"))
1093 elif len(names) > 1:
1093 elif len(names) > 1:
1094 raise error.Abort(_("only one new bookmark name allowed"))
1094 raise error.Abort(_("only one new bookmark name allowed"))
1095 mark = checkformat(names[0])
1095 mark = checkformat(names[0])
1096 if rename not in marks:
1096 if rename not in marks:
1097 raise error.Abort(_("bookmark '%s' does not exist")
1097 raise error.Abort(_("bookmark '%s' does not exist")
1098 % rename)
1098 % rename)
1099 checkconflict(repo, mark, cur, force)
1099 checkconflict(repo, mark, cur, force)
1100 marks[mark] = marks[rename]
1100 marks[mark] = marks[rename]
1101 if repo._activebookmark == rename and not inactive:
1101 if repo._activebookmark == rename and not inactive:
1102 bookmarks.activate(repo, mark)
1102 bookmarks.activate(repo, mark)
1103 del marks[rename]
1103 del marks[rename]
1104 elif names:
1104 elif names:
1105 tr = repo.transaction('bookmark')
1105 tr = repo.transaction('bookmark')
1106 newact = None
1106 newact = None
1107 for mark in names:
1107 for mark in names:
1108 mark = checkformat(mark)
1108 mark = checkformat(mark)
1109 if newact is None:
1109 if newact is None:
1110 newact = mark
1110 newact = mark
1111 if inactive and mark == repo._activebookmark:
1111 if inactive and mark == repo._activebookmark:
1112 bookmarks.deactivate(repo)
1112 bookmarks.deactivate(repo)
1113 return
1113 return
1114 tgt = cur
1114 tgt = cur
1115 if rev:
1115 if rev:
1116 tgt = scmutil.revsingle(repo, rev).node()
1116 tgt = scmutil.revsingle(repo, rev).node()
1117 checkconflict(repo, mark, cur, force, tgt)
1117 checkconflict(repo, mark, cur, force, tgt)
1118 marks[mark] = tgt
1118 marks[mark] = tgt
1119 if not inactive and cur == marks[newact] and not rev:
1119 if not inactive and cur == marks[newact] and not rev:
1120 bookmarks.activate(repo, newact)
1120 bookmarks.activate(repo, newact)
1121 elif cur != tgt and newact == repo._activebookmark:
1121 elif cur != tgt and newact == repo._activebookmark:
1122 bookmarks.deactivate(repo)
1122 bookmarks.deactivate(repo)
1123 elif inactive:
1123 elif inactive:
1124 if len(marks) == 0:
1124 if len(marks) == 0:
1125 ui.status(_("no bookmarks set\n"))
1125 ui.status(_("no bookmarks set\n"))
1126 elif not repo._activebookmark:
1126 elif not repo._activebookmark:
1127 ui.status(_("no active bookmark\n"))
1127 ui.status(_("no active bookmark\n"))
1128 else:
1128 else:
1129 bookmarks.deactivate(repo)
1129 bookmarks.deactivate(repo)
1130 if tr is not None:
1130 if tr is not None:
1131 marks.recordchange(tr)
1131 marks.recordchange(tr)
1132 tr.close()
1132 tr.close()
1133 finally:
1133 finally:
1134 lockmod.release(tr, lock, wlock)
1134 lockmod.release(tr, lock, wlock)
1135 else: # show bookmarks
1135 else: # show bookmarks
1136 fm = ui.formatter('bookmarks', opts)
1136 fm = ui.formatter('bookmarks', opts)
1137 hexfn = fm.hexfunc
1137 hexfn = fm.hexfunc
1138 marks = repo._bookmarks
1138 marks = repo._bookmarks
1139 if len(marks) == 0 and not fm:
1139 if len(marks) == 0 and not fm:
1140 ui.status(_("no bookmarks set\n"))
1140 ui.status(_("no bookmarks set\n"))
1141 for bmark, n in sorted(marks.iteritems()):
1141 for bmark, n in sorted(marks.iteritems()):
1142 active = repo._activebookmark
1142 active = repo._activebookmark
1143 if bmark == active:
1143 if bmark == active:
1144 prefix, label = '*', activebookmarklabel
1144 prefix, label = '*', activebookmarklabel
1145 else:
1145 else:
1146 prefix, label = ' ', ''
1146 prefix, label = ' ', ''
1147
1147
1148 fm.startitem()
1148 fm.startitem()
1149 if not ui.quiet:
1149 if not ui.quiet:
1150 fm.plain(' %s ' % prefix, label=label)
1150 fm.plain(' %s ' % prefix, label=label)
1151 fm.write('bookmark', '%s', bmark, label=label)
1151 fm.write('bookmark', '%s', bmark, label=label)
1152 pad = " " * (25 - encoding.colwidth(bmark))
1152 pad = " " * (25 - encoding.colwidth(bmark))
1153 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1153 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1154 repo.changelog.rev(n), hexfn(n), label=label)
1154 repo.changelog.rev(n), hexfn(n), label=label)
1155 fm.data(active=(bmark == active))
1155 fm.data(active=(bmark == active))
1156 fm.plain('\n')
1156 fm.plain('\n')
1157 fm.end()
1157 fm.end()
1158
1158
1159 @command('branch',
1159 @command('branch',
1160 [('f', 'force', None,
1160 [('f', 'force', None,
1161 _('set branch name even if it shadows an existing branch')),
1161 _('set branch name even if it shadows an existing branch')),
1162 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1162 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1163 _('[-fC] [NAME]'))
1163 _('[-fC] [NAME]'))
1164 def branch(ui, repo, label=None, **opts):
1164 def branch(ui, repo, label=None, **opts):
1165 """set or show the current branch name
1165 """set or show the current branch name
1166
1166
1167 .. note::
1167 .. note::
1168
1168
1169 Branch names are permanent and global. Use :hg:`bookmark` to create a
1169 Branch names are permanent and global. Use :hg:`bookmark` to create a
1170 light-weight bookmark instead. See :hg:`help glossary` for more
1170 light-weight bookmark instead. See :hg:`help glossary` for more
1171 information about named branches and bookmarks.
1171 information about named branches and bookmarks.
1172
1172
1173 With no argument, show the current branch name. With one argument,
1173 With no argument, show the current branch name. With one argument,
1174 set the working directory branch name (the branch will not exist
1174 set the working directory branch name (the branch will not exist
1175 in the repository until the next commit). Standard practice
1175 in the repository until the next commit). Standard practice
1176 recommends that primary development take place on the 'default'
1176 recommends that primary development take place on the 'default'
1177 branch.
1177 branch.
1178
1178
1179 Unless -f/--force is specified, branch will not let you set a
1179 Unless -f/--force is specified, branch will not let you set a
1180 branch name that already exists.
1180 branch name that already exists.
1181
1181
1182 Use -C/--clean to reset the working directory branch to that of
1182 Use -C/--clean to reset the working directory branch to that of
1183 the parent of the working directory, negating a previous branch
1183 the parent of the working directory, negating a previous branch
1184 change.
1184 change.
1185
1185
1186 Use the command :hg:`update` to switch to an existing branch. Use
1186 Use the command :hg:`update` to switch to an existing branch. Use
1187 :hg:`commit --close-branch` to mark this branch head as closed.
1187 :hg:`commit --close-branch` to mark this branch head as closed.
1188 When all heads of a branch are closed, the branch will be
1188 When all heads of a branch are closed, the branch will be
1189 considered closed.
1189 considered closed.
1190
1190
1191 Returns 0 on success.
1191 Returns 0 on success.
1192 """
1192 """
1193 if label:
1193 if label:
1194 label = label.strip()
1194 label = label.strip()
1195
1195
1196 if not opts.get('clean') and not label:
1196 if not opts.get('clean') and not label:
1197 ui.write("%s\n" % repo.dirstate.branch())
1197 ui.write("%s\n" % repo.dirstate.branch())
1198 return
1198 return
1199
1199
1200 with repo.wlock():
1200 with repo.wlock():
1201 if opts.get('clean'):
1201 if opts.get('clean'):
1202 label = repo[None].p1().branch()
1202 label = repo[None].p1().branch()
1203 repo.dirstate.setbranch(label)
1203 repo.dirstate.setbranch(label)
1204 ui.status(_('reset working directory to branch %s\n') % label)
1204 ui.status(_('reset working directory to branch %s\n') % label)
1205 elif label:
1205 elif label:
1206 if not opts.get('force') and label in repo.branchmap():
1206 if not opts.get('force') and label in repo.branchmap():
1207 if label not in [p.branch() for p in repo[None].parents()]:
1207 if label not in [p.branch() for p in repo[None].parents()]:
1208 raise error.Abort(_('a branch of the same name already'
1208 raise error.Abort(_('a branch of the same name already'
1209 ' exists'),
1209 ' exists'),
1210 # i18n: "it" refers to an existing branch
1210 # i18n: "it" refers to an existing branch
1211 hint=_("use 'hg update' to switch to it"))
1211 hint=_("use 'hg update' to switch to it"))
1212 scmutil.checknewlabel(repo, label, 'branch')
1212 scmutil.checknewlabel(repo, label, 'branch')
1213 repo.dirstate.setbranch(label)
1213 repo.dirstate.setbranch(label)
1214 ui.status(_('marked working directory as branch %s\n') % label)
1214 ui.status(_('marked working directory as branch %s\n') % label)
1215
1215
1216 # find any open named branches aside from default
1216 # find any open named branches aside from default
1217 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1217 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1218 if n != "default" and not c]
1218 if n != "default" and not c]
1219 if not others:
1219 if not others:
1220 ui.status(_('(branches are permanent and global, '
1220 ui.status(_('(branches are permanent and global, '
1221 'did you want a bookmark?)\n'))
1221 'did you want a bookmark?)\n'))
1222
1222
1223 @command('branches',
1223 @command('branches',
1224 [('a', 'active', False,
1224 [('a', 'active', False,
1225 _('show only branches that have unmerged heads (DEPRECATED)')),
1225 _('show only branches that have unmerged heads (DEPRECATED)')),
1226 ('c', 'closed', False, _('show normal and closed branches')),
1226 ('c', 'closed', False, _('show normal and closed branches')),
1227 ] + formatteropts,
1227 ] + formatteropts,
1228 _('[-ac]'))
1228 _('[-ac]'))
1229 def branches(ui, repo, active=False, closed=False, **opts):
1229 def branches(ui, repo, active=False, closed=False, **opts):
1230 """list repository named branches
1230 """list repository named branches
1231
1231
1232 List the repository's named branches, indicating which ones are
1232 List the repository's named branches, indicating which ones are
1233 inactive. If -c/--closed is specified, also list branches which have
1233 inactive. If -c/--closed is specified, also list branches which have
1234 been marked closed (see :hg:`commit --close-branch`).
1234 been marked closed (see :hg:`commit --close-branch`).
1235
1235
1236 Use the command :hg:`update` to switch to an existing branch.
1236 Use the command :hg:`update` to switch to an existing branch.
1237
1237
1238 Returns 0.
1238 Returns 0.
1239 """
1239 """
1240
1240
1241 fm = ui.formatter('branches', opts)
1241 fm = ui.formatter('branches', opts)
1242 hexfunc = fm.hexfunc
1242 hexfunc = fm.hexfunc
1243
1243
1244 allheads = set(repo.heads())
1244 allheads = set(repo.heads())
1245 branches = []
1245 branches = []
1246 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1246 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1247 isactive = not isclosed and bool(set(heads) & allheads)
1247 isactive = not isclosed and bool(set(heads) & allheads)
1248 branches.append((tag, repo[tip], isactive, not isclosed))
1248 branches.append((tag, repo[tip], isactive, not isclosed))
1249 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1249 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1250 reverse=True)
1250 reverse=True)
1251
1251
1252 for tag, ctx, isactive, isopen in branches:
1252 for tag, ctx, isactive, isopen in branches:
1253 if active and not isactive:
1253 if active and not isactive:
1254 continue
1254 continue
1255 if isactive:
1255 if isactive:
1256 label = 'branches.active'
1256 label = 'branches.active'
1257 notice = ''
1257 notice = ''
1258 elif not isopen:
1258 elif not isopen:
1259 if not closed:
1259 if not closed:
1260 continue
1260 continue
1261 label = 'branches.closed'
1261 label = 'branches.closed'
1262 notice = _(' (closed)')
1262 notice = _(' (closed)')
1263 else:
1263 else:
1264 label = 'branches.inactive'
1264 label = 'branches.inactive'
1265 notice = _(' (inactive)')
1265 notice = _(' (inactive)')
1266 current = (tag == repo.dirstate.branch())
1266 current = (tag == repo.dirstate.branch())
1267 if current:
1267 if current:
1268 label = 'branches.current'
1268 label = 'branches.current'
1269
1269
1270 fm.startitem()
1270 fm.startitem()
1271 fm.write('branch', '%s', tag, label=label)
1271 fm.write('branch', '%s', tag, label=label)
1272 rev = ctx.rev()
1272 rev = ctx.rev()
1273 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1273 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1274 fmt = ' ' * padsize + ' %d:%s'
1274 fmt = ' ' * padsize + ' %d:%s'
1275 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1275 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1276 label='log.changeset changeset.%s' % ctx.phasestr())
1276 label='log.changeset changeset.%s' % ctx.phasestr())
1277 fm.data(active=isactive, closed=not isopen, current=current)
1277 fm.data(active=isactive, closed=not isopen, current=current)
1278 if not ui.quiet:
1278 if not ui.quiet:
1279 fm.plain(notice)
1279 fm.plain(notice)
1280 fm.plain('\n')
1280 fm.plain('\n')
1281 fm.end()
1281 fm.end()
1282
1282
1283 @command('bundle',
1283 @command('bundle',
1284 [('f', 'force', None, _('run even when the destination is unrelated')),
1284 [('f', 'force', None, _('run even when the destination is unrelated')),
1285 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1285 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1286 _('REV')),
1286 _('REV')),
1287 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1287 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1288 _('BRANCH')),
1288 _('BRANCH')),
1289 ('', 'base', [],
1289 ('', 'base', [],
1290 _('a base changeset assumed to be available at the destination'),
1290 _('a base changeset assumed to be available at the destination'),
1291 _('REV')),
1291 _('REV')),
1292 ('a', 'all', None, _('bundle all changesets in the repository')),
1292 ('a', 'all', None, _('bundle all changesets in the repository')),
1293 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1293 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1294 ] + remoteopts,
1294 ] + remoteopts,
1295 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1295 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1296 def bundle(ui, repo, fname, dest=None, **opts):
1296 def bundle(ui, repo, fname, dest=None, **opts):
1297 """create a changegroup file
1297 """create a changegroup file
1298
1298
1299 Generate a changegroup file collecting changesets to be added
1299 Generate a changegroup file collecting changesets to be added
1300 to a repository.
1300 to a repository.
1301
1301
1302 To create a bundle containing all changesets, use -a/--all
1302 To create a bundle containing all changesets, use -a/--all
1303 (or --base null). Otherwise, hg assumes the destination will have
1303 (or --base null). Otherwise, hg assumes the destination will have
1304 all the nodes you specify with --base parameters. Otherwise, hg
1304 all the nodes you specify with --base parameters. Otherwise, hg
1305 will assume the repository has all the nodes in destination, or
1305 will assume the repository has all the nodes in destination, or
1306 default-push/default if no destination is specified.
1306 default-push/default if no destination is specified.
1307
1307
1308 You can change bundle format with the -t/--type option. You can
1308 You can change bundle format with the -t/--type option. You can
1309 specify a compression, a bundle version or both using a dash
1309 specify a compression, a bundle version or both using a dash
1310 (comp-version). The available compression methods are: none, bzip2,
1310 (comp-version). The available compression methods are: none, bzip2,
1311 and gzip (by default, bundles are compressed using bzip2). The
1311 and gzip (by default, bundles are compressed using bzip2). The
1312 available formats are: v1, v2 (default to most suitable).
1312 available formats are: v1, v2 (default to most suitable).
1313
1313
1314 The bundle file can then be transferred using conventional means
1314 The bundle file can then be transferred using conventional means
1315 and applied to another repository with the unbundle or pull
1315 and applied to another repository with the unbundle or pull
1316 command. This is useful when direct push and pull are not
1316 command. This is useful when direct push and pull are not
1317 available or when exporting an entire repository is undesirable.
1317 available or when exporting an entire repository is undesirable.
1318
1318
1319 Applying bundles preserves all changeset contents including
1319 Applying bundles preserves all changeset contents including
1320 permissions, copy/rename information, and revision history.
1320 permissions, copy/rename information, and revision history.
1321
1321
1322 Returns 0 on success, 1 if no changes found.
1322 Returns 0 on success, 1 if no changes found.
1323 """
1323 """
1324 revs = None
1324 revs = None
1325 if 'rev' in opts:
1325 if 'rev' in opts:
1326 revs = scmutil.revrange(repo, opts['rev'])
1326 revs = scmutil.revrange(repo, opts['rev'])
1327
1327
1328 bundletype = opts.get('type', 'bzip2').lower()
1328 bundletype = opts.get('type', 'bzip2').lower()
1329 try:
1329 try:
1330 bcompression, cgversion, params = exchange.parsebundlespec(
1330 bcompression, cgversion, params = exchange.parsebundlespec(
1331 repo, bundletype, strict=False)
1331 repo, bundletype, strict=False)
1332 except error.UnsupportedBundleSpecification as e:
1332 except error.UnsupportedBundleSpecification as e:
1333 raise error.Abort(str(e),
1333 raise error.Abort(str(e),
1334 hint=_('see "hg help bundle" for supported '
1334 hint=_('see "hg help bundle" for supported '
1335 'values for --type'))
1335 'values for --type'))
1336
1336
1337 # Packed bundles are a pseudo bundle format for now.
1337 # Packed bundles are a pseudo bundle format for now.
1338 if cgversion == 's1':
1338 if cgversion == 's1':
1339 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1339 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1340 hint=_('use "hg debugcreatestreamclonebundle"'))
1340 hint=_('use "hg debugcreatestreamclonebundle"'))
1341
1341
1342 if opts.get('all'):
1342 if opts.get('all'):
1343 if dest:
1343 if dest:
1344 raise error.Abort(_("--all is incompatible with specifying "
1344 raise error.Abort(_("--all is incompatible with specifying "
1345 "a destination"))
1345 "a destination"))
1346 if opts.get('base'):
1346 if opts.get('base'):
1347 ui.warn(_("ignoring --base because --all was specified\n"))
1347 ui.warn(_("ignoring --base because --all was specified\n"))
1348 base = ['null']
1348 base = ['null']
1349 else:
1349 else:
1350 base = scmutil.revrange(repo, opts.get('base'))
1350 base = scmutil.revrange(repo, opts.get('base'))
1351 # TODO: get desired bundlecaps from command line.
1351 # TODO: get desired bundlecaps from command line.
1352 bundlecaps = None
1352 bundlecaps = None
1353 if base:
1353 if base:
1354 if dest:
1354 if dest:
1355 raise error.Abort(_("--base is incompatible with specifying "
1355 raise error.Abort(_("--base is incompatible with specifying "
1356 "a destination"))
1356 "a destination"))
1357 common = [repo.lookup(rev) for rev in base]
1357 common = [repo.lookup(rev) for rev in base]
1358 heads = revs and map(repo.lookup, revs) or revs
1358 heads = revs and map(repo.lookup, revs) or revs
1359 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1359 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1360 common=common, bundlecaps=bundlecaps,
1360 common=common, bundlecaps=bundlecaps,
1361 version=cgversion)
1361 version=cgversion)
1362 outgoing = None
1362 outgoing = None
1363 else:
1363 else:
1364 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1364 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1365 dest, branches = hg.parseurl(dest, opts.get('branch'))
1365 dest, branches = hg.parseurl(dest, opts.get('branch'))
1366 other = hg.peer(repo, opts, dest)
1366 other = hg.peer(repo, opts, dest)
1367 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1367 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1368 heads = revs and map(repo.lookup, revs) or revs
1368 heads = revs and map(repo.lookup, revs) or revs
1369 outgoing = discovery.findcommonoutgoing(repo, other,
1369 outgoing = discovery.findcommonoutgoing(repo, other,
1370 onlyheads=heads,
1370 onlyheads=heads,
1371 force=opts.get('force'),
1371 force=opts.get('force'),
1372 portable=True)
1372 portable=True)
1373 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1373 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1374 bundlecaps, version=cgversion)
1374 bundlecaps, version=cgversion)
1375 if not cg:
1375 if not cg:
1376 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1376 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1377 return 1
1377 return 1
1378
1378
1379 if cgversion == '01': #bundle1
1379 if cgversion == '01': #bundle1
1380 if bcompression is None:
1380 if bcompression is None:
1381 bcompression = 'UN'
1381 bcompression = 'UN'
1382 bversion = 'HG10' + bcompression
1382 bversion = 'HG10' + bcompression
1383 bcompression = None
1383 bcompression = None
1384 else:
1384 else:
1385 assert cgversion == '02'
1385 assert cgversion == '02'
1386 bversion = 'HG20'
1386 bversion = 'HG20'
1387
1387
1388
1388
1389 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1389 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1390
1390
1391 @command('cat',
1391 @command('cat',
1392 [('o', 'output', '',
1392 [('o', 'output', '',
1393 _('print output to file with formatted name'), _('FORMAT')),
1393 _('print output to file with formatted name'), _('FORMAT')),
1394 ('r', 'rev', '', _('print the given revision'), _('REV')),
1394 ('r', 'rev', '', _('print the given revision'), _('REV')),
1395 ('', 'decode', None, _('apply any matching decode filter')),
1395 ('', 'decode', None, _('apply any matching decode filter')),
1396 ] + walkopts,
1396 ] + walkopts,
1397 _('[OPTION]... FILE...'),
1397 _('[OPTION]... FILE...'),
1398 inferrepo=True)
1398 inferrepo=True)
1399 def cat(ui, repo, file1, *pats, **opts):
1399 def cat(ui, repo, file1, *pats, **opts):
1400 """output the current or given revision of files
1400 """output the current or given revision of files
1401
1401
1402 Print the specified files as they were at the given revision. If
1402 Print the specified files as they were at the given revision. If
1403 no revision is given, the parent of the working directory is used.
1403 no revision is given, the parent of the working directory is used.
1404
1404
1405 Output may be to a file, in which case the name of the file is
1405 Output may be to a file, in which case the name of the file is
1406 given using a format string. The formatting rules as follows:
1406 given using a format string. The formatting rules as follows:
1407
1407
1408 :``%%``: literal "%" character
1408 :``%%``: literal "%" character
1409 :``%s``: basename of file being printed
1409 :``%s``: basename of file being printed
1410 :``%d``: dirname of file being printed, or '.' if in repository root
1410 :``%d``: dirname of file being printed, or '.' if in repository root
1411 :``%p``: root-relative path name of file being printed
1411 :``%p``: root-relative path name of file being printed
1412 :``%H``: changeset hash (40 hexadecimal digits)
1412 :``%H``: changeset hash (40 hexadecimal digits)
1413 :``%R``: changeset revision number
1413 :``%R``: changeset revision number
1414 :``%h``: short-form changeset hash (12 hexadecimal digits)
1414 :``%h``: short-form changeset hash (12 hexadecimal digits)
1415 :``%r``: zero-padded changeset revision number
1415 :``%r``: zero-padded changeset revision number
1416 :``%b``: basename of the exporting repository
1416 :``%b``: basename of the exporting repository
1417
1417
1418 Returns 0 on success.
1418 Returns 0 on success.
1419 """
1419 """
1420 ctx = scmutil.revsingle(repo, opts.get('rev'))
1420 ctx = scmutil.revsingle(repo, opts.get('rev'))
1421 m = scmutil.match(ctx, (file1,) + pats, opts)
1421 m = scmutil.match(ctx, (file1,) + pats, opts)
1422
1422
1423 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1423 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1424
1424
1425 @command('^clone',
1425 @command('^clone',
1426 [('U', 'noupdate', None, _('the clone will include an empty working '
1426 [('U', 'noupdate', None, _('the clone will include an empty working '
1427 'directory (only a repository)')),
1427 'directory (only a repository)')),
1428 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1428 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1429 _('REV')),
1429 _('REV')),
1430 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1430 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1431 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1431 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1432 ('', 'pull', None, _('use pull protocol to copy metadata')),
1432 ('', 'pull', None, _('use pull protocol to copy metadata')),
1433 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1433 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1434 ] + remoteopts,
1434 ] + remoteopts,
1435 _('[OPTION]... SOURCE [DEST]'),
1435 _('[OPTION]... SOURCE [DEST]'),
1436 norepo=True)
1436 norepo=True)
1437 def clone(ui, source, dest=None, **opts):
1437 def clone(ui, source, dest=None, **opts):
1438 """make a copy of an existing repository
1438 """make a copy of an existing repository
1439
1439
1440 Create a copy of an existing repository in a new directory.
1440 Create a copy of an existing repository in a new directory.
1441
1441
1442 If no destination directory name is specified, it defaults to the
1442 If no destination directory name is specified, it defaults to the
1443 basename of the source.
1443 basename of the source.
1444
1444
1445 The location of the source is added to the new repository's
1445 The location of the source is added to the new repository's
1446 ``.hg/hgrc`` file, as the default to be used for future pulls.
1446 ``.hg/hgrc`` file, as the default to be used for future pulls.
1447
1447
1448 Only local paths and ``ssh://`` URLs are supported as
1448 Only local paths and ``ssh://`` URLs are supported as
1449 destinations. For ``ssh://`` destinations, no working directory or
1449 destinations. For ``ssh://`` destinations, no working directory or
1450 ``.hg/hgrc`` will be created on the remote side.
1450 ``.hg/hgrc`` will be created on the remote side.
1451
1451
1452 If the source repository has a bookmark called '@' set, that
1452 If the source repository has a bookmark called '@' set, that
1453 revision will be checked out in the new repository by default.
1453 revision will be checked out in the new repository by default.
1454
1454
1455 To check out a particular version, use -u/--update, or
1455 To check out a particular version, use -u/--update, or
1456 -U/--noupdate to create a clone with no working directory.
1456 -U/--noupdate to create a clone with no working directory.
1457
1457
1458 To pull only a subset of changesets, specify one or more revisions
1458 To pull only a subset of changesets, specify one or more revisions
1459 identifiers with -r/--rev or branches with -b/--branch. The
1459 identifiers with -r/--rev or branches with -b/--branch. The
1460 resulting clone will contain only the specified changesets and
1460 resulting clone will contain only the specified changesets and
1461 their ancestors. These options (or 'clone src#rev dest') imply
1461 their ancestors. These options (or 'clone src#rev dest') imply
1462 --pull, even for local source repositories.
1462 --pull, even for local source repositories.
1463
1463
1464 .. note::
1464 .. note::
1465
1465
1466 Specifying a tag will include the tagged changeset but not the
1466 Specifying a tag will include the tagged changeset but not the
1467 changeset containing the tag.
1467 changeset containing the tag.
1468
1468
1469 .. container:: verbose
1469 .. container:: verbose
1470
1470
1471 For efficiency, hardlinks are used for cloning whenever the
1471 For efficiency, hardlinks are used for cloning whenever the
1472 source and destination are on the same filesystem (note this
1472 source and destination are on the same filesystem (note this
1473 applies only to the repository data, not to the working
1473 applies only to the repository data, not to the working
1474 directory). Some filesystems, such as AFS, implement hardlinking
1474 directory). Some filesystems, such as AFS, implement hardlinking
1475 incorrectly, but do not report errors. In these cases, use the
1475 incorrectly, but do not report errors. In these cases, use the
1476 --pull option to avoid hardlinking.
1476 --pull option to avoid hardlinking.
1477
1477
1478 In some cases, you can clone repositories and the working
1478 In some cases, you can clone repositories and the working
1479 directory using full hardlinks with ::
1479 directory using full hardlinks with ::
1480
1480
1481 $ cp -al REPO REPOCLONE
1481 $ cp -al REPO REPOCLONE
1482
1482
1483 This is the fastest way to clone, but it is not always safe. The
1483 This is the fastest way to clone, but it is not always safe. The
1484 operation is not atomic (making sure REPO is not modified during
1484 operation is not atomic (making sure REPO is not modified during
1485 the operation is up to you) and you have to make sure your
1485 the operation is up to you) and you have to make sure your
1486 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1486 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1487 so). Also, this is not compatible with certain extensions that
1487 so). Also, this is not compatible with certain extensions that
1488 place their metadata under the .hg directory, such as mq.
1488 place their metadata under the .hg directory, such as mq.
1489
1489
1490 Mercurial will update the working directory to the first applicable
1490 Mercurial will update the working directory to the first applicable
1491 revision from this list:
1491 revision from this list:
1492
1492
1493 a) null if -U or the source repository has no changesets
1493 a) null if -U or the source repository has no changesets
1494 b) if -u . and the source repository is local, the first parent of
1494 b) if -u . and the source repository is local, the first parent of
1495 the source repository's working directory
1495 the source repository's working directory
1496 c) the changeset specified with -u (if a branch name, this means the
1496 c) the changeset specified with -u (if a branch name, this means the
1497 latest head of that branch)
1497 latest head of that branch)
1498 d) the changeset specified with -r
1498 d) the changeset specified with -r
1499 e) the tipmost head specified with -b
1499 e) the tipmost head specified with -b
1500 f) the tipmost head specified with the url#branch source syntax
1500 f) the tipmost head specified with the url#branch source syntax
1501 g) the revision marked with the '@' bookmark, if present
1501 g) the revision marked with the '@' bookmark, if present
1502 h) the tipmost head of the default branch
1502 h) the tipmost head of the default branch
1503 i) tip
1503 i) tip
1504
1504
1505 Examples:
1505 Examples:
1506
1506
1507 - clone a remote repository to a new directory named hg/::
1507 - clone a remote repository to a new directory named hg/::
1508
1508
1509 hg clone http://selenic.com/hg
1509 hg clone http://selenic.com/hg
1510
1510
1511 - create a lightweight local clone::
1511 - create a lightweight local clone::
1512
1512
1513 hg clone project/ project-feature/
1513 hg clone project/ project-feature/
1514
1514
1515 - clone from an absolute path on an ssh server (note double-slash)::
1515 - clone from an absolute path on an ssh server (note double-slash)::
1516
1516
1517 hg clone ssh://user@server//home/projects/alpha/
1517 hg clone ssh://user@server//home/projects/alpha/
1518
1518
1519 - do a high-speed clone over a LAN while checking out a
1519 - do a high-speed clone over a LAN while checking out a
1520 specified version::
1520 specified version::
1521
1521
1522 hg clone --uncompressed http://server/repo -u 1.5
1522 hg clone --uncompressed http://server/repo -u 1.5
1523
1523
1524 - create a repository without changesets after a particular revision::
1524 - create a repository without changesets after a particular revision::
1525
1525
1526 hg clone -r 04e544 experimental/ good/
1526 hg clone -r 04e544 experimental/ good/
1527
1527
1528 - clone (and track) a particular named branch::
1528 - clone (and track) a particular named branch::
1529
1529
1530 hg clone http://selenic.com/hg#stable
1530 hg clone http://selenic.com/hg#stable
1531
1531
1532 See :hg:`help urls` for details on specifying URLs.
1532 See :hg:`help urls` for details on specifying URLs.
1533
1533
1534 Returns 0 on success.
1534 Returns 0 on success.
1535 """
1535 """
1536 if opts.get('noupdate') and opts.get('updaterev'):
1536 if opts.get('noupdate') and opts.get('updaterev'):
1537 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1537 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1538
1538
1539 r = hg.clone(ui, opts, source, dest,
1539 r = hg.clone(ui, opts, source, dest,
1540 pull=opts.get('pull'),
1540 pull=opts.get('pull'),
1541 stream=opts.get('uncompressed'),
1541 stream=opts.get('uncompressed'),
1542 rev=opts.get('rev'),
1542 rev=opts.get('rev'),
1543 update=opts.get('updaterev') or not opts.get('noupdate'),
1543 update=opts.get('updaterev') or not opts.get('noupdate'),
1544 branch=opts.get('branch'),
1544 branch=opts.get('branch'),
1545 shareopts=opts.get('shareopts'))
1545 shareopts=opts.get('shareopts'))
1546
1546
1547 return r is None
1547 return r is None
1548
1548
1549 @command('^commit|ci',
1549 @command('^commit|ci',
1550 [('A', 'addremove', None,
1550 [('A', 'addremove', None,
1551 _('mark new/missing files as added/removed before committing')),
1551 _('mark new/missing files as added/removed before committing')),
1552 ('', 'close-branch', None,
1552 ('', 'close-branch', None,
1553 _('mark a branch head as closed')),
1553 _('mark a branch head as closed')),
1554 ('', 'amend', None, _('amend the parent of the working directory')),
1554 ('', 'amend', None, _('amend the parent of the working directory')),
1555 ('s', 'secret', None, _('use the secret phase for committing')),
1555 ('s', 'secret', None, _('use the secret phase for committing')),
1556 ('e', 'edit', None, _('invoke editor on commit messages')),
1556 ('e', 'edit', None, _('invoke editor on commit messages')),
1557 ('i', 'interactive', None, _('use interactive mode')),
1557 ('i', 'interactive', None, _('use interactive mode')),
1558 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1558 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1559 _('[OPTION]... [FILE]...'),
1559 _('[OPTION]... [FILE]...'),
1560 inferrepo=True)
1560 inferrepo=True)
1561 def commit(ui, repo, *pats, **opts):
1561 def commit(ui, repo, *pats, **opts):
1562 """commit the specified files or all outstanding changes
1562 """commit the specified files or all outstanding changes
1563
1563
1564 Commit changes to the given files into the repository. Unlike a
1564 Commit changes to the given files into the repository. Unlike a
1565 centralized SCM, this operation is a local operation. See
1565 centralized SCM, this operation is a local operation. See
1566 :hg:`push` for a way to actively distribute your changes.
1566 :hg:`push` for a way to actively distribute your changes.
1567
1567
1568 If a list of files is omitted, all changes reported by :hg:`status`
1568 If a list of files is omitted, all changes reported by :hg:`status`
1569 will be committed.
1569 will be committed.
1570
1570
1571 If you are committing the result of a merge, do not provide any
1571 If you are committing the result of a merge, do not provide any
1572 filenames or -I/-X filters.
1572 filenames or -I/-X filters.
1573
1573
1574 If no commit message is specified, Mercurial starts your
1574 If no commit message is specified, Mercurial starts your
1575 configured editor where you can enter a message. In case your
1575 configured editor where you can enter a message. In case your
1576 commit fails, you will find a backup of your message in
1576 commit fails, you will find a backup of your message in
1577 ``.hg/last-message.txt``.
1577 ``.hg/last-message.txt``.
1578
1578
1579 The --close-branch flag can be used to mark the current branch
1579 The --close-branch flag can be used to mark the current branch
1580 head closed. When all heads of a branch are closed, the branch
1580 head closed. When all heads of a branch are closed, the branch
1581 will be considered closed and no longer listed.
1581 will be considered closed and no longer listed.
1582
1582
1583 The --amend flag can be used to amend the parent of the
1583 The --amend flag can be used to amend the parent of the
1584 working directory with a new commit that contains the changes
1584 working directory with a new commit that contains the changes
1585 in the parent in addition to those currently reported by :hg:`status`,
1585 in the parent in addition to those currently reported by :hg:`status`,
1586 if there are any. The old commit is stored in a backup bundle in
1586 if there are any. The old commit is stored in a backup bundle in
1587 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1587 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1588 on how to restore it).
1588 on how to restore it).
1589
1589
1590 Message, user and date are taken from the amended commit unless
1590 Message, user and date are taken from the amended commit unless
1591 specified. When a message isn't specified on the command line,
1591 specified. When a message isn't specified on the command line,
1592 the editor will open with the message of the amended commit.
1592 the editor will open with the message of the amended commit.
1593
1593
1594 It is not possible to amend public changesets (see :hg:`help phases`)
1594 It is not possible to amend public changesets (see :hg:`help phases`)
1595 or changesets that have children.
1595 or changesets that have children.
1596
1596
1597 See :hg:`help dates` for a list of formats valid for -d/--date.
1597 See :hg:`help dates` for a list of formats valid for -d/--date.
1598
1598
1599 Returns 0 on success, 1 if nothing changed.
1599 Returns 0 on success, 1 if nothing changed.
1600
1600
1601 .. container:: verbose
1601 .. container:: verbose
1602
1602
1603 Examples:
1603 Examples:
1604
1604
1605 - commit all files ending in .py::
1605 - commit all files ending in .py::
1606
1606
1607 hg commit --include "set:**.py"
1607 hg commit --include "set:**.py"
1608
1608
1609 - commit all non-binary files::
1609 - commit all non-binary files::
1610
1610
1611 hg commit --exclude "set:binary()"
1611 hg commit --exclude "set:binary()"
1612
1612
1613 - amend the current commit and set the date to now::
1613 - amend the current commit and set the date to now::
1614
1614
1615 hg commit --amend --date now
1615 hg commit --amend --date now
1616 """
1616 """
1617 wlock = lock = None
1617 wlock = lock = None
1618 try:
1618 try:
1619 wlock = repo.wlock()
1619 wlock = repo.wlock()
1620 lock = repo.lock()
1620 lock = repo.lock()
1621 return _docommit(ui, repo, *pats, **opts)
1621 return _docommit(ui, repo, *pats, **opts)
1622 finally:
1622 finally:
1623 release(lock, wlock)
1623 release(lock, wlock)
1624
1624
1625 def _docommit(ui, repo, *pats, **opts):
1625 def _docommit(ui, repo, *pats, **opts):
1626 if opts.get('interactive'):
1626 if opts.get('interactive'):
1627 opts.pop('interactive')
1627 opts.pop('interactive')
1628 cmdutil.dorecord(ui, repo, commit, None, False,
1628 cmdutil.dorecord(ui, repo, commit, None, False,
1629 cmdutil.recordfilter, *pats, **opts)
1629 cmdutil.recordfilter, *pats, **opts)
1630 return
1630 return
1631
1631
1632 if opts.get('subrepos'):
1632 if opts.get('subrepos'):
1633 if opts.get('amend'):
1633 if opts.get('amend'):
1634 raise error.Abort(_('cannot amend with --subrepos'))
1634 raise error.Abort(_('cannot amend with --subrepos'))
1635 # Let --subrepos on the command line override config setting.
1635 # Let --subrepos on the command line override config setting.
1636 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1636 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1637
1637
1638 cmdutil.checkunfinished(repo, commit=True)
1638 cmdutil.checkunfinished(repo, commit=True)
1639
1639
1640 branch = repo[None].branch()
1640 branch = repo[None].branch()
1641 bheads = repo.branchheads(branch)
1641 bheads = repo.branchheads(branch)
1642
1642
1643 extra = {}
1643 extra = {}
1644 if opts.get('close_branch'):
1644 if opts.get('close_branch'):
1645 extra['close'] = 1
1645 extra['close'] = 1
1646
1646
1647 if not bheads:
1647 if not bheads:
1648 raise error.Abort(_('can only close branch heads'))
1648 raise error.Abort(_('can only close branch heads'))
1649 elif opts.get('amend'):
1649 elif opts.get('amend'):
1650 if repo[None].parents()[0].p1().branch() != branch and \
1650 if repo[None].parents()[0].p1().branch() != branch and \
1651 repo[None].parents()[0].p2().branch() != branch:
1651 repo[None].parents()[0].p2().branch() != branch:
1652 raise error.Abort(_('can only close branch heads'))
1652 raise error.Abort(_('can only close branch heads'))
1653
1653
1654 if opts.get('amend'):
1654 if opts.get('amend'):
1655 if ui.configbool('ui', 'commitsubrepos'):
1655 if ui.configbool('ui', 'commitsubrepos'):
1656 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1656 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1657
1657
1658 old = repo['.']
1658 old = repo['.']
1659 if not old.mutable():
1659 if not old.mutable():
1660 raise error.Abort(_('cannot amend public changesets'))
1660 raise error.Abort(_('cannot amend public changesets'))
1661 if len(repo[None].parents()) > 1:
1661 if len(repo[None].parents()) > 1:
1662 raise error.Abort(_('cannot amend while merging'))
1662 raise error.Abort(_('cannot amend while merging'))
1663 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1663 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1664 if not allowunstable and old.children():
1664 if not allowunstable and old.children():
1665 raise error.Abort(_('cannot amend changeset with children'))
1665 raise error.Abort(_('cannot amend changeset with children'))
1666
1666
1667 newextra = extra.copy()
1667 newextra = extra.copy()
1668 newextra['branch'] = branch
1668 newextra['branch'] = branch
1669 extra = newextra
1669 extra = newextra
1670 # commitfunc is used only for temporary amend commit by cmdutil.amend
1670 # commitfunc is used only for temporary amend commit by cmdutil.amend
1671 def commitfunc(ui, repo, message, match, opts):
1671 def commitfunc(ui, repo, message, match, opts):
1672 return repo.commit(message,
1672 return repo.commit(message,
1673 opts.get('user') or old.user(),
1673 opts.get('user') or old.user(),
1674 opts.get('date') or old.date(),
1674 opts.get('date') or old.date(),
1675 match,
1675 match,
1676 extra=extra)
1676 extra=extra)
1677
1677
1678 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1678 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1679 if node == old.node():
1679 if node == old.node():
1680 ui.status(_("nothing changed\n"))
1680 ui.status(_("nothing changed\n"))
1681 return 1
1681 return 1
1682 else:
1682 else:
1683 def commitfunc(ui, repo, message, match, opts):
1683 def commitfunc(ui, repo, message, match, opts):
1684 backup = ui.backupconfig('phases', 'new-commit')
1684 backup = ui.backupconfig('phases', 'new-commit')
1685 baseui = repo.baseui
1685 baseui = repo.baseui
1686 basebackup = baseui.backupconfig('phases', 'new-commit')
1686 basebackup = baseui.backupconfig('phases', 'new-commit')
1687 try:
1687 try:
1688 if opts.get('secret'):
1688 if opts.get('secret'):
1689 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1689 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1690 # Propagate to subrepos
1690 # Propagate to subrepos
1691 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1691 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1692
1692
1693 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1693 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1694 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1694 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1695 return repo.commit(message, opts.get('user'), opts.get('date'),
1695 return repo.commit(message, opts.get('user'), opts.get('date'),
1696 match,
1696 match,
1697 editor=editor,
1697 editor=editor,
1698 extra=extra)
1698 extra=extra)
1699 finally:
1699 finally:
1700 ui.restoreconfig(backup)
1700 ui.restoreconfig(backup)
1701 repo.baseui.restoreconfig(basebackup)
1701 repo.baseui.restoreconfig(basebackup)
1702
1702
1703
1703
1704 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1704 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1705
1705
1706 if not node:
1706 if not node:
1707 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1707 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1708 if stat[3]:
1708 if stat[3]:
1709 ui.status(_("nothing changed (%d missing files, see "
1709 ui.status(_("nothing changed (%d missing files, see "
1710 "'hg status')\n") % len(stat[3]))
1710 "'hg status')\n") % len(stat[3]))
1711 else:
1711 else:
1712 ui.status(_("nothing changed\n"))
1712 ui.status(_("nothing changed\n"))
1713 return 1
1713 return 1
1714
1714
1715 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1715 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1716
1716
1717 @command('config|showconfig|debugconfig',
1717 @command('config|showconfig|debugconfig',
1718 [('u', 'untrusted', None, _('show untrusted configuration options')),
1718 [('u', 'untrusted', None, _('show untrusted configuration options')),
1719 ('e', 'edit', None, _('edit user config')),
1719 ('e', 'edit', None, _('edit user config')),
1720 ('l', 'local', None, _('edit repository config')),
1720 ('l', 'local', None, _('edit repository config')),
1721 ('g', 'global', None, _('edit global config'))],
1721 ('g', 'global', None, _('edit global config'))],
1722 _('[-u] [NAME]...'),
1722 _('[-u] [NAME]...'),
1723 optionalrepo=True)
1723 optionalrepo=True)
1724 def config(ui, repo, *values, **opts):
1724 def config(ui, repo, *values, **opts):
1725 """show combined config settings from all hgrc files
1725 """show combined config settings from all hgrc files
1726
1726
1727 With no arguments, print names and values of all config items.
1727 With no arguments, print names and values of all config items.
1728
1728
1729 With one argument of the form section.name, print just the value
1729 With one argument of the form section.name, print just the value
1730 of that config item.
1730 of that config item.
1731
1731
1732 With multiple arguments, print names and values of all config
1732 With multiple arguments, print names and values of all config
1733 items with matching section names.
1733 items with matching section names.
1734
1734
1735 With --edit, start an editor on the user-level config file. With
1735 With --edit, start an editor on the user-level config file. With
1736 --global, edit the system-wide config file. With --local, edit the
1736 --global, edit the system-wide config file. With --local, edit the
1737 repository-level config file.
1737 repository-level config file.
1738
1738
1739 With --debug, the source (filename and line number) is printed
1739 With --debug, the source (filename and line number) is printed
1740 for each config item.
1740 for each config item.
1741
1741
1742 See :hg:`help config` for more information about config files.
1742 See :hg:`help config` for more information about config files.
1743
1743
1744 Returns 0 on success, 1 if NAME does not exist.
1744 Returns 0 on success, 1 if NAME does not exist.
1745
1745
1746 """
1746 """
1747
1747
1748 if opts.get('edit') or opts.get('local') or opts.get('global'):
1748 if opts.get('edit') or opts.get('local') or opts.get('global'):
1749 if opts.get('local') and opts.get('global'):
1749 if opts.get('local') and opts.get('global'):
1750 raise error.Abort(_("can't use --local and --global together"))
1750 raise error.Abort(_("can't use --local and --global together"))
1751
1751
1752 if opts.get('local'):
1752 if opts.get('local'):
1753 if not repo:
1753 if not repo:
1754 raise error.Abort(_("can't use --local outside a repository"))
1754 raise error.Abort(_("can't use --local outside a repository"))
1755 paths = [repo.join('hgrc')]
1755 paths = [repo.join('hgrc')]
1756 elif opts.get('global'):
1756 elif opts.get('global'):
1757 paths = scmutil.systemrcpath()
1757 paths = scmutil.systemrcpath()
1758 else:
1758 else:
1759 paths = scmutil.userrcpath()
1759 paths = scmutil.userrcpath()
1760
1760
1761 for f in paths:
1761 for f in paths:
1762 if os.path.exists(f):
1762 if os.path.exists(f):
1763 break
1763 break
1764 else:
1764 else:
1765 if opts.get('global'):
1765 if opts.get('global'):
1766 samplehgrc = uimod.samplehgrcs['global']
1766 samplehgrc = uimod.samplehgrcs['global']
1767 elif opts.get('local'):
1767 elif opts.get('local'):
1768 samplehgrc = uimod.samplehgrcs['local']
1768 samplehgrc = uimod.samplehgrcs['local']
1769 else:
1769 else:
1770 samplehgrc = uimod.samplehgrcs['user']
1770 samplehgrc = uimod.samplehgrcs['user']
1771
1771
1772 f = paths[0]
1772 f = paths[0]
1773 fp = open(f, "w")
1773 fp = open(f, "w")
1774 fp.write(samplehgrc)
1774 fp.write(samplehgrc)
1775 fp.close()
1775 fp.close()
1776
1776
1777 editor = ui.geteditor()
1777 editor = ui.geteditor()
1778 ui.system("%s \"%s\"" % (editor, f),
1778 ui.system("%s \"%s\"" % (editor, f),
1779 onerr=error.Abort, errprefix=_("edit failed"))
1779 onerr=error.Abort, errprefix=_("edit failed"))
1780 return
1780 return
1781
1781
1782 for f in scmutil.rcpath():
1782 for f in scmutil.rcpath():
1783 ui.debug('read config from: %s\n' % f)
1783 ui.debug('read config from: %s\n' % f)
1784 untrusted = bool(opts.get('untrusted'))
1784 untrusted = bool(opts.get('untrusted'))
1785 if values:
1785 if values:
1786 sections = [v for v in values if '.' not in v]
1786 sections = [v for v in values if '.' not in v]
1787 items = [v for v in values if '.' in v]
1787 items = [v for v in values if '.' in v]
1788 if len(items) > 1 or items and sections:
1788 if len(items) > 1 or items and sections:
1789 raise error.Abort(_('only one config item permitted'))
1789 raise error.Abort(_('only one config item permitted'))
1790 matched = False
1790 matched = False
1791 for section, name, value in ui.walkconfig(untrusted=untrusted):
1791 for section, name, value in ui.walkconfig(untrusted=untrusted):
1792 value = str(value).replace('\n', '\\n')
1792 value = str(value).replace('\n', '\\n')
1793 sectname = section + '.' + name
1793 sectname = section + '.' + name
1794 if values:
1794 if values:
1795 for v in values:
1795 for v in values:
1796 if v == section:
1796 if v == section:
1797 ui.debug('%s: ' %
1797 ui.debug('%s: ' %
1798 ui.configsource(section, name, untrusted))
1798 ui.configsource(section, name, untrusted))
1799 ui.write('%s=%s\n' % (sectname, value))
1799 ui.write('%s=%s\n' % (sectname, value))
1800 matched = True
1800 matched = True
1801 elif v == sectname:
1801 elif v == sectname:
1802 ui.debug('%s: ' %
1802 ui.debug('%s: ' %
1803 ui.configsource(section, name, untrusted))
1803 ui.configsource(section, name, untrusted))
1804 ui.write(value, '\n')
1804 ui.write(value, '\n')
1805 matched = True
1805 matched = True
1806 else:
1806 else:
1807 ui.debug('%s: ' %
1807 ui.debug('%s: ' %
1808 ui.configsource(section, name, untrusted))
1808 ui.configsource(section, name, untrusted))
1809 ui.write('%s=%s\n' % (sectname, value))
1809 ui.write('%s=%s\n' % (sectname, value))
1810 matched = True
1810 matched = True
1811 if matched:
1811 if matched:
1812 return 0
1812 return 0
1813 return 1
1813 return 1
1814
1814
1815 @command('copy|cp',
1815 @command('copy|cp',
1816 [('A', 'after', None, _('record a copy that has already occurred')),
1816 [('A', 'after', None, _('record a copy that has already occurred')),
1817 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1817 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1818 ] + walkopts + dryrunopts,
1818 ] + walkopts + dryrunopts,
1819 _('[OPTION]... [SOURCE]... DEST'))
1819 _('[OPTION]... [SOURCE]... DEST'))
1820 def copy(ui, repo, *pats, **opts):
1820 def copy(ui, repo, *pats, **opts):
1821 """mark files as copied for the next commit
1821 """mark files as copied for the next commit
1822
1822
1823 Mark dest as having copies of source files. If dest is a
1823 Mark dest as having copies of source files. If dest is a
1824 directory, copies are put in that directory. If dest is a file,
1824 directory, copies are put in that directory. If dest is a file,
1825 the source must be a single file.
1825 the source must be a single file.
1826
1826
1827 By default, this command copies the contents of files as they
1827 By default, this command copies the contents of files as they
1828 exist in the working directory. If invoked with -A/--after, the
1828 exist in the working directory. If invoked with -A/--after, the
1829 operation is recorded, but no copying is performed.
1829 operation is recorded, but no copying is performed.
1830
1830
1831 This command takes effect with the next commit. To undo a copy
1831 This command takes effect with the next commit. To undo a copy
1832 before that, see :hg:`revert`.
1832 before that, see :hg:`revert`.
1833
1833
1834 Returns 0 on success, 1 if errors are encountered.
1834 Returns 0 on success, 1 if errors are encountered.
1835 """
1835 """
1836 with repo.wlock(False):
1836 with repo.wlock(False):
1837 return cmdutil.copy(ui, repo, pats, opts)
1837 return cmdutil.copy(ui, repo, pats, opts)
1838
1838
1839 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1839 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1840 def debugancestor(ui, repo, *args):
1840 def debugancestor(ui, repo, *args):
1841 """find the ancestor revision of two revisions in a given index"""
1841 """find the ancestor revision of two revisions in a given index"""
1842 if len(args) == 3:
1842 if len(args) == 3:
1843 index, rev1, rev2 = args
1843 index, rev1, rev2 = args
1844 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1844 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1845 lookup = r.lookup
1845 lookup = r.lookup
1846 elif len(args) == 2:
1846 elif len(args) == 2:
1847 if not repo:
1847 if not repo:
1848 raise error.Abort(_("there is no Mercurial repository here "
1848 raise error.Abort(_("there is no Mercurial repository here "
1849 "(.hg not found)"))
1849 "(.hg not found)"))
1850 rev1, rev2 = args
1850 rev1, rev2 = args
1851 r = repo.changelog
1851 r = repo.changelog
1852 lookup = repo.lookup
1852 lookup = repo.lookup
1853 else:
1853 else:
1854 raise error.Abort(_('either two or three arguments required'))
1854 raise error.Abort(_('either two or three arguments required'))
1855 a = r.ancestor(lookup(rev1), lookup(rev2))
1855 a = r.ancestor(lookup(rev1), lookup(rev2))
1856 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1856 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1857
1857
1858 @command('debugbuilddag',
1858 @command('debugbuilddag',
1859 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1859 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1860 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1860 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1861 ('n', 'new-file', None, _('add new file at each rev'))],
1861 ('n', 'new-file', None, _('add new file at each rev'))],
1862 _('[OPTION]... [TEXT]'))
1862 _('[OPTION]... [TEXT]'))
1863 def debugbuilddag(ui, repo, text=None,
1863 def debugbuilddag(ui, repo, text=None,
1864 mergeable_file=False,
1864 mergeable_file=False,
1865 overwritten_file=False,
1865 overwritten_file=False,
1866 new_file=False):
1866 new_file=False):
1867 """builds a repo with a given DAG from scratch in the current empty repo
1867 """builds a repo with a given DAG from scratch in the current empty repo
1868
1868
1869 The description of the DAG is read from stdin if not given on the
1869 The description of the DAG is read from stdin if not given on the
1870 command line.
1870 command line.
1871
1871
1872 Elements:
1872 Elements:
1873
1873
1874 - "+n" is a linear run of n nodes based on the current default parent
1874 - "+n" is a linear run of n nodes based on the current default parent
1875 - "." is a single node based on the current default parent
1875 - "." is a single node based on the current default parent
1876 - "$" resets the default parent to null (implied at the start);
1876 - "$" resets the default parent to null (implied at the start);
1877 otherwise the default parent is always the last node created
1877 otherwise the default parent is always the last node created
1878 - "<p" sets the default parent to the backref p
1878 - "<p" sets the default parent to the backref p
1879 - "*p" is a fork at parent p, which is a backref
1879 - "*p" is a fork at parent p, which is a backref
1880 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1880 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1881 - "/p2" is a merge of the preceding node and p2
1881 - "/p2" is a merge of the preceding node and p2
1882 - ":tag" defines a local tag for the preceding node
1882 - ":tag" defines a local tag for the preceding node
1883 - "@branch" sets the named branch for subsequent nodes
1883 - "@branch" sets the named branch for subsequent nodes
1884 - "#...\\n" is a comment up to the end of the line
1884 - "#...\\n" is a comment up to the end of the line
1885
1885
1886 Whitespace between the above elements is ignored.
1886 Whitespace between the above elements is ignored.
1887
1887
1888 A backref is either
1888 A backref is either
1889
1889
1890 - a number n, which references the node curr-n, where curr is the current
1890 - a number n, which references the node curr-n, where curr is the current
1891 node, or
1891 node, or
1892 - the name of a local tag you placed earlier using ":tag", or
1892 - the name of a local tag you placed earlier using ":tag", or
1893 - empty to denote the default parent.
1893 - empty to denote the default parent.
1894
1894
1895 All string valued-elements are either strictly alphanumeric, or must
1895 All string valued-elements are either strictly alphanumeric, or must
1896 be enclosed in double quotes ("..."), with "\\" as escape character.
1896 be enclosed in double quotes ("..."), with "\\" as escape character.
1897 """
1897 """
1898
1898
1899 if text is None:
1899 if text is None:
1900 ui.status(_("reading DAG from stdin\n"))
1900 ui.status(_("reading DAG from stdin\n"))
1901 text = ui.fin.read()
1901 text = ui.fin.read()
1902
1902
1903 cl = repo.changelog
1903 cl = repo.changelog
1904 if len(cl) > 0:
1904 if len(cl) > 0:
1905 raise error.Abort(_('repository is not empty'))
1905 raise error.Abort(_('repository is not empty'))
1906
1906
1907 # determine number of revs in DAG
1907 # determine number of revs in DAG
1908 total = 0
1908 total = 0
1909 for type, data in dagparser.parsedag(text):
1909 for type, data in dagparser.parsedag(text):
1910 if type == 'n':
1910 if type == 'n':
1911 total += 1
1911 total += 1
1912
1912
1913 if mergeable_file:
1913 if mergeable_file:
1914 linesperrev = 2
1914 linesperrev = 2
1915 # make a file with k lines per rev
1915 # make a file with k lines per rev
1916 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1916 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1917 initialmergedlines.append("")
1917 initialmergedlines.append("")
1918
1918
1919 tags = []
1919 tags = []
1920
1920
1921 lock = tr = None
1921 lock = tr = None
1922 try:
1922 try:
1923 lock = repo.lock()
1923 lock = repo.lock()
1924 tr = repo.transaction("builddag")
1924 tr = repo.transaction("builddag")
1925
1925
1926 at = -1
1926 at = -1
1927 atbranch = 'default'
1927 atbranch = 'default'
1928 nodeids = []
1928 nodeids = []
1929 id = 0
1929 id = 0
1930 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1930 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1931 for type, data in dagparser.parsedag(text):
1931 for type, data in dagparser.parsedag(text):
1932 if type == 'n':
1932 if type == 'n':
1933 ui.note(('node %s\n' % str(data)))
1933 ui.note(('node %s\n' % str(data)))
1934 id, ps = data
1934 id, ps = data
1935
1935
1936 files = []
1936 files = []
1937 fctxs = {}
1937 fctxs = {}
1938
1938
1939 p2 = None
1939 p2 = None
1940 if mergeable_file:
1940 if mergeable_file:
1941 fn = "mf"
1941 fn = "mf"
1942 p1 = repo[ps[0]]
1942 p1 = repo[ps[0]]
1943 if len(ps) > 1:
1943 if len(ps) > 1:
1944 p2 = repo[ps[1]]
1944 p2 = repo[ps[1]]
1945 pa = p1.ancestor(p2)
1945 pa = p1.ancestor(p2)
1946 base, local, other = [x[fn].data() for x in (pa, p1,
1946 base, local, other = [x[fn].data() for x in (pa, p1,
1947 p2)]
1947 p2)]
1948 m3 = simplemerge.Merge3Text(base, local, other)
1948 m3 = simplemerge.Merge3Text(base, local, other)
1949 ml = [l.strip() for l in m3.merge_lines()]
1949 ml = [l.strip() for l in m3.merge_lines()]
1950 ml.append("")
1950 ml.append("")
1951 elif at > 0:
1951 elif at > 0:
1952 ml = p1[fn].data().split("\n")
1952 ml = p1[fn].data().split("\n")
1953 else:
1953 else:
1954 ml = initialmergedlines
1954 ml = initialmergedlines
1955 ml[id * linesperrev] += " r%i" % id
1955 ml[id * linesperrev] += " r%i" % id
1956 mergedtext = "\n".join(ml)
1956 mergedtext = "\n".join(ml)
1957 files.append(fn)
1957 files.append(fn)
1958 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1958 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1959
1959
1960 if overwritten_file:
1960 if overwritten_file:
1961 fn = "of"
1961 fn = "of"
1962 files.append(fn)
1962 files.append(fn)
1963 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1963 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1964
1964
1965 if new_file:
1965 if new_file:
1966 fn = "nf%i" % id
1966 fn = "nf%i" % id
1967 files.append(fn)
1967 files.append(fn)
1968 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1968 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1969 if len(ps) > 1:
1969 if len(ps) > 1:
1970 if not p2:
1970 if not p2:
1971 p2 = repo[ps[1]]
1971 p2 = repo[ps[1]]
1972 for fn in p2:
1972 for fn in p2:
1973 if fn.startswith("nf"):
1973 if fn.startswith("nf"):
1974 files.append(fn)
1974 files.append(fn)
1975 fctxs[fn] = p2[fn]
1975 fctxs[fn] = p2[fn]
1976
1976
1977 def fctxfn(repo, cx, path):
1977 def fctxfn(repo, cx, path):
1978 return fctxs.get(path)
1978 return fctxs.get(path)
1979
1979
1980 if len(ps) == 0 or ps[0] < 0:
1980 if len(ps) == 0 or ps[0] < 0:
1981 pars = [None, None]
1981 pars = [None, None]
1982 elif len(ps) == 1:
1982 elif len(ps) == 1:
1983 pars = [nodeids[ps[0]], None]
1983 pars = [nodeids[ps[0]], None]
1984 else:
1984 else:
1985 pars = [nodeids[p] for p in ps]
1985 pars = [nodeids[p] for p in ps]
1986 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1986 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1987 date=(id, 0),
1987 date=(id, 0),
1988 user="debugbuilddag",
1988 user="debugbuilddag",
1989 extra={'branch': atbranch})
1989 extra={'branch': atbranch})
1990 nodeid = repo.commitctx(cx)
1990 nodeid = repo.commitctx(cx)
1991 nodeids.append(nodeid)
1991 nodeids.append(nodeid)
1992 at = id
1992 at = id
1993 elif type == 'l':
1993 elif type == 'l':
1994 id, name = data
1994 id, name = data
1995 ui.note(('tag %s\n' % name))
1995 ui.note(('tag %s\n' % name))
1996 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1996 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1997 elif type == 'a':
1997 elif type == 'a':
1998 ui.note(('branch %s\n' % data))
1998 ui.note(('branch %s\n' % data))
1999 atbranch = data
1999 atbranch = data
2000 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2000 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2001 tr.close()
2001 tr.close()
2002
2002
2003 if tags:
2003 if tags:
2004 repo.vfs.write("localtags", "".join(tags))
2004 repo.vfs.write("localtags", "".join(tags))
2005 finally:
2005 finally:
2006 ui.progress(_('building'), None)
2006 ui.progress(_('building'), None)
2007 release(tr, lock)
2007 release(tr, lock)
2008
2008
2009 @command('debugbundle',
2009 @command('debugbundle',
2010 [('a', 'all', None, _('show all details'))],
2010 [('a', 'all', None, _('show all details'))],
2011 _('FILE'),
2011 _('FILE'),
2012 norepo=True)
2012 norepo=True)
2013 def debugbundle(ui, bundlepath, all=None, **opts):
2013 def debugbundle(ui, bundlepath, all=None, **opts):
2014 """lists the contents of a bundle"""
2014 """lists the contents of a bundle"""
2015 f = hg.openpath(ui, bundlepath)
2015 with hg.openpath(ui, bundlepath) as f:
2016 try:
2017 gen = exchange.readbundle(ui, f, bundlepath)
2016 gen = exchange.readbundle(ui, f, bundlepath)
2018 if isinstance(gen, bundle2.unbundle20):
2017 if isinstance(gen, bundle2.unbundle20):
2019 return _debugbundle2(ui, gen, all=all, **opts)
2018 return _debugbundle2(ui, gen, all=all, **opts)
2020 if all:
2019 if all:
2021 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2020 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2022
2021
2023 def showchunks(named):
2022 def showchunks(named):
2024 ui.write("\n%s\n" % named)
2023 ui.write("\n%s\n" % named)
2025 chain = None
2024 chain = None
2026 while True:
2025 while True:
2027 chunkdata = gen.deltachunk(chain)
2026 chunkdata = gen.deltachunk(chain)
2028 if not chunkdata:
2027 if not chunkdata:
2029 break
2028 break
2030 node = chunkdata['node']
2029 node = chunkdata['node']
2031 p1 = chunkdata['p1']
2030 p1 = chunkdata['p1']
2032 p2 = chunkdata['p2']
2031 p2 = chunkdata['p2']
2033 cs = chunkdata['cs']
2032 cs = chunkdata['cs']
2034 deltabase = chunkdata['deltabase']
2033 deltabase = chunkdata['deltabase']
2035 delta = chunkdata['delta']
2034 delta = chunkdata['delta']
2036 ui.write("%s %s %s %s %s %s\n" %
2035 ui.write("%s %s %s %s %s %s\n" %
2037 (hex(node), hex(p1), hex(p2),
2036 (hex(node), hex(p1), hex(p2),
2038 hex(cs), hex(deltabase), len(delta)))
2037 hex(cs), hex(deltabase), len(delta)))
2039 chain = node
2038 chain = node
2040
2039
2041 chunkdata = gen.changelogheader()
2040 chunkdata = gen.changelogheader()
2042 showchunks("changelog")
2041 showchunks("changelog")
2043 chunkdata = gen.manifestheader()
2042 chunkdata = gen.manifestheader()
2044 showchunks("manifest")
2043 showchunks("manifest")
2045 while True:
2044 while True:
2046 chunkdata = gen.filelogheader()
2045 chunkdata = gen.filelogheader()
2047 if not chunkdata:
2046 if not chunkdata:
2048 break
2047 break
2049 fname = chunkdata['filename']
2048 fname = chunkdata['filename']
2050 showchunks(fname)
2049 showchunks(fname)
2051 else:
2050 else:
2052 if isinstance(gen, bundle2.unbundle20):
2051 if isinstance(gen, bundle2.unbundle20):
2053 raise error.Abort(_('use debugbundle2 for this file'))
2052 raise error.Abort(_('use debugbundle2 for this file'))
2054 chunkdata = gen.changelogheader()
2053 chunkdata = gen.changelogheader()
2055 chain = None
2054 chain = None
2056 while True:
2055 while True:
2057 chunkdata = gen.deltachunk(chain)
2056 chunkdata = gen.deltachunk(chain)
2058 if not chunkdata:
2057 if not chunkdata:
2059 break
2058 break
2060 node = chunkdata['node']
2059 node = chunkdata['node']
2061 ui.write("%s\n" % hex(node))
2060 ui.write("%s\n" % hex(node))
2062 chain = node
2061 chain = node
2063 finally:
2064 f.close()
2065
2062
2066 def _debugbundle2(ui, gen, **opts):
2063 def _debugbundle2(ui, gen, **opts):
2067 """lists the contents of a bundle2"""
2064 """lists the contents of a bundle2"""
2068 if not isinstance(gen, bundle2.unbundle20):
2065 if not isinstance(gen, bundle2.unbundle20):
2069 raise error.Abort(_('not a bundle2 file'))
2066 raise error.Abort(_('not a bundle2 file'))
2070 ui.write(('Stream params: %s\n' % repr(gen.params)))
2067 ui.write(('Stream params: %s\n' % repr(gen.params)))
2071 for part in gen.iterparts():
2068 for part in gen.iterparts():
2072 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2069 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2073 if part.type == 'changegroup':
2070 if part.type == 'changegroup':
2074 version = part.params.get('version', '01')
2071 version = part.params.get('version', '01')
2075 cg = changegroup.getunbundler(version, part, 'UN')
2072 cg = changegroup.getunbundler(version, part, 'UN')
2076 chunkdata = cg.changelogheader()
2073 chunkdata = cg.changelogheader()
2077 chain = None
2074 chain = None
2078 while True:
2075 while True:
2079 chunkdata = cg.deltachunk(chain)
2076 chunkdata = cg.deltachunk(chain)
2080 if not chunkdata:
2077 if not chunkdata:
2081 break
2078 break
2082 node = chunkdata['node']
2079 node = chunkdata['node']
2083 ui.write(" %s\n" % hex(node))
2080 ui.write(" %s\n" % hex(node))
2084 chain = node
2081 chain = node
2085
2082
2086 @command('debugcreatestreamclonebundle', [], 'FILE')
2083 @command('debugcreatestreamclonebundle', [], 'FILE')
2087 def debugcreatestreamclonebundle(ui, repo, fname):
2084 def debugcreatestreamclonebundle(ui, repo, fname):
2088 """create a stream clone bundle file
2085 """create a stream clone bundle file
2089
2086
2090 Stream bundles are special bundles that are essentially archives of
2087 Stream bundles are special bundles that are essentially archives of
2091 revlog files. They are commonly used for cloning very quickly.
2088 revlog files. They are commonly used for cloning very quickly.
2092 """
2089 """
2093 requirements, gen = streamclone.generatebundlev1(repo)
2090 requirements, gen = streamclone.generatebundlev1(repo)
2094 changegroup.writechunks(ui, gen, fname)
2091 changegroup.writechunks(ui, gen, fname)
2095
2092
2096 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2093 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2097
2094
2098 @command('debugapplystreamclonebundle', [], 'FILE')
2095 @command('debugapplystreamclonebundle', [], 'FILE')
2099 def debugapplystreamclonebundle(ui, repo, fname):
2096 def debugapplystreamclonebundle(ui, repo, fname):
2100 """apply a stream clone bundle file"""
2097 """apply a stream clone bundle file"""
2101 f = hg.openpath(ui, fname)
2098 f = hg.openpath(ui, fname)
2102 gen = exchange.readbundle(ui, f, fname)
2099 gen = exchange.readbundle(ui, f, fname)
2103 gen.apply(repo)
2100 gen.apply(repo)
2104
2101
2105 @command('debugcheckstate', [], '')
2102 @command('debugcheckstate', [], '')
2106 def debugcheckstate(ui, repo):
2103 def debugcheckstate(ui, repo):
2107 """validate the correctness of the current dirstate"""
2104 """validate the correctness of the current dirstate"""
2108 parent1, parent2 = repo.dirstate.parents()
2105 parent1, parent2 = repo.dirstate.parents()
2109 m1 = repo[parent1].manifest()
2106 m1 = repo[parent1].manifest()
2110 m2 = repo[parent2].manifest()
2107 m2 = repo[parent2].manifest()
2111 errors = 0
2108 errors = 0
2112 for f in repo.dirstate:
2109 for f in repo.dirstate:
2113 state = repo.dirstate[f]
2110 state = repo.dirstate[f]
2114 if state in "nr" and f not in m1:
2111 if state in "nr" and f not in m1:
2115 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2112 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2116 errors += 1
2113 errors += 1
2117 if state in "a" and f in m1:
2114 if state in "a" and f in m1:
2118 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2115 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2119 errors += 1
2116 errors += 1
2120 if state in "m" and f not in m1 and f not in m2:
2117 if state in "m" and f not in m1 and f not in m2:
2121 ui.warn(_("%s in state %s, but not in either manifest\n") %
2118 ui.warn(_("%s in state %s, but not in either manifest\n") %
2122 (f, state))
2119 (f, state))
2123 errors += 1
2120 errors += 1
2124 for f in m1:
2121 for f in m1:
2125 state = repo.dirstate[f]
2122 state = repo.dirstate[f]
2126 if state not in "nrm":
2123 if state not in "nrm":
2127 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2124 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2128 errors += 1
2125 errors += 1
2129 if errors:
2126 if errors:
2130 error = _(".hg/dirstate inconsistent with current parent's manifest")
2127 error = _(".hg/dirstate inconsistent with current parent's manifest")
2131 raise error.Abort(error)
2128 raise error.Abort(error)
2132
2129
2133 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2130 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2134 def debugcommands(ui, cmd='', *args):
2131 def debugcommands(ui, cmd='', *args):
2135 """list all available commands and options"""
2132 """list all available commands and options"""
2136 for cmd, vals in sorted(table.iteritems()):
2133 for cmd, vals in sorted(table.iteritems()):
2137 cmd = cmd.split('|')[0].strip('^')
2134 cmd = cmd.split('|')[0].strip('^')
2138 opts = ', '.join([i[1] for i in vals[1]])
2135 opts = ', '.join([i[1] for i in vals[1]])
2139 ui.write('%s: %s\n' % (cmd, opts))
2136 ui.write('%s: %s\n' % (cmd, opts))
2140
2137
2141 @command('debugcomplete',
2138 @command('debugcomplete',
2142 [('o', 'options', None, _('show the command options'))],
2139 [('o', 'options', None, _('show the command options'))],
2143 _('[-o] CMD'),
2140 _('[-o] CMD'),
2144 norepo=True)
2141 norepo=True)
2145 def debugcomplete(ui, cmd='', **opts):
2142 def debugcomplete(ui, cmd='', **opts):
2146 """returns the completion list associated with the given command"""
2143 """returns the completion list associated with the given command"""
2147
2144
2148 if opts.get('options'):
2145 if opts.get('options'):
2149 options = []
2146 options = []
2150 otables = [globalopts]
2147 otables = [globalopts]
2151 if cmd:
2148 if cmd:
2152 aliases, entry = cmdutil.findcmd(cmd, table, False)
2149 aliases, entry = cmdutil.findcmd(cmd, table, False)
2153 otables.append(entry[1])
2150 otables.append(entry[1])
2154 for t in otables:
2151 for t in otables:
2155 for o in t:
2152 for o in t:
2156 if "(DEPRECATED)" in o[3]:
2153 if "(DEPRECATED)" in o[3]:
2157 continue
2154 continue
2158 if o[0]:
2155 if o[0]:
2159 options.append('-%s' % o[0])
2156 options.append('-%s' % o[0])
2160 options.append('--%s' % o[1])
2157 options.append('--%s' % o[1])
2161 ui.write("%s\n" % "\n".join(options))
2158 ui.write("%s\n" % "\n".join(options))
2162 return
2159 return
2163
2160
2164 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2161 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2165 if ui.verbose:
2162 if ui.verbose:
2166 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2163 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2167 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2164 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2168
2165
2169 @command('debugdag',
2166 @command('debugdag',
2170 [('t', 'tags', None, _('use tags as labels')),
2167 [('t', 'tags', None, _('use tags as labels')),
2171 ('b', 'branches', None, _('annotate with branch names')),
2168 ('b', 'branches', None, _('annotate with branch names')),
2172 ('', 'dots', None, _('use dots for runs')),
2169 ('', 'dots', None, _('use dots for runs')),
2173 ('s', 'spaces', None, _('separate elements by spaces'))],
2170 ('s', 'spaces', None, _('separate elements by spaces'))],
2174 _('[OPTION]... [FILE [REV]...]'),
2171 _('[OPTION]... [FILE [REV]...]'),
2175 optionalrepo=True)
2172 optionalrepo=True)
2176 def debugdag(ui, repo, file_=None, *revs, **opts):
2173 def debugdag(ui, repo, file_=None, *revs, **opts):
2177 """format the changelog or an index DAG as a concise textual description
2174 """format the changelog or an index DAG as a concise textual description
2178
2175
2179 If you pass a revlog index, the revlog's DAG is emitted. If you list
2176 If you pass a revlog index, the revlog's DAG is emitted. If you list
2180 revision numbers, they get labeled in the output as rN.
2177 revision numbers, they get labeled in the output as rN.
2181
2178
2182 Otherwise, the changelog DAG of the current repo is emitted.
2179 Otherwise, the changelog DAG of the current repo is emitted.
2183 """
2180 """
2184 spaces = opts.get('spaces')
2181 spaces = opts.get('spaces')
2185 dots = opts.get('dots')
2182 dots = opts.get('dots')
2186 if file_:
2183 if file_:
2187 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2184 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2188 revs = set((int(r) for r in revs))
2185 revs = set((int(r) for r in revs))
2189 def events():
2186 def events():
2190 for r in rlog:
2187 for r in rlog:
2191 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2188 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2192 if p != -1))
2189 if p != -1))
2193 if r in revs:
2190 if r in revs:
2194 yield 'l', (r, "r%i" % r)
2191 yield 'l', (r, "r%i" % r)
2195 elif repo:
2192 elif repo:
2196 cl = repo.changelog
2193 cl = repo.changelog
2197 tags = opts.get('tags')
2194 tags = opts.get('tags')
2198 branches = opts.get('branches')
2195 branches = opts.get('branches')
2199 if tags:
2196 if tags:
2200 labels = {}
2197 labels = {}
2201 for l, n in repo.tags().items():
2198 for l, n in repo.tags().items():
2202 labels.setdefault(cl.rev(n), []).append(l)
2199 labels.setdefault(cl.rev(n), []).append(l)
2203 def events():
2200 def events():
2204 b = "default"
2201 b = "default"
2205 for r in cl:
2202 for r in cl:
2206 if branches:
2203 if branches:
2207 newb = cl.read(cl.node(r))[5]['branch']
2204 newb = cl.read(cl.node(r))[5]['branch']
2208 if newb != b:
2205 if newb != b:
2209 yield 'a', newb
2206 yield 'a', newb
2210 b = newb
2207 b = newb
2211 yield 'n', (r, list(p for p in cl.parentrevs(r)
2208 yield 'n', (r, list(p for p in cl.parentrevs(r)
2212 if p != -1))
2209 if p != -1))
2213 if tags:
2210 if tags:
2214 ls = labels.get(r)
2211 ls = labels.get(r)
2215 if ls:
2212 if ls:
2216 for l in ls:
2213 for l in ls:
2217 yield 'l', (r, l)
2214 yield 'l', (r, l)
2218 else:
2215 else:
2219 raise error.Abort(_('need repo for changelog dag'))
2216 raise error.Abort(_('need repo for changelog dag'))
2220
2217
2221 for line in dagparser.dagtextlines(events(),
2218 for line in dagparser.dagtextlines(events(),
2222 addspaces=spaces,
2219 addspaces=spaces,
2223 wraplabels=True,
2220 wraplabels=True,
2224 wrapannotations=True,
2221 wrapannotations=True,
2225 wrapnonlinear=dots,
2222 wrapnonlinear=dots,
2226 usedots=dots,
2223 usedots=dots,
2227 maxlinewidth=70):
2224 maxlinewidth=70):
2228 ui.write(line)
2225 ui.write(line)
2229 ui.write("\n")
2226 ui.write("\n")
2230
2227
2231 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2228 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2232 def debugdata(ui, repo, file_, rev=None, **opts):
2229 def debugdata(ui, repo, file_, rev=None, **opts):
2233 """dump the contents of a data file revision"""
2230 """dump the contents of a data file revision"""
2234 if opts.get('changelog') or opts.get('manifest'):
2231 if opts.get('changelog') or opts.get('manifest'):
2235 file_, rev = None, file_
2232 file_, rev = None, file_
2236 elif rev is None:
2233 elif rev is None:
2237 raise error.CommandError('debugdata', _('invalid arguments'))
2234 raise error.CommandError('debugdata', _('invalid arguments'))
2238 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2235 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2239 try:
2236 try:
2240 ui.write(r.revision(r.lookup(rev)))
2237 ui.write(r.revision(r.lookup(rev)))
2241 except KeyError:
2238 except KeyError:
2242 raise error.Abort(_('invalid revision identifier %s') % rev)
2239 raise error.Abort(_('invalid revision identifier %s') % rev)
2243
2240
2244 @command('debugdate',
2241 @command('debugdate',
2245 [('e', 'extended', None, _('try extended date formats'))],
2242 [('e', 'extended', None, _('try extended date formats'))],
2246 _('[-e] DATE [RANGE]'),
2243 _('[-e] DATE [RANGE]'),
2247 norepo=True, optionalrepo=True)
2244 norepo=True, optionalrepo=True)
2248 def debugdate(ui, date, range=None, **opts):
2245 def debugdate(ui, date, range=None, **opts):
2249 """parse and display a date"""
2246 """parse and display a date"""
2250 if opts["extended"]:
2247 if opts["extended"]:
2251 d = util.parsedate(date, util.extendeddateformats)
2248 d = util.parsedate(date, util.extendeddateformats)
2252 else:
2249 else:
2253 d = util.parsedate(date)
2250 d = util.parsedate(date)
2254 ui.write(("internal: %s %s\n") % d)
2251 ui.write(("internal: %s %s\n") % d)
2255 ui.write(("standard: %s\n") % util.datestr(d))
2252 ui.write(("standard: %s\n") % util.datestr(d))
2256 if range:
2253 if range:
2257 m = util.matchdate(range)
2254 m = util.matchdate(range)
2258 ui.write(("match: %s\n") % m(d[0]))
2255 ui.write(("match: %s\n") % m(d[0]))
2259
2256
2260 @command('debugdiscovery',
2257 @command('debugdiscovery',
2261 [('', 'old', None, _('use old-style discovery')),
2258 [('', 'old', None, _('use old-style discovery')),
2262 ('', 'nonheads', None,
2259 ('', 'nonheads', None,
2263 _('use old-style discovery with non-heads included')),
2260 _('use old-style discovery with non-heads included')),
2264 ] + remoteopts,
2261 ] + remoteopts,
2265 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2262 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2266 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2263 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2267 """runs the changeset discovery protocol in isolation"""
2264 """runs the changeset discovery protocol in isolation"""
2268 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2265 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2269 opts.get('branch'))
2266 opts.get('branch'))
2270 remote = hg.peer(repo, opts, remoteurl)
2267 remote = hg.peer(repo, opts, remoteurl)
2271 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2268 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2272
2269
2273 # make sure tests are repeatable
2270 # make sure tests are repeatable
2274 random.seed(12323)
2271 random.seed(12323)
2275
2272
2276 def doit(localheads, remoteheads, remote=remote):
2273 def doit(localheads, remoteheads, remote=remote):
2277 if opts.get('old'):
2274 if opts.get('old'):
2278 if localheads:
2275 if localheads:
2279 raise error.Abort('cannot use localheads with old style '
2276 raise error.Abort('cannot use localheads with old style '
2280 'discovery')
2277 'discovery')
2281 if not util.safehasattr(remote, 'branches'):
2278 if not util.safehasattr(remote, 'branches'):
2282 # enable in-client legacy support
2279 # enable in-client legacy support
2283 remote = localrepo.locallegacypeer(remote.local())
2280 remote = localrepo.locallegacypeer(remote.local())
2284 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2281 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2285 force=True)
2282 force=True)
2286 common = set(common)
2283 common = set(common)
2287 if not opts.get('nonheads'):
2284 if not opts.get('nonheads'):
2288 ui.write(("unpruned common: %s\n") %
2285 ui.write(("unpruned common: %s\n") %
2289 " ".join(sorted(short(n) for n in common)))
2286 " ".join(sorted(short(n) for n in common)))
2290 dag = dagutil.revlogdag(repo.changelog)
2287 dag = dagutil.revlogdag(repo.changelog)
2291 all = dag.ancestorset(dag.internalizeall(common))
2288 all = dag.ancestorset(dag.internalizeall(common))
2292 common = dag.externalizeall(dag.headsetofconnecteds(all))
2289 common = dag.externalizeall(dag.headsetofconnecteds(all))
2293 else:
2290 else:
2294 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2291 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2295 common = set(common)
2292 common = set(common)
2296 rheads = set(hds)
2293 rheads = set(hds)
2297 lheads = set(repo.heads())
2294 lheads = set(repo.heads())
2298 ui.write(("common heads: %s\n") %
2295 ui.write(("common heads: %s\n") %
2299 " ".join(sorted(short(n) for n in common)))
2296 " ".join(sorted(short(n) for n in common)))
2300 if lheads <= common:
2297 if lheads <= common:
2301 ui.write(("local is subset\n"))
2298 ui.write(("local is subset\n"))
2302 elif rheads <= common:
2299 elif rheads <= common:
2303 ui.write(("remote is subset\n"))
2300 ui.write(("remote is subset\n"))
2304
2301
2305 serverlogs = opts.get('serverlog')
2302 serverlogs = opts.get('serverlog')
2306 if serverlogs:
2303 if serverlogs:
2307 for filename in serverlogs:
2304 for filename in serverlogs:
2308 with open(filename, 'r') as logfile:
2305 with open(filename, 'r') as logfile:
2309 line = logfile.readline()
2306 line = logfile.readline()
2310 while line:
2307 while line:
2311 parts = line.strip().split(';')
2308 parts = line.strip().split(';')
2312 op = parts[1]
2309 op = parts[1]
2313 if op == 'cg':
2310 if op == 'cg':
2314 pass
2311 pass
2315 elif op == 'cgss':
2312 elif op == 'cgss':
2316 doit(parts[2].split(' '), parts[3].split(' '))
2313 doit(parts[2].split(' '), parts[3].split(' '))
2317 elif op == 'unb':
2314 elif op == 'unb':
2318 doit(parts[3].split(' '), parts[2].split(' '))
2315 doit(parts[3].split(' '), parts[2].split(' '))
2319 line = logfile.readline()
2316 line = logfile.readline()
2320 else:
2317 else:
2321 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2318 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2322 opts.get('remote_head'))
2319 opts.get('remote_head'))
2323 localrevs = opts.get('local_head')
2320 localrevs = opts.get('local_head')
2324 doit(localrevs, remoterevs)
2321 doit(localrevs, remoterevs)
2325
2322
2326 @command('debugextensions', formatteropts, [], norepo=True)
2323 @command('debugextensions', formatteropts, [], norepo=True)
2327 def debugextensions(ui, **opts):
2324 def debugextensions(ui, **opts):
2328 '''show information about active extensions'''
2325 '''show information about active extensions'''
2329 exts = extensions.extensions(ui)
2326 exts = extensions.extensions(ui)
2330 fm = ui.formatter('debugextensions', opts)
2327 fm = ui.formatter('debugextensions', opts)
2331 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2328 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2332 extsource = extmod.__file__
2329 extsource = extmod.__file__
2333 exttestedwith = getattr(extmod, 'testedwith', None)
2330 exttestedwith = getattr(extmod, 'testedwith', None)
2334 if exttestedwith is not None:
2331 if exttestedwith is not None:
2335 exttestedwith = exttestedwith.split()
2332 exttestedwith = exttestedwith.split()
2336 extbuglink = getattr(extmod, 'buglink', None)
2333 extbuglink = getattr(extmod, 'buglink', None)
2337
2334
2338 fm.startitem()
2335 fm.startitem()
2339
2336
2340 if ui.quiet or ui.verbose:
2337 if ui.quiet or ui.verbose:
2341 fm.write('name', '%s\n', extname)
2338 fm.write('name', '%s\n', extname)
2342 else:
2339 else:
2343 fm.write('name', '%s', extname)
2340 fm.write('name', '%s', extname)
2344 if not exttestedwith:
2341 if not exttestedwith:
2345 fm.plain(_(' (untested!)\n'))
2342 fm.plain(_(' (untested!)\n'))
2346 else:
2343 else:
2347 if exttestedwith == ['internal'] or \
2344 if exttestedwith == ['internal'] or \
2348 util.version() in exttestedwith:
2345 util.version() in exttestedwith:
2349 fm.plain('\n')
2346 fm.plain('\n')
2350 else:
2347 else:
2351 lasttestedversion = exttestedwith[-1]
2348 lasttestedversion = exttestedwith[-1]
2352 fm.plain(' (%s!)\n' % lasttestedversion)
2349 fm.plain(' (%s!)\n' % lasttestedversion)
2353
2350
2354 fm.condwrite(ui.verbose and extsource, 'source',
2351 fm.condwrite(ui.verbose and extsource, 'source',
2355 _(' location: %s\n'), extsource or "")
2352 _(' location: %s\n'), extsource or "")
2356
2353
2357 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2354 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2358 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2355 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2359
2356
2360 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2357 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2361 _(' bug reporting: %s\n'), extbuglink or "")
2358 _(' bug reporting: %s\n'), extbuglink or "")
2362
2359
2363 fm.end()
2360 fm.end()
2364
2361
2365 @command('debugfileset',
2362 @command('debugfileset',
2366 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2363 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2367 _('[-r REV] FILESPEC'))
2364 _('[-r REV] FILESPEC'))
2368 def debugfileset(ui, repo, expr, **opts):
2365 def debugfileset(ui, repo, expr, **opts):
2369 '''parse and apply a fileset specification'''
2366 '''parse and apply a fileset specification'''
2370 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2367 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2371 if ui.verbose:
2368 if ui.verbose:
2372 tree = fileset.parse(expr)
2369 tree = fileset.parse(expr)
2373 ui.note(fileset.prettyformat(tree), "\n")
2370 ui.note(fileset.prettyformat(tree), "\n")
2374
2371
2375 for f in ctx.getfileset(expr):
2372 for f in ctx.getfileset(expr):
2376 ui.write("%s\n" % f)
2373 ui.write("%s\n" % f)
2377
2374
2378 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2375 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2379 def debugfsinfo(ui, path="."):
2376 def debugfsinfo(ui, path="."):
2380 """show information detected about current filesystem"""
2377 """show information detected about current filesystem"""
2381 util.writefile('.debugfsinfo', '')
2378 util.writefile('.debugfsinfo', '')
2382 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2379 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2383 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2380 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2384 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2381 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2385 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2382 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2386 and 'yes' or 'no'))
2383 and 'yes' or 'no'))
2387 os.unlink('.debugfsinfo')
2384 os.unlink('.debugfsinfo')
2388
2385
2389 @command('debuggetbundle',
2386 @command('debuggetbundle',
2390 [('H', 'head', [], _('id of head node'), _('ID')),
2387 [('H', 'head', [], _('id of head node'), _('ID')),
2391 ('C', 'common', [], _('id of common node'), _('ID')),
2388 ('C', 'common', [], _('id of common node'), _('ID')),
2392 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2389 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2393 _('REPO FILE [-H|-C ID]...'),
2390 _('REPO FILE [-H|-C ID]...'),
2394 norepo=True)
2391 norepo=True)
2395 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2392 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2396 """retrieves a bundle from a repo
2393 """retrieves a bundle from a repo
2397
2394
2398 Every ID must be a full-length hex node id string. Saves the bundle to the
2395 Every ID must be a full-length hex node id string. Saves the bundle to the
2399 given file.
2396 given file.
2400 """
2397 """
2401 repo = hg.peer(ui, opts, repopath)
2398 repo = hg.peer(ui, opts, repopath)
2402 if not repo.capable('getbundle'):
2399 if not repo.capable('getbundle'):
2403 raise error.Abort("getbundle() not supported by target repository")
2400 raise error.Abort("getbundle() not supported by target repository")
2404 args = {}
2401 args = {}
2405 if common:
2402 if common:
2406 args['common'] = [bin(s) for s in common]
2403 args['common'] = [bin(s) for s in common]
2407 if head:
2404 if head:
2408 args['heads'] = [bin(s) for s in head]
2405 args['heads'] = [bin(s) for s in head]
2409 # TODO: get desired bundlecaps from command line.
2406 # TODO: get desired bundlecaps from command line.
2410 args['bundlecaps'] = None
2407 args['bundlecaps'] = None
2411 bundle = repo.getbundle('debug', **args)
2408 bundle = repo.getbundle('debug', **args)
2412
2409
2413 bundletype = opts.get('type', 'bzip2').lower()
2410 bundletype = opts.get('type', 'bzip2').lower()
2414 btypes = {'none': 'HG10UN',
2411 btypes = {'none': 'HG10UN',
2415 'bzip2': 'HG10BZ',
2412 'bzip2': 'HG10BZ',
2416 'gzip': 'HG10GZ',
2413 'gzip': 'HG10GZ',
2417 'bundle2': 'HG20'}
2414 'bundle2': 'HG20'}
2418 bundletype = btypes.get(bundletype)
2415 bundletype = btypes.get(bundletype)
2419 if bundletype not in changegroup.bundletypes:
2416 if bundletype not in changegroup.bundletypes:
2420 raise error.Abort(_('unknown bundle type specified with --type'))
2417 raise error.Abort(_('unknown bundle type specified with --type'))
2421 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2418 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2422
2419
2423 @command('debugignore', [], '[FILE]')
2420 @command('debugignore', [], '[FILE]')
2424 def debugignore(ui, repo, *files, **opts):
2421 def debugignore(ui, repo, *files, **opts):
2425 """display the combined ignore pattern and information about ignored files
2422 """display the combined ignore pattern and information about ignored files
2426
2423
2427 With no argument display the combined ignore pattern.
2424 With no argument display the combined ignore pattern.
2428
2425
2429 Given space separated file names, shows if the given file is ignored and
2426 Given space separated file names, shows if the given file is ignored and
2430 if so, show the ignore rule (file and line number) that matched it.
2427 if so, show the ignore rule (file and line number) that matched it.
2431 """
2428 """
2432 ignore = repo.dirstate._ignore
2429 ignore = repo.dirstate._ignore
2433 if not files:
2430 if not files:
2434 # Show all the patterns
2431 # Show all the patterns
2435 includepat = getattr(ignore, 'includepat', None)
2432 includepat = getattr(ignore, 'includepat', None)
2436 if includepat is not None:
2433 if includepat is not None:
2437 ui.write("%s\n" % includepat)
2434 ui.write("%s\n" % includepat)
2438 else:
2435 else:
2439 raise error.Abort(_("no ignore patterns found"))
2436 raise error.Abort(_("no ignore patterns found"))
2440 else:
2437 else:
2441 for f in files:
2438 for f in files:
2442 ignored = None
2439 ignored = None
2443 ignoredata = None
2440 ignoredata = None
2444 if f != '.':
2441 if f != '.':
2445 if ignore(f):
2442 if ignore(f):
2446 ignored = f
2443 ignored = f
2447 ignoredata = repo.dirstate._ignorefileandline(f)
2444 ignoredata = repo.dirstate._ignorefileandline(f)
2448 else:
2445 else:
2449 for p in util.finddirs(f):
2446 for p in util.finddirs(f):
2450 if ignore(p):
2447 if ignore(p):
2451 ignored = p
2448 ignored = p
2452 ignoredata = repo.dirstate._ignorefileandline(p)
2449 ignoredata = repo.dirstate._ignorefileandline(p)
2453 break
2450 break
2454 if ignored:
2451 if ignored:
2455 if ignored == f:
2452 if ignored == f:
2456 ui.write("%s is ignored\n" % f)
2453 ui.write("%s is ignored\n" % f)
2457 else:
2454 else:
2458 ui.write("%s is ignored because of containing folder %s\n"
2455 ui.write("%s is ignored because of containing folder %s\n"
2459 % (f, ignored))
2456 % (f, ignored))
2460 ignorefile, lineno, line = ignoredata
2457 ignorefile, lineno, line = ignoredata
2461 ui.write("(ignore rule in %s, line %d: '%s')\n"
2458 ui.write("(ignore rule in %s, line %d: '%s')\n"
2462 % (ignorefile, lineno, line))
2459 % (ignorefile, lineno, line))
2463 else:
2460 else:
2464 ui.write("%s is not ignored\n" % f)
2461 ui.write("%s is not ignored\n" % f)
2465
2462
2466 @command('debugindex', debugrevlogopts +
2463 @command('debugindex', debugrevlogopts +
2467 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2464 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2468 _('[-f FORMAT] -c|-m|FILE'),
2465 _('[-f FORMAT] -c|-m|FILE'),
2469 optionalrepo=True)
2466 optionalrepo=True)
2470 def debugindex(ui, repo, file_=None, **opts):
2467 def debugindex(ui, repo, file_=None, **opts):
2471 """dump the contents of an index file"""
2468 """dump the contents of an index file"""
2472 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2469 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2473 format = opts.get('format', 0)
2470 format = opts.get('format', 0)
2474 if format not in (0, 1):
2471 if format not in (0, 1):
2475 raise error.Abort(_("unknown format %d") % format)
2472 raise error.Abort(_("unknown format %d") % format)
2476
2473
2477 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2474 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2478 if generaldelta:
2475 if generaldelta:
2479 basehdr = ' delta'
2476 basehdr = ' delta'
2480 else:
2477 else:
2481 basehdr = ' base'
2478 basehdr = ' base'
2482
2479
2483 if ui.debugflag:
2480 if ui.debugflag:
2484 shortfn = hex
2481 shortfn = hex
2485 else:
2482 else:
2486 shortfn = short
2483 shortfn = short
2487
2484
2488 # There might not be anything in r, so have a sane default
2485 # There might not be anything in r, so have a sane default
2489 idlen = 12
2486 idlen = 12
2490 for i in r:
2487 for i in r:
2491 idlen = len(shortfn(r.node(i)))
2488 idlen = len(shortfn(r.node(i)))
2492 break
2489 break
2493
2490
2494 if format == 0:
2491 if format == 0:
2495 ui.write(" rev offset length " + basehdr + " linkrev"
2492 ui.write(" rev offset length " + basehdr + " linkrev"
2496 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2493 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2497 elif format == 1:
2494 elif format == 1:
2498 ui.write(" rev flag offset length"
2495 ui.write(" rev flag offset length"
2499 " size " + basehdr + " link p1 p2"
2496 " size " + basehdr + " link p1 p2"
2500 " %s\n" % "nodeid".rjust(idlen))
2497 " %s\n" % "nodeid".rjust(idlen))
2501
2498
2502 for i in r:
2499 for i in r:
2503 node = r.node(i)
2500 node = r.node(i)
2504 if generaldelta:
2501 if generaldelta:
2505 base = r.deltaparent(i)
2502 base = r.deltaparent(i)
2506 else:
2503 else:
2507 base = r.chainbase(i)
2504 base = r.chainbase(i)
2508 if format == 0:
2505 if format == 0:
2509 try:
2506 try:
2510 pp = r.parents(node)
2507 pp = r.parents(node)
2511 except Exception:
2508 except Exception:
2512 pp = [nullid, nullid]
2509 pp = [nullid, nullid]
2513 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2510 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2514 i, r.start(i), r.length(i), base, r.linkrev(i),
2511 i, r.start(i), r.length(i), base, r.linkrev(i),
2515 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2512 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2516 elif format == 1:
2513 elif format == 1:
2517 pr = r.parentrevs(i)
2514 pr = r.parentrevs(i)
2518 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2515 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2519 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2516 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2520 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2517 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2521
2518
2522 @command('debugindexdot', debugrevlogopts,
2519 @command('debugindexdot', debugrevlogopts,
2523 _('-c|-m|FILE'), optionalrepo=True)
2520 _('-c|-m|FILE'), optionalrepo=True)
2524 def debugindexdot(ui, repo, file_=None, **opts):
2521 def debugindexdot(ui, repo, file_=None, **opts):
2525 """dump an index DAG as a graphviz dot file"""
2522 """dump an index DAG as a graphviz dot file"""
2526 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2523 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2527 ui.write(("digraph G {\n"))
2524 ui.write(("digraph G {\n"))
2528 for i in r:
2525 for i in r:
2529 node = r.node(i)
2526 node = r.node(i)
2530 pp = r.parents(node)
2527 pp = r.parents(node)
2531 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2528 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2532 if pp[1] != nullid:
2529 if pp[1] != nullid:
2533 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2530 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2534 ui.write("}\n")
2531 ui.write("}\n")
2535
2532
2536 @command('debugdeltachain',
2533 @command('debugdeltachain',
2537 debugrevlogopts + formatteropts,
2534 debugrevlogopts + formatteropts,
2538 _('-c|-m|FILE'),
2535 _('-c|-m|FILE'),
2539 optionalrepo=True)
2536 optionalrepo=True)
2540 def debugdeltachain(ui, repo, file_=None, **opts):
2537 def debugdeltachain(ui, repo, file_=None, **opts):
2541 """dump information about delta chains in a revlog
2538 """dump information about delta chains in a revlog
2542
2539
2543 Output can be templatized. Available template keywords are:
2540 Output can be templatized. Available template keywords are:
2544
2541
2545 rev revision number
2542 rev revision number
2546 chainid delta chain identifier (numbered by unique base)
2543 chainid delta chain identifier (numbered by unique base)
2547 chainlen delta chain length to this revision
2544 chainlen delta chain length to this revision
2548 prevrev previous revision in delta chain
2545 prevrev previous revision in delta chain
2549 deltatype role of delta / how it was computed
2546 deltatype role of delta / how it was computed
2550 compsize compressed size of revision
2547 compsize compressed size of revision
2551 uncompsize uncompressed size of revision
2548 uncompsize uncompressed size of revision
2552 chainsize total size of compressed revisions in chain
2549 chainsize total size of compressed revisions in chain
2553 chainratio total chain size divided by uncompressed revision size
2550 chainratio total chain size divided by uncompressed revision size
2554 (new delta chains typically start at ratio 2.00)
2551 (new delta chains typically start at ratio 2.00)
2555 lindist linear distance from base revision in delta chain to end
2552 lindist linear distance from base revision in delta chain to end
2556 of this revision
2553 of this revision
2557 extradist total size of revisions not part of this delta chain from
2554 extradist total size of revisions not part of this delta chain from
2558 base of delta chain to end of this revision; a measurement
2555 base of delta chain to end of this revision; a measurement
2559 of how much extra data we need to read/seek across to read
2556 of how much extra data we need to read/seek across to read
2560 the delta chain for this revision
2557 the delta chain for this revision
2561 extraratio extradist divided by chainsize; another representation of
2558 extraratio extradist divided by chainsize; another representation of
2562 how much unrelated data is needed to load this delta chain
2559 how much unrelated data is needed to load this delta chain
2563 """
2560 """
2564 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2561 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2565 index = r.index
2562 index = r.index
2566 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2563 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2567
2564
2568 def revinfo(rev):
2565 def revinfo(rev):
2569 e = index[rev]
2566 e = index[rev]
2570 compsize = e[1]
2567 compsize = e[1]
2571 uncompsize = e[2]
2568 uncompsize = e[2]
2572 chainsize = 0
2569 chainsize = 0
2573
2570
2574 if generaldelta:
2571 if generaldelta:
2575 if e[3] == e[5]:
2572 if e[3] == e[5]:
2576 deltatype = 'p1'
2573 deltatype = 'p1'
2577 elif e[3] == e[6]:
2574 elif e[3] == e[6]:
2578 deltatype = 'p2'
2575 deltatype = 'p2'
2579 elif e[3] == rev - 1:
2576 elif e[3] == rev - 1:
2580 deltatype = 'prev'
2577 deltatype = 'prev'
2581 elif e[3] == rev:
2578 elif e[3] == rev:
2582 deltatype = 'base'
2579 deltatype = 'base'
2583 else:
2580 else:
2584 deltatype = 'other'
2581 deltatype = 'other'
2585 else:
2582 else:
2586 if e[3] == rev:
2583 if e[3] == rev:
2587 deltatype = 'base'
2584 deltatype = 'base'
2588 else:
2585 else:
2589 deltatype = 'prev'
2586 deltatype = 'prev'
2590
2587
2591 chain = r._deltachain(rev)[0]
2588 chain = r._deltachain(rev)[0]
2592 for iterrev in chain:
2589 for iterrev in chain:
2593 e = index[iterrev]
2590 e = index[iterrev]
2594 chainsize += e[1]
2591 chainsize += e[1]
2595
2592
2596 return compsize, uncompsize, deltatype, chain, chainsize
2593 return compsize, uncompsize, deltatype, chain, chainsize
2597
2594
2598 fm = ui.formatter('debugdeltachain', opts)
2595 fm = ui.formatter('debugdeltachain', opts)
2599
2596
2600 fm.plain(' rev chain# chainlen prev delta '
2597 fm.plain(' rev chain# chainlen prev delta '
2601 'size rawsize chainsize ratio lindist extradist '
2598 'size rawsize chainsize ratio lindist extradist '
2602 'extraratio\n')
2599 'extraratio\n')
2603
2600
2604 chainbases = {}
2601 chainbases = {}
2605 for rev in r:
2602 for rev in r:
2606 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2603 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2607 chainbase = chain[0]
2604 chainbase = chain[0]
2608 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2605 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2609 basestart = r.start(chainbase)
2606 basestart = r.start(chainbase)
2610 revstart = r.start(rev)
2607 revstart = r.start(rev)
2611 lineardist = revstart + comp - basestart
2608 lineardist = revstart + comp - basestart
2612 extradist = lineardist - chainsize
2609 extradist = lineardist - chainsize
2613 try:
2610 try:
2614 prevrev = chain[-2]
2611 prevrev = chain[-2]
2615 except IndexError:
2612 except IndexError:
2616 prevrev = -1
2613 prevrev = -1
2617
2614
2618 chainratio = float(chainsize) / float(uncomp)
2615 chainratio = float(chainsize) / float(uncomp)
2619 extraratio = float(extradist) / float(chainsize)
2616 extraratio = float(extradist) / float(chainsize)
2620
2617
2621 fm.startitem()
2618 fm.startitem()
2622 fm.write('rev chainid chainlen prevrev deltatype compsize '
2619 fm.write('rev chainid chainlen prevrev deltatype compsize '
2623 'uncompsize chainsize chainratio lindist extradist '
2620 'uncompsize chainsize chainratio lindist extradist '
2624 'extraratio',
2621 'extraratio',
2625 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2622 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2626 rev, chainid, len(chain), prevrev, deltatype, comp,
2623 rev, chainid, len(chain), prevrev, deltatype, comp,
2627 uncomp, chainsize, chainratio, lineardist, extradist,
2624 uncomp, chainsize, chainratio, lineardist, extradist,
2628 extraratio,
2625 extraratio,
2629 rev=rev, chainid=chainid, chainlen=len(chain),
2626 rev=rev, chainid=chainid, chainlen=len(chain),
2630 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2627 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2631 uncompsize=uncomp, chainsize=chainsize,
2628 uncompsize=uncomp, chainsize=chainsize,
2632 chainratio=chainratio, lindist=lineardist,
2629 chainratio=chainratio, lindist=lineardist,
2633 extradist=extradist, extraratio=extraratio)
2630 extradist=extradist, extraratio=extraratio)
2634
2631
2635 fm.end()
2632 fm.end()
2636
2633
2637 @command('debuginstall', [], '', norepo=True)
2634 @command('debuginstall', [], '', norepo=True)
2638 def debuginstall(ui):
2635 def debuginstall(ui):
2639 '''test Mercurial installation
2636 '''test Mercurial installation
2640
2637
2641 Returns 0 on success.
2638 Returns 0 on success.
2642 '''
2639 '''
2643
2640
2644 def writetemp(contents):
2641 def writetemp(contents):
2645 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2642 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2646 f = os.fdopen(fd, "wb")
2643 f = os.fdopen(fd, "wb")
2647 f.write(contents)
2644 f.write(contents)
2648 f.close()
2645 f.close()
2649 return name
2646 return name
2650
2647
2651 problems = 0
2648 problems = 0
2652
2649
2653 # encoding
2650 # encoding
2654 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2651 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2655 try:
2652 try:
2656 encoding.fromlocal("test")
2653 encoding.fromlocal("test")
2657 except error.Abort as inst:
2654 except error.Abort as inst:
2658 ui.write(" %s\n" % inst)
2655 ui.write(" %s\n" % inst)
2659 ui.write(_(" (check that your locale is properly set)\n"))
2656 ui.write(_(" (check that your locale is properly set)\n"))
2660 problems += 1
2657 problems += 1
2661
2658
2662 # Python
2659 # Python
2663 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2660 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2664 ui.status(_("checking Python version (%s)\n")
2661 ui.status(_("checking Python version (%s)\n")
2665 % ("%s.%s.%s" % sys.version_info[:3]))
2662 % ("%s.%s.%s" % sys.version_info[:3]))
2666 ui.status(_("checking Python lib (%s)...\n")
2663 ui.status(_("checking Python lib (%s)...\n")
2667 % os.path.dirname(os.__file__))
2664 % os.path.dirname(os.__file__))
2668
2665
2669 # compiled modules
2666 # compiled modules
2670 ui.status(_("checking installed modules (%s)...\n")
2667 ui.status(_("checking installed modules (%s)...\n")
2671 % os.path.dirname(__file__))
2668 % os.path.dirname(__file__))
2672 try:
2669 try:
2673 import bdiff, mpatch, base85, osutil
2670 import bdiff, mpatch, base85, osutil
2674 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2671 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2675 except Exception as inst:
2672 except Exception as inst:
2676 ui.write(" %s\n" % inst)
2673 ui.write(" %s\n" % inst)
2677 ui.write(_(" One or more extensions could not be found"))
2674 ui.write(_(" One or more extensions could not be found"))
2678 ui.write(_(" (check that you compiled the extensions)\n"))
2675 ui.write(_(" (check that you compiled the extensions)\n"))
2679 problems += 1
2676 problems += 1
2680
2677
2681 # templates
2678 # templates
2682 import templater
2679 import templater
2683 p = templater.templatepaths()
2680 p = templater.templatepaths()
2684 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2681 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2685 if p:
2682 if p:
2686 m = templater.templatepath("map-cmdline.default")
2683 m = templater.templatepath("map-cmdline.default")
2687 if m:
2684 if m:
2688 # template found, check if it is working
2685 # template found, check if it is working
2689 try:
2686 try:
2690 templater.templater(m)
2687 templater.templater(m)
2691 except Exception as inst:
2688 except Exception as inst:
2692 ui.write(" %s\n" % inst)
2689 ui.write(" %s\n" % inst)
2693 p = None
2690 p = None
2694 else:
2691 else:
2695 ui.write(_(" template 'default' not found\n"))
2692 ui.write(_(" template 'default' not found\n"))
2696 p = None
2693 p = None
2697 else:
2694 else:
2698 ui.write(_(" no template directories found\n"))
2695 ui.write(_(" no template directories found\n"))
2699 if not p:
2696 if not p:
2700 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2697 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2701 problems += 1
2698 problems += 1
2702
2699
2703 # editor
2700 # editor
2704 ui.status(_("checking commit editor...\n"))
2701 ui.status(_("checking commit editor...\n"))
2705 editor = ui.geteditor()
2702 editor = ui.geteditor()
2706 editor = util.expandpath(editor)
2703 editor = util.expandpath(editor)
2707 cmdpath = util.findexe(shlex.split(editor)[0])
2704 cmdpath = util.findexe(shlex.split(editor)[0])
2708 if not cmdpath:
2705 if not cmdpath:
2709 if editor == 'vi':
2706 if editor == 'vi':
2710 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2707 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2711 ui.write(_(" (specify a commit editor in your configuration"
2708 ui.write(_(" (specify a commit editor in your configuration"
2712 " file)\n"))
2709 " file)\n"))
2713 else:
2710 else:
2714 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2711 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2715 ui.write(_(" (specify a commit editor in your configuration"
2712 ui.write(_(" (specify a commit editor in your configuration"
2716 " file)\n"))
2713 " file)\n"))
2717 problems += 1
2714 problems += 1
2718
2715
2719 # check username
2716 # check username
2720 ui.status(_("checking username...\n"))
2717 ui.status(_("checking username...\n"))
2721 try:
2718 try:
2722 ui.username()
2719 ui.username()
2723 except error.Abort as e:
2720 except error.Abort as e:
2724 ui.write(" %s\n" % e)
2721 ui.write(" %s\n" % e)
2725 ui.write(_(" (specify a username in your configuration file)\n"))
2722 ui.write(_(" (specify a username in your configuration file)\n"))
2726 problems += 1
2723 problems += 1
2727
2724
2728 if not problems:
2725 if not problems:
2729 ui.status(_("no problems detected\n"))
2726 ui.status(_("no problems detected\n"))
2730 else:
2727 else:
2731 ui.write(_("%s problems detected,"
2728 ui.write(_("%s problems detected,"
2732 " please check your install!\n") % problems)
2729 " please check your install!\n") % problems)
2733
2730
2734 return problems
2731 return problems
2735
2732
2736 @command('debugknown', [], _('REPO ID...'), norepo=True)
2733 @command('debugknown', [], _('REPO ID...'), norepo=True)
2737 def debugknown(ui, repopath, *ids, **opts):
2734 def debugknown(ui, repopath, *ids, **opts):
2738 """test whether node ids are known to a repo
2735 """test whether node ids are known to a repo
2739
2736
2740 Every ID must be a full-length hex node id string. Returns a list of 0s
2737 Every ID must be a full-length hex node id string. Returns a list of 0s
2741 and 1s indicating unknown/known.
2738 and 1s indicating unknown/known.
2742 """
2739 """
2743 repo = hg.peer(ui, opts, repopath)
2740 repo = hg.peer(ui, opts, repopath)
2744 if not repo.capable('known'):
2741 if not repo.capable('known'):
2745 raise error.Abort("known() not supported by target repository")
2742 raise error.Abort("known() not supported by target repository")
2746 flags = repo.known([bin(s) for s in ids])
2743 flags = repo.known([bin(s) for s in ids])
2747 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2744 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2748
2745
2749 @command('debuglabelcomplete', [], _('LABEL...'))
2746 @command('debuglabelcomplete', [], _('LABEL...'))
2750 def debuglabelcomplete(ui, repo, *args):
2747 def debuglabelcomplete(ui, repo, *args):
2751 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2748 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2752 debugnamecomplete(ui, repo, *args)
2749 debugnamecomplete(ui, repo, *args)
2753
2750
2754 @command('debugmergestate', [], '')
2751 @command('debugmergestate', [], '')
2755 def debugmergestate(ui, repo, *args):
2752 def debugmergestate(ui, repo, *args):
2756 """print merge state
2753 """print merge state
2757
2754
2758 Use --verbose to print out information about whether v1 or v2 merge state
2755 Use --verbose to print out information about whether v1 or v2 merge state
2759 was chosen."""
2756 was chosen."""
2760 def _hashornull(h):
2757 def _hashornull(h):
2761 if h == nullhex:
2758 if h == nullhex:
2762 return 'null'
2759 return 'null'
2763 else:
2760 else:
2764 return h
2761 return h
2765
2762
2766 def printrecords(version):
2763 def printrecords(version):
2767 ui.write(('* version %s records\n') % version)
2764 ui.write(('* version %s records\n') % version)
2768 if version == 1:
2765 if version == 1:
2769 records = v1records
2766 records = v1records
2770 else:
2767 else:
2771 records = v2records
2768 records = v2records
2772
2769
2773 for rtype, record in records:
2770 for rtype, record in records:
2774 # pretty print some record types
2771 # pretty print some record types
2775 if rtype == 'L':
2772 if rtype == 'L':
2776 ui.write(('local: %s\n') % record)
2773 ui.write(('local: %s\n') % record)
2777 elif rtype == 'O':
2774 elif rtype == 'O':
2778 ui.write(('other: %s\n') % record)
2775 ui.write(('other: %s\n') % record)
2779 elif rtype == 'm':
2776 elif rtype == 'm':
2780 driver, mdstate = record.split('\0', 1)
2777 driver, mdstate = record.split('\0', 1)
2781 ui.write(('merge driver: %s (state "%s")\n')
2778 ui.write(('merge driver: %s (state "%s")\n')
2782 % (driver, mdstate))
2779 % (driver, mdstate))
2783 elif rtype in 'FDC':
2780 elif rtype in 'FDC':
2784 r = record.split('\0')
2781 r = record.split('\0')
2785 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2782 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2786 if version == 1:
2783 if version == 1:
2787 onode = 'not stored in v1 format'
2784 onode = 'not stored in v1 format'
2788 flags = r[7]
2785 flags = r[7]
2789 else:
2786 else:
2790 onode, flags = r[7:9]
2787 onode, flags = r[7:9]
2791 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2788 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2792 % (f, rtype, state, _hashornull(hash)))
2789 % (f, rtype, state, _hashornull(hash)))
2793 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2790 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2794 ui.write((' ancestor path: %s (node %s)\n')
2791 ui.write((' ancestor path: %s (node %s)\n')
2795 % (afile, _hashornull(anode)))
2792 % (afile, _hashornull(anode)))
2796 ui.write((' other path: %s (node %s)\n')
2793 ui.write((' other path: %s (node %s)\n')
2797 % (ofile, _hashornull(onode)))
2794 % (ofile, _hashornull(onode)))
2798 else:
2795 else:
2799 ui.write(('unrecognized entry: %s\t%s\n')
2796 ui.write(('unrecognized entry: %s\t%s\n')
2800 % (rtype, record.replace('\0', '\t')))
2797 % (rtype, record.replace('\0', '\t')))
2801
2798
2802 # Avoid mergestate.read() since it may raise an exception for unsupported
2799 # Avoid mergestate.read() since it may raise an exception for unsupported
2803 # merge state records. We shouldn't be doing this, but this is OK since this
2800 # merge state records. We shouldn't be doing this, but this is OK since this
2804 # command is pretty low-level.
2801 # command is pretty low-level.
2805 ms = mergemod.mergestate(repo)
2802 ms = mergemod.mergestate(repo)
2806
2803
2807 # sort so that reasonable information is on top
2804 # sort so that reasonable information is on top
2808 v1records = ms._readrecordsv1()
2805 v1records = ms._readrecordsv1()
2809 v2records = ms._readrecordsv2()
2806 v2records = ms._readrecordsv2()
2810 order = 'LOm'
2807 order = 'LOm'
2811 def key(r):
2808 def key(r):
2812 idx = order.find(r[0])
2809 idx = order.find(r[0])
2813 if idx == -1:
2810 if idx == -1:
2814 return (1, r[1])
2811 return (1, r[1])
2815 else:
2812 else:
2816 return (0, idx)
2813 return (0, idx)
2817 v1records.sort(key=key)
2814 v1records.sort(key=key)
2818 v2records.sort(key=key)
2815 v2records.sort(key=key)
2819
2816
2820 if not v1records and not v2records:
2817 if not v1records and not v2records:
2821 ui.write(('no merge state found\n'))
2818 ui.write(('no merge state found\n'))
2822 elif not v2records:
2819 elif not v2records:
2823 ui.note(('no version 2 merge state\n'))
2820 ui.note(('no version 2 merge state\n'))
2824 printrecords(1)
2821 printrecords(1)
2825 elif ms._v1v2match(v1records, v2records):
2822 elif ms._v1v2match(v1records, v2records):
2826 ui.note(('v1 and v2 states match: using v2\n'))
2823 ui.note(('v1 and v2 states match: using v2\n'))
2827 printrecords(2)
2824 printrecords(2)
2828 else:
2825 else:
2829 ui.note(('v1 and v2 states mismatch: using v1\n'))
2826 ui.note(('v1 and v2 states mismatch: using v1\n'))
2830 printrecords(1)
2827 printrecords(1)
2831 if ui.verbose:
2828 if ui.verbose:
2832 printrecords(2)
2829 printrecords(2)
2833
2830
2834 @command('debugnamecomplete', [], _('NAME...'))
2831 @command('debugnamecomplete', [], _('NAME...'))
2835 def debugnamecomplete(ui, repo, *args):
2832 def debugnamecomplete(ui, repo, *args):
2836 '''complete "names" - tags, open branch names, bookmark names'''
2833 '''complete "names" - tags, open branch names, bookmark names'''
2837
2834
2838 names = set()
2835 names = set()
2839 # since we previously only listed open branches, we will handle that
2836 # since we previously only listed open branches, we will handle that
2840 # specially (after this for loop)
2837 # specially (after this for loop)
2841 for name, ns in repo.names.iteritems():
2838 for name, ns in repo.names.iteritems():
2842 if name != 'branches':
2839 if name != 'branches':
2843 names.update(ns.listnames(repo))
2840 names.update(ns.listnames(repo))
2844 names.update(tag for (tag, heads, tip, closed)
2841 names.update(tag for (tag, heads, tip, closed)
2845 in repo.branchmap().iterbranches() if not closed)
2842 in repo.branchmap().iterbranches() if not closed)
2846 completions = set()
2843 completions = set()
2847 if not args:
2844 if not args:
2848 args = ['']
2845 args = ['']
2849 for a in args:
2846 for a in args:
2850 completions.update(n for n in names if n.startswith(a))
2847 completions.update(n for n in names if n.startswith(a))
2851 ui.write('\n'.join(sorted(completions)))
2848 ui.write('\n'.join(sorted(completions)))
2852 ui.write('\n')
2849 ui.write('\n')
2853
2850
2854 @command('debuglocks',
2851 @command('debuglocks',
2855 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2852 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2856 ('W', 'force-wlock', None,
2853 ('W', 'force-wlock', None,
2857 _('free the working state lock (DANGEROUS)'))],
2854 _('free the working state lock (DANGEROUS)'))],
2858 _('[OPTION]...'))
2855 _('[OPTION]...'))
2859 def debuglocks(ui, repo, **opts):
2856 def debuglocks(ui, repo, **opts):
2860 """show or modify state of locks
2857 """show or modify state of locks
2861
2858
2862 By default, this command will show which locks are held. This
2859 By default, this command will show which locks are held. This
2863 includes the user and process holding the lock, the amount of time
2860 includes the user and process holding the lock, the amount of time
2864 the lock has been held, and the machine name where the process is
2861 the lock has been held, and the machine name where the process is
2865 running if it's not local.
2862 running if it's not local.
2866
2863
2867 Locks protect the integrity of Mercurial's data, so should be
2864 Locks protect the integrity of Mercurial's data, so should be
2868 treated with care. System crashes or other interruptions may cause
2865 treated with care. System crashes or other interruptions may cause
2869 locks to not be properly released, though Mercurial will usually
2866 locks to not be properly released, though Mercurial will usually
2870 detect and remove such stale locks automatically.
2867 detect and remove such stale locks automatically.
2871
2868
2872 However, detecting stale locks may not always be possible (for
2869 However, detecting stale locks may not always be possible (for
2873 instance, on a shared filesystem). Removing locks may also be
2870 instance, on a shared filesystem). Removing locks may also be
2874 blocked by filesystem permissions.
2871 blocked by filesystem permissions.
2875
2872
2876 Returns 0 if no locks are held.
2873 Returns 0 if no locks are held.
2877
2874
2878 """
2875 """
2879
2876
2880 if opts.get('force_lock'):
2877 if opts.get('force_lock'):
2881 repo.svfs.unlink('lock')
2878 repo.svfs.unlink('lock')
2882 if opts.get('force_wlock'):
2879 if opts.get('force_wlock'):
2883 repo.vfs.unlink('wlock')
2880 repo.vfs.unlink('wlock')
2884 if opts.get('force_lock') or opts.get('force_lock'):
2881 if opts.get('force_lock') or opts.get('force_lock'):
2885 return 0
2882 return 0
2886
2883
2887 now = time.time()
2884 now = time.time()
2888 held = 0
2885 held = 0
2889
2886
2890 def report(vfs, name, method):
2887 def report(vfs, name, method):
2891 # this causes stale locks to get reaped for more accurate reporting
2888 # this causes stale locks to get reaped for more accurate reporting
2892 try:
2889 try:
2893 l = method(False)
2890 l = method(False)
2894 except error.LockHeld:
2891 except error.LockHeld:
2895 l = None
2892 l = None
2896
2893
2897 if l:
2894 if l:
2898 l.release()
2895 l.release()
2899 else:
2896 else:
2900 try:
2897 try:
2901 stat = vfs.lstat(name)
2898 stat = vfs.lstat(name)
2902 age = now - stat.st_mtime
2899 age = now - stat.st_mtime
2903 user = util.username(stat.st_uid)
2900 user = util.username(stat.st_uid)
2904 locker = vfs.readlock(name)
2901 locker = vfs.readlock(name)
2905 if ":" in locker:
2902 if ":" in locker:
2906 host, pid = locker.split(':')
2903 host, pid = locker.split(':')
2907 if host == socket.gethostname():
2904 if host == socket.gethostname():
2908 locker = 'user %s, process %s' % (user, pid)
2905 locker = 'user %s, process %s' % (user, pid)
2909 else:
2906 else:
2910 locker = 'user %s, process %s, host %s' \
2907 locker = 'user %s, process %s, host %s' \
2911 % (user, pid, host)
2908 % (user, pid, host)
2912 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2909 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2913 return 1
2910 return 1
2914 except OSError as e:
2911 except OSError as e:
2915 if e.errno != errno.ENOENT:
2912 if e.errno != errno.ENOENT:
2916 raise
2913 raise
2917
2914
2918 ui.write("%-6s free\n" % (name + ":"))
2915 ui.write("%-6s free\n" % (name + ":"))
2919 return 0
2916 return 0
2920
2917
2921 held += report(repo.svfs, "lock", repo.lock)
2918 held += report(repo.svfs, "lock", repo.lock)
2922 held += report(repo.vfs, "wlock", repo.wlock)
2919 held += report(repo.vfs, "wlock", repo.wlock)
2923
2920
2924 return held
2921 return held
2925
2922
2926 @command('debugobsolete',
2923 @command('debugobsolete',
2927 [('', 'flags', 0, _('markers flag')),
2924 [('', 'flags', 0, _('markers flag')),
2928 ('', 'record-parents', False,
2925 ('', 'record-parents', False,
2929 _('record parent information for the precursor')),
2926 _('record parent information for the precursor')),
2930 ('r', 'rev', [], _('display markers relevant to REV')),
2927 ('r', 'rev', [], _('display markers relevant to REV')),
2931 ] + commitopts2,
2928 ] + commitopts2,
2932 _('[OBSOLETED [REPLACEMENT ...]]'))
2929 _('[OBSOLETED [REPLACEMENT ...]]'))
2933 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2930 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2934 """create arbitrary obsolete marker
2931 """create arbitrary obsolete marker
2935
2932
2936 With no arguments, displays the list of obsolescence markers."""
2933 With no arguments, displays the list of obsolescence markers."""
2937
2934
2938 def parsenodeid(s):
2935 def parsenodeid(s):
2939 try:
2936 try:
2940 # We do not use revsingle/revrange functions here to accept
2937 # We do not use revsingle/revrange functions here to accept
2941 # arbitrary node identifiers, possibly not present in the
2938 # arbitrary node identifiers, possibly not present in the
2942 # local repository.
2939 # local repository.
2943 n = bin(s)
2940 n = bin(s)
2944 if len(n) != len(nullid):
2941 if len(n) != len(nullid):
2945 raise TypeError()
2942 raise TypeError()
2946 return n
2943 return n
2947 except TypeError:
2944 except TypeError:
2948 raise error.Abort('changeset references must be full hexadecimal '
2945 raise error.Abort('changeset references must be full hexadecimal '
2949 'node identifiers')
2946 'node identifiers')
2950
2947
2951 if precursor is not None:
2948 if precursor is not None:
2952 if opts['rev']:
2949 if opts['rev']:
2953 raise error.Abort('cannot select revision when creating marker')
2950 raise error.Abort('cannot select revision when creating marker')
2954 metadata = {}
2951 metadata = {}
2955 metadata['user'] = opts['user'] or ui.username()
2952 metadata['user'] = opts['user'] or ui.username()
2956 succs = tuple(parsenodeid(succ) for succ in successors)
2953 succs = tuple(parsenodeid(succ) for succ in successors)
2957 l = repo.lock()
2954 l = repo.lock()
2958 try:
2955 try:
2959 tr = repo.transaction('debugobsolete')
2956 tr = repo.transaction('debugobsolete')
2960 try:
2957 try:
2961 date = opts.get('date')
2958 date = opts.get('date')
2962 if date:
2959 if date:
2963 date = util.parsedate(date)
2960 date = util.parsedate(date)
2964 else:
2961 else:
2965 date = None
2962 date = None
2966 prec = parsenodeid(precursor)
2963 prec = parsenodeid(precursor)
2967 parents = None
2964 parents = None
2968 if opts['record_parents']:
2965 if opts['record_parents']:
2969 if prec not in repo.unfiltered():
2966 if prec not in repo.unfiltered():
2970 raise error.Abort('cannot used --record-parents on '
2967 raise error.Abort('cannot used --record-parents on '
2971 'unknown changesets')
2968 'unknown changesets')
2972 parents = repo.unfiltered()[prec].parents()
2969 parents = repo.unfiltered()[prec].parents()
2973 parents = tuple(p.node() for p in parents)
2970 parents = tuple(p.node() for p in parents)
2974 repo.obsstore.create(tr, prec, succs, opts['flags'],
2971 repo.obsstore.create(tr, prec, succs, opts['flags'],
2975 parents=parents, date=date,
2972 parents=parents, date=date,
2976 metadata=metadata)
2973 metadata=metadata)
2977 tr.close()
2974 tr.close()
2978 except ValueError as exc:
2975 except ValueError as exc:
2979 raise error.Abort(_('bad obsmarker input: %s') % exc)
2976 raise error.Abort(_('bad obsmarker input: %s') % exc)
2980 finally:
2977 finally:
2981 tr.release()
2978 tr.release()
2982 finally:
2979 finally:
2983 l.release()
2980 l.release()
2984 else:
2981 else:
2985 if opts['rev']:
2982 if opts['rev']:
2986 revs = scmutil.revrange(repo, opts['rev'])
2983 revs = scmutil.revrange(repo, opts['rev'])
2987 nodes = [repo[r].node() for r in revs]
2984 nodes = [repo[r].node() for r in revs]
2988 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2985 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2989 markers.sort(key=lambda x: x._data)
2986 markers.sort(key=lambda x: x._data)
2990 else:
2987 else:
2991 markers = obsolete.getmarkers(repo)
2988 markers = obsolete.getmarkers(repo)
2992
2989
2993 for m in markers:
2990 for m in markers:
2994 cmdutil.showmarker(ui, m)
2991 cmdutil.showmarker(ui, m)
2995
2992
2996 @command('debugpathcomplete',
2993 @command('debugpathcomplete',
2997 [('f', 'full', None, _('complete an entire path')),
2994 [('f', 'full', None, _('complete an entire path')),
2998 ('n', 'normal', None, _('show only normal files')),
2995 ('n', 'normal', None, _('show only normal files')),
2999 ('a', 'added', None, _('show only added files')),
2996 ('a', 'added', None, _('show only added files')),
3000 ('r', 'removed', None, _('show only removed files'))],
2997 ('r', 'removed', None, _('show only removed files'))],
3001 _('FILESPEC...'))
2998 _('FILESPEC...'))
3002 def debugpathcomplete(ui, repo, *specs, **opts):
2999 def debugpathcomplete(ui, repo, *specs, **opts):
3003 '''complete part or all of a tracked path
3000 '''complete part or all of a tracked path
3004
3001
3005 This command supports shells that offer path name completion. It
3002 This command supports shells that offer path name completion. It
3006 currently completes only files already known to the dirstate.
3003 currently completes only files already known to the dirstate.
3007
3004
3008 Completion extends only to the next path segment unless
3005 Completion extends only to the next path segment unless
3009 --full is specified, in which case entire paths are used.'''
3006 --full is specified, in which case entire paths are used.'''
3010
3007
3011 def complete(path, acceptable):
3008 def complete(path, acceptable):
3012 dirstate = repo.dirstate
3009 dirstate = repo.dirstate
3013 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3010 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3014 rootdir = repo.root + os.sep
3011 rootdir = repo.root + os.sep
3015 if spec != repo.root and not spec.startswith(rootdir):
3012 if spec != repo.root and not spec.startswith(rootdir):
3016 return [], []
3013 return [], []
3017 if os.path.isdir(spec):
3014 if os.path.isdir(spec):
3018 spec += '/'
3015 spec += '/'
3019 spec = spec[len(rootdir):]
3016 spec = spec[len(rootdir):]
3020 fixpaths = os.sep != '/'
3017 fixpaths = os.sep != '/'
3021 if fixpaths:
3018 if fixpaths:
3022 spec = spec.replace(os.sep, '/')
3019 spec = spec.replace(os.sep, '/')
3023 speclen = len(spec)
3020 speclen = len(spec)
3024 fullpaths = opts['full']
3021 fullpaths = opts['full']
3025 files, dirs = set(), set()
3022 files, dirs = set(), set()
3026 adddir, addfile = dirs.add, files.add
3023 adddir, addfile = dirs.add, files.add
3027 for f, st in dirstate.iteritems():
3024 for f, st in dirstate.iteritems():
3028 if f.startswith(spec) and st[0] in acceptable:
3025 if f.startswith(spec) and st[0] in acceptable:
3029 if fixpaths:
3026 if fixpaths:
3030 f = f.replace('/', os.sep)
3027 f = f.replace('/', os.sep)
3031 if fullpaths:
3028 if fullpaths:
3032 addfile(f)
3029 addfile(f)
3033 continue
3030 continue
3034 s = f.find(os.sep, speclen)
3031 s = f.find(os.sep, speclen)
3035 if s >= 0:
3032 if s >= 0:
3036 adddir(f[:s])
3033 adddir(f[:s])
3037 else:
3034 else:
3038 addfile(f)
3035 addfile(f)
3039 return files, dirs
3036 return files, dirs
3040
3037
3041 acceptable = ''
3038 acceptable = ''
3042 if opts['normal']:
3039 if opts['normal']:
3043 acceptable += 'nm'
3040 acceptable += 'nm'
3044 if opts['added']:
3041 if opts['added']:
3045 acceptable += 'a'
3042 acceptable += 'a'
3046 if opts['removed']:
3043 if opts['removed']:
3047 acceptable += 'r'
3044 acceptable += 'r'
3048 cwd = repo.getcwd()
3045 cwd = repo.getcwd()
3049 if not specs:
3046 if not specs:
3050 specs = ['.']
3047 specs = ['.']
3051
3048
3052 files, dirs = set(), set()
3049 files, dirs = set(), set()
3053 for spec in specs:
3050 for spec in specs:
3054 f, d = complete(spec, acceptable or 'nmar')
3051 f, d = complete(spec, acceptable or 'nmar')
3055 files.update(f)
3052 files.update(f)
3056 dirs.update(d)
3053 dirs.update(d)
3057 files.update(dirs)
3054 files.update(dirs)
3058 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3055 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3059 ui.write('\n')
3056 ui.write('\n')
3060
3057
3061 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3058 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3062 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3059 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3063 '''access the pushkey key/value protocol
3060 '''access the pushkey key/value protocol
3064
3061
3065 With two args, list the keys in the given namespace.
3062 With two args, list the keys in the given namespace.
3066
3063
3067 With five args, set a key to new if it currently is set to old.
3064 With five args, set a key to new if it currently is set to old.
3068 Reports success or failure.
3065 Reports success or failure.
3069 '''
3066 '''
3070
3067
3071 target = hg.peer(ui, {}, repopath)
3068 target = hg.peer(ui, {}, repopath)
3072 if keyinfo:
3069 if keyinfo:
3073 key, old, new = keyinfo
3070 key, old, new = keyinfo
3074 r = target.pushkey(namespace, key, old, new)
3071 r = target.pushkey(namespace, key, old, new)
3075 ui.status(str(r) + '\n')
3072 ui.status(str(r) + '\n')
3076 return not r
3073 return not r
3077 else:
3074 else:
3078 for k, v in sorted(target.listkeys(namespace).iteritems()):
3075 for k, v in sorted(target.listkeys(namespace).iteritems()):
3079 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3076 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3080 v.encode('string-escape')))
3077 v.encode('string-escape')))
3081
3078
3082 @command('debugpvec', [], _('A B'))
3079 @command('debugpvec', [], _('A B'))
3083 def debugpvec(ui, repo, a, b=None):
3080 def debugpvec(ui, repo, a, b=None):
3084 ca = scmutil.revsingle(repo, a)
3081 ca = scmutil.revsingle(repo, a)
3085 cb = scmutil.revsingle(repo, b)
3082 cb = scmutil.revsingle(repo, b)
3086 pa = pvec.ctxpvec(ca)
3083 pa = pvec.ctxpvec(ca)
3087 pb = pvec.ctxpvec(cb)
3084 pb = pvec.ctxpvec(cb)
3088 if pa == pb:
3085 if pa == pb:
3089 rel = "="
3086 rel = "="
3090 elif pa > pb:
3087 elif pa > pb:
3091 rel = ">"
3088 rel = ">"
3092 elif pa < pb:
3089 elif pa < pb:
3093 rel = "<"
3090 rel = "<"
3094 elif pa | pb:
3091 elif pa | pb:
3095 rel = "|"
3092 rel = "|"
3096 ui.write(_("a: %s\n") % pa)
3093 ui.write(_("a: %s\n") % pa)
3097 ui.write(_("b: %s\n") % pb)
3094 ui.write(_("b: %s\n") % pb)
3098 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3095 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3099 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3096 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3100 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3097 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3101 pa.distance(pb), rel))
3098 pa.distance(pb), rel))
3102
3099
3103 @command('debugrebuilddirstate|debugrebuildstate',
3100 @command('debugrebuilddirstate|debugrebuildstate',
3104 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3101 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3105 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3102 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3106 'the working copy parent')),
3103 'the working copy parent')),
3107 ],
3104 ],
3108 _('[-r REV]'))
3105 _('[-r REV]'))
3109 def debugrebuilddirstate(ui, repo, rev, **opts):
3106 def debugrebuilddirstate(ui, repo, rev, **opts):
3110 """rebuild the dirstate as it would look like for the given revision
3107 """rebuild the dirstate as it would look like for the given revision
3111
3108
3112 If no revision is specified the first current parent will be used.
3109 If no revision is specified the first current parent will be used.
3113
3110
3114 The dirstate will be set to the files of the given revision.
3111 The dirstate will be set to the files of the given revision.
3115 The actual working directory content or existing dirstate
3112 The actual working directory content or existing dirstate
3116 information such as adds or removes is not considered.
3113 information such as adds or removes is not considered.
3117
3114
3118 ``minimal`` will only rebuild the dirstate status for files that claim to be
3115 ``minimal`` will only rebuild the dirstate status for files that claim to be
3119 tracked but are not in the parent manifest, or that exist in the parent
3116 tracked but are not in the parent manifest, or that exist in the parent
3120 manifest but are not in the dirstate. It will not change adds, removes, or
3117 manifest but are not in the dirstate. It will not change adds, removes, or
3121 modified files that are in the working copy parent.
3118 modified files that are in the working copy parent.
3122
3119
3123 One use of this command is to make the next :hg:`status` invocation
3120 One use of this command is to make the next :hg:`status` invocation
3124 check the actual file content.
3121 check the actual file content.
3125 """
3122 """
3126 ctx = scmutil.revsingle(repo, rev)
3123 ctx = scmutil.revsingle(repo, rev)
3127 with repo.wlock():
3124 with repo.wlock():
3128 dirstate = repo.dirstate
3125 dirstate = repo.dirstate
3129 changedfiles = None
3126 changedfiles = None
3130 # See command doc for what minimal does.
3127 # See command doc for what minimal does.
3131 if opts.get('minimal'):
3128 if opts.get('minimal'):
3132 manifestfiles = set(ctx.manifest().keys())
3129 manifestfiles = set(ctx.manifest().keys())
3133 dirstatefiles = set(dirstate)
3130 dirstatefiles = set(dirstate)
3134 manifestonly = manifestfiles - dirstatefiles
3131 manifestonly = manifestfiles - dirstatefiles
3135 dsonly = dirstatefiles - manifestfiles
3132 dsonly = dirstatefiles - manifestfiles
3136 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3133 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3137 changedfiles = manifestonly | dsnotadded
3134 changedfiles = manifestonly | dsnotadded
3138
3135
3139 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3136 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3140
3137
3141 @command('debugrebuildfncache', [], '')
3138 @command('debugrebuildfncache', [], '')
3142 def debugrebuildfncache(ui, repo):
3139 def debugrebuildfncache(ui, repo):
3143 """rebuild the fncache file"""
3140 """rebuild the fncache file"""
3144 repair.rebuildfncache(ui, repo)
3141 repair.rebuildfncache(ui, repo)
3145
3142
3146 @command('debugrename',
3143 @command('debugrename',
3147 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3144 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3148 _('[-r REV] FILE'))
3145 _('[-r REV] FILE'))
3149 def debugrename(ui, repo, file1, *pats, **opts):
3146 def debugrename(ui, repo, file1, *pats, **opts):
3150 """dump rename information"""
3147 """dump rename information"""
3151
3148
3152 ctx = scmutil.revsingle(repo, opts.get('rev'))
3149 ctx = scmutil.revsingle(repo, opts.get('rev'))
3153 m = scmutil.match(ctx, (file1,) + pats, opts)
3150 m = scmutil.match(ctx, (file1,) + pats, opts)
3154 for abs in ctx.walk(m):
3151 for abs in ctx.walk(m):
3155 fctx = ctx[abs]
3152 fctx = ctx[abs]
3156 o = fctx.filelog().renamed(fctx.filenode())
3153 o = fctx.filelog().renamed(fctx.filenode())
3157 rel = m.rel(abs)
3154 rel = m.rel(abs)
3158 if o:
3155 if o:
3159 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3156 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3160 else:
3157 else:
3161 ui.write(_("%s not renamed\n") % rel)
3158 ui.write(_("%s not renamed\n") % rel)
3162
3159
3163 @command('debugrevlog', debugrevlogopts +
3160 @command('debugrevlog', debugrevlogopts +
3164 [('d', 'dump', False, _('dump index data'))],
3161 [('d', 'dump', False, _('dump index data'))],
3165 _('-c|-m|FILE'),
3162 _('-c|-m|FILE'),
3166 optionalrepo=True)
3163 optionalrepo=True)
3167 def debugrevlog(ui, repo, file_=None, **opts):
3164 def debugrevlog(ui, repo, file_=None, **opts):
3168 """show data and statistics about a revlog"""
3165 """show data and statistics about a revlog"""
3169 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3166 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3170
3167
3171 if opts.get("dump"):
3168 if opts.get("dump"):
3172 numrevs = len(r)
3169 numrevs = len(r)
3173 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3170 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3174 " rawsize totalsize compression heads chainlen\n")
3171 " rawsize totalsize compression heads chainlen\n")
3175 ts = 0
3172 ts = 0
3176 heads = set()
3173 heads = set()
3177
3174
3178 for rev in xrange(numrevs):
3175 for rev in xrange(numrevs):
3179 dbase = r.deltaparent(rev)
3176 dbase = r.deltaparent(rev)
3180 if dbase == -1:
3177 if dbase == -1:
3181 dbase = rev
3178 dbase = rev
3182 cbase = r.chainbase(rev)
3179 cbase = r.chainbase(rev)
3183 clen = r.chainlen(rev)
3180 clen = r.chainlen(rev)
3184 p1, p2 = r.parentrevs(rev)
3181 p1, p2 = r.parentrevs(rev)
3185 rs = r.rawsize(rev)
3182 rs = r.rawsize(rev)
3186 ts = ts + rs
3183 ts = ts + rs
3187 heads -= set(r.parentrevs(rev))
3184 heads -= set(r.parentrevs(rev))
3188 heads.add(rev)
3185 heads.add(rev)
3189 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3186 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3190 "%11d %5d %8d\n" %
3187 "%11d %5d %8d\n" %
3191 (rev, p1, p2, r.start(rev), r.end(rev),
3188 (rev, p1, p2, r.start(rev), r.end(rev),
3192 r.start(dbase), r.start(cbase),
3189 r.start(dbase), r.start(cbase),
3193 r.start(p1), r.start(p2),
3190 r.start(p1), r.start(p2),
3194 rs, ts, ts / r.end(rev), len(heads), clen))
3191 rs, ts, ts / r.end(rev), len(heads), clen))
3195 return 0
3192 return 0
3196
3193
3197 v = r.version
3194 v = r.version
3198 format = v & 0xFFFF
3195 format = v & 0xFFFF
3199 flags = []
3196 flags = []
3200 gdelta = False
3197 gdelta = False
3201 if v & revlog.REVLOGNGINLINEDATA:
3198 if v & revlog.REVLOGNGINLINEDATA:
3202 flags.append('inline')
3199 flags.append('inline')
3203 if v & revlog.REVLOGGENERALDELTA:
3200 if v & revlog.REVLOGGENERALDELTA:
3204 gdelta = True
3201 gdelta = True
3205 flags.append('generaldelta')
3202 flags.append('generaldelta')
3206 if not flags:
3203 if not flags:
3207 flags = ['(none)']
3204 flags = ['(none)']
3208
3205
3209 nummerges = 0
3206 nummerges = 0
3210 numfull = 0
3207 numfull = 0
3211 numprev = 0
3208 numprev = 0
3212 nump1 = 0
3209 nump1 = 0
3213 nump2 = 0
3210 nump2 = 0
3214 numother = 0
3211 numother = 0
3215 nump1prev = 0
3212 nump1prev = 0
3216 nump2prev = 0
3213 nump2prev = 0
3217 chainlengths = []
3214 chainlengths = []
3218
3215
3219 datasize = [None, 0, 0L]
3216 datasize = [None, 0, 0L]
3220 fullsize = [None, 0, 0L]
3217 fullsize = [None, 0, 0L]
3221 deltasize = [None, 0, 0L]
3218 deltasize = [None, 0, 0L]
3222
3219
3223 def addsize(size, l):
3220 def addsize(size, l):
3224 if l[0] is None or size < l[0]:
3221 if l[0] is None or size < l[0]:
3225 l[0] = size
3222 l[0] = size
3226 if size > l[1]:
3223 if size > l[1]:
3227 l[1] = size
3224 l[1] = size
3228 l[2] += size
3225 l[2] += size
3229
3226
3230 numrevs = len(r)
3227 numrevs = len(r)
3231 for rev in xrange(numrevs):
3228 for rev in xrange(numrevs):
3232 p1, p2 = r.parentrevs(rev)
3229 p1, p2 = r.parentrevs(rev)
3233 delta = r.deltaparent(rev)
3230 delta = r.deltaparent(rev)
3234 if format > 0:
3231 if format > 0:
3235 addsize(r.rawsize(rev), datasize)
3232 addsize(r.rawsize(rev), datasize)
3236 if p2 != nullrev:
3233 if p2 != nullrev:
3237 nummerges += 1
3234 nummerges += 1
3238 size = r.length(rev)
3235 size = r.length(rev)
3239 if delta == nullrev:
3236 if delta == nullrev:
3240 chainlengths.append(0)
3237 chainlengths.append(0)
3241 numfull += 1
3238 numfull += 1
3242 addsize(size, fullsize)
3239 addsize(size, fullsize)
3243 else:
3240 else:
3244 chainlengths.append(chainlengths[delta] + 1)
3241 chainlengths.append(chainlengths[delta] + 1)
3245 addsize(size, deltasize)
3242 addsize(size, deltasize)
3246 if delta == rev - 1:
3243 if delta == rev - 1:
3247 numprev += 1
3244 numprev += 1
3248 if delta == p1:
3245 if delta == p1:
3249 nump1prev += 1
3246 nump1prev += 1
3250 elif delta == p2:
3247 elif delta == p2:
3251 nump2prev += 1
3248 nump2prev += 1
3252 elif delta == p1:
3249 elif delta == p1:
3253 nump1 += 1
3250 nump1 += 1
3254 elif delta == p2:
3251 elif delta == p2:
3255 nump2 += 1
3252 nump2 += 1
3256 elif delta != nullrev:
3253 elif delta != nullrev:
3257 numother += 1
3254 numother += 1
3258
3255
3259 # Adjust size min value for empty cases
3256 # Adjust size min value for empty cases
3260 for size in (datasize, fullsize, deltasize):
3257 for size in (datasize, fullsize, deltasize):
3261 if size[0] is None:
3258 if size[0] is None:
3262 size[0] = 0
3259 size[0] = 0
3263
3260
3264 numdeltas = numrevs - numfull
3261 numdeltas = numrevs - numfull
3265 numoprev = numprev - nump1prev - nump2prev
3262 numoprev = numprev - nump1prev - nump2prev
3266 totalrawsize = datasize[2]
3263 totalrawsize = datasize[2]
3267 datasize[2] /= numrevs
3264 datasize[2] /= numrevs
3268 fulltotal = fullsize[2]
3265 fulltotal = fullsize[2]
3269 fullsize[2] /= numfull
3266 fullsize[2] /= numfull
3270 deltatotal = deltasize[2]
3267 deltatotal = deltasize[2]
3271 if numrevs - numfull > 0:
3268 if numrevs - numfull > 0:
3272 deltasize[2] /= numrevs - numfull
3269 deltasize[2] /= numrevs - numfull
3273 totalsize = fulltotal + deltatotal
3270 totalsize = fulltotal + deltatotal
3274 avgchainlen = sum(chainlengths) / numrevs
3271 avgchainlen = sum(chainlengths) / numrevs
3275 maxchainlen = max(chainlengths)
3272 maxchainlen = max(chainlengths)
3276 compratio = 1
3273 compratio = 1
3277 if totalsize:
3274 if totalsize:
3278 compratio = totalrawsize / totalsize
3275 compratio = totalrawsize / totalsize
3279
3276
3280 basedfmtstr = '%%%dd\n'
3277 basedfmtstr = '%%%dd\n'
3281 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3278 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3282
3279
3283 def dfmtstr(max):
3280 def dfmtstr(max):
3284 return basedfmtstr % len(str(max))
3281 return basedfmtstr % len(str(max))
3285 def pcfmtstr(max, padding=0):
3282 def pcfmtstr(max, padding=0):
3286 return basepcfmtstr % (len(str(max)), ' ' * padding)
3283 return basepcfmtstr % (len(str(max)), ' ' * padding)
3287
3284
3288 def pcfmt(value, total):
3285 def pcfmt(value, total):
3289 if total:
3286 if total:
3290 return (value, 100 * float(value) / total)
3287 return (value, 100 * float(value) / total)
3291 else:
3288 else:
3292 return value, 100.0
3289 return value, 100.0
3293
3290
3294 ui.write(('format : %d\n') % format)
3291 ui.write(('format : %d\n') % format)
3295 ui.write(('flags : %s\n') % ', '.join(flags))
3292 ui.write(('flags : %s\n') % ', '.join(flags))
3296
3293
3297 ui.write('\n')
3294 ui.write('\n')
3298 fmt = pcfmtstr(totalsize)
3295 fmt = pcfmtstr(totalsize)
3299 fmt2 = dfmtstr(totalsize)
3296 fmt2 = dfmtstr(totalsize)
3300 ui.write(('revisions : ') + fmt2 % numrevs)
3297 ui.write(('revisions : ') + fmt2 % numrevs)
3301 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3298 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3302 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3299 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3303 ui.write(('revisions : ') + fmt2 % numrevs)
3300 ui.write(('revisions : ') + fmt2 % numrevs)
3304 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3301 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3305 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3302 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3306 ui.write(('revision size : ') + fmt2 % totalsize)
3303 ui.write(('revision size : ') + fmt2 % totalsize)
3307 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3304 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3308 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3305 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3309
3306
3310 ui.write('\n')
3307 ui.write('\n')
3311 fmt = dfmtstr(max(avgchainlen, compratio))
3308 fmt = dfmtstr(max(avgchainlen, compratio))
3312 ui.write(('avg chain length : ') + fmt % avgchainlen)
3309 ui.write(('avg chain length : ') + fmt % avgchainlen)
3313 ui.write(('max chain length : ') + fmt % maxchainlen)
3310 ui.write(('max chain length : ') + fmt % maxchainlen)
3314 ui.write(('compression ratio : ') + fmt % compratio)
3311 ui.write(('compression ratio : ') + fmt % compratio)
3315
3312
3316 if format > 0:
3313 if format > 0:
3317 ui.write('\n')
3314 ui.write('\n')
3318 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3315 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3319 % tuple(datasize))
3316 % tuple(datasize))
3320 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3317 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3321 % tuple(fullsize))
3318 % tuple(fullsize))
3322 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3319 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3323 % tuple(deltasize))
3320 % tuple(deltasize))
3324
3321
3325 if numdeltas > 0:
3322 if numdeltas > 0:
3326 ui.write('\n')
3323 ui.write('\n')
3327 fmt = pcfmtstr(numdeltas)
3324 fmt = pcfmtstr(numdeltas)
3328 fmt2 = pcfmtstr(numdeltas, 4)
3325 fmt2 = pcfmtstr(numdeltas, 4)
3329 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3326 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3330 if numprev > 0:
3327 if numprev > 0:
3331 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3328 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3332 numprev))
3329 numprev))
3333 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3330 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3334 numprev))
3331 numprev))
3335 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3332 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3336 numprev))
3333 numprev))
3337 if gdelta:
3334 if gdelta:
3338 ui.write(('deltas against p1 : ')
3335 ui.write(('deltas against p1 : ')
3339 + fmt % pcfmt(nump1, numdeltas))
3336 + fmt % pcfmt(nump1, numdeltas))
3340 ui.write(('deltas against p2 : ')
3337 ui.write(('deltas against p2 : ')
3341 + fmt % pcfmt(nump2, numdeltas))
3338 + fmt % pcfmt(nump2, numdeltas))
3342 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3339 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3343 numdeltas))
3340 numdeltas))
3344
3341
3345 @command('debugrevspec',
3342 @command('debugrevspec',
3346 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3343 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3347 ('REVSPEC'))
3344 ('REVSPEC'))
3348 def debugrevspec(ui, repo, expr, **opts):
3345 def debugrevspec(ui, repo, expr, **opts):
3349 """parse and apply a revision specification
3346 """parse and apply a revision specification
3350
3347
3351 Use --verbose to print the parsed tree before and after aliases
3348 Use --verbose to print the parsed tree before and after aliases
3352 expansion.
3349 expansion.
3353 """
3350 """
3354 if ui.verbose:
3351 if ui.verbose:
3355 tree = revset.parse(expr, lookup=repo.__contains__)
3352 tree = revset.parse(expr, lookup=repo.__contains__)
3356 ui.note(revset.prettyformat(tree), "\n")
3353 ui.note(revset.prettyformat(tree), "\n")
3357 newtree = revset.findaliases(ui, tree)
3354 newtree = revset.findaliases(ui, tree)
3358 if newtree != tree:
3355 if newtree != tree:
3359 ui.note(revset.prettyformat(newtree), "\n")
3356 ui.note(revset.prettyformat(newtree), "\n")
3360 tree = newtree
3357 tree = newtree
3361 newtree = revset.foldconcat(tree)
3358 newtree = revset.foldconcat(tree)
3362 if newtree != tree:
3359 if newtree != tree:
3363 ui.note(revset.prettyformat(newtree), "\n")
3360 ui.note(revset.prettyformat(newtree), "\n")
3364 if opts["optimize"]:
3361 if opts["optimize"]:
3365 weight, optimizedtree = revset.optimize(newtree, True)
3362 weight, optimizedtree = revset.optimize(newtree, True)
3366 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3363 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3367 func = revset.match(ui, expr, repo)
3364 func = revset.match(ui, expr, repo)
3368 revs = func(repo)
3365 revs = func(repo)
3369 if ui.verbose:
3366 if ui.verbose:
3370 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3367 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3371 for c in revs:
3368 for c in revs:
3372 ui.write("%s\n" % c)
3369 ui.write("%s\n" % c)
3373
3370
3374 @command('debugsetparents', [], _('REV1 [REV2]'))
3371 @command('debugsetparents', [], _('REV1 [REV2]'))
3375 def debugsetparents(ui, repo, rev1, rev2=None):
3372 def debugsetparents(ui, repo, rev1, rev2=None):
3376 """manually set the parents of the current working directory
3373 """manually set the parents of the current working directory
3377
3374
3378 This is useful for writing repository conversion tools, but should
3375 This is useful for writing repository conversion tools, but should
3379 be used with care. For example, neither the working directory nor the
3376 be used with care. For example, neither the working directory nor the
3380 dirstate is updated, so file status may be incorrect after running this
3377 dirstate is updated, so file status may be incorrect after running this
3381 command.
3378 command.
3382
3379
3383 Returns 0 on success.
3380 Returns 0 on success.
3384 """
3381 """
3385
3382
3386 r1 = scmutil.revsingle(repo, rev1).node()
3383 r1 = scmutil.revsingle(repo, rev1).node()
3387 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3384 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3388
3385
3389 with repo.wlock():
3386 with repo.wlock():
3390 repo.dirstate.beginparentchange()
3387 repo.dirstate.beginparentchange()
3391 repo.setparents(r1, r2)
3388 repo.setparents(r1, r2)
3392 repo.dirstate.endparentchange()
3389 repo.dirstate.endparentchange()
3393
3390
3394 @command('debugdirstate|debugstate',
3391 @command('debugdirstate|debugstate',
3395 [('', 'nodates', None, _('do not display the saved mtime')),
3392 [('', 'nodates', None, _('do not display the saved mtime')),
3396 ('', 'datesort', None, _('sort by saved mtime'))],
3393 ('', 'datesort', None, _('sort by saved mtime'))],
3397 _('[OPTION]...'))
3394 _('[OPTION]...'))
3398 def debugstate(ui, repo, **opts):
3395 def debugstate(ui, repo, **opts):
3399 """show the contents of the current dirstate"""
3396 """show the contents of the current dirstate"""
3400
3397
3401 nodates = opts.get('nodates')
3398 nodates = opts.get('nodates')
3402 datesort = opts.get('datesort')
3399 datesort = opts.get('datesort')
3403
3400
3404 timestr = ""
3401 timestr = ""
3405 if datesort:
3402 if datesort:
3406 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3403 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3407 else:
3404 else:
3408 keyfunc = None # sort by filename
3405 keyfunc = None # sort by filename
3409 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3406 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3410 if ent[3] == -1:
3407 if ent[3] == -1:
3411 timestr = 'unset '
3408 timestr = 'unset '
3412 elif nodates:
3409 elif nodates:
3413 timestr = 'set '
3410 timestr = 'set '
3414 else:
3411 else:
3415 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3412 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3416 time.localtime(ent[3]))
3413 time.localtime(ent[3]))
3417 if ent[1] & 0o20000:
3414 if ent[1] & 0o20000:
3418 mode = 'lnk'
3415 mode = 'lnk'
3419 else:
3416 else:
3420 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3417 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3421 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3418 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3422 for f in repo.dirstate.copies():
3419 for f in repo.dirstate.copies():
3423 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3420 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3424
3421
3425 @command('debugsub',
3422 @command('debugsub',
3426 [('r', 'rev', '',
3423 [('r', 'rev', '',
3427 _('revision to check'), _('REV'))],
3424 _('revision to check'), _('REV'))],
3428 _('[-r REV] [REV]'))
3425 _('[-r REV] [REV]'))
3429 def debugsub(ui, repo, rev=None):
3426 def debugsub(ui, repo, rev=None):
3430 ctx = scmutil.revsingle(repo, rev, None)
3427 ctx = scmutil.revsingle(repo, rev, None)
3431 for k, v in sorted(ctx.substate.items()):
3428 for k, v in sorted(ctx.substate.items()):
3432 ui.write(('path %s\n') % k)
3429 ui.write(('path %s\n') % k)
3433 ui.write((' source %s\n') % v[0])
3430 ui.write((' source %s\n') % v[0])
3434 ui.write((' revision %s\n') % v[1])
3431 ui.write((' revision %s\n') % v[1])
3435
3432
3436 @command('debugsuccessorssets',
3433 @command('debugsuccessorssets',
3437 [],
3434 [],
3438 _('[REV]'))
3435 _('[REV]'))
3439 def debugsuccessorssets(ui, repo, *revs):
3436 def debugsuccessorssets(ui, repo, *revs):
3440 """show set of successors for revision
3437 """show set of successors for revision
3441
3438
3442 A successors set of changeset A is a consistent group of revisions that
3439 A successors set of changeset A is a consistent group of revisions that
3443 succeed A. It contains non-obsolete changesets only.
3440 succeed A. It contains non-obsolete changesets only.
3444
3441
3445 In most cases a changeset A has a single successors set containing a single
3442 In most cases a changeset A has a single successors set containing a single
3446 successor (changeset A replaced by A').
3443 successor (changeset A replaced by A').
3447
3444
3448 A changeset that is made obsolete with no successors are called "pruned".
3445 A changeset that is made obsolete with no successors are called "pruned".
3449 Such changesets have no successors sets at all.
3446 Such changesets have no successors sets at all.
3450
3447
3451 A changeset that has been "split" will have a successors set containing
3448 A changeset that has been "split" will have a successors set containing
3452 more than one successor.
3449 more than one successor.
3453
3450
3454 A changeset that has been rewritten in multiple different ways is called
3451 A changeset that has been rewritten in multiple different ways is called
3455 "divergent". Such changesets have multiple successor sets (each of which
3452 "divergent". Such changesets have multiple successor sets (each of which
3456 may also be split, i.e. have multiple successors).
3453 may also be split, i.e. have multiple successors).
3457
3454
3458 Results are displayed as follows::
3455 Results are displayed as follows::
3459
3456
3460 <rev1>
3457 <rev1>
3461 <successors-1A>
3458 <successors-1A>
3462 <rev2>
3459 <rev2>
3463 <successors-2A>
3460 <successors-2A>
3464 <successors-2B1> <successors-2B2> <successors-2B3>
3461 <successors-2B1> <successors-2B2> <successors-2B3>
3465
3462
3466 Here rev2 has two possible (i.e. divergent) successors sets. The first
3463 Here rev2 has two possible (i.e. divergent) successors sets. The first
3467 holds one element, whereas the second holds three (i.e. the changeset has
3464 holds one element, whereas the second holds three (i.e. the changeset has
3468 been split).
3465 been split).
3469 """
3466 """
3470 # passed to successorssets caching computation from one call to another
3467 # passed to successorssets caching computation from one call to another
3471 cache = {}
3468 cache = {}
3472 ctx2str = str
3469 ctx2str = str
3473 node2str = short
3470 node2str = short
3474 if ui.debug():
3471 if ui.debug():
3475 def ctx2str(ctx):
3472 def ctx2str(ctx):
3476 return ctx.hex()
3473 return ctx.hex()
3477 node2str = hex
3474 node2str = hex
3478 for rev in scmutil.revrange(repo, revs):
3475 for rev in scmutil.revrange(repo, revs):
3479 ctx = repo[rev]
3476 ctx = repo[rev]
3480 ui.write('%s\n'% ctx2str(ctx))
3477 ui.write('%s\n'% ctx2str(ctx))
3481 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3478 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3482 if succsset:
3479 if succsset:
3483 ui.write(' ')
3480 ui.write(' ')
3484 ui.write(node2str(succsset[0]))
3481 ui.write(node2str(succsset[0]))
3485 for node in succsset[1:]:
3482 for node in succsset[1:]:
3486 ui.write(' ')
3483 ui.write(' ')
3487 ui.write(node2str(node))
3484 ui.write(node2str(node))
3488 ui.write('\n')
3485 ui.write('\n')
3489
3486
3490 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3487 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3491 def debugwalk(ui, repo, *pats, **opts):
3488 def debugwalk(ui, repo, *pats, **opts):
3492 """show how files match on given patterns"""
3489 """show how files match on given patterns"""
3493 m = scmutil.match(repo[None], pats, opts)
3490 m = scmutil.match(repo[None], pats, opts)
3494 items = list(repo.walk(m))
3491 items = list(repo.walk(m))
3495 if not items:
3492 if not items:
3496 return
3493 return
3497 f = lambda fn: fn
3494 f = lambda fn: fn
3498 if ui.configbool('ui', 'slash') and os.sep != '/':
3495 if ui.configbool('ui', 'slash') and os.sep != '/':
3499 f = lambda fn: util.normpath(fn)
3496 f = lambda fn: util.normpath(fn)
3500 fmt = 'f %%-%ds %%-%ds %%s' % (
3497 fmt = 'f %%-%ds %%-%ds %%s' % (
3501 max([len(abs) for abs in items]),
3498 max([len(abs) for abs in items]),
3502 max([len(m.rel(abs)) for abs in items]))
3499 max([len(m.rel(abs)) for abs in items]))
3503 for abs in items:
3500 for abs in items:
3504 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3501 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3505 ui.write("%s\n" % line.rstrip())
3502 ui.write("%s\n" % line.rstrip())
3506
3503
3507 @command('debugwireargs',
3504 @command('debugwireargs',
3508 [('', 'three', '', 'three'),
3505 [('', 'three', '', 'three'),
3509 ('', 'four', '', 'four'),
3506 ('', 'four', '', 'four'),
3510 ('', 'five', '', 'five'),
3507 ('', 'five', '', 'five'),
3511 ] + remoteopts,
3508 ] + remoteopts,
3512 _('REPO [OPTIONS]... [ONE [TWO]]'),
3509 _('REPO [OPTIONS]... [ONE [TWO]]'),
3513 norepo=True)
3510 norepo=True)
3514 def debugwireargs(ui, repopath, *vals, **opts):
3511 def debugwireargs(ui, repopath, *vals, **opts):
3515 repo = hg.peer(ui, opts, repopath)
3512 repo = hg.peer(ui, opts, repopath)
3516 for opt in remoteopts:
3513 for opt in remoteopts:
3517 del opts[opt[1]]
3514 del opts[opt[1]]
3518 args = {}
3515 args = {}
3519 for k, v in opts.iteritems():
3516 for k, v in opts.iteritems():
3520 if v:
3517 if v:
3521 args[k] = v
3518 args[k] = v
3522 # run twice to check that we don't mess up the stream for the next command
3519 # run twice to check that we don't mess up the stream for the next command
3523 res1 = repo.debugwireargs(*vals, **args)
3520 res1 = repo.debugwireargs(*vals, **args)
3524 res2 = repo.debugwireargs(*vals, **args)
3521 res2 = repo.debugwireargs(*vals, **args)
3525 ui.write("%s\n" % res1)
3522 ui.write("%s\n" % res1)
3526 if res1 != res2:
3523 if res1 != res2:
3527 ui.warn("%s\n" % res2)
3524 ui.warn("%s\n" % res2)
3528
3525
3529 @command('^diff',
3526 @command('^diff',
3530 [('r', 'rev', [], _('revision'), _('REV')),
3527 [('r', 'rev', [], _('revision'), _('REV')),
3531 ('c', 'change', '', _('change made by revision'), _('REV'))
3528 ('c', 'change', '', _('change made by revision'), _('REV'))
3532 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3529 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3533 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3530 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3534 inferrepo=True)
3531 inferrepo=True)
3535 def diff(ui, repo, *pats, **opts):
3532 def diff(ui, repo, *pats, **opts):
3536 """diff repository (or selected files)
3533 """diff repository (or selected files)
3537
3534
3538 Show differences between revisions for the specified files.
3535 Show differences between revisions for the specified files.
3539
3536
3540 Differences between files are shown using the unified diff format.
3537 Differences between files are shown using the unified diff format.
3541
3538
3542 .. note::
3539 .. note::
3543
3540
3544 :hg:`diff` may generate unexpected results for merges, as it will
3541 :hg:`diff` may generate unexpected results for merges, as it will
3545 default to comparing against the working directory's first
3542 default to comparing against the working directory's first
3546 parent changeset if no revisions are specified.
3543 parent changeset if no revisions are specified.
3547
3544
3548 When two revision arguments are given, then changes are shown
3545 When two revision arguments are given, then changes are shown
3549 between those revisions. If only one revision is specified then
3546 between those revisions. If only one revision is specified then
3550 that revision is compared to the working directory, and, when no
3547 that revision is compared to the working directory, and, when no
3551 revisions are specified, the working directory files are compared
3548 revisions are specified, the working directory files are compared
3552 to its first parent.
3549 to its first parent.
3553
3550
3554 Alternatively you can specify -c/--change with a revision to see
3551 Alternatively you can specify -c/--change with a revision to see
3555 the changes in that changeset relative to its first parent.
3552 the changes in that changeset relative to its first parent.
3556
3553
3557 Without the -a/--text option, diff will avoid generating diffs of
3554 Without the -a/--text option, diff will avoid generating diffs of
3558 files it detects as binary. With -a, diff will generate a diff
3555 files it detects as binary. With -a, diff will generate a diff
3559 anyway, probably with undesirable results.
3556 anyway, probably with undesirable results.
3560
3557
3561 Use the -g/--git option to generate diffs in the git extended diff
3558 Use the -g/--git option to generate diffs in the git extended diff
3562 format. For more information, read :hg:`help diffs`.
3559 format. For more information, read :hg:`help diffs`.
3563
3560
3564 .. container:: verbose
3561 .. container:: verbose
3565
3562
3566 Examples:
3563 Examples:
3567
3564
3568 - compare a file in the current working directory to its parent::
3565 - compare a file in the current working directory to its parent::
3569
3566
3570 hg diff foo.c
3567 hg diff foo.c
3571
3568
3572 - compare two historical versions of a directory, with rename info::
3569 - compare two historical versions of a directory, with rename info::
3573
3570
3574 hg diff --git -r 1.0:1.2 lib/
3571 hg diff --git -r 1.0:1.2 lib/
3575
3572
3576 - get change stats relative to the last change on some date::
3573 - get change stats relative to the last change on some date::
3577
3574
3578 hg diff --stat -r "date('may 2')"
3575 hg diff --stat -r "date('may 2')"
3579
3576
3580 - diff all newly-added files that contain a keyword::
3577 - diff all newly-added files that contain a keyword::
3581
3578
3582 hg diff "set:added() and grep(GNU)"
3579 hg diff "set:added() and grep(GNU)"
3583
3580
3584 - compare a revision and its parents::
3581 - compare a revision and its parents::
3585
3582
3586 hg diff -c 9353 # compare against first parent
3583 hg diff -c 9353 # compare against first parent
3587 hg diff -r 9353^:9353 # same using revset syntax
3584 hg diff -r 9353^:9353 # same using revset syntax
3588 hg diff -r 9353^2:9353 # compare against the second parent
3585 hg diff -r 9353^2:9353 # compare against the second parent
3589
3586
3590 Returns 0 on success.
3587 Returns 0 on success.
3591 """
3588 """
3592
3589
3593 revs = opts.get('rev')
3590 revs = opts.get('rev')
3594 change = opts.get('change')
3591 change = opts.get('change')
3595 stat = opts.get('stat')
3592 stat = opts.get('stat')
3596 reverse = opts.get('reverse')
3593 reverse = opts.get('reverse')
3597
3594
3598 if revs and change:
3595 if revs and change:
3599 msg = _('cannot specify --rev and --change at the same time')
3596 msg = _('cannot specify --rev and --change at the same time')
3600 raise error.Abort(msg)
3597 raise error.Abort(msg)
3601 elif change:
3598 elif change:
3602 node2 = scmutil.revsingle(repo, change, None).node()
3599 node2 = scmutil.revsingle(repo, change, None).node()
3603 node1 = repo[node2].p1().node()
3600 node1 = repo[node2].p1().node()
3604 else:
3601 else:
3605 node1, node2 = scmutil.revpair(repo, revs)
3602 node1, node2 = scmutil.revpair(repo, revs)
3606
3603
3607 if reverse:
3604 if reverse:
3608 node1, node2 = node2, node1
3605 node1, node2 = node2, node1
3609
3606
3610 diffopts = patch.diffallopts(ui, opts)
3607 diffopts = patch.diffallopts(ui, opts)
3611 m = scmutil.match(repo[node2], pats, opts)
3608 m = scmutil.match(repo[node2], pats, opts)
3612 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3609 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3613 listsubrepos=opts.get('subrepos'),
3610 listsubrepos=opts.get('subrepos'),
3614 root=opts.get('root'))
3611 root=opts.get('root'))
3615
3612
3616 @command('^export',
3613 @command('^export',
3617 [('o', 'output', '',
3614 [('o', 'output', '',
3618 _('print output to file with formatted name'), _('FORMAT')),
3615 _('print output to file with formatted name'), _('FORMAT')),
3619 ('', 'switch-parent', None, _('diff against the second parent')),
3616 ('', 'switch-parent', None, _('diff against the second parent')),
3620 ('r', 'rev', [], _('revisions to export'), _('REV')),
3617 ('r', 'rev', [], _('revisions to export'), _('REV')),
3621 ] + diffopts,
3618 ] + diffopts,
3622 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3619 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3623 def export(ui, repo, *changesets, **opts):
3620 def export(ui, repo, *changesets, **opts):
3624 """dump the header and diffs for one or more changesets
3621 """dump the header and diffs for one or more changesets
3625
3622
3626 Print the changeset header and diffs for one or more revisions.
3623 Print the changeset header and diffs for one or more revisions.
3627 If no revision is given, the parent of the working directory is used.
3624 If no revision is given, the parent of the working directory is used.
3628
3625
3629 The information shown in the changeset header is: author, date,
3626 The information shown in the changeset header is: author, date,
3630 branch name (if non-default), changeset hash, parent(s) and commit
3627 branch name (if non-default), changeset hash, parent(s) and commit
3631 comment.
3628 comment.
3632
3629
3633 .. note::
3630 .. note::
3634
3631
3635 :hg:`export` may generate unexpected diff output for merge
3632 :hg:`export` may generate unexpected diff output for merge
3636 changesets, as it will compare the merge changeset against its
3633 changesets, as it will compare the merge changeset against its
3637 first parent only.
3634 first parent only.
3638
3635
3639 Output may be to a file, in which case the name of the file is
3636 Output may be to a file, in which case the name of the file is
3640 given using a format string. The formatting rules are as follows:
3637 given using a format string. The formatting rules are as follows:
3641
3638
3642 :``%%``: literal "%" character
3639 :``%%``: literal "%" character
3643 :``%H``: changeset hash (40 hexadecimal digits)
3640 :``%H``: changeset hash (40 hexadecimal digits)
3644 :``%N``: number of patches being generated
3641 :``%N``: number of patches being generated
3645 :``%R``: changeset revision number
3642 :``%R``: changeset revision number
3646 :``%b``: basename of the exporting repository
3643 :``%b``: basename of the exporting repository
3647 :``%h``: short-form changeset hash (12 hexadecimal digits)
3644 :``%h``: short-form changeset hash (12 hexadecimal digits)
3648 :``%m``: first line of the commit message (only alphanumeric characters)
3645 :``%m``: first line of the commit message (only alphanumeric characters)
3649 :``%n``: zero-padded sequence number, starting at 1
3646 :``%n``: zero-padded sequence number, starting at 1
3650 :``%r``: zero-padded changeset revision number
3647 :``%r``: zero-padded changeset revision number
3651
3648
3652 Without the -a/--text option, export will avoid generating diffs
3649 Without the -a/--text option, export will avoid generating diffs
3653 of files it detects as binary. With -a, export will generate a
3650 of files it detects as binary. With -a, export will generate a
3654 diff anyway, probably with undesirable results.
3651 diff anyway, probably with undesirable results.
3655
3652
3656 Use the -g/--git option to generate diffs in the git extended diff
3653 Use the -g/--git option to generate diffs in the git extended diff
3657 format. See :hg:`help diffs` for more information.
3654 format. See :hg:`help diffs` for more information.
3658
3655
3659 With the --switch-parent option, the diff will be against the
3656 With the --switch-parent option, the diff will be against the
3660 second parent. It can be useful to review a merge.
3657 second parent. It can be useful to review a merge.
3661
3658
3662 .. container:: verbose
3659 .. container:: verbose
3663
3660
3664 Examples:
3661 Examples:
3665
3662
3666 - use export and import to transplant a bugfix to the current
3663 - use export and import to transplant a bugfix to the current
3667 branch::
3664 branch::
3668
3665
3669 hg export -r 9353 | hg import -
3666 hg export -r 9353 | hg import -
3670
3667
3671 - export all the changesets between two revisions to a file with
3668 - export all the changesets between two revisions to a file with
3672 rename information::
3669 rename information::
3673
3670
3674 hg export --git -r 123:150 > changes.txt
3671 hg export --git -r 123:150 > changes.txt
3675
3672
3676 - split outgoing changes into a series of patches with
3673 - split outgoing changes into a series of patches with
3677 descriptive names::
3674 descriptive names::
3678
3675
3679 hg export -r "outgoing()" -o "%n-%m.patch"
3676 hg export -r "outgoing()" -o "%n-%m.patch"
3680
3677
3681 Returns 0 on success.
3678 Returns 0 on success.
3682 """
3679 """
3683 changesets += tuple(opts.get('rev', []))
3680 changesets += tuple(opts.get('rev', []))
3684 if not changesets:
3681 if not changesets:
3685 changesets = ['.']
3682 changesets = ['.']
3686 revs = scmutil.revrange(repo, changesets)
3683 revs = scmutil.revrange(repo, changesets)
3687 if not revs:
3684 if not revs:
3688 raise error.Abort(_("export requires at least one changeset"))
3685 raise error.Abort(_("export requires at least one changeset"))
3689 if len(revs) > 1:
3686 if len(revs) > 1:
3690 ui.note(_('exporting patches:\n'))
3687 ui.note(_('exporting patches:\n'))
3691 else:
3688 else:
3692 ui.note(_('exporting patch:\n'))
3689 ui.note(_('exporting patch:\n'))
3693 cmdutil.export(repo, revs, template=opts.get('output'),
3690 cmdutil.export(repo, revs, template=opts.get('output'),
3694 switch_parent=opts.get('switch_parent'),
3691 switch_parent=opts.get('switch_parent'),
3695 opts=patch.diffallopts(ui, opts))
3692 opts=patch.diffallopts(ui, opts))
3696
3693
3697 @command('files',
3694 @command('files',
3698 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3695 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3699 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3696 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3700 ] + walkopts + formatteropts + subrepoopts,
3697 ] + walkopts + formatteropts + subrepoopts,
3701 _('[OPTION]... [PATTERN]...'))
3698 _('[OPTION]... [PATTERN]...'))
3702 def files(ui, repo, *pats, **opts):
3699 def files(ui, repo, *pats, **opts):
3703 """list tracked files
3700 """list tracked files
3704
3701
3705 Print files under Mercurial control in the working directory or
3702 Print files under Mercurial control in the working directory or
3706 specified revision whose names match the given patterns (excluding
3703 specified revision whose names match the given patterns (excluding
3707 removed files).
3704 removed files).
3708
3705
3709 If no patterns are given to match, this command prints the names
3706 If no patterns are given to match, this command prints the names
3710 of all files under Mercurial control in the working directory.
3707 of all files under Mercurial control in the working directory.
3711
3708
3712 .. container:: verbose
3709 .. container:: verbose
3713
3710
3714 Examples:
3711 Examples:
3715
3712
3716 - list all files under the current directory::
3713 - list all files under the current directory::
3717
3714
3718 hg files .
3715 hg files .
3719
3716
3720 - shows sizes and flags for current revision::
3717 - shows sizes and flags for current revision::
3721
3718
3722 hg files -vr .
3719 hg files -vr .
3723
3720
3724 - list all files named README::
3721 - list all files named README::
3725
3722
3726 hg files -I "**/README"
3723 hg files -I "**/README"
3727
3724
3728 - list all binary files::
3725 - list all binary files::
3729
3726
3730 hg files "set:binary()"
3727 hg files "set:binary()"
3731
3728
3732 - find files containing a regular expression::
3729 - find files containing a regular expression::
3733
3730
3734 hg files "set:grep('bob')"
3731 hg files "set:grep('bob')"
3735
3732
3736 - search tracked file contents with xargs and grep::
3733 - search tracked file contents with xargs and grep::
3737
3734
3738 hg files -0 | xargs -0 grep foo
3735 hg files -0 | xargs -0 grep foo
3739
3736
3740 See :hg:`help patterns` and :hg:`help filesets` for more information
3737 See :hg:`help patterns` and :hg:`help filesets` for more information
3741 on specifying file patterns.
3738 on specifying file patterns.
3742
3739
3743 Returns 0 if a match is found, 1 otherwise.
3740 Returns 0 if a match is found, 1 otherwise.
3744
3741
3745 """
3742 """
3746 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3743 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3747
3744
3748 end = '\n'
3745 end = '\n'
3749 if opts.get('print0'):
3746 if opts.get('print0'):
3750 end = '\0'
3747 end = '\0'
3751 fm = ui.formatter('files', opts)
3748 fm = ui.formatter('files', opts)
3752 fmt = '%s' + end
3749 fmt = '%s' + end
3753
3750
3754 m = scmutil.match(ctx, pats, opts)
3751 m = scmutil.match(ctx, pats, opts)
3755 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3752 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3756
3753
3757 fm.end()
3754 fm.end()
3758
3755
3759 return ret
3756 return ret
3760
3757
3761 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3758 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3762 def forget(ui, repo, *pats, **opts):
3759 def forget(ui, repo, *pats, **opts):
3763 """forget the specified files on the next commit
3760 """forget the specified files on the next commit
3764
3761
3765 Mark the specified files so they will no longer be tracked
3762 Mark the specified files so they will no longer be tracked
3766 after the next commit.
3763 after the next commit.
3767
3764
3768 This only removes files from the current branch, not from the
3765 This only removes files from the current branch, not from the
3769 entire project history, and it does not delete them from the
3766 entire project history, and it does not delete them from the
3770 working directory.
3767 working directory.
3771
3768
3772 To delete the file from the working directory, see :hg:`remove`.
3769 To delete the file from the working directory, see :hg:`remove`.
3773
3770
3774 To undo a forget before the next commit, see :hg:`add`.
3771 To undo a forget before the next commit, see :hg:`add`.
3775
3772
3776 .. container:: verbose
3773 .. container:: verbose
3777
3774
3778 Examples:
3775 Examples:
3779
3776
3780 - forget newly-added binary files::
3777 - forget newly-added binary files::
3781
3778
3782 hg forget "set:added() and binary()"
3779 hg forget "set:added() and binary()"
3783
3780
3784 - forget files that would be excluded by .hgignore::
3781 - forget files that would be excluded by .hgignore::
3785
3782
3786 hg forget "set:hgignore()"
3783 hg forget "set:hgignore()"
3787
3784
3788 Returns 0 on success.
3785 Returns 0 on success.
3789 """
3786 """
3790
3787
3791 if not pats:
3788 if not pats:
3792 raise error.Abort(_('no files specified'))
3789 raise error.Abort(_('no files specified'))
3793
3790
3794 m = scmutil.match(repo[None], pats, opts)
3791 m = scmutil.match(repo[None], pats, opts)
3795 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3792 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3796 return rejected and 1 or 0
3793 return rejected and 1 or 0
3797
3794
3798 @command(
3795 @command(
3799 'graft',
3796 'graft',
3800 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3797 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3801 ('c', 'continue', False, _('resume interrupted graft')),
3798 ('c', 'continue', False, _('resume interrupted graft')),
3802 ('e', 'edit', False, _('invoke editor on commit messages')),
3799 ('e', 'edit', False, _('invoke editor on commit messages')),
3803 ('', 'log', None, _('append graft info to log message')),
3800 ('', 'log', None, _('append graft info to log message')),
3804 ('f', 'force', False, _('force graft')),
3801 ('f', 'force', False, _('force graft')),
3805 ('D', 'currentdate', False,
3802 ('D', 'currentdate', False,
3806 _('record the current date as commit date')),
3803 _('record the current date as commit date')),
3807 ('U', 'currentuser', False,
3804 ('U', 'currentuser', False,
3808 _('record the current user as committer'), _('DATE'))]
3805 _('record the current user as committer'), _('DATE'))]
3809 + commitopts2 + mergetoolopts + dryrunopts,
3806 + commitopts2 + mergetoolopts + dryrunopts,
3810 _('[OPTION]... [-r] REV...'))
3807 _('[OPTION]... [-r] REV...'))
3811 def graft(ui, repo, *revs, **opts):
3808 def graft(ui, repo, *revs, **opts):
3812 '''copy changes from other branches onto the current branch
3809 '''copy changes from other branches onto the current branch
3813
3810
3814 This command uses Mercurial's merge logic to copy individual
3811 This command uses Mercurial's merge logic to copy individual
3815 changes from other branches without merging branches in the
3812 changes from other branches without merging branches in the
3816 history graph. This is sometimes known as 'backporting' or
3813 history graph. This is sometimes known as 'backporting' or
3817 'cherry-picking'. By default, graft will copy user, date, and
3814 'cherry-picking'. By default, graft will copy user, date, and
3818 description from the source changesets.
3815 description from the source changesets.
3819
3816
3820 Changesets that are ancestors of the current revision, that have
3817 Changesets that are ancestors of the current revision, that have
3821 already been grafted, or that are merges will be skipped.
3818 already been grafted, or that are merges will be skipped.
3822
3819
3823 If --log is specified, log messages will have a comment appended
3820 If --log is specified, log messages will have a comment appended
3824 of the form::
3821 of the form::
3825
3822
3826 (grafted from CHANGESETHASH)
3823 (grafted from CHANGESETHASH)
3827
3824
3828 If --force is specified, revisions will be grafted even if they
3825 If --force is specified, revisions will be grafted even if they
3829 are already ancestors of or have been grafted to the destination.
3826 are already ancestors of or have been grafted to the destination.
3830 This is useful when the revisions have since been backed out.
3827 This is useful when the revisions have since been backed out.
3831
3828
3832 If a graft merge results in conflicts, the graft process is
3829 If a graft merge results in conflicts, the graft process is
3833 interrupted so that the current merge can be manually resolved.
3830 interrupted so that the current merge can be manually resolved.
3834 Once all conflicts are addressed, the graft process can be
3831 Once all conflicts are addressed, the graft process can be
3835 continued with the -c/--continue option.
3832 continued with the -c/--continue option.
3836
3833
3837 .. note::
3834 .. note::
3838
3835
3839 The -c/--continue option does not reapply earlier options, except
3836 The -c/--continue option does not reapply earlier options, except
3840 for --force.
3837 for --force.
3841
3838
3842 .. container:: verbose
3839 .. container:: verbose
3843
3840
3844 Examples:
3841 Examples:
3845
3842
3846 - copy a single change to the stable branch and edit its description::
3843 - copy a single change to the stable branch and edit its description::
3847
3844
3848 hg update stable
3845 hg update stable
3849 hg graft --edit 9393
3846 hg graft --edit 9393
3850
3847
3851 - graft a range of changesets with one exception, updating dates::
3848 - graft a range of changesets with one exception, updating dates::
3852
3849
3853 hg graft -D "2085::2093 and not 2091"
3850 hg graft -D "2085::2093 and not 2091"
3854
3851
3855 - continue a graft after resolving conflicts::
3852 - continue a graft after resolving conflicts::
3856
3853
3857 hg graft -c
3854 hg graft -c
3858
3855
3859 - show the source of a grafted changeset::
3856 - show the source of a grafted changeset::
3860
3857
3861 hg log --debug -r .
3858 hg log --debug -r .
3862
3859
3863 - show revisions sorted by date::
3860 - show revisions sorted by date::
3864
3861
3865 hg log -r 'sort(all(), date)'
3862 hg log -r 'sort(all(), date)'
3866
3863
3867 See :hg:`help revisions` and :hg:`help revsets` for more about
3864 See :hg:`help revisions` and :hg:`help revsets` for more about
3868 specifying revisions.
3865 specifying revisions.
3869
3866
3870 Returns 0 on successful completion.
3867 Returns 0 on successful completion.
3871 '''
3868 '''
3872 with repo.wlock():
3869 with repo.wlock():
3873 return _dograft(ui, repo, *revs, **opts)
3870 return _dograft(ui, repo, *revs, **opts)
3874
3871
3875 def _dograft(ui, repo, *revs, **opts):
3872 def _dograft(ui, repo, *revs, **opts):
3876 revs = list(revs)
3873 revs = list(revs)
3877 revs.extend(opts['rev'])
3874 revs.extend(opts['rev'])
3878
3875
3879 if not opts.get('user') and opts.get('currentuser'):
3876 if not opts.get('user') and opts.get('currentuser'):
3880 opts['user'] = ui.username()
3877 opts['user'] = ui.username()
3881 if not opts.get('date') and opts.get('currentdate'):
3878 if not opts.get('date') and opts.get('currentdate'):
3882 opts['date'] = "%d %d" % util.makedate()
3879 opts['date'] = "%d %d" % util.makedate()
3883
3880
3884 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3881 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3885
3882
3886 cont = False
3883 cont = False
3887 if opts['continue']:
3884 if opts['continue']:
3888 cont = True
3885 cont = True
3889 if revs:
3886 if revs:
3890 raise error.Abort(_("can't specify --continue and revisions"))
3887 raise error.Abort(_("can't specify --continue and revisions"))
3891 # read in unfinished revisions
3888 # read in unfinished revisions
3892 try:
3889 try:
3893 nodes = repo.vfs.read('graftstate').splitlines()
3890 nodes = repo.vfs.read('graftstate').splitlines()
3894 revs = [repo[node].rev() for node in nodes]
3891 revs = [repo[node].rev() for node in nodes]
3895 except IOError as inst:
3892 except IOError as inst:
3896 if inst.errno != errno.ENOENT:
3893 if inst.errno != errno.ENOENT:
3897 raise
3894 raise
3898 raise error.Abort(_("no graft state found, can't continue"))
3895 raise error.Abort(_("no graft state found, can't continue"))
3899 else:
3896 else:
3900 cmdutil.checkunfinished(repo)
3897 cmdutil.checkunfinished(repo)
3901 cmdutil.bailifchanged(repo)
3898 cmdutil.bailifchanged(repo)
3902 if not revs:
3899 if not revs:
3903 raise error.Abort(_('no revisions specified'))
3900 raise error.Abort(_('no revisions specified'))
3904 revs = scmutil.revrange(repo, revs)
3901 revs = scmutil.revrange(repo, revs)
3905
3902
3906 skipped = set()
3903 skipped = set()
3907 # check for merges
3904 # check for merges
3908 for rev in repo.revs('%ld and merge()', revs):
3905 for rev in repo.revs('%ld and merge()', revs):
3909 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3906 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3910 skipped.add(rev)
3907 skipped.add(rev)
3911 revs = [r for r in revs if r not in skipped]
3908 revs = [r for r in revs if r not in skipped]
3912 if not revs:
3909 if not revs:
3913 return -1
3910 return -1
3914
3911
3915 # Don't check in the --continue case, in effect retaining --force across
3912 # Don't check in the --continue case, in effect retaining --force across
3916 # --continues. That's because without --force, any revisions we decided to
3913 # --continues. That's because without --force, any revisions we decided to
3917 # skip would have been filtered out here, so they wouldn't have made their
3914 # skip would have been filtered out here, so they wouldn't have made their
3918 # way to the graftstate. With --force, any revisions we would have otherwise
3915 # way to the graftstate. With --force, any revisions we would have otherwise
3919 # skipped would not have been filtered out, and if they hadn't been applied
3916 # skipped would not have been filtered out, and if they hadn't been applied
3920 # already, they'd have been in the graftstate.
3917 # already, they'd have been in the graftstate.
3921 if not (cont or opts.get('force')):
3918 if not (cont or opts.get('force')):
3922 # check for ancestors of dest branch
3919 # check for ancestors of dest branch
3923 crev = repo['.'].rev()
3920 crev = repo['.'].rev()
3924 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3921 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3925 # Cannot use x.remove(y) on smart set, this has to be a list.
3922 # Cannot use x.remove(y) on smart set, this has to be a list.
3926 # XXX make this lazy in the future
3923 # XXX make this lazy in the future
3927 revs = list(revs)
3924 revs = list(revs)
3928 # don't mutate while iterating, create a copy
3925 # don't mutate while iterating, create a copy
3929 for rev in list(revs):
3926 for rev in list(revs):
3930 if rev in ancestors:
3927 if rev in ancestors:
3931 ui.warn(_('skipping ancestor revision %d:%s\n') %
3928 ui.warn(_('skipping ancestor revision %d:%s\n') %
3932 (rev, repo[rev]))
3929 (rev, repo[rev]))
3933 # XXX remove on list is slow
3930 # XXX remove on list is slow
3934 revs.remove(rev)
3931 revs.remove(rev)
3935 if not revs:
3932 if not revs:
3936 return -1
3933 return -1
3937
3934
3938 # analyze revs for earlier grafts
3935 # analyze revs for earlier grafts
3939 ids = {}
3936 ids = {}
3940 for ctx in repo.set("%ld", revs):
3937 for ctx in repo.set("%ld", revs):
3941 ids[ctx.hex()] = ctx.rev()
3938 ids[ctx.hex()] = ctx.rev()
3942 n = ctx.extra().get('source')
3939 n = ctx.extra().get('source')
3943 if n:
3940 if n:
3944 ids[n] = ctx.rev()
3941 ids[n] = ctx.rev()
3945
3942
3946 # check ancestors for earlier grafts
3943 # check ancestors for earlier grafts
3947 ui.debug('scanning for duplicate grafts\n')
3944 ui.debug('scanning for duplicate grafts\n')
3948
3945
3949 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3946 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3950 ctx = repo[rev]
3947 ctx = repo[rev]
3951 n = ctx.extra().get('source')
3948 n = ctx.extra().get('source')
3952 if n in ids:
3949 if n in ids:
3953 try:
3950 try:
3954 r = repo[n].rev()
3951 r = repo[n].rev()
3955 except error.RepoLookupError:
3952 except error.RepoLookupError:
3956 r = None
3953 r = None
3957 if r in revs:
3954 if r in revs:
3958 ui.warn(_('skipping revision %d:%s '
3955 ui.warn(_('skipping revision %d:%s '
3959 '(already grafted to %d:%s)\n')
3956 '(already grafted to %d:%s)\n')
3960 % (r, repo[r], rev, ctx))
3957 % (r, repo[r], rev, ctx))
3961 revs.remove(r)
3958 revs.remove(r)
3962 elif ids[n] in revs:
3959 elif ids[n] in revs:
3963 if r is None:
3960 if r is None:
3964 ui.warn(_('skipping already grafted revision %d:%s '
3961 ui.warn(_('skipping already grafted revision %d:%s '
3965 '(%d:%s also has unknown origin %s)\n')
3962 '(%d:%s also has unknown origin %s)\n')
3966 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3963 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3967 else:
3964 else:
3968 ui.warn(_('skipping already grafted revision %d:%s '
3965 ui.warn(_('skipping already grafted revision %d:%s '
3969 '(%d:%s also has origin %d:%s)\n')
3966 '(%d:%s also has origin %d:%s)\n')
3970 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3967 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3971 revs.remove(ids[n])
3968 revs.remove(ids[n])
3972 elif ctx.hex() in ids:
3969 elif ctx.hex() in ids:
3973 r = ids[ctx.hex()]
3970 r = ids[ctx.hex()]
3974 ui.warn(_('skipping already grafted revision %d:%s '
3971 ui.warn(_('skipping already grafted revision %d:%s '
3975 '(was grafted from %d:%s)\n') %
3972 '(was grafted from %d:%s)\n') %
3976 (r, repo[r], rev, ctx))
3973 (r, repo[r], rev, ctx))
3977 revs.remove(r)
3974 revs.remove(r)
3978 if not revs:
3975 if not revs:
3979 return -1
3976 return -1
3980
3977
3981 for pos, ctx in enumerate(repo.set("%ld", revs)):
3978 for pos, ctx in enumerate(repo.set("%ld", revs)):
3982 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3979 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3983 ctx.description().split('\n', 1)[0])
3980 ctx.description().split('\n', 1)[0])
3984 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3981 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3985 if names:
3982 if names:
3986 desc += ' (%s)' % ' '.join(names)
3983 desc += ' (%s)' % ' '.join(names)
3987 ui.status(_('grafting %s\n') % desc)
3984 ui.status(_('grafting %s\n') % desc)
3988 if opts.get('dry_run'):
3985 if opts.get('dry_run'):
3989 continue
3986 continue
3990
3987
3991 extra = ctx.extra().copy()
3988 extra = ctx.extra().copy()
3992 del extra['branch']
3989 del extra['branch']
3993 source = extra.get('source')
3990 source = extra.get('source')
3994 if source:
3991 if source:
3995 extra['intermediate-source'] = ctx.hex()
3992 extra['intermediate-source'] = ctx.hex()
3996 else:
3993 else:
3997 extra['source'] = ctx.hex()
3994 extra['source'] = ctx.hex()
3998 user = ctx.user()
3995 user = ctx.user()
3999 if opts.get('user'):
3996 if opts.get('user'):
4000 user = opts['user']
3997 user = opts['user']
4001 date = ctx.date()
3998 date = ctx.date()
4002 if opts.get('date'):
3999 if opts.get('date'):
4003 date = opts['date']
4000 date = opts['date']
4004 message = ctx.description()
4001 message = ctx.description()
4005 if opts.get('log'):
4002 if opts.get('log'):
4006 message += '\n(grafted from %s)' % ctx.hex()
4003 message += '\n(grafted from %s)' % ctx.hex()
4007
4004
4008 # we don't merge the first commit when continuing
4005 # we don't merge the first commit when continuing
4009 if not cont:
4006 if not cont:
4010 # perform the graft merge with p1(rev) as 'ancestor'
4007 # perform the graft merge with p1(rev) as 'ancestor'
4011 try:
4008 try:
4012 # ui.forcemerge is an internal variable, do not document
4009 # ui.forcemerge is an internal variable, do not document
4013 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4010 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4014 'graft')
4011 'graft')
4015 stats = mergemod.graft(repo, ctx, ctx.p1(),
4012 stats = mergemod.graft(repo, ctx, ctx.p1(),
4016 ['local', 'graft'])
4013 ['local', 'graft'])
4017 finally:
4014 finally:
4018 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4015 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4019 # report any conflicts
4016 # report any conflicts
4020 if stats and stats[3] > 0:
4017 if stats and stats[3] > 0:
4021 # write out state for --continue
4018 # write out state for --continue
4022 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4019 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4023 repo.vfs.write('graftstate', ''.join(nodelines))
4020 repo.vfs.write('graftstate', ''.join(nodelines))
4024 extra = ''
4021 extra = ''
4025 if opts.get('user'):
4022 if opts.get('user'):
4026 extra += ' --user %s' % opts['user']
4023 extra += ' --user %s' % opts['user']
4027 if opts.get('date'):
4024 if opts.get('date'):
4028 extra += ' --date %s' % opts['date']
4025 extra += ' --date %s' % opts['date']
4029 if opts.get('log'):
4026 if opts.get('log'):
4030 extra += ' --log'
4027 extra += ' --log'
4031 hint=_('use hg resolve and hg graft --continue%s') % extra
4028 hint=_('use hg resolve and hg graft --continue%s') % extra
4032 raise error.Abort(
4029 raise error.Abort(
4033 _("unresolved conflicts, can't continue"),
4030 _("unresolved conflicts, can't continue"),
4034 hint=hint)
4031 hint=hint)
4035 else:
4032 else:
4036 cont = False
4033 cont = False
4037
4034
4038 # commit
4035 # commit
4039 node = repo.commit(text=message, user=user,
4036 node = repo.commit(text=message, user=user,
4040 date=date, extra=extra, editor=editor)
4037 date=date, extra=extra, editor=editor)
4041 if node is None:
4038 if node is None:
4042 ui.warn(
4039 ui.warn(
4043 _('note: graft of %d:%s created no changes to commit\n') %
4040 _('note: graft of %d:%s created no changes to commit\n') %
4044 (ctx.rev(), ctx))
4041 (ctx.rev(), ctx))
4045
4042
4046 # remove state when we complete successfully
4043 # remove state when we complete successfully
4047 if not opts.get('dry_run'):
4044 if not opts.get('dry_run'):
4048 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4045 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4049
4046
4050 return 0
4047 return 0
4051
4048
4052 @command('grep',
4049 @command('grep',
4053 [('0', 'print0', None, _('end fields with NUL')),
4050 [('0', 'print0', None, _('end fields with NUL')),
4054 ('', 'all', None, _('print all revisions that match')),
4051 ('', 'all', None, _('print all revisions that match')),
4055 ('a', 'text', None, _('treat all files as text')),
4052 ('a', 'text', None, _('treat all files as text')),
4056 ('f', 'follow', None,
4053 ('f', 'follow', None,
4057 _('follow changeset history,'
4054 _('follow changeset history,'
4058 ' or file history across copies and renames')),
4055 ' or file history across copies and renames')),
4059 ('i', 'ignore-case', None, _('ignore case when matching')),
4056 ('i', 'ignore-case', None, _('ignore case when matching')),
4060 ('l', 'files-with-matches', None,
4057 ('l', 'files-with-matches', None,
4061 _('print only filenames and revisions that match')),
4058 _('print only filenames and revisions that match')),
4062 ('n', 'line-number', None, _('print matching line numbers')),
4059 ('n', 'line-number', None, _('print matching line numbers')),
4063 ('r', 'rev', [],
4060 ('r', 'rev', [],
4064 _('only search files changed within revision range'), _('REV')),
4061 _('only search files changed within revision range'), _('REV')),
4065 ('u', 'user', None, _('list the author (long with -v)')),
4062 ('u', 'user', None, _('list the author (long with -v)')),
4066 ('d', 'date', None, _('list the date (short with -q)')),
4063 ('d', 'date', None, _('list the date (short with -q)')),
4067 ] + walkopts,
4064 ] + walkopts,
4068 _('[OPTION]... PATTERN [FILE]...'),
4065 _('[OPTION]... PATTERN [FILE]...'),
4069 inferrepo=True)
4066 inferrepo=True)
4070 def grep(ui, repo, pattern, *pats, **opts):
4067 def grep(ui, repo, pattern, *pats, **opts):
4071 """search for a pattern in specified files and revisions
4068 """search for a pattern in specified files and revisions
4072
4069
4073 Search revisions of files for a regular expression.
4070 Search revisions of files for a regular expression.
4074
4071
4075 This command behaves differently than Unix grep. It only accepts
4072 This command behaves differently than Unix grep. It only accepts
4076 Python/Perl regexps. It searches repository history, not the
4073 Python/Perl regexps. It searches repository history, not the
4077 working directory. It always prints the revision number in which a
4074 working directory. It always prints the revision number in which a
4078 match appears.
4075 match appears.
4079
4076
4080 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
4081 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
4082 that contains a change in match status ("-" for a match that
4079 that contains a change in match status ("-" for a match that
4083 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),
4084 use the --all flag.
4081 use the --all flag.
4085
4082
4086 Returns 0 if a match is found, 1 otherwise.
4083 Returns 0 if a match is found, 1 otherwise.
4087 """
4084 """
4088 reflags = re.M
4085 reflags = re.M
4089 if opts.get('ignore_case'):
4086 if opts.get('ignore_case'):
4090 reflags |= re.I
4087 reflags |= re.I
4091 try:
4088 try:
4092 regexp = util.re.compile(pattern, reflags)
4089 regexp = util.re.compile(pattern, reflags)
4093 except re.error as inst:
4090 except re.error as inst:
4094 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4091 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4095 return 1
4092 return 1
4096 sep, eol = ':', '\n'
4093 sep, eol = ':', '\n'
4097 if opts.get('print0'):
4094 if opts.get('print0'):
4098 sep = eol = '\0'
4095 sep = eol = '\0'
4099
4096
4100 getfile = util.lrucachefunc(repo.file)
4097 getfile = util.lrucachefunc(repo.file)
4101
4098
4102 def matchlines(body):
4099 def matchlines(body):
4103 begin = 0
4100 begin = 0
4104 linenum = 0
4101 linenum = 0
4105 while begin < len(body):
4102 while begin < len(body):
4106 match = regexp.search(body, begin)
4103 match = regexp.search(body, begin)
4107 if not match:
4104 if not match:
4108 break
4105 break
4109 mstart, mend = match.span()
4106 mstart, mend = match.span()
4110 linenum += body.count('\n', begin, mstart) + 1
4107 linenum += body.count('\n', begin, mstart) + 1
4111 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4108 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4112 begin = body.find('\n', mend) + 1 or len(body) + 1
4109 begin = body.find('\n', mend) + 1 or len(body) + 1
4113 lend = begin - 1
4110 lend = begin - 1
4114 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4111 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4115
4112
4116 class linestate(object):
4113 class linestate(object):
4117 def __init__(self, line, linenum, colstart, colend):
4114 def __init__(self, line, linenum, colstart, colend):
4118 self.line = line
4115 self.line = line
4119 self.linenum = linenum
4116 self.linenum = linenum
4120 self.colstart = colstart
4117 self.colstart = colstart
4121 self.colend = colend
4118 self.colend = colend
4122
4119
4123 def __hash__(self):
4120 def __hash__(self):
4124 return hash((self.linenum, self.line))
4121 return hash((self.linenum, self.line))
4125
4122
4126 def __eq__(self, other):
4123 def __eq__(self, other):
4127 return self.line == other.line
4124 return self.line == other.line
4128
4125
4129 def __iter__(self):
4126 def __iter__(self):
4130 yield (self.line[:self.colstart], '')
4127 yield (self.line[:self.colstart], '')
4131 yield (self.line[self.colstart:self.colend], 'grep.match')
4128 yield (self.line[self.colstart:self.colend], 'grep.match')
4132 rest = self.line[self.colend:]
4129 rest = self.line[self.colend:]
4133 while rest != '':
4130 while rest != '':
4134 match = regexp.search(rest)
4131 match = regexp.search(rest)
4135 if not match:
4132 if not match:
4136 yield (rest, '')
4133 yield (rest, '')
4137 break
4134 break
4138 mstart, mend = match.span()
4135 mstart, mend = match.span()
4139 yield (rest[:mstart], '')
4136 yield (rest[:mstart], '')
4140 yield (rest[mstart:mend], 'grep.match')
4137 yield (rest[mstart:mend], 'grep.match')
4141 rest = rest[mend:]
4138 rest = rest[mend:]
4142
4139
4143 matches = {}
4140 matches = {}
4144 copies = {}
4141 copies = {}
4145 def grepbody(fn, rev, body):
4142 def grepbody(fn, rev, body):
4146 matches[rev].setdefault(fn, [])
4143 matches[rev].setdefault(fn, [])
4147 m = matches[rev][fn]
4144 m = matches[rev][fn]
4148 for lnum, cstart, cend, line in matchlines(body):
4145 for lnum, cstart, cend, line in matchlines(body):
4149 s = linestate(line, lnum, cstart, cend)
4146 s = linestate(line, lnum, cstart, cend)
4150 m.append(s)
4147 m.append(s)
4151
4148
4152 def difflinestates(a, b):
4149 def difflinestates(a, b):
4153 sm = difflib.SequenceMatcher(None, a, b)
4150 sm = difflib.SequenceMatcher(None, a, b)
4154 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4151 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4155 if tag == 'insert':
4152 if tag == 'insert':
4156 for i in xrange(blo, bhi):
4153 for i in xrange(blo, bhi):
4157 yield ('+', b[i])
4154 yield ('+', b[i])
4158 elif tag == 'delete':
4155 elif tag == 'delete':
4159 for i in xrange(alo, ahi):
4156 for i in xrange(alo, ahi):
4160 yield ('-', a[i])
4157 yield ('-', a[i])
4161 elif tag == 'replace':
4158 elif tag == 'replace':
4162 for i in xrange(alo, ahi):
4159 for i in xrange(alo, ahi):
4163 yield ('-', a[i])
4160 yield ('-', a[i])
4164 for i in xrange(blo, bhi):
4161 for i in xrange(blo, bhi):
4165 yield ('+', b[i])
4162 yield ('+', b[i])
4166
4163
4167 def display(fn, ctx, pstates, states):
4164 def display(fn, ctx, pstates, states):
4168 rev = ctx.rev()
4165 rev = ctx.rev()
4169 if ui.quiet:
4166 if ui.quiet:
4170 datefunc = util.shortdate
4167 datefunc = util.shortdate
4171 else:
4168 else:
4172 datefunc = util.datestr
4169 datefunc = util.datestr
4173 found = False
4170 found = False
4174 @util.cachefunc
4171 @util.cachefunc
4175 def binary():
4172 def binary():
4176 flog = getfile(fn)
4173 flog = getfile(fn)
4177 return util.binary(flog.read(ctx.filenode(fn)))
4174 return util.binary(flog.read(ctx.filenode(fn)))
4178
4175
4179 if opts.get('all'):
4176 if opts.get('all'):
4180 iter = difflinestates(pstates, states)
4177 iter = difflinestates(pstates, states)
4181 else:
4178 else:
4182 iter = [('', l) for l in states]
4179 iter = [('', l) for l in states]
4183 for change, l in iter:
4180 for change, l in iter:
4184 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4181 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4185
4182
4186 if opts.get('line_number'):
4183 if opts.get('line_number'):
4187 cols.append((str(l.linenum), 'grep.linenumber'))
4184 cols.append((str(l.linenum), 'grep.linenumber'))
4188 if opts.get('all'):
4185 if opts.get('all'):
4189 cols.append((change, 'grep.change'))
4186 cols.append((change, 'grep.change'))
4190 if opts.get('user'):
4187 if opts.get('user'):
4191 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4188 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4192 if opts.get('date'):
4189 if opts.get('date'):
4193 cols.append((datefunc(ctx.date()), 'grep.date'))
4190 cols.append((datefunc(ctx.date()), 'grep.date'))
4194 for col, label in cols[:-1]:
4191 for col, label in cols[:-1]:
4195 ui.write(col, label=label)
4192 ui.write(col, label=label)
4196 ui.write(sep, label='grep.sep')
4193 ui.write(sep, label='grep.sep')
4197 ui.write(cols[-1][0], label=cols[-1][1])
4194 ui.write(cols[-1][0], label=cols[-1][1])
4198 if not opts.get('files_with_matches'):
4195 if not opts.get('files_with_matches'):
4199 ui.write(sep, label='grep.sep')
4196 ui.write(sep, label='grep.sep')
4200 if not opts.get('text') and binary():
4197 if not opts.get('text') and binary():
4201 ui.write(" Binary file matches")
4198 ui.write(" Binary file matches")
4202 else:
4199 else:
4203 for s, label in l:
4200 for s, label in l:
4204 ui.write(s, label=label)
4201 ui.write(s, label=label)
4205 ui.write(eol)
4202 ui.write(eol)
4206 found = True
4203 found = True
4207 if opts.get('files_with_matches'):
4204 if opts.get('files_with_matches'):
4208 break
4205 break
4209 return found
4206 return found
4210
4207
4211 skip = {}
4208 skip = {}
4212 revfiles = {}
4209 revfiles = {}
4213 matchfn = scmutil.match(repo[None], pats, opts)
4210 matchfn = scmutil.match(repo[None], pats, opts)
4214 found = False
4211 found = False
4215 follow = opts.get('follow')
4212 follow = opts.get('follow')
4216
4213
4217 def prep(ctx, fns):
4214 def prep(ctx, fns):
4218 rev = ctx.rev()
4215 rev = ctx.rev()
4219 pctx = ctx.p1()
4216 pctx = ctx.p1()
4220 parent = pctx.rev()
4217 parent = pctx.rev()
4221 matches.setdefault(rev, {})
4218 matches.setdefault(rev, {})
4222 matches.setdefault(parent, {})
4219 matches.setdefault(parent, {})
4223 files = revfiles.setdefault(rev, [])
4220 files = revfiles.setdefault(rev, [])
4224 for fn in fns:
4221 for fn in fns:
4225 flog = getfile(fn)
4222 flog = getfile(fn)
4226 try:
4223 try:
4227 fnode = ctx.filenode(fn)
4224 fnode = ctx.filenode(fn)
4228 except error.LookupError:
4225 except error.LookupError:
4229 continue
4226 continue
4230
4227
4231 copied = flog.renamed(fnode)
4228 copied = flog.renamed(fnode)
4232 copy = follow and copied and copied[0]
4229 copy = follow and copied and copied[0]
4233 if copy:
4230 if copy:
4234 copies.setdefault(rev, {})[fn] = copy
4231 copies.setdefault(rev, {})[fn] = copy
4235 if fn in skip:
4232 if fn in skip:
4236 if copy:
4233 if copy:
4237 skip[copy] = True
4234 skip[copy] = True
4238 continue
4235 continue
4239 files.append(fn)
4236 files.append(fn)
4240
4237
4241 if fn not in matches[rev]:
4238 if fn not in matches[rev]:
4242 grepbody(fn, rev, flog.read(fnode))
4239 grepbody(fn, rev, flog.read(fnode))
4243
4240
4244 pfn = copy or fn
4241 pfn = copy or fn
4245 if pfn not in matches[parent]:
4242 if pfn not in matches[parent]:
4246 try:
4243 try:
4247 fnode = pctx.filenode(pfn)
4244 fnode = pctx.filenode(pfn)
4248 grepbody(pfn, parent, flog.read(fnode))
4245 grepbody(pfn, parent, flog.read(fnode))
4249 except error.LookupError:
4246 except error.LookupError:
4250 pass
4247 pass
4251
4248
4252 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4249 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4253 rev = ctx.rev()
4250 rev = ctx.rev()
4254 parent = ctx.p1().rev()
4251 parent = ctx.p1().rev()
4255 for fn in sorted(revfiles.get(rev, [])):
4252 for fn in sorted(revfiles.get(rev, [])):
4256 states = matches[rev][fn]
4253 states = matches[rev][fn]
4257 copy = copies.get(rev, {}).get(fn)
4254 copy = copies.get(rev, {}).get(fn)
4258 if fn in skip:
4255 if fn in skip:
4259 if copy:
4256 if copy:
4260 skip[copy] = True
4257 skip[copy] = True
4261 continue
4258 continue
4262 pstates = matches.get(parent, {}).get(copy or fn, [])
4259 pstates = matches.get(parent, {}).get(copy or fn, [])
4263 if pstates or states:
4260 if pstates or states:
4264 r = display(fn, ctx, pstates, states)
4261 r = display(fn, ctx, pstates, states)
4265 found = found or r
4262 found = found or r
4266 if r and not opts.get('all'):
4263 if r and not opts.get('all'):
4267 skip[fn] = True
4264 skip[fn] = True
4268 if copy:
4265 if copy:
4269 skip[copy] = True
4266 skip[copy] = True
4270 del matches[rev]
4267 del matches[rev]
4271 del revfiles[rev]
4268 del revfiles[rev]
4272
4269
4273 return not found
4270 return not found
4274
4271
4275 @command('heads',
4272 @command('heads',
4276 [('r', 'rev', '',
4273 [('r', 'rev', '',
4277 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4274 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4278 ('t', 'topo', False, _('show topological heads only')),
4275 ('t', 'topo', False, _('show topological heads only')),
4279 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4276 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4280 ('c', 'closed', False, _('show normal and closed branch heads')),
4277 ('c', 'closed', False, _('show normal and closed branch heads')),
4281 ] + templateopts,
4278 ] + templateopts,
4282 _('[-ct] [-r STARTREV] [REV]...'))
4279 _('[-ct] [-r STARTREV] [REV]...'))
4283 def heads(ui, repo, *branchrevs, **opts):
4280 def heads(ui, repo, *branchrevs, **opts):
4284 """show branch heads
4281 """show branch heads
4285
4282
4286 With no arguments, show all open branch heads in the repository.
4283 With no arguments, show all open branch heads in the repository.
4287 Branch heads are changesets that have no descendants on the
4284 Branch heads are changesets that have no descendants on the
4288 same branch. They are where development generally takes place and
4285 same branch. They are where development generally takes place and
4289 are the usual targets for update and merge operations.
4286 are the usual targets for update and merge operations.
4290
4287
4291 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
4292 branches associated with the specified changesets are shown. This
4289 branches associated with the specified changesets are shown. This
4293 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
4294 currently checked-out branch.
4291 currently checked-out branch.
4295
4292
4296 If -c/--closed is specified, also show branch heads marked closed
4293 If -c/--closed is specified, also show branch heads marked closed
4297 (see :hg:`commit --close-branch`).
4294 (see :hg:`commit --close-branch`).
4298
4295
4299 If STARTREV is specified, only those heads that are descendants of
4296 If STARTREV is specified, only those heads that are descendants of
4300 STARTREV will be displayed.
4297 STARTREV will be displayed.
4301
4298
4302 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
4303 topological heads (changesets with no children) will be shown.
4300 topological heads (changesets with no children) will be shown.
4304
4301
4305 Returns 0 if matching heads are found, 1 if not.
4302 Returns 0 if matching heads are found, 1 if not.
4306 """
4303 """
4307
4304
4308 start = None
4305 start = None
4309 if 'rev' in opts:
4306 if 'rev' in opts:
4310 start = scmutil.revsingle(repo, opts['rev'], None).node()
4307 start = scmutil.revsingle(repo, opts['rev'], None).node()
4311
4308
4312 if opts.get('topo'):
4309 if opts.get('topo'):
4313 heads = [repo[h] for h in repo.heads(start)]
4310 heads = [repo[h] for h in repo.heads(start)]
4314 else:
4311 else:
4315 heads = []
4312 heads = []
4316 for branch in repo.branchmap():
4313 for branch in repo.branchmap():
4317 heads += repo.branchheads(branch, start, opts.get('closed'))
4314 heads += repo.branchheads(branch, start, opts.get('closed'))
4318 heads = [repo[h] for h in heads]
4315 heads = [repo[h] for h in heads]
4319
4316
4320 if branchrevs:
4317 if branchrevs:
4321 branches = set(repo[br].branch() for br in branchrevs)
4318 branches = set(repo[br].branch() for br in branchrevs)
4322 heads = [h for h in heads if h.branch() in branches]
4319 heads = [h for h in heads if h.branch() in branches]
4323
4320
4324 if opts.get('active') and branchrevs:
4321 if opts.get('active') and branchrevs:
4325 dagheads = repo.heads(start)
4322 dagheads = repo.heads(start)
4326 heads = [h for h in heads if h.node() in dagheads]
4323 heads = [h for h in heads if h.node() in dagheads]
4327
4324
4328 if branchrevs:
4325 if branchrevs:
4329 haveheads = set(h.branch() for h in heads)
4326 haveheads = set(h.branch() for h in heads)
4330 if branches - haveheads:
4327 if branches - haveheads:
4331 headless = ', '.join(b for b in branches - haveheads)
4328 headless = ', '.join(b for b in branches - haveheads)
4332 msg = _('no open branch heads found on branches %s')
4329 msg = _('no open branch heads found on branches %s')
4333 if opts.get('rev'):
4330 if opts.get('rev'):
4334 msg += _(' (started at %s)') % opts['rev']
4331 msg += _(' (started at %s)') % opts['rev']
4335 ui.warn((msg + '\n') % headless)
4332 ui.warn((msg + '\n') % headless)
4336
4333
4337 if not heads:
4334 if not heads:
4338 return 1
4335 return 1
4339
4336
4340 heads = sorted(heads, key=lambda x: -x.rev())
4337 heads = sorted(heads, key=lambda x: -x.rev())
4341 displayer = cmdutil.show_changeset(ui, repo, opts)
4338 displayer = cmdutil.show_changeset(ui, repo, opts)
4342 for ctx in heads:
4339 for ctx in heads:
4343 displayer.show(ctx)
4340 displayer.show(ctx)
4344 displayer.close()
4341 displayer.close()
4345
4342
4346 @command('help',
4343 @command('help',
4347 [('e', 'extension', None, _('show only help for extensions')),
4344 [('e', 'extension', None, _('show only help for extensions')),
4348 ('c', 'command', None, _('show only help for commands')),
4345 ('c', 'command', None, _('show only help for commands')),
4349 ('k', 'keyword', None, _('show topics matching keyword')),
4346 ('k', 'keyword', None, _('show topics matching keyword')),
4350 ('s', 'system', [], _('show help for specific platform(s)')),
4347 ('s', 'system', [], _('show help for specific platform(s)')),
4351 ],
4348 ],
4352 _('[-ecks] [TOPIC]'),
4349 _('[-ecks] [TOPIC]'),
4353 norepo=True)
4350 norepo=True)
4354 def help_(ui, name=None, **opts):
4351 def help_(ui, name=None, **opts):
4355 """show help for a given topic or a help overview
4352 """show help for a given topic or a help overview
4356
4353
4357 With no arguments, print a list of commands with short help messages.
4354 With no arguments, print a list of commands with short help messages.
4358
4355
4359 Given a topic, extension, or command name, print help for that
4356 Given a topic, extension, or command name, print help for that
4360 topic.
4357 topic.
4361
4358
4362 Returns 0 if successful.
4359 Returns 0 if successful.
4363 """
4360 """
4364
4361
4365 textwidth = min(ui.termwidth(), 80) - 2
4362 textwidth = min(ui.termwidth(), 80) - 2
4366
4363
4367 keep = opts.get('system') or []
4364 keep = opts.get('system') or []
4368 if len(keep) == 0:
4365 if len(keep) == 0:
4369 if sys.platform.startswith('win'):
4366 if sys.platform.startswith('win'):
4370 keep.append('windows')
4367 keep.append('windows')
4371 elif sys.platform == 'OpenVMS':
4368 elif sys.platform == 'OpenVMS':
4372 keep.append('vms')
4369 keep.append('vms')
4373 elif sys.platform == 'plan9':
4370 elif sys.platform == 'plan9':
4374 keep.append('plan9')
4371 keep.append('plan9')
4375 else:
4372 else:
4376 keep.append('unix')
4373 keep.append('unix')
4377 keep.append(sys.platform.lower())
4374 keep.append(sys.platform.lower())
4378 if ui.verbose:
4375 if ui.verbose:
4379 keep.append('verbose')
4376 keep.append('verbose')
4380
4377
4381 section = None
4378 section = None
4382 subtopic = None
4379 subtopic = None
4383 if name and '.' in name:
4380 if name and '.' in name:
4384 name, section = name.split('.', 1)
4381 name, section = name.split('.', 1)
4385 section = section.lower()
4382 section = section.lower()
4386 if '.' in section:
4383 if '.' in section:
4387 subtopic, section = section.split('.', 1)
4384 subtopic, section = section.split('.', 1)
4388 else:
4385 else:
4389 subtopic = section
4386 subtopic = section
4390
4387
4391 text = help.help_(ui, name, subtopic=subtopic, **opts)
4388 text = help.help_(ui, name, subtopic=subtopic, **opts)
4392
4389
4393 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4390 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4394 section=section)
4391 section=section)
4395
4392
4396 # We could have been given a weird ".foo" section without a name
4393 # We could have been given a weird ".foo" section without a name
4397 # to look for, or we could have simply failed to found "foo.bar"
4394 # to look for, or we could have simply failed to found "foo.bar"
4398 # because bar isn't a section of foo
4395 # because bar isn't a section of foo
4399 if section and not (formatted and name):
4396 if section and not (formatted and name):
4400 raise error.Abort(_("help section not found"))
4397 raise error.Abort(_("help section not found"))
4401
4398
4402 if 'verbose' in pruned:
4399 if 'verbose' in pruned:
4403 keep.append('omitted')
4400 keep.append('omitted')
4404 else:
4401 else:
4405 keep.append('notomitted')
4402 keep.append('notomitted')
4406 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4403 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4407 section=section)
4404 section=section)
4408 ui.write(formatted)
4405 ui.write(formatted)
4409
4406
4410
4407
4411 @command('identify|id',
4408 @command('identify|id',
4412 [('r', 'rev', '',
4409 [('r', 'rev', '',
4413 _('identify the specified revision'), _('REV')),
4410 _('identify the specified revision'), _('REV')),
4414 ('n', 'num', None, _('show local revision number')),
4411 ('n', 'num', None, _('show local revision number')),
4415 ('i', 'id', None, _('show global revision id')),
4412 ('i', 'id', None, _('show global revision id')),
4416 ('b', 'branch', None, _('show branch')),
4413 ('b', 'branch', None, _('show branch')),
4417 ('t', 'tags', None, _('show tags')),
4414 ('t', 'tags', None, _('show tags')),
4418 ('B', 'bookmarks', None, _('show bookmarks')),
4415 ('B', 'bookmarks', None, _('show bookmarks')),
4419 ] + remoteopts,
4416 ] + remoteopts,
4420 _('[-nibtB] [-r REV] [SOURCE]'),
4417 _('[-nibtB] [-r REV] [SOURCE]'),
4421 optionalrepo=True)
4418 optionalrepo=True)
4422 def identify(ui, repo, source=None, rev=None,
4419 def identify(ui, repo, source=None, rev=None,
4423 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4420 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4424 """identify the working directory or specified revision
4421 """identify the working directory or specified revision
4425
4422
4426 Print a summary identifying the repository state at REV using one or
4423 Print a summary identifying the repository state at REV using one or
4427 two parent hash identifiers, followed by a "+" if the working
4424 two parent hash identifiers, followed by a "+" if the working
4428 directory has uncommitted changes, the branch name (if not default),
4425 directory has uncommitted changes, the branch name (if not default),
4429 a list of tags, and a list of bookmarks.
4426 a list of tags, and a list of bookmarks.
4430
4427
4431 When REV is not given, print a summary of the current state of the
4428 When REV is not given, print a summary of the current state of the
4432 repository.
4429 repository.
4433
4430
4434 Specifying a path to a repository root or Mercurial bundle will
4431 Specifying a path to a repository root or Mercurial bundle will
4435 cause lookup to operate on that repository/bundle.
4432 cause lookup to operate on that repository/bundle.
4436
4433
4437 .. container:: verbose
4434 .. container:: verbose
4438
4435
4439 Examples:
4436 Examples:
4440
4437
4441 - generate a build identifier for the working directory::
4438 - generate a build identifier for the working directory::
4442
4439
4443 hg id --id > build-id.dat
4440 hg id --id > build-id.dat
4444
4441
4445 - find the revision corresponding to a tag::
4442 - find the revision corresponding to a tag::
4446
4443
4447 hg id -n -r 1.3
4444 hg id -n -r 1.3
4448
4445
4449 - check the most recent revision of a remote repository::
4446 - check the most recent revision of a remote repository::
4450
4447
4451 hg id -r tip http://selenic.com/hg/
4448 hg id -r tip http://selenic.com/hg/
4452
4449
4453 See :hg:`log` for generating more information about specific revisions,
4450 See :hg:`log` for generating more information about specific revisions,
4454 including full hash identifiers.
4451 including full hash identifiers.
4455
4452
4456 Returns 0 if successful.
4453 Returns 0 if successful.
4457 """
4454 """
4458
4455
4459 if not repo and not source:
4456 if not repo and not source:
4460 raise error.Abort(_("there is no Mercurial repository here "
4457 raise error.Abort(_("there is no Mercurial repository here "
4461 "(.hg not found)"))
4458 "(.hg not found)"))
4462
4459
4463 if ui.debugflag:
4460 if ui.debugflag:
4464 hexfunc = hex
4461 hexfunc = hex
4465 else:
4462 else:
4466 hexfunc = short
4463 hexfunc = short
4467 default = not (num or id or branch or tags or bookmarks)
4464 default = not (num or id or branch or tags or bookmarks)
4468 output = []
4465 output = []
4469 revs = []
4466 revs = []
4470
4467
4471 if source:
4468 if source:
4472 source, branches = hg.parseurl(ui.expandpath(source))
4469 source, branches = hg.parseurl(ui.expandpath(source))
4473 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4470 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4474 repo = peer.local()
4471 repo = peer.local()
4475 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4472 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4476
4473
4477 if not repo:
4474 if not repo:
4478 if num or branch or tags:
4475 if num or branch or tags:
4479 raise error.Abort(
4476 raise error.Abort(
4480 _("can't query remote revision number, branch, or tags"))
4477 _("can't query remote revision number, branch, or tags"))
4481 if not rev and revs:
4478 if not rev and revs:
4482 rev = revs[0]
4479 rev = revs[0]
4483 if not rev:
4480 if not rev:
4484 rev = "tip"
4481 rev = "tip"
4485
4482
4486 remoterev = peer.lookup(rev)
4483 remoterev = peer.lookup(rev)
4487 if default or id:
4484 if default or id:
4488 output = [hexfunc(remoterev)]
4485 output = [hexfunc(remoterev)]
4489
4486
4490 def getbms():
4487 def getbms():
4491 bms = []
4488 bms = []
4492
4489
4493 if 'bookmarks' in peer.listkeys('namespaces'):
4490 if 'bookmarks' in peer.listkeys('namespaces'):
4494 hexremoterev = hex(remoterev)
4491 hexremoterev = hex(remoterev)
4495 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4492 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4496 if bmr == hexremoterev]
4493 if bmr == hexremoterev]
4497
4494
4498 return sorted(bms)
4495 return sorted(bms)
4499
4496
4500 if bookmarks:
4497 if bookmarks:
4501 output.extend(getbms())
4498 output.extend(getbms())
4502 elif default and not ui.quiet:
4499 elif default and not ui.quiet:
4503 # multiple bookmarks for a single parent separated by '/'
4500 # multiple bookmarks for a single parent separated by '/'
4504 bm = '/'.join(getbms())
4501 bm = '/'.join(getbms())
4505 if bm:
4502 if bm:
4506 output.append(bm)
4503 output.append(bm)
4507 else:
4504 else:
4508 ctx = scmutil.revsingle(repo, rev, None)
4505 ctx = scmutil.revsingle(repo, rev, None)
4509
4506
4510 if ctx.rev() is None:
4507 if ctx.rev() is None:
4511 ctx = repo[None]
4508 ctx = repo[None]
4512 parents = ctx.parents()
4509 parents = ctx.parents()
4513 taglist = []
4510 taglist = []
4514 for p in parents:
4511 for p in parents:
4515 taglist.extend(p.tags())
4512 taglist.extend(p.tags())
4516
4513
4517 changed = ""
4514 changed = ""
4518 if default or id or num:
4515 if default or id or num:
4519 if (any(repo.status())
4516 if (any(repo.status())
4520 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4517 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4521 changed = '+'
4518 changed = '+'
4522 if default or id:
4519 if default or id:
4523 output = ["%s%s" %
4520 output = ["%s%s" %
4524 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4521 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4525 if num:
4522 if num:
4526 output.append("%s%s" %
4523 output.append("%s%s" %
4527 ('+'.join([str(p.rev()) for p in parents]), changed))
4524 ('+'.join([str(p.rev()) for p in parents]), changed))
4528 else:
4525 else:
4529 if default or id:
4526 if default or id:
4530 output = [hexfunc(ctx.node())]
4527 output = [hexfunc(ctx.node())]
4531 if num:
4528 if num:
4532 output.append(str(ctx.rev()))
4529 output.append(str(ctx.rev()))
4533 taglist = ctx.tags()
4530 taglist = ctx.tags()
4534
4531
4535 if default and not ui.quiet:
4532 if default and not ui.quiet:
4536 b = ctx.branch()
4533 b = ctx.branch()
4537 if b != 'default':
4534 if b != 'default':
4538 output.append("(%s)" % b)
4535 output.append("(%s)" % b)
4539
4536
4540 # multiple tags for a single parent separated by '/'
4537 # multiple tags for a single parent separated by '/'
4541 t = '/'.join(taglist)
4538 t = '/'.join(taglist)
4542 if t:
4539 if t:
4543 output.append(t)
4540 output.append(t)
4544
4541
4545 # multiple bookmarks for a single parent separated by '/'
4542 # multiple bookmarks for a single parent separated by '/'
4546 bm = '/'.join(ctx.bookmarks())
4543 bm = '/'.join(ctx.bookmarks())
4547 if bm:
4544 if bm:
4548 output.append(bm)
4545 output.append(bm)
4549 else:
4546 else:
4550 if branch:
4547 if branch:
4551 output.append(ctx.branch())
4548 output.append(ctx.branch())
4552
4549
4553 if tags:
4550 if tags:
4554 output.extend(taglist)
4551 output.extend(taglist)
4555
4552
4556 if bookmarks:
4553 if bookmarks:
4557 output.extend(ctx.bookmarks())
4554 output.extend(ctx.bookmarks())
4558
4555
4559 ui.write("%s\n" % ' '.join(output))
4556 ui.write("%s\n" % ' '.join(output))
4560
4557
4561 @command('import|patch',
4558 @command('import|patch',
4562 [('p', 'strip', 1,
4559 [('p', 'strip', 1,
4563 _('directory strip option for patch. This has the same '
4560 _('directory strip option for patch. This has the same '
4564 'meaning as the corresponding patch option'), _('NUM')),
4561 'meaning as the corresponding patch option'), _('NUM')),
4565 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4562 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4566 ('e', 'edit', False, _('invoke editor on commit messages')),
4563 ('e', 'edit', False, _('invoke editor on commit messages')),
4567 ('f', 'force', None,
4564 ('f', 'force', None,
4568 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4565 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4569 ('', 'no-commit', None,
4566 ('', 'no-commit', None,
4570 _("don't commit, just update the working directory")),
4567 _("don't commit, just update the working directory")),
4571 ('', 'bypass', None,
4568 ('', 'bypass', None,
4572 _("apply patch without touching the working directory")),
4569 _("apply patch without touching the working directory")),
4573 ('', 'partial', None,
4570 ('', 'partial', None,
4574 _('commit even if some hunks fail')),
4571 _('commit even if some hunks fail')),
4575 ('', 'exact', None,
4572 ('', 'exact', None,
4576 _('apply patch to the nodes from which it was generated')),
4573 _('apply patch to the nodes from which it was generated')),
4577 ('', 'prefix', '',
4574 ('', 'prefix', '',
4578 _('apply patch to subdirectory'), _('DIR')),
4575 _('apply patch to subdirectory'), _('DIR')),
4579 ('', 'import-branch', None,
4576 ('', 'import-branch', None,
4580 _('use any branch information in patch (implied by --exact)'))] +
4577 _('use any branch information in patch (implied by --exact)'))] +
4581 commitopts + commitopts2 + similarityopts,
4578 commitopts + commitopts2 + similarityopts,
4582 _('[OPTION]... PATCH...'))
4579 _('[OPTION]... PATCH...'))
4583 def import_(ui, repo, patch1=None, *patches, **opts):
4580 def import_(ui, repo, patch1=None, *patches, **opts):
4584 """import an ordered set of patches
4581 """import an ordered set of patches
4585
4582
4586 Import a list of patches and commit them individually (unless
4583 Import a list of patches and commit them individually (unless
4587 --no-commit is specified).
4584 --no-commit is specified).
4588
4585
4589 To read a patch from standard input, use "-" as the patch name. If
4586 To read a patch from standard input, use "-" as the patch name. If
4590 a URL is specified, the patch will be downloaded from there.
4587 a URL is specified, the patch will be downloaded from there.
4591
4588
4592 Import first applies changes to the working directory (unless
4589 Import first applies changes to the working directory (unless
4593 --bypass is specified), import will abort if there are outstanding
4590 --bypass is specified), import will abort if there are outstanding
4594 changes.
4591 changes.
4595
4592
4596 Use --bypass to apply and commit patches directly to the
4593 Use --bypass to apply and commit patches directly to the
4597 repository, without affecting the working directory. Without
4594 repository, without affecting the working directory. Without
4598 --exact, patches will be applied on top of the working directory
4595 --exact, patches will be applied on top of the working directory
4599 parent revision.
4596 parent revision.
4600
4597
4601 You can import a patch straight from a mail message. Even patches
4598 You can import a patch straight from a mail message. Even patches
4602 as attachments work (to use the body part, it must have type
4599 as attachments work (to use the body part, it must have type
4603 text/plain or text/x-patch). From and Subject headers of email
4600 text/plain or text/x-patch). From and Subject headers of email
4604 message are used as default committer and commit message. All
4601 message are used as default committer and commit message. All
4605 text/plain body parts before first diff are added to the commit
4602 text/plain body parts before first diff are added to the commit
4606 message.
4603 message.
4607
4604
4608 If the imported patch was generated by :hg:`export`, user and
4605 If the imported patch was generated by :hg:`export`, user and
4609 description from patch override values from message headers and
4606 description from patch override values from message headers and
4610 body. Values given on command line with -m/--message and -u/--user
4607 body. Values given on command line with -m/--message and -u/--user
4611 override these.
4608 override these.
4612
4609
4613 If --exact is specified, import will set the working directory to
4610 If --exact is specified, import will set the working directory to
4614 the parent of each patch before applying it, and will abort if the
4611 the parent of each patch before applying it, and will abort if the
4615 resulting changeset has a different ID than the one recorded in
4612 resulting changeset has a different ID than the one recorded in
4616 the patch. This may happen due to character set problems or other
4613 the patch. This may happen due to character set problems or other
4617 deficiencies in the text patch format.
4614 deficiencies in the text patch format.
4618
4615
4619 Use --partial to ensure a changeset will be created from the patch
4616 Use --partial to ensure a changeset will be created from the patch
4620 even if some hunks fail to apply. Hunks that fail to apply will be
4617 even if some hunks fail to apply. Hunks that fail to apply will be
4621 written to a <target-file>.rej file. Conflicts can then be resolved
4618 written to a <target-file>.rej file. Conflicts can then be resolved
4622 by hand before :hg:`commit --amend` is run to update the created
4619 by hand before :hg:`commit --amend` is run to update the created
4623 changeset. This flag exists to let people import patches that
4620 changeset. This flag exists to let people import patches that
4624 partially apply without losing the associated metadata (author,
4621 partially apply without losing the associated metadata (author,
4625 date, description, ...).
4622 date, description, ...).
4626
4623
4627 .. note::
4624 .. note::
4628
4625
4629 When no hunks apply cleanly, :hg:`import --partial` will create
4626 When no hunks apply cleanly, :hg:`import --partial` will create
4630 an empty changeset, importing only the patch metadata.
4627 an empty changeset, importing only the patch metadata.
4631
4628
4632 With -s/--similarity, hg will attempt to discover renames and
4629 With -s/--similarity, hg will attempt to discover renames and
4633 copies in the patch in the same way as :hg:`addremove`.
4630 copies in the patch in the same way as :hg:`addremove`.
4634
4631
4635 It is possible to use external patch programs to perform the patch
4632 It is possible to use external patch programs to perform the patch
4636 by setting the ``ui.patch`` configuration option. For the default
4633 by setting the ``ui.patch`` configuration option. For the default
4637 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4634 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4638 See :hg:`help config` for more information about configuration
4635 See :hg:`help config` for more information about configuration
4639 files and how to use these options.
4636 files and how to use these options.
4640
4637
4641 See :hg:`help dates` for a list of formats valid for -d/--date.
4638 See :hg:`help dates` for a list of formats valid for -d/--date.
4642
4639
4643 .. container:: verbose
4640 .. container:: verbose
4644
4641
4645 Examples:
4642 Examples:
4646
4643
4647 - import a traditional patch from a website and detect renames::
4644 - import a traditional patch from a website and detect renames::
4648
4645
4649 hg import -s 80 http://example.com/bugfix.patch
4646 hg import -s 80 http://example.com/bugfix.patch
4650
4647
4651 - import a changeset from an hgweb server::
4648 - import a changeset from an hgweb server::
4652
4649
4653 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4650 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4654
4651
4655 - import all the patches in an Unix-style mbox::
4652 - import all the patches in an Unix-style mbox::
4656
4653
4657 hg import incoming-patches.mbox
4654 hg import incoming-patches.mbox
4658
4655
4659 - attempt to exactly restore an exported changeset (not always
4656 - attempt to exactly restore an exported changeset (not always
4660 possible)::
4657 possible)::
4661
4658
4662 hg import --exact proposed-fix.patch
4659 hg import --exact proposed-fix.patch
4663
4660
4664 - use an external tool to apply a patch which is too fuzzy for
4661 - use an external tool to apply a patch which is too fuzzy for
4665 the default internal tool.
4662 the default internal tool.
4666
4663
4667 hg import --config ui.patch="patch --merge" fuzzy.patch
4664 hg import --config ui.patch="patch --merge" fuzzy.patch
4668
4665
4669 - change the default fuzzing from 2 to a less strict 7
4666 - change the default fuzzing from 2 to a less strict 7
4670
4667
4671 hg import --config ui.fuzz=7 fuzz.patch
4668 hg import --config ui.fuzz=7 fuzz.patch
4672
4669
4673 Returns 0 on success, 1 on partial success (see --partial).
4670 Returns 0 on success, 1 on partial success (see --partial).
4674 """
4671 """
4675
4672
4676 if not patch1:
4673 if not patch1:
4677 raise error.Abort(_('need at least one patch to import'))
4674 raise error.Abort(_('need at least one patch to import'))
4678
4675
4679 patches = (patch1,) + patches
4676 patches = (patch1,) + patches
4680
4677
4681 date = opts.get('date')
4678 date = opts.get('date')
4682 if date:
4679 if date:
4683 opts['date'] = util.parsedate(date)
4680 opts['date'] = util.parsedate(date)
4684
4681
4685 exact = opts.get('exact')
4682 exact = opts.get('exact')
4686 update = not opts.get('bypass')
4683 update = not opts.get('bypass')
4687 if not update and opts.get('no_commit'):
4684 if not update and opts.get('no_commit'):
4688 raise error.Abort(_('cannot use --no-commit with --bypass'))
4685 raise error.Abort(_('cannot use --no-commit with --bypass'))
4689 try:
4686 try:
4690 sim = float(opts.get('similarity') or 0)
4687 sim = float(opts.get('similarity') or 0)
4691 except ValueError:
4688 except ValueError:
4692 raise error.Abort(_('similarity must be a number'))
4689 raise error.Abort(_('similarity must be a number'))
4693 if sim < 0 or sim > 100:
4690 if sim < 0 or sim > 100:
4694 raise error.Abort(_('similarity must be between 0 and 100'))
4691 raise error.Abort(_('similarity must be between 0 and 100'))
4695 if sim and not update:
4692 if sim and not update:
4696 raise error.Abort(_('cannot use --similarity with --bypass'))
4693 raise error.Abort(_('cannot use --similarity with --bypass'))
4697 if exact:
4694 if exact:
4698 if opts.get('edit'):
4695 if opts.get('edit'):
4699 raise error.Abort(_('cannot use --exact with --edit'))
4696 raise error.Abort(_('cannot use --exact with --edit'))
4700 if opts.get('prefix'):
4697 if opts.get('prefix'):
4701 raise error.Abort(_('cannot use --exact with --prefix'))
4698 raise error.Abort(_('cannot use --exact with --prefix'))
4702
4699
4703 base = opts["base"]
4700 base = opts["base"]
4704 wlock = dsguard = lock = tr = None
4701 wlock = dsguard = lock = tr = None
4705 msgs = []
4702 msgs = []
4706 ret = 0
4703 ret = 0
4707
4704
4708
4705
4709 try:
4706 try:
4710 wlock = repo.wlock()
4707 wlock = repo.wlock()
4711
4708
4712 if update:
4709 if update:
4713 cmdutil.checkunfinished(repo)
4710 cmdutil.checkunfinished(repo)
4714 if (exact or not opts.get('force')):
4711 if (exact or not opts.get('force')):
4715 cmdutil.bailifchanged(repo)
4712 cmdutil.bailifchanged(repo)
4716
4713
4717 if not opts.get('no_commit'):
4714 if not opts.get('no_commit'):
4718 lock = repo.lock()
4715 lock = repo.lock()
4719 tr = repo.transaction('import')
4716 tr = repo.transaction('import')
4720 else:
4717 else:
4721 dsguard = cmdutil.dirstateguard(repo, 'import')
4718 dsguard = cmdutil.dirstateguard(repo, 'import')
4722 parents = repo[None].parents()
4719 parents = repo[None].parents()
4723 for patchurl in patches:
4720 for patchurl in patches:
4724 if patchurl == '-':
4721 if patchurl == '-':
4725 ui.status(_('applying patch from stdin\n'))
4722 ui.status(_('applying patch from stdin\n'))
4726 patchfile = ui.fin
4723 patchfile = ui.fin
4727 patchurl = 'stdin' # for error message
4724 patchurl = 'stdin' # for error message
4728 else:
4725 else:
4729 patchurl = os.path.join(base, patchurl)
4726 patchurl = os.path.join(base, patchurl)
4730 ui.status(_('applying %s\n') % patchurl)
4727 ui.status(_('applying %s\n') % patchurl)
4731 patchfile = hg.openpath(ui, patchurl)
4728 patchfile = hg.openpath(ui, patchurl)
4732
4729
4733 haspatch = False
4730 haspatch = False
4734 for hunk in patch.split(patchfile):
4731 for hunk in patch.split(patchfile):
4735 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4732 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4736 parents, opts,
4733 parents, opts,
4737 msgs, hg.clean)
4734 msgs, hg.clean)
4738 if msg:
4735 if msg:
4739 haspatch = True
4736 haspatch = True
4740 ui.note(msg + '\n')
4737 ui.note(msg + '\n')
4741 if update or exact:
4738 if update or exact:
4742 parents = repo[None].parents()
4739 parents = repo[None].parents()
4743 else:
4740 else:
4744 parents = [repo[node]]
4741 parents = [repo[node]]
4745 if rej:
4742 if rej:
4746 ui.write_err(_("patch applied partially\n"))
4743 ui.write_err(_("patch applied partially\n"))
4747 ui.write_err(_("(fix the .rej files and run "
4744 ui.write_err(_("(fix the .rej files and run "
4748 "`hg commit --amend`)\n"))
4745 "`hg commit --amend`)\n"))
4749 ret = 1
4746 ret = 1
4750 break
4747 break
4751
4748
4752 if not haspatch:
4749 if not haspatch:
4753 raise error.Abort(_('%s: no diffs found') % patchurl)
4750 raise error.Abort(_('%s: no diffs found') % patchurl)
4754
4751
4755 if tr:
4752 if tr:
4756 tr.close()
4753 tr.close()
4757 if msgs:
4754 if msgs:
4758 repo.savecommitmessage('\n* * *\n'.join(msgs))
4755 repo.savecommitmessage('\n* * *\n'.join(msgs))
4759 if dsguard:
4756 if dsguard:
4760 dsguard.close()
4757 dsguard.close()
4761 return ret
4758 return ret
4762 finally:
4759 finally:
4763 if tr:
4760 if tr:
4764 tr.release()
4761 tr.release()
4765 release(lock, dsguard, wlock)
4762 release(lock, dsguard, wlock)
4766
4763
4767 @command('incoming|in',
4764 @command('incoming|in',
4768 [('f', 'force', None,
4765 [('f', 'force', None,
4769 _('run even if remote repository is unrelated')),
4766 _('run even if remote repository is unrelated')),
4770 ('n', 'newest-first', None, _('show newest record first')),
4767 ('n', 'newest-first', None, _('show newest record first')),
4771 ('', 'bundle', '',
4768 ('', 'bundle', '',
4772 _('file to store the bundles into'), _('FILE')),
4769 _('file to store the bundles into'), _('FILE')),
4773 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4770 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4774 ('B', 'bookmarks', False, _("compare bookmarks")),
4771 ('B', 'bookmarks', False, _("compare bookmarks")),
4775 ('b', 'branch', [],
4772 ('b', 'branch', [],
4776 _('a specific branch you would like to pull'), _('BRANCH')),
4773 _('a specific branch you would like to pull'), _('BRANCH')),
4777 ] + logopts + remoteopts + subrepoopts,
4774 ] + logopts + remoteopts + subrepoopts,
4778 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4775 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4779 def incoming(ui, repo, source="default", **opts):
4776 def incoming(ui, repo, source="default", **opts):
4780 """show new changesets found in source
4777 """show new changesets found in source
4781
4778
4782 Show new changesets found in the specified path/URL or the default
4779 Show new changesets found in the specified path/URL or the default
4783 pull location. These are the changesets that would have been pulled
4780 pull location. These are the changesets that would have been pulled
4784 if a pull at the time you issued this command.
4781 if a pull at the time you issued this command.
4785
4782
4786 See pull for valid source format details.
4783 See pull for valid source format details.
4787
4784
4788 .. container:: verbose
4785 .. container:: verbose
4789
4786
4790 With -B/--bookmarks, the result of bookmark comparison between
4787 With -B/--bookmarks, the result of bookmark comparison between
4791 local and remote repositories is displayed. With -v/--verbose,
4788 local and remote repositories is displayed. With -v/--verbose,
4792 status is also displayed for each bookmark like below::
4789 status is also displayed for each bookmark like below::
4793
4790
4794 BM1 01234567890a added
4791 BM1 01234567890a added
4795 BM2 1234567890ab advanced
4792 BM2 1234567890ab advanced
4796 BM3 234567890abc diverged
4793 BM3 234567890abc diverged
4797 BM4 34567890abcd changed
4794 BM4 34567890abcd changed
4798
4795
4799 The action taken locally when pulling depends on the
4796 The action taken locally when pulling depends on the
4800 status of each bookmark:
4797 status of each bookmark:
4801
4798
4802 :``added``: pull will create it
4799 :``added``: pull will create it
4803 :``advanced``: pull will update it
4800 :``advanced``: pull will update it
4804 :``diverged``: pull will create a divergent bookmark
4801 :``diverged``: pull will create a divergent bookmark
4805 :``changed``: result depends on remote changesets
4802 :``changed``: result depends on remote changesets
4806
4803
4807 From the point of view of pulling behavior, bookmark
4804 From the point of view of pulling behavior, bookmark
4808 existing only in the remote repository are treated as ``added``,
4805 existing only in the remote repository are treated as ``added``,
4809 even if it is in fact locally deleted.
4806 even if it is in fact locally deleted.
4810
4807
4811 .. container:: verbose
4808 .. container:: verbose
4812
4809
4813 For remote repository, using --bundle avoids downloading the
4810 For remote repository, using --bundle avoids downloading the
4814 changesets twice if the incoming is followed by a pull.
4811 changesets twice if the incoming is followed by a pull.
4815
4812
4816 Examples:
4813 Examples:
4817
4814
4818 - show incoming changes with patches and full description::
4815 - show incoming changes with patches and full description::
4819
4816
4820 hg incoming -vp
4817 hg incoming -vp
4821
4818
4822 - show incoming changes excluding merges, store a bundle::
4819 - show incoming changes excluding merges, store a bundle::
4823
4820
4824 hg in -vpM --bundle incoming.hg
4821 hg in -vpM --bundle incoming.hg
4825 hg pull incoming.hg
4822 hg pull incoming.hg
4826
4823
4827 - briefly list changes inside a bundle::
4824 - briefly list changes inside a bundle::
4828
4825
4829 hg in changes.hg -T "{desc|firstline}\\n"
4826 hg in changes.hg -T "{desc|firstline}\\n"
4830
4827
4831 Returns 0 if there are incoming changes, 1 otherwise.
4828 Returns 0 if there are incoming changes, 1 otherwise.
4832 """
4829 """
4833 if opts.get('graph'):
4830 if opts.get('graph'):
4834 cmdutil.checkunsupportedgraphflags([], opts)
4831 cmdutil.checkunsupportedgraphflags([], opts)
4835 def display(other, chlist, displayer):
4832 def display(other, chlist, displayer):
4836 revdag = cmdutil.graphrevs(other, chlist, opts)
4833 revdag = cmdutil.graphrevs(other, chlist, opts)
4837 cmdutil.displaygraph(ui, repo, revdag, displayer,
4834 cmdutil.displaygraph(ui, repo, revdag, displayer,
4838 graphmod.asciiedges)
4835 graphmod.asciiedges)
4839
4836
4840 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4837 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4841 return 0
4838 return 0
4842
4839
4843 if opts.get('bundle') and opts.get('subrepos'):
4840 if opts.get('bundle') and opts.get('subrepos'):
4844 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4841 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4845
4842
4846 if opts.get('bookmarks'):
4843 if opts.get('bookmarks'):
4847 source, branches = hg.parseurl(ui.expandpath(source),
4844 source, branches = hg.parseurl(ui.expandpath(source),
4848 opts.get('branch'))
4845 opts.get('branch'))
4849 other = hg.peer(repo, opts, source)
4846 other = hg.peer(repo, opts, source)
4850 if 'bookmarks' not in other.listkeys('namespaces'):
4847 if 'bookmarks' not in other.listkeys('namespaces'):
4851 ui.warn(_("remote doesn't support bookmarks\n"))
4848 ui.warn(_("remote doesn't support bookmarks\n"))
4852 return 0
4849 return 0
4853 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4850 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4854 return bookmarks.incoming(ui, repo, other)
4851 return bookmarks.incoming(ui, repo, other)
4855
4852
4856 repo._subtoppath = ui.expandpath(source)
4853 repo._subtoppath = ui.expandpath(source)
4857 try:
4854 try:
4858 return hg.incoming(ui, repo, source, opts)
4855 return hg.incoming(ui, repo, source, opts)
4859 finally:
4856 finally:
4860 del repo._subtoppath
4857 del repo._subtoppath
4861
4858
4862
4859
4863 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4860 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4864 norepo=True)
4861 norepo=True)
4865 def init(ui, dest=".", **opts):
4862 def init(ui, dest=".", **opts):
4866 """create a new repository in the given directory
4863 """create a new repository in the given directory
4867
4864
4868 Initialize a new repository in the given directory. If the given
4865 Initialize a new repository in the given directory. If the given
4869 directory does not exist, it will be created.
4866 directory does not exist, it will be created.
4870
4867
4871 If no directory is given, the current directory is used.
4868 If no directory is given, the current directory is used.
4872
4869
4873 It is possible to specify an ``ssh://`` URL as the destination.
4870 It is possible to specify an ``ssh://`` URL as the destination.
4874 See :hg:`help urls` for more information.
4871 See :hg:`help urls` for more information.
4875
4872
4876 Returns 0 on success.
4873 Returns 0 on success.
4877 """
4874 """
4878 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4875 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4879
4876
4880 @command('locate',
4877 @command('locate',
4881 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4878 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4882 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4879 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4883 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4880 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4884 ] + walkopts,
4881 ] + walkopts,
4885 _('[OPTION]... [PATTERN]...'))
4882 _('[OPTION]... [PATTERN]...'))
4886 def locate(ui, repo, *pats, **opts):
4883 def locate(ui, repo, *pats, **opts):
4887 """locate files matching specific patterns (DEPRECATED)
4884 """locate files matching specific patterns (DEPRECATED)
4888
4885
4889 Print files under Mercurial control in the working directory whose
4886 Print files under Mercurial control in the working directory whose
4890 names match the given patterns.
4887 names match the given patterns.
4891
4888
4892 By default, this command searches all directories in the working
4889 By default, this command searches all directories in the working
4893 directory. To search just the current directory and its
4890 directory. To search just the current directory and its
4894 subdirectories, use "--include .".
4891 subdirectories, use "--include .".
4895
4892
4896 If no patterns are given to match, this command prints the names
4893 If no patterns are given to match, this command prints the names
4897 of all files under Mercurial control in the working directory.
4894 of all files under Mercurial control in the working directory.
4898
4895
4899 If you want to feed the output of this command into the "xargs"
4896 If you want to feed the output of this command into the "xargs"
4900 command, use the -0 option to both this command and "xargs". This
4897 command, use the -0 option to both this command and "xargs". This
4901 will avoid the problem of "xargs" treating single filenames that
4898 will avoid the problem of "xargs" treating single filenames that
4902 contain whitespace as multiple filenames.
4899 contain whitespace as multiple filenames.
4903
4900
4904 See :hg:`help files` for a more versatile command.
4901 See :hg:`help files` for a more versatile command.
4905
4902
4906 Returns 0 if a match is found, 1 otherwise.
4903 Returns 0 if a match is found, 1 otherwise.
4907 """
4904 """
4908 if opts.get('print0'):
4905 if opts.get('print0'):
4909 end = '\0'
4906 end = '\0'
4910 else:
4907 else:
4911 end = '\n'
4908 end = '\n'
4912 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4909 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4913
4910
4914 ret = 1
4911 ret = 1
4915 ctx = repo[rev]
4912 ctx = repo[rev]
4916 m = scmutil.match(ctx, pats, opts, default='relglob',
4913 m = scmutil.match(ctx, pats, opts, default='relglob',
4917 badfn=lambda x, y: False)
4914 badfn=lambda x, y: False)
4918
4915
4919 for abs in ctx.matches(m):
4916 for abs in ctx.matches(m):
4920 if opts.get('fullpath'):
4917 if opts.get('fullpath'):
4921 ui.write(repo.wjoin(abs), end)
4918 ui.write(repo.wjoin(abs), end)
4922 else:
4919 else:
4923 ui.write(((pats and m.rel(abs)) or abs), end)
4920 ui.write(((pats and m.rel(abs)) or abs), end)
4924 ret = 0
4921 ret = 0
4925
4922
4926 return ret
4923 return ret
4927
4924
4928 @command('^log|history',
4925 @command('^log|history',
4929 [('f', 'follow', None,
4926 [('f', 'follow', None,
4930 _('follow changeset history, or file history across copies and renames')),
4927 _('follow changeset history, or file history across copies and renames')),
4931 ('', 'follow-first', None,
4928 ('', 'follow-first', None,
4932 _('only follow the first parent of merge changesets (DEPRECATED)')),
4929 _('only follow the first parent of merge changesets (DEPRECATED)')),
4933 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4930 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4934 ('C', 'copies', None, _('show copied files')),
4931 ('C', 'copies', None, _('show copied files')),
4935 ('k', 'keyword', [],
4932 ('k', 'keyword', [],
4936 _('do case-insensitive search for a given text'), _('TEXT')),
4933 _('do case-insensitive search for a given text'), _('TEXT')),
4937 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4934 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4938 ('', 'removed', None, _('include revisions where files were removed')),
4935 ('', 'removed', None, _('include revisions where files were removed')),
4939 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4936 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4940 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4937 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4941 ('', 'only-branch', [],
4938 ('', 'only-branch', [],
4942 _('show only changesets within the given named branch (DEPRECATED)'),
4939 _('show only changesets within the given named branch (DEPRECATED)'),
4943 _('BRANCH')),
4940 _('BRANCH')),
4944 ('b', 'branch', [],
4941 ('b', 'branch', [],
4945 _('show changesets within the given named branch'), _('BRANCH')),
4942 _('show changesets within the given named branch'), _('BRANCH')),
4946 ('P', 'prune', [],
4943 ('P', 'prune', [],
4947 _('do not display revision or any of its ancestors'), _('REV')),
4944 _('do not display revision or any of its ancestors'), _('REV')),
4948 ] + logopts + walkopts,
4945 ] + logopts + walkopts,
4949 _('[OPTION]... [FILE]'),
4946 _('[OPTION]... [FILE]'),
4950 inferrepo=True)
4947 inferrepo=True)
4951 def log(ui, repo, *pats, **opts):
4948 def log(ui, repo, *pats, **opts):
4952 """show revision history of entire repository or files
4949 """show revision history of entire repository or files
4953
4950
4954 Print the revision history of the specified files or the entire
4951 Print the revision history of the specified files or the entire
4955 project.
4952 project.
4956
4953
4957 If no revision range is specified, the default is ``tip:0`` unless
4954 If no revision range is specified, the default is ``tip:0`` unless
4958 --follow is set, in which case the working directory parent is
4955 --follow is set, in which case the working directory parent is
4959 used as the starting revision.
4956 used as the starting revision.
4960
4957
4961 File history is shown without following rename or copy history of
4958 File history is shown without following rename or copy history of
4962 files. Use -f/--follow with a filename to follow history across
4959 files. Use -f/--follow with a filename to follow history across
4963 renames and copies. --follow without a filename will only show
4960 renames and copies. --follow without a filename will only show
4964 ancestors or descendants of the starting revision.
4961 ancestors or descendants of the starting revision.
4965
4962
4966 By default this command prints revision number and changeset id,
4963 By default this command prints revision number and changeset id,
4967 tags, non-trivial parents, user, date and time, and a summary for
4964 tags, non-trivial parents, user, date and time, and a summary for
4968 each commit. When the -v/--verbose switch is used, the list of
4965 each commit. When the -v/--verbose switch is used, the list of
4969 changed files and full commit message are shown.
4966 changed files and full commit message are shown.
4970
4967
4971 With --graph the revisions are shown as an ASCII art DAG with the most
4968 With --graph the revisions are shown as an ASCII art DAG with the most
4972 recent changeset at the top.
4969 recent changeset at the top.
4973 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4970 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4974 and '+' represents a fork where the changeset from the lines below is a
4971 and '+' represents a fork where the changeset from the lines below is a
4975 parent of the 'o' merge on the same line.
4972 parent of the 'o' merge on the same line.
4976
4973
4977 .. note::
4974 .. note::
4978
4975
4979 :hg:`log --patch` may generate unexpected diff output for merge
4976 :hg:`log --patch` may generate unexpected diff output for merge
4980 changesets, as it will only compare the merge changeset against
4977 changesets, as it will only compare the merge changeset against
4981 its first parent. Also, only files different from BOTH parents
4978 its first parent. Also, only files different from BOTH parents
4982 will appear in files:.
4979 will appear in files:.
4983
4980
4984 .. note::
4981 .. note::
4985
4982
4986 For performance reasons, :hg:`log FILE` may omit duplicate changes
4983 For performance reasons, :hg:`log FILE` may omit duplicate changes
4987 made on branches and will not show removals or mode changes. To
4984 made on branches and will not show removals or mode changes. To
4988 see all such changes, use the --removed switch.
4985 see all such changes, use the --removed switch.
4989
4986
4990 .. container:: verbose
4987 .. container:: verbose
4991
4988
4992 Some examples:
4989 Some examples:
4993
4990
4994 - changesets with full descriptions and file lists::
4991 - changesets with full descriptions and file lists::
4995
4992
4996 hg log -v
4993 hg log -v
4997
4994
4998 - changesets ancestral to the working directory::
4995 - changesets ancestral to the working directory::
4999
4996
5000 hg log -f
4997 hg log -f
5001
4998
5002 - last 10 commits on the current branch::
4999 - last 10 commits on the current branch::
5003
5000
5004 hg log -l 10 -b .
5001 hg log -l 10 -b .
5005
5002
5006 - changesets showing all modifications of a file, including removals::
5003 - changesets showing all modifications of a file, including removals::
5007
5004
5008 hg log --removed file.c
5005 hg log --removed file.c
5009
5006
5010 - all changesets that touch a directory, with diffs, excluding merges::
5007 - all changesets that touch a directory, with diffs, excluding merges::
5011
5008
5012 hg log -Mp lib/
5009 hg log -Mp lib/
5013
5010
5014 - all revision numbers that match a keyword::
5011 - all revision numbers that match a keyword::
5015
5012
5016 hg log -k bug --template "{rev}\\n"
5013 hg log -k bug --template "{rev}\\n"
5017
5014
5018 - the full hash identifier of the working directory parent::
5015 - the full hash identifier of the working directory parent::
5019
5016
5020 hg log -r . --template "{node}\\n"
5017 hg log -r . --template "{node}\\n"
5021
5018
5022 - list available log templates::
5019 - list available log templates::
5023
5020
5024 hg log -T list
5021 hg log -T list
5025
5022
5026 - check if a given changeset is included in a tagged release::
5023 - check if a given changeset is included in a tagged release::
5027
5024
5028 hg log -r "a21ccf and ancestor(1.9)"
5025 hg log -r "a21ccf and ancestor(1.9)"
5029
5026
5030 - find all changesets by some user in a date range::
5027 - find all changesets by some user in a date range::
5031
5028
5032 hg log -k alice -d "may 2008 to jul 2008"
5029 hg log -k alice -d "may 2008 to jul 2008"
5033
5030
5034 - summary of all changesets after the last tag::
5031 - summary of all changesets after the last tag::
5035
5032
5036 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5033 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5037
5034
5038 See :hg:`help dates` for a list of formats valid for -d/--date.
5035 See :hg:`help dates` for a list of formats valid for -d/--date.
5039
5036
5040 See :hg:`help revisions` and :hg:`help revsets` for more about
5037 See :hg:`help revisions` and :hg:`help revsets` for more about
5041 specifying and ordering revisions.
5038 specifying and ordering revisions.
5042
5039
5043 See :hg:`help templates` for more about pre-packaged styles and
5040 See :hg:`help templates` for more about pre-packaged styles and
5044 specifying custom templates.
5041 specifying custom templates.
5045
5042
5046 Returns 0 on success.
5043 Returns 0 on success.
5047
5044
5048 """
5045 """
5049 if opts.get('follow') and opts.get('rev'):
5046 if opts.get('follow') and opts.get('rev'):
5050 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5047 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5051 del opts['follow']
5048 del opts['follow']
5052
5049
5053 if opts.get('graph'):
5050 if opts.get('graph'):
5054 return cmdutil.graphlog(ui, repo, *pats, **opts)
5051 return cmdutil.graphlog(ui, repo, *pats, **opts)
5055
5052
5056 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5053 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5057 limit = cmdutil.loglimit(opts)
5054 limit = cmdutil.loglimit(opts)
5058 count = 0
5055 count = 0
5059
5056
5060 getrenamed = None
5057 getrenamed = None
5061 if opts.get('copies'):
5058 if opts.get('copies'):
5062 endrev = None
5059 endrev = None
5063 if opts.get('rev'):
5060 if opts.get('rev'):
5064 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5061 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5065 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5062 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5066
5063
5067 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5064 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5068 for rev in revs:
5065 for rev in revs:
5069 if count == limit:
5066 if count == limit:
5070 break
5067 break
5071 ctx = repo[rev]
5068 ctx = repo[rev]
5072 copies = None
5069 copies = None
5073 if getrenamed is not None and rev:
5070 if getrenamed is not None and rev:
5074 copies = []
5071 copies = []
5075 for fn in ctx.files():
5072 for fn in ctx.files():
5076 rename = getrenamed(fn, rev)
5073 rename = getrenamed(fn, rev)
5077 if rename:
5074 if rename:
5078 copies.append((fn, rename[0]))
5075 copies.append((fn, rename[0]))
5079 if filematcher:
5076 if filematcher:
5080 revmatchfn = filematcher(ctx.rev())
5077 revmatchfn = filematcher(ctx.rev())
5081 else:
5078 else:
5082 revmatchfn = None
5079 revmatchfn = None
5083 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5080 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5084 if displayer.flush(ctx):
5081 if displayer.flush(ctx):
5085 count += 1
5082 count += 1
5086
5083
5087 displayer.close()
5084 displayer.close()
5088
5085
5089 @command('manifest',
5086 @command('manifest',
5090 [('r', 'rev', '', _('revision to display'), _('REV')),
5087 [('r', 'rev', '', _('revision to display'), _('REV')),
5091 ('', 'all', False, _("list files from all revisions"))]
5088 ('', 'all', False, _("list files from all revisions"))]
5092 + formatteropts,
5089 + formatteropts,
5093 _('[-r REV]'))
5090 _('[-r REV]'))
5094 def manifest(ui, repo, node=None, rev=None, **opts):
5091 def manifest(ui, repo, node=None, rev=None, **opts):
5095 """output the current or given revision of the project manifest
5092 """output the current or given revision of the project manifest
5096
5093
5097 Print a list of version controlled files for the given revision.
5094 Print a list of version controlled files for the given revision.
5098 If no revision is given, the first parent of the working directory
5095 If no revision is given, the first parent of the working directory
5099 is used, or the null revision if no revision is checked out.
5096 is used, or the null revision if no revision is checked out.
5100
5097
5101 With -v, print file permissions, symlink and executable bits.
5098 With -v, print file permissions, symlink and executable bits.
5102 With --debug, print file revision hashes.
5099 With --debug, print file revision hashes.
5103
5100
5104 If option --all is specified, the list of all files from all revisions
5101 If option --all is specified, the list of all files from all revisions
5105 is printed. This includes deleted and renamed files.
5102 is printed. This includes deleted and renamed files.
5106
5103
5107 Returns 0 on success.
5104 Returns 0 on success.
5108 """
5105 """
5109
5106
5110 fm = ui.formatter('manifest', opts)
5107 fm = ui.formatter('manifest', opts)
5111
5108
5112 if opts.get('all'):
5109 if opts.get('all'):
5113 if rev or node:
5110 if rev or node:
5114 raise error.Abort(_("can't specify a revision with --all"))
5111 raise error.Abort(_("can't specify a revision with --all"))
5115
5112
5116 res = []
5113 res = []
5117 prefix = "data/"
5114 prefix = "data/"
5118 suffix = ".i"
5115 suffix = ".i"
5119 plen = len(prefix)
5116 plen = len(prefix)
5120 slen = len(suffix)
5117 slen = len(suffix)
5121 with repo.lock():
5118 with repo.lock():
5122 for fn, b, size in repo.store.datafiles():
5119 for fn, b, size in repo.store.datafiles():
5123 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5120 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5124 res.append(fn[plen:-slen])
5121 res.append(fn[plen:-slen])
5125 for f in res:
5122 for f in res:
5126 fm.startitem()
5123 fm.startitem()
5127 fm.write("path", '%s\n', f)
5124 fm.write("path", '%s\n', f)
5128 fm.end()
5125 fm.end()
5129 return
5126 return
5130
5127
5131 if rev and node:
5128 if rev and node:
5132 raise error.Abort(_("please specify just one revision"))
5129 raise error.Abort(_("please specify just one revision"))
5133
5130
5134 if not node:
5131 if not node:
5135 node = rev
5132 node = rev
5136
5133
5137 char = {'l': '@', 'x': '*', '': ''}
5134 char = {'l': '@', 'x': '*', '': ''}
5138 mode = {'l': '644', 'x': '755', '': '644'}
5135 mode = {'l': '644', 'x': '755', '': '644'}
5139 ctx = scmutil.revsingle(repo, node)
5136 ctx = scmutil.revsingle(repo, node)
5140 mf = ctx.manifest()
5137 mf = ctx.manifest()
5141 for f in ctx:
5138 for f in ctx:
5142 fm.startitem()
5139 fm.startitem()
5143 fl = ctx[f].flags()
5140 fl = ctx[f].flags()
5144 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5141 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5145 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5142 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5146 fm.write('path', '%s\n', f)
5143 fm.write('path', '%s\n', f)
5147 fm.end()
5144 fm.end()
5148
5145
5149 @command('^merge',
5146 @command('^merge',
5150 [('f', 'force', None,
5147 [('f', 'force', None,
5151 _('force a merge including outstanding changes (DEPRECATED)')),
5148 _('force a merge including outstanding changes (DEPRECATED)')),
5152 ('r', 'rev', '', _('revision to merge'), _('REV')),
5149 ('r', 'rev', '', _('revision to merge'), _('REV')),
5153 ('P', 'preview', None,
5150 ('P', 'preview', None,
5154 _('review revisions to merge (no merge is performed)'))
5151 _('review revisions to merge (no merge is performed)'))
5155 ] + mergetoolopts,
5152 ] + mergetoolopts,
5156 _('[-P] [-f] [[-r] REV]'))
5153 _('[-P] [-f] [[-r] REV]'))
5157 def merge(ui, repo, node=None, **opts):
5154 def merge(ui, repo, node=None, **opts):
5158 """merge another revision into working directory
5155 """merge another revision into working directory
5159
5156
5160 The current working directory is updated with all changes made in
5157 The current working directory is updated with all changes made in
5161 the requested revision since the last common predecessor revision.
5158 the requested revision since the last common predecessor revision.
5162
5159
5163 Files that changed between either parent are marked as changed for
5160 Files that changed between either parent are marked as changed for
5164 the next commit and a commit must be performed before any further
5161 the next commit and a commit must be performed before any further
5165 updates to the repository are allowed. The next commit will have
5162 updates to the repository are allowed. The next commit will have
5166 two parents.
5163 two parents.
5167
5164
5168 ``--tool`` can be used to specify the merge tool used for file
5165 ``--tool`` can be used to specify the merge tool used for file
5169 merges. It overrides the HGMERGE environment variable and your
5166 merges. It overrides the HGMERGE environment variable and your
5170 configuration files. See :hg:`help merge-tools` for options.
5167 configuration files. See :hg:`help merge-tools` for options.
5171
5168
5172 If no revision is specified, the working directory's parent is a
5169 If no revision is specified, the working directory's parent is a
5173 head revision, and the current branch contains exactly one other
5170 head revision, and the current branch contains exactly one other
5174 head, the other head is merged with by default. Otherwise, an
5171 head, the other head is merged with by default. Otherwise, an
5175 explicit revision with which to merge with must be provided.
5172 explicit revision with which to merge with must be provided.
5176
5173
5177 See :hg:`help resolve` for information on handling file conflicts.
5174 See :hg:`help resolve` for information on handling file conflicts.
5178
5175
5179 To undo an uncommitted merge, use :hg:`update --clean .` which
5176 To undo an uncommitted merge, use :hg:`update --clean .` which
5180 will check out a clean copy of the original merge parent, losing
5177 will check out a clean copy of the original merge parent, losing
5181 all changes.
5178 all changes.
5182
5179
5183 Returns 0 on success, 1 if there are unresolved files.
5180 Returns 0 on success, 1 if there are unresolved files.
5184 """
5181 """
5185
5182
5186 if opts.get('rev') and node:
5183 if opts.get('rev') and node:
5187 raise error.Abort(_("please specify just one revision"))
5184 raise error.Abort(_("please specify just one revision"))
5188 if not node:
5185 if not node:
5189 node = opts.get('rev')
5186 node = opts.get('rev')
5190
5187
5191 if node:
5188 if node:
5192 node = scmutil.revsingle(repo, node).node()
5189 node = scmutil.revsingle(repo, node).node()
5193
5190
5194 if not node:
5191 if not node:
5195 node = repo[destutil.destmerge(repo)].node()
5192 node = repo[destutil.destmerge(repo)].node()
5196
5193
5197 if opts.get('preview'):
5194 if opts.get('preview'):
5198 # find nodes that are ancestors of p2 but not of p1
5195 # find nodes that are ancestors of p2 but not of p1
5199 p1 = repo.lookup('.')
5196 p1 = repo.lookup('.')
5200 p2 = repo.lookup(node)
5197 p2 = repo.lookup(node)
5201 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5198 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5202
5199
5203 displayer = cmdutil.show_changeset(ui, repo, opts)
5200 displayer = cmdutil.show_changeset(ui, repo, opts)
5204 for node in nodes:
5201 for node in nodes:
5205 displayer.show(repo[node])
5202 displayer.show(repo[node])
5206 displayer.close()
5203 displayer.close()
5207 return 0
5204 return 0
5208
5205
5209 try:
5206 try:
5210 # ui.forcemerge is an internal variable, do not document
5207 # ui.forcemerge is an internal variable, do not document
5211 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5208 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5212 return hg.merge(repo, node, force=opts.get('force'))
5209 return hg.merge(repo, node, force=opts.get('force'))
5213 finally:
5210 finally:
5214 ui.setconfig('ui', 'forcemerge', '', 'merge')
5211 ui.setconfig('ui', 'forcemerge', '', 'merge')
5215
5212
5216 @command('outgoing|out',
5213 @command('outgoing|out',
5217 [('f', 'force', None, _('run even when the destination is unrelated')),
5214 [('f', 'force', None, _('run even when the destination is unrelated')),
5218 ('r', 'rev', [],
5215 ('r', 'rev', [],
5219 _('a changeset intended to be included in the destination'), _('REV')),
5216 _('a changeset intended to be included in the destination'), _('REV')),
5220 ('n', 'newest-first', None, _('show newest record first')),
5217 ('n', 'newest-first', None, _('show newest record first')),
5221 ('B', 'bookmarks', False, _('compare bookmarks')),
5218 ('B', 'bookmarks', False, _('compare bookmarks')),
5222 ('b', 'branch', [], _('a specific branch you would like to push'),
5219 ('b', 'branch', [], _('a specific branch you would like to push'),
5223 _('BRANCH')),
5220 _('BRANCH')),
5224 ] + logopts + remoteopts + subrepoopts,
5221 ] + logopts + remoteopts + subrepoopts,
5225 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5222 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5226 def outgoing(ui, repo, dest=None, **opts):
5223 def outgoing(ui, repo, dest=None, **opts):
5227 """show changesets not found in the destination
5224 """show changesets not found in the destination
5228
5225
5229 Show changesets not found in the specified destination repository
5226 Show changesets not found in the specified destination repository
5230 or the default push location. These are the changesets that would
5227 or the default push location. These are the changesets that would
5231 be pushed if a push was requested.
5228 be pushed if a push was requested.
5232
5229
5233 See pull for details of valid destination formats.
5230 See pull for details of valid destination formats.
5234
5231
5235 .. container:: verbose
5232 .. container:: verbose
5236
5233
5237 With -B/--bookmarks, the result of bookmark comparison between
5234 With -B/--bookmarks, the result of bookmark comparison between
5238 local and remote repositories is displayed. With -v/--verbose,
5235 local and remote repositories is displayed. With -v/--verbose,
5239 status is also displayed for each bookmark like below::
5236 status is also displayed for each bookmark like below::
5240
5237
5241 BM1 01234567890a added
5238 BM1 01234567890a added
5242 BM2 deleted
5239 BM2 deleted
5243 BM3 234567890abc advanced
5240 BM3 234567890abc advanced
5244 BM4 34567890abcd diverged
5241 BM4 34567890abcd diverged
5245 BM5 4567890abcde changed
5242 BM5 4567890abcde changed
5246
5243
5247 The action taken when pushing depends on the
5244 The action taken when pushing depends on the
5248 status of each bookmark:
5245 status of each bookmark:
5249
5246
5250 :``added``: push with ``-B`` will create it
5247 :``added``: push with ``-B`` will create it
5251 :``deleted``: push with ``-B`` will delete it
5248 :``deleted``: push with ``-B`` will delete it
5252 :``advanced``: push will update it
5249 :``advanced``: push will update it
5253 :``diverged``: push with ``-B`` will update it
5250 :``diverged``: push with ``-B`` will update it
5254 :``changed``: push with ``-B`` will update it
5251 :``changed``: push with ``-B`` will update it
5255
5252
5256 From the point of view of pushing behavior, bookmarks
5253 From the point of view of pushing behavior, bookmarks
5257 existing only in the remote repository are treated as
5254 existing only in the remote repository are treated as
5258 ``deleted``, even if it is in fact added remotely.
5255 ``deleted``, even if it is in fact added remotely.
5259
5256
5260 Returns 0 if there are outgoing changes, 1 otherwise.
5257 Returns 0 if there are outgoing changes, 1 otherwise.
5261 """
5258 """
5262 if opts.get('graph'):
5259 if opts.get('graph'):
5263 cmdutil.checkunsupportedgraphflags([], opts)
5260 cmdutil.checkunsupportedgraphflags([], opts)
5264 o, other = hg._outgoing(ui, repo, dest, opts)
5261 o, other = hg._outgoing(ui, repo, dest, opts)
5265 if not o:
5262 if not o:
5266 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5263 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5267 return
5264 return
5268
5265
5269 revdag = cmdutil.graphrevs(repo, o, opts)
5266 revdag = cmdutil.graphrevs(repo, o, opts)
5270 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5267 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5271 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5268 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5272 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5269 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5273 return 0
5270 return 0
5274
5271
5275 if opts.get('bookmarks'):
5272 if opts.get('bookmarks'):
5276 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5273 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5277 dest, branches = hg.parseurl(dest, opts.get('branch'))
5274 dest, branches = hg.parseurl(dest, opts.get('branch'))
5278 other = hg.peer(repo, opts, dest)
5275 other = hg.peer(repo, opts, dest)
5279 if 'bookmarks' not in other.listkeys('namespaces'):
5276 if 'bookmarks' not in other.listkeys('namespaces'):
5280 ui.warn(_("remote doesn't support bookmarks\n"))
5277 ui.warn(_("remote doesn't support bookmarks\n"))
5281 return 0
5278 return 0
5282 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5279 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5283 return bookmarks.outgoing(ui, repo, other)
5280 return bookmarks.outgoing(ui, repo, other)
5284
5281
5285 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5282 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5286 try:
5283 try:
5287 return hg.outgoing(ui, repo, dest, opts)
5284 return hg.outgoing(ui, repo, dest, opts)
5288 finally:
5285 finally:
5289 del repo._subtoppath
5286 del repo._subtoppath
5290
5287
5291 @command('parents',
5288 @command('parents',
5292 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5289 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5293 ] + templateopts,
5290 ] + templateopts,
5294 _('[-r REV] [FILE]'),
5291 _('[-r REV] [FILE]'),
5295 inferrepo=True)
5292 inferrepo=True)
5296 def parents(ui, repo, file_=None, **opts):
5293 def parents(ui, repo, file_=None, **opts):
5297 """show the parents of the working directory or revision (DEPRECATED)
5294 """show the parents of the working directory or revision (DEPRECATED)
5298
5295
5299 Print the working directory's parent revisions. If a revision is
5296 Print the working directory's parent revisions. If a revision is
5300 given via -r/--rev, the parent of that revision will be printed.
5297 given via -r/--rev, the parent of that revision will be printed.
5301 If a file argument is given, the revision in which the file was
5298 If a file argument is given, the revision in which the file was
5302 last changed (before the working directory revision or the
5299 last changed (before the working directory revision or the
5303 argument to --rev if given) is printed.
5300 argument to --rev if given) is printed.
5304
5301
5305 This command is equivalent to::
5302 This command is equivalent to::
5306
5303
5307 hg log -r "p1()+p2()" or
5304 hg log -r "p1()+p2()" or
5308 hg log -r "p1(REV)+p2(REV)" or
5305 hg log -r "p1(REV)+p2(REV)" or
5309 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5306 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5310 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5307 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5311
5308
5312 See :hg:`summary` and :hg:`help revsets` for related information.
5309 See :hg:`summary` and :hg:`help revsets` for related information.
5313
5310
5314 Returns 0 on success.
5311 Returns 0 on success.
5315 """
5312 """
5316
5313
5317 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5314 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5318
5315
5319 if file_:
5316 if file_:
5320 m = scmutil.match(ctx, (file_,), opts)
5317 m = scmutil.match(ctx, (file_,), opts)
5321 if m.anypats() or len(m.files()) != 1:
5318 if m.anypats() or len(m.files()) != 1:
5322 raise error.Abort(_('can only specify an explicit filename'))
5319 raise error.Abort(_('can only specify an explicit filename'))
5323 file_ = m.files()[0]
5320 file_ = m.files()[0]
5324 filenodes = []
5321 filenodes = []
5325 for cp in ctx.parents():
5322 for cp in ctx.parents():
5326 if not cp:
5323 if not cp:
5327 continue
5324 continue
5328 try:
5325 try:
5329 filenodes.append(cp.filenode(file_))
5326 filenodes.append(cp.filenode(file_))
5330 except error.LookupError:
5327 except error.LookupError:
5331 pass
5328 pass
5332 if not filenodes:
5329 if not filenodes:
5333 raise error.Abort(_("'%s' not found in manifest!") % file_)
5330 raise error.Abort(_("'%s' not found in manifest!") % file_)
5334 p = []
5331 p = []
5335 for fn in filenodes:
5332 for fn in filenodes:
5336 fctx = repo.filectx(file_, fileid=fn)
5333 fctx = repo.filectx(file_, fileid=fn)
5337 p.append(fctx.node())
5334 p.append(fctx.node())
5338 else:
5335 else:
5339 p = [cp.node() for cp in ctx.parents()]
5336 p = [cp.node() for cp in ctx.parents()]
5340
5337
5341 displayer = cmdutil.show_changeset(ui, repo, opts)
5338 displayer = cmdutil.show_changeset(ui, repo, opts)
5342 for n in p:
5339 for n in p:
5343 if n != nullid:
5340 if n != nullid:
5344 displayer.show(repo[n])
5341 displayer.show(repo[n])
5345 displayer.close()
5342 displayer.close()
5346
5343
5347 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5344 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5348 def paths(ui, repo, search=None, **opts):
5345 def paths(ui, repo, search=None, **opts):
5349 """show aliases for remote repositories
5346 """show aliases for remote repositories
5350
5347
5351 Show definition of symbolic path name NAME. If no name is given,
5348 Show definition of symbolic path name NAME. If no name is given,
5352 show definition of all available names.
5349 show definition of all available names.
5353
5350
5354 Option -q/--quiet suppresses all output when searching for NAME
5351 Option -q/--quiet suppresses all output when searching for NAME
5355 and shows only the path names when listing all definitions.
5352 and shows only the path names when listing all definitions.
5356
5353
5357 Path names are defined in the [paths] section of your
5354 Path names are defined in the [paths] section of your
5358 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5355 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5359 repository, ``.hg/hgrc`` is used, too.
5356 repository, ``.hg/hgrc`` is used, too.
5360
5357
5361 The path names ``default`` and ``default-push`` have a special
5358 The path names ``default`` and ``default-push`` have a special
5362 meaning. When performing a push or pull operation, they are used
5359 meaning. When performing a push or pull operation, they are used
5363 as fallbacks if no location is specified on the command-line.
5360 as fallbacks if no location is specified on the command-line.
5364 When ``default-push`` is set, it will be used for push and
5361 When ``default-push`` is set, it will be used for push and
5365 ``default`` will be used for pull; otherwise ``default`` is used
5362 ``default`` will be used for pull; otherwise ``default`` is used
5366 as the fallback for both. When cloning a repository, the clone
5363 as the fallback for both. When cloning a repository, the clone
5367 source is written as ``default`` in ``.hg/hgrc``.
5364 source is written as ``default`` in ``.hg/hgrc``.
5368
5365
5369 .. note::
5366 .. note::
5370
5367
5371 ``default`` and ``default-push`` apply to all inbound (e.g.
5368 ``default`` and ``default-push`` apply to all inbound (e.g.
5372 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5369 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5373 and :hg:`bundle`) operations.
5370 and :hg:`bundle`) operations.
5374
5371
5375 See :hg:`help urls` for more information.
5372 See :hg:`help urls` for more information.
5376
5373
5377 Returns 0 on success.
5374 Returns 0 on success.
5378 """
5375 """
5379 if search:
5376 if search:
5380 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5377 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5381 if name == search]
5378 if name == search]
5382 else:
5379 else:
5383 pathitems = sorted(ui.paths.iteritems())
5380 pathitems = sorted(ui.paths.iteritems())
5384
5381
5385 fm = ui.formatter('paths', opts)
5382 fm = ui.formatter('paths', opts)
5386 if fm:
5383 if fm:
5387 hidepassword = str
5384 hidepassword = str
5388 else:
5385 else:
5389 hidepassword = util.hidepassword
5386 hidepassword = util.hidepassword
5390 if ui.quiet:
5387 if ui.quiet:
5391 namefmt = '%s\n'
5388 namefmt = '%s\n'
5392 else:
5389 else:
5393 namefmt = '%s = '
5390 namefmt = '%s = '
5394 showsubopts = not search and not ui.quiet
5391 showsubopts = not search and not ui.quiet
5395
5392
5396 for name, path in pathitems:
5393 for name, path in pathitems:
5397 fm.startitem()
5394 fm.startitem()
5398 fm.condwrite(not search, 'name', namefmt, name)
5395 fm.condwrite(not search, 'name', namefmt, name)
5399 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5396 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5400 for subopt, value in sorted(path.suboptions.items()):
5397 for subopt, value in sorted(path.suboptions.items()):
5401 assert subopt not in ('name', 'url')
5398 assert subopt not in ('name', 'url')
5402 if showsubopts:
5399 if showsubopts:
5403 fm.plain('%s:%s = ' % (name, subopt))
5400 fm.plain('%s:%s = ' % (name, subopt))
5404 fm.condwrite(showsubopts, subopt, '%s\n', value)
5401 fm.condwrite(showsubopts, subopt, '%s\n', value)
5405
5402
5406 fm.end()
5403 fm.end()
5407
5404
5408 if search and not pathitems:
5405 if search and not pathitems:
5409 if not ui.quiet:
5406 if not ui.quiet:
5410 ui.warn(_("not found!\n"))
5407 ui.warn(_("not found!\n"))
5411 return 1
5408 return 1
5412 else:
5409 else:
5413 return 0
5410 return 0
5414
5411
5415 @command('phase',
5412 @command('phase',
5416 [('p', 'public', False, _('set changeset phase to public')),
5413 [('p', 'public', False, _('set changeset phase to public')),
5417 ('d', 'draft', False, _('set changeset phase to draft')),
5414 ('d', 'draft', False, _('set changeset phase to draft')),
5418 ('s', 'secret', False, _('set changeset phase to secret')),
5415 ('s', 'secret', False, _('set changeset phase to secret')),
5419 ('f', 'force', False, _('allow to move boundary backward')),
5416 ('f', 'force', False, _('allow to move boundary backward')),
5420 ('r', 'rev', [], _('target revision'), _('REV')),
5417 ('r', 'rev', [], _('target revision'), _('REV')),
5421 ],
5418 ],
5422 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5419 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5423 def phase(ui, repo, *revs, **opts):
5420 def phase(ui, repo, *revs, **opts):
5424 """set or show the current phase name
5421 """set or show the current phase name
5425
5422
5426 With no argument, show the phase name of the current revision(s).
5423 With no argument, show the phase name of the current revision(s).
5427
5424
5428 With one of -p/--public, -d/--draft or -s/--secret, change the
5425 With one of -p/--public, -d/--draft or -s/--secret, change the
5429 phase value of the specified revisions.
5426 phase value of the specified revisions.
5430
5427
5431 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5428 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5432 lower phase to an higher phase. Phases are ordered as follows::
5429 lower phase to an higher phase. Phases are ordered as follows::
5433
5430
5434 public < draft < secret
5431 public < draft < secret
5435
5432
5436 Returns 0 on success, 1 if some phases could not be changed.
5433 Returns 0 on success, 1 if some phases could not be changed.
5437
5434
5438 (For more information about the phases concept, see :hg:`help phases`.)
5435 (For more information about the phases concept, see :hg:`help phases`.)
5439 """
5436 """
5440 # search for a unique phase argument
5437 # search for a unique phase argument
5441 targetphase = None
5438 targetphase = None
5442 for idx, name in enumerate(phases.phasenames):
5439 for idx, name in enumerate(phases.phasenames):
5443 if opts[name]:
5440 if opts[name]:
5444 if targetphase is not None:
5441 if targetphase is not None:
5445 raise error.Abort(_('only one phase can be specified'))
5442 raise error.Abort(_('only one phase can be specified'))
5446 targetphase = idx
5443 targetphase = idx
5447
5444
5448 # look for specified revision
5445 # look for specified revision
5449 revs = list(revs)
5446 revs = list(revs)
5450 revs.extend(opts['rev'])
5447 revs.extend(opts['rev'])
5451 if not revs:
5448 if not revs:
5452 # display both parents as the second parent phase can influence
5449 # display both parents as the second parent phase can influence
5453 # the phase of a merge commit
5450 # the phase of a merge commit
5454 revs = [c.rev() for c in repo[None].parents()]
5451 revs = [c.rev() for c in repo[None].parents()]
5455
5452
5456 revs = scmutil.revrange(repo, revs)
5453 revs = scmutil.revrange(repo, revs)
5457
5454
5458 lock = None
5455 lock = None
5459 ret = 0
5456 ret = 0
5460 if targetphase is None:
5457 if targetphase is None:
5461 # display
5458 # display
5462 for r in revs:
5459 for r in revs:
5463 ctx = repo[r]
5460 ctx = repo[r]
5464 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5461 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5465 else:
5462 else:
5466 tr = None
5463 tr = None
5467 lock = repo.lock()
5464 lock = repo.lock()
5468 try:
5465 try:
5469 tr = repo.transaction("phase")
5466 tr = repo.transaction("phase")
5470 # set phase
5467 # set phase
5471 if not revs:
5468 if not revs:
5472 raise error.Abort(_('empty revision set'))
5469 raise error.Abort(_('empty revision set'))
5473 nodes = [repo[r].node() for r in revs]
5470 nodes = [repo[r].node() for r in revs]
5474 # moving revision from public to draft may hide them
5471 # moving revision from public to draft may hide them
5475 # We have to check result on an unfiltered repository
5472 # We have to check result on an unfiltered repository
5476 unfi = repo.unfiltered()
5473 unfi = repo.unfiltered()
5477 getphase = unfi._phasecache.phase
5474 getphase = unfi._phasecache.phase
5478 olddata = [getphase(unfi, r) for r in unfi]
5475 olddata = [getphase(unfi, r) for r in unfi]
5479 phases.advanceboundary(repo, tr, targetphase, nodes)
5476 phases.advanceboundary(repo, tr, targetphase, nodes)
5480 if opts['force']:
5477 if opts['force']:
5481 phases.retractboundary(repo, tr, targetphase, nodes)
5478 phases.retractboundary(repo, tr, targetphase, nodes)
5482 tr.close()
5479 tr.close()
5483 finally:
5480 finally:
5484 if tr is not None:
5481 if tr is not None:
5485 tr.release()
5482 tr.release()
5486 lock.release()
5483 lock.release()
5487 getphase = unfi._phasecache.phase
5484 getphase = unfi._phasecache.phase
5488 newdata = [getphase(unfi, r) for r in unfi]
5485 newdata = [getphase(unfi, r) for r in unfi]
5489 changes = sum(newdata[r] != olddata[r] for r in unfi)
5486 changes = sum(newdata[r] != olddata[r] for r in unfi)
5490 cl = unfi.changelog
5487 cl = unfi.changelog
5491 rejected = [n for n in nodes
5488 rejected = [n for n in nodes
5492 if newdata[cl.rev(n)] < targetphase]
5489 if newdata[cl.rev(n)] < targetphase]
5493 if rejected:
5490 if rejected:
5494 ui.warn(_('cannot move %i changesets to a higher '
5491 ui.warn(_('cannot move %i changesets to a higher '
5495 'phase, use --force\n') % len(rejected))
5492 'phase, use --force\n') % len(rejected))
5496 ret = 1
5493 ret = 1
5497 if changes:
5494 if changes:
5498 msg = _('phase changed for %i changesets\n') % changes
5495 msg = _('phase changed for %i changesets\n') % changes
5499 if ret:
5496 if ret:
5500 ui.status(msg)
5497 ui.status(msg)
5501 else:
5498 else:
5502 ui.note(msg)
5499 ui.note(msg)
5503 else:
5500 else:
5504 ui.warn(_('no phases changed\n'))
5501 ui.warn(_('no phases changed\n'))
5505 return ret
5502 return ret
5506
5503
5507 def postincoming(ui, repo, modheads, optupdate, checkout):
5504 def postincoming(ui, repo, modheads, optupdate, checkout):
5508 if modheads == 0:
5505 if modheads == 0:
5509 return
5506 return
5510 if optupdate:
5507 if optupdate:
5511 try:
5508 try:
5512 brev = checkout
5509 brev = checkout
5513 movemarkfrom = None
5510 movemarkfrom = None
5514 if not checkout:
5511 if not checkout:
5515 updata = destutil.destupdate(repo)
5512 updata = destutil.destupdate(repo)
5516 checkout, movemarkfrom, brev = updata
5513 checkout, movemarkfrom, brev = updata
5517 ret = hg.update(repo, checkout)
5514 ret = hg.update(repo, checkout)
5518 except error.UpdateAbort as inst:
5515 except error.UpdateAbort as inst:
5519 msg = _("not updating: %s") % str(inst)
5516 msg = _("not updating: %s") % str(inst)
5520 hint = inst.hint
5517 hint = inst.hint
5521 raise error.UpdateAbort(msg, hint=hint)
5518 raise error.UpdateAbort(msg, hint=hint)
5522 if not ret and not checkout:
5519 if not ret and not checkout:
5523 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5520 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5524 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5521 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5525 return ret
5522 return ret
5526 if modheads > 1:
5523 if modheads > 1:
5527 currentbranchheads = len(repo.branchheads())
5524 currentbranchheads = len(repo.branchheads())
5528 if currentbranchheads == modheads:
5525 if currentbranchheads == modheads:
5529 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5526 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5530 elif currentbranchheads > 1:
5527 elif currentbranchheads > 1:
5531 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5528 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5532 "merge)\n"))
5529 "merge)\n"))
5533 else:
5530 else:
5534 ui.status(_("(run 'hg heads' to see heads)\n"))
5531 ui.status(_("(run 'hg heads' to see heads)\n"))
5535 else:
5532 else:
5536 ui.status(_("(run 'hg update' to get a working copy)\n"))
5533 ui.status(_("(run 'hg update' to get a working copy)\n"))
5537
5534
5538 @command('^pull',
5535 @command('^pull',
5539 [('u', 'update', None,
5536 [('u', 'update', None,
5540 _('update to new branch head if changesets were pulled')),
5537 _('update to new branch head if changesets were pulled')),
5541 ('f', 'force', None, _('run even when remote repository is unrelated')),
5538 ('f', 'force', None, _('run even when remote repository is unrelated')),
5542 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5539 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5543 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5540 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5544 ('b', 'branch', [], _('a specific branch you would like to pull'),
5541 ('b', 'branch', [], _('a specific branch you would like to pull'),
5545 _('BRANCH')),
5542 _('BRANCH')),
5546 ] + remoteopts,
5543 ] + remoteopts,
5547 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5544 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5548 def pull(ui, repo, source="default", **opts):
5545 def pull(ui, repo, source="default", **opts):
5549 """pull changes from the specified source
5546 """pull changes from the specified source
5550
5547
5551 Pull changes from a remote repository to a local one.
5548 Pull changes from a remote repository to a local one.
5552
5549
5553 This finds all changes from the repository at the specified path
5550 This finds all changes from the repository at the specified path
5554 or URL and adds them to a local repository (the current one unless
5551 or URL and adds them to a local repository (the current one unless
5555 -R is specified). By default, this does not update the copy of the
5552 -R is specified). By default, this does not update the copy of the
5556 project in the working directory.
5553 project in the working directory.
5557
5554
5558 Use :hg:`incoming` if you want to see what would have been added
5555 Use :hg:`incoming` if you want to see what would have been added
5559 by a pull at the time you issued this command. If you then decide
5556 by a pull at the time you issued this command. If you then decide
5560 to add those changes to the repository, you should use :hg:`pull
5557 to add those changes to the repository, you should use :hg:`pull
5561 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5558 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5562
5559
5563 If SOURCE is omitted, the 'default' path will be used.
5560 If SOURCE is omitted, the 'default' path will be used.
5564 See :hg:`help urls` for more information.
5561 See :hg:`help urls` for more information.
5565
5562
5566 Returns 0 on success, 1 if an update had unresolved files.
5563 Returns 0 on success, 1 if an update had unresolved files.
5567 """
5564 """
5568 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5565 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5569 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5566 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5570 other = hg.peer(repo, opts, source)
5567 other = hg.peer(repo, opts, source)
5571 try:
5568 try:
5572 revs, checkout = hg.addbranchrevs(repo, other, branches,
5569 revs, checkout = hg.addbranchrevs(repo, other, branches,
5573 opts.get('rev'))
5570 opts.get('rev'))
5574
5571
5575
5572
5576 pullopargs = {}
5573 pullopargs = {}
5577 if opts.get('bookmark'):
5574 if opts.get('bookmark'):
5578 if not revs:
5575 if not revs:
5579 revs = []
5576 revs = []
5580 # The list of bookmark used here is not the one used to actually
5577 # The list of bookmark used here is not the one used to actually
5581 # update the bookmark name. This can result in the revision pulled
5578 # update the bookmark name. This can result in the revision pulled
5582 # not ending up with the name of the bookmark because of a race
5579 # not ending up with the name of the bookmark because of a race
5583 # condition on the server. (See issue 4689 for details)
5580 # condition on the server. (See issue 4689 for details)
5584 remotebookmarks = other.listkeys('bookmarks')
5581 remotebookmarks = other.listkeys('bookmarks')
5585 pullopargs['remotebookmarks'] = remotebookmarks
5582 pullopargs['remotebookmarks'] = remotebookmarks
5586 for b in opts['bookmark']:
5583 for b in opts['bookmark']:
5587 if b not in remotebookmarks:
5584 if b not in remotebookmarks:
5588 raise error.Abort(_('remote bookmark %s not found!') % b)
5585 raise error.Abort(_('remote bookmark %s not found!') % b)
5589 revs.append(remotebookmarks[b])
5586 revs.append(remotebookmarks[b])
5590
5587
5591 if revs:
5588 if revs:
5592 try:
5589 try:
5593 # When 'rev' is a bookmark name, we cannot guarantee that it
5590 # When 'rev' is a bookmark name, we cannot guarantee that it
5594 # will be updated with that name because of a race condition
5591 # will be updated with that name because of a race condition
5595 # server side. (See issue 4689 for details)
5592 # server side. (See issue 4689 for details)
5596 oldrevs = revs
5593 oldrevs = revs
5597 revs = [] # actually, nodes
5594 revs = [] # actually, nodes
5598 for r in oldrevs:
5595 for r in oldrevs:
5599 node = other.lookup(r)
5596 node = other.lookup(r)
5600 revs.append(node)
5597 revs.append(node)
5601 if r == checkout:
5598 if r == checkout:
5602 checkout = node
5599 checkout = node
5603 except error.CapabilityError:
5600 except error.CapabilityError:
5604 err = _("other repository doesn't support revision lookup, "
5601 err = _("other repository doesn't support revision lookup, "
5605 "so a rev cannot be specified.")
5602 "so a rev cannot be specified.")
5606 raise error.Abort(err)
5603 raise error.Abort(err)
5607
5604
5608 pullopargs.update(opts.get('opargs', {}))
5605 pullopargs.update(opts.get('opargs', {}))
5609 modheads = exchange.pull(repo, other, heads=revs,
5606 modheads = exchange.pull(repo, other, heads=revs,
5610 force=opts.get('force'),
5607 force=opts.get('force'),
5611 bookmarks=opts.get('bookmark', ()),
5608 bookmarks=opts.get('bookmark', ()),
5612 opargs=pullopargs).cgresult
5609 opargs=pullopargs).cgresult
5613 if checkout:
5610 if checkout:
5614 checkout = str(repo.changelog.rev(checkout))
5611 checkout = str(repo.changelog.rev(checkout))
5615 repo._subtoppath = source
5612 repo._subtoppath = source
5616 try:
5613 try:
5617 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5614 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5618
5615
5619 finally:
5616 finally:
5620 del repo._subtoppath
5617 del repo._subtoppath
5621
5618
5622 finally:
5619 finally:
5623 other.close()
5620 other.close()
5624 return ret
5621 return ret
5625
5622
5626 @command('^push',
5623 @command('^push',
5627 [('f', 'force', None, _('force push')),
5624 [('f', 'force', None, _('force push')),
5628 ('r', 'rev', [],
5625 ('r', 'rev', [],
5629 _('a changeset intended to be included in the destination'),
5626 _('a changeset intended to be included in the destination'),
5630 _('REV')),
5627 _('REV')),
5631 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5628 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5632 ('b', 'branch', [],
5629 ('b', 'branch', [],
5633 _('a specific branch you would like to push'), _('BRANCH')),
5630 _('a specific branch you would like to push'), _('BRANCH')),
5634 ('', 'new-branch', False, _('allow pushing a new branch')),
5631 ('', 'new-branch', False, _('allow pushing a new branch')),
5635 ] + remoteopts,
5632 ] + remoteopts,
5636 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5633 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5637 def push(ui, repo, dest=None, **opts):
5634 def push(ui, repo, dest=None, **opts):
5638 """push changes to the specified destination
5635 """push changes to the specified destination
5639
5636
5640 Push changesets from the local repository to the specified
5637 Push changesets from the local repository to the specified
5641 destination.
5638 destination.
5642
5639
5643 This operation is symmetrical to pull: it is identical to a pull
5640 This operation is symmetrical to pull: it is identical to a pull
5644 in the destination repository from the current one.
5641 in the destination repository from the current one.
5645
5642
5646 By default, push will not allow creation of new heads at the
5643 By default, push will not allow creation of new heads at the
5647 destination, since multiple heads would make it unclear which head
5644 destination, since multiple heads would make it unclear which head
5648 to use. In this situation, it is recommended to pull and merge
5645 to use. In this situation, it is recommended to pull and merge
5649 before pushing.
5646 before pushing.
5650
5647
5651 Use --new-branch if you want to allow push to create a new named
5648 Use --new-branch if you want to allow push to create a new named
5652 branch that is not present at the destination. This allows you to
5649 branch that is not present at the destination. This allows you to
5653 only create a new branch without forcing other changes.
5650 only create a new branch without forcing other changes.
5654
5651
5655 .. note::
5652 .. note::
5656
5653
5657 Extra care should be taken with the -f/--force option,
5654 Extra care should be taken with the -f/--force option,
5658 which will push all new heads on all branches, an action which will
5655 which will push all new heads on all branches, an action which will
5659 almost always cause confusion for collaborators.
5656 almost always cause confusion for collaborators.
5660
5657
5661 If -r/--rev is used, the specified revision and all its ancestors
5658 If -r/--rev is used, the specified revision and all its ancestors
5662 will be pushed to the remote repository.
5659 will be pushed to the remote repository.
5663
5660
5664 If -B/--bookmark is used, the specified bookmarked revision, its
5661 If -B/--bookmark is used, the specified bookmarked revision, its
5665 ancestors, and the bookmark will be pushed to the remote
5662 ancestors, and the bookmark will be pushed to the remote
5666 repository.
5663 repository.
5667
5664
5668 Please see :hg:`help urls` for important details about ``ssh://``
5665 Please see :hg:`help urls` for important details about ``ssh://``
5669 URLs. If DESTINATION is omitted, a default path will be used.
5666 URLs. If DESTINATION is omitted, a default path will be used.
5670
5667
5671 Returns 0 if push was successful, 1 if nothing to push.
5668 Returns 0 if push was successful, 1 if nothing to push.
5672 """
5669 """
5673
5670
5674 if opts.get('bookmark'):
5671 if opts.get('bookmark'):
5675 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5672 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5676 for b in opts['bookmark']:
5673 for b in opts['bookmark']:
5677 # translate -B options to -r so changesets get pushed
5674 # translate -B options to -r so changesets get pushed
5678 if b in repo._bookmarks:
5675 if b in repo._bookmarks:
5679 opts.setdefault('rev', []).append(b)
5676 opts.setdefault('rev', []).append(b)
5680 else:
5677 else:
5681 # if we try to push a deleted bookmark, translate it to null
5678 # if we try to push a deleted bookmark, translate it to null
5682 # this lets simultaneous -r, -b options continue working
5679 # this lets simultaneous -r, -b options continue working
5683 opts.setdefault('rev', []).append("null")
5680 opts.setdefault('rev', []).append("null")
5684
5681
5685 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5682 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5686 if not path:
5683 if not path:
5687 raise error.Abort(_('default repository not configured!'),
5684 raise error.Abort(_('default repository not configured!'),
5688 hint=_('see the "path" section in "hg help config"'))
5685 hint=_('see the "path" section in "hg help config"'))
5689 dest = path.pushloc or path.loc
5686 dest = path.pushloc or path.loc
5690 branches = (path.branch, opts.get('branch') or [])
5687 branches = (path.branch, opts.get('branch') or [])
5691 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5688 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5692 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5689 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5693 other = hg.peer(repo, opts, dest)
5690 other = hg.peer(repo, opts, dest)
5694
5691
5695 if revs:
5692 if revs:
5696 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5693 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5697 if not revs:
5694 if not revs:
5698 raise error.Abort(_("specified revisions evaluate to an empty set"),
5695 raise error.Abort(_("specified revisions evaluate to an empty set"),
5699 hint=_("use different revision arguments"))
5696 hint=_("use different revision arguments"))
5700
5697
5701 repo._subtoppath = dest
5698 repo._subtoppath = dest
5702 try:
5699 try:
5703 # push subrepos depth-first for coherent ordering
5700 # push subrepos depth-first for coherent ordering
5704 c = repo['']
5701 c = repo['']
5705 subs = c.substate # only repos that are committed
5702 subs = c.substate # only repos that are committed
5706 for s in sorted(subs):
5703 for s in sorted(subs):
5707 result = c.sub(s).push(opts)
5704 result = c.sub(s).push(opts)
5708 if result == 0:
5705 if result == 0:
5709 return not result
5706 return not result
5710 finally:
5707 finally:
5711 del repo._subtoppath
5708 del repo._subtoppath
5712 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5709 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5713 newbranch=opts.get('new_branch'),
5710 newbranch=opts.get('new_branch'),
5714 bookmarks=opts.get('bookmark', ()),
5711 bookmarks=opts.get('bookmark', ()),
5715 opargs=opts.get('opargs'))
5712 opargs=opts.get('opargs'))
5716
5713
5717 result = not pushop.cgresult
5714 result = not pushop.cgresult
5718
5715
5719 if pushop.bkresult is not None:
5716 if pushop.bkresult is not None:
5720 if pushop.bkresult == 2:
5717 if pushop.bkresult == 2:
5721 result = 2
5718 result = 2
5722 elif not result and pushop.bkresult:
5719 elif not result and pushop.bkresult:
5723 result = 2
5720 result = 2
5724
5721
5725 return result
5722 return result
5726
5723
5727 @command('recover', [])
5724 @command('recover', [])
5728 def recover(ui, repo):
5725 def recover(ui, repo):
5729 """roll back an interrupted transaction
5726 """roll back an interrupted transaction
5730
5727
5731 Recover from an interrupted commit or pull.
5728 Recover from an interrupted commit or pull.
5732
5729
5733 This command tries to fix the repository status after an
5730 This command tries to fix the repository status after an
5734 interrupted operation. It should only be necessary when Mercurial
5731 interrupted operation. It should only be necessary when Mercurial
5735 suggests it.
5732 suggests it.
5736
5733
5737 Returns 0 if successful, 1 if nothing to recover or verify fails.
5734 Returns 0 if successful, 1 if nothing to recover or verify fails.
5738 """
5735 """
5739 if repo.recover():
5736 if repo.recover():
5740 return hg.verify(repo)
5737 return hg.verify(repo)
5741 return 1
5738 return 1
5742
5739
5743 @command('^remove|rm',
5740 @command('^remove|rm',
5744 [('A', 'after', None, _('record delete for missing files')),
5741 [('A', 'after', None, _('record delete for missing files')),
5745 ('f', 'force', None,
5742 ('f', 'force', None,
5746 _('remove (and delete) file even if added or modified')),
5743 _('remove (and delete) file even if added or modified')),
5747 ] + subrepoopts + walkopts,
5744 ] + subrepoopts + walkopts,
5748 _('[OPTION]... FILE...'),
5745 _('[OPTION]... FILE...'),
5749 inferrepo=True)
5746 inferrepo=True)
5750 def remove(ui, repo, *pats, **opts):
5747 def remove(ui, repo, *pats, **opts):
5751 """remove the specified files on the next commit
5748 """remove the specified files on the next commit
5752
5749
5753 Schedule the indicated files for removal from the current branch.
5750 Schedule the indicated files for removal from the current branch.
5754
5751
5755 This command schedules the files to be removed at the next commit.
5752 This command schedules the files to be removed at the next commit.
5756 To undo a remove before that, see :hg:`revert`. To undo added
5753 To undo a remove before that, see :hg:`revert`. To undo added
5757 files, see :hg:`forget`.
5754 files, see :hg:`forget`.
5758
5755
5759 .. container:: verbose
5756 .. container:: verbose
5760
5757
5761 -A/--after can be used to remove only files that have already
5758 -A/--after can be used to remove only files that have already
5762 been deleted, -f/--force can be used to force deletion, and -Af
5759 been deleted, -f/--force can be used to force deletion, and -Af
5763 can be used to remove files from the next revision without
5760 can be used to remove files from the next revision without
5764 deleting them from the working directory.
5761 deleting them from the working directory.
5765
5762
5766 The following table details the behavior of remove for different
5763 The following table details the behavior of remove for different
5767 file states (columns) and option combinations (rows). The file
5764 file states (columns) and option combinations (rows). The file
5768 states are Added [A], Clean [C], Modified [M] and Missing [!]
5765 states are Added [A], Clean [C], Modified [M] and Missing [!]
5769 (as reported by :hg:`status`). The actions are Warn, Remove
5766 (as reported by :hg:`status`). The actions are Warn, Remove
5770 (from branch) and Delete (from disk):
5767 (from branch) and Delete (from disk):
5771
5768
5772 ========= == == == ==
5769 ========= == == == ==
5773 opt/state A C M !
5770 opt/state A C M !
5774 ========= == == == ==
5771 ========= == == == ==
5775 none W RD W R
5772 none W RD W R
5776 -f R RD RD R
5773 -f R RD RD R
5777 -A W W W R
5774 -A W W W R
5778 -Af R R R R
5775 -Af R R R R
5779 ========= == == == ==
5776 ========= == == == ==
5780
5777
5781 .. note::
5778 .. note::
5782
5779
5783 :hg:`remove` never deletes files in Added [A] state from the
5780 :hg:`remove` never deletes files in Added [A] state from the
5784 working directory, not even if ``--force`` is specified.
5781 working directory, not even if ``--force`` is specified.
5785
5782
5786 Returns 0 on success, 1 if any warnings encountered.
5783 Returns 0 on success, 1 if any warnings encountered.
5787 """
5784 """
5788
5785
5789 after, force = opts.get('after'), opts.get('force')
5786 after, force = opts.get('after'), opts.get('force')
5790 if not pats and not after:
5787 if not pats and not after:
5791 raise error.Abort(_('no files specified'))
5788 raise error.Abort(_('no files specified'))
5792
5789
5793 m = scmutil.match(repo[None], pats, opts)
5790 m = scmutil.match(repo[None], pats, opts)
5794 subrepos = opts.get('subrepos')
5791 subrepos = opts.get('subrepos')
5795 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5792 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5796
5793
5797 @command('rename|move|mv',
5794 @command('rename|move|mv',
5798 [('A', 'after', None, _('record a rename that has already occurred')),
5795 [('A', 'after', None, _('record a rename that has already occurred')),
5799 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5796 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5800 ] + walkopts + dryrunopts,
5797 ] + walkopts + dryrunopts,
5801 _('[OPTION]... SOURCE... DEST'))
5798 _('[OPTION]... SOURCE... DEST'))
5802 def rename(ui, repo, *pats, **opts):
5799 def rename(ui, repo, *pats, **opts):
5803 """rename files; equivalent of copy + remove
5800 """rename files; equivalent of copy + remove
5804
5801
5805 Mark dest as copies of sources; mark sources for deletion. If dest
5802 Mark dest as copies of sources; mark sources for deletion. If dest
5806 is a directory, copies are put in that directory. If dest is a
5803 is a directory, copies are put in that directory. If dest is a
5807 file, there can only be one source.
5804 file, there can only be one source.
5808
5805
5809 By default, this command copies the contents of files as they
5806 By default, this command copies the contents of files as they
5810 exist in the working directory. If invoked with -A/--after, the
5807 exist in the working directory. If invoked with -A/--after, the
5811 operation is recorded, but no copying is performed.
5808 operation is recorded, but no copying is performed.
5812
5809
5813 This command takes effect at the next commit. To undo a rename
5810 This command takes effect at the next commit. To undo a rename
5814 before that, see :hg:`revert`.
5811 before that, see :hg:`revert`.
5815
5812
5816 Returns 0 on success, 1 if errors are encountered.
5813 Returns 0 on success, 1 if errors are encountered.
5817 """
5814 """
5818 with repo.wlock(False):
5815 with repo.wlock(False):
5819 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5816 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5820
5817
5821 @command('resolve',
5818 @command('resolve',
5822 [('a', 'all', None, _('select all unresolved files')),
5819 [('a', 'all', None, _('select all unresolved files')),
5823 ('l', 'list', None, _('list state of files needing merge')),
5820 ('l', 'list', None, _('list state of files needing merge')),
5824 ('m', 'mark', None, _('mark files as resolved')),
5821 ('m', 'mark', None, _('mark files as resolved')),
5825 ('u', 'unmark', None, _('mark files as unresolved')),
5822 ('u', 'unmark', None, _('mark files as unresolved')),
5826 ('n', 'no-status', None, _('hide status prefix'))]
5823 ('n', 'no-status', None, _('hide status prefix'))]
5827 + mergetoolopts + walkopts + formatteropts,
5824 + mergetoolopts + walkopts + formatteropts,
5828 _('[OPTION]... [FILE]...'),
5825 _('[OPTION]... [FILE]...'),
5829 inferrepo=True)
5826 inferrepo=True)
5830 def resolve(ui, repo, *pats, **opts):
5827 def resolve(ui, repo, *pats, **opts):
5831 """redo merges or set/view the merge status of files
5828 """redo merges or set/view the merge status of files
5832
5829
5833 Merges with unresolved conflicts are often the result of
5830 Merges with unresolved conflicts are often the result of
5834 non-interactive merging using the ``internal:merge`` configuration
5831 non-interactive merging using the ``internal:merge`` configuration
5835 setting, or a command-line merge tool like ``diff3``. The resolve
5832 setting, or a command-line merge tool like ``diff3``. The resolve
5836 command is used to manage the files involved in a merge, after
5833 command is used to manage the files involved in a merge, after
5837 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5834 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5838 working directory must have two parents). See :hg:`help
5835 working directory must have two parents). See :hg:`help
5839 merge-tools` for information on configuring merge tools.
5836 merge-tools` for information on configuring merge tools.
5840
5837
5841 The resolve command can be used in the following ways:
5838 The resolve command can be used in the following ways:
5842
5839
5843 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5840 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5844 files, discarding any previous merge attempts. Re-merging is not
5841 files, discarding any previous merge attempts. Re-merging is not
5845 performed for files already marked as resolved. Use ``--all/-a``
5842 performed for files already marked as resolved. Use ``--all/-a``
5846 to select all unresolved files. ``--tool`` can be used to specify
5843 to select all unresolved files. ``--tool`` can be used to specify
5847 the merge tool used for the given files. It overrides the HGMERGE
5844 the merge tool used for the given files. It overrides the HGMERGE
5848 environment variable and your configuration files. Previous file
5845 environment variable and your configuration files. Previous file
5849 contents are saved with a ``.orig`` suffix.
5846 contents are saved with a ``.orig`` suffix.
5850
5847
5851 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5848 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5852 (e.g. after having manually fixed-up the files). The default is
5849 (e.g. after having manually fixed-up the files). The default is
5853 to mark all unresolved files.
5850 to mark all unresolved files.
5854
5851
5855 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5852 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5856 default is to mark all resolved files.
5853 default is to mark all resolved files.
5857
5854
5858 - :hg:`resolve -l`: list files which had or still have conflicts.
5855 - :hg:`resolve -l`: list files which had or still have conflicts.
5859 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5856 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5860
5857
5861 .. note::
5858 .. note::
5862
5859
5863 Mercurial will not let you commit files with unresolved merge
5860 Mercurial will not let you commit files with unresolved merge
5864 conflicts. You must use :hg:`resolve -m ...` before you can
5861 conflicts. You must use :hg:`resolve -m ...` before you can
5865 commit after a conflicting merge.
5862 commit after a conflicting merge.
5866
5863
5867 Returns 0 on success, 1 if any files fail a resolve attempt.
5864 Returns 0 on success, 1 if any files fail a resolve attempt.
5868 """
5865 """
5869
5866
5870 all, mark, unmark, show, nostatus = \
5867 all, mark, unmark, show, nostatus = \
5871 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5868 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5872
5869
5873 if (show and (mark or unmark)) or (mark and unmark):
5870 if (show and (mark or unmark)) or (mark and unmark):
5874 raise error.Abort(_("too many options specified"))
5871 raise error.Abort(_("too many options specified"))
5875 if pats and all:
5872 if pats and all:
5876 raise error.Abort(_("can't specify --all and patterns"))
5873 raise error.Abort(_("can't specify --all and patterns"))
5877 if not (all or pats or show or mark or unmark):
5874 if not (all or pats or show or mark or unmark):
5878 raise error.Abort(_('no files or directories specified'),
5875 raise error.Abort(_('no files or directories specified'),
5879 hint=('use --all to re-merge all unresolved files'))
5876 hint=('use --all to re-merge all unresolved files'))
5880
5877
5881 if show:
5878 if show:
5882 fm = ui.formatter('resolve', opts)
5879 fm = ui.formatter('resolve', opts)
5883 ms = mergemod.mergestate.read(repo)
5880 ms = mergemod.mergestate.read(repo)
5884 m = scmutil.match(repo[None], pats, opts)
5881 m = scmutil.match(repo[None], pats, opts)
5885 for f in ms:
5882 for f in ms:
5886 if not m(f):
5883 if not m(f):
5887 continue
5884 continue
5888 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5885 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5889 'd': 'driverresolved'}[ms[f]]
5886 'd': 'driverresolved'}[ms[f]]
5890 fm.startitem()
5887 fm.startitem()
5891 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5888 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5892 fm.write('path', '%s\n', f, label=l)
5889 fm.write('path', '%s\n', f, label=l)
5893 fm.end()
5890 fm.end()
5894 return 0
5891 return 0
5895
5892
5896 with repo.wlock():
5893 with repo.wlock():
5897 ms = mergemod.mergestate.read(repo)
5894 ms = mergemod.mergestate.read(repo)
5898
5895
5899 if not (ms.active() or repo.dirstate.p2() != nullid):
5896 if not (ms.active() or repo.dirstate.p2() != nullid):
5900 raise error.Abort(
5897 raise error.Abort(
5901 _('resolve command not applicable when not merging'))
5898 _('resolve command not applicable when not merging'))
5902
5899
5903 wctx = repo[None]
5900 wctx = repo[None]
5904
5901
5905 if ms.mergedriver and ms.mdstate() == 'u':
5902 if ms.mergedriver and ms.mdstate() == 'u':
5906 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5903 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5907 ms.commit()
5904 ms.commit()
5908 # allow mark and unmark to go through
5905 # allow mark and unmark to go through
5909 if not mark and not unmark and not proceed:
5906 if not mark and not unmark and not proceed:
5910 return 1
5907 return 1
5911
5908
5912 m = scmutil.match(wctx, pats, opts)
5909 m = scmutil.match(wctx, pats, opts)
5913 ret = 0
5910 ret = 0
5914 didwork = False
5911 didwork = False
5915 runconclude = False
5912 runconclude = False
5916
5913
5917 tocomplete = []
5914 tocomplete = []
5918 for f in ms:
5915 for f in ms:
5919 if not m(f):
5916 if not m(f):
5920 continue
5917 continue
5921
5918
5922 didwork = True
5919 didwork = True
5923
5920
5924 # don't let driver-resolved files be marked, and run the conclude
5921 # don't let driver-resolved files be marked, and run the conclude
5925 # step if asked to resolve
5922 # step if asked to resolve
5926 if ms[f] == "d":
5923 if ms[f] == "d":
5927 exact = m.exact(f)
5924 exact = m.exact(f)
5928 if mark:
5925 if mark:
5929 if exact:
5926 if exact:
5930 ui.warn(_('not marking %s as it is driver-resolved\n')
5927 ui.warn(_('not marking %s as it is driver-resolved\n')
5931 % f)
5928 % f)
5932 elif unmark:
5929 elif unmark:
5933 if exact:
5930 if exact:
5934 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5931 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5935 % f)
5932 % f)
5936 else:
5933 else:
5937 runconclude = True
5934 runconclude = True
5938 continue
5935 continue
5939
5936
5940 if mark:
5937 if mark:
5941 ms.mark(f, "r")
5938 ms.mark(f, "r")
5942 elif unmark:
5939 elif unmark:
5943 ms.mark(f, "u")
5940 ms.mark(f, "u")
5944 else:
5941 else:
5945 # backup pre-resolve (merge uses .orig for its own purposes)
5942 # backup pre-resolve (merge uses .orig for its own purposes)
5946 a = repo.wjoin(f)
5943 a = repo.wjoin(f)
5947 try:
5944 try:
5948 util.copyfile(a, a + ".resolve")
5945 util.copyfile(a, a + ".resolve")
5949 except (IOError, OSError) as inst:
5946 except (IOError, OSError) as inst:
5950 if inst.errno != errno.ENOENT:
5947 if inst.errno != errno.ENOENT:
5951 raise
5948 raise
5952
5949
5953 try:
5950 try:
5954 # preresolve file
5951 # preresolve file
5955 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5952 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5956 'resolve')
5953 'resolve')
5957 complete, r = ms.preresolve(f, wctx)
5954 complete, r = ms.preresolve(f, wctx)
5958 if not complete:
5955 if not complete:
5959 tocomplete.append(f)
5956 tocomplete.append(f)
5960 elif r:
5957 elif r:
5961 ret = 1
5958 ret = 1
5962 finally:
5959 finally:
5963 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5960 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5964 ms.commit()
5961 ms.commit()
5965
5962
5966 # replace filemerge's .orig file with our resolve file, but only
5963 # replace filemerge's .orig file with our resolve file, but only
5967 # for merges that are complete
5964 # for merges that are complete
5968 if complete:
5965 if complete:
5969 try:
5966 try:
5970 util.rename(a + ".resolve",
5967 util.rename(a + ".resolve",
5971 scmutil.origpath(ui, repo, a))
5968 scmutil.origpath(ui, repo, a))
5972 except OSError as inst:
5969 except OSError as inst:
5973 if inst.errno != errno.ENOENT:
5970 if inst.errno != errno.ENOENT:
5974 raise
5971 raise
5975
5972
5976 for f in tocomplete:
5973 for f in tocomplete:
5977 try:
5974 try:
5978 # resolve file
5975 # resolve file
5979 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5976 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5980 'resolve')
5977 'resolve')
5981 r = ms.resolve(f, wctx)
5978 r = ms.resolve(f, wctx)
5982 if r:
5979 if r:
5983 ret = 1
5980 ret = 1
5984 finally:
5981 finally:
5985 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5982 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5986 ms.commit()
5983 ms.commit()
5987
5984
5988 # replace filemerge's .orig file with our resolve file
5985 # replace filemerge's .orig file with our resolve file
5989 a = repo.wjoin(f)
5986 a = repo.wjoin(f)
5990 try:
5987 try:
5991 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5988 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5992 except OSError as inst:
5989 except OSError as inst:
5993 if inst.errno != errno.ENOENT:
5990 if inst.errno != errno.ENOENT:
5994 raise
5991 raise
5995
5992
5996 ms.commit()
5993 ms.commit()
5997 ms.recordactions()
5994 ms.recordactions()
5998
5995
5999 if not didwork and pats:
5996 if not didwork and pats:
6000 ui.warn(_("arguments do not match paths that need resolving\n"))
5997 ui.warn(_("arguments do not match paths that need resolving\n"))
6001 elif ms.mergedriver and ms.mdstate() != 's':
5998 elif ms.mergedriver and ms.mdstate() != 's':
6002 # run conclude step when either a driver-resolved file is requested
5999 # run conclude step when either a driver-resolved file is requested
6003 # or there are no driver-resolved files
6000 # or there are no driver-resolved files
6004 # we can't use 'ret' to determine whether any files are unresolved
6001 # we can't use 'ret' to determine whether any files are unresolved
6005 # because we might not have tried to resolve some
6002 # because we might not have tried to resolve some
6006 if ((runconclude or not list(ms.driverresolved()))
6003 if ((runconclude or not list(ms.driverresolved()))
6007 and not list(ms.unresolved())):
6004 and not list(ms.unresolved())):
6008 proceed = mergemod.driverconclude(repo, ms, wctx)
6005 proceed = mergemod.driverconclude(repo, ms, wctx)
6009 ms.commit()
6006 ms.commit()
6010 if not proceed:
6007 if not proceed:
6011 return 1
6008 return 1
6012
6009
6013 # Nudge users into finishing an unfinished operation
6010 # Nudge users into finishing an unfinished operation
6014 unresolvedf = list(ms.unresolved())
6011 unresolvedf = list(ms.unresolved())
6015 driverresolvedf = list(ms.driverresolved())
6012 driverresolvedf = list(ms.driverresolved())
6016 if not unresolvedf and not driverresolvedf:
6013 if not unresolvedf and not driverresolvedf:
6017 ui.status(_('(no more unresolved files)\n'))
6014 ui.status(_('(no more unresolved files)\n'))
6018 cmdutil.checkafterresolved(repo)
6015 cmdutil.checkafterresolved(repo)
6019 elif not unresolvedf:
6016 elif not unresolvedf:
6020 ui.status(_('(no more unresolved files -- '
6017 ui.status(_('(no more unresolved files -- '
6021 'run "hg resolve --all" to conclude)\n'))
6018 'run "hg resolve --all" to conclude)\n'))
6022
6019
6023 return ret
6020 return ret
6024
6021
6025 @command('revert',
6022 @command('revert',
6026 [('a', 'all', None, _('revert all changes when no arguments given')),
6023 [('a', 'all', None, _('revert all changes when no arguments given')),
6027 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6024 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6028 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6025 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6029 ('C', 'no-backup', None, _('do not save backup copies of files')),
6026 ('C', 'no-backup', None, _('do not save backup copies of files')),
6030 ('i', 'interactive', None,
6027 ('i', 'interactive', None,
6031 _('interactively select the changes (EXPERIMENTAL)')),
6028 _('interactively select the changes (EXPERIMENTAL)')),
6032 ] + walkopts + dryrunopts,
6029 ] + walkopts + dryrunopts,
6033 _('[OPTION]... [-r REV] [NAME]...'))
6030 _('[OPTION]... [-r REV] [NAME]...'))
6034 def revert(ui, repo, *pats, **opts):
6031 def revert(ui, repo, *pats, **opts):
6035 """restore files to their checkout state
6032 """restore files to their checkout state
6036
6033
6037 .. note::
6034 .. note::
6038
6035
6039 To check out earlier revisions, you should use :hg:`update REV`.
6036 To check out earlier revisions, you should use :hg:`update REV`.
6040 To cancel an uncommitted merge (and lose your changes),
6037 To cancel an uncommitted merge (and lose your changes),
6041 use :hg:`update --clean .`.
6038 use :hg:`update --clean .`.
6042
6039
6043 With no revision specified, revert the specified files or directories
6040 With no revision specified, revert the specified files or directories
6044 to the contents they had in the parent of the working directory.
6041 to the contents they had in the parent of the working directory.
6045 This restores the contents of files to an unmodified
6042 This restores the contents of files to an unmodified
6046 state and unschedules adds, removes, copies, and renames. If the
6043 state and unschedules adds, removes, copies, and renames. If the
6047 working directory has two parents, you must explicitly specify a
6044 working directory has two parents, you must explicitly specify a
6048 revision.
6045 revision.
6049
6046
6050 Using the -r/--rev or -d/--date options, revert the given files or
6047 Using the -r/--rev or -d/--date options, revert the given files or
6051 directories to their states as of a specific revision. Because
6048 directories to their states as of a specific revision. Because
6052 revert does not change the working directory parents, this will
6049 revert does not change the working directory parents, this will
6053 cause these files to appear modified. This can be helpful to "back
6050 cause these files to appear modified. This can be helpful to "back
6054 out" some or all of an earlier change. See :hg:`backout` for a
6051 out" some or all of an earlier change. See :hg:`backout` for a
6055 related method.
6052 related method.
6056
6053
6057 Modified files are saved with a .orig suffix before reverting.
6054 Modified files are saved with a .orig suffix before reverting.
6058 To disable these backups, use --no-backup.
6055 To disable these backups, use --no-backup.
6059
6056
6060 See :hg:`help dates` for a list of formats valid for -d/--date.
6057 See :hg:`help dates` for a list of formats valid for -d/--date.
6061
6058
6062 See :hg:`help backout` for a way to reverse the effect of an
6059 See :hg:`help backout` for a way to reverse the effect of an
6063 earlier changeset.
6060 earlier changeset.
6064
6061
6065 Returns 0 on success.
6062 Returns 0 on success.
6066 """
6063 """
6067
6064
6068 if opts.get("date"):
6065 if opts.get("date"):
6069 if opts.get("rev"):
6066 if opts.get("rev"):
6070 raise error.Abort(_("you can't specify a revision and a date"))
6067 raise error.Abort(_("you can't specify a revision and a date"))
6071 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6068 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6072
6069
6073 parent, p2 = repo.dirstate.parents()
6070 parent, p2 = repo.dirstate.parents()
6074 if not opts.get('rev') and p2 != nullid:
6071 if not opts.get('rev') and p2 != nullid:
6075 # revert after merge is a trap for new users (issue2915)
6072 # revert after merge is a trap for new users (issue2915)
6076 raise error.Abort(_('uncommitted merge with no revision specified'),
6073 raise error.Abort(_('uncommitted merge with no revision specified'),
6077 hint=_('use "hg update" or see "hg help revert"'))
6074 hint=_('use "hg update" or see "hg help revert"'))
6078
6075
6079 ctx = scmutil.revsingle(repo, opts.get('rev'))
6076 ctx = scmutil.revsingle(repo, opts.get('rev'))
6080
6077
6081 if (not (pats or opts.get('include') or opts.get('exclude') or
6078 if (not (pats or opts.get('include') or opts.get('exclude') or
6082 opts.get('all') or opts.get('interactive'))):
6079 opts.get('all') or opts.get('interactive'))):
6083 msg = _("no files or directories specified")
6080 msg = _("no files or directories specified")
6084 if p2 != nullid:
6081 if p2 != nullid:
6085 hint = _("uncommitted merge, use --all to discard all changes,"
6082 hint = _("uncommitted merge, use --all to discard all changes,"
6086 " or 'hg update -C .' to abort the merge")
6083 " or 'hg update -C .' to abort the merge")
6087 raise error.Abort(msg, hint=hint)
6084 raise error.Abort(msg, hint=hint)
6088 dirty = any(repo.status())
6085 dirty = any(repo.status())
6089 node = ctx.node()
6086 node = ctx.node()
6090 if node != parent:
6087 if node != parent:
6091 if dirty:
6088 if dirty:
6092 hint = _("uncommitted changes, use --all to discard all"
6089 hint = _("uncommitted changes, use --all to discard all"
6093 " changes, or 'hg update %s' to update") % ctx.rev()
6090 " changes, or 'hg update %s' to update") % ctx.rev()
6094 else:
6091 else:
6095 hint = _("use --all to revert all files,"
6092 hint = _("use --all to revert all files,"
6096 " or 'hg update %s' to update") % ctx.rev()
6093 " or 'hg update %s' to update") % ctx.rev()
6097 elif dirty:
6094 elif dirty:
6098 hint = _("uncommitted changes, use --all to discard all changes")
6095 hint = _("uncommitted changes, use --all to discard all changes")
6099 else:
6096 else:
6100 hint = _("use --all to revert all files")
6097 hint = _("use --all to revert all files")
6101 raise error.Abort(msg, hint=hint)
6098 raise error.Abort(msg, hint=hint)
6102
6099
6103 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6100 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6104
6101
6105 @command('rollback', dryrunopts +
6102 @command('rollback', dryrunopts +
6106 [('f', 'force', False, _('ignore safety measures'))])
6103 [('f', 'force', False, _('ignore safety measures'))])
6107 def rollback(ui, repo, **opts):
6104 def rollback(ui, repo, **opts):
6108 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6105 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6109
6106
6110 Please use :hg:`commit --amend` instead of rollback to correct
6107 Please use :hg:`commit --amend` instead of rollback to correct
6111 mistakes in the last commit.
6108 mistakes in the last commit.
6112
6109
6113 This command should be used with care. There is only one level of
6110 This command should be used with care. There is only one level of
6114 rollback, and there is no way to undo a rollback. It will also
6111 rollback, and there is no way to undo a rollback. It will also
6115 restore the dirstate at the time of the last transaction, losing
6112 restore the dirstate at the time of the last transaction, losing
6116 any dirstate changes since that time. This command does not alter
6113 any dirstate changes since that time. This command does not alter
6117 the working directory.
6114 the working directory.
6118
6115
6119 Transactions are used to encapsulate the effects of all commands
6116 Transactions are used to encapsulate the effects of all commands
6120 that create new changesets or propagate existing changesets into a
6117 that create new changesets or propagate existing changesets into a
6121 repository.
6118 repository.
6122
6119
6123 .. container:: verbose
6120 .. container:: verbose
6124
6121
6125 For example, the following commands are transactional, and their
6122 For example, the following commands are transactional, and their
6126 effects can be rolled back:
6123 effects can be rolled back:
6127
6124
6128 - commit
6125 - commit
6129 - import
6126 - import
6130 - pull
6127 - pull
6131 - push (with this repository as the destination)
6128 - push (with this repository as the destination)
6132 - unbundle
6129 - unbundle
6133
6130
6134 To avoid permanent data loss, rollback will refuse to rollback a
6131 To avoid permanent data loss, rollback will refuse to rollback a
6135 commit transaction if it isn't checked out. Use --force to
6132 commit transaction if it isn't checked out. Use --force to
6136 override this protection.
6133 override this protection.
6137
6134
6138 This command is not intended for use on public repositories. Once
6135 This command is not intended for use on public repositories. Once
6139 changes are visible for pull by other users, rolling a transaction
6136 changes are visible for pull by other users, rolling a transaction
6140 back locally is ineffective (someone else may already have pulled
6137 back locally is ineffective (someone else may already have pulled
6141 the changes). Furthermore, a race is possible with readers of the
6138 the changes). Furthermore, a race is possible with readers of the
6142 repository; for example an in-progress pull from the repository
6139 repository; for example an in-progress pull from the repository
6143 may fail if a rollback is performed.
6140 may fail if a rollback is performed.
6144
6141
6145 Returns 0 on success, 1 if no rollback data is available.
6142 Returns 0 on success, 1 if no rollback data is available.
6146 """
6143 """
6147 return repo.rollback(dryrun=opts.get('dry_run'),
6144 return repo.rollback(dryrun=opts.get('dry_run'),
6148 force=opts.get('force'))
6145 force=opts.get('force'))
6149
6146
6150 @command('root', [])
6147 @command('root', [])
6151 def root(ui, repo):
6148 def root(ui, repo):
6152 """print the root (top) of the current working directory
6149 """print the root (top) of the current working directory
6153
6150
6154 Print the root directory of the current repository.
6151 Print the root directory of the current repository.
6155
6152
6156 Returns 0 on success.
6153 Returns 0 on success.
6157 """
6154 """
6158 ui.write(repo.root + "\n")
6155 ui.write(repo.root + "\n")
6159
6156
6160 @command('^serve',
6157 @command('^serve',
6161 [('A', 'accesslog', '', _('name of access log file to write to'),
6158 [('A', 'accesslog', '', _('name of access log file to write to'),
6162 _('FILE')),
6159 _('FILE')),
6163 ('d', 'daemon', None, _('run server in background')),
6160 ('d', 'daemon', None, _('run server in background')),
6164 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6161 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6165 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6162 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6166 # use string type, then we can check if something was passed
6163 # use string type, then we can check if something was passed
6167 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6164 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6168 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6165 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6169 _('ADDR')),
6166 _('ADDR')),
6170 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6167 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6171 _('PREFIX')),
6168 _('PREFIX')),
6172 ('n', 'name', '',
6169 ('n', 'name', '',
6173 _('name to show in web pages (default: working directory)'), _('NAME')),
6170 _('name to show in web pages (default: working directory)'), _('NAME')),
6174 ('', 'web-conf', '',
6171 ('', 'web-conf', '',
6175 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6172 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6176 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6173 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6177 _('FILE')),
6174 _('FILE')),
6178 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6175 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6179 ('', 'stdio', None, _('for remote clients')),
6176 ('', 'stdio', None, _('for remote clients')),
6180 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6177 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6181 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6178 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6182 ('', 'style', '', _('template style to use'), _('STYLE')),
6179 ('', 'style', '', _('template style to use'), _('STYLE')),
6183 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6180 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6184 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6181 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6185 _('[OPTION]...'),
6182 _('[OPTION]...'),
6186 optionalrepo=True)
6183 optionalrepo=True)
6187 def serve(ui, repo, **opts):
6184 def serve(ui, repo, **opts):
6188 """start stand-alone webserver
6185 """start stand-alone webserver
6189
6186
6190 Start a local HTTP repository browser and pull server. You can use
6187 Start a local HTTP repository browser and pull server. You can use
6191 this for ad-hoc sharing and browsing of repositories. It is
6188 this for ad-hoc sharing and browsing of repositories. It is
6192 recommended to use a real web server to serve a repository for
6189 recommended to use a real web server to serve a repository for
6193 longer periods of time.
6190 longer periods of time.
6194
6191
6195 Please note that the server does not implement access control.
6192 Please note that the server does not implement access control.
6196 This means that, by default, anybody can read from the server and
6193 This means that, by default, anybody can read from the server and
6197 nobody can write to it by default. Set the ``web.allow_push``
6194 nobody can write to it by default. Set the ``web.allow_push``
6198 option to ``*`` to allow everybody to push to the server. You
6195 option to ``*`` to allow everybody to push to the server. You
6199 should use a real web server if you need to authenticate users.
6196 should use a real web server if you need to authenticate users.
6200
6197
6201 By default, the server logs accesses to stdout and errors to
6198 By default, the server logs accesses to stdout and errors to
6202 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6199 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6203 files.
6200 files.
6204
6201
6205 To have the server choose a free port number to listen on, specify
6202 To have the server choose a free port number to listen on, specify
6206 a port number of 0; in this case, the server will print the port
6203 a port number of 0; in this case, the server will print the port
6207 number it uses.
6204 number it uses.
6208
6205
6209 Returns 0 on success.
6206 Returns 0 on success.
6210 """
6207 """
6211
6208
6212 if opts["stdio"] and opts["cmdserver"]:
6209 if opts["stdio"] and opts["cmdserver"]:
6213 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6210 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6214
6211
6215 if opts["stdio"]:
6212 if opts["stdio"]:
6216 if repo is None:
6213 if repo is None:
6217 raise error.RepoError(_("there is no Mercurial repository here"
6214 raise error.RepoError(_("there is no Mercurial repository here"
6218 " (.hg not found)"))
6215 " (.hg not found)"))
6219 s = sshserver.sshserver(ui, repo)
6216 s = sshserver.sshserver(ui, repo)
6220 s.serve_forever()
6217 s.serve_forever()
6221
6218
6222 if opts["cmdserver"]:
6219 if opts["cmdserver"]:
6223 service = commandserver.createservice(ui, repo, opts)
6220 service = commandserver.createservice(ui, repo, opts)
6224 else:
6221 else:
6225 service = hgweb.createservice(ui, repo, opts)
6222 service = hgweb.createservice(ui, repo, opts)
6226 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6223 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6227
6224
6228 @command('^status|st',
6225 @command('^status|st',
6229 [('A', 'all', None, _('show status of all files')),
6226 [('A', 'all', None, _('show status of all files')),
6230 ('m', 'modified', None, _('show only modified files')),
6227 ('m', 'modified', None, _('show only modified files')),
6231 ('a', 'added', None, _('show only added files')),
6228 ('a', 'added', None, _('show only added files')),
6232 ('r', 'removed', None, _('show only removed files')),
6229 ('r', 'removed', None, _('show only removed files')),
6233 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6230 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6234 ('c', 'clean', None, _('show only files without changes')),
6231 ('c', 'clean', None, _('show only files without changes')),
6235 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6232 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6236 ('i', 'ignored', None, _('show only ignored files')),
6233 ('i', 'ignored', None, _('show only ignored files')),
6237 ('n', 'no-status', None, _('hide status prefix')),
6234 ('n', 'no-status', None, _('hide status prefix')),
6238 ('C', 'copies', None, _('show source of copied files')),
6235 ('C', 'copies', None, _('show source of copied files')),
6239 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6236 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6240 ('', 'rev', [], _('show difference from revision'), _('REV')),
6237 ('', 'rev', [], _('show difference from revision'), _('REV')),
6241 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6238 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6242 ] + walkopts + subrepoopts + formatteropts,
6239 ] + walkopts + subrepoopts + formatteropts,
6243 _('[OPTION]... [FILE]...'),
6240 _('[OPTION]... [FILE]...'),
6244 inferrepo=True)
6241 inferrepo=True)
6245 def status(ui, repo, *pats, **opts):
6242 def status(ui, repo, *pats, **opts):
6246 """show changed files in the working directory
6243 """show changed files in the working directory
6247
6244
6248 Show status of files in the repository. If names are given, only
6245 Show status of files in the repository. If names are given, only
6249 files that match are shown. Files that are clean or ignored or
6246 files that match are shown. Files that are clean or ignored or
6250 the source of a copy/move operation, are not listed unless
6247 the source of a copy/move operation, are not listed unless
6251 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6248 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6252 Unless options described with "show only ..." are given, the
6249 Unless options described with "show only ..." are given, the
6253 options -mardu are used.
6250 options -mardu are used.
6254
6251
6255 Option -q/--quiet hides untracked (unknown and ignored) files
6252 Option -q/--quiet hides untracked (unknown and ignored) files
6256 unless explicitly requested with -u/--unknown or -i/--ignored.
6253 unless explicitly requested with -u/--unknown or -i/--ignored.
6257
6254
6258 .. note::
6255 .. note::
6259
6256
6260 :hg:`status` may appear to disagree with diff if permissions have
6257 :hg:`status` may appear to disagree with diff if permissions have
6261 changed or a merge has occurred. The standard diff format does
6258 changed or a merge has occurred. The standard diff format does
6262 not report permission changes and diff only reports changes
6259 not report permission changes and diff only reports changes
6263 relative to one merge parent.
6260 relative to one merge parent.
6264
6261
6265 If one revision is given, it is used as the base revision.
6262 If one revision is given, it is used as the base revision.
6266 If two revisions are given, the differences between them are
6263 If two revisions are given, the differences between them are
6267 shown. The --change option can also be used as a shortcut to list
6264 shown. The --change option can also be used as a shortcut to list
6268 the changed files of a revision from its first parent.
6265 the changed files of a revision from its first parent.
6269
6266
6270 The codes used to show the status of files are::
6267 The codes used to show the status of files are::
6271
6268
6272 M = modified
6269 M = modified
6273 A = added
6270 A = added
6274 R = removed
6271 R = removed
6275 C = clean
6272 C = clean
6276 ! = missing (deleted by non-hg command, but still tracked)
6273 ! = missing (deleted by non-hg command, but still tracked)
6277 ? = not tracked
6274 ? = not tracked
6278 I = ignored
6275 I = ignored
6279 = origin of the previous file (with --copies)
6276 = origin of the previous file (with --copies)
6280
6277
6281 .. container:: verbose
6278 .. container:: verbose
6282
6279
6283 Examples:
6280 Examples:
6284
6281
6285 - show changes in the working directory relative to a
6282 - show changes in the working directory relative to a
6286 changeset::
6283 changeset::
6287
6284
6288 hg status --rev 9353
6285 hg status --rev 9353
6289
6286
6290 - show changes in the working directory relative to the
6287 - show changes in the working directory relative to the
6291 current directory (see :hg:`help patterns` for more information)::
6288 current directory (see :hg:`help patterns` for more information)::
6292
6289
6293 hg status re:
6290 hg status re:
6294
6291
6295 - show all changes including copies in an existing changeset::
6292 - show all changes including copies in an existing changeset::
6296
6293
6297 hg status --copies --change 9353
6294 hg status --copies --change 9353
6298
6295
6299 - get a NUL separated list of added files, suitable for xargs::
6296 - get a NUL separated list of added files, suitable for xargs::
6300
6297
6301 hg status -an0
6298 hg status -an0
6302
6299
6303 Returns 0 on success.
6300 Returns 0 on success.
6304 """
6301 """
6305
6302
6306 revs = opts.get('rev')
6303 revs = opts.get('rev')
6307 change = opts.get('change')
6304 change = opts.get('change')
6308
6305
6309 if revs and change:
6306 if revs and change:
6310 msg = _('cannot specify --rev and --change at the same time')
6307 msg = _('cannot specify --rev and --change at the same time')
6311 raise error.Abort(msg)
6308 raise error.Abort(msg)
6312 elif change:
6309 elif change:
6313 node2 = scmutil.revsingle(repo, change, None).node()
6310 node2 = scmutil.revsingle(repo, change, None).node()
6314 node1 = repo[node2].p1().node()
6311 node1 = repo[node2].p1().node()
6315 else:
6312 else:
6316 node1, node2 = scmutil.revpair(repo, revs)
6313 node1, node2 = scmutil.revpair(repo, revs)
6317
6314
6318 if pats:
6315 if pats:
6319 cwd = repo.getcwd()
6316 cwd = repo.getcwd()
6320 else:
6317 else:
6321 cwd = ''
6318 cwd = ''
6322
6319
6323 if opts.get('print0'):
6320 if opts.get('print0'):
6324 end = '\0'
6321 end = '\0'
6325 else:
6322 else:
6326 end = '\n'
6323 end = '\n'
6327 copy = {}
6324 copy = {}
6328 states = 'modified added removed deleted unknown ignored clean'.split()
6325 states = 'modified added removed deleted unknown ignored clean'.split()
6329 show = [k for k in states if opts.get(k)]
6326 show = [k for k in states if opts.get(k)]
6330 if opts.get('all'):
6327 if opts.get('all'):
6331 show += ui.quiet and (states[:4] + ['clean']) or states
6328 show += ui.quiet and (states[:4] + ['clean']) or states
6332 if not show:
6329 if not show:
6333 if ui.quiet:
6330 if ui.quiet:
6334 show = states[:4]
6331 show = states[:4]
6335 else:
6332 else:
6336 show = states[:5]
6333 show = states[:5]
6337
6334
6338 m = scmutil.match(repo[node2], pats, opts)
6335 m = scmutil.match(repo[node2], pats, opts)
6339 stat = repo.status(node1, node2, m,
6336 stat = repo.status(node1, node2, m,
6340 'ignored' in show, 'clean' in show, 'unknown' in show,
6337 'ignored' in show, 'clean' in show, 'unknown' in show,
6341 opts.get('subrepos'))
6338 opts.get('subrepos'))
6342 changestates = zip(states, 'MAR!?IC', stat)
6339 changestates = zip(states, 'MAR!?IC', stat)
6343
6340
6344 if (opts.get('all') or opts.get('copies')
6341 if (opts.get('all') or opts.get('copies')
6345 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6342 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6346 copy = copies.pathcopies(repo[node1], repo[node2], m)
6343 copy = copies.pathcopies(repo[node1], repo[node2], m)
6347
6344
6348 fm = ui.formatter('status', opts)
6345 fm = ui.formatter('status', opts)
6349 fmt = '%s' + end
6346 fmt = '%s' + end
6350 showchar = not opts.get('no_status')
6347 showchar = not opts.get('no_status')
6351
6348
6352 for state, char, files in changestates:
6349 for state, char, files in changestates:
6353 if state in show:
6350 if state in show:
6354 label = 'status.' + state
6351 label = 'status.' + state
6355 for f in files:
6352 for f in files:
6356 fm.startitem()
6353 fm.startitem()
6357 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6354 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6358 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6355 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6359 if f in copy:
6356 if f in copy:
6360 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6357 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6361 label='status.copied')
6358 label='status.copied')
6362 fm.end()
6359 fm.end()
6363
6360
6364 @command('^summary|sum',
6361 @command('^summary|sum',
6365 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6362 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6366 def summary(ui, repo, **opts):
6363 def summary(ui, repo, **opts):
6367 """summarize working directory state
6364 """summarize working directory state
6368
6365
6369 This generates a brief summary of the working directory state,
6366 This generates a brief summary of the working directory state,
6370 including parents, branch, commit status, phase and available updates.
6367 including parents, branch, commit status, phase and available updates.
6371
6368
6372 With the --remote option, this will check the default paths for
6369 With the --remote option, this will check the default paths for
6373 incoming and outgoing changes. This can be time-consuming.
6370 incoming and outgoing changes. This can be time-consuming.
6374
6371
6375 Returns 0 on success.
6372 Returns 0 on success.
6376 """
6373 """
6377
6374
6378 ctx = repo[None]
6375 ctx = repo[None]
6379 parents = ctx.parents()
6376 parents = ctx.parents()
6380 pnode = parents[0].node()
6377 pnode = parents[0].node()
6381 marks = []
6378 marks = []
6382
6379
6383 for p in parents:
6380 for p in parents:
6384 # label with log.changeset (instead of log.parent) since this
6381 # label with log.changeset (instead of log.parent) since this
6385 # shows a working directory parent *changeset*:
6382 # shows a working directory parent *changeset*:
6386 # i18n: column positioning for "hg summary"
6383 # i18n: column positioning for "hg summary"
6387 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6384 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6388 label='log.changeset changeset.%s' % p.phasestr())
6385 label='log.changeset changeset.%s' % p.phasestr())
6389 ui.write(' '.join(p.tags()), label='log.tag')
6386 ui.write(' '.join(p.tags()), label='log.tag')
6390 if p.bookmarks():
6387 if p.bookmarks():
6391 marks.extend(p.bookmarks())
6388 marks.extend(p.bookmarks())
6392 if p.rev() == -1:
6389 if p.rev() == -1:
6393 if not len(repo):
6390 if not len(repo):
6394 ui.write(_(' (empty repository)'))
6391 ui.write(_(' (empty repository)'))
6395 else:
6392 else:
6396 ui.write(_(' (no revision checked out)'))
6393 ui.write(_(' (no revision checked out)'))
6397 ui.write('\n')
6394 ui.write('\n')
6398 if p.description():
6395 if p.description():
6399 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6396 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6400 label='log.summary')
6397 label='log.summary')
6401
6398
6402 branch = ctx.branch()
6399 branch = ctx.branch()
6403 bheads = repo.branchheads(branch)
6400 bheads = repo.branchheads(branch)
6404 # i18n: column positioning for "hg summary"
6401 # i18n: column positioning for "hg summary"
6405 m = _('branch: %s\n') % branch
6402 m = _('branch: %s\n') % branch
6406 if branch != 'default':
6403 if branch != 'default':
6407 ui.write(m, label='log.branch')
6404 ui.write(m, label='log.branch')
6408 else:
6405 else:
6409 ui.status(m, label='log.branch')
6406 ui.status(m, label='log.branch')
6410
6407
6411 if marks:
6408 if marks:
6412 active = repo._activebookmark
6409 active = repo._activebookmark
6413 # i18n: column positioning for "hg summary"
6410 # i18n: column positioning for "hg summary"
6414 ui.write(_('bookmarks:'), label='log.bookmark')
6411 ui.write(_('bookmarks:'), label='log.bookmark')
6415 if active is not None:
6412 if active is not None:
6416 if active in marks:
6413 if active in marks:
6417 ui.write(' *' + active, label=activebookmarklabel)
6414 ui.write(' *' + active, label=activebookmarklabel)
6418 marks.remove(active)
6415 marks.remove(active)
6419 else:
6416 else:
6420 ui.write(' [%s]' % active, label=activebookmarklabel)
6417 ui.write(' [%s]' % active, label=activebookmarklabel)
6421 for m in marks:
6418 for m in marks:
6422 ui.write(' ' + m, label='log.bookmark')
6419 ui.write(' ' + m, label='log.bookmark')
6423 ui.write('\n', label='log.bookmark')
6420 ui.write('\n', label='log.bookmark')
6424
6421
6425 status = repo.status(unknown=True)
6422 status = repo.status(unknown=True)
6426
6423
6427 c = repo.dirstate.copies()
6424 c = repo.dirstate.copies()
6428 copied, renamed = [], []
6425 copied, renamed = [], []
6429 for d, s in c.iteritems():
6426 for d, s in c.iteritems():
6430 if s in status.removed:
6427 if s in status.removed:
6431 status.removed.remove(s)
6428 status.removed.remove(s)
6432 renamed.append(d)
6429 renamed.append(d)
6433 else:
6430 else:
6434 copied.append(d)
6431 copied.append(d)
6435 if d in status.added:
6432 if d in status.added:
6436 status.added.remove(d)
6433 status.added.remove(d)
6437
6434
6438 try:
6435 try:
6439 ms = mergemod.mergestate.read(repo)
6436 ms = mergemod.mergestate.read(repo)
6440 except error.UnsupportedMergeRecords as e:
6437 except error.UnsupportedMergeRecords as e:
6441 s = ' '.join(e.recordtypes)
6438 s = ' '.join(e.recordtypes)
6442 ui.warn(
6439 ui.warn(
6443 _('warning: merge state has unsupported record types: %s\n') % s)
6440 _('warning: merge state has unsupported record types: %s\n') % s)
6444 unresolved = 0
6441 unresolved = 0
6445 else:
6442 else:
6446 unresolved = [f for f in ms if ms[f] == 'u']
6443 unresolved = [f for f in ms if ms[f] == 'u']
6447
6444
6448 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6445 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6449
6446
6450 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6447 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6451 (ui.label(_('%d added'), 'status.added'), status.added),
6448 (ui.label(_('%d added'), 'status.added'), status.added),
6452 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6449 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6453 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6450 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6454 (ui.label(_('%d copied'), 'status.copied'), copied),
6451 (ui.label(_('%d copied'), 'status.copied'), copied),
6455 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6452 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6456 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6453 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6457 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6454 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6458 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6455 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6459 t = []
6456 t = []
6460 for l, s in labels:
6457 for l, s in labels:
6461 if s:
6458 if s:
6462 t.append(l % len(s))
6459 t.append(l % len(s))
6463
6460
6464 t = ', '.join(t)
6461 t = ', '.join(t)
6465 cleanworkdir = False
6462 cleanworkdir = False
6466
6463
6467 if repo.vfs.exists('graftstate'):
6464 if repo.vfs.exists('graftstate'):
6468 t += _(' (graft in progress)')
6465 t += _(' (graft in progress)')
6469 if repo.vfs.exists('updatestate'):
6466 if repo.vfs.exists('updatestate'):
6470 t += _(' (interrupted update)')
6467 t += _(' (interrupted update)')
6471 elif len(parents) > 1:
6468 elif len(parents) > 1:
6472 t += _(' (merge)')
6469 t += _(' (merge)')
6473 elif branch != parents[0].branch():
6470 elif branch != parents[0].branch():
6474 t += _(' (new branch)')
6471 t += _(' (new branch)')
6475 elif (parents[0].closesbranch() and
6472 elif (parents[0].closesbranch() and
6476 pnode in repo.branchheads(branch, closed=True)):
6473 pnode in repo.branchheads(branch, closed=True)):
6477 t += _(' (head closed)')
6474 t += _(' (head closed)')
6478 elif not (status.modified or status.added or status.removed or renamed or
6475 elif not (status.modified or status.added or status.removed or renamed or
6479 copied or subs):
6476 copied or subs):
6480 t += _(' (clean)')
6477 t += _(' (clean)')
6481 cleanworkdir = True
6478 cleanworkdir = True
6482 elif pnode not in bheads:
6479 elif pnode not in bheads:
6483 t += _(' (new branch head)')
6480 t += _(' (new branch head)')
6484
6481
6485 if parents:
6482 if parents:
6486 pendingphase = max(p.phase() for p in parents)
6483 pendingphase = max(p.phase() for p in parents)
6487 else:
6484 else:
6488 pendingphase = phases.public
6485 pendingphase = phases.public
6489
6486
6490 if pendingphase > phases.newcommitphase(ui):
6487 if pendingphase > phases.newcommitphase(ui):
6491 t += ' (%s)' % phases.phasenames[pendingphase]
6488 t += ' (%s)' % phases.phasenames[pendingphase]
6492
6489
6493 if cleanworkdir:
6490 if cleanworkdir:
6494 # i18n: column positioning for "hg summary"
6491 # i18n: column positioning for "hg summary"
6495 ui.status(_('commit: %s\n') % t.strip())
6492 ui.status(_('commit: %s\n') % t.strip())
6496 else:
6493 else:
6497 # i18n: column positioning for "hg summary"
6494 # i18n: column positioning for "hg summary"
6498 ui.write(_('commit: %s\n') % t.strip())
6495 ui.write(_('commit: %s\n') % t.strip())
6499
6496
6500 # all ancestors of branch heads - all ancestors of parent = new csets
6497 # all ancestors of branch heads - all ancestors of parent = new csets
6501 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6498 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6502 bheads))
6499 bheads))
6503
6500
6504 if new == 0:
6501 if new == 0:
6505 # i18n: column positioning for "hg summary"
6502 # i18n: column positioning for "hg summary"
6506 ui.status(_('update: (current)\n'))
6503 ui.status(_('update: (current)\n'))
6507 elif pnode not in bheads:
6504 elif pnode not in bheads:
6508 # i18n: column positioning for "hg summary"
6505 # i18n: column positioning for "hg summary"
6509 ui.write(_('update: %d new changesets (update)\n') % new)
6506 ui.write(_('update: %d new changesets (update)\n') % new)
6510 else:
6507 else:
6511 # i18n: column positioning for "hg summary"
6508 # i18n: column positioning for "hg summary"
6512 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6509 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6513 (new, len(bheads)))
6510 (new, len(bheads)))
6514
6511
6515 t = []
6512 t = []
6516 draft = len(repo.revs('draft()'))
6513 draft = len(repo.revs('draft()'))
6517 if draft:
6514 if draft:
6518 t.append(_('%d draft') % draft)
6515 t.append(_('%d draft') % draft)
6519 secret = len(repo.revs('secret()'))
6516 secret = len(repo.revs('secret()'))
6520 if secret:
6517 if secret:
6521 t.append(_('%d secret') % secret)
6518 t.append(_('%d secret') % secret)
6522
6519
6523 if draft or secret:
6520 if draft or secret:
6524 ui.status(_('phases: %s\n') % ', '.join(t))
6521 ui.status(_('phases: %s\n') % ', '.join(t))
6525
6522
6526 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6523 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6527 for trouble in ("unstable", "divergent", "bumped"):
6524 for trouble in ("unstable", "divergent", "bumped"):
6528 numtrouble = len(repo.revs(trouble + "()"))
6525 numtrouble = len(repo.revs(trouble + "()"))
6529 # We write all the possibilities to ease translation
6526 # We write all the possibilities to ease translation
6530 troublemsg = {
6527 troublemsg = {
6531 "unstable": _("unstable: %d changesets"),
6528 "unstable": _("unstable: %d changesets"),
6532 "divergent": _("divergent: %d changesets"),
6529 "divergent": _("divergent: %d changesets"),
6533 "bumped": _("bumped: %d changesets"),
6530 "bumped": _("bumped: %d changesets"),
6534 }
6531 }
6535 if numtrouble > 0:
6532 if numtrouble > 0:
6536 ui.status(troublemsg[trouble] % numtrouble + "\n")
6533 ui.status(troublemsg[trouble] % numtrouble + "\n")
6537
6534
6538 cmdutil.summaryhooks(ui, repo)
6535 cmdutil.summaryhooks(ui, repo)
6539
6536
6540 if opts.get('remote'):
6537 if opts.get('remote'):
6541 needsincoming, needsoutgoing = True, True
6538 needsincoming, needsoutgoing = True, True
6542 else:
6539 else:
6543 needsincoming, needsoutgoing = False, False
6540 needsincoming, needsoutgoing = False, False
6544 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6541 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6545 if i:
6542 if i:
6546 needsincoming = True
6543 needsincoming = True
6547 if o:
6544 if o:
6548 needsoutgoing = True
6545 needsoutgoing = True
6549 if not needsincoming and not needsoutgoing:
6546 if not needsincoming and not needsoutgoing:
6550 return
6547 return
6551
6548
6552 def getincoming():
6549 def getincoming():
6553 source, branches = hg.parseurl(ui.expandpath('default'))
6550 source, branches = hg.parseurl(ui.expandpath('default'))
6554 sbranch = branches[0]
6551 sbranch = branches[0]
6555 try:
6552 try:
6556 other = hg.peer(repo, {}, source)
6553 other = hg.peer(repo, {}, source)
6557 except error.RepoError:
6554 except error.RepoError:
6558 if opts.get('remote'):
6555 if opts.get('remote'):
6559 raise
6556 raise
6560 return source, sbranch, None, None, None
6557 return source, sbranch, None, None, None
6561 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6558 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6562 if revs:
6559 if revs:
6563 revs = [other.lookup(rev) for rev in revs]
6560 revs = [other.lookup(rev) for rev in revs]
6564 ui.debug('comparing with %s\n' % util.hidepassword(source))
6561 ui.debug('comparing with %s\n' % util.hidepassword(source))
6565 repo.ui.pushbuffer()
6562 repo.ui.pushbuffer()
6566 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6563 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6567 repo.ui.popbuffer()
6564 repo.ui.popbuffer()
6568 return source, sbranch, other, commoninc, commoninc[1]
6565 return source, sbranch, other, commoninc, commoninc[1]
6569
6566
6570 if needsincoming:
6567 if needsincoming:
6571 source, sbranch, sother, commoninc, incoming = getincoming()
6568 source, sbranch, sother, commoninc, incoming = getincoming()
6572 else:
6569 else:
6573 source = sbranch = sother = commoninc = incoming = None
6570 source = sbranch = sother = commoninc = incoming = None
6574
6571
6575 def getoutgoing():
6572 def getoutgoing():
6576 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6573 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6577 dbranch = branches[0]
6574 dbranch = branches[0]
6578 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6575 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6579 if source != dest:
6576 if source != dest:
6580 try:
6577 try:
6581 dother = hg.peer(repo, {}, dest)
6578 dother = hg.peer(repo, {}, dest)
6582 except error.RepoError:
6579 except error.RepoError:
6583 if opts.get('remote'):
6580 if opts.get('remote'):
6584 raise
6581 raise
6585 return dest, dbranch, None, None
6582 return dest, dbranch, None, None
6586 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6583 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6587 elif sother is None:
6584 elif sother is None:
6588 # there is no explicit destination peer, but source one is invalid
6585 # there is no explicit destination peer, but source one is invalid
6589 return dest, dbranch, None, None
6586 return dest, dbranch, None, None
6590 else:
6587 else:
6591 dother = sother
6588 dother = sother
6592 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6589 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6593 common = None
6590 common = None
6594 else:
6591 else:
6595 common = commoninc
6592 common = commoninc
6596 if revs:
6593 if revs:
6597 revs = [repo.lookup(rev) for rev in revs]
6594 revs = [repo.lookup(rev) for rev in revs]
6598 repo.ui.pushbuffer()
6595 repo.ui.pushbuffer()
6599 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6596 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6600 commoninc=common)
6597 commoninc=common)
6601 repo.ui.popbuffer()
6598 repo.ui.popbuffer()
6602 return dest, dbranch, dother, outgoing
6599 return dest, dbranch, dother, outgoing
6603
6600
6604 if needsoutgoing:
6601 if needsoutgoing:
6605 dest, dbranch, dother, outgoing = getoutgoing()
6602 dest, dbranch, dother, outgoing = getoutgoing()
6606 else:
6603 else:
6607 dest = dbranch = dother = outgoing = None
6604 dest = dbranch = dother = outgoing = None
6608
6605
6609 if opts.get('remote'):
6606 if opts.get('remote'):
6610 t = []
6607 t = []
6611 if incoming:
6608 if incoming:
6612 t.append(_('1 or more incoming'))
6609 t.append(_('1 or more incoming'))
6613 o = outgoing.missing
6610 o = outgoing.missing
6614 if o:
6611 if o:
6615 t.append(_('%d outgoing') % len(o))
6612 t.append(_('%d outgoing') % len(o))
6616 other = dother or sother
6613 other = dother or sother
6617 if 'bookmarks' in other.listkeys('namespaces'):
6614 if 'bookmarks' in other.listkeys('namespaces'):
6618 counts = bookmarks.summary(repo, other)
6615 counts = bookmarks.summary(repo, other)
6619 if counts[0] > 0:
6616 if counts[0] > 0:
6620 t.append(_('%d incoming bookmarks') % counts[0])
6617 t.append(_('%d incoming bookmarks') % counts[0])
6621 if counts[1] > 0:
6618 if counts[1] > 0:
6622 t.append(_('%d outgoing bookmarks') % counts[1])
6619 t.append(_('%d outgoing bookmarks') % counts[1])
6623
6620
6624 if t:
6621 if t:
6625 # i18n: column positioning for "hg summary"
6622 # i18n: column positioning for "hg summary"
6626 ui.write(_('remote: %s\n') % (', '.join(t)))
6623 ui.write(_('remote: %s\n') % (', '.join(t)))
6627 else:
6624 else:
6628 # i18n: column positioning for "hg summary"
6625 # i18n: column positioning for "hg summary"
6629 ui.status(_('remote: (synced)\n'))
6626 ui.status(_('remote: (synced)\n'))
6630
6627
6631 cmdutil.summaryremotehooks(ui, repo, opts,
6628 cmdutil.summaryremotehooks(ui, repo, opts,
6632 ((source, sbranch, sother, commoninc),
6629 ((source, sbranch, sother, commoninc),
6633 (dest, dbranch, dother, outgoing)))
6630 (dest, dbranch, dother, outgoing)))
6634
6631
6635 @command('tag',
6632 @command('tag',
6636 [('f', 'force', None, _('force tag')),
6633 [('f', 'force', None, _('force tag')),
6637 ('l', 'local', None, _('make the tag local')),
6634 ('l', 'local', None, _('make the tag local')),
6638 ('r', 'rev', '', _('revision to tag'), _('REV')),
6635 ('r', 'rev', '', _('revision to tag'), _('REV')),
6639 ('', 'remove', None, _('remove a tag')),
6636 ('', 'remove', None, _('remove a tag')),
6640 # -l/--local is already there, commitopts cannot be used
6637 # -l/--local is already there, commitopts cannot be used
6641 ('e', 'edit', None, _('invoke editor on commit messages')),
6638 ('e', 'edit', None, _('invoke editor on commit messages')),
6642 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6639 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6643 ] + commitopts2,
6640 ] + commitopts2,
6644 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6641 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6645 def tag(ui, repo, name1, *names, **opts):
6642 def tag(ui, repo, name1, *names, **opts):
6646 """add one or more tags for the current or given revision
6643 """add one or more tags for the current or given revision
6647
6644
6648 Name a particular revision using <name>.
6645 Name a particular revision using <name>.
6649
6646
6650 Tags are used to name particular revisions of the repository and are
6647 Tags are used to name particular revisions of the repository and are
6651 very useful to compare different revisions, to go back to significant
6648 very useful to compare different revisions, to go back to significant
6652 earlier versions or to mark branch points as releases, etc. Changing
6649 earlier versions or to mark branch points as releases, etc. Changing
6653 an existing tag is normally disallowed; use -f/--force to override.
6650 an existing tag is normally disallowed; use -f/--force to override.
6654
6651
6655 If no revision is given, the parent of the working directory is
6652 If no revision is given, the parent of the working directory is
6656 used.
6653 used.
6657
6654
6658 To facilitate version control, distribution, and merging of tags,
6655 To facilitate version control, distribution, and merging of tags,
6659 they are stored as a file named ".hgtags" which is managed similarly
6656 they are stored as a file named ".hgtags" which is managed similarly
6660 to other project files and can be hand-edited if necessary. This
6657 to other project files and can be hand-edited if necessary. This
6661 also means that tagging creates a new commit. The file
6658 also means that tagging creates a new commit. The file
6662 ".hg/localtags" is used for local tags (not shared among
6659 ".hg/localtags" is used for local tags (not shared among
6663 repositories).
6660 repositories).
6664
6661
6665 Tag commits are usually made at the head of a branch. If the parent
6662 Tag commits are usually made at the head of a branch. If the parent
6666 of the working directory is not a branch head, :hg:`tag` aborts; use
6663 of the working directory is not a branch head, :hg:`tag` aborts; use
6667 -f/--force to force the tag commit to be based on a non-head
6664 -f/--force to force the tag commit to be based on a non-head
6668 changeset.
6665 changeset.
6669
6666
6670 See :hg:`help dates` for a list of formats valid for -d/--date.
6667 See :hg:`help dates` for a list of formats valid for -d/--date.
6671
6668
6672 Since tag names have priority over branch names during revision
6669 Since tag names have priority over branch names during revision
6673 lookup, using an existing branch name as a tag name is discouraged.
6670 lookup, using an existing branch name as a tag name is discouraged.
6674
6671
6675 Returns 0 on success.
6672 Returns 0 on success.
6676 """
6673 """
6677 wlock = lock = None
6674 wlock = lock = None
6678 try:
6675 try:
6679 wlock = repo.wlock()
6676 wlock = repo.wlock()
6680 lock = repo.lock()
6677 lock = repo.lock()
6681 rev_ = "."
6678 rev_ = "."
6682 names = [t.strip() for t in (name1,) + names]
6679 names = [t.strip() for t in (name1,) + names]
6683 if len(names) != len(set(names)):
6680 if len(names) != len(set(names)):
6684 raise error.Abort(_('tag names must be unique'))
6681 raise error.Abort(_('tag names must be unique'))
6685 for n in names:
6682 for n in names:
6686 scmutil.checknewlabel(repo, n, 'tag')
6683 scmutil.checknewlabel(repo, n, 'tag')
6687 if not n:
6684 if not n:
6688 raise error.Abort(_('tag names cannot consist entirely of '
6685 raise error.Abort(_('tag names cannot consist entirely of '
6689 'whitespace'))
6686 'whitespace'))
6690 if opts.get('rev') and opts.get('remove'):
6687 if opts.get('rev') and opts.get('remove'):
6691 raise error.Abort(_("--rev and --remove are incompatible"))
6688 raise error.Abort(_("--rev and --remove are incompatible"))
6692 if opts.get('rev'):
6689 if opts.get('rev'):
6693 rev_ = opts['rev']
6690 rev_ = opts['rev']
6694 message = opts.get('message')
6691 message = opts.get('message')
6695 if opts.get('remove'):
6692 if opts.get('remove'):
6696 if opts.get('local'):
6693 if opts.get('local'):
6697 expectedtype = 'local'
6694 expectedtype = 'local'
6698 else:
6695 else:
6699 expectedtype = 'global'
6696 expectedtype = 'global'
6700
6697
6701 for n in names:
6698 for n in names:
6702 if not repo.tagtype(n):
6699 if not repo.tagtype(n):
6703 raise error.Abort(_("tag '%s' does not exist") % n)
6700 raise error.Abort(_("tag '%s' does not exist") % n)
6704 if repo.tagtype(n) != expectedtype:
6701 if repo.tagtype(n) != expectedtype:
6705 if expectedtype == 'global':
6702 if expectedtype == 'global':
6706 raise error.Abort(_("tag '%s' is not a global tag") % n)
6703 raise error.Abort(_("tag '%s' is not a global tag") % n)
6707 else:
6704 else:
6708 raise error.Abort(_("tag '%s' is not a local tag") % n)
6705 raise error.Abort(_("tag '%s' is not a local tag") % n)
6709 rev_ = 'null'
6706 rev_ = 'null'
6710 if not message:
6707 if not message:
6711 # we don't translate commit messages
6708 # we don't translate commit messages
6712 message = 'Removed tag %s' % ', '.join(names)
6709 message = 'Removed tag %s' % ', '.join(names)
6713 elif not opts.get('force'):
6710 elif not opts.get('force'):
6714 for n in names:
6711 for n in names:
6715 if n in repo.tags():
6712 if n in repo.tags():
6716 raise error.Abort(_("tag '%s' already exists "
6713 raise error.Abort(_("tag '%s' already exists "
6717 "(use -f to force)") % n)
6714 "(use -f to force)") % n)
6718 if not opts.get('local'):
6715 if not opts.get('local'):
6719 p1, p2 = repo.dirstate.parents()
6716 p1, p2 = repo.dirstate.parents()
6720 if p2 != nullid:
6717 if p2 != nullid:
6721 raise error.Abort(_('uncommitted merge'))
6718 raise error.Abort(_('uncommitted merge'))
6722 bheads = repo.branchheads()
6719 bheads = repo.branchheads()
6723 if not opts.get('force') and bheads and p1 not in bheads:
6720 if not opts.get('force') and bheads and p1 not in bheads:
6724 raise error.Abort(_('not at a branch head (use -f to force)'))
6721 raise error.Abort(_('not at a branch head (use -f to force)'))
6725 r = scmutil.revsingle(repo, rev_).node()
6722 r = scmutil.revsingle(repo, rev_).node()
6726
6723
6727 if not message:
6724 if not message:
6728 # we don't translate commit messages
6725 # we don't translate commit messages
6729 message = ('Added tag %s for changeset %s' %
6726 message = ('Added tag %s for changeset %s' %
6730 (', '.join(names), short(r)))
6727 (', '.join(names), short(r)))
6731
6728
6732 date = opts.get('date')
6729 date = opts.get('date')
6733 if date:
6730 if date:
6734 date = util.parsedate(date)
6731 date = util.parsedate(date)
6735
6732
6736 if opts.get('remove'):
6733 if opts.get('remove'):
6737 editform = 'tag.remove'
6734 editform = 'tag.remove'
6738 else:
6735 else:
6739 editform = 'tag.add'
6736 editform = 'tag.add'
6740 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6737 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6741
6738
6742 # don't allow tagging the null rev
6739 # don't allow tagging the null rev
6743 if (not opts.get('remove') and
6740 if (not opts.get('remove') and
6744 scmutil.revsingle(repo, rev_).rev() == nullrev):
6741 scmutil.revsingle(repo, rev_).rev() == nullrev):
6745 raise error.Abort(_("cannot tag null revision"))
6742 raise error.Abort(_("cannot tag null revision"))
6746
6743
6747 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6744 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6748 editor=editor)
6745 editor=editor)
6749 finally:
6746 finally:
6750 release(lock, wlock)
6747 release(lock, wlock)
6751
6748
6752 @command('tags', formatteropts, '')
6749 @command('tags', formatteropts, '')
6753 def tags(ui, repo, **opts):
6750 def tags(ui, repo, **opts):
6754 """list repository tags
6751 """list repository tags
6755
6752
6756 This lists both regular and local tags. When the -v/--verbose
6753 This lists both regular and local tags. When the -v/--verbose
6757 switch is used, a third column "local" is printed for local tags.
6754 switch is used, a third column "local" is printed for local tags.
6758 When the -q/--quiet switch is used, only the tag name is printed.
6755 When the -q/--quiet switch is used, only the tag name is printed.
6759
6756
6760 Returns 0 on success.
6757 Returns 0 on success.
6761 """
6758 """
6762
6759
6763 fm = ui.formatter('tags', opts)
6760 fm = ui.formatter('tags', opts)
6764 hexfunc = fm.hexfunc
6761 hexfunc = fm.hexfunc
6765 tagtype = ""
6762 tagtype = ""
6766
6763
6767 for t, n in reversed(repo.tagslist()):
6764 for t, n in reversed(repo.tagslist()):
6768 hn = hexfunc(n)
6765 hn = hexfunc(n)
6769 label = 'tags.normal'
6766 label = 'tags.normal'
6770 tagtype = ''
6767 tagtype = ''
6771 if repo.tagtype(t) == 'local':
6768 if repo.tagtype(t) == 'local':
6772 label = 'tags.local'
6769 label = 'tags.local'
6773 tagtype = 'local'
6770 tagtype = 'local'
6774
6771
6775 fm.startitem()
6772 fm.startitem()
6776 fm.write('tag', '%s', t, label=label)
6773 fm.write('tag', '%s', t, label=label)
6777 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6774 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6778 fm.condwrite(not ui.quiet, 'rev node', fmt,
6775 fm.condwrite(not ui.quiet, 'rev node', fmt,
6779 repo.changelog.rev(n), hn, label=label)
6776 repo.changelog.rev(n), hn, label=label)
6780 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6777 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6781 tagtype, label=label)
6778 tagtype, label=label)
6782 fm.plain('\n')
6779 fm.plain('\n')
6783 fm.end()
6780 fm.end()
6784
6781
6785 @command('tip',
6782 @command('tip',
6786 [('p', 'patch', None, _('show patch')),
6783 [('p', 'patch', None, _('show patch')),
6787 ('g', 'git', None, _('use git extended diff format')),
6784 ('g', 'git', None, _('use git extended diff format')),
6788 ] + templateopts,
6785 ] + templateopts,
6789 _('[-p] [-g]'))
6786 _('[-p] [-g]'))
6790 def tip(ui, repo, **opts):
6787 def tip(ui, repo, **opts):
6791 """show the tip revision (DEPRECATED)
6788 """show the tip revision (DEPRECATED)
6792
6789
6793 The tip revision (usually just called the tip) is the changeset
6790 The tip revision (usually just called the tip) is the changeset
6794 most recently added to the repository (and therefore the most
6791 most recently added to the repository (and therefore the most
6795 recently changed head).
6792 recently changed head).
6796
6793
6797 If you have just made a commit, that commit will be the tip. If
6794 If you have just made a commit, that commit will be the tip. If
6798 you have just pulled changes from another repository, the tip of
6795 you have just pulled changes from another repository, the tip of
6799 that repository becomes the current tip. The "tip" tag is special
6796 that repository becomes the current tip. The "tip" tag is special
6800 and cannot be renamed or assigned to a different changeset.
6797 and cannot be renamed or assigned to a different changeset.
6801
6798
6802 This command is deprecated, please use :hg:`heads` instead.
6799 This command is deprecated, please use :hg:`heads` instead.
6803
6800
6804 Returns 0 on success.
6801 Returns 0 on success.
6805 """
6802 """
6806 displayer = cmdutil.show_changeset(ui, repo, opts)
6803 displayer = cmdutil.show_changeset(ui, repo, opts)
6807 displayer.show(repo['tip'])
6804 displayer.show(repo['tip'])
6808 displayer.close()
6805 displayer.close()
6809
6806
6810 @command('unbundle',
6807 @command('unbundle',
6811 [('u', 'update', None,
6808 [('u', 'update', None,
6812 _('update to new branch head if changesets were unbundled'))],
6809 _('update to new branch head if changesets were unbundled'))],
6813 _('[-u] FILE...'))
6810 _('[-u] FILE...'))
6814 def unbundle(ui, repo, fname1, *fnames, **opts):
6811 def unbundle(ui, repo, fname1, *fnames, **opts):
6815 """apply one or more changegroup files
6812 """apply one or more changegroup files
6816
6813
6817 Apply one or more compressed changegroup files generated by the
6814 Apply one or more compressed changegroup files generated by the
6818 bundle command.
6815 bundle command.
6819
6816
6820 Returns 0 on success, 1 if an update has unresolved files.
6817 Returns 0 on success, 1 if an update has unresolved files.
6821 """
6818 """
6822 fnames = (fname1,) + fnames
6819 fnames = (fname1,) + fnames
6823
6820
6824 with repo.lock():
6821 with repo.lock():
6825 for fname in fnames:
6822 for fname in fnames:
6826 f = hg.openpath(ui, fname)
6823 f = hg.openpath(ui, fname)
6827 gen = exchange.readbundle(ui, f, fname)
6824 gen = exchange.readbundle(ui, f, fname)
6828 if isinstance(gen, bundle2.unbundle20):
6825 if isinstance(gen, bundle2.unbundle20):
6829 tr = repo.transaction('unbundle')
6826 tr = repo.transaction('unbundle')
6830 try:
6827 try:
6831 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6828 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6832 url='bundle:' + fname)
6829 url='bundle:' + fname)
6833 tr.close()
6830 tr.close()
6834 except error.BundleUnknownFeatureError as exc:
6831 except error.BundleUnknownFeatureError as exc:
6835 raise error.Abort(_('%s: unknown bundle feature, %s')
6832 raise error.Abort(_('%s: unknown bundle feature, %s')
6836 % (fname, exc),
6833 % (fname, exc),
6837 hint=_("see https://mercurial-scm.org/"
6834 hint=_("see https://mercurial-scm.org/"
6838 "wiki/BundleFeature for more "
6835 "wiki/BundleFeature for more "
6839 "information"))
6836 "information"))
6840 finally:
6837 finally:
6841 if tr:
6838 if tr:
6842 tr.release()
6839 tr.release()
6843 changes = [r.get('return', 0)
6840 changes = [r.get('return', 0)
6844 for r in op.records['changegroup']]
6841 for r in op.records['changegroup']]
6845 modheads = changegroup.combineresults(changes)
6842 modheads = changegroup.combineresults(changes)
6846 elif isinstance(gen, streamclone.streamcloneapplier):
6843 elif isinstance(gen, streamclone.streamcloneapplier):
6847 raise error.Abort(
6844 raise error.Abort(
6848 _('packed bundles cannot be applied with '
6845 _('packed bundles cannot be applied with '
6849 '"hg unbundle"'),
6846 '"hg unbundle"'),
6850 hint=_('use "hg debugapplystreamclonebundle"'))
6847 hint=_('use "hg debugapplystreamclonebundle"'))
6851 else:
6848 else:
6852 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6849 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6853
6850
6854 return postincoming(ui, repo, modheads, opts.get('update'), None)
6851 return postincoming(ui, repo, modheads, opts.get('update'), None)
6855
6852
6856 @command('^update|up|checkout|co',
6853 @command('^update|up|checkout|co',
6857 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6854 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6858 ('c', 'check', None,
6855 ('c', 'check', None,
6859 _('update across branches if no uncommitted changes')),
6856 _('update across branches if no uncommitted changes')),
6860 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6857 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6861 ('r', 'rev', '', _('revision'), _('REV'))
6858 ('r', 'rev', '', _('revision'), _('REV'))
6862 ] + mergetoolopts,
6859 ] + mergetoolopts,
6863 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6860 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6864 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6861 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6865 tool=None):
6862 tool=None):
6866 """update working directory (or switch revisions)
6863 """update working directory (or switch revisions)
6867
6864
6868 Update the repository's working directory to the specified
6865 Update the repository's working directory to the specified
6869 changeset. If no changeset is specified, update to the tip of the
6866 changeset. If no changeset is specified, update to the tip of the
6870 current named branch and move the active bookmark (see :hg:`help
6867 current named branch and move the active bookmark (see :hg:`help
6871 bookmarks`).
6868 bookmarks`).
6872
6869
6873 Update sets the working directory's parent revision to the specified
6870 Update sets the working directory's parent revision to the specified
6874 changeset (see :hg:`help parents`).
6871 changeset (see :hg:`help parents`).
6875
6872
6876 If the changeset is not a descendant or ancestor of the working
6873 If the changeset is not a descendant or ancestor of the working
6877 directory's parent, the update is aborted. With the -c/--check
6874 directory's parent, the update is aborted. With the -c/--check
6878 option, the working directory is checked for uncommitted changes; if
6875 option, the working directory is checked for uncommitted changes; if
6879 none are found, the working directory is updated to the specified
6876 none are found, the working directory is updated to the specified
6880 changeset.
6877 changeset.
6881
6878
6882 .. container:: verbose
6879 .. container:: verbose
6883
6880
6884 The following rules apply when the working directory contains
6881 The following rules apply when the working directory contains
6885 uncommitted changes:
6882 uncommitted changes:
6886
6883
6887 1. If neither -c/--check nor -C/--clean is specified, and if
6884 1. If neither -c/--check nor -C/--clean is specified, and if
6888 the requested changeset is an ancestor or descendant of
6885 the requested changeset is an ancestor or descendant of
6889 the working directory's parent, the uncommitted changes
6886 the working directory's parent, the uncommitted changes
6890 are merged into the requested changeset and the merged
6887 are merged into the requested changeset and the merged
6891 result is left uncommitted. If the requested changeset is
6888 result is left uncommitted. If the requested changeset is
6892 not an ancestor or descendant (that is, it is on another
6889 not an ancestor or descendant (that is, it is on another
6893 branch), the update is aborted and the uncommitted changes
6890 branch), the update is aborted and the uncommitted changes
6894 are preserved.
6891 are preserved.
6895
6892
6896 2. With the -c/--check option, the update is aborted and the
6893 2. With the -c/--check option, the update is aborted and the
6897 uncommitted changes are preserved.
6894 uncommitted changes are preserved.
6898
6895
6899 3. With the -C/--clean option, uncommitted changes are discarded and
6896 3. With the -C/--clean option, uncommitted changes are discarded and
6900 the working directory is updated to the requested changeset.
6897 the working directory is updated to the requested changeset.
6901
6898
6902 To cancel an uncommitted merge (and lose your changes), use
6899 To cancel an uncommitted merge (and lose your changes), use
6903 :hg:`update --clean .`.
6900 :hg:`update --clean .`.
6904
6901
6905 Use null as the changeset to remove the working directory (like
6902 Use null as the changeset to remove the working directory (like
6906 :hg:`clone -U`).
6903 :hg:`clone -U`).
6907
6904
6908 If you want to revert just one file to an older revision, use
6905 If you want to revert just one file to an older revision, use
6909 :hg:`revert [-r REV] NAME`.
6906 :hg:`revert [-r REV] NAME`.
6910
6907
6911 See :hg:`help dates` for a list of formats valid for -d/--date.
6908 See :hg:`help dates` for a list of formats valid for -d/--date.
6912
6909
6913 Returns 0 on success, 1 if there are unresolved files.
6910 Returns 0 on success, 1 if there are unresolved files.
6914 """
6911 """
6915 movemarkfrom = None
6912 movemarkfrom = None
6916 if rev and node:
6913 if rev and node:
6917 raise error.Abort(_("please specify just one revision"))
6914 raise error.Abort(_("please specify just one revision"))
6918
6915
6919 if rev is None or rev == '':
6916 if rev is None or rev == '':
6920 rev = node
6917 rev = node
6921
6918
6922 with repo.wlock():
6919 with repo.wlock():
6923 cmdutil.clearunfinished(repo)
6920 cmdutil.clearunfinished(repo)
6924
6921
6925 if date:
6922 if date:
6926 if rev is not None:
6923 if rev is not None:
6927 raise error.Abort(_("you can't specify a revision and a date"))
6924 raise error.Abort(_("you can't specify a revision and a date"))
6928 rev = cmdutil.finddate(ui, repo, date)
6925 rev = cmdutil.finddate(ui, repo, date)
6929
6926
6930 # if we defined a bookmark, we have to remember the original name
6927 # if we defined a bookmark, we have to remember the original name
6931 brev = rev
6928 brev = rev
6932 rev = scmutil.revsingle(repo, rev, rev).rev()
6929 rev = scmutil.revsingle(repo, rev, rev).rev()
6933
6930
6934 if check and clean:
6931 if check and clean:
6935 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6932 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6936 )
6933 )
6937
6934
6938 if check:
6935 if check:
6939 cmdutil.bailifchanged(repo, merge=False)
6936 cmdutil.bailifchanged(repo, merge=False)
6940 if rev is None:
6937 if rev is None:
6941 updata = destutil.destupdate(repo, clean=clean, check=check)
6938 updata = destutil.destupdate(repo, clean=clean, check=check)
6942 rev, movemarkfrom, brev = updata
6939 rev, movemarkfrom, brev = updata
6943
6940
6944 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6941 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6945
6942
6946 if clean:
6943 if clean:
6947 ret = hg.clean(repo, rev)
6944 ret = hg.clean(repo, rev)
6948 else:
6945 else:
6949 ret = hg.update(repo, rev)
6946 ret = hg.update(repo, rev)
6950
6947
6951 if not ret and movemarkfrom:
6948 if not ret and movemarkfrom:
6952 if movemarkfrom == repo['.'].node():
6949 if movemarkfrom == repo['.'].node():
6953 pass # no-op update
6950 pass # no-op update
6954 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6951 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6955 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6952 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6956 else:
6953 else:
6957 # this can happen with a non-linear update
6954 # this can happen with a non-linear update
6958 ui.status(_("(leaving bookmark %s)\n") %
6955 ui.status(_("(leaving bookmark %s)\n") %
6959 repo._activebookmark)
6956 repo._activebookmark)
6960 bookmarks.deactivate(repo)
6957 bookmarks.deactivate(repo)
6961 elif brev in repo._bookmarks:
6958 elif brev in repo._bookmarks:
6962 bookmarks.activate(repo, brev)
6959 bookmarks.activate(repo, brev)
6963 ui.status(_("(activating bookmark %s)\n") % brev)
6960 ui.status(_("(activating bookmark %s)\n") % brev)
6964 elif brev:
6961 elif brev:
6965 if repo._activebookmark:
6962 if repo._activebookmark:
6966 ui.status(_("(leaving bookmark %s)\n") %
6963 ui.status(_("(leaving bookmark %s)\n") %
6967 repo._activebookmark)
6964 repo._activebookmark)
6968 bookmarks.deactivate(repo)
6965 bookmarks.deactivate(repo)
6969
6966
6970 return ret
6967 return ret
6971
6968
6972 @command('verify', [])
6969 @command('verify', [])
6973 def verify(ui, repo):
6970 def verify(ui, repo):
6974 """verify the integrity of the repository
6971 """verify the integrity of the repository
6975
6972
6976 Verify the integrity of the current repository.
6973 Verify the integrity of the current repository.
6977
6974
6978 This will perform an extensive check of the repository's
6975 This will perform an extensive check of the repository's
6979 integrity, validating the hashes and checksums of each entry in
6976 integrity, validating the hashes and checksums of each entry in
6980 the changelog, manifest, and tracked files, as well as the
6977 the changelog, manifest, and tracked files, as well as the
6981 integrity of their crosslinks and indices.
6978 integrity of their crosslinks and indices.
6982
6979
6983 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6980 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6984 for more information about recovery from corruption of the
6981 for more information about recovery from corruption of the
6985 repository.
6982 repository.
6986
6983
6987 Returns 0 on success, 1 if errors are encountered.
6984 Returns 0 on success, 1 if errors are encountered.
6988 """
6985 """
6989 return hg.verify(repo)
6986 return hg.verify(repo)
6990
6987
6991 @command('version', [], norepo=True)
6988 @command('version', [], norepo=True)
6992 def version_(ui):
6989 def version_(ui):
6993 """output version and copyright information"""
6990 """output version and copyright information"""
6994 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6991 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6995 % util.version())
6992 % util.version())
6996 ui.status(_(
6993 ui.status(_(
6997 "(see https://mercurial-scm.org for more information)\n"
6994 "(see https://mercurial-scm.org for more information)\n"
6998 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6995 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6999 "This is free software; see the source for copying conditions. "
6996 "This is free software; see the source for copying conditions. "
7000 "There is NO\nwarranty; "
6997 "There is NO\nwarranty; "
7001 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6998 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7002 ))
6999 ))
7003
7000
7004 ui.note(_("\nEnabled extensions:\n\n"))
7001 ui.note(_("\nEnabled extensions:\n\n"))
7005 if ui.verbose:
7002 if ui.verbose:
7006 # format names and versions into columns
7003 # format names and versions into columns
7007 names = []
7004 names = []
7008 vers = []
7005 vers = []
7009 for name, module in extensions.extensions():
7006 for name, module in extensions.extensions():
7010 names.append(name)
7007 names.append(name)
7011 vers.append(extensions.moduleversion(module))
7008 vers.append(extensions.moduleversion(module))
7012 if names:
7009 if names:
7013 maxnamelen = max(len(n) for n in names)
7010 maxnamelen = max(len(n) for n in names)
7014 for i, name in enumerate(names):
7011 for i, name in enumerate(names):
7015 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7012 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now