##// END OF EJS Templates
with: use context manager in update
Bryan O'Sullivan -
r27854:55394c6f default
parent child Browse files
Show More
@@ -1,7031 +1,7028 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 f = hg.openpath(ui, bundlepath)
2016 try:
2016 try:
2017 gen = exchange.readbundle(ui, f, bundlepath)
2017 gen = exchange.readbundle(ui, f, bundlepath)
2018 if isinstance(gen, bundle2.unbundle20):
2018 if isinstance(gen, bundle2.unbundle20):
2019 return _debugbundle2(ui, gen, all=all, **opts)
2019 return _debugbundle2(ui, gen, all=all, **opts)
2020 if all:
2020 if all:
2021 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2021 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2022
2022
2023 def showchunks(named):
2023 def showchunks(named):
2024 ui.write("\n%s\n" % named)
2024 ui.write("\n%s\n" % named)
2025 chain = None
2025 chain = None
2026 while True:
2026 while True:
2027 chunkdata = gen.deltachunk(chain)
2027 chunkdata = gen.deltachunk(chain)
2028 if not chunkdata:
2028 if not chunkdata:
2029 break
2029 break
2030 node = chunkdata['node']
2030 node = chunkdata['node']
2031 p1 = chunkdata['p1']
2031 p1 = chunkdata['p1']
2032 p2 = chunkdata['p2']
2032 p2 = chunkdata['p2']
2033 cs = chunkdata['cs']
2033 cs = chunkdata['cs']
2034 deltabase = chunkdata['deltabase']
2034 deltabase = chunkdata['deltabase']
2035 delta = chunkdata['delta']
2035 delta = chunkdata['delta']
2036 ui.write("%s %s %s %s %s %s\n" %
2036 ui.write("%s %s %s %s %s %s\n" %
2037 (hex(node), hex(p1), hex(p2),
2037 (hex(node), hex(p1), hex(p2),
2038 hex(cs), hex(deltabase), len(delta)))
2038 hex(cs), hex(deltabase), len(delta)))
2039 chain = node
2039 chain = node
2040
2040
2041 chunkdata = gen.changelogheader()
2041 chunkdata = gen.changelogheader()
2042 showchunks("changelog")
2042 showchunks("changelog")
2043 chunkdata = gen.manifestheader()
2043 chunkdata = gen.manifestheader()
2044 showchunks("manifest")
2044 showchunks("manifest")
2045 while True:
2045 while True:
2046 chunkdata = gen.filelogheader()
2046 chunkdata = gen.filelogheader()
2047 if not chunkdata:
2047 if not chunkdata:
2048 break
2048 break
2049 fname = chunkdata['filename']
2049 fname = chunkdata['filename']
2050 showchunks(fname)
2050 showchunks(fname)
2051 else:
2051 else:
2052 if isinstance(gen, bundle2.unbundle20):
2052 if isinstance(gen, bundle2.unbundle20):
2053 raise error.Abort(_('use debugbundle2 for this file'))
2053 raise error.Abort(_('use debugbundle2 for this file'))
2054 chunkdata = gen.changelogheader()
2054 chunkdata = gen.changelogheader()
2055 chain = None
2055 chain = None
2056 while True:
2056 while True:
2057 chunkdata = gen.deltachunk(chain)
2057 chunkdata = gen.deltachunk(chain)
2058 if not chunkdata:
2058 if not chunkdata:
2059 break
2059 break
2060 node = chunkdata['node']
2060 node = chunkdata['node']
2061 ui.write("%s\n" % hex(node))
2061 ui.write("%s\n" % hex(node))
2062 chain = node
2062 chain = node
2063 finally:
2063 finally:
2064 f.close()
2064 f.close()
2065
2065
2066 def _debugbundle2(ui, gen, **opts):
2066 def _debugbundle2(ui, gen, **opts):
2067 """lists the contents of a bundle2"""
2067 """lists the contents of a bundle2"""
2068 if not isinstance(gen, bundle2.unbundle20):
2068 if not isinstance(gen, bundle2.unbundle20):
2069 raise error.Abort(_('not a bundle2 file'))
2069 raise error.Abort(_('not a bundle2 file'))
2070 ui.write(('Stream params: %s\n' % repr(gen.params)))
2070 ui.write(('Stream params: %s\n' % repr(gen.params)))
2071 for part in gen.iterparts():
2071 for part in gen.iterparts():
2072 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2072 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2073 if part.type == 'changegroup':
2073 if part.type == 'changegroup':
2074 version = part.params.get('version', '01')
2074 version = part.params.get('version', '01')
2075 cg = changegroup.getunbundler(version, part, 'UN')
2075 cg = changegroup.getunbundler(version, part, 'UN')
2076 chunkdata = cg.changelogheader()
2076 chunkdata = cg.changelogheader()
2077 chain = None
2077 chain = None
2078 while True:
2078 while True:
2079 chunkdata = cg.deltachunk(chain)
2079 chunkdata = cg.deltachunk(chain)
2080 if not chunkdata:
2080 if not chunkdata:
2081 break
2081 break
2082 node = chunkdata['node']
2082 node = chunkdata['node']
2083 ui.write(" %s\n" % hex(node))
2083 ui.write(" %s\n" % hex(node))
2084 chain = node
2084 chain = node
2085
2085
2086 @command('debugcreatestreamclonebundle', [], 'FILE')
2086 @command('debugcreatestreamclonebundle', [], 'FILE')
2087 def debugcreatestreamclonebundle(ui, repo, fname):
2087 def debugcreatestreamclonebundle(ui, repo, fname):
2088 """create a stream clone bundle file
2088 """create a stream clone bundle file
2089
2089
2090 Stream bundles are special bundles that are essentially archives of
2090 Stream bundles are special bundles that are essentially archives of
2091 revlog files. They are commonly used for cloning very quickly.
2091 revlog files. They are commonly used for cloning very quickly.
2092 """
2092 """
2093 requirements, gen = streamclone.generatebundlev1(repo)
2093 requirements, gen = streamclone.generatebundlev1(repo)
2094 changegroup.writechunks(ui, gen, fname)
2094 changegroup.writechunks(ui, gen, fname)
2095
2095
2096 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2096 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2097
2097
2098 @command('debugapplystreamclonebundle', [], 'FILE')
2098 @command('debugapplystreamclonebundle', [], 'FILE')
2099 def debugapplystreamclonebundle(ui, repo, fname):
2099 def debugapplystreamclonebundle(ui, repo, fname):
2100 """apply a stream clone bundle file"""
2100 """apply a stream clone bundle file"""
2101 f = hg.openpath(ui, fname)
2101 f = hg.openpath(ui, fname)
2102 gen = exchange.readbundle(ui, f, fname)
2102 gen = exchange.readbundle(ui, f, fname)
2103 gen.apply(repo)
2103 gen.apply(repo)
2104
2104
2105 @command('debugcheckstate', [], '')
2105 @command('debugcheckstate', [], '')
2106 def debugcheckstate(ui, repo):
2106 def debugcheckstate(ui, repo):
2107 """validate the correctness of the current dirstate"""
2107 """validate the correctness of the current dirstate"""
2108 parent1, parent2 = repo.dirstate.parents()
2108 parent1, parent2 = repo.dirstate.parents()
2109 m1 = repo[parent1].manifest()
2109 m1 = repo[parent1].manifest()
2110 m2 = repo[parent2].manifest()
2110 m2 = repo[parent2].manifest()
2111 errors = 0
2111 errors = 0
2112 for f in repo.dirstate:
2112 for f in repo.dirstate:
2113 state = repo.dirstate[f]
2113 state = repo.dirstate[f]
2114 if state in "nr" and f not in m1:
2114 if state in "nr" and f not in m1:
2115 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2115 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2116 errors += 1
2116 errors += 1
2117 if state in "a" and f in m1:
2117 if state in "a" and f in m1:
2118 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2118 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2119 errors += 1
2119 errors += 1
2120 if state in "m" and f not in m1 and f not in m2:
2120 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") %
2121 ui.warn(_("%s in state %s, but not in either manifest\n") %
2122 (f, state))
2122 (f, state))
2123 errors += 1
2123 errors += 1
2124 for f in m1:
2124 for f in m1:
2125 state = repo.dirstate[f]
2125 state = repo.dirstate[f]
2126 if state not in "nrm":
2126 if state not in "nrm":
2127 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2127 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2128 errors += 1
2128 errors += 1
2129 if errors:
2129 if errors:
2130 error = _(".hg/dirstate inconsistent with current parent's manifest")
2130 error = _(".hg/dirstate inconsistent with current parent's manifest")
2131 raise error.Abort(error)
2131 raise error.Abort(error)
2132
2132
2133 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2133 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2134 def debugcommands(ui, cmd='', *args):
2134 def debugcommands(ui, cmd='', *args):
2135 """list all available commands and options"""
2135 """list all available commands and options"""
2136 for cmd, vals in sorted(table.iteritems()):
2136 for cmd, vals in sorted(table.iteritems()):
2137 cmd = cmd.split('|')[0].strip('^')
2137 cmd = cmd.split('|')[0].strip('^')
2138 opts = ', '.join([i[1] for i in vals[1]])
2138 opts = ', '.join([i[1] for i in vals[1]])
2139 ui.write('%s: %s\n' % (cmd, opts))
2139 ui.write('%s: %s\n' % (cmd, opts))
2140
2140
2141 @command('debugcomplete',
2141 @command('debugcomplete',
2142 [('o', 'options', None, _('show the command options'))],
2142 [('o', 'options', None, _('show the command options'))],
2143 _('[-o] CMD'),
2143 _('[-o] CMD'),
2144 norepo=True)
2144 norepo=True)
2145 def debugcomplete(ui, cmd='', **opts):
2145 def debugcomplete(ui, cmd='', **opts):
2146 """returns the completion list associated with the given command"""
2146 """returns the completion list associated with the given command"""
2147
2147
2148 if opts.get('options'):
2148 if opts.get('options'):
2149 options = []
2149 options = []
2150 otables = [globalopts]
2150 otables = [globalopts]
2151 if cmd:
2151 if cmd:
2152 aliases, entry = cmdutil.findcmd(cmd, table, False)
2152 aliases, entry = cmdutil.findcmd(cmd, table, False)
2153 otables.append(entry[1])
2153 otables.append(entry[1])
2154 for t in otables:
2154 for t in otables:
2155 for o in t:
2155 for o in t:
2156 if "(DEPRECATED)" in o[3]:
2156 if "(DEPRECATED)" in o[3]:
2157 continue
2157 continue
2158 if o[0]:
2158 if o[0]:
2159 options.append('-%s' % o[0])
2159 options.append('-%s' % o[0])
2160 options.append('--%s' % o[1])
2160 options.append('--%s' % o[1])
2161 ui.write("%s\n" % "\n".join(options))
2161 ui.write("%s\n" % "\n".join(options))
2162 return
2162 return
2163
2163
2164 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2164 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2165 if ui.verbose:
2165 if ui.verbose:
2166 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2166 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2167 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2167 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2168
2168
2169 @command('debugdag',
2169 @command('debugdag',
2170 [('t', 'tags', None, _('use tags as labels')),
2170 [('t', 'tags', None, _('use tags as labels')),
2171 ('b', 'branches', None, _('annotate with branch names')),
2171 ('b', 'branches', None, _('annotate with branch names')),
2172 ('', 'dots', None, _('use dots for runs')),
2172 ('', 'dots', None, _('use dots for runs')),
2173 ('s', 'spaces', None, _('separate elements by spaces'))],
2173 ('s', 'spaces', None, _('separate elements by spaces'))],
2174 _('[OPTION]... [FILE [REV]...]'),
2174 _('[OPTION]... [FILE [REV]...]'),
2175 optionalrepo=True)
2175 optionalrepo=True)
2176 def debugdag(ui, repo, file_=None, *revs, **opts):
2176 def debugdag(ui, repo, file_=None, *revs, **opts):
2177 """format the changelog or an index DAG as a concise textual description
2177 """format the changelog or an index DAG as a concise textual description
2178
2178
2179 If you pass a revlog index, the revlog's DAG is emitted. If you list
2179 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.
2180 revision numbers, they get labeled in the output as rN.
2181
2181
2182 Otherwise, the changelog DAG of the current repo is emitted.
2182 Otherwise, the changelog DAG of the current repo is emitted.
2183 """
2183 """
2184 spaces = opts.get('spaces')
2184 spaces = opts.get('spaces')
2185 dots = opts.get('dots')
2185 dots = opts.get('dots')
2186 if file_:
2186 if file_:
2187 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2187 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2188 revs = set((int(r) for r in revs))
2188 revs = set((int(r) for r in revs))
2189 def events():
2189 def events():
2190 for r in rlog:
2190 for r in rlog:
2191 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2191 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2192 if p != -1))
2192 if p != -1))
2193 if r in revs:
2193 if r in revs:
2194 yield 'l', (r, "r%i" % r)
2194 yield 'l', (r, "r%i" % r)
2195 elif repo:
2195 elif repo:
2196 cl = repo.changelog
2196 cl = repo.changelog
2197 tags = opts.get('tags')
2197 tags = opts.get('tags')
2198 branches = opts.get('branches')
2198 branches = opts.get('branches')
2199 if tags:
2199 if tags:
2200 labels = {}
2200 labels = {}
2201 for l, n in repo.tags().items():
2201 for l, n in repo.tags().items():
2202 labels.setdefault(cl.rev(n), []).append(l)
2202 labels.setdefault(cl.rev(n), []).append(l)
2203 def events():
2203 def events():
2204 b = "default"
2204 b = "default"
2205 for r in cl:
2205 for r in cl:
2206 if branches:
2206 if branches:
2207 newb = cl.read(cl.node(r))[5]['branch']
2207 newb = cl.read(cl.node(r))[5]['branch']
2208 if newb != b:
2208 if newb != b:
2209 yield 'a', newb
2209 yield 'a', newb
2210 b = newb
2210 b = newb
2211 yield 'n', (r, list(p for p in cl.parentrevs(r)
2211 yield 'n', (r, list(p for p in cl.parentrevs(r)
2212 if p != -1))
2212 if p != -1))
2213 if tags:
2213 if tags:
2214 ls = labels.get(r)
2214 ls = labels.get(r)
2215 if ls:
2215 if ls:
2216 for l in ls:
2216 for l in ls:
2217 yield 'l', (r, l)
2217 yield 'l', (r, l)
2218 else:
2218 else:
2219 raise error.Abort(_('need repo for changelog dag'))
2219 raise error.Abort(_('need repo for changelog dag'))
2220
2220
2221 for line in dagparser.dagtextlines(events(),
2221 for line in dagparser.dagtextlines(events(),
2222 addspaces=spaces,
2222 addspaces=spaces,
2223 wraplabels=True,
2223 wraplabels=True,
2224 wrapannotations=True,
2224 wrapannotations=True,
2225 wrapnonlinear=dots,
2225 wrapnonlinear=dots,
2226 usedots=dots,
2226 usedots=dots,
2227 maxlinewidth=70):
2227 maxlinewidth=70):
2228 ui.write(line)
2228 ui.write(line)
2229 ui.write("\n")
2229 ui.write("\n")
2230
2230
2231 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2231 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2232 def debugdata(ui, repo, file_, rev=None, **opts):
2232 def debugdata(ui, repo, file_, rev=None, **opts):
2233 """dump the contents of a data file revision"""
2233 """dump the contents of a data file revision"""
2234 if opts.get('changelog') or opts.get('manifest'):
2234 if opts.get('changelog') or opts.get('manifest'):
2235 file_, rev = None, file_
2235 file_, rev = None, file_
2236 elif rev is None:
2236 elif rev is None:
2237 raise error.CommandError('debugdata', _('invalid arguments'))
2237 raise error.CommandError('debugdata', _('invalid arguments'))
2238 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2238 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2239 try:
2239 try:
2240 ui.write(r.revision(r.lookup(rev)))
2240 ui.write(r.revision(r.lookup(rev)))
2241 except KeyError:
2241 except KeyError:
2242 raise error.Abort(_('invalid revision identifier %s') % rev)
2242 raise error.Abort(_('invalid revision identifier %s') % rev)
2243
2243
2244 @command('debugdate',
2244 @command('debugdate',
2245 [('e', 'extended', None, _('try extended date formats'))],
2245 [('e', 'extended', None, _('try extended date formats'))],
2246 _('[-e] DATE [RANGE]'),
2246 _('[-e] DATE [RANGE]'),
2247 norepo=True, optionalrepo=True)
2247 norepo=True, optionalrepo=True)
2248 def debugdate(ui, date, range=None, **opts):
2248 def debugdate(ui, date, range=None, **opts):
2249 """parse and display a date"""
2249 """parse and display a date"""
2250 if opts["extended"]:
2250 if opts["extended"]:
2251 d = util.parsedate(date, util.extendeddateformats)
2251 d = util.parsedate(date, util.extendeddateformats)
2252 else:
2252 else:
2253 d = util.parsedate(date)
2253 d = util.parsedate(date)
2254 ui.write(("internal: %s %s\n") % d)
2254 ui.write(("internal: %s %s\n") % d)
2255 ui.write(("standard: %s\n") % util.datestr(d))
2255 ui.write(("standard: %s\n") % util.datestr(d))
2256 if range:
2256 if range:
2257 m = util.matchdate(range)
2257 m = util.matchdate(range)
2258 ui.write(("match: %s\n") % m(d[0]))
2258 ui.write(("match: %s\n") % m(d[0]))
2259
2259
2260 @command('debugdiscovery',
2260 @command('debugdiscovery',
2261 [('', 'old', None, _('use old-style discovery')),
2261 [('', 'old', None, _('use old-style discovery')),
2262 ('', 'nonheads', None,
2262 ('', 'nonheads', None,
2263 _('use old-style discovery with non-heads included')),
2263 _('use old-style discovery with non-heads included')),
2264 ] + remoteopts,
2264 ] + remoteopts,
2265 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2265 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2266 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2266 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2267 """runs the changeset discovery protocol in isolation"""
2267 """runs the changeset discovery protocol in isolation"""
2268 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2268 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2269 opts.get('branch'))
2269 opts.get('branch'))
2270 remote = hg.peer(repo, opts, remoteurl)
2270 remote = hg.peer(repo, opts, remoteurl)
2271 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2271 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2272
2272
2273 # make sure tests are repeatable
2273 # make sure tests are repeatable
2274 random.seed(12323)
2274 random.seed(12323)
2275
2275
2276 def doit(localheads, remoteheads, remote=remote):
2276 def doit(localheads, remoteheads, remote=remote):
2277 if opts.get('old'):
2277 if opts.get('old'):
2278 if localheads:
2278 if localheads:
2279 raise error.Abort('cannot use localheads with old style '
2279 raise error.Abort('cannot use localheads with old style '
2280 'discovery')
2280 'discovery')
2281 if not util.safehasattr(remote, 'branches'):
2281 if not util.safehasattr(remote, 'branches'):
2282 # enable in-client legacy support
2282 # enable in-client legacy support
2283 remote = localrepo.locallegacypeer(remote.local())
2283 remote = localrepo.locallegacypeer(remote.local())
2284 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2284 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2285 force=True)
2285 force=True)
2286 common = set(common)
2286 common = set(common)
2287 if not opts.get('nonheads'):
2287 if not opts.get('nonheads'):
2288 ui.write(("unpruned common: %s\n") %
2288 ui.write(("unpruned common: %s\n") %
2289 " ".join(sorted(short(n) for n in common)))
2289 " ".join(sorted(short(n) for n in common)))
2290 dag = dagutil.revlogdag(repo.changelog)
2290 dag = dagutil.revlogdag(repo.changelog)
2291 all = dag.ancestorset(dag.internalizeall(common))
2291 all = dag.ancestorset(dag.internalizeall(common))
2292 common = dag.externalizeall(dag.headsetofconnecteds(all))
2292 common = dag.externalizeall(dag.headsetofconnecteds(all))
2293 else:
2293 else:
2294 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2294 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2295 common = set(common)
2295 common = set(common)
2296 rheads = set(hds)
2296 rheads = set(hds)
2297 lheads = set(repo.heads())
2297 lheads = set(repo.heads())
2298 ui.write(("common heads: %s\n") %
2298 ui.write(("common heads: %s\n") %
2299 " ".join(sorted(short(n) for n in common)))
2299 " ".join(sorted(short(n) for n in common)))
2300 if lheads <= common:
2300 if lheads <= common:
2301 ui.write(("local is subset\n"))
2301 ui.write(("local is subset\n"))
2302 elif rheads <= common:
2302 elif rheads <= common:
2303 ui.write(("remote is subset\n"))
2303 ui.write(("remote is subset\n"))
2304
2304
2305 serverlogs = opts.get('serverlog')
2305 serverlogs = opts.get('serverlog')
2306 if serverlogs:
2306 if serverlogs:
2307 for filename in serverlogs:
2307 for filename in serverlogs:
2308 with open(filename, 'r') as logfile:
2308 with open(filename, 'r') as logfile:
2309 line = logfile.readline()
2309 line = logfile.readline()
2310 while line:
2310 while line:
2311 parts = line.strip().split(';')
2311 parts = line.strip().split(';')
2312 op = parts[1]
2312 op = parts[1]
2313 if op == 'cg':
2313 if op == 'cg':
2314 pass
2314 pass
2315 elif op == 'cgss':
2315 elif op == 'cgss':
2316 doit(parts[2].split(' '), parts[3].split(' '))
2316 doit(parts[2].split(' '), parts[3].split(' '))
2317 elif op == 'unb':
2317 elif op == 'unb':
2318 doit(parts[3].split(' '), parts[2].split(' '))
2318 doit(parts[3].split(' '), parts[2].split(' '))
2319 line = logfile.readline()
2319 line = logfile.readline()
2320 else:
2320 else:
2321 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2321 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2322 opts.get('remote_head'))
2322 opts.get('remote_head'))
2323 localrevs = opts.get('local_head')
2323 localrevs = opts.get('local_head')
2324 doit(localrevs, remoterevs)
2324 doit(localrevs, remoterevs)
2325
2325
2326 @command('debugextensions', formatteropts, [], norepo=True)
2326 @command('debugextensions', formatteropts, [], norepo=True)
2327 def debugextensions(ui, **opts):
2327 def debugextensions(ui, **opts):
2328 '''show information about active extensions'''
2328 '''show information about active extensions'''
2329 exts = extensions.extensions(ui)
2329 exts = extensions.extensions(ui)
2330 fm = ui.formatter('debugextensions', opts)
2330 fm = ui.formatter('debugextensions', opts)
2331 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2331 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2332 extsource = extmod.__file__
2332 extsource = extmod.__file__
2333 exttestedwith = getattr(extmod, 'testedwith', None)
2333 exttestedwith = getattr(extmod, 'testedwith', None)
2334 if exttestedwith is not None:
2334 if exttestedwith is not None:
2335 exttestedwith = exttestedwith.split()
2335 exttestedwith = exttestedwith.split()
2336 extbuglink = getattr(extmod, 'buglink', None)
2336 extbuglink = getattr(extmod, 'buglink', None)
2337
2337
2338 fm.startitem()
2338 fm.startitem()
2339
2339
2340 if ui.quiet or ui.verbose:
2340 if ui.quiet or ui.verbose:
2341 fm.write('name', '%s\n', extname)
2341 fm.write('name', '%s\n', extname)
2342 else:
2342 else:
2343 fm.write('name', '%s', extname)
2343 fm.write('name', '%s', extname)
2344 if not exttestedwith:
2344 if not exttestedwith:
2345 fm.plain(_(' (untested!)\n'))
2345 fm.plain(_(' (untested!)\n'))
2346 else:
2346 else:
2347 if exttestedwith == ['internal'] or \
2347 if exttestedwith == ['internal'] or \
2348 util.version() in exttestedwith:
2348 util.version() in exttestedwith:
2349 fm.plain('\n')
2349 fm.plain('\n')
2350 else:
2350 else:
2351 lasttestedversion = exttestedwith[-1]
2351 lasttestedversion = exttestedwith[-1]
2352 fm.plain(' (%s!)\n' % lasttestedversion)
2352 fm.plain(' (%s!)\n' % lasttestedversion)
2353
2353
2354 fm.condwrite(ui.verbose and extsource, 'source',
2354 fm.condwrite(ui.verbose and extsource, 'source',
2355 _(' location: %s\n'), extsource or "")
2355 _(' location: %s\n'), extsource or "")
2356
2356
2357 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2357 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2358 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2358 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2359
2359
2360 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2360 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2361 _(' bug reporting: %s\n'), extbuglink or "")
2361 _(' bug reporting: %s\n'), extbuglink or "")
2362
2362
2363 fm.end()
2363 fm.end()
2364
2364
2365 @command('debugfileset',
2365 @command('debugfileset',
2366 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2366 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2367 _('[-r REV] FILESPEC'))
2367 _('[-r REV] FILESPEC'))
2368 def debugfileset(ui, repo, expr, **opts):
2368 def debugfileset(ui, repo, expr, **opts):
2369 '''parse and apply a fileset specification'''
2369 '''parse and apply a fileset specification'''
2370 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2370 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2371 if ui.verbose:
2371 if ui.verbose:
2372 tree = fileset.parse(expr)
2372 tree = fileset.parse(expr)
2373 ui.note(fileset.prettyformat(tree), "\n")
2373 ui.note(fileset.prettyformat(tree), "\n")
2374
2374
2375 for f in ctx.getfileset(expr):
2375 for f in ctx.getfileset(expr):
2376 ui.write("%s\n" % f)
2376 ui.write("%s\n" % f)
2377
2377
2378 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2378 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2379 def debugfsinfo(ui, path="."):
2379 def debugfsinfo(ui, path="."):
2380 """show information detected about current filesystem"""
2380 """show information detected about current filesystem"""
2381 util.writefile('.debugfsinfo', '')
2381 util.writefile('.debugfsinfo', '')
2382 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2382 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'))
2383 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'))
2384 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2385 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2385 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2386 and 'yes' or 'no'))
2386 and 'yes' or 'no'))
2387 os.unlink('.debugfsinfo')
2387 os.unlink('.debugfsinfo')
2388
2388
2389 @command('debuggetbundle',
2389 @command('debuggetbundle',
2390 [('H', 'head', [], _('id of head node'), _('ID')),
2390 [('H', 'head', [], _('id of head node'), _('ID')),
2391 ('C', 'common', [], _('id of common node'), _('ID')),
2391 ('C', 'common', [], _('id of common node'), _('ID')),
2392 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2392 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2393 _('REPO FILE [-H|-C ID]...'),
2393 _('REPO FILE [-H|-C ID]...'),
2394 norepo=True)
2394 norepo=True)
2395 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2395 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2396 """retrieves a bundle from a repo
2396 """retrieves a bundle from a repo
2397
2397
2398 Every ID must be a full-length hex node id string. Saves the bundle to the
2398 Every ID must be a full-length hex node id string. Saves the bundle to the
2399 given file.
2399 given file.
2400 """
2400 """
2401 repo = hg.peer(ui, opts, repopath)
2401 repo = hg.peer(ui, opts, repopath)
2402 if not repo.capable('getbundle'):
2402 if not repo.capable('getbundle'):
2403 raise error.Abort("getbundle() not supported by target repository")
2403 raise error.Abort("getbundle() not supported by target repository")
2404 args = {}
2404 args = {}
2405 if common:
2405 if common:
2406 args['common'] = [bin(s) for s in common]
2406 args['common'] = [bin(s) for s in common]
2407 if head:
2407 if head:
2408 args['heads'] = [bin(s) for s in head]
2408 args['heads'] = [bin(s) for s in head]
2409 # TODO: get desired bundlecaps from command line.
2409 # TODO: get desired bundlecaps from command line.
2410 args['bundlecaps'] = None
2410 args['bundlecaps'] = None
2411 bundle = repo.getbundle('debug', **args)
2411 bundle = repo.getbundle('debug', **args)
2412
2412
2413 bundletype = opts.get('type', 'bzip2').lower()
2413 bundletype = opts.get('type', 'bzip2').lower()
2414 btypes = {'none': 'HG10UN',
2414 btypes = {'none': 'HG10UN',
2415 'bzip2': 'HG10BZ',
2415 'bzip2': 'HG10BZ',
2416 'gzip': 'HG10GZ',
2416 'gzip': 'HG10GZ',
2417 'bundle2': 'HG20'}
2417 'bundle2': 'HG20'}
2418 bundletype = btypes.get(bundletype)
2418 bundletype = btypes.get(bundletype)
2419 if bundletype not in changegroup.bundletypes:
2419 if bundletype not in changegroup.bundletypes:
2420 raise error.Abort(_('unknown bundle type specified with --type'))
2420 raise error.Abort(_('unknown bundle type specified with --type'))
2421 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2421 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2422
2422
2423 @command('debugignore', [], '[FILE]')
2423 @command('debugignore', [], '[FILE]')
2424 def debugignore(ui, repo, *files, **opts):
2424 def debugignore(ui, repo, *files, **opts):
2425 """display the combined ignore pattern and information about ignored files
2425 """display the combined ignore pattern and information about ignored files
2426
2426
2427 With no argument display the combined ignore pattern.
2427 With no argument display the combined ignore pattern.
2428
2428
2429 Given space separated file names, shows if the given file is ignored and
2429 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.
2430 if so, show the ignore rule (file and line number) that matched it.
2431 """
2431 """
2432 ignore = repo.dirstate._ignore
2432 ignore = repo.dirstate._ignore
2433 if not files:
2433 if not files:
2434 # Show all the patterns
2434 # Show all the patterns
2435 includepat = getattr(ignore, 'includepat', None)
2435 includepat = getattr(ignore, 'includepat', None)
2436 if includepat is not None:
2436 if includepat is not None:
2437 ui.write("%s\n" % includepat)
2437 ui.write("%s\n" % includepat)
2438 else:
2438 else:
2439 raise error.Abort(_("no ignore patterns found"))
2439 raise error.Abort(_("no ignore patterns found"))
2440 else:
2440 else:
2441 for f in files:
2441 for f in files:
2442 ignored = None
2442 ignored = None
2443 ignoredata = None
2443 ignoredata = None
2444 if f != '.':
2444 if f != '.':
2445 if ignore(f):
2445 if ignore(f):
2446 ignored = f
2446 ignored = f
2447 ignoredata = repo.dirstate._ignorefileandline(f)
2447 ignoredata = repo.dirstate._ignorefileandline(f)
2448 else:
2448 else:
2449 for p in util.finddirs(f):
2449 for p in util.finddirs(f):
2450 if ignore(p):
2450 if ignore(p):
2451 ignored = p
2451 ignored = p
2452 ignoredata = repo.dirstate._ignorefileandline(p)
2452 ignoredata = repo.dirstate._ignorefileandline(p)
2453 break
2453 break
2454 if ignored:
2454 if ignored:
2455 if ignored == f:
2455 if ignored == f:
2456 ui.write("%s is ignored\n" % f)
2456 ui.write("%s is ignored\n" % f)
2457 else:
2457 else:
2458 ui.write("%s is ignored because of containing folder %s\n"
2458 ui.write("%s is ignored because of containing folder %s\n"
2459 % (f, ignored))
2459 % (f, ignored))
2460 ignorefile, lineno, line = ignoredata
2460 ignorefile, lineno, line = ignoredata
2461 ui.write("(ignore rule in %s, line %d: '%s')\n"
2461 ui.write("(ignore rule in %s, line %d: '%s')\n"
2462 % (ignorefile, lineno, line))
2462 % (ignorefile, lineno, line))
2463 else:
2463 else:
2464 ui.write("%s is not ignored\n" % f)
2464 ui.write("%s is not ignored\n" % f)
2465
2465
2466 @command('debugindex', debugrevlogopts +
2466 @command('debugindex', debugrevlogopts +
2467 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2467 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2468 _('[-f FORMAT] -c|-m|FILE'),
2468 _('[-f FORMAT] -c|-m|FILE'),
2469 optionalrepo=True)
2469 optionalrepo=True)
2470 def debugindex(ui, repo, file_=None, **opts):
2470 def debugindex(ui, repo, file_=None, **opts):
2471 """dump the contents of an index file"""
2471 """dump the contents of an index file"""
2472 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2472 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2473 format = opts.get('format', 0)
2473 format = opts.get('format', 0)
2474 if format not in (0, 1):
2474 if format not in (0, 1):
2475 raise error.Abort(_("unknown format %d") % format)
2475 raise error.Abort(_("unknown format %d") % format)
2476
2476
2477 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2477 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2478 if generaldelta:
2478 if generaldelta:
2479 basehdr = ' delta'
2479 basehdr = ' delta'
2480 else:
2480 else:
2481 basehdr = ' base'
2481 basehdr = ' base'
2482
2482
2483 if ui.debugflag:
2483 if ui.debugflag:
2484 shortfn = hex
2484 shortfn = hex
2485 else:
2485 else:
2486 shortfn = short
2486 shortfn = short
2487
2487
2488 # There might not be anything in r, so have a sane default
2488 # There might not be anything in r, so have a sane default
2489 idlen = 12
2489 idlen = 12
2490 for i in r:
2490 for i in r:
2491 idlen = len(shortfn(r.node(i)))
2491 idlen = len(shortfn(r.node(i)))
2492 break
2492 break
2493
2493
2494 if format == 0:
2494 if format == 0:
2495 ui.write(" rev offset length " + basehdr + " linkrev"
2495 ui.write(" rev offset length " + basehdr + " linkrev"
2496 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2496 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2497 elif format == 1:
2497 elif format == 1:
2498 ui.write(" rev flag offset length"
2498 ui.write(" rev flag offset length"
2499 " size " + basehdr + " link p1 p2"
2499 " size " + basehdr + " link p1 p2"
2500 " %s\n" % "nodeid".rjust(idlen))
2500 " %s\n" % "nodeid".rjust(idlen))
2501
2501
2502 for i in r:
2502 for i in r:
2503 node = r.node(i)
2503 node = r.node(i)
2504 if generaldelta:
2504 if generaldelta:
2505 base = r.deltaparent(i)
2505 base = r.deltaparent(i)
2506 else:
2506 else:
2507 base = r.chainbase(i)
2507 base = r.chainbase(i)
2508 if format == 0:
2508 if format == 0:
2509 try:
2509 try:
2510 pp = r.parents(node)
2510 pp = r.parents(node)
2511 except Exception:
2511 except Exception:
2512 pp = [nullid, nullid]
2512 pp = [nullid, nullid]
2513 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2513 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2514 i, r.start(i), r.length(i), base, r.linkrev(i),
2514 i, r.start(i), r.length(i), base, r.linkrev(i),
2515 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2515 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2516 elif format == 1:
2516 elif format == 1:
2517 pr = r.parentrevs(i)
2517 pr = r.parentrevs(i)
2518 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2518 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),
2519 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2520 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2520 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2521
2521
2522 @command('debugindexdot', debugrevlogopts,
2522 @command('debugindexdot', debugrevlogopts,
2523 _('-c|-m|FILE'), optionalrepo=True)
2523 _('-c|-m|FILE'), optionalrepo=True)
2524 def debugindexdot(ui, repo, file_=None, **opts):
2524 def debugindexdot(ui, repo, file_=None, **opts):
2525 """dump an index DAG as a graphviz dot file"""
2525 """dump an index DAG as a graphviz dot file"""
2526 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2526 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2527 ui.write(("digraph G {\n"))
2527 ui.write(("digraph G {\n"))
2528 for i in r:
2528 for i in r:
2529 node = r.node(i)
2529 node = r.node(i)
2530 pp = r.parents(node)
2530 pp = r.parents(node)
2531 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2531 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2532 if pp[1] != nullid:
2532 if pp[1] != nullid:
2533 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2533 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2534 ui.write("}\n")
2534 ui.write("}\n")
2535
2535
2536 @command('debugdeltachain',
2536 @command('debugdeltachain',
2537 debugrevlogopts + formatteropts,
2537 debugrevlogopts + formatteropts,
2538 _('-c|-m|FILE'),
2538 _('-c|-m|FILE'),
2539 optionalrepo=True)
2539 optionalrepo=True)
2540 def debugdeltachain(ui, repo, file_=None, **opts):
2540 def debugdeltachain(ui, repo, file_=None, **opts):
2541 """dump information about delta chains in a revlog
2541 """dump information about delta chains in a revlog
2542
2542
2543 Output can be templatized. Available template keywords are:
2543 Output can be templatized. Available template keywords are:
2544
2544
2545 rev revision number
2545 rev revision number
2546 chainid delta chain identifier (numbered by unique base)
2546 chainid delta chain identifier (numbered by unique base)
2547 chainlen delta chain length to this revision
2547 chainlen delta chain length to this revision
2548 prevrev previous revision in delta chain
2548 prevrev previous revision in delta chain
2549 deltatype role of delta / how it was computed
2549 deltatype role of delta / how it was computed
2550 compsize compressed size of revision
2550 compsize compressed size of revision
2551 uncompsize uncompressed size of revision
2551 uncompsize uncompressed size of revision
2552 chainsize total size of compressed revisions in chain
2552 chainsize total size of compressed revisions in chain
2553 chainratio total chain size divided by uncompressed revision size
2553 chainratio total chain size divided by uncompressed revision size
2554 (new delta chains typically start at ratio 2.00)
2554 (new delta chains typically start at ratio 2.00)
2555 lindist linear distance from base revision in delta chain to end
2555 lindist linear distance from base revision in delta chain to end
2556 of this revision
2556 of this revision
2557 extradist total size of revisions not part of this delta chain from
2557 extradist total size of revisions not part of this delta chain from
2558 base of delta chain to end of this revision; a measurement
2558 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
2559 of how much extra data we need to read/seek across to read
2560 the delta chain for this revision
2560 the delta chain for this revision
2561 extraratio extradist divided by chainsize; another representation of
2561 extraratio extradist divided by chainsize; another representation of
2562 how much unrelated data is needed to load this delta chain
2562 how much unrelated data is needed to load this delta chain
2563 """
2563 """
2564 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2564 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2565 index = r.index
2565 index = r.index
2566 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2566 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2567
2567
2568 def revinfo(rev):
2568 def revinfo(rev):
2569 e = index[rev]
2569 e = index[rev]
2570 compsize = e[1]
2570 compsize = e[1]
2571 uncompsize = e[2]
2571 uncompsize = e[2]
2572 chainsize = 0
2572 chainsize = 0
2573
2573
2574 if generaldelta:
2574 if generaldelta:
2575 if e[3] == e[5]:
2575 if e[3] == e[5]:
2576 deltatype = 'p1'
2576 deltatype = 'p1'
2577 elif e[3] == e[6]:
2577 elif e[3] == e[6]:
2578 deltatype = 'p2'
2578 deltatype = 'p2'
2579 elif e[3] == rev - 1:
2579 elif e[3] == rev - 1:
2580 deltatype = 'prev'
2580 deltatype = 'prev'
2581 elif e[3] == rev:
2581 elif e[3] == rev:
2582 deltatype = 'base'
2582 deltatype = 'base'
2583 else:
2583 else:
2584 deltatype = 'other'
2584 deltatype = 'other'
2585 else:
2585 else:
2586 if e[3] == rev:
2586 if e[3] == rev:
2587 deltatype = 'base'
2587 deltatype = 'base'
2588 else:
2588 else:
2589 deltatype = 'prev'
2589 deltatype = 'prev'
2590
2590
2591 chain = r._deltachain(rev)[0]
2591 chain = r._deltachain(rev)[0]
2592 for iterrev in chain:
2592 for iterrev in chain:
2593 e = index[iterrev]
2593 e = index[iterrev]
2594 chainsize += e[1]
2594 chainsize += e[1]
2595
2595
2596 return compsize, uncompsize, deltatype, chain, chainsize
2596 return compsize, uncompsize, deltatype, chain, chainsize
2597
2597
2598 fm = ui.formatter('debugdeltachain', opts)
2598 fm = ui.formatter('debugdeltachain', opts)
2599
2599
2600 fm.plain(' rev chain# chainlen prev delta '
2600 fm.plain(' rev chain# chainlen prev delta '
2601 'size rawsize chainsize ratio lindist extradist '
2601 'size rawsize chainsize ratio lindist extradist '
2602 'extraratio\n')
2602 'extraratio\n')
2603
2603
2604 chainbases = {}
2604 chainbases = {}
2605 for rev in r:
2605 for rev in r:
2606 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2606 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2607 chainbase = chain[0]
2607 chainbase = chain[0]
2608 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2608 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2609 basestart = r.start(chainbase)
2609 basestart = r.start(chainbase)
2610 revstart = r.start(rev)
2610 revstart = r.start(rev)
2611 lineardist = revstart + comp - basestart
2611 lineardist = revstart + comp - basestart
2612 extradist = lineardist - chainsize
2612 extradist = lineardist - chainsize
2613 try:
2613 try:
2614 prevrev = chain[-2]
2614 prevrev = chain[-2]
2615 except IndexError:
2615 except IndexError:
2616 prevrev = -1
2616 prevrev = -1
2617
2617
2618 chainratio = float(chainsize) / float(uncomp)
2618 chainratio = float(chainsize) / float(uncomp)
2619 extraratio = float(extradist) / float(chainsize)
2619 extraratio = float(extradist) / float(chainsize)
2620
2620
2621 fm.startitem()
2621 fm.startitem()
2622 fm.write('rev chainid chainlen prevrev deltatype compsize '
2622 fm.write('rev chainid chainlen prevrev deltatype compsize '
2623 'uncompsize chainsize chainratio lindist extradist '
2623 'uncompsize chainsize chainratio lindist extradist '
2624 'extraratio',
2624 'extraratio',
2625 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2625 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2626 rev, chainid, len(chain), prevrev, deltatype, comp,
2626 rev, chainid, len(chain), prevrev, deltatype, comp,
2627 uncomp, chainsize, chainratio, lineardist, extradist,
2627 uncomp, chainsize, chainratio, lineardist, extradist,
2628 extraratio,
2628 extraratio,
2629 rev=rev, chainid=chainid, chainlen=len(chain),
2629 rev=rev, chainid=chainid, chainlen=len(chain),
2630 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2630 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2631 uncompsize=uncomp, chainsize=chainsize,
2631 uncompsize=uncomp, chainsize=chainsize,
2632 chainratio=chainratio, lindist=lineardist,
2632 chainratio=chainratio, lindist=lineardist,
2633 extradist=extradist, extraratio=extraratio)
2633 extradist=extradist, extraratio=extraratio)
2634
2634
2635 fm.end()
2635 fm.end()
2636
2636
2637 @command('debuginstall', [], '', norepo=True)
2637 @command('debuginstall', [], '', norepo=True)
2638 def debuginstall(ui):
2638 def debuginstall(ui):
2639 '''test Mercurial installation
2639 '''test Mercurial installation
2640
2640
2641 Returns 0 on success.
2641 Returns 0 on success.
2642 '''
2642 '''
2643
2643
2644 def writetemp(contents):
2644 def writetemp(contents):
2645 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2645 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2646 f = os.fdopen(fd, "wb")
2646 f = os.fdopen(fd, "wb")
2647 f.write(contents)
2647 f.write(contents)
2648 f.close()
2648 f.close()
2649 return name
2649 return name
2650
2650
2651 problems = 0
2651 problems = 0
2652
2652
2653 # encoding
2653 # encoding
2654 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2654 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2655 try:
2655 try:
2656 encoding.fromlocal("test")
2656 encoding.fromlocal("test")
2657 except error.Abort as inst:
2657 except error.Abort as inst:
2658 ui.write(" %s\n" % inst)
2658 ui.write(" %s\n" % inst)
2659 ui.write(_(" (check that your locale is properly set)\n"))
2659 ui.write(_(" (check that your locale is properly set)\n"))
2660 problems += 1
2660 problems += 1
2661
2661
2662 # Python
2662 # Python
2663 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2663 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2664 ui.status(_("checking Python version (%s)\n")
2664 ui.status(_("checking Python version (%s)\n")
2665 % ("%s.%s.%s" % sys.version_info[:3]))
2665 % ("%s.%s.%s" % sys.version_info[:3]))
2666 ui.status(_("checking Python lib (%s)...\n")
2666 ui.status(_("checking Python lib (%s)...\n")
2667 % os.path.dirname(os.__file__))
2667 % os.path.dirname(os.__file__))
2668
2668
2669 # compiled modules
2669 # compiled modules
2670 ui.status(_("checking installed modules (%s)...\n")
2670 ui.status(_("checking installed modules (%s)...\n")
2671 % os.path.dirname(__file__))
2671 % os.path.dirname(__file__))
2672 try:
2672 try:
2673 import bdiff, mpatch, base85, osutil
2673 import bdiff, mpatch, base85, osutil
2674 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2674 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2675 except Exception as inst:
2675 except Exception as inst:
2676 ui.write(" %s\n" % inst)
2676 ui.write(" %s\n" % inst)
2677 ui.write(_(" One or more extensions could not be found"))
2677 ui.write(_(" One or more extensions could not be found"))
2678 ui.write(_(" (check that you compiled the extensions)\n"))
2678 ui.write(_(" (check that you compiled the extensions)\n"))
2679 problems += 1
2679 problems += 1
2680
2680
2681 # templates
2681 # templates
2682 import templater
2682 import templater
2683 p = templater.templatepaths()
2683 p = templater.templatepaths()
2684 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2684 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2685 if p:
2685 if p:
2686 m = templater.templatepath("map-cmdline.default")
2686 m = templater.templatepath("map-cmdline.default")
2687 if m:
2687 if m:
2688 # template found, check if it is working
2688 # template found, check if it is working
2689 try:
2689 try:
2690 templater.templater(m)
2690 templater.templater(m)
2691 except Exception as inst:
2691 except Exception as inst:
2692 ui.write(" %s\n" % inst)
2692 ui.write(" %s\n" % inst)
2693 p = None
2693 p = None
2694 else:
2694 else:
2695 ui.write(_(" template 'default' not found\n"))
2695 ui.write(_(" template 'default' not found\n"))
2696 p = None
2696 p = None
2697 else:
2697 else:
2698 ui.write(_(" no template directories found\n"))
2698 ui.write(_(" no template directories found\n"))
2699 if not p:
2699 if not p:
2700 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2700 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2701 problems += 1
2701 problems += 1
2702
2702
2703 # editor
2703 # editor
2704 ui.status(_("checking commit editor...\n"))
2704 ui.status(_("checking commit editor...\n"))
2705 editor = ui.geteditor()
2705 editor = ui.geteditor()
2706 editor = util.expandpath(editor)
2706 editor = util.expandpath(editor)
2707 cmdpath = util.findexe(shlex.split(editor)[0])
2707 cmdpath = util.findexe(shlex.split(editor)[0])
2708 if not cmdpath:
2708 if not cmdpath:
2709 if editor == 'vi':
2709 if editor == 'vi':
2710 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2710 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2711 ui.write(_(" (specify a commit editor in your configuration"
2711 ui.write(_(" (specify a commit editor in your configuration"
2712 " file)\n"))
2712 " file)\n"))
2713 else:
2713 else:
2714 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2714 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2715 ui.write(_(" (specify a commit editor in your configuration"
2715 ui.write(_(" (specify a commit editor in your configuration"
2716 " file)\n"))
2716 " file)\n"))
2717 problems += 1
2717 problems += 1
2718
2718
2719 # check username
2719 # check username
2720 ui.status(_("checking username...\n"))
2720 ui.status(_("checking username...\n"))
2721 try:
2721 try:
2722 ui.username()
2722 ui.username()
2723 except error.Abort as e:
2723 except error.Abort as e:
2724 ui.write(" %s\n" % e)
2724 ui.write(" %s\n" % e)
2725 ui.write(_(" (specify a username in your configuration file)\n"))
2725 ui.write(_(" (specify a username in your configuration file)\n"))
2726 problems += 1
2726 problems += 1
2727
2727
2728 if not problems:
2728 if not problems:
2729 ui.status(_("no problems detected\n"))
2729 ui.status(_("no problems detected\n"))
2730 else:
2730 else:
2731 ui.write(_("%s problems detected,"
2731 ui.write(_("%s problems detected,"
2732 " please check your install!\n") % problems)
2732 " please check your install!\n") % problems)
2733
2733
2734 return problems
2734 return problems
2735
2735
2736 @command('debugknown', [], _('REPO ID...'), norepo=True)
2736 @command('debugknown', [], _('REPO ID...'), norepo=True)
2737 def debugknown(ui, repopath, *ids, **opts):
2737 def debugknown(ui, repopath, *ids, **opts):
2738 """test whether node ids are known to a repo
2738 """test whether node ids are known to a repo
2739
2739
2740 Every ID must be a full-length hex node id string. Returns a list of 0s
2740 Every ID must be a full-length hex node id string. Returns a list of 0s
2741 and 1s indicating unknown/known.
2741 and 1s indicating unknown/known.
2742 """
2742 """
2743 repo = hg.peer(ui, opts, repopath)
2743 repo = hg.peer(ui, opts, repopath)
2744 if not repo.capable('known'):
2744 if not repo.capable('known'):
2745 raise error.Abort("known() not supported by target repository")
2745 raise error.Abort("known() not supported by target repository")
2746 flags = repo.known([bin(s) for s in ids])
2746 flags = repo.known([bin(s) for s in ids])
2747 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2747 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2748
2748
2749 @command('debuglabelcomplete', [], _('LABEL...'))
2749 @command('debuglabelcomplete', [], _('LABEL...'))
2750 def debuglabelcomplete(ui, repo, *args):
2750 def debuglabelcomplete(ui, repo, *args):
2751 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2751 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2752 debugnamecomplete(ui, repo, *args)
2752 debugnamecomplete(ui, repo, *args)
2753
2753
2754 @command('debugmergestate', [], '')
2754 @command('debugmergestate', [], '')
2755 def debugmergestate(ui, repo, *args):
2755 def debugmergestate(ui, repo, *args):
2756 """print merge state
2756 """print merge state
2757
2757
2758 Use --verbose to print out information about whether v1 or v2 merge state
2758 Use --verbose to print out information about whether v1 or v2 merge state
2759 was chosen."""
2759 was chosen."""
2760 def _hashornull(h):
2760 def _hashornull(h):
2761 if h == nullhex:
2761 if h == nullhex:
2762 return 'null'
2762 return 'null'
2763 else:
2763 else:
2764 return h
2764 return h
2765
2765
2766 def printrecords(version):
2766 def printrecords(version):
2767 ui.write(('* version %s records\n') % version)
2767 ui.write(('* version %s records\n') % version)
2768 if version == 1:
2768 if version == 1:
2769 records = v1records
2769 records = v1records
2770 else:
2770 else:
2771 records = v2records
2771 records = v2records
2772
2772
2773 for rtype, record in records:
2773 for rtype, record in records:
2774 # pretty print some record types
2774 # pretty print some record types
2775 if rtype == 'L':
2775 if rtype == 'L':
2776 ui.write(('local: %s\n') % record)
2776 ui.write(('local: %s\n') % record)
2777 elif rtype == 'O':
2777 elif rtype == 'O':
2778 ui.write(('other: %s\n') % record)
2778 ui.write(('other: %s\n') % record)
2779 elif rtype == 'm':
2779 elif rtype == 'm':
2780 driver, mdstate = record.split('\0', 1)
2780 driver, mdstate = record.split('\0', 1)
2781 ui.write(('merge driver: %s (state "%s")\n')
2781 ui.write(('merge driver: %s (state "%s")\n')
2782 % (driver, mdstate))
2782 % (driver, mdstate))
2783 elif rtype in 'FDC':
2783 elif rtype in 'FDC':
2784 r = record.split('\0')
2784 r = record.split('\0')
2785 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2785 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2786 if version == 1:
2786 if version == 1:
2787 onode = 'not stored in v1 format'
2787 onode = 'not stored in v1 format'
2788 flags = r[7]
2788 flags = r[7]
2789 else:
2789 else:
2790 onode, flags = r[7:9]
2790 onode, flags = r[7:9]
2791 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2791 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2792 % (f, rtype, state, _hashornull(hash)))
2792 % (f, rtype, state, _hashornull(hash)))
2793 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2793 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2794 ui.write((' ancestor path: %s (node %s)\n')
2794 ui.write((' ancestor path: %s (node %s)\n')
2795 % (afile, _hashornull(anode)))
2795 % (afile, _hashornull(anode)))
2796 ui.write((' other path: %s (node %s)\n')
2796 ui.write((' other path: %s (node %s)\n')
2797 % (ofile, _hashornull(onode)))
2797 % (ofile, _hashornull(onode)))
2798 else:
2798 else:
2799 ui.write(('unrecognized entry: %s\t%s\n')
2799 ui.write(('unrecognized entry: %s\t%s\n')
2800 % (rtype, record.replace('\0', '\t')))
2800 % (rtype, record.replace('\0', '\t')))
2801
2801
2802 # Avoid mergestate.read() since it may raise an exception for unsupported
2802 # 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
2803 # merge state records. We shouldn't be doing this, but this is OK since this
2804 # command is pretty low-level.
2804 # command is pretty low-level.
2805 ms = mergemod.mergestate(repo)
2805 ms = mergemod.mergestate(repo)
2806
2806
2807 # sort so that reasonable information is on top
2807 # sort so that reasonable information is on top
2808 v1records = ms._readrecordsv1()
2808 v1records = ms._readrecordsv1()
2809 v2records = ms._readrecordsv2()
2809 v2records = ms._readrecordsv2()
2810 order = 'LOm'
2810 order = 'LOm'
2811 def key(r):
2811 def key(r):
2812 idx = order.find(r[0])
2812 idx = order.find(r[0])
2813 if idx == -1:
2813 if idx == -1:
2814 return (1, r[1])
2814 return (1, r[1])
2815 else:
2815 else:
2816 return (0, idx)
2816 return (0, idx)
2817 v1records.sort(key=key)
2817 v1records.sort(key=key)
2818 v2records.sort(key=key)
2818 v2records.sort(key=key)
2819
2819
2820 if not v1records and not v2records:
2820 if not v1records and not v2records:
2821 ui.write(('no merge state found\n'))
2821 ui.write(('no merge state found\n'))
2822 elif not v2records:
2822 elif not v2records:
2823 ui.note(('no version 2 merge state\n'))
2823 ui.note(('no version 2 merge state\n'))
2824 printrecords(1)
2824 printrecords(1)
2825 elif ms._v1v2match(v1records, v2records):
2825 elif ms._v1v2match(v1records, v2records):
2826 ui.note(('v1 and v2 states match: using v2\n'))
2826 ui.note(('v1 and v2 states match: using v2\n'))
2827 printrecords(2)
2827 printrecords(2)
2828 else:
2828 else:
2829 ui.note(('v1 and v2 states mismatch: using v1\n'))
2829 ui.note(('v1 and v2 states mismatch: using v1\n'))
2830 printrecords(1)
2830 printrecords(1)
2831 if ui.verbose:
2831 if ui.verbose:
2832 printrecords(2)
2832 printrecords(2)
2833
2833
2834 @command('debugnamecomplete', [], _('NAME...'))
2834 @command('debugnamecomplete', [], _('NAME...'))
2835 def debugnamecomplete(ui, repo, *args):
2835 def debugnamecomplete(ui, repo, *args):
2836 '''complete "names" - tags, open branch names, bookmark names'''
2836 '''complete "names" - tags, open branch names, bookmark names'''
2837
2837
2838 names = set()
2838 names = set()
2839 # since we previously only listed open branches, we will handle that
2839 # since we previously only listed open branches, we will handle that
2840 # specially (after this for loop)
2840 # specially (after this for loop)
2841 for name, ns in repo.names.iteritems():
2841 for name, ns in repo.names.iteritems():
2842 if name != 'branches':
2842 if name != 'branches':
2843 names.update(ns.listnames(repo))
2843 names.update(ns.listnames(repo))
2844 names.update(tag for (tag, heads, tip, closed)
2844 names.update(tag for (tag, heads, tip, closed)
2845 in repo.branchmap().iterbranches() if not closed)
2845 in repo.branchmap().iterbranches() if not closed)
2846 completions = set()
2846 completions = set()
2847 if not args:
2847 if not args:
2848 args = ['']
2848 args = ['']
2849 for a in args:
2849 for a in args:
2850 completions.update(n for n in names if n.startswith(a))
2850 completions.update(n for n in names if n.startswith(a))
2851 ui.write('\n'.join(sorted(completions)))
2851 ui.write('\n'.join(sorted(completions)))
2852 ui.write('\n')
2852 ui.write('\n')
2853
2853
2854 @command('debuglocks',
2854 @command('debuglocks',
2855 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2855 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2856 ('W', 'force-wlock', None,
2856 ('W', 'force-wlock', None,
2857 _('free the working state lock (DANGEROUS)'))],
2857 _('free the working state lock (DANGEROUS)'))],
2858 _('[OPTION]...'))
2858 _('[OPTION]...'))
2859 def debuglocks(ui, repo, **opts):
2859 def debuglocks(ui, repo, **opts):
2860 """show or modify state of locks
2860 """show or modify state of locks
2861
2861
2862 By default, this command will show which locks are held. This
2862 By default, this command will show which locks are held. This
2863 includes the user and process holding the lock, the amount of time
2863 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
2864 the lock has been held, and the machine name where the process is
2865 running if it's not local.
2865 running if it's not local.
2866
2866
2867 Locks protect the integrity of Mercurial's data, so should be
2867 Locks protect the integrity of Mercurial's data, so should be
2868 treated with care. System crashes or other interruptions may cause
2868 treated with care. System crashes or other interruptions may cause
2869 locks to not be properly released, though Mercurial will usually
2869 locks to not be properly released, though Mercurial will usually
2870 detect and remove such stale locks automatically.
2870 detect and remove such stale locks automatically.
2871
2871
2872 However, detecting stale locks may not always be possible (for
2872 However, detecting stale locks may not always be possible (for
2873 instance, on a shared filesystem). Removing locks may also be
2873 instance, on a shared filesystem). Removing locks may also be
2874 blocked by filesystem permissions.
2874 blocked by filesystem permissions.
2875
2875
2876 Returns 0 if no locks are held.
2876 Returns 0 if no locks are held.
2877
2877
2878 """
2878 """
2879
2879
2880 if opts.get('force_lock'):
2880 if opts.get('force_lock'):
2881 repo.svfs.unlink('lock')
2881 repo.svfs.unlink('lock')
2882 if opts.get('force_wlock'):
2882 if opts.get('force_wlock'):
2883 repo.vfs.unlink('wlock')
2883 repo.vfs.unlink('wlock')
2884 if opts.get('force_lock') or opts.get('force_lock'):
2884 if opts.get('force_lock') or opts.get('force_lock'):
2885 return 0
2885 return 0
2886
2886
2887 now = time.time()
2887 now = time.time()
2888 held = 0
2888 held = 0
2889
2889
2890 def report(vfs, name, method):
2890 def report(vfs, name, method):
2891 # this causes stale locks to get reaped for more accurate reporting
2891 # this causes stale locks to get reaped for more accurate reporting
2892 try:
2892 try:
2893 l = method(False)
2893 l = method(False)
2894 except error.LockHeld:
2894 except error.LockHeld:
2895 l = None
2895 l = None
2896
2896
2897 if l:
2897 if l:
2898 l.release()
2898 l.release()
2899 else:
2899 else:
2900 try:
2900 try:
2901 stat = vfs.lstat(name)
2901 stat = vfs.lstat(name)
2902 age = now - stat.st_mtime
2902 age = now - stat.st_mtime
2903 user = util.username(stat.st_uid)
2903 user = util.username(stat.st_uid)
2904 locker = vfs.readlock(name)
2904 locker = vfs.readlock(name)
2905 if ":" in locker:
2905 if ":" in locker:
2906 host, pid = locker.split(':')
2906 host, pid = locker.split(':')
2907 if host == socket.gethostname():
2907 if host == socket.gethostname():
2908 locker = 'user %s, process %s' % (user, pid)
2908 locker = 'user %s, process %s' % (user, pid)
2909 else:
2909 else:
2910 locker = 'user %s, process %s, host %s' \
2910 locker = 'user %s, process %s, host %s' \
2911 % (user, pid, host)
2911 % (user, pid, host)
2912 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2912 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2913 return 1
2913 return 1
2914 except OSError as e:
2914 except OSError as e:
2915 if e.errno != errno.ENOENT:
2915 if e.errno != errno.ENOENT:
2916 raise
2916 raise
2917
2917
2918 ui.write("%-6s free\n" % (name + ":"))
2918 ui.write("%-6s free\n" % (name + ":"))
2919 return 0
2919 return 0
2920
2920
2921 held += report(repo.svfs, "lock", repo.lock)
2921 held += report(repo.svfs, "lock", repo.lock)
2922 held += report(repo.vfs, "wlock", repo.wlock)
2922 held += report(repo.vfs, "wlock", repo.wlock)
2923
2923
2924 return held
2924 return held
2925
2925
2926 @command('debugobsolete',
2926 @command('debugobsolete',
2927 [('', 'flags', 0, _('markers flag')),
2927 [('', 'flags', 0, _('markers flag')),
2928 ('', 'record-parents', False,
2928 ('', 'record-parents', False,
2929 _('record parent information for the precursor')),
2929 _('record parent information for the precursor')),
2930 ('r', 'rev', [], _('display markers relevant to REV')),
2930 ('r', 'rev', [], _('display markers relevant to REV')),
2931 ] + commitopts2,
2931 ] + commitopts2,
2932 _('[OBSOLETED [REPLACEMENT ...]]'))
2932 _('[OBSOLETED [REPLACEMENT ...]]'))
2933 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2933 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2934 """create arbitrary obsolete marker
2934 """create arbitrary obsolete marker
2935
2935
2936 With no arguments, displays the list of obsolescence markers."""
2936 With no arguments, displays the list of obsolescence markers."""
2937
2937
2938 def parsenodeid(s):
2938 def parsenodeid(s):
2939 try:
2939 try:
2940 # We do not use revsingle/revrange functions here to accept
2940 # We do not use revsingle/revrange functions here to accept
2941 # arbitrary node identifiers, possibly not present in the
2941 # arbitrary node identifiers, possibly not present in the
2942 # local repository.
2942 # local repository.
2943 n = bin(s)
2943 n = bin(s)
2944 if len(n) != len(nullid):
2944 if len(n) != len(nullid):
2945 raise TypeError()
2945 raise TypeError()
2946 return n
2946 return n
2947 except TypeError:
2947 except TypeError:
2948 raise error.Abort('changeset references must be full hexadecimal '
2948 raise error.Abort('changeset references must be full hexadecimal '
2949 'node identifiers')
2949 'node identifiers')
2950
2950
2951 if precursor is not None:
2951 if precursor is not None:
2952 if opts['rev']:
2952 if opts['rev']:
2953 raise error.Abort('cannot select revision when creating marker')
2953 raise error.Abort('cannot select revision when creating marker')
2954 metadata = {}
2954 metadata = {}
2955 metadata['user'] = opts['user'] or ui.username()
2955 metadata['user'] = opts['user'] or ui.username()
2956 succs = tuple(parsenodeid(succ) for succ in successors)
2956 succs = tuple(parsenodeid(succ) for succ in successors)
2957 l = repo.lock()
2957 l = repo.lock()
2958 try:
2958 try:
2959 tr = repo.transaction('debugobsolete')
2959 tr = repo.transaction('debugobsolete')
2960 try:
2960 try:
2961 date = opts.get('date')
2961 date = opts.get('date')
2962 if date:
2962 if date:
2963 date = util.parsedate(date)
2963 date = util.parsedate(date)
2964 else:
2964 else:
2965 date = None
2965 date = None
2966 prec = parsenodeid(precursor)
2966 prec = parsenodeid(precursor)
2967 parents = None
2967 parents = None
2968 if opts['record_parents']:
2968 if opts['record_parents']:
2969 if prec not in repo.unfiltered():
2969 if prec not in repo.unfiltered():
2970 raise error.Abort('cannot used --record-parents on '
2970 raise error.Abort('cannot used --record-parents on '
2971 'unknown changesets')
2971 'unknown changesets')
2972 parents = repo.unfiltered()[prec].parents()
2972 parents = repo.unfiltered()[prec].parents()
2973 parents = tuple(p.node() for p in parents)
2973 parents = tuple(p.node() for p in parents)
2974 repo.obsstore.create(tr, prec, succs, opts['flags'],
2974 repo.obsstore.create(tr, prec, succs, opts['flags'],
2975 parents=parents, date=date,
2975 parents=parents, date=date,
2976 metadata=metadata)
2976 metadata=metadata)
2977 tr.close()
2977 tr.close()
2978 except ValueError as exc:
2978 except ValueError as exc:
2979 raise error.Abort(_('bad obsmarker input: %s') % exc)
2979 raise error.Abort(_('bad obsmarker input: %s') % exc)
2980 finally:
2980 finally:
2981 tr.release()
2981 tr.release()
2982 finally:
2982 finally:
2983 l.release()
2983 l.release()
2984 else:
2984 else:
2985 if opts['rev']:
2985 if opts['rev']:
2986 revs = scmutil.revrange(repo, opts['rev'])
2986 revs = scmutil.revrange(repo, opts['rev'])
2987 nodes = [repo[r].node() for r in revs]
2987 nodes = [repo[r].node() for r in revs]
2988 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2988 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2989 markers.sort(key=lambda x: x._data)
2989 markers.sort(key=lambda x: x._data)
2990 else:
2990 else:
2991 markers = obsolete.getmarkers(repo)
2991 markers = obsolete.getmarkers(repo)
2992
2992
2993 for m in markers:
2993 for m in markers:
2994 cmdutil.showmarker(ui, m)
2994 cmdutil.showmarker(ui, m)
2995
2995
2996 @command('debugpathcomplete',
2996 @command('debugpathcomplete',
2997 [('f', 'full', None, _('complete an entire path')),
2997 [('f', 'full', None, _('complete an entire path')),
2998 ('n', 'normal', None, _('show only normal files')),
2998 ('n', 'normal', None, _('show only normal files')),
2999 ('a', 'added', None, _('show only added files')),
2999 ('a', 'added', None, _('show only added files')),
3000 ('r', 'removed', None, _('show only removed files'))],
3000 ('r', 'removed', None, _('show only removed files'))],
3001 _('FILESPEC...'))
3001 _('FILESPEC...'))
3002 def debugpathcomplete(ui, repo, *specs, **opts):
3002 def debugpathcomplete(ui, repo, *specs, **opts):
3003 '''complete part or all of a tracked path
3003 '''complete part or all of a tracked path
3004
3004
3005 This command supports shells that offer path name completion. It
3005 This command supports shells that offer path name completion. It
3006 currently completes only files already known to the dirstate.
3006 currently completes only files already known to the dirstate.
3007
3007
3008 Completion extends only to the next path segment unless
3008 Completion extends only to the next path segment unless
3009 --full is specified, in which case entire paths are used.'''
3009 --full is specified, in which case entire paths are used.'''
3010
3010
3011 def complete(path, acceptable):
3011 def complete(path, acceptable):
3012 dirstate = repo.dirstate
3012 dirstate = repo.dirstate
3013 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3013 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3014 rootdir = repo.root + os.sep
3014 rootdir = repo.root + os.sep
3015 if spec != repo.root and not spec.startswith(rootdir):
3015 if spec != repo.root and not spec.startswith(rootdir):
3016 return [], []
3016 return [], []
3017 if os.path.isdir(spec):
3017 if os.path.isdir(spec):
3018 spec += '/'
3018 spec += '/'
3019 spec = spec[len(rootdir):]
3019 spec = spec[len(rootdir):]
3020 fixpaths = os.sep != '/'
3020 fixpaths = os.sep != '/'
3021 if fixpaths:
3021 if fixpaths:
3022 spec = spec.replace(os.sep, '/')
3022 spec = spec.replace(os.sep, '/')
3023 speclen = len(spec)
3023 speclen = len(spec)
3024 fullpaths = opts['full']
3024 fullpaths = opts['full']
3025 files, dirs = set(), set()
3025 files, dirs = set(), set()
3026 adddir, addfile = dirs.add, files.add
3026 adddir, addfile = dirs.add, files.add
3027 for f, st in dirstate.iteritems():
3027 for f, st in dirstate.iteritems():
3028 if f.startswith(spec) and st[0] in acceptable:
3028 if f.startswith(spec) and st[0] in acceptable:
3029 if fixpaths:
3029 if fixpaths:
3030 f = f.replace('/', os.sep)
3030 f = f.replace('/', os.sep)
3031 if fullpaths:
3031 if fullpaths:
3032 addfile(f)
3032 addfile(f)
3033 continue
3033 continue
3034 s = f.find(os.sep, speclen)
3034 s = f.find(os.sep, speclen)
3035 if s >= 0:
3035 if s >= 0:
3036 adddir(f[:s])
3036 adddir(f[:s])
3037 else:
3037 else:
3038 addfile(f)
3038 addfile(f)
3039 return files, dirs
3039 return files, dirs
3040
3040
3041 acceptable = ''
3041 acceptable = ''
3042 if opts['normal']:
3042 if opts['normal']:
3043 acceptable += 'nm'
3043 acceptable += 'nm'
3044 if opts['added']:
3044 if opts['added']:
3045 acceptable += 'a'
3045 acceptable += 'a'
3046 if opts['removed']:
3046 if opts['removed']:
3047 acceptable += 'r'
3047 acceptable += 'r'
3048 cwd = repo.getcwd()
3048 cwd = repo.getcwd()
3049 if not specs:
3049 if not specs:
3050 specs = ['.']
3050 specs = ['.']
3051
3051
3052 files, dirs = set(), set()
3052 files, dirs = set(), set()
3053 for spec in specs:
3053 for spec in specs:
3054 f, d = complete(spec, acceptable or 'nmar')
3054 f, d = complete(spec, acceptable or 'nmar')
3055 files.update(f)
3055 files.update(f)
3056 dirs.update(d)
3056 dirs.update(d)
3057 files.update(dirs)
3057 files.update(dirs)
3058 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3058 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3059 ui.write('\n')
3059 ui.write('\n')
3060
3060
3061 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3061 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3062 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3062 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3063 '''access the pushkey key/value protocol
3063 '''access the pushkey key/value protocol
3064
3064
3065 With two args, list the keys in the given namespace.
3065 With two args, list the keys in the given namespace.
3066
3066
3067 With five args, set a key to new if it currently is set to old.
3067 With five args, set a key to new if it currently is set to old.
3068 Reports success or failure.
3068 Reports success or failure.
3069 '''
3069 '''
3070
3070
3071 target = hg.peer(ui, {}, repopath)
3071 target = hg.peer(ui, {}, repopath)
3072 if keyinfo:
3072 if keyinfo:
3073 key, old, new = keyinfo
3073 key, old, new = keyinfo
3074 r = target.pushkey(namespace, key, old, new)
3074 r = target.pushkey(namespace, key, old, new)
3075 ui.status(str(r) + '\n')
3075 ui.status(str(r) + '\n')
3076 return not r
3076 return not r
3077 else:
3077 else:
3078 for k, v in sorted(target.listkeys(namespace).iteritems()):
3078 for k, v in sorted(target.listkeys(namespace).iteritems()):
3079 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3079 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3080 v.encode('string-escape')))
3080 v.encode('string-escape')))
3081
3081
3082 @command('debugpvec', [], _('A B'))
3082 @command('debugpvec', [], _('A B'))
3083 def debugpvec(ui, repo, a, b=None):
3083 def debugpvec(ui, repo, a, b=None):
3084 ca = scmutil.revsingle(repo, a)
3084 ca = scmutil.revsingle(repo, a)
3085 cb = scmutil.revsingle(repo, b)
3085 cb = scmutil.revsingle(repo, b)
3086 pa = pvec.ctxpvec(ca)
3086 pa = pvec.ctxpvec(ca)
3087 pb = pvec.ctxpvec(cb)
3087 pb = pvec.ctxpvec(cb)
3088 if pa == pb:
3088 if pa == pb:
3089 rel = "="
3089 rel = "="
3090 elif pa > pb:
3090 elif pa > pb:
3091 rel = ">"
3091 rel = ">"
3092 elif pa < pb:
3092 elif pa < pb:
3093 rel = "<"
3093 rel = "<"
3094 elif pa | pb:
3094 elif pa | pb:
3095 rel = "|"
3095 rel = "|"
3096 ui.write(_("a: %s\n") % pa)
3096 ui.write(_("a: %s\n") % pa)
3097 ui.write(_("b: %s\n") % pb)
3097 ui.write(_("b: %s\n") % pb)
3098 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3098 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") %
3099 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3100 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3100 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3101 pa.distance(pb), rel))
3101 pa.distance(pb), rel))
3102
3102
3103 @command('debugrebuilddirstate|debugrebuildstate',
3103 @command('debugrebuilddirstate|debugrebuildstate',
3104 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3104 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3105 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3105 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3106 'the working copy parent')),
3106 'the working copy parent')),
3107 ],
3107 ],
3108 _('[-r REV]'))
3108 _('[-r REV]'))
3109 def debugrebuilddirstate(ui, repo, rev, **opts):
3109 def debugrebuilddirstate(ui, repo, rev, **opts):
3110 """rebuild the dirstate as it would look like for the given revision
3110 """rebuild the dirstate as it would look like for the given revision
3111
3111
3112 If no revision is specified the first current parent will be used.
3112 If no revision is specified the first current parent will be used.
3113
3113
3114 The dirstate will be set to the files of the given revision.
3114 The dirstate will be set to the files of the given revision.
3115 The actual working directory content or existing dirstate
3115 The actual working directory content or existing dirstate
3116 information such as adds or removes is not considered.
3116 information such as adds or removes is not considered.
3117
3117
3118 ``minimal`` will only rebuild the dirstate status for files that claim to be
3118 ``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
3119 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
3120 manifest but are not in the dirstate. It will not change adds, removes, or
3121 modified files that are in the working copy parent.
3121 modified files that are in the working copy parent.
3122
3122
3123 One use of this command is to make the next :hg:`status` invocation
3123 One use of this command is to make the next :hg:`status` invocation
3124 check the actual file content.
3124 check the actual file content.
3125 """
3125 """
3126 ctx = scmutil.revsingle(repo, rev)
3126 ctx = scmutil.revsingle(repo, rev)
3127 with repo.wlock():
3127 with repo.wlock():
3128 dirstate = repo.dirstate
3128 dirstate = repo.dirstate
3129 changedfiles = None
3129 changedfiles = None
3130 # See command doc for what minimal does.
3130 # See command doc for what minimal does.
3131 if opts.get('minimal'):
3131 if opts.get('minimal'):
3132 manifestfiles = set(ctx.manifest().keys())
3132 manifestfiles = set(ctx.manifest().keys())
3133 dirstatefiles = set(dirstate)
3133 dirstatefiles = set(dirstate)
3134 manifestonly = manifestfiles - dirstatefiles
3134 manifestonly = manifestfiles - dirstatefiles
3135 dsonly = dirstatefiles - manifestfiles
3135 dsonly = dirstatefiles - manifestfiles
3136 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3136 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3137 changedfiles = manifestonly | dsnotadded
3137 changedfiles = manifestonly | dsnotadded
3138
3138
3139 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3139 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3140
3140
3141 @command('debugrebuildfncache', [], '')
3141 @command('debugrebuildfncache', [], '')
3142 def debugrebuildfncache(ui, repo):
3142 def debugrebuildfncache(ui, repo):
3143 """rebuild the fncache file"""
3143 """rebuild the fncache file"""
3144 repair.rebuildfncache(ui, repo)
3144 repair.rebuildfncache(ui, repo)
3145
3145
3146 @command('debugrename',
3146 @command('debugrename',
3147 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3147 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3148 _('[-r REV] FILE'))
3148 _('[-r REV] FILE'))
3149 def debugrename(ui, repo, file1, *pats, **opts):
3149 def debugrename(ui, repo, file1, *pats, **opts):
3150 """dump rename information"""
3150 """dump rename information"""
3151
3151
3152 ctx = scmutil.revsingle(repo, opts.get('rev'))
3152 ctx = scmutil.revsingle(repo, opts.get('rev'))
3153 m = scmutil.match(ctx, (file1,) + pats, opts)
3153 m = scmutil.match(ctx, (file1,) + pats, opts)
3154 for abs in ctx.walk(m):
3154 for abs in ctx.walk(m):
3155 fctx = ctx[abs]
3155 fctx = ctx[abs]
3156 o = fctx.filelog().renamed(fctx.filenode())
3156 o = fctx.filelog().renamed(fctx.filenode())
3157 rel = m.rel(abs)
3157 rel = m.rel(abs)
3158 if o:
3158 if o:
3159 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3159 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3160 else:
3160 else:
3161 ui.write(_("%s not renamed\n") % rel)
3161 ui.write(_("%s not renamed\n") % rel)
3162
3162
3163 @command('debugrevlog', debugrevlogopts +
3163 @command('debugrevlog', debugrevlogopts +
3164 [('d', 'dump', False, _('dump index data'))],
3164 [('d', 'dump', False, _('dump index data'))],
3165 _('-c|-m|FILE'),
3165 _('-c|-m|FILE'),
3166 optionalrepo=True)
3166 optionalrepo=True)
3167 def debugrevlog(ui, repo, file_=None, **opts):
3167 def debugrevlog(ui, repo, file_=None, **opts):
3168 """show data and statistics about a revlog"""
3168 """show data and statistics about a revlog"""
3169 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3169 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3170
3170
3171 if opts.get("dump"):
3171 if opts.get("dump"):
3172 numrevs = len(r)
3172 numrevs = len(r)
3173 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3173 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3174 " rawsize totalsize compression heads chainlen\n")
3174 " rawsize totalsize compression heads chainlen\n")
3175 ts = 0
3175 ts = 0
3176 heads = set()
3176 heads = set()
3177
3177
3178 for rev in xrange(numrevs):
3178 for rev in xrange(numrevs):
3179 dbase = r.deltaparent(rev)
3179 dbase = r.deltaparent(rev)
3180 if dbase == -1:
3180 if dbase == -1:
3181 dbase = rev
3181 dbase = rev
3182 cbase = r.chainbase(rev)
3182 cbase = r.chainbase(rev)
3183 clen = r.chainlen(rev)
3183 clen = r.chainlen(rev)
3184 p1, p2 = r.parentrevs(rev)
3184 p1, p2 = r.parentrevs(rev)
3185 rs = r.rawsize(rev)
3185 rs = r.rawsize(rev)
3186 ts = ts + rs
3186 ts = ts + rs
3187 heads -= set(r.parentrevs(rev))
3187 heads -= set(r.parentrevs(rev))
3188 heads.add(rev)
3188 heads.add(rev)
3189 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3189 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3190 "%11d %5d %8d\n" %
3190 "%11d %5d %8d\n" %
3191 (rev, p1, p2, r.start(rev), r.end(rev),
3191 (rev, p1, p2, r.start(rev), r.end(rev),
3192 r.start(dbase), r.start(cbase),
3192 r.start(dbase), r.start(cbase),
3193 r.start(p1), r.start(p2),
3193 r.start(p1), r.start(p2),
3194 rs, ts, ts / r.end(rev), len(heads), clen))
3194 rs, ts, ts / r.end(rev), len(heads), clen))
3195 return 0
3195 return 0
3196
3196
3197 v = r.version
3197 v = r.version
3198 format = v & 0xFFFF
3198 format = v & 0xFFFF
3199 flags = []
3199 flags = []
3200 gdelta = False
3200 gdelta = False
3201 if v & revlog.REVLOGNGINLINEDATA:
3201 if v & revlog.REVLOGNGINLINEDATA:
3202 flags.append('inline')
3202 flags.append('inline')
3203 if v & revlog.REVLOGGENERALDELTA:
3203 if v & revlog.REVLOGGENERALDELTA:
3204 gdelta = True
3204 gdelta = True
3205 flags.append('generaldelta')
3205 flags.append('generaldelta')
3206 if not flags:
3206 if not flags:
3207 flags = ['(none)']
3207 flags = ['(none)']
3208
3208
3209 nummerges = 0
3209 nummerges = 0
3210 numfull = 0
3210 numfull = 0
3211 numprev = 0
3211 numprev = 0
3212 nump1 = 0
3212 nump1 = 0
3213 nump2 = 0
3213 nump2 = 0
3214 numother = 0
3214 numother = 0
3215 nump1prev = 0
3215 nump1prev = 0
3216 nump2prev = 0
3216 nump2prev = 0
3217 chainlengths = []
3217 chainlengths = []
3218
3218
3219 datasize = [None, 0, 0L]
3219 datasize = [None, 0, 0L]
3220 fullsize = [None, 0, 0L]
3220 fullsize = [None, 0, 0L]
3221 deltasize = [None, 0, 0L]
3221 deltasize = [None, 0, 0L]
3222
3222
3223 def addsize(size, l):
3223 def addsize(size, l):
3224 if l[0] is None or size < l[0]:
3224 if l[0] is None or size < l[0]:
3225 l[0] = size
3225 l[0] = size
3226 if size > l[1]:
3226 if size > l[1]:
3227 l[1] = size
3227 l[1] = size
3228 l[2] += size
3228 l[2] += size
3229
3229
3230 numrevs = len(r)
3230 numrevs = len(r)
3231 for rev in xrange(numrevs):
3231 for rev in xrange(numrevs):
3232 p1, p2 = r.parentrevs(rev)
3232 p1, p2 = r.parentrevs(rev)
3233 delta = r.deltaparent(rev)
3233 delta = r.deltaparent(rev)
3234 if format > 0:
3234 if format > 0:
3235 addsize(r.rawsize(rev), datasize)
3235 addsize(r.rawsize(rev), datasize)
3236 if p2 != nullrev:
3236 if p2 != nullrev:
3237 nummerges += 1
3237 nummerges += 1
3238 size = r.length(rev)
3238 size = r.length(rev)
3239 if delta == nullrev:
3239 if delta == nullrev:
3240 chainlengths.append(0)
3240 chainlengths.append(0)
3241 numfull += 1
3241 numfull += 1
3242 addsize(size, fullsize)
3242 addsize(size, fullsize)
3243 else:
3243 else:
3244 chainlengths.append(chainlengths[delta] + 1)
3244 chainlengths.append(chainlengths[delta] + 1)
3245 addsize(size, deltasize)
3245 addsize(size, deltasize)
3246 if delta == rev - 1:
3246 if delta == rev - 1:
3247 numprev += 1
3247 numprev += 1
3248 if delta == p1:
3248 if delta == p1:
3249 nump1prev += 1
3249 nump1prev += 1
3250 elif delta == p2:
3250 elif delta == p2:
3251 nump2prev += 1
3251 nump2prev += 1
3252 elif delta == p1:
3252 elif delta == p1:
3253 nump1 += 1
3253 nump1 += 1
3254 elif delta == p2:
3254 elif delta == p2:
3255 nump2 += 1
3255 nump2 += 1
3256 elif delta != nullrev:
3256 elif delta != nullrev:
3257 numother += 1
3257 numother += 1
3258
3258
3259 # Adjust size min value for empty cases
3259 # Adjust size min value for empty cases
3260 for size in (datasize, fullsize, deltasize):
3260 for size in (datasize, fullsize, deltasize):
3261 if size[0] is None:
3261 if size[0] is None:
3262 size[0] = 0
3262 size[0] = 0
3263
3263
3264 numdeltas = numrevs - numfull
3264 numdeltas = numrevs - numfull
3265 numoprev = numprev - nump1prev - nump2prev
3265 numoprev = numprev - nump1prev - nump2prev
3266 totalrawsize = datasize[2]
3266 totalrawsize = datasize[2]
3267 datasize[2] /= numrevs
3267 datasize[2] /= numrevs
3268 fulltotal = fullsize[2]
3268 fulltotal = fullsize[2]
3269 fullsize[2] /= numfull
3269 fullsize[2] /= numfull
3270 deltatotal = deltasize[2]
3270 deltatotal = deltasize[2]
3271 if numrevs - numfull > 0:
3271 if numrevs - numfull > 0:
3272 deltasize[2] /= numrevs - numfull
3272 deltasize[2] /= numrevs - numfull
3273 totalsize = fulltotal + deltatotal
3273 totalsize = fulltotal + deltatotal
3274 avgchainlen = sum(chainlengths) / numrevs
3274 avgchainlen = sum(chainlengths) / numrevs
3275 maxchainlen = max(chainlengths)
3275 maxchainlen = max(chainlengths)
3276 compratio = 1
3276 compratio = 1
3277 if totalsize:
3277 if totalsize:
3278 compratio = totalrawsize / totalsize
3278 compratio = totalrawsize / totalsize
3279
3279
3280 basedfmtstr = '%%%dd\n'
3280 basedfmtstr = '%%%dd\n'
3281 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3281 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3282
3282
3283 def dfmtstr(max):
3283 def dfmtstr(max):
3284 return basedfmtstr % len(str(max))
3284 return basedfmtstr % len(str(max))
3285 def pcfmtstr(max, padding=0):
3285 def pcfmtstr(max, padding=0):
3286 return basepcfmtstr % (len(str(max)), ' ' * padding)
3286 return basepcfmtstr % (len(str(max)), ' ' * padding)
3287
3287
3288 def pcfmt(value, total):
3288 def pcfmt(value, total):
3289 if total:
3289 if total:
3290 return (value, 100 * float(value) / total)
3290 return (value, 100 * float(value) / total)
3291 else:
3291 else:
3292 return value, 100.0
3292 return value, 100.0
3293
3293
3294 ui.write(('format : %d\n') % format)
3294 ui.write(('format : %d\n') % format)
3295 ui.write(('flags : %s\n') % ', '.join(flags))
3295 ui.write(('flags : %s\n') % ', '.join(flags))
3296
3296
3297 ui.write('\n')
3297 ui.write('\n')
3298 fmt = pcfmtstr(totalsize)
3298 fmt = pcfmtstr(totalsize)
3299 fmt2 = dfmtstr(totalsize)
3299 fmt2 = dfmtstr(totalsize)
3300 ui.write(('revisions : ') + fmt2 % numrevs)
3300 ui.write(('revisions : ') + fmt2 % numrevs)
3301 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3301 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3302 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3302 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3303 ui.write(('revisions : ') + fmt2 % numrevs)
3303 ui.write(('revisions : ') + fmt2 % numrevs)
3304 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3304 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3305 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3305 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3306 ui.write(('revision size : ') + fmt2 % totalsize)
3306 ui.write(('revision size : ') + fmt2 % totalsize)
3307 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3307 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3308 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3308 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3309
3309
3310 ui.write('\n')
3310 ui.write('\n')
3311 fmt = dfmtstr(max(avgchainlen, compratio))
3311 fmt = dfmtstr(max(avgchainlen, compratio))
3312 ui.write(('avg chain length : ') + fmt % avgchainlen)
3312 ui.write(('avg chain length : ') + fmt % avgchainlen)
3313 ui.write(('max chain length : ') + fmt % maxchainlen)
3313 ui.write(('max chain length : ') + fmt % maxchainlen)
3314 ui.write(('compression ratio : ') + fmt % compratio)
3314 ui.write(('compression ratio : ') + fmt % compratio)
3315
3315
3316 if format > 0:
3316 if format > 0:
3317 ui.write('\n')
3317 ui.write('\n')
3318 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3318 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3319 % tuple(datasize))
3319 % tuple(datasize))
3320 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3320 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3321 % tuple(fullsize))
3321 % tuple(fullsize))
3322 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3322 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3323 % tuple(deltasize))
3323 % tuple(deltasize))
3324
3324
3325 if numdeltas > 0:
3325 if numdeltas > 0:
3326 ui.write('\n')
3326 ui.write('\n')
3327 fmt = pcfmtstr(numdeltas)
3327 fmt = pcfmtstr(numdeltas)
3328 fmt2 = pcfmtstr(numdeltas, 4)
3328 fmt2 = pcfmtstr(numdeltas, 4)
3329 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3329 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3330 if numprev > 0:
3330 if numprev > 0:
3331 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3331 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3332 numprev))
3332 numprev))
3333 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3333 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3334 numprev))
3334 numprev))
3335 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3335 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3336 numprev))
3336 numprev))
3337 if gdelta:
3337 if gdelta:
3338 ui.write(('deltas against p1 : ')
3338 ui.write(('deltas against p1 : ')
3339 + fmt % pcfmt(nump1, numdeltas))
3339 + fmt % pcfmt(nump1, numdeltas))
3340 ui.write(('deltas against p2 : ')
3340 ui.write(('deltas against p2 : ')
3341 + fmt % pcfmt(nump2, numdeltas))
3341 + fmt % pcfmt(nump2, numdeltas))
3342 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3342 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3343 numdeltas))
3343 numdeltas))
3344
3344
3345 @command('debugrevspec',
3345 @command('debugrevspec',
3346 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3346 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3347 ('REVSPEC'))
3347 ('REVSPEC'))
3348 def debugrevspec(ui, repo, expr, **opts):
3348 def debugrevspec(ui, repo, expr, **opts):
3349 """parse and apply a revision specification
3349 """parse and apply a revision specification
3350
3350
3351 Use --verbose to print the parsed tree before and after aliases
3351 Use --verbose to print the parsed tree before and after aliases
3352 expansion.
3352 expansion.
3353 """
3353 """
3354 if ui.verbose:
3354 if ui.verbose:
3355 tree = revset.parse(expr, lookup=repo.__contains__)
3355 tree = revset.parse(expr, lookup=repo.__contains__)
3356 ui.note(revset.prettyformat(tree), "\n")
3356 ui.note(revset.prettyformat(tree), "\n")
3357 newtree = revset.findaliases(ui, tree)
3357 newtree = revset.findaliases(ui, tree)
3358 if newtree != tree:
3358 if newtree != tree:
3359 ui.note(revset.prettyformat(newtree), "\n")
3359 ui.note(revset.prettyformat(newtree), "\n")
3360 tree = newtree
3360 tree = newtree
3361 newtree = revset.foldconcat(tree)
3361 newtree = revset.foldconcat(tree)
3362 if newtree != tree:
3362 if newtree != tree:
3363 ui.note(revset.prettyformat(newtree), "\n")
3363 ui.note(revset.prettyformat(newtree), "\n")
3364 if opts["optimize"]:
3364 if opts["optimize"]:
3365 weight, optimizedtree = revset.optimize(newtree, True)
3365 weight, optimizedtree = revset.optimize(newtree, True)
3366 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3366 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3367 func = revset.match(ui, expr, repo)
3367 func = revset.match(ui, expr, repo)
3368 revs = func(repo)
3368 revs = func(repo)
3369 if ui.verbose:
3369 if ui.verbose:
3370 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3370 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3371 for c in revs:
3371 for c in revs:
3372 ui.write("%s\n" % c)
3372 ui.write("%s\n" % c)
3373
3373
3374 @command('debugsetparents', [], _('REV1 [REV2]'))
3374 @command('debugsetparents', [], _('REV1 [REV2]'))
3375 def debugsetparents(ui, repo, rev1, rev2=None):
3375 def debugsetparents(ui, repo, rev1, rev2=None):
3376 """manually set the parents of the current working directory
3376 """manually set the parents of the current working directory
3377
3377
3378 This is useful for writing repository conversion tools, but should
3378 This is useful for writing repository conversion tools, but should
3379 be used with care. For example, neither the working directory nor the
3379 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
3380 dirstate is updated, so file status may be incorrect after running this
3381 command.
3381 command.
3382
3382
3383 Returns 0 on success.
3383 Returns 0 on success.
3384 """
3384 """
3385
3385
3386 r1 = scmutil.revsingle(repo, rev1).node()
3386 r1 = scmutil.revsingle(repo, rev1).node()
3387 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3387 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3388
3388
3389 with repo.wlock():
3389 with repo.wlock():
3390 repo.dirstate.beginparentchange()
3390 repo.dirstate.beginparentchange()
3391 repo.setparents(r1, r2)
3391 repo.setparents(r1, r2)
3392 repo.dirstate.endparentchange()
3392 repo.dirstate.endparentchange()
3393
3393
3394 @command('debugdirstate|debugstate',
3394 @command('debugdirstate|debugstate',
3395 [('', 'nodates', None, _('do not display the saved mtime')),
3395 [('', 'nodates', None, _('do not display the saved mtime')),
3396 ('', 'datesort', None, _('sort by saved mtime'))],
3396 ('', 'datesort', None, _('sort by saved mtime'))],
3397 _('[OPTION]...'))
3397 _('[OPTION]...'))
3398 def debugstate(ui, repo, **opts):
3398 def debugstate(ui, repo, **opts):
3399 """show the contents of the current dirstate"""
3399 """show the contents of the current dirstate"""
3400
3400
3401 nodates = opts.get('nodates')
3401 nodates = opts.get('nodates')
3402 datesort = opts.get('datesort')
3402 datesort = opts.get('datesort')
3403
3403
3404 timestr = ""
3404 timestr = ""
3405 if datesort:
3405 if datesort:
3406 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3406 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3407 else:
3407 else:
3408 keyfunc = None # sort by filename
3408 keyfunc = None # sort by filename
3409 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3409 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3410 if ent[3] == -1:
3410 if ent[3] == -1:
3411 timestr = 'unset '
3411 timestr = 'unset '
3412 elif nodates:
3412 elif nodates:
3413 timestr = 'set '
3413 timestr = 'set '
3414 else:
3414 else:
3415 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3415 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3416 time.localtime(ent[3]))
3416 time.localtime(ent[3]))
3417 if ent[1] & 0o20000:
3417 if ent[1] & 0o20000:
3418 mode = 'lnk'
3418 mode = 'lnk'
3419 else:
3419 else:
3420 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3420 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3421 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3421 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3422 for f in repo.dirstate.copies():
3422 for f in repo.dirstate.copies():
3423 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3423 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3424
3424
3425 @command('debugsub',
3425 @command('debugsub',
3426 [('r', 'rev', '',
3426 [('r', 'rev', '',
3427 _('revision to check'), _('REV'))],
3427 _('revision to check'), _('REV'))],
3428 _('[-r REV] [REV]'))
3428 _('[-r REV] [REV]'))
3429 def debugsub(ui, repo, rev=None):
3429 def debugsub(ui, repo, rev=None):
3430 ctx = scmutil.revsingle(repo, rev, None)
3430 ctx = scmutil.revsingle(repo, rev, None)
3431 for k, v in sorted(ctx.substate.items()):
3431 for k, v in sorted(ctx.substate.items()):
3432 ui.write(('path %s\n') % k)
3432 ui.write(('path %s\n') % k)
3433 ui.write((' source %s\n') % v[0])
3433 ui.write((' source %s\n') % v[0])
3434 ui.write((' revision %s\n') % v[1])
3434 ui.write((' revision %s\n') % v[1])
3435
3435
3436 @command('debugsuccessorssets',
3436 @command('debugsuccessorssets',
3437 [],
3437 [],
3438 _('[REV]'))
3438 _('[REV]'))
3439 def debugsuccessorssets(ui, repo, *revs):
3439 def debugsuccessorssets(ui, repo, *revs):
3440 """show set of successors for revision
3440 """show set of successors for revision
3441
3441
3442 A successors set of changeset A is a consistent group of revisions that
3442 A successors set of changeset A is a consistent group of revisions that
3443 succeed A. It contains non-obsolete changesets only.
3443 succeed A. It contains non-obsolete changesets only.
3444
3444
3445 In most cases a changeset A has a single successors set containing a single
3445 In most cases a changeset A has a single successors set containing a single
3446 successor (changeset A replaced by A').
3446 successor (changeset A replaced by A').
3447
3447
3448 A changeset that is made obsolete with no successors are called "pruned".
3448 A changeset that is made obsolete with no successors are called "pruned".
3449 Such changesets have no successors sets at all.
3449 Such changesets have no successors sets at all.
3450
3450
3451 A changeset that has been "split" will have a successors set containing
3451 A changeset that has been "split" will have a successors set containing
3452 more than one successor.
3452 more than one successor.
3453
3453
3454 A changeset that has been rewritten in multiple different ways is called
3454 A changeset that has been rewritten in multiple different ways is called
3455 "divergent". Such changesets have multiple successor sets (each of which
3455 "divergent". Such changesets have multiple successor sets (each of which
3456 may also be split, i.e. have multiple successors).
3456 may also be split, i.e. have multiple successors).
3457
3457
3458 Results are displayed as follows::
3458 Results are displayed as follows::
3459
3459
3460 <rev1>
3460 <rev1>
3461 <successors-1A>
3461 <successors-1A>
3462 <rev2>
3462 <rev2>
3463 <successors-2A>
3463 <successors-2A>
3464 <successors-2B1> <successors-2B2> <successors-2B3>
3464 <successors-2B1> <successors-2B2> <successors-2B3>
3465
3465
3466 Here rev2 has two possible (i.e. divergent) successors sets. The first
3466 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
3467 holds one element, whereas the second holds three (i.e. the changeset has
3468 been split).
3468 been split).
3469 """
3469 """
3470 # passed to successorssets caching computation from one call to another
3470 # passed to successorssets caching computation from one call to another
3471 cache = {}
3471 cache = {}
3472 ctx2str = str
3472 ctx2str = str
3473 node2str = short
3473 node2str = short
3474 if ui.debug():
3474 if ui.debug():
3475 def ctx2str(ctx):
3475 def ctx2str(ctx):
3476 return ctx.hex()
3476 return ctx.hex()
3477 node2str = hex
3477 node2str = hex
3478 for rev in scmutil.revrange(repo, revs):
3478 for rev in scmutil.revrange(repo, revs):
3479 ctx = repo[rev]
3479 ctx = repo[rev]
3480 ui.write('%s\n'% ctx2str(ctx))
3480 ui.write('%s\n'% ctx2str(ctx))
3481 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3481 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3482 if succsset:
3482 if succsset:
3483 ui.write(' ')
3483 ui.write(' ')
3484 ui.write(node2str(succsset[0]))
3484 ui.write(node2str(succsset[0]))
3485 for node in succsset[1:]:
3485 for node in succsset[1:]:
3486 ui.write(' ')
3486 ui.write(' ')
3487 ui.write(node2str(node))
3487 ui.write(node2str(node))
3488 ui.write('\n')
3488 ui.write('\n')
3489
3489
3490 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3490 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3491 def debugwalk(ui, repo, *pats, **opts):
3491 def debugwalk(ui, repo, *pats, **opts):
3492 """show how files match on given patterns"""
3492 """show how files match on given patterns"""
3493 m = scmutil.match(repo[None], pats, opts)
3493 m = scmutil.match(repo[None], pats, opts)
3494 items = list(repo.walk(m))
3494 items = list(repo.walk(m))
3495 if not items:
3495 if not items:
3496 return
3496 return
3497 f = lambda fn: fn
3497 f = lambda fn: fn
3498 if ui.configbool('ui', 'slash') and os.sep != '/':
3498 if ui.configbool('ui', 'slash') and os.sep != '/':
3499 f = lambda fn: util.normpath(fn)
3499 f = lambda fn: util.normpath(fn)
3500 fmt = 'f %%-%ds %%-%ds %%s' % (
3500 fmt = 'f %%-%ds %%-%ds %%s' % (
3501 max([len(abs) for abs in items]),
3501 max([len(abs) for abs in items]),
3502 max([len(m.rel(abs)) for abs in items]))
3502 max([len(m.rel(abs)) for abs in items]))
3503 for abs in items:
3503 for abs in items:
3504 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3504 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3505 ui.write("%s\n" % line.rstrip())
3505 ui.write("%s\n" % line.rstrip())
3506
3506
3507 @command('debugwireargs',
3507 @command('debugwireargs',
3508 [('', 'three', '', 'three'),
3508 [('', 'three', '', 'three'),
3509 ('', 'four', '', 'four'),
3509 ('', 'four', '', 'four'),
3510 ('', 'five', '', 'five'),
3510 ('', 'five', '', 'five'),
3511 ] + remoteopts,
3511 ] + remoteopts,
3512 _('REPO [OPTIONS]... [ONE [TWO]]'),
3512 _('REPO [OPTIONS]... [ONE [TWO]]'),
3513 norepo=True)
3513 norepo=True)
3514 def debugwireargs(ui, repopath, *vals, **opts):
3514 def debugwireargs(ui, repopath, *vals, **opts):
3515 repo = hg.peer(ui, opts, repopath)
3515 repo = hg.peer(ui, opts, repopath)
3516 for opt in remoteopts:
3516 for opt in remoteopts:
3517 del opts[opt[1]]
3517 del opts[opt[1]]
3518 args = {}
3518 args = {}
3519 for k, v in opts.iteritems():
3519 for k, v in opts.iteritems():
3520 if v:
3520 if v:
3521 args[k] = v
3521 args[k] = v
3522 # run twice to check that we don't mess up the stream for the next command
3522 # run twice to check that we don't mess up the stream for the next command
3523 res1 = repo.debugwireargs(*vals, **args)
3523 res1 = repo.debugwireargs(*vals, **args)
3524 res2 = repo.debugwireargs(*vals, **args)
3524 res2 = repo.debugwireargs(*vals, **args)
3525 ui.write("%s\n" % res1)
3525 ui.write("%s\n" % res1)
3526 if res1 != res2:
3526 if res1 != res2:
3527 ui.warn("%s\n" % res2)
3527 ui.warn("%s\n" % res2)
3528
3528
3529 @command('^diff',
3529 @command('^diff',
3530 [('r', 'rev', [], _('revision'), _('REV')),
3530 [('r', 'rev', [], _('revision'), _('REV')),
3531 ('c', 'change', '', _('change made by revision'), _('REV'))
3531 ('c', 'change', '', _('change made by revision'), _('REV'))
3532 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3532 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3533 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3533 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3534 inferrepo=True)
3534 inferrepo=True)
3535 def diff(ui, repo, *pats, **opts):
3535 def diff(ui, repo, *pats, **opts):
3536 """diff repository (or selected files)
3536 """diff repository (or selected files)
3537
3537
3538 Show differences between revisions for the specified files.
3538 Show differences between revisions for the specified files.
3539
3539
3540 Differences between files are shown using the unified diff format.
3540 Differences between files are shown using the unified diff format.
3541
3541
3542 .. note::
3542 .. note::
3543
3543
3544 :hg:`diff` may generate unexpected results for merges, as it will
3544 :hg:`diff` may generate unexpected results for merges, as it will
3545 default to comparing against the working directory's first
3545 default to comparing against the working directory's first
3546 parent changeset if no revisions are specified.
3546 parent changeset if no revisions are specified.
3547
3547
3548 When two revision arguments are given, then changes are shown
3548 When two revision arguments are given, then changes are shown
3549 between those revisions. If only one revision is specified then
3549 between those revisions. If only one revision is specified then
3550 that revision is compared to the working directory, and, when no
3550 that revision is compared to the working directory, and, when no
3551 revisions are specified, the working directory files are compared
3551 revisions are specified, the working directory files are compared
3552 to its first parent.
3552 to its first parent.
3553
3553
3554 Alternatively you can specify -c/--change with a revision to see
3554 Alternatively you can specify -c/--change with a revision to see
3555 the changes in that changeset relative to its first parent.
3555 the changes in that changeset relative to its first parent.
3556
3556
3557 Without the -a/--text option, diff will avoid generating diffs of
3557 Without the -a/--text option, diff will avoid generating diffs of
3558 files it detects as binary. With -a, diff will generate a diff
3558 files it detects as binary. With -a, diff will generate a diff
3559 anyway, probably with undesirable results.
3559 anyway, probably with undesirable results.
3560
3560
3561 Use the -g/--git option to generate diffs in the git extended diff
3561 Use the -g/--git option to generate diffs in the git extended diff
3562 format. For more information, read :hg:`help diffs`.
3562 format. For more information, read :hg:`help diffs`.
3563
3563
3564 .. container:: verbose
3564 .. container:: verbose
3565
3565
3566 Examples:
3566 Examples:
3567
3567
3568 - compare a file in the current working directory to its parent::
3568 - compare a file in the current working directory to its parent::
3569
3569
3570 hg diff foo.c
3570 hg diff foo.c
3571
3571
3572 - compare two historical versions of a directory, with rename info::
3572 - compare two historical versions of a directory, with rename info::
3573
3573
3574 hg diff --git -r 1.0:1.2 lib/
3574 hg diff --git -r 1.0:1.2 lib/
3575
3575
3576 - get change stats relative to the last change on some date::
3576 - get change stats relative to the last change on some date::
3577
3577
3578 hg diff --stat -r "date('may 2')"
3578 hg diff --stat -r "date('may 2')"
3579
3579
3580 - diff all newly-added files that contain a keyword::
3580 - diff all newly-added files that contain a keyword::
3581
3581
3582 hg diff "set:added() and grep(GNU)"
3582 hg diff "set:added() and grep(GNU)"
3583
3583
3584 - compare a revision and its parents::
3584 - compare a revision and its parents::
3585
3585
3586 hg diff -c 9353 # compare against first parent
3586 hg diff -c 9353 # compare against first parent
3587 hg diff -r 9353^:9353 # same using revset syntax
3587 hg diff -r 9353^:9353 # same using revset syntax
3588 hg diff -r 9353^2:9353 # compare against the second parent
3588 hg diff -r 9353^2:9353 # compare against the second parent
3589
3589
3590 Returns 0 on success.
3590 Returns 0 on success.
3591 """
3591 """
3592
3592
3593 revs = opts.get('rev')
3593 revs = opts.get('rev')
3594 change = opts.get('change')
3594 change = opts.get('change')
3595 stat = opts.get('stat')
3595 stat = opts.get('stat')
3596 reverse = opts.get('reverse')
3596 reverse = opts.get('reverse')
3597
3597
3598 if revs and change:
3598 if revs and change:
3599 msg = _('cannot specify --rev and --change at the same time')
3599 msg = _('cannot specify --rev and --change at the same time')
3600 raise error.Abort(msg)
3600 raise error.Abort(msg)
3601 elif change:
3601 elif change:
3602 node2 = scmutil.revsingle(repo, change, None).node()
3602 node2 = scmutil.revsingle(repo, change, None).node()
3603 node1 = repo[node2].p1().node()
3603 node1 = repo[node2].p1().node()
3604 else:
3604 else:
3605 node1, node2 = scmutil.revpair(repo, revs)
3605 node1, node2 = scmutil.revpair(repo, revs)
3606
3606
3607 if reverse:
3607 if reverse:
3608 node1, node2 = node2, node1
3608 node1, node2 = node2, node1
3609
3609
3610 diffopts = patch.diffallopts(ui, opts)
3610 diffopts = patch.diffallopts(ui, opts)
3611 m = scmutil.match(repo[node2], pats, opts)
3611 m = scmutil.match(repo[node2], pats, opts)
3612 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3612 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3613 listsubrepos=opts.get('subrepos'),
3613 listsubrepos=opts.get('subrepos'),
3614 root=opts.get('root'))
3614 root=opts.get('root'))
3615
3615
3616 @command('^export',
3616 @command('^export',
3617 [('o', 'output', '',
3617 [('o', 'output', '',
3618 _('print output to file with formatted name'), _('FORMAT')),
3618 _('print output to file with formatted name'), _('FORMAT')),
3619 ('', 'switch-parent', None, _('diff against the second parent')),
3619 ('', 'switch-parent', None, _('diff against the second parent')),
3620 ('r', 'rev', [], _('revisions to export'), _('REV')),
3620 ('r', 'rev', [], _('revisions to export'), _('REV')),
3621 ] + diffopts,
3621 ] + diffopts,
3622 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3622 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3623 def export(ui, repo, *changesets, **opts):
3623 def export(ui, repo, *changesets, **opts):
3624 """dump the header and diffs for one or more changesets
3624 """dump the header and diffs for one or more changesets
3625
3625
3626 Print the changeset header and diffs for one or more revisions.
3626 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.
3627 If no revision is given, the parent of the working directory is used.
3628
3628
3629 The information shown in the changeset header is: author, date,
3629 The information shown in the changeset header is: author, date,
3630 branch name (if non-default), changeset hash, parent(s) and commit
3630 branch name (if non-default), changeset hash, parent(s) and commit
3631 comment.
3631 comment.
3632
3632
3633 .. note::
3633 .. note::
3634
3634
3635 :hg:`export` may generate unexpected diff output for merge
3635 :hg:`export` may generate unexpected diff output for merge
3636 changesets, as it will compare the merge changeset against its
3636 changesets, as it will compare the merge changeset against its
3637 first parent only.
3637 first parent only.
3638
3638
3639 Output may be to a file, in which case the name of the file is
3639 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:
3640 given using a format string. The formatting rules are as follows:
3641
3641
3642 :``%%``: literal "%" character
3642 :``%%``: literal "%" character
3643 :``%H``: changeset hash (40 hexadecimal digits)
3643 :``%H``: changeset hash (40 hexadecimal digits)
3644 :``%N``: number of patches being generated
3644 :``%N``: number of patches being generated
3645 :``%R``: changeset revision number
3645 :``%R``: changeset revision number
3646 :``%b``: basename of the exporting repository
3646 :``%b``: basename of the exporting repository
3647 :``%h``: short-form changeset hash (12 hexadecimal digits)
3647 :``%h``: short-form changeset hash (12 hexadecimal digits)
3648 :``%m``: first line of the commit message (only alphanumeric characters)
3648 :``%m``: first line of the commit message (only alphanumeric characters)
3649 :``%n``: zero-padded sequence number, starting at 1
3649 :``%n``: zero-padded sequence number, starting at 1
3650 :``%r``: zero-padded changeset revision number
3650 :``%r``: zero-padded changeset revision number
3651
3651
3652 Without the -a/--text option, export will avoid generating diffs
3652 Without the -a/--text option, export will avoid generating diffs
3653 of files it detects as binary. With -a, export will generate a
3653 of files it detects as binary. With -a, export will generate a
3654 diff anyway, probably with undesirable results.
3654 diff anyway, probably with undesirable results.
3655
3655
3656 Use the -g/--git option to generate diffs in the git extended diff
3656 Use the -g/--git option to generate diffs in the git extended diff
3657 format. See :hg:`help diffs` for more information.
3657 format. See :hg:`help diffs` for more information.
3658
3658
3659 With the --switch-parent option, the diff will be against the
3659 With the --switch-parent option, the diff will be against the
3660 second parent. It can be useful to review a merge.
3660 second parent. It can be useful to review a merge.
3661
3661
3662 .. container:: verbose
3662 .. container:: verbose
3663
3663
3664 Examples:
3664 Examples:
3665
3665
3666 - use export and import to transplant a bugfix to the current
3666 - use export and import to transplant a bugfix to the current
3667 branch::
3667 branch::
3668
3668
3669 hg export -r 9353 | hg import -
3669 hg export -r 9353 | hg import -
3670
3670
3671 - export all the changesets between two revisions to a file with
3671 - export all the changesets between two revisions to a file with
3672 rename information::
3672 rename information::
3673
3673
3674 hg export --git -r 123:150 > changes.txt
3674 hg export --git -r 123:150 > changes.txt
3675
3675
3676 - split outgoing changes into a series of patches with
3676 - split outgoing changes into a series of patches with
3677 descriptive names::
3677 descriptive names::
3678
3678
3679 hg export -r "outgoing()" -o "%n-%m.patch"
3679 hg export -r "outgoing()" -o "%n-%m.patch"
3680
3680
3681 Returns 0 on success.
3681 Returns 0 on success.
3682 """
3682 """
3683 changesets += tuple(opts.get('rev', []))
3683 changesets += tuple(opts.get('rev', []))
3684 if not changesets:
3684 if not changesets:
3685 changesets = ['.']
3685 changesets = ['.']
3686 revs = scmutil.revrange(repo, changesets)
3686 revs = scmutil.revrange(repo, changesets)
3687 if not revs:
3687 if not revs:
3688 raise error.Abort(_("export requires at least one changeset"))
3688 raise error.Abort(_("export requires at least one changeset"))
3689 if len(revs) > 1:
3689 if len(revs) > 1:
3690 ui.note(_('exporting patches:\n'))
3690 ui.note(_('exporting patches:\n'))
3691 else:
3691 else:
3692 ui.note(_('exporting patch:\n'))
3692 ui.note(_('exporting patch:\n'))
3693 cmdutil.export(repo, revs, template=opts.get('output'),
3693 cmdutil.export(repo, revs, template=opts.get('output'),
3694 switch_parent=opts.get('switch_parent'),
3694 switch_parent=opts.get('switch_parent'),
3695 opts=patch.diffallopts(ui, opts))
3695 opts=patch.diffallopts(ui, opts))
3696
3696
3697 @command('files',
3697 @command('files',
3698 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3698 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3699 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3699 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3700 ] + walkopts + formatteropts + subrepoopts,
3700 ] + walkopts + formatteropts + subrepoopts,
3701 _('[OPTION]... [PATTERN]...'))
3701 _('[OPTION]... [PATTERN]...'))
3702 def files(ui, repo, *pats, **opts):
3702 def files(ui, repo, *pats, **opts):
3703 """list tracked files
3703 """list tracked files
3704
3704
3705 Print files under Mercurial control in the working directory or
3705 Print files under Mercurial control in the working directory or
3706 specified revision whose names match the given patterns (excluding
3706 specified revision whose names match the given patterns (excluding
3707 removed files).
3707 removed files).
3708
3708
3709 If no patterns are given to match, this command prints the names
3709 If no patterns are given to match, this command prints the names
3710 of all files under Mercurial control in the working directory.
3710 of all files under Mercurial control in the working directory.
3711
3711
3712 .. container:: verbose
3712 .. container:: verbose
3713
3713
3714 Examples:
3714 Examples:
3715
3715
3716 - list all files under the current directory::
3716 - list all files under the current directory::
3717
3717
3718 hg files .
3718 hg files .
3719
3719
3720 - shows sizes and flags for current revision::
3720 - shows sizes and flags for current revision::
3721
3721
3722 hg files -vr .
3722 hg files -vr .
3723
3723
3724 - list all files named README::
3724 - list all files named README::
3725
3725
3726 hg files -I "**/README"
3726 hg files -I "**/README"
3727
3727
3728 - list all binary files::
3728 - list all binary files::
3729
3729
3730 hg files "set:binary()"
3730 hg files "set:binary()"
3731
3731
3732 - find files containing a regular expression::
3732 - find files containing a regular expression::
3733
3733
3734 hg files "set:grep('bob')"
3734 hg files "set:grep('bob')"
3735
3735
3736 - search tracked file contents with xargs and grep::
3736 - search tracked file contents with xargs and grep::
3737
3737
3738 hg files -0 | xargs -0 grep foo
3738 hg files -0 | xargs -0 grep foo
3739
3739
3740 See :hg:`help patterns` and :hg:`help filesets` for more information
3740 See :hg:`help patterns` and :hg:`help filesets` for more information
3741 on specifying file patterns.
3741 on specifying file patterns.
3742
3742
3743 Returns 0 if a match is found, 1 otherwise.
3743 Returns 0 if a match is found, 1 otherwise.
3744
3744
3745 """
3745 """
3746 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3746 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3747
3747
3748 end = '\n'
3748 end = '\n'
3749 if opts.get('print0'):
3749 if opts.get('print0'):
3750 end = '\0'
3750 end = '\0'
3751 fm = ui.formatter('files', opts)
3751 fm = ui.formatter('files', opts)
3752 fmt = '%s' + end
3752 fmt = '%s' + end
3753
3753
3754 m = scmutil.match(ctx, pats, opts)
3754 m = scmutil.match(ctx, pats, opts)
3755 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3755 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3756
3756
3757 fm.end()
3757 fm.end()
3758
3758
3759 return ret
3759 return ret
3760
3760
3761 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3761 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3762 def forget(ui, repo, *pats, **opts):
3762 def forget(ui, repo, *pats, **opts):
3763 """forget the specified files on the next commit
3763 """forget the specified files on the next commit
3764
3764
3765 Mark the specified files so they will no longer be tracked
3765 Mark the specified files so they will no longer be tracked
3766 after the next commit.
3766 after the next commit.
3767
3767
3768 This only removes files from the current branch, not from the
3768 This only removes files from the current branch, not from the
3769 entire project history, and it does not delete them from the
3769 entire project history, and it does not delete them from the
3770 working directory.
3770 working directory.
3771
3771
3772 To delete the file from the working directory, see :hg:`remove`.
3772 To delete the file from the working directory, see :hg:`remove`.
3773
3773
3774 To undo a forget before the next commit, see :hg:`add`.
3774 To undo a forget before the next commit, see :hg:`add`.
3775
3775
3776 .. container:: verbose
3776 .. container:: verbose
3777
3777
3778 Examples:
3778 Examples:
3779
3779
3780 - forget newly-added binary files::
3780 - forget newly-added binary files::
3781
3781
3782 hg forget "set:added() and binary()"
3782 hg forget "set:added() and binary()"
3783
3783
3784 - forget files that would be excluded by .hgignore::
3784 - forget files that would be excluded by .hgignore::
3785
3785
3786 hg forget "set:hgignore()"
3786 hg forget "set:hgignore()"
3787
3787
3788 Returns 0 on success.
3788 Returns 0 on success.
3789 """
3789 """
3790
3790
3791 if not pats:
3791 if not pats:
3792 raise error.Abort(_('no files specified'))
3792 raise error.Abort(_('no files specified'))
3793
3793
3794 m = scmutil.match(repo[None], pats, opts)
3794 m = scmutil.match(repo[None], pats, opts)
3795 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3795 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3796 return rejected and 1 or 0
3796 return rejected and 1 or 0
3797
3797
3798 @command(
3798 @command(
3799 'graft',
3799 'graft',
3800 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3800 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3801 ('c', 'continue', False, _('resume interrupted graft')),
3801 ('c', 'continue', False, _('resume interrupted graft')),
3802 ('e', 'edit', False, _('invoke editor on commit messages')),
3802 ('e', 'edit', False, _('invoke editor on commit messages')),
3803 ('', 'log', None, _('append graft info to log message')),
3803 ('', 'log', None, _('append graft info to log message')),
3804 ('f', 'force', False, _('force graft')),
3804 ('f', 'force', False, _('force graft')),
3805 ('D', 'currentdate', False,
3805 ('D', 'currentdate', False,
3806 _('record the current date as commit date')),
3806 _('record the current date as commit date')),
3807 ('U', 'currentuser', False,
3807 ('U', 'currentuser', False,
3808 _('record the current user as committer'), _('DATE'))]
3808 _('record the current user as committer'), _('DATE'))]
3809 + commitopts2 + mergetoolopts + dryrunopts,
3809 + commitopts2 + mergetoolopts + dryrunopts,
3810 _('[OPTION]... [-r] REV...'))
3810 _('[OPTION]... [-r] REV...'))
3811 def graft(ui, repo, *revs, **opts):
3811 def graft(ui, repo, *revs, **opts):
3812 '''copy changes from other branches onto the current branch
3812 '''copy changes from other branches onto the current branch
3813
3813
3814 This command uses Mercurial's merge logic to copy individual
3814 This command uses Mercurial's merge logic to copy individual
3815 changes from other branches without merging branches in the
3815 changes from other branches without merging branches in the
3816 history graph. This is sometimes known as 'backporting' or
3816 history graph. This is sometimes known as 'backporting' or
3817 'cherry-picking'. By default, graft will copy user, date, and
3817 'cherry-picking'. By default, graft will copy user, date, and
3818 description from the source changesets.
3818 description from the source changesets.
3819
3819
3820 Changesets that are ancestors of the current revision, that have
3820 Changesets that are ancestors of the current revision, that have
3821 already been grafted, or that are merges will be skipped.
3821 already been grafted, or that are merges will be skipped.
3822
3822
3823 If --log is specified, log messages will have a comment appended
3823 If --log is specified, log messages will have a comment appended
3824 of the form::
3824 of the form::
3825
3825
3826 (grafted from CHANGESETHASH)
3826 (grafted from CHANGESETHASH)
3827
3827
3828 If --force is specified, revisions will be grafted even if they
3828 If --force is specified, revisions will be grafted even if they
3829 are already ancestors of or have been grafted to the destination.
3829 are already ancestors of or have been grafted to the destination.
3830 This is useful when the revisions have since been backed out.
3830 This is useful when the revisions have since been backed out.
3831
3831
3832 If a graft merge results in conflicts, the graft process is
3832 If a graft merge results in conflicts, the graft process is
3833 interrupted so that the current merge can be manually resolved.
3833 interrupted so that the current merge can be manually resolved.
3834 Once all conflicts are addressed, the graft process can be
3834 Once all conflicts are addressed, the graft process can be
3835 continued with the -c/--continue option.
3835 continued with the -c/--continue option.
3836
3836
3837 .. note::
3837 .. note::
3838
3838
3839 The -c/--continue option does not reapply earlier options, except
3839 The -c/--continue option does not reapply earlier options, except
3840 for --force.
3840 for --force.
3841
3841
3842 .. container:: verbose
3842 .. container:: verbose
3843
3843
3844 Examples:
3844 Examples:
3845
3845
3846 - copy a single change to the stable branch and edit its description::
3846 - copy a single change to the stable branch and edit its description::
3847
3847
3848 hg update stable
3848 hg update stable
3849 hg graft --edit 9393
3849 hg graft --edit 9393
3850
3850
3851 - graft a range of changesets with one exception, updating dates::
3851 - graft a range of changesets with one exception, updating dates::
3852
3852
3853 hg graft -D "2085::2093 and not 2091"
3853 hg graft -D "2085::2093 and not 2091"
3854
3854
3855 - continue a graft after resolving conflicts::
3855 - continue a graft after resolving conflicts::
3856
3856
3857 hg graft -c
3857 hg graft -c
3858
3858
3859 - show the source of a grafted changeset::
3859 - show the source of a grafted changeset::
3860
3860
3861 hg log --debug -r .
3861 hg log --debug -r .
3862
3862
3863 - show revisions sorted by date::
3863 - show revisions sorted by date::
3864
3864
3865 hg log -r 'sort(all(), date)'
3865 hg log -r 'sort(all(), date)'
3866
3866
3867 See :hg:`help revisions` and :hg:`help revsets` for more about
3867 See :hg:`help revisions` and :hg:`help revsets` for more about
3868 specifying revisions.
3868 specifying revisions.
3869
3869
3870 Returns 0 on successful completion.
3870 Returns 0 on successful completion.
3871 '''
3871 '''
3872 with repo.wlock():
3872 with repo.wlock():
3873 return _dograft(ui, repo, *revs, **opts)
3873 return _dograft(ui, repo, *revs, **opts)
3874
3874
3875 def _dograft(ui, repo, *revs, **opts):
3875 def _dograft(ui, repo, *revs, **opts):
3876 revs = list(revs)
3876 revs = list(revs)
3877 revs.extend(opts['rev'])
3877 revs.extend(opts['rev'])
3878
3878
3879 if not opts.get('user') and opts.get('currentuser'):
3879 if not opts.get('user') and opts.get('currentuser'):
3880 opts['user'] = ui.username()
3880 opts['user'] = ui.username()
3881 if not opts.get('date') and opts.get('currentdate'):
3881 if not opts.get('date') and opts.get('currentdate'):
3882 opts['date'] = "%d %d" % util.makedate()
3882 opts['date'] = "%d %d" % util.makedate()
3883
3883
3884 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3884 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3885
3885
3886 cont = False
3886 cont = False
3887 if opts['continue']:
3887 if opts['continue']:
3888 cont = True
3888 cont = True
3889 if revs:
3889 if revs:
3890 raise error.Abort(_("can't specify --continue and revisions"))
3890 raise error.Abort(_("can't specify --continue and revisions"))
3891 # read in unfinished revisions
3891 # read in unfinished revisions
3892 try:
3892 try:
3893 nodes = repo.vfs.read('graftstate').splitlines()
3893 nodes = repo.vfs.read('graftstate').splitlines()
3894 revs = [repo[node].rev() for node in nodes]
3894 revs = [repo[node].rev() for node in nodes]
3895 except IOError as inst:
3895 except IOError as inst:
3896 if inst.errno != errno.ENOENT:
3896 if inst.errno != errno.ENOENT:
3897 raise
3897 raise
3898 raise error.Abort(_("no graft state found, can't continue"))
3898 raise error.Abort(_("no graft state found, can't continue"))
3899 else:
3899 else:
3900 cmdutil.checkunfinished(repo)
3900 cmdutil.checkunfinished(repo)
3901 cmdutil.bailifchanged(repo)
3901 cmdutil.bailifchanged(repo)
3902 if not revs:
3902 if not revs:
3903 raise error.Abort(_('no revisions specified'))
3903 raise error.Abort(_('no revisions specified'))
3904 revs = scmutil.revrange(repo, revs)
3904 revs = scmutil.revrange(repo, revs)
3905
3905
3906 skipped = set()
3906 skipped = set()
3907 # check for merges
3907 # check for merges
3908 for rev in repo.revs('%ld and merge()', revs):
3908 for rev in repo.revs('%ld and merge()', revs):
3909 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3909 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3910 skipped.add(rev)
3910 skipped.add(rev)
3911 revs = [r for r in revs if r not in skipped]
3911 revs = [r for r in revs if r not in skipped]
3912 if not revs:
3912 if not revs:
3913 return -1
3913 return -1
3914
3914
3915 # Don't check in the --continue case, in effect retaining --force across
3915 # Don't check in the --continue case, in effect retaining --force across
3916 # --continues. That's because without --force, any revisions we decided to
3916 # --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
3917 # 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
3918 # 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
3919 # skipped would not have been filtered out, and if they hadn't been applied
3920 # already, they'd have been in the graftstate.
3920 # already, they'd have been in the graftstate.
3921 if not (cont or opts.get('force')):
3921 if not (cont or opts.get('force')):
3922 # check for ancestors of dest branch
3922 # check for ancestors of dest branch
3923 crev = repo['.'].rev()
3923 crev = repo['.'].rev()
3924 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3924 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3925 # Cannot use x.remove(y) on smart set, this has to be a list.
3925 # Cannot use x.remove(y) on smart set, this has to be a list.
3926 # XXX make this lazy in the future
3926 # XXX make this lazy in the future
3927 revs = list(revs)
3927 revs = list(revs)
3928 # don't mutate while iterating, create a copy
3928 # don't mutate while iterating, create a copy
3929 for rev in list(revs):
3929 for rev in list(revs):
3930 if rev in ancestors:
3930 if rev in ancestors:
3931 ui.warn(_('skipping ancestor revision %d:%s\n') %
3931 ui.warn(_('skipping ancestor revision %d:%s\n') %
3932 (rev, repo[rev]))
3932 (rev, repo[rev]))
3933 # XXX remove on list is slow
3933 # XXX remove on list is slow
3934 revs.remove(rev)
3934 revs.remove(rev)
3935 if not revs:
3935 if not revs:
3936 return -1
3936 return -1
3937
3937
3938 # analyze revs for earlier grafts
3938 # analyze revs for earlier grafts
3939 ids = {}
3939 ids = {}
3940 for ctx in repo.set("%ld", revs):
3940 for ctx in repo.set("%ld", revs):
3941 ids[ctx.hex()] = ctx.rev()
3941 ids[ctx.hex()] = ctx.rev()
3942 n = ctx.extra().get('source')
3942 n = ctx.extra().get('source')
3943 if n:
3943 if n:
3944 ids[n] = ctx.rev()
3944 ids[n] = ctx.rev()
3945
3945
3946 # check ancestors for earlier grafts
3946 # check ancestors for earlier grafts
3947 ui.debug('scanning for duplicate grafts\n')
3947 ui.debug('scanning for duplicate grafts\n')
3948
3948
3949 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3949 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3950 ctx = repo[rev]
3950 ctx = repo[rev]
3951 n = ctx.extra().get('source')
3951 n = ctx.extra().get('source')
3952 if n in ids:
3952 if n in ids:
3953 try:
3953 try:
3954 r = repo[n].rev()
3954 r = repo[n].rev()
3955 except error.RepoLookupError:
3955 except error.RepoLookupError:
3956 r = None
3956 r = None
3957 if r in revs:
3957 if r in revs:
3958 ui.warn(_('skipping revision %d:%s '
3958 ui.warn(_('skipping revision %d:%s '
3959 '(already grafted to %d:%s)\n')
3959 '(already grafted to %d:%s)\n')
3960 % (r, repo[r], rev, ctx))
3960 % (r, repo[r], rev, ctx))
3961 revs.remove(r)
3961 revs.remove(r)
3962 elif ids[n] in revs:
3962 elif ids[n] in revs:
3963 if r is None:
3963 if r is None:
3964 ui.warn(_('skipping already grafted revision %d:%s '
3964 ui.warn(_('skipping already grafted revision %d:%s '
3965 '(%d:%s also has unknown origin %s)\n')
3965 '(%d:%s also has unknown origin %s)\n')
3966 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3966 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3967 else:
3967 else:
3968 ui.warn(_('skipping already grafted revision %d:%s '
3968 ui.warn(_('skipping already grafted revision %d:%s '
3969 '(%d:%s also has origin %d:%s)\n')
3969 '(%d:%s also has origin %d:%s)\n')
3970 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3970 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3971 revs.remove(ids[n])
3971 revs.remove(ids[n])
3972 elif ctx.hex() in ids:
3972 elif ctx.hex() in ids:
3973 r = ids[ctx.hex()]
3973 r = ids[ctx.hex()]
3974 ui.warn(_('skipping already grafted revision %d:%s '
3974 ui.warn(_('skipping already grafted revision %d:%s '
3975 '(was grafted from %d:%s)\n') %
3975 '(was grafted from %d:%s)\n') %
3976 (r, repo[r], rev, ctx))
3976 (r, repo[r], rev, ctx))
3977 revs.remove(r)
3977 revs.remove(r)
3978 if not revs:
3978 if not revs:
3979 return -1
3979 return -1
3980
3980
3981 for pos, ctx in enumerate(repo.set("%ld", revs)):
3981 for pos, ctx in enumerate(repo.set("%ld", revs)):
3982 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3982 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3983 ctx.description().split('\n', 1)[0])
3983 ctx.description().split('\n', 1)[0])
3984 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3984 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3985 if names:
3985 if names:
3986 desc += ' (%s)' % ' '.join(names)
3986 desc += ' (%s)' % ' '.join(names)
3987 ui.status(_('grafting %s\n') % desc)
3987 ui.status(_('grafting %s\n') % desc)
3988 if opts.get('dry_run'):
3988 if opts.get('dry_run'):
3989 continue
3989 continue
3990
3990
3991 extra = ctx.extra().copy()
3991 extra = ctx.extra().copy()
3992 del extra['branch']
3992 del extra['branch']
3993 source = extra.get('source')
3993 source = extra.get('source')
3994 if source:
3994 if source:
3995 extra['intermediate-source'] = ctx.hex()
3995 extra['intermediate-source'] = ctx.hex()
3996 else:
3996 else:
3997 extra['source'] = ctx.hex()
3997 extra['source'] = ctx.hex()
3998 user = ctx.user()
3998 user = ctx.user()
3999 if opts.get('user'):
3999 if opts.get('user'):
4000 user = opts['user']
4000 user = opts['user']
4001 date = ctx.date()
4001 date = ctx.date()
4002 if opts.get('date'):
4002 if opts.get('date'):
4003 date = opts['date']
4003 date = opts['date']
4004 message = ctx.description()
4004 message = ctx.description()
4005 if opts.get('log'):
4005 if opts.get('log'):
4006 message += '\n(grafted from %s)' % ctx.hex()
4006 message += '\n(grafted from %s)' % ctx.hex()
4007
4007
4008 # we don't merge the first commit when continuing
4008 # we don't merge the first commit when continuing
4009 if not cont:
4009 if not cont:
4010 # perform the graft merge with p1(rev) as 'ancestor'
4010 # perform the graft merge with p1(rev) as 'ancestor'
4011 try:
4011 try:
4012 # ui.forcemerge is an internal variable, do not document
4012 # ui.forcemerge is an internal variable, do not document
4013 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4013 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4014 'graft')
4014 'graft')
4015 stats = mergemod.graft(repo, ctx, ctx.p1(),
4015 stats = mergemod.graft(repo, ctx, ctx.p1(),
4016 ['local', 'graft'])
4016 ['local', 'graft'])
4017 finally:
4017 finally:
4018 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4018 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4019 # report any conflicts
4019 # report any conflicts
4020 if stats and stats[3] > 0:
4020 if stats and stats[3] > 0:
4021 # write out state for --continue
4021 # write out state for --continue
4022 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4022 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4023 repo.vfs.write('graftstate', ''.join(nodelines))
4023 repo.vfs.write('graftstate', ''.join(nodelines))
4024 extra = ''
4024 extra = ''
4025 if opts.get('user'):
4025 if opts.get('user'):
4026 extra += ' --user %s' % opts['user']
4026 extra += ' --user %s' % opts['user']
4027 if opts.get('date'):
4027 if opts.get('date'):
4028 extra += ' --date %s' % opts['date']
4028 extra += ' --date %s' % opts['date']
4029 if opts.get('log'):
4029 if opts.get('log'):
4030 extra += ' --log'
4030 extra += ' --log'
4031 hint=_('use hg resolve and hg graft --continue%s') % extra
4031 hint=_('use hg resolve and hg graft --continue%s') % extra
4032 raise error.Abort(
4032 raise error.Abort(
4033 _("unresolved conflicts, can't continue"),
4033 _("unresolved conflicts, can't continue"),
4034 hint=hint)
4034 hint=hint)
4035 else:
4035 else:
4036 cont = False
4036 cont = False
4037
4037
4038 # commit
4038 # commit
4039 node = repo.commit(text=message, user=user,
4039 node = repo.commit(text=message, user=user,
4040 date=date, extra=extra, editor=editor)
4040 date=date, extra=extra, editor=editor)
4041 if node is None:
4041 if node is None:
4042 ui.warn(
4042 ui.warn(
4043 _('note: graft of %d:%s created no changes to commit\n') %
4043 _('note: graft of %d:%s created no changes to commit\n') %
4044 (ctx.rev(), ctx))
4044 (ctx.rev(), ctx))
4045
4045
4046 # remove state when we complete successfully
4046 # remove state when we complete successfully
4047 if not opts.get('dry_run'):
4047 if not opts.get('dry_run'):
4048 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4048 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4049
4049
4050 return 0
4050 return 0
4051
4051
4052 @command('grep',
4052 @command('grep',
4053 [('0', 'print0', None, _('end fields with NUL')),
4053 [('0', 'print0', None, _('end fields with NUL')),
4054 ('', 'all', None, _('print all revisions that match')),
4054 ('', 'all', None, _('print all revisions that match')),
4055 ('a', 'text', None, _('treat all files as text')),
4055 ('a', 'text', None, _('treat all files as text')),
4056 ('f', 'follow', None,
4056 ('f', 'follow', None,
4057 _('follow changeset history,'
4057 _('follow changeset history,'
4058 ' or file history across copies and renames')),
4058 ' or file history across copies and renames')),
4059 ('i', 'ignore-case', None, _('ignore case when matching')),
4059 ('i', 'ignore-case', None, _('ignore case when matching')),
4060 ('l', 'files-with-matches', None,
4060 ('l', 'files-with-matches', None,
4061 _('print only filenames and revisions that match')),
4061 _('print only filenames and revisions that match')),
4062 ('n', 'line-number', None, _('print matching line numbers')),
4062 ('n', 'line-number', None, _('print matching line numbers')),
4063 ('r', 'rev', [],
4063 ('r', 'rev', [],
4064 _('only search files changed within revision range'), _('REV')),
4064 _('only search files changed within revision range'), _('REV')),
4065 ('u', 'user', None, _('list the author (long with -v)')),
4065 ('u', 'user', None, _('list the author (long with -v)')),
4066 ('d', 'date', None, _('list the date (short with -q)')),
4066 ('d', 'date', None, _('list the date (short with -q)')),
4067 ] + walkopts,
4067 ] + walkopts,
4068 _('[OPTION]... PATTERN [FILE]...'),
4068 _('[OPTION]... PATTERN [FILE]...'),
4069 inferrepo=True)
4069 inferrepo=True)
4070 def grep(ui, repo, pattern, *pats, **opts):
4070 def grep(ui, repo, pattern, *pats, **opts):
4071 """search for a pattern in specified files and revisions
4071 """search for a pattern in specified files and revisions
4072
4072
4073 Search revisions of files for a regular expression.
4073 Search revisions of files for a regular expression.
4074
4074
4075 This command behaves differently than Unix grep. It only accepts
4075 This command behaves differently than Unix grep. It only accepts
4076 Python/Perl regexps. It searches repository history, not the
4076 Python/Perl regexps. It searches repository history, not the
4077 working directory. It always prints the revision number in which a
4077 working directory. It always prints the revision number in which a
4078 match appears.
4078 match appears.
4079
4079
4080 By default, grep only prints output for the first revision of a
4080 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
4081 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
4082 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),
4083 becomes a non-match, or "+" for a non-match that becomes a match),
4084 use the --all flag.
4084 use the --all flag.
4085
4085
4086 Returns 0 if a match is found, 1 otherwise.
4086 Returns 0 if a match is found, 1 otherwise.
4087 """
4087 """
4088 reflags = re.M
4088 reflags = re.M
4089 if opts.get('ignore_case'):
4089 if opts.get('ignore_case'):
4090 reflags |= re.I
4090 reflags |= re.I
4091 try:
4091 try:
4092 regexp = util.re.compile(pattern, reflags)
4092 regexp = util.re.compile(pattern, reflags)
4093 except re.error as inst:
4093 except re.error as inst:
4094 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4094 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4095 return 1
4095 return 1
4096 sep, eol = ':', '\n'
4096 sep, eol = ':', '\n'
4097 if opts.get('print0'):
4097 if opts.get('print0'):
4098 sep = eol = '\0'
4098 sep = eol = '\0'
4099
4099
4100 getfile = util.lrucachefunc(repo.file)
4100 getfile = util.lrucachefunc(repo.file)
4101
4101
4102 def matchlines(body):
4102 def matchlines(body):
4103 begin = 0
4103 begin = 0
4104 linenum = 0
4104 linenum = 0
4105 while begin < len(body):
4105 while begin < len(body):
4106 match = regexp.search(body, begin)
4106 match = regexp.search(body, begin)
4107 if not match:
4107 if not match:
4108 break
4108 break
4109 mstart, mend = match.span()
4109 mstart, mend = match.span()
4110 linenum += body.count('\n', begin, mstart) + 1
4110 linenum += body.count('\n', begin, mstart) + 1
4111 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4111 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4112 begin = body.find('\n', mend) + 1 or len(body) + 1
4112 begin = body.find('\n', mend) + 1 or len(body) + 1
4113 lend = begin - 1
4113 lend = begin - 1
4114 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4114 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4115
4115
4116 class linestate(object):
4116 class linestate(object):
4117 def __init__(self, line, linenum, colstart, colend):
4117 def __init__(self, line, linenum, colstart, colend):
4118 self.line = line
4118 self.line = line
4119 self.linenum = linenum
4119 self.linenum = linenum
4120 self.colstart = colstart
4120 self.colstart = colstart
4121 self.colend = colend
4121 self.colend = colend
4122
4122
4123 def __hash__(self):
4123 def __hash__(self):
4124 return hash((self.linenum, self.line))
4124 return hash((self.linenum, self.line))
4125
4125
4126 def __eq__(self, other):
4126 def __eq__(self, other):
4127 return self.line == other.line
4127 return self.line == other.line
4128
4128
4129 def __iter__(self):
4129 def __iter__(self):
4130 yield (self.line[:self.colstart], '')
4130 yield (self.line[:self.colstart], '')
4131 yield (self.line[self.colstart:self.colend], 'grep.match')
4131 yield (self.line[self.colstart:self.colend], 'grep.match')
4132 rest = self.line[self.colend:]
4132 rest = self.line[self.colend:]
4133 while rest != '':
4133 while rest != '':
4134 match = regexp.search(rest)
4134 match = regexp.search(rest)
4135 if not match:
4135 if not match:
4136 yield (rest, '')
4136 yield (rest, '')
4137 break
4137 break
4138 mstart, mend = match.span()
4138 mstart, mend = match.span()
4139 yield (rest[:mstart], '')
4139 yield (rest[:mstart], '')
4140 yield (rest[mstart:mend], 'grep.match')
4140 yield (rest[mstart:mend], 'grep.match')
4141 rest = rest[mend:]
4141 rest = rest[mend:]
4142
4142
4143 matches = {}
4143 matches = {}
4144 copies = {}
4144 copies = {}
4145 def grepbody(fn, rev, body):
4145 def grepbody(fn, rev, body):
4146 matches[rev].setdefault(fn, [])
4146 matches[rev].setdefault(fn, [])
4147 m = matches[rev][fn]
4147 m = matches[rev][fn]
4148 for lnum, cstart, cend, line in matchlines(body):
4148 for lnum, cstart, cend, line in matchlines(body):
4149 s = linestate(line, lnum, cstart, cend)
4149 s = linestate(line, lnum, cstart, cend)
4150 m.append(s)
4150 m.append(s)
4151
4151
4152 def difflinestates(a, b):
4152 def difflinestates(a, b):
4153 sm = difflib.SequenceMatcher(None, a, b)
4153 sm = difflib.SequenceMatcher(None, a, b)
4154 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4154 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4155 if tag == 'insert':
4155 if tag == 'insert':
4156 for i in xrange(blo, bhi):
4156 for i in xrange(blo, bhi):
4157 yield ('+', b[i])
4157 yield ('+', b[i])
4158 elif tag == 'delete':
4158 elif tag == 'delete':
4159 for i in xrange(alo, ahi):
4159 for i in xrange(alo, ahi):
4160 yield ('-', a[i])
4160 yield ('-', a[i])
4161 elif tag == 'replace':
4161 elif tag == 'replace':
4162 for i in xrange(alo, ahi):
4162 for i in xrange(alo, ahi):
4163 yield ('-', a[i])
4163 yield ('-', a[i])
4164 for i in xrange(blo, bhi):
4164 for i in xrange(blo, bhi):
4165 yield ('+', b[i])
4165 yield ('+', b[i])
4166
4166
4167 def display(fn, ctx, pstates, states):
4167 def display(fn, ctx, pstates, states):
4168 rev = ctx.rev()
4168 rev = ctx.rev()
4169 if ui.quiet:
4169 if ui.quiet:
4170 datefunc = util.shortdate
4170 datefunc = util.shortdate
4171 else:
4171 else:
4172 datefunc = util.datestr
4172 datefunc = util.datestr
4173 found = False
4173 found = False
4174 @util.cachefunc
4174 @util.cachefunc
4175 def binary():
4175 def binary():
4176 flog = getfile(fn)
4176 flog = getfile(fn)
4177 return util.binary(flog.read(ctx.filenode(fn)))
4177 return util.binary(flog.read(ctx.filenode(fn)))
4178
4178
4179 if opts.get('all'):
4179 if opts.get('all'):
4180 iter = difflinestates(pstates, states)
4180 iter = difflinestates(pstates, states)
4181 else:
4181 else:
4182 iter = [('', l) for l in states]
4182 iter = [('', l) for l in states]
4183 for change, l in iter:
4183 for change, l in iter:
4184 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4184 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4185
4185
4186 if opts.get('line_number'):
4186 if opts.get('line_number'):
4187 cols.append((str(l.linenum), 'grep.linenumber'))
4187 cols.append((str(l.linenum), 'grep.linenumber'))
4188 if opts.get('all'):
4188 if opts.get('all'):
4189 cols.append((change, 'grep.change'))
4189 cols.append((change, 'grep.change'))
4190 if opts.get('user'):
4190 if opts.get('user'):
4191 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4191 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4192 if opts.get('date'):
4192 if opts.get('date'):
4193 cols.append((datefunc(ctx.date()), 'grep.date'))
4193 cols.append((datefunc(ctx.date()), 'grep.date'))
4194 for col, label in cols[:-1]:
4194 for col, label in cols[:-1]:
4195 ui.write(col, label=label)
4195 ui.write(col, label=label)
4196 ui.write(sep, label='grep.sep')
4196 ui.write(sep, label='grep.sep')
4197 ui.write(cols[-1][0], label=cols[-1][1])
4197 ui.write(cols[-1][0], label=cols[-1][1])
4198 if not opts.get('files_with_matches'):
4198 if not opts.get('files_with_matches'):
4199 ui.write(sep, label='grep.sep')
4199 ui.write(sep, label='grep.sep')
4200 if not opts.get('text') and binary():
4200 if not opts.get('text') and binary():
4201 ui.write(" Binary file matches")
4201 ui.write(" Binary file matches")
4202 else:
4202 else:
4203 for s, label in l:
4203 for s, label in l:
4204 ui.write(s, label=label)
4204 ui.write(s, label=label)
4205 ui.write(eol)
4205 ui.write(eol)
4206 found = True
4206 found = True
4207 if opts.get('files_with_matches'):
4207 if opts.get('files_with_matches'):
4208 break
4208 break
4209 return found
4209 return found
4210
4210
4211 skip = {}
4211 skip = {}
4212 revfiles = {}
4212 revfiles = {}
4213 matchfn = scmutil.match(repo[None], pats, opts)
4213 matchfn = scmutil.match(repo[None], pats, opts)
4214 found = False
4214 found = False
4215 follow = opts.get('follow')
4215 follow = opts.get('follow')
4216
4216
4217 def prep(ctx, fns):
4217 def prep(ctx, fns):
4218 rev = ctx.rev()
4218 rev = ctx.rev()
4219 pctx = ctx.p1()
4219 pctx = ctx.p1()
4220 parent = pctx.rev()
4220 parent = pctx.rev()
4221 matches.setdefault(rev, {})
4221 matches.setdefault(rev, {})
4222 matches.setdefault(parent, {})
4222 matches.setdefault(parent, {})
4223 files = revfiles.setdefault(rev, [])
4223 files = revfiles.setdefault(rev, [])
4224 for fn in fns:
4224 for fn in fns:
4225 flog = getfile(fn)
4225 flog = getfile(fn)
4226 try:
4226 try:
4227 fnode = ctx.filenode(fn)
4227 fnode = ctx.filenode(fn)
4228 except error.LookupError:
4228 except error.LookupError:
4229 continue
4229 continue
4230
4230
4231 copied = flog.renamed(fnode)
4231 copied = flog.renamed(fnode)
4232 copy = follow and copied and copied[0]
4232 copy = follow and copied and copied[0]
4233 if copy:
4233 if copy:
4234 copies.setdefault(rev, {})[fn] = copy
4234 copies.setdefault(rev, {})[fn] = copy
4235 if fn in skip:
4235 if fn in skip:
4236 if copy:
4236 if copy:
4237 skip[copy] = True
4237 skip[copy] = True
4238 continue
4238 continue
4239 files.append(fn)
4239 files.append(fn)
4240
4240
4241 if fn not in matches[rev]:
4241 if fn not in matches[rev]:
4242 grepbody(fn, rev, flog.read(fnode))
4242 grepbody(fn, rev, flog.read(fnode))
4243
4243
4244 pfn = copy or fn
4244 pfn = copy or fn
4245 if pfn not in matches[parent]:
4245 if pfn not in matches[parent]:
4246 try:
4246 try:
4247 fnode = pctx.filenode(pfn)
4247 fnode = pctx.filenode(pfn)
4248 grepbody(pfn, parent, flog.read(fnode))
4248 grepbody(pfn, parent, flog.read(fnode))
4249 except error.LookupError:
4249 except error.LookupError:
4250 pass
4250 pass
4251
4251
4252 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4252 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4253 rev = ctx.rev()
4253 rev = ctx.rev()
4254 parent = ctx.p1().rev()
4254 parent = ctx.p1().rev()
4255 for fn in sorted(revfiles.get(rev, [])):
4255 for fn in sorted(revfiles.get(rev, [])):
4256 states = matches[rev][fn]
4256 states = matches[rev][fn]
4257 copy = copies.get(rev, {}).get(fn)
4257 copy = copies.get(rev, {}).get(fn)
4258 if fn in skip:
4258 if fn in skip:
4259 if copy:
4259 if copy:
4260 skip[copy] = True
4260 skip[copy] = True
4261 continue
4261 continue
4262 pstates = matches.get(parent, {}).get(copy or fn, [])
4262 pstates = matches.get(parent, {}).get(copy or fn, [])
4263 if pstates or states:
4263 if pstates or states:
4264 r = display(fn, ctx, pstates, states)
4264 r = display(fn, ctx, pstates, states)
4265 found = found or r
4265 found = found or r
4266 if r and not opts.get('all'):
4266 if r and not opts.get('all'):
4267 skip[fn] = True
4267 skip[fn] = True
4268 if copy:
4268 if copy:
4269 skip[copy] = True
4269 skip[copy] = True
4270 del matches[rev]
4270 del matches[rev]
4271 del revfiles[rev]
4271 del revfiles[rev]
4272
4272
4273 return not found
4273 return not found
4274
4274
4275 @command('heads',
4275 @command('heads',
4276 [('r', 'rev', '',
4276 [('r', 'rev', '',
4277 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4277 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4278 ('t', 'topo', False, _('show topological heads only')),
4278 ('t', 'topo', False, _('show topological heads only')),
4279 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4279 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4280 ('c', 'closed', False, _('show normal and closed branch heads')),
4280 ('c', 'closed', False, _('show normal and closed branch heads')),
4281 ] + templateopts,
4281 ] + templateopts,
4282 _('[-ct] [-r STARTREV] [REV]...'))
4282 _('[-ct] [-r STARTREV] [REV]...'))
4283 def heads(ui, repo, *branchrevs, **opts):
4283 def heads(ui, repo, *branchrevs, **opts):
4284 """show branch heads
4284 """show branch heads
4285
4285
4286 With no arguments, show all open branch heads in the repository.
4286 With no arguments, show all open branch heads in the repository.
4287 Branch heads are changesets that have no descendants on the
4287 Branch heads are changesets that have no descendants on the
4288 same branch. They are where development generally takes place and
4288 same branch. They are where development generally takes place and
4289 are the usual targets for update and merge operations.
4289 are the usual targets for update and merge operations.
4290
4290
4291 If one or more REVs are given, only open branch heads on the
4291 If one or more REVs are given, only open branch heads on the
4292 branches associated with the specified changesets are shown. This
4292 branches associated with the specified changesets are shown. This
4293 means that you can use :hg:`heads .` to see the heads on the
4293 means that you can use :hg:`heads .` to see the heads on the
4294 currently checked-out branch.
4294 currently checked-out branch.
4295
4295
4296 If -c/--closed is specified, also show branch heads marked closed
4296 If -c/--closed is specified, also show branch heads marked closed
4297 (see :hg:`commit --close-branch`).
4297 (see :hg:`commit --close-branch`).
4298
4298
4299 If STARTREV is specified, only those heads that are descendants of
4299 If STARTREV is specified, only those heads that are descendants of
4300 STARTREV will be displayed.
4300 STARTREV will be displayed.
4301
4301
4302 If -t/--topo is specified, named branch mechanics will be ignored and only
4302 If -t/--topo is specified, named branch mechanics will be ignored and only
4303 topological heads (changesets with no children) will be shown.
4303 topological heads (changesets with no children) will be shown.
4304
4304
4305 Returns 0 if matching heads are found, 1 if not.
4305 Returns 0 if matching heads are found, 1 if not.
4306 """
4306 """
4307
4307
4308 start = None
4308 start = None
4309 if 'rev' in opts:
4309 if 'rev' in opts:
4310 start = scmutil.revsingle(repo, opts['rev'], None).node()
4310 start = scmutil.revsingle(repo, opts['rev'], None).node()
4311
4311
4312 if opts.get('topo'):
4312 if opts.get('topo'):
4313 heads = [repo[h] for h in repo.heads(start)]
4313 heads = [repo[h] for h in repo.heads(start)]
4314 else:
4314 else:
4315 heads = []
4315 heads = []
4316 for branch in repo.branchmap():
4316 for branch in repo.branchmap():
4317 heads += repo.branchheads(branch, start, opts.get('closed'))
4317 heads += repo.branchheads(branch, start, opts.get('closed'))
4318 heads = [repo[h] for h in heads]
4318 heads = [repo[h] for h in heads]
4319
4319
4320 if branchrevs:
4320 if branchrevs:
4321 branches = set(repo[br].branch() for br in branchrevs)
4321 branches = set(repo[br].branch() for br in branchrevs)
4322 heads = [h for h in heads if h.branch() in branches]
4322 heads = [h for h in heads if h.branch() in branches]
4323
4323
4324 if opts.get('active') and branchrevs:
4324 if opts.get('active') and branchrevs:
4325 dagheads = repo.heads(start)
4325 dagheads = repo.heads(start)
4326 heads = [h for h in heads if h.node() in dagheads]
4326 heads = [h for h in heads if h.node() in dagheads]
4327
4327
4328 if branchrevs:
4328 if branchrevs:
4329 haveheads = set(h.branch() for h in heads)
4329 haveheads = set(h.branch() for h in heads)
4330 if branches - haveheads:
4330 if branches - haveheads:
4331 headless = ', '.join(b for b in branches - haveheads)
4331 headless = ', '.join(b for b in branches - haveheads)
4332 msg = _('no open branch heads found on branches %s')
4332 msg = _('no open branch heads found on branches %s')
4333 if opts.get('rev'):
4333 if opts.get('rev'):
4334 msg += _(' (started at %s)') % opts['rev']
4334 msg += _(' (started at %s)') % opts['rev']
4335 ui.warn((msg + '\n') % headless)
4335 ui.warn((msg + '\n') % headless)
4336
4336
4337 if not heads:
4337 if not heads:
4338 return 1
4338 return 1
4339
4339
4340 heads = sorted(heads, key=lambda x: -x.rev())
4340 heads = sorted(heads, key=lambda x: -x.rev())
4341 displayer = cmdutil.show_changeset(ui, repo, opts)
4341 displayer = cmdutil.show_changeset(ui, repo, opts)
4342 for ctx in heads:
4342 for ctx in heads:
4343 displayer.show(ctx)
4343 displayer.show(ctx)
4344 displayer.close()
4344 displayer.close()
4345
4345
4346 @command('help',
4346 @command('help',
4347 [('e', 'extension', None, _('show only help for extensions')),
4347 [('e', 'extension', None, _('show only help for extensions')),
4348 ('c', 'command', None, _('show only help for commands')),
4348 ('c', 'command', None, _('show only help for commands')),
4349 ('k', 'keyword', None, _('show topics matching keyword')),
4349 ('k', 'keyword', None, _('show topics matching keyword')),
4350 ('s', 'system', [], _('show help for specific platform(s)')),
4350 ('s', 'system', [], _('show help for specific platform(s)')),
4351 ],
4351 ],
4352 _('[-ecks] [TOPIC]'),
4352 _('[-ecks] [TOPIC]'),
4353 norepo=True)
4353 norepo=True)
4354 def help_(ui, name=None, **opts):
4354 def help_(ui, name=None, **opts):
4355 """show help for a given topic or a help overview
4355 """show help for a given topic or a help overview
4356
4356
4357 With no arguments, print a list of commands with short help messages.
4357 With no arguments, print a list of commands with short help messages.
4358
4358
4359 Given a topic, extension, or command name, print help for that
4359 Given a topic, extension, or command name, print help for that
4360 topic.
4360 topic.
4361
4361
4362 Returns 0 if successful.
4362 Returns 0 if successful.
4363 """
4363 """
4364
4364
4365 textwidth = min(ui.termwidth(), 80) - 2
4365 textwidth = min(ui.termwidth(), 80) - 2
4366
4366
4367 keep = opts.get('system') or []
4367 keep = opts.get('system') or []
4368 if len(keep) == 0:
4368 if len(keep) == 0:
4369 if sys.platform.startswith('win'):
4369 if sys.platform.startswith('win'):
4370 keep.append('windows')
4370 keep.append('windows')
4371 elif sys.platform == 'OpenVMS':
4371 elif sys.platform == 'OpenVMS':
4372 keep.append('vms')
4372 keep.append('vms')
4373 elif sys.platform == 'plan9':
4373 elif sys.platform == 'plan9':
4374 keep.append('plan9')
4374 keep.append('plan9')
4375 else:
4375 else:
4376 keep.append('unix')
4376 keep.append('unix')
4377 keep.append(sys.platform.lower())
4377 keep.append(sys.platform.lower())
4378 if ui.verbose:
4378 if ui.verbose:
4379 keep.append('verbose')
4379 keep.append('verbose')
4380
4380
4381 section = None
4381 section = None
4382 subtopic = None
4382 subtopic = None
4383 if name and '.' in name:
4383 if name and '.' in name:
4384 name, section = name.split('.', 1)
4384 name, section = name.split('.', 1)
4385 section = section.lower()
4385 section = section.lower()
4386 if '.' in section:
4386 if '.' in section:
4387 subtopic, section = section.split('.', 1)
4387 subtopic, section = section.split('.', 1)
4388 else:
4388 else:
4389 subtopic = section
4389 subtopic = section
4390
4390
4391 text = help.help_(ui, name, subtopic=subtopic, **opts)
4391 text = help.help_(ui, name, subtopic=subtopic, **opts)
4392
4392
4393 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4393 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4394 section=section)
4394 section=section)
4395
4395
4396 # We could have been given a weird ".foo" section without a name
4396 # 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"
4397 # to look for, or we could have simply failed to found "foo.bar"
4398 # because bar isn't a section of foo
4398 # because bar isn't a section of foo
4399 if section and not (formatted and name):
4399 if section and not (formatted and name):
4400 raise error.Abort(_("help section not found"))
4400 raise error.Abort(_("help section not found"))
4401
4401
4402 if 'verbose' in pruned:
4402 if 'verbose' in pruned:
4403 keep.append('omitted')
4403 keep.append('omitted')
4404 else:
4404 else:
4405 keep.append('notomitted')
4405 keep.append('notomitted')
4406 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4406 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4407 section=section)
4407 section=section)
4408 ui.write(formatted)
4408 ui.write(formatted)
4409
4409
4410
4410
4411 @command('identify|id',
4411 @command('identify|id',
4412 [('r', 'rev', '',
4412 [('r', 'rev', '',
4413 _('identify the specified revision'), _('REV')),
4413 _('identify the specified revision'), _('REV')),
4414 ('n', 'num', None, _('show local revision number')),
4414 ('n', 'num', None, _('show local revision number')),
4415 ('i', 'id', None, _('show global revision id')),
4415 ('i', 'id', None, _('show global revision id')),
4416 ('b', 'branch', None, _('show branch')),
4416 ('b', 'branch', None, _('show branch')),
4417 ('t', 'tags', None, _('show tags')),
4417 ('t', 'tags', None, _('show tags')),
4418 ('B', 'bookmarks', None, _('show bookmarks')),
4418 ('B', 'bookmarks', None, _('show bookmarks')),
4419 ] + remoteopts,
4419 ] + remoteopts,
4420 _('[-nibtB] [-r REV] [SOURCE]'),
4420 _('[-nibtB] [-r REV] [SOURCE]'),
4421 optionalrepo=True)
4421 optionalrepo=True)
4422 def identify(ui, repo, source=None, rev=None,
4422 def identify(ui, repo, source=None, rev=None,
4423 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4423 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4424 """identify the working directory or specified revision
4424 """identify the working directory or specified revision
4425
4425
4426 Print a summary identifying the repository state at REV using one or
4426 Print a summary identifying the repository state at REV using one or
4427 two parent hash identifiers, followed by a "+" if the working
4427 two parent hash identifiers, followed by a "+" if the working
4428 directory has uncommitted changes, the branch name (if not default),
4428 directory has uncommitted changes, the branch name (if not default),
4429 a list of tags, and a list of bookmarks.
4429 a list of tags, and a list of bookmarks.
4430
4430
4431 When REV is not given, print a summary of the current state of the
4431 When REV is not given, print a summary of the current state of the
4432 repository.
4432 repository.
4433
4433
4434 Specifying a path to a repository root or Mercurial bundle will
4434 Specifying a path to a repository root or Mercurial bundle will
4435 cause lookup to operate on that repository/bundle.
4435 cause lookup to operate on that repository/bundle.
4436
4436
4437 .. container:: verbose
4437 .. container:: verbose
4438
4438
4439 Examples:
4439 Examples:
4440
4440
4441 - generate a build identifier for the working directory::
4441 - generate a build identifier for the working directory::
4442
4442
4443 hg id --id > build-id.dat
4443 hg id --id > build-id.dat
4444
4444
4445 - find the revision corresponding to a tag::
4445 - find the revision corresponding to a tag::
4446
4446
4447 hg id -n -r 1.3
4447 hg id -n -r 1.3
4448
4448
4449 - check the most recent revision of a remote repository::
4449 - check the most recent revision of a remote repository::
4450
4450
4451 hg id -r tip http://selenic.com/hg/
4451 hg id -r tip http://selenic.com/hg/
4452
4452
4453 See :hg:`log` for generating more information about specific revisions,
4453 See :hg:`log` for generating more information about specific revisions,
4454 including full hash identifiers.
4454 including full hash identifiers.
4455
4455
4456 Returns 0 if successful.
4456 Returns 0 if successful.
4457 """
4457 """
4458
4458
4459 if not repo and not source:
4459 if not repo and not source:
4460 raise error.Abort(_("there is no Mercurial repository here "
4460 raise error.Abort(_("there is no Mercurial repository here "
4461 "(.hg not found)"))
4461 "(.hg not found)"))
4462
4462
4463 if ui.debugflag:
4463 if ui.debugflag:
4464 hexfunc = hex
4464 hexfunc = hex
4465 else:
4465 else:
4466 hexfunc = short
4466 hexfunc = short
4467 default = not (num or id or branch or tags or bookmarks)
4467 default = not (num or id or branch or tags or bookmarks)
4468 output = []
4468 output = []
4469 revs = []
4469 revs = []
4470
4470
4471 if source:
4471 if source:
4472 source, branches = hg.parseurl(ui.expandpath(source))
4472 source, branches = hg.parseurl(ui.expandpath(source))
4473 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4473 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4474 repo = peer.local()
4474 repo = peer.local()
4475 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4475 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4476
4476
4477 if not repo:
4477 if not repo:
4478 if num or branch or tags:
4478 if num or branch or tags:
4479 raise error.Abort(
4479 raise error.Abort(
4480 _("can't query remote revision number, branch, or tags"))
4480 _("can't query remote revision number, branch, or tags"))
4481 if not rev and revs:
4481 if not rev and revs:
4482 rev = revs[0]
4482 rev = revs[0]
4483 if not rev:
4483 if not rev:
4484 rev = "tip"
4484 rev = "tip"
4485
4485
4486 remoterev = peer.lookup(rev)
4486 remoterev = peer.lookup(rev)
4487 if default or id:
4487 if default or id:
4488 output = [hexfunc(remoterev)]
4488 output = [hexfunc(remoterev)]
4489
4489
4490 def getbms():
4490 def getbms():
4491 bms = []
4491 bms = []
4492
4492
4493 if 'bookmarks' in peer.listkeys('namespaces'):
4493 if 'bookmarks' in peer.listkeys('namespaces'):
4494 hexremoterev = hex(remoterev)
4494 hexremoterev = hex(remoterev)
4495 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4495 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4496 if bmr == hexremoterev]
4496 if bmr == hexremoterev]
4497
4497
4498 return sorted(bms)
4498 return sorted(bms)
4499
4499
4500 if bookmarks:
4500 if bookmarks:
4501 output.extend(getbms())
4501 output.extend(getbms())
4502 elif default and not ui.quiet:
4502 elif default and not ui.quiet:
4503 # multiple bookmarks for a single parent separated by '/'
4503 # multiple bookmarks for a single parent separated by '/'
4504 bm = '/'.join(getbms())
4504 bm = '/'.join(getbms())
4505 if bm:
4505 if bm:
4506 output.append(bm)
4506 output.append(bm)
4507 else:
4507 else:
4508 ctx = scmutil.revsingle(repo, rev, None)
4508 ctx = scmutil.revsingle(repo, rev, None)
4509
4509
4510 if ctx.rev() is None:
4510 if ctx.rev() is None:
4511 ctx = repo[None]
4511 ctx = repo[None]
4512 parents = ctx.parents()
4512 parents = ctx.parents()
4513 taglist = []
4513 taglist = []
4514 for p in parents:
4514 for p in parents:
4515 taglist.extend(p.tags())
4515 taglist.extend(p.tags())
4516
4516
4517 changed = ""
4517 changed = ""
4518 if default or id or num:
4518 if default or id or num:
4519 if (any(repo.status())
4519 if (any(repo.status())
4520 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4520 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4521 changed = '+'
4521 changed = '+'
4522 if default or id:
4522 if default or id:
4523 output = ["%s%s" %
4523 output = ["%s%s" %
4524 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4524 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4525 if num:
4525 if num:
4526 output.append("%s%s" %
4526 output.append("%s%s" %
4527 ('+'.join([str(p.rev()) for p in parents]), changed))
4527 ('+'.join([str(p.rev()) for p in parents]), changed))
4528 else:
4528 else:
4529 if default or id:
4529 if default or id:
4530 output = [hexfunc(ctx.node())]
4530 output = [hexfunc(ctx.node())]
4531 if num:
4531 if num:
4532 output.append(str(ctx.rev()))
4532 output.append(str(ctx.rev()))
4533 taglist = ctx.tags()
4533 taglist = ctx.tags()
4534
4534
4535 if default and not ui.quiet:
4535 if default and not ui.quiet:
4536 b = ctx.branch()
4536 b = ctx.branch()
4537 if b != 'default':
4537 if b != 'default':
4538 output.append("(%s)" % b)
4538 output.append("(%s)" % b)
4539
4539
4540 # multiple tags for a single parent separated by '/'
4540 # multiple tags for a single parent separated by '/'
4541 t = '/'.join(taglist)
4541 t = '/'.join(taglist)
4542 if t:
4542 if t:
4543 output.append(t)
4543 output.append(t)
4544
4544
4545 # multiple bookmarks for a single parent separated by '/'
4545 # multiple bookmarks for a single parent separated by '/'
4546 bm = '/'.join(ctx.bookmarks())
4546 bm = '/'.join(ctx.bookmarks())
4547 if bm:
4547 if bm:
4548 output.append(bm)
4548 output.append(bm)
4549 else:
4549 else:
4550 if branch:
4550 if branch:
4551 output.append(ctx.branch())
4551 output.append(ctx.branch())
4552
4552
4553 if tags:
4553 if tags:
4554 output.extend(taglist)
4554 output.extend(taglist)
4555
4555
4556 if bookmarks:
4556 if bookmarks:
4557 output.extend(ctx.bookmarks())
4557 output.extend(ctx.bookmarks())
4558
4558
4559 ui.write("%s\n" % ' '.join(output))
4559 ui.write("%s\n" % ' '.join(output))
4560
4560
4561 @command('import|patch',
4561 @command('import|patch',
4562 [('p', 'strip', 1,
4562 [('p', 'strip', 1,
4563 _('directory strip option for patch. This has the same '
4563 _('directory strip option for patch. This has the same '
4564 'meaning as the corresponding patch option'), _('NUM')),
4564 'meaning as the corresponding patch option'), _('NUM')),
4565 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4565 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4566 ('e', 'edit', False, _('invoke editor on commit messages')),
4566 ('e', 'edit', False, _('invoke editor on commit messages')),
4567 ('f', 'force', None,
4567 ('f', 'force', None,
4568 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4568 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4569 ('', 'no-commit', None,
4569 ('', 'no-commit', None,
4570 _("don't commit, just update the working directory")),
4570 _("don't commit, just update the working directory")),
4571 ('', 'bypass', None,
4571 ('', 'bypass', None,
4572 _("apply patch without touching the working directory")),
4572 _("apply patch without touching the working directory")),
4573 ('', 'partial', None,
4573 ('', 'partial', None,
4574 _('commit even if some hunks fail')),
4574 _('commit even if some hunks fail')),
4575 ('', 'exact', None,
4575 ('', 'exact', None,
4576 _('apply patch to the nodes from which it was generated')),
4576 _('apply patch to the nodes from which it was generated')),
4577 ('', 'prefix', '',
4577 ('', 'prefix', '',
4578 _('apply patch to subdirectory'), _('DIR')),
4578 _('apply patch to subdirectory'), _('DIR')),
4579 ('', 'import-branch', None,
4579 ('', 'import-branch', None,
4580 _('use any branch information in patch (implied by --exact)'))] +
4580 _('use any branch information in patch (implied by --exact)'))] +
4581 commitopts + commitopts2 + similarityopts,
4581 commitopts + commitopts2 + similarityopts,
4582 _('[OPTION]... PATCH...'))
4582 _('[OPTION]... PATCH...'))
4583 def import_(ui, repo, patch1=None, *patches, **opts):
4583 def import_(ui, repo, patch1=None, *patches, **opts):
4584 """import an ordered set of patches
4584 """import an ordered set of patches
4585
4585
4586 Import a list of patches and commit them individually (unless
4586 Import a list of patches and commit them individually (unless
4587 --no-commit is specified).
4587 --no-commit is specified).
4588
4588
4589 To read a patch from standard input, use "-" as the patch name. If
4589 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.
4590 a URL is specified, the patch will be downloaded from there.
4591
4591
4592 Import first applies changes to the working directory (unless
4592 Import first applies changes to the working directory (unless
4593 --bypass is specified), import will abort if there are outstanding
4593 --bypass is specified), import will abort if there are outstanding
4594 changes.
4594 changes.
4595
4595
4596 Use --bypass to apply and commit patches directly to the
4596 Use --bypass to apply and commit patches directly to the
4597 repository, without affecting the working directory. Without
4597 repository, without affecting the working directory. Without
4598 --exact, patches will be applied on top of the working directory
4598 --exact, patches will be applied on top of the working directory
4599 parent revision.
4599 parent revision.
4600
4600
4601 You can import a patch straight from a mail message. Even patches
4601 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
4602 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
4603 text/plain or text/x-patch). From and Subject headers of email
4604 message are used as default committer and commit message. All
4604 message are used as default committer and commit message. All
4605 text/plain body parts before first diff are added to the commit
4605 text/plain body parts before first diff are added to the commit
4606 message.
4606 message.
4607
4607
4608 If the imported patch was generated by :hg:`export`, user and
4608 If the imported patch was generated by :hg:`export`, user and
4609 description from patch override values from message headers and
4609 description from patch override values from message headers and
4610 body. Values given on command line with -m/--message and -u/--user
4610 body. Values given on command line with -m/--message and -u/--user
4611 override these.
4611 override these.
4612
4612
4613 If --exact is specified, import will set the working directory to
4613 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
4614 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
4615 resulting changeset has a different ID than the one recorded in
4616 the patch. This may happen due to character set problems or other
4616 the patch. This may happen due to character set problems or other
4617 deficiencies in the text patch format.
4617 deficiencies in the text patch format.
4618
4618
4619 Use --partial to ensure a changeset will be created from the patch
4619 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
4620 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
4621 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
4622 by hand before :hg:`commit --amend` is run to update the created
4623 changeset. This flag exists to let people import patches that
4623 changeset. This flag exists to let people import patches that
4624 partially apply without losing the associated metadata (author,
4624 partially apply without losing the associated metadata (author,
4625 date, description, ...).
4625 date, description, ...).
4626
4626
4627 .. note::
4627 .. note::
4628
4628
4629 When no hunks apply cleanly, :hg:`import --partial` will create
4629 When no hunks apply cleanly, :hg:`import --partial` will create
4630 an empty changeset, importing only the patch metadata.
4630 an empty changeset, importing only the patch metadata.
4631
4631
4632 With -s/--similarity, hg will attempt to discover renames and
4632 With -s/--similarity, hg will attempt to discover renames and
4633 copies in the patch in the same way as :hg:`addremove`.
4633 copies in the patch in the same way as :hg:`addremove`.
4634
4634
4635 It is possible to use external patch programs to perform the patch
4635 It is possible to use external patch programs to perform the patch
4636 by setting the ``ui.patch`` configuration option. For the default
4636 by setting the ``ui.patch`` configuration option. For the default
4637 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4637 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4638 See :hg:`help config` for more information about configuration
4638 See :hg:`help config` for more information about configuration
4639 files and how to use these options.
4639 files and how to use these options.
4640
4640
4641 See :hg:`help dates` for a list of formats valid for -d/--date.
4641 See :hg:`help dates` for a list of formats valid for -d/--date.
4642
4642
4643 .. container:: verbose
4643 .. container:: verbose
4644
4644
4645 Examples:
4645 Examples:
4646
4646
4647 - import a traditional patch from a website and detect renames::
4647 - import a traditional patch from a website and detect renames::
4648
4648
4649 hg import -s 80 http://example.com/bugfix.patch
4649 hg import -s 80 http://example.com/bugfix.patch
4650
4650
4651 - import a changeset from an hgweb server::
4651 - import a changeset from an hgweb server::
4652
4652
4653 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4653 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4654
4654
4655 - import all the patches in an Unix-style mbox::
4655 - import all the patches in an Unix-style mbox::
4656
4656
4657 hg import incoming-patches.mbox
4657 hg import incoming-patches.mbox
4658
4658
4659 - attempt to exactly restore an exported changeset (not always
4659 - attempt to exactly restore an exported changeset (not always
4660 possible)::
4660 possible)::
4661
4661
4662 hg import --exact proposed-fix.patch
4662 hg import --exact proposed-fix.patch
4663
4663
4664 - use an external tool to apply a patch which is too fuzzy for
4664 - use an external tool to apply a patch which is too fuzzy for
4665 the default internal tool.
4665 the default internal tool.
4666
4666
4667 hg import --config ui.patch="patch --merge" fuzzy.patch
4667 hg import --config ui.patch="patch --merge" fuzzy.patch
4668
4668
4669 - change the default fuzzing from 2 to a less strict 7
4669 - change the default fuzzing from 2 to a less strict 7
4670
4670
4671 hg import --config ui.fuzz=7 fuzz.patch
4671 hg import --config ui.fuzz=7 fuzz.patch
4672
4672
4673 Returns 0 on success, 1 on partial success (see --partial).
4673 Returns 0 on success, 1 on partial success (see --partial).
4674 """
4674 """
4675
4675
4676 if not patch1:
4676 if not patch1:
4677 raise error.Abort(_('need at least one patch to import'))
4677 raise error.Abort(_('need at least one patch to import'))
4678
4678
4679 patches = (patch1,) + patches
4679 patches = (patch1,) + patches
4680
4680
4681 date = opts.get('date')
4681 date = opts.get('date')
4682 if date:
4682 if date:
4683 opts['date'] = util.parsedate(date)
4683 opts['date'] = util.parsedate(date)
4684
4684
4685 exact = opts.get('exact')
4685 exact = opts.get('exact')
4686 update = not opts.get('bypass')
4686 update = not opts.get('bypass')
4687 if not update and opts.get('no_commit'):
4687 if not update and opts.get('no_commit'):
4688 raise error.Abort(_('cannot use --no-commit with --bypass'))
4688 raise error.Abort(_('cannot use --no-commit with --bypass'))
4689 try:
4689 try:
4690 sim = float(opts.get('similarity') or 0)
4690 sim = float(opts.get('similarity') or 0)
4691 except ValueError:
4691 except ValueError:
4692 raise error.Abort(_('similarity must be a number'))
4692 raise error.Abort(_('similarity must be a number'))
4693 if sim < 0 or sim > 100:
4693 if sim < 0 or sim > 100:
4694 raise error.Abort(_('similarity must be between 0 and 100'))
4694 raise error.Abort(_('similarity must be between 0 and 100'))
4695 if sim and not update:
4695 if sim and not update:
4696 raise error.Abort(_('cannot use --similarity with --bypass'))
4696 raise error.Abort(_('cannot use --similarity with --bypass'))
4697 if exact:
4697 if exact:
4698 if opts.get('edit'):
4698 if opts.get('edit'):
4699 raise error.Abort(_('cannot use --exact with --edit'))
4699 raise error.Abort(_('cannot use --exact with --edit'))
4700 if opts.get('prefix'):
4700 if opts.get('prefix'):
4701 raise error.Abort(_('cannot use --exact with --prefix'))
4701 raise error.Abort(_('cannot use --exact with --prefix'))
4702
4702
4703 base = opts["base"]
4703 base = opts["base"]
4704 wlock = dsguard = lock = tr = None
4704 wlock = dsguard = lock = tr = None
4705 msgs = []
4705 msgs = []
4706 ret = 0
4706 ret = 0
4707
4707
4708
4708
4709 try:
4709 try:
4710 wlock = repo.wlock()
4710 wlock = repo.wlock()
4711
4711
4712 if update:
4712 if update:
4713 cmdutil.checkunfinished(repo)
4713 cmdutil.checkunfinished(repo)
4714 if (exact or not opts.get('force')):
4714 if (exact or not opts.get('force')):
4715 cmdutil.bailifchanged(repo)
4715 cmdutil.bailifchanged(repo)
4716
4716
4717 if not opts.get('no_commit'):
4717 if not opts.get('no_commit'):
4718 lock = repo.lock()
4718 lock = repo.lock()
4719 tr = repo.transaction('import')
4719 tr = repo.transaction('import')
4720 else:
4720 else:
4721 dsguard = cmdutil.dirstateguard(repo, 'import')
4721 dsguard = cmdutil.dirstateguard(repo, 'import')
4722 parents = repo[None].parents()
4722 parents = repo[None].parents()
4723 for patchurl in patches:
4723 for patchurl in patches:
4724 if patchurl == '-':
4724 if patchurl == '-':
4725 ui.status(_('applying patch from stdin\n'))
4725 ui.status(_('applying patch from stdin\n'))
4726 patchfile = ui.fin
4726 patchfile = ui.fin
4727 patchurl = 'stdin' # for error message
4727 patchurl = 'stdin' # for error message
4728 else:
4728 else:
4729 patchurl = os.path.join(base, patchurl)
4729 patchurl = os.path.join(base, patchurl)
4730 ui.status(_('applying %s\n') % patchurl)
4730 ui.status(_('applying %s\n') % patchurl)
4731 patchfile = hg.openpath(ui, patchurl)
4731 patchfile = hg.openpath(ui, patchurl)
4732
4732
4733 haspatch = False
4733 haspatch = False
4734 for hunk in patch.split(patchfile):
4734 for hunk in patch.split(patchfile):
4735 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4735 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4736 parents, opts,
4736 parents, opts,
4737 msgs, hg.clean)
4737 msgs, hg.clean)
4738 if msg:
4738 if msg:
4739 haspatch = True
4739 haspatch = True
4740 ui.note(msg + '\n')
4740 ui.note(msg + '\n')
4741 if update or exact:
4741 if update or exact:
4742 parents = repo[None].parents()
4742 parents = repo[None].parents()
4743 else:
4743 else:
4744 parents = [repo[node]]
4744 parents = [repo[node]]
4745 if rej:
4745 if rej:
4746 ui.write_err(_("patch applied partially\n"))
4746 ui.write_err(_("patch applied partially\n"))
4747 ui.write_err(_("(fix the .rej files and run "
4747 ui.write_err(_("(fix the .rej files and run "
4748 "`hg commit --amend`)\n"))
4748 "`hg commit --amend`)\n"))
4749 ret = 1
4749 ret = 1
4750 break
4750 break
4751
4751
4752 if not haspatch:
4752 if not haspatch:
4753 raise error.Abort(_('%s: no diffs found') % patchurl)
4753 raise error.Abort(_('%s: no diffs found') % patchurl)
4754
4754
4755 if tr:
4755 if tr:
4756 tr.close()
4756 tr.close()
4757 if msgs:
4757 if msgs:
4758 repo.savecommitmessage('\n* * *\n'.join(msgs))
4758 repo.savecommitmessage('\n* * *\n'.join(msgs))
4759 if dsguard:
4759 if dsguard:
4760 dsguard.close()
4760 dsguard.close()
4761 return ret
4761 return ret
4762 finally:
4762 finally:
4763 if tr:
4763 if tr:
4764 tr.release()
4764 tr.release()
4765 release(lock, dsguard, wlock)
4765 release(lock, dsguard, wlock)
4766
4766
4767 @command('incoming|in',
4767 @command('incoming|in',
4768 [('f', 'force', None,
4768 [('f', 'force', None,
4769 _('run even if remote repository is unrelated')),
4769 _('run even if remote repository is unrelated')),
4770 ('n', 'newest-first', None, _('show newest record first')),
4770 ('n', 'newest-first', None, _('show newest record first')),
4771 ('', 'bundle', '',
4771 ('', 'bundle', '',
4772 _('file to store the bundles into'), _('FILE')),
4772 _('file to store the bundles into'), _('FILE')),
4773 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4773 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4774 ('B', 'bookmarks', False, _("compare bookmarks")),
4774 ('B', 'bookmarks', False, _("compare bookmarks")),
4775 ('b', 'branch', [],
4775 ('b', 'branch', [],
4776 _('a specific branch you would like to pull'), _('BRANCH')),
4776 _('a specific branch you would like to pull'), _('BRANCH')),
4777 ] + logopts + remoteopts + subrepoopts,
4777 ] + logopts + remoteopts + subrepoopts,
4778 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4778 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4779 def incoming(ui, repo, source="default", **opts):
4779 def incoming(ui, repo, source="default", **opts):
4780 """show new changesets found in source
4780 """show new changesets found in source
4781
4781
4782 Show new changesets found in the specified path/URL or the default
4782 Show new changesets found in the specified path/URL or the default
4783 pull location. These are the changesets that would have been pulled
4783 pull location. These are the changesets that would have been pulled
4784 if a pull at the time you issued this command.
4784 if a pull at the time you issued this command.
4785
4785
4786 See pull for valid source format details.
4786 See pull for valid source format details.
4787
4787
4788 .. container:: verbose
4788 .. container:: verbose
4789
4789
4790 With -B/--bookmarks, the result of bookmark comparison between
4790 With -B/--bookmarks, the result of bookmark comparison between
4791 local and remote repositories is displayed. With -v/--verbose,
4791 local and remote repositories is displayed. With -v/--verbose,
4792 status is also displayed for each bookmark like below::
4792 status is also displayed for each bookmark like below::
4793
4793
4794 BM1 01234567890a added
4794 BM1 01234567890a added
4795 BM2 1234567890ab advanced
4795 BM2 1234567890ab advanced
4796 BM3 234567890abc diverged
4796 BM3 234567890abc diverged
4797 BM4 34567890abcd changed
4797 BM4 34567890abcd changed
4798
4798
4799 The action taken locally when pulling depends on the
4799 The action taken locally when pulling depends on the
4800 status of each bookmark:
4800 status of each bookmark:
4801
4801
4802 :``added``: pull will create it
4802 :``added``: pull will create it
4803 :``advanced``: pull will update it
4803 :``advanced``: pull will update it
4804 :``diverged``: pull will create a divergent bookmark
4804 :``diverged``: pull will create a divergent bookmark
4805 :``changed``: result depends on remote changesets
4805 :``changed``: result depends on remote changesets
4806
4806
4807 From the point of view of pulling behavior, bookmark
4807 From the point of view of pulling behavior, bookmark
4808 existing only in the remote repository are treated as ``added``,
4808 existing only in the remote repository are treated as ``added``,
4809 even if it is in fact locally deleted.
4809 even if it is in fact locally deleted.
4810
4810
4811 .. container:: verbose
4811 .. container:: verbose
4812
4812
4813 For remote repository, using --bundle avoids downloading the
4813 For remote repository, using --bundle avoids downloading the
4814 changesets twice if the incoming is followed by a pull.
4814 changesets twice if the incoming is followed by a pull.
4815
4815
4816 Examples:
4816 Examples:
4817
4817
4818 - show incoming changes with patches and full description::
4818 - show incoming changes with patches and full description::
4819
4819
4820 hg incoming -vp
4820 hg incoming -vp
4821
4821
4822 - show incoming changes excluding merges, store a bundle::
4822 - show incoming changes excluding merges, store a bundle::
4823
4823
4824 hg in -vpM --bundle incoming.hg
4824 hg in -vpM --bundle incoming.hg
4825 hg pull incoming.hg
4825 hg pull incoming.hg
4826
4826
4827 - briefly list changes inside a bundle::
4827 - briefly list changes inside a bundle::
4828
4828
4829 hg in changes.hg -T "{desc|firstline}\\n"
4829 hg in changes.hg -T "{desc|firstline}\\n"
4830
4830
4831 Returns 0 if there are incoming changes, 1 otherwise.
4831 Returns 0 if there are incoming changes, 1 otherwise.
4832 """
4832 """
4833 if opts.get('graph'):
4833 if opts.get('graph'):
4834 cmdutil.checkunsupportedgraphflags([], opts)
4834 cmdutil.checkunsupportedgraphflags([], opts)
4835 def display(other, chlist, displayer):
4835 def display(other, chlist, displayer):
4836 revdag = cmdutil.graphrevs(other, chlist, opts)
4836 revdag = cmdutil.graphrevs(other, chlist, opts)
4837 cmdutil.displaygraph(ui, repo, revdag, displayer,
4837 cmdutil.displaygraph(ui, repo, revdag, displayer,
4838 graphmod.asciiedges)
4838 graphmod.asciiedges)
4839
4839
4840 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4840 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4841 return 0
4841 return 0
4842
4842
4843 if opts.get('bundle') and opts.get('subrepos'):
4843 if opts.get('bundle') and opts.get('subrepos'):
4844 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4844 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4845
4845
4846 if opts.get('bookmarks'):
4846 if opts.get('bookmarks'):
4847 source, branches = hg.parseurl(ui.expandpath(source),
4847 source, branches = hg.parseurl(ui.expandpath(source),
4848 opts.get('branch'))
4848 opts.get('branch'))
4849 other = hg.peer(repo, opts, source)
4849 other = hg.peer(repo, opts, source)
4850 if 'bookmarks' not in other.listkeys('namespaces'):
4850 if 'bookmarks' not in other.listkeys('namespaces'):
4851 ui.warn(_("remote doesn't support bookmarks\n"))
4851 ui.warn(_("remote doesn't support bookmarks\n"))
4852 return 0
4852 return 0
4853 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4853 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4854 return bookmarks.incoming(ui, repo, other)
4854 return bookmarks.incoming(ui, repo, other)
4855
4855
4856 repo._subtoppath = ui.expandpath(source)
4856 repo._subtoppath = ui.expandpath(source)
4857 try:
4857 try:
4858 return hg.incoming(ui, repo, source, opts)
4858 return hg.incoming(ui, repo, source, opts)
4859 finally:
4859 finally:
4860 del repo._subtoppath
4860 del repo._subtoppath
4861
4861
4862
4862
4863 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4863 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4864 norepo=True)
4864 norepo=True)
4865 def init(ui, dest=".", **opts):
4865 def init(ui, dest=".", **opts):
4866 """create a new repository in the given directory
4866 """create a new repository in the given directory
4867
4867
4868 Initialize a new repository in the given directory. If the given
4868 Initialize a new repository in the given directory. If the given
4869 directory does not exist, it will be created.
4869 directory does not exist, it will be created.
4870
4870
4871 If no directory is given, the current directory is used.
4871 If no directory is given, the current directory is used.
4872
4872
4873 It is possible to specify an ``ssh://`` URL as the destination.
4873 It is possible to specify an ``ssh://`` URL as the destination.
4874 See :hg:`help urls` for more information.
4874 See :hg:`help urls` for more information.
4875
4875
4876 Returns 0 on success.
4876 Returns 0 on success.
4877 """
4877 """
4878 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4878 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4879
4879
4880 @command('locate',
4880 @command('locate',
4881 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4881 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4882 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4882 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4883 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4883 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4884 ] + walkopts,
4884 ] + walkopts,
4885 _('[OPTION]... [PATTERN]...'))
4885 _('[OPTION]... [PATTERN]...'))
4886 def locate(ui, repo, *pats, **opts):
4886 def locate(ui, repo, *pats, **opts):
4887 """locate files matching specific patterns (DEPRECATED)
4887 """locate files matching specific patterns (DEPRECATED)
4888
4888
4889 Print files under Mercurial control in the working directory whose
4889 Print files under Mercurial control in the working directory whose
4890 names match the given patterns.
4890 names match the given patterns.
4891
4891
4892 By default, this command searches all directories in the working
4892 By default, this command searches all directories in the working
4893 directory. To search just the current directory and its
4893 directory. To search just the current directory and its
4894 subdirectories, use "--include .".
4894 subdirectories, use "--include .".
4895
4895
4896 If no patterns are given to match, this command prints the names
4896 If no patterns are given to match, this command prints the names
4897 of all files under Mercurial control in the working directory.
4897 of all files under Mercurial control in the working directory.
4898
4898
4899 If you want to feed the output of this command into the "xargs"
4899 If you want to feed the output of this command into the "xargs"
4900 command, use the -0 option to both this command and "xargs". This
4900 command, use the -0 option to both this command and "xargs". This
4901 will avoid the problem of "xargs" treating single filenames that
4901 will avoid the problem of "xargs" treating single filenames that
4902 contain whitespace as multiple filenames.
4902 contain whitespace as multiple filenames.
4903
4903
4904 See :hg:`help files` for a more versatile command.
4904 See :hg:`help files` for a more versatile command.
4905
4905
4906 Returns 0 if a match is found, 1 otherwise.
4906 Returns 0 if a match is found, 1 otherwise.
4907 """
4907 """
4908 if opts.get('print0'):
4908 if opts.get('print0'):
4909 end = '\0'
4909 end = '\0'
4910 else:
4910 else:
4911 end = '\n'
4911 end = '\n'
4912 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4912 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4913
4913
4914 ret = 1
4914 ret = 1
4915 ctx = repo[rev]
4915 ctx = repo[rev]
4916 m = scmutil.match(ctx, pats, opts, default='relglob',
4916 m = scmutil.match(ctx, pats, opts, default='relglob',
4917 badfn=lambda x, y: False)
4917 badfn=lambda x, y: False)
4918
4918
4919 for abs in ctx.matches(m):
4919 for abs in ctx.matches(m):
4920 if opts.get('fullpath'):
4920 if opts.get('fullpath'):
4921 ui.write(repo.wjoin(abs), end)
4921 ui.write(repo.wjoin(abs), end)
4922 else:
4922 else:
4923 ui.write(((pats and m.rel(abs)) or abs), end)
4923 ui.write(((pats and m.rel(abs)) or abs), end)
4924 ret = 0
4924 ret = 0
4925
4925
4926 return ret
4926 return ret
4927
4927
4928 @command('^log|history',
4928 @command('^log|history',
4929 [('f', 'follow', None,
4929 [('f', 'follow', None,
4930 _('follow changeset history, or file history across copies and renames')),
4930 _('follow changeset history, or file history across copies and renames')),
4931 ('', 'follow-first', None,
4931 ('', 'follow-first', None,
4932 _('only follow the first parent of merge changesets (DEPRECATED)')),
4932 _('only follow the first parent of merge changesets (DEPRECATED)')),
4933 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4933 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4934 ('C', 'copies', None, _('show copied files')),
4934 ('C', 'copies', None, _('show copied files')),
4935 ('k', 'keyword', [],
4935 ('k', 'keyword', [],
4936 _('do case-insensitive search for a given text'), _('TEXT')),
4936 _('do case-insensitive search for a given text'), _('TEXT')),
4937 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4937 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4938 ('', 'removed', None, _('include revisions where files were removed')),
4938 ('', 'removed', None, _('include revisions where files were removed')),
4939 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4939 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4940 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4940 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4941 ('', 'only-branch', [],
4941 ('', 'only-branch', [],
4942 _('show only changesets within the given named branch (DEPRECATED)'),
4942 _('show only changesets within the given named branch (DEPRECATED)'),
4943 _('BRANCH')),
4943 _('BRANCH')),
4944 ('b', 'branch', [],
4944 ('b', 'branch', [],
4945 _('show changesets within the given named branch'), _('BRANCH')),
4945 _('show changesets within the given named branch'), _('BRANCH')),
4946 ('P', 'prune', [],
4946 ('P', 'prune', [],
4947 _('do not display revision or any of its ancestors'), _('REV')),
4947 _('do not display revision or any of its ancestors'), _('REV')),
4948 ] + logopts + walkopts,
4948 ] + logopts + walkopts,
4949 _('[OPTION]... [FILE]'),
4949 _('[OPTION]... [FILE]'),
4950 inferrepo=True)
4950 inferrepo=True)
4951 def log(ui, repo, *pats, **opts):
4951 def log(ui, repo, *pats, **opts):
4952 """show revision history of entire repository or files
4952 """show revision history of entire repository or files
4953
4953
4954 Print the revision history of the specified files or the entire
4954 Print the revision history of the specified files or the entire
4955 project.
4955 project.
4956
4956
4957 If no revision range is specified, the default is ``tip:0`` unless
4957 If no revision range is specified, the default is ``tip:0`` unless
4958 --follow is set, in which case the working directory parent is
4958 --follow is set, in which case the working directory parent is
4959 used as the starting revision.
4959 used as the starting revision.
4960
4960
4961 File history is shown without following rename or copy history of
4961 File history is shown without following rename or copy history of
4962 files. Use -f/--follow with a filename to follow history across
4962 files. Use -f/--follow with a filename to follow history across
4963 renames and copies. --follow without a filename will only show
4963 renames and copies. --follow without a filename will only show
4964 ancestors or descendants of the starting revision.
4964 ancestors or descendants of the starting revision.
4965
4965
4966 By default this command prints revision number and changeset id,
4966 By default this command prints revision number and changeset id,
4967 tags, non-trivial parents, user, date and time, and a summary for
4967 tags, non-trivial parents, user, date and time, and a summary for
4968 each commit. When the -v/--verbose switch is used, the list of
4968 each commit. When the -v/--verbose switch is used, the list of
4969 changed files and full commit message are shown.
4969 changed files and full commit message are shown.
4970
4970
4971 With --graph the revisions are shown as an ASCII art DAG with the most
4971 With --graph the revisions are shown as an ASCII art DAG with the most
4972 recent changeset at the top.
4972 recent changeset at the top.
4973 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4973 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4974 and '+' represents a fork where the changeset from the lines below is a
4974 and '+' represents a fork where the changeset from the lines below is a
4975 parent of the 'o' merge on the same line.
4975 parent of the 'o' merge on the same line.
4976
4976
4977 .. note::
4977 .. note::
4978
4978
4979 :hg:`log --patch` may generate unexpected diff output for merge
4979 :hg:`log --patch` may generate unexpected diff output for merge
4980 changesets, as it will only compare the merge changeset against
4980 changesets, as it will only compare the merge changeset against
4981 its first parent. Also, only files different from BOTH parents
4981 its first parent. Also, only files different from BOTH parents
4982 will appear in files:.
4982 will appear in files:.
4983
4983
4984 .. note::
4984 .. note::
4985
4985
4986 For performance reasons, :hg:`log FILE` may omit duplicate changes
4986 For performance reasons, :hg:`log FILE` may omit duplicate changes
4987 made on branches and will not show removals or mode changes. To
4987 made on branches and will not show removals or mode changes. To
4988 see all such changes, use the --removed switch.
4988 see all such changes, use the --removed switch.
4989
4989
4990 .. container:: verbose
4990 .. container:: verbose
4991
4991
4992 Some examples:
4992 Some examples:
4993
4993
4994 - changesets with full descriptions and file lists::
4994 - changesets with full descriptions and file lists::
4995
4995
4996 hg log -v
4996 hg log -v
4997
4997
4998 - changesets ancestral to the working directory::
4998 - changesets ancestral to the working directory::
4999
4999
5000 hg log -f
5000 hg log -f
5001
5001
5002 - last 10 commits on the current branch::
5002 - last 10 commits on the current branch::
5003
5003
5004 hg log -l 10 -b .
5004 hg log -l 10 -b .
5005
5005
5006 - changesets showing all modifications of a file, including removals::
5006 - changesets showing all modifications of a file, including removals::
5007
5007
5008 hg log --removed file.c
5008 hg log --removed file.c
5009
5009
5010 - all changesets that touch a directory, with diffs, excluding merges::
5010 - all changesets that touch a directory, with diffs, excluding merges::
5011
5011
5012 hg log -Mp lib/
5012 hg log -Mp lib/
5013
5013
5014 - all revision numbers that match a keyword::
5014 - all revision numbers that match a keyword::
5015
5015
5016 hg log -k bug --template "{rev}\\n"
5016 hg log -k bug --template "{rev}\\n"
5017
5017
5018 - the full hash identifier of the working directory parent::
5018 - the full hash identifier of the working directory parent::
5019
5019
5020 hg log -r . --template "{node}\\n"
5020 hg log -r . --template "{node}\\n"
5021
5021
5022 - list available log templates::
5022 - list available log templates::
5023
5023
5024 hg log -T list
5024 hg log -T list
5025
5025
5026 - check if a given changeset is included in a tagged release::
5026 - check if a given changeset is included in a tagged release::
5027
5027
5028 hg log -r "a21ccf and ancestor(1.9)"
5028 hg log -r "a21ccf and ancestor(1.9)"
5029
5029
5030 - find all changesets by some user in a date range::
5030 - find all changesets by some user in a date range::
5031
5031
5032 hg log -k alice -d "may 2008 to jul 2008"
5032 hg log -k alice -d "may 2008 to jul 2008"
5033
5033
5034 - summary of all changesets after the last tag::
5034 - summary of all changesets after the last tag::
5035
5035
5036 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5036 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5037
5037
5038 See :hg:`help dates` for a list of formats valid for -d/--date.
5038 See :hg:`help dates` for a list of formats valid for -d/--date.
5039
5039
5040 See :hg:`help revisions` and :hg:`help revsets` for more about
5040 See :hg:`help revisions` and :hg:`help revsets` for more about
5041 specifying and ordering revisions.
5041 specifying and ordering revisions.
5042
5042
5043 See :hg:`help templates` for more about pre-packaged styles and
5043 See :hg:`help templates` for more about pre-packaged styles and
5044 specifying custom templates.
5044 specifying custom templates.
5045
5045
5046 Returns 0 on success.
5046 Returns 0 on success.
5047
5047
5048 """
5048 """
5049 if opts.get('follow') and opts.get('rev'):
5049 if opts.get('follow') and opts.get('rev'):
5050 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5050 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5051 del opts['follow']
5051 del opts['follow']
5052
5052
5053 if opts.get('graph'):
5053 if opts.get('graph'):
5054 return cmdutil.graphlog(ui, repo, *pats, **opts)
5054 return cmdutil.graphlog(ui, repo, *pats, **opts)
5055
5055
5056 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5056 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5057 limit = cmdutil.loglimit(opts)
5057 limit = cmdutil.loglimit(opts)
5058 count = 0
5058 count = 0
5059
5059
5060 getrenamed = None
5060 getrenamed = None
5061 if opts.get('copies'):
5061 if opts.get('copies'):
5062 endrev = None
5062 endrev = None
5063 if opts.get('rev'):
5063 if opts.get('rev'):
5064 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5064 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5065 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5065 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5066
5066
5067 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5067 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5068 for rev in revs:
5068 for rev in revs:
5069 if count == limit:
5069 if count == limit:
5070 break
5070 break
5071 ctx = repo[rev]
5071 ctx = repo[rev]
5072 copies = None
5072 copies = None
5073 if getrenamed is not None and rev:
5073 if getrenamed is not None and rev:
5074 copies = []
5074 copies = []
5075 for fn in ctx.files():
5075 for fn in ctx.files():
5076 rename = getrenamed(fn, rev)
5076 rename = getrenamed(fn, rev)
5077 if rename:
5077 if rename:
5078 copies.append((fn, rename[0]))
5078 copies.append((fn, rename[0]))
5079 if filematcher:
5079 if filematcher:
5080 revmatchfn = filematcher(ctx.rev())
5080 revmatchfn = filematcher(ctx.rev())
5081 else:
5081 else:
5082 revmatchfn = None
5082 revmatchfn = None
5083 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5083 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5084 if displayer.flush(ctx):
5084 if displayer.flush(ctx):
5085 count += 1
5085 count += 1
5086
5086
5087 displayer.close()
5087 displayer.close()
5088
5088
5089 @command('manifest',
5089 @command('manifest',
5090 [('r', 'rev', '', _('revision to display'), _('REV')),
5090 [('r', 'rev', '', _('revision to display'), _('REV')),
5091 ('', 'all', False, _("list files from all revisions"))]
5091 ('', 'all', False, _("list files from all revisions"))]
5092 + formatteropts,
5092 + formatteropts,
5093 _('[-r REV]'))
5093 _('[-r REV]'))
5094 def manifest(ui, repo, node=None, rev=None, **opts):
5094 def manifest(ui, repo, node=None, rev=None, **opts):
5095 """output the current or given revision of the project manifest
5095 """output the current or given revision of the project manifest
5096
5096
5097 Print a list of version controlled files for the given revision.
5097 Print a list of version controlled files for the given revision.
5098 If no revision is given, the first parent of the working directory
5098 If no revision is given, the first parent of the working directory
5099 is used, or the null revision if no revision is checked out.
5099 is used, or the null revision if no revision is checked out.
5100
5100
5101 With -v, print file permissions, symlink and executable bits.
5101 With -v, print file permissions, symlink and executable bits.
5102 With --debug, print file revision hashes.
5102 With --debug, print file revision hashes.
5103
5103
5104 If option --all is specified, the list of all files from all revisions
5104 If option --all is specified, the list of all files from all revisions
5105 is printed. This includes deleted and renamed files.
5105 is printed. This includes deleted and renamed files.
5106
5106
5107 Returns 0 on success.
5107 Returns 0 on success.
5108 """
5108 """
5109
5109
5110 fm = ui.formatter('manifest', opts)
5110 fm = ui.formatter('manifest', opts)
5111
5111
5112 if opts.get('all'):
5112 if opts.get('all'):
5113 if rev or node:
5113 if rev or node:
5114 raise error.Abort(_("can't specify a revision with --all"))
5114 raise error.Abort(_("can't specify a revision with --all"))
5115
5115
5116 res = []
5116 res = []
5117 prefix = "data/"
5117 prefix = "data/"
5118 suffix = ".i"
5118 suffix = ".i"
5119 plen = len(prefix)
5119 plen = len(prefix)
5120 slen = len(suffix)
5120 slen = len(suffix)
5121 lock = repo.lock()
5121 lock = repo.lock()
5122 try:
5122 try:
5123 for fn, b, size in repo.store.datafiles():
5123 for fn, b, size in repo.store.datafiles():
5124 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5124 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5125 res.append(fn[plen:-slen])
5125 res.append(fn[plen:-slen])
5126 finally:
5126 finally:
5127 lock.release()
5127 lock.release()
5128 for f in res:
5128 for f in res:
5129 fm.startitem()
5129 fm.startitem()
5130 fm.write("path", '%s\n', f)
5130 fm.write("path", '%s\n', f)
5131 fm.end()
5131 fm.end()
5132 return
5132 return
5133
5133
5134 if rev and node:
5134 if rev and node:
5135 raise error.Abort(_("please specify just one revision"))
5135 raise error.Abort(_("please specify just one revision"))
5136
5136
5137 if not node:
5137 if not node:
5138 node = rev
5138 node = rev
5139
5139
5140 char = {'l': '@', 'x': '*', '': ''}
5140 char = {'l': '@', 'x': '*', '': ''}
5141 mode = {'l': '644', 'x': '755', '': '644'}
5141 mode = {'l': '644', 'x': '755', '': '644'}
5142 ctx = scmutil.revsingle(repo, node)
5142 ctx = scmutil.revsingle(repo, node)
5143 mf = ctx.manifest()
5143 mf = ctx.manifest()
5144 for f in ctx:
5144 for f in ctx:
5145 fm.startitem()
5145 fm.startitem()
5146 fl = ctx[f].flags()
5146 fl = ctx[f].flags()
5147 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5147 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5148 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5148 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5149 fm.write('path', '%s\n', f)
5149 fm.write('path', '%s\n', f)
5150 fm.end()
5150 fm.end()
5151
5151
5152 @command('^merge',
5152 @command('^merge',
5153 [('f', 'force', None,
5153 [('f', 'force', None,
5154 _('force a merge including outstanding changes (DEPRECATED)')),
5154 _('force a merge including outstanding changes (DEPRECATED)')),
5155 ('r', 'rev', '', _('revision to merge'), _('REV')),
5155 ('r', 'rev', '', _('revision to merge'), _('REV')),
5156 ('P', 'preview', None,
5156 ('P', 'preview', None,
5157 _('review revisions to merge (no merge is performed)'))
5157 _('review revisions to merge (no merge is performed)'))
5158 ] + mergetoolopts,
5158 ] + mergetoolopts,
5159 _('[-P] [-f] [[-r] REV]'))
5159 _('[-P] [-f] [[-r] REV]'))
5160 def merge(ui, repo, node=None, **opts):
5160 def merge(ui, repo, node=None, **opts):
5161 """merge another revision into working directory
5161 """merge another revision into working directory
5162
5162
5163 The current working directory is updated with all changes made in
5163 The current working directory is updated with all changes made in
5164 the requested revision since the last common predecessor revision.
5164 the requested revision since the last common predecessor revision.
5165
5165
5166 Files that changed between either parent are marked as changed for
5166 Files that changed between either parent are marked as changed for
5167 the next commit and a commit must be performed before any further
5167 the next commit and a commit must be performed before any further
5168 updates to the repository are allowed. The next commit will have
5168 updates to the repository are allowed. The next commit will have
5169 two parents.
5169 two parents.
5170
5170
5171 ``--tool`` can be used to specify the merge tool used for file
5171 ``--tool`` can be used to specify the merge tool used for file
5172 merges. It overrides the HGMERGE environment variable and your
5172 merges. It overrides the HGMERGE environment variable and your
5173 configuration files. See :hg:`help merge-tools` for options.
5173 configuration files. See :hg:`help merge-tools` for options.
5174
5174
5175 If no revision is specified, the working directory's parent is a
5175 If no revision is specified, the working directory's parent is a
5176 head revision, and the current branch contains exactly one other
5176 head revision, and the current branch contains exactly one other
5177 head, the other head is merged with by default. Otherwise, an
5177 head, the other head is merged with by default. Otherwise, an
5178 explicit revision with which to merge with must be provided.
5178 explicit revision with which to merge with must be provided.
5179
5179
5180 See :hg:`help resolve` for information on handling file conflicts.
5180 See :hg:`help resolve` for information on handling file conflicts.
5181
5181
5182 To undo an uncommitted merge, use :hg:`update --clean .` which
5182 To undo an uncommitted merge, use :hg:`update --clean .` which
5183 will check out a clean copy of the original merge parent, losing
5183 will check out a clean copy of the original merge parent, losing
5184 all changes.
5184 all changes.
5185
5185
5186 Returns 0 on success, 1 if there are unresolved files.
5186 Returns 0 on success, 1 if there are unresolved files.
5187 """
5187 """
5188
5188
5189 if opts.get('rev') and node:
5189 if opts.get('rev') and node:
5190 raise error.Abort(_("please specify just one revision"))
5190 raise error.Abort(_("please specify just one revision"))
5191 if not node:
5191 if not node:
5192 node = opts.get('rev')
5192 node = opts.get('rev')
5193
5193
5194 if node:
5194 if node:
5195 node = scmutil.revsingle(repo, node).node()
5195 node = scmutil.revsingle(repo, node).node()
5196
5196
5197 if not node:
5197 if not node:
5198 node = repo[destutil.destmerge(repo)].node()
5198 node = repo[destutil.destmerge(repo)].node()
5199
5199
5200 if opts.get('preview'):
5200 if opts.get('preview'):
5201 # find nodes that are ancestors of p2 but not of p1
5201 # find nodes that are ancestors of p2 but not of p1
5202 p1 = repo.lookup('.')
5202 p1 = repo.lookup('.')
5203 p2 = repo.lookup(node)
5203 p2 = repo.lookup(node)
5204 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5204 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5205
5205
5206 displayer = cmdutil.show_changeset(ui, repo, opts)
5206 displayer = cmdutil.show_changeset(ui, repo, opts)
5207 for node in nodes:
5207 for node in nodes:
5208 displayer.show(repo[node])
5208 displayer.show(repo[node])
5209 displayer.close()
5209 displayer.close()
5210 return 0
5210 return 0
5211
5211
5212 try:
5212 try:
5213 # ui.forcemerge is an internal variable, do not document
5213 # ui.forcemerge is an internal variable, do not document
5214 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5214 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5215 return hg.merge(repo, node, force=opts.get('force'))
5215 return hg.merge(repo, node, force=opts.get('force'))
5216 finally:
5216 finally:
5217 ui.setconfig('ui', 'forcemerge', '', 'merge')
5217 ui.setconfig('ui', 'forcemerge', '', 'merge')
5218
5218
5219 @command('outgoing|out',
5219 @command('outgoing|out',
5220 [('f', 'force', None, _('run even when the destination is unrelated')),
5220 [('f', 'force', None, _('run even when the destination is unrelated')),
5221 ('r', 'rev', [],
5221 ('r', 'rev', [],
5222 _('a changeset intended to be included in the destination'), _('REV')),
5222 _('a changeset intended to be included in the destination'), _('REV')),
5223 ('n', 'newest-first', None, _('show newest record first')),
5223 ('n', 'newest-first', None, _('show newest record first')),
5224 ('B', 'bookmarks', False, _('compare bookmarks')),
5224 ('B', 'bookmarks', False, _('compare bookmarks')),
5225 ('b', 'branch', [], _('a specific branch you would like to push'),
5225 ('b', 'branch', [], _('a specific branch you would like to push'),
5226 _('BRANCH')),
5226 _('BRANCH')),
5227 ] + logopts + remoteopts + subrepoopts,
5227 ] + logopts + remoteopts + subrepoopts,
5228 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5228 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5229 def outgoing(ui, repo, dest=None, **opts):
5229 def outgoing(ui, repo, dest=None, **opts):
5230 """show changesets not found in the destination
5230 """show changesets not found in the destination
5231
5231
5232 Show changesets not found in the specified destination repository
5232 Show changesets not found in the specified destination repository
5233 or the default push location. These are the changesets that would
5233 or the default push location. These are the changesets that would
5234 be pushed if a push was requested.
5234 be pushed if a push was requested.
5235
5235
5236 See pull for details of valid destination formats.
5236 See pull for details of valid destination formats.
5237
5237
5238 .. container:: verbose
5238 .. container:: verbose
5239
5239
5240 With -B/--bookmarks, the result of bookmark comparison between
5240 With -B/--bookmarks, the result of bookmark comparison between
5241 local and remote repositories is displayed. With -v/--verbose,
5241 local and remote repositories is displayed. With -v/--verbose,
5242 status is also displayed for each bookmark like below::
5242 status is also displayed for each bookmark like below::
5243
5243
5244 BM1 01234567890a added
5244 BM1 01234567890a added
5245 BM2 deleted
5245 BM2 deleted
5246 BM3 234567890abc advanced
5246 BM3 234567890abc advanced
5247 BM4 34567890abcd diverged
5247 BM4 34567890abcd diverged
5248 BM5 4567890abcde changed
5248 BM5 4567890abcde changed
5249
5249
5250 The action taken when pushing depends on the
5250 The action taken when pushing depends on the
5251 status of each bookmark:
5251 status of each bookmark:
5252
5252
5253 :``added``: push with ``-B`` will create it
5253 :``added``: push with ``-B`` will create it
5254 :``deleted``: push with ``-B`` will delete it
5254 :``deleted``: push with ``-B`` will delete it
5255 :``advanced``: push will update it
5255 :``advanced``: push will update it
5256 :``diverged``: push with ``-B`` will update it
5256 :``diverged``: push with ``-B`` will update it
5257 :``changed``: push with ``-B`` will update it
5257 :``changed``: push with ``-B`` will update it
5258
5258
5259 From the point of view of pushing behavior, bookmarks
5259 From the point of view of pushing behavior, bookmarks
5260 existing only in the remote repository are treated as
5260 existing only in the remote repository are treated as
5261 ``deleted``, even if it is in fact added remotely.
5261 ``deleted``, even if it is in fact added remotely.
5262
5262
5263 Returns 0 if there are outgoing changes, 1 otherwise.
5263 Returns 0 if there are outgoing changes, 1 otherwise.
5264 """
5264 """
5265 if opts.get('graph'):
5265 if opts.get('graph'):
5266 cmdutil.checkunsupportedgraphflags([], opts)
5266 cmdutil.checkunsupportedgraphflags([], opts)
5267 o, other = hg._outgoing(ui, repo, dest, opts)
5267 o, other = hg._outgoing(ui, repo, dest, opts)
5268 if not o:
5268 if not o:
5269 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5269 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5270 return
5270 return
5271
5271
5272 revdag = cmdutil.graphrevs(repo, o, opts)
5272 revdag = cmdutil.graphrevs(repo, o, opts)
5273 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5273 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5274 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5274 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5275 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5275 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5276 return 0
5276 return 0
5277
5277
5278 if opts.get('bookmarks'):
5278 if opts.get('bookmarks'):
5279 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5279 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5280 dest, branches = hg.parseurl(dest, opts.get('branch'))
5280 dest, branches = hg.parseurl(dest, opts.get('branch'))
5281 other = hg.peer(repo, opts, dest)
5281 other = hg.peer(repo, opts, dest)
5282 if 'bookmarks' not in other.listkeys('namespaces'):
5282 if 'bookmarks' not in other.listkeys('namespaces'):
5283 ui.warn(_("remote doesn't support bookmarks\n"))
5283 ui.warn(_("remote doesn't support bookmarks\n"))
5284 return 0
5284 return 0
5285 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5285 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5286 return bookmarks.outgoing(ui, repo, other)
5286 return bookmarks.outgoing(ui, repo, other)
5287
5287
5288 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5288 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5289 try:
5289 try:
5290 return hg.outgoing(ui, repo, dest, opts)
5290 return hg.outgoing(ui, repo, dest, opts)
5291 finally:
5291 finally:
5292 del repo._subtoppath
5292 del repo._subtoppath
5293
5293
5294 @command('parents',
5294 @command('parents',
5295 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5295 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5296 ] + templateopts,
5296 ] + templateopts,
5297 _('[-r REV] [FILE]'),
5297 _('[-r REV] [FILE]'),
5298 inferrepo=True)
5298 inferrepo=True)
5299 def parents(ui, repo, file_=None, **opts):
5299 def parents(ui, repo, file_=None, **opts):
5300 """show the parents of the working directory or revision (DEPRECATED)
5300 """show the parents of the working directory or revision (DEPRECATED)
5301
5301
5302 Print the working directory's parent revisions. If a revision is
5302 Print the working directory's parent revisions. If a revision is
5303 given via -r/--rev, the parent of that revision will be printed.
5303 given via -r/--rev, the parent of that revision will be printed.
5304 If a file argument is given, the revision in which the file was
5304 If a file argument is given, the revision in which the file was
5305 last changed (before the working directory revision or the
5305 last changed (before the working directory revision or the
5306 argument to --rev if given) is printed.
5306 argument to --rev if given) is printed.
5307
5307
5308 This command is equivalent to::
5308 This command is equivalent to::
5309
5309
5310 hg log -r "p1()+p2()" or
5310 hg log -r "p1()+p2()" or
5311 hg log -r "p1(REV)+p2(REV)" or
5311 hg log -r "p1(REV)+p2(REV)" or
5312 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5312 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5313 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5313 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5314
5314
5315 See :hg:`summary` and :hg:`help revsets` for related information.
5315 See :hg:`summary` and :hg:`help revsets` for related information.
5316
5316
5317 Returns 0 on success.
5317 Returns 0 on success.
5318 """
5318 """
5319
5319
5320 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5320 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5321
5321
5322 if file_:
5322 if file_:
5323 m = scmutil.match(ctx, (file_,), opts)
5323 m = scmutil.match(ctx, (file_,), opts)
5324 if m.anypats() or len(m.files()) != 1:
5324 if m.anypats() or len(m.files()) != 1:
5325 raise error.Abort(_('can only specify an explicit filename'))
5325 raise error.Abort(_('can only specify an explicit filename'))
5326 file_ = m.files()[0]
5326 file_ = m.files()[0]
5327 filenodes = []
5327 filenodes = []
5328 for cp in ctx.parents():
5328 for cp in ctx.parents():
5329 if not cp:
5329 if not cp:
5330 continue
5330 continue
5331 try:
5331 try:
5332 filenodes.append(cp.filenode(file_))
5332 filenodes.append(cp.filenode(file_))
5333 except error.LookupError:
5333 except error.LookupError:
5334 pass
5334 pass
5335 if not filenodes:
5335 if not filenodes:
5336 raise error.Abort(_("'%s' not found in manifest!") % file_)
5336 raise error.Abort(_("'%s' not found in manifest!") % file_)
5337 p = []
5337 p = []
5338 for fn in filenodes:
5338 for fn in filenodes:
5339 fctx = repo.filectx(file_, fileid=fn)
5339 fctx = repo.filectx(file_, fileid=fn)
5340 p.append(fctx.node())
5340 p.append(fctx.node())
5341 else:
5341 else:
5342 p = [cp.node() for cp in ctx.parents()]
5342 p = [cp.node() for cp in ctx.parents()]
5343
5343
5344 displayer = cmdutil.show_changeset(ui, repo, opts)
5344 displayer = cmdutil.show_changeset(ui, repo, opts)
5345 for n in p:
5345 for n in p:
5346 if n != nullid:
5346 if n != nullid:
5347 displayer.show(repo[n])
5347 displayer.show(repo[n])
5348 displayer.close()
5348 displayer.close()
5349
5349
5350 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5350 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5351 def paths(ui, repo, search=None, **opts):
5351 def paths(ui, repo, search=None, **opts):
5352 """show aliases for remote repositories
5352 """show aliases for remote repositories
5353
5353
5354 Show definition of symbolic path name NAME. If no name is given,
5354 Show definition of symbolic path name NAME. If no name is given,
5355 show definition of all available names.
5355 show definition of all available names.
5356
5356
5357 Option -q/--quiet suppresses all output when searching for NAME
5357 Option -q/--quiet suppresses all output when searching for NAME
5358 and shows only the path names when listing all definitions.
5358 and shows only the path names when listing all definitions.
5359
5359
5360 Path names are defined in the [paths] section of your
5360 Path names are defined in the [paths] section of your
5361 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5361 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5362 repository, ``.hg/hgrc`` is used, too.
5362 repository, ``.hg/hgrc`` is used, too.
5363
5363
5364 The path names ``default`` and ``default-push`` have a special
5364 The path names ``default`` and ``default-push`` have a special
5365 meaning. When performing a push or pull operation, they are used
5365 meaning. When performing a push or pull operation, they are used
5366 as fallbacks if no location is specified on the command-line.
5366 as fallbacks if no location is specified on the command-line.
5367 When ``default-push`` is set, it will be used for push and
5367 When ``default-push`` is set, it will be used for push and
5368 ``default`` will be used for pull; otherwise ``default`` is used
5368 ``default`` will be used for pull; otherwise ``default`` is used
5369 as the fallback for both. When cloning a repository, the clone
5369 as the fallback for both. When cloning a repository, the clone
5370 source is written as ``default`` in ``.hg/hgrc``.
5370 source is written as ``default`` in ``.hg/hgrc``.
5371
5371
5372 .. note::
5372 .. note::
5373
5373
5374 ``default`` and ``default-push`` apply to all inbound (e.g.
5374 ``default`` and ``default-push`` apply to all inbound (e.g.
5375 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5375 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5376 and :hg:`bundle`) operations.
5376 and :hg:`bundle`) operations.
5377
5377
5378 See :hg:`help urls` for more information.
5378 See :hg:`help urls` for more information.
5379
5379
5380 Returns 0 on success.
5380 Returns 0 on success.
5381 """
5381 """
5382 if search:
5382 if search:
5383 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5383 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5384 if name == search]
5384 if name == search]
5385 else:
5385 else:
5386 pathitems = sorted(ui.paths.iteritems())
5386 pathitems = sorted(ui.paths.iteritems())
5387
5387
5388 fm = ui.formatter('paths', opts)
5388 fm = ui.formatter('paths', opts)
5389 if fm:
5389 if fm:
5390 hidepassword = str
5390 hidepassword = str
5391 else:
5391 else:
5392 hidepassword = util.hidepassword
5392 hidepassword = util.hidepassword
5393 if ui.quiet:
5393 if ui.quiet:
5394 namefmt = '%s\n'
5394 namefmt = '%s\n'
5395 else:
5395 else:
5396 namefmt = '%s = '
5396 namefmt = '%s = '
5397 showsubopts = not search and not ui.quiet
5397 showsubopts = not search and not ui.quiet
5398
5398
5399 for name, path in pathitems:
5399 for name, path in pathitems:
5400 fm.startitem()
5400 fm.startitem()
5401 fm.condwrite(not search, 'name', namefmt, name)
5401 fm.condwrite(not search, 'name', namefmt, name)
5402 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5402 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5403 for subopt, value in sorted(path.suboptions.items()):
5403 for subopt, value in sorted(path.suboptions.items()):
5404 assert subopt not in ('name', 'url')
5404 assert subopt not in ('name', 'url')
5405 if showsubopts:
5405 if showsubopts:
5406 fm.plain('%s:%s = ' % (name, subopt))
5406 fm.plain('%s:%s = ' % (name, subopt))
5407 fm.condwrite(showsubopts, subopt, '%s\n', value)
5407 fm.condwrite(showsubopts, subopt, '%s\n', value)
5408
5408
5409 fm.end()
5409 fm.end()
5410
5410
5411 if search and not pathitems:
5411 if search and not pathitems:
5412 if not ui.quiet:
5412 if not ui.quiet:
5413 ui.warn(_("not found!\n"))
5413 ui.warn(_("not found!\n"))
5414 return 1
5414 return 1
5415 else:
5415 else:
5416 return 0
5416 return 0
5417
5417
5418 @command('phase',
5418 @command('phase',
5419 [('p', 'public', False, _('set changeset phase to public')),
5419 [('p', 'public', False, _('set changeset phase to public')),
5420 ('d', 'draft', False, _('set changeset phase to draft')),
5420 ('d', 'draft', False, _('set changeset phase to draft')),
5421 ('s', 'secret', False, _('set changeset phase to secret')),
5421 ('s', 'secret', False, _('set changeset phase to secret')),
5422 ('f', 'force', False, _('allow to move boundary backward')),
5422 ('f', 'force', False, _('allow to move boundary backward')),
5423 ('r', 'rev', [], _('target revision'), _('REV')),
5423 ('r', 'rev', [], _('target revision'), _('REV')),
5424 ],
5424 ],
5425 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5425 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5426 def phase(ui, repo, *revs, **opts):
5426 def phase(ui, repo, *revs, **opts):
5427 """set or show the current phase name
5427 """set or show the current phase name
5428
5428
5429 With no argument, show the phase name of the current revision(s).
5429 With no argument, show the phase name of the current revision(s).
5430
5430
5431 With one of -p/--public, -d/--draft or -s/--secret, change the
5431 With one of -p/--public, -d/--draft or -s/--secret, change the
5432 phase value of the specified revisions.
5432 phase value of the specified revisions.
5433
5433
5434 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5434 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5435 lower phase to an higher phase. Phases are ordered as follows::
5435 lower phase to an higher phase. Phases are ordered as follows::
5436
5436
5437 public < draft < secret
5437 public < draft < secret
5438
5438
5439 Returns 0 on success, 1 if some phases could not be changed.
5439 Returns 0 on success, 1 if some phases could not be changed.
5440
5440
5441 (For more information about the phases concept, see :hg:`help phases`.)
5441 (For more information about the phases concept, see :hg:`help phases`.)
5442 """
5442 """
5443 # search for a unique phase argument
5443 # search for a unique phase argument
5444 targetphase = None
5444 targetphase = None
5445 for idx, name in enumerate(phases.phasenames):
5445 for idx, name in enumerate(phases.phasenames):
5446 if opts[name]:
5446 if opts[name]:
5447 if targetphase is not None:
5447 if targetphase is not None:
5448 raise error.Abort(_('only one phase can be specified'))
5448 raise error.Abort(_('only one phase can be specified'))
5449 targetphase = idx
5449 targetphase = idx
5450
5450
5451 # look for specified revision
5451 # look for specified revision
5452 revs = list(revs)
5452 revs = list(revs)
5453 revs.extend(opts['rev'])
5453 revs.extend(opts['rev'])
5454 if not revs:
5454 if not revs:
5455 # display both parents as the second parent phase can influence
5455 # display both parents as the second parent phase can influence
5456 # the phase of a merge commit
5456 # the phase of a merge commit
5457 revs = [c.rev() for c in repo[None].parents()]
5457 revs = [c.rev() for c in repo[None].parents()]
5458
5458
5459 revs = scmutil.revrange(repo, revs)
5459 revs = scmutil.revrange(repo, revs)
5460
5460
5461 lock = None
5461 lock = None
5462 ret = 0
5462 ret = 0
5463 if targetphase is None:
5463 if targetphase is None:
5464 # display
5464 # display
5465 for r in revs:
5465 for r in revs:
5466 ctx = repo[r]
5466 ctx = repo[r]
5467 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5467 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5468 else:
5468 else:
5469 tr = None
5469 tr = None
5470 lock = repo.lock()
5470 lock = repo.lock()
5471 try:
5471 try:
5472 tr = repo.transaction("phase")
5472 tr = repo.transaction("phase")
5473 # set phase
5473 # set phase
5474 if not revs:
5474 if not revs:
5475 raise error.Abort(_('empty revision set'))
5475 raise error.Abort(_('empty revision set'))
5476 nodes = [repo[r].node() for r in revs]
5476 nodes = [repo[r].node() for r in revs]
5477 # moving revision from public to draft may hide them
5477 # moving revision from public to draft may hide them
5478 # We have to check result on an unfiltered repository
5478 # We have to check result on an unfiltered repository
5479 unfi = repo.unfiltered()
5479 unfi = repo.unfiltered()
5480 getphase = unfi._phasecache.phase
5480 getphase = unfi._phasecache.phase
5481 olddata = [getphase(unfi, r) for r in unfi]
5481 olddata = [getphase(unfi, r) for r in unfi]
5482 phases.advanceboundary(repo, tr, targetphase, nodes)
5482 phases.advanceboundary(repo, tr, targetphase, nodes)
5483 if opts['force']:
5483 if opts['force']:
5484 phases.retractboundary(repo, tr, targetphase, nodes)
5484 phases.retractboundary(repo, tr, targetphase, nodes)
5485 tr.close()
5485 tr.close()
5486 finally:
5486 finally:
5487 if tr is not None:
5487 if tr is not None:
5488 tr.release()
5488 tr.release()
5489 lock.release()
5489 lock.release()
5490 getphase = unfi._phasecache.phase
5490 getphase = unfi._phasecache.phase
5491 newdata = [getphase(unfi, r) for r in unfi]
5491 newdata = [getphase(unfi, r) for r in unfi]
5492 changes = sum(newdata[r] != olddata[r] for r in unfi)
5492 changes = sum(newdata[r] != olddata[r] for r in unfi)
5493 cl = unfi.changelog
5493 cl = unfi.changelog
5494 rejected = [n for n in nodes
5494 rejected = [n for n in nodes
5495 if newdata[cl.rev(n)] < targetphase]
5495 if newdata[cl.rev(n)] < targetphase]
5496 if rejected:
5496 if rejected:
5497 ui.warn(_('cannot move %i changesets to a higher '
5497 ui.warn(_('cannot move %i changesets to a higher '
5498 'phase, use --force\n') % len(rejected))
5498 'phase, use --force\n') % len(rejected))
5499 ret = 1
5499 ret = 1
5500 if changes:
5500 if changes:
5501 msg = _('phase changed for %i changesets\n') % changes
5501 msg = _('phase changed for %i changesets\n') % changes
5502 if ret:
5502 if ret:
5503 ui.status(msg)
5503 ui.status(msg)
5504 else:
5504 else:
5505 ui.note(msg)
5505 ui.note(msg)
5506 else:
5506 else:
5507 ui.warn(_('no phases changed\n'))
5507 ui.warn(_('no phases changed\n'))
5508 return ret
5508 return ret
5509
5509
5510 def postincoming(ui, repo, modheads, optupdate, checkout):
5510 def postincoming(ui, repo, modheads, optupdate, checkout):
5511 if modheads == 0:
5511 if modheads == 0:
5512 return
5512 return
5513 if optupdate:
5513 if optupdate:
5514 try:
5514 try:
5515 brev = checkout
5515 brev = checkout
5516 movemarkfrom = None
5516 movemarkfrom = None
5517 if not checkout:
5517 if not checkout:
5518 updata = destutil.destupdate(repo)
5518 updata = destutil.destupdate(repo)
5519 checkout, movemarkfrom, brev = updata
5519 checkout, movemarkfrom, brev = updata
5520 ret = hg.update(repo, checkout)
5520 ret = hg.update(repo, checkout)
5521 except error.UpdateAbort as inst:
5521 except error.UpdateAbort as inst:
5522 msg = _("not updating: %s") % str(inst)
5522 msg = _("not updating: %s") % str(inst)
5523 hint = inst.hint
5523 hint = inst.hint
5524 raise error.UpdateAbort(msg, hint=hint)
5524 raise error.UpdateAbort(msg, hint=hint)
5525 if not ret and not checkout:
5525 if not ret and not checkout:
5526 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5526 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5527 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5527 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5528 return ret
5528 return ret
5529 if modheads > 1:
5529 if modheads > 1:
5530 currentbranchheads = len(repo.branchheads())
5530 currentbranchheads = len(repo.branchheads())
5531 if currentbranchheads == modheads:
5531 if currentbranchheads == modheads:
5532 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5532 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5533 elif currentbranchheads > 1:
5533 elif currentbranchheads > 1:
5534 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5534 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5535 "merge)\n"))
5535 "merge)\n"))
5536 else:
5536 else:
5537 ui.status(_("(run 'hg heads' to see heads)\n"))
5537 ui.status(_("(run 'hg heads' to see heads)\n"))
5538 else:
5538 else:
5539 ui.status(_("(run 'hg update' to get a working copy)\n"))
5539 ui.status(_("(run 'hg update' to get a working copy)\n"))
5540
5540
5541 @command('^pull',
5541 @command('^pull',
5542 [('u', 'update', None,
5542 [('u', 'update', None,
5543 _('update to new branch head if changesets were pulled')),
5543 _('update to new branch head if changesets were pulled')),
5544 ('f', 'force', None, _('run even when remote repository is unrelated')),
5544 ('f', 'force', None, _('run even when remote repository is unrelated')),
5545 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5545 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5546 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5546 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5547 ('b', 'branch', [], _('a specific branch you would like to pull'),
5547 ('b', 'branch', [], _('a specific branch you would like to pull'),
5548 _('BRANCH')),
5548 _('BRANCH')),
5549 ] + remoteopts,
5549 ] + remoteopts,
5550 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5550 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5551 def pull(ui, repo, source="default", **opts):
5551 def pull(ui, repo, source="default", **opts):
5552 """pull changes from the specified source
5552 """pull changes from the specified source
5553
5553
5554 Pull changes from a remote repository to a local one.
5554 Pull changes from a remote repository to a local one.
5555
5555
5556 This finds all changes from the repository at the specified path
5556 This finds all changes from the repository at the specified path
5557 or URL and adds them to a local repository (the current one unless
5557 or URL and adds them to a local repository (the current one unless
5558 -R is specified). By default, this does not update the copy of the
5558 -R is specified). By default, this does not update the copy of the
5559 project in the working directory.
5559 project in the working directory.
5560
5560
5561 Use :hg:`incoming` if you want to see what would have been added
5561 Use :hg:`incoming` if you want to see what would have been added
5562 by a pull at the time you issued this command. If you then decide
5562 by a pull at the time you issued this command. If you then decide
5563 to add those changes to the repository, you should use :hg:`pull
5563 to add those changes to the repository, you should use :hg:`pull
5564 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5564 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5565
5565
5566 If SOURCE is omitted, the 'default' path will be used.
5566 If SOURCE is omitted, the 'default' path will be used.
5567 See :hg:`help urls` for more information.
5567 See :hg:`help urls` for more information.
5568
5568
5569 Returns 0 on success, 1 if an update had unresolved files.
5569 Returns 0 on success, 1 if an update had unresolved files.
5570 """
5570 """
5571 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5571 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5572 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5572 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5573 other = hg.peer(repo, opts, source)
5573 other = hg.peer(repo, opts, source)
5574 try:
5574 try:
5575 revs, checkout = hg.addbranchrevs(repo, other, branches,
5575 revs, checkout = hg.addbranchrevs(repo, other, branches,
5576 opts.get('rev'))
5576 opts.get('rev'))
5577
5577
5578
5578
5579 pullopargs = {}
5579 pullopargs = {}
5580 if opts.get('bookmark'):
5580 if opts.get('bookmark'):
5581 if not revs:
5581 if not revs:
5582 revs = []
5582 revs = []
5583 # The list of bookmark used here is not the one used to actually
5583 # The list of bookmark used here is not the one used to actually
5584 # update the bookmark name. This can result in the revision pulled
5584 # update the bookmark name. This can result in the revision pulled
5585 # not ending up with the name of the bookmark because of a race
5585 # not ending up with the name of the bookmark because of a race
5586 # condition on the server. (See issue 4689 for details)
5586 # condition on the server. (See issue 4689 for details)
5587 remotebookmarks = other.listkeys('bookmarks')
5587 remotebookmarks = other.listkeys('bookmarks')
5588 pullopargs['remotebookmarks'] = remotebookmarks
5588 pullopargs['remotebookmarks'] = remotebookmarks
5589 for b in opts['bookmark']:
5589 for b in opts['bookmark']:
5590 if b not in remotebookmarks:
5590 if b not in remotebookmarks:
5591 raise error.Abort(_('remote bookmark %s not found!') % b)
5591 raise error.Abort(_('remote bookmark %s not found!') % b)
5592 revs.append(remotebookmarks[b])
5592 revs.append(remotebookmarks[b])
5593
5593
5594 if revs:
5594 if revs:
5595 try:
5595 try:
5596 # When 'rev' is a bookmark name, we cannot guarantee that it
5596 # When 'rev' is a bookmark name, we cannot guarantee that it
5597 # will be updated with that name because of a race condition
5597 # will be updated with that name because of a race condition
5598 # server side. (See issue 4689 for details)
5598 # server side. (See issue 4689 for details)
5599 oldrevs = revs
5599 oldrevs = revs
5600 revs = [] # actually, nodes
5600 revs = [] # actually, nodes
5601 for r in oldrevs:
5601 for r in oldrevs:
5602 node = other.lookup(r)
5602 node = other.lookup(r)
5603 revs.append(node)
5603 revs.append(node)
5604 if r == checkout:
5604 if r == checkout:
5605 checkout = node
5605 checkout = node
5606 except error.CapabilityError:
5606 except error.CapabilityError:
5607 err = _("other repository doesn't support revision lookup, "
5607 err = _("other repository doesn't support revision lookup, "
5608 "so a rev cannot be specified.")
5608 "so a rev cannot be specified.")
5609 raise error.Abort(err)
5609 raise error.Abort(err)
5610
5610
5611 pullopargs.update(opts.get('opargs', {}))
5611 pullopargs.update(opts.get('opargs', {}))
5612 modheads = exchange.pull(repo, other, heads=revs,
5612 modheads = exchange.pull(repo, other, heads=revs,
5613 force=opts.get('force'),
5613 force=opts.get('force'),
5614 bookmarks=opts.get('bookmark', ()),
5614 bookmarks=opts.get('bookmark', ()),
5615 opargs=pullopargs).cgresult
5615 opargs=pullopargs).cgresult
5616 if checkout:
5616 if checkout:
5617 checkout = str(repo.changelog.rev(checkout))
5617 checkout = str(repo.changelog.rev(checkout))
5618 repo._subtoppath = source
5618 repo._subtoppath = source
5619 try:
5619 try:
5620 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5620 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5621
5621
5622 finally:
5622 finally:
5623 del repo._subtoppath
5623 del repo._subtoppath
5624
5624
5625 finally:
5625 finally:
5626 other.close()
5626 other.close()
5627 return ret
5627 return ret
5628
5628
5629 @command('^push',
5629 @command('^push',
5630 [('f', 'force', None, _('force push')),
5630 [('f', 'force', None, _('force push')),
5631 ('r', 'rev', [],
5631 ('r', 'rev', [],
5632 _('a changeset intended to be included in the destination'),
5632 _('a changeset intended to be included in the destination'),
5633 _('REV')),
5633 _('REV')),
5634 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5634 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5635 ('b', 'branch', [],
5635 ('b', 'branch', [],
5636 _('a specific branch you would like to push'), _('BRANCH')),
5636 _('a specific branch you would like to push'), _('BRANCH')),
5637 ('', 'new-branch', False, _('allow pushing a new branch')),
5637 ('', 'new-branch', False, _('allow pushing a new branch')),
5638 ] + remoteopts,
5638 ] + remoteopts,
5639 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5639 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5640 def push(ui, repo, dest=None, **opts):
5640 def push(ui, repo, dest=None, **opts):
5641 """push changes to the specified destination
5641 """push changes to the specified destination
5642
5642
5643 Push changesets from the local repository to the specified
5643 Push changesets from the local repository to the specified
5644 destination.
5644 destination.
5645
5645
5646 This operation is symmetrical to pull: it is identical to a pull
5646 This operation is symmetrical to pull: it is identical to a pull
5647 in the destination repository from the current one.
5647 in the destination repository from the current one.
5648
5648
5649 By default, push will not allow creation of new heads at the
5649 By default, push will not allow creation of new heads at the
5650 destination, since multiple heads would make it unclear which head
5650 destination, since multiple heads would make it unclear which head
5651 to use. In this situation, it is recommended to pull and merge
5651 to use. In this situation, it is recommended to pull and merge
5652 before pushing.
5652 before pushing.
5653
5653
5654 Use --new-branch if you want to allow push to create a new named
5654 Use --new-branch if you want to allow push to create a new named
5655 branch that is not present at the destination. This allows you to
5655 branch that is not present at the destination. This allows you to
5656 only create a new branch without forcing other changes.
5656 only create a new branch without forcing other changes.
5657
5657
5658 .. note::
5658 .. note::
5659
5659
5660 Extra care should be taken with the -f/--force option,
5660 Extra care should be taken with the -f/--force option,
5661 which will push all new heads on all branches, an action which will
5661 which will push all new heads on all branches, an action which will
5662 almost always cause confusion for collaborators.
5662 almost always cause confusion for collaborators.
5663
5663
5664 If -r/--rev is used, the specified revision and all its ancestors
5664 If -r/--rev is used, the specified revision and all its ancestors
5665 will be pushed to the remote repository.
5665 will be pushed to the remote repository.
5666
5666
5667 If -B/--bookmark is used, the specified bookmarked revision, its
5667 If -B/--bookmark is used, the specified bookmarked revision, its
5668 ancestors, and the bookmark will be pushed to the remote
5668 ancestors, and the bookmark will be pushed to the remote
5669 repository.
5669 repository.
5670
5670
5671 Please see :hg:`help urls` for important details about ``ssh://``
5671 Please see :hg:`help urls` for important details about ``ssh://``
5672 URLs. If DESTINATION is omitted, a default path will be used.
5672 URLs. If DESTINATION is omitted, a default path will be used.
5673
5673
5674 Returns 0 if push was successful, 1 if nothing to push.
5674 Returns 0 if push was successful, 1 if nothing to push.
5675 """
5675 """
5676
5676
5677 if opts.get('bookmark'):
5677 if opts.get('bookmark'):
5678 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5678 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5679 for b in opts['bookmark']:
5679 for b in opts['bookmark']:
5680 # translate -B options to -r so changesets get pushed
5680 # translate -B options to -r so changesets get pushed
5681 if b in repo._bookmarks:
5681 if b in repo._bookmarks:
5682 opts.setdefault('rev', []).append(b)
5682 opts.setdefault('rev', []).append(b)
5683 else:
5683 else:
5684 # if we try to push a deleted bookmark, translate it to null
5684 # if we try to push a deleted bookmark, translate it to null
5685 # this lets simultaneous -r, -b options continue working
5685 # this lets simultaneous -r, -b options continue working
5686 opts.setdefault('rev', []).append("null")
5686 opts.setdefault('rev', []).append("null")
5687
5687
5688 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5688 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5689 if not path:
5689 if not path:
5690 raise error.Abort(_('default repository not configured!'),
5690 raise error.Abort(_('default repository not configured!'),
5691 hint=_('see the "path" section in "hg help config"'))
5691 hint=_('see the "path" section in "hg help config"'))
5692 dest = path.pushloc or path.loc
5692 dest = path.pushloc or path.loc
5693 branches = (path.branch, opts.get('branch') or [])
5693 branches = (path.branch, opts.get('branch') or [])
5694 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5694 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5695 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5695 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5696 other = hg.peer(repo, opts, dest)
5696 other = hg.peer(repo, opts, dest)
5697
5697
5698 if revs:
5698 if revs:
5699 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5699 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5700 if not revs:
5700 if not revs:
5701 raise error.Abort(_("specified revisions evaluate to an empty set"),
5701 raise error.Abort(_("specified revisions evaluate to an empty set"),
5702 hint=_("use different revision arguments"))
5702 hint=_("use different revision arguments"))
5703
5703
5704 repo._subtoppath = dest
5704 repo._subtoppath = dest
5705 try:
5705 try:
5706 # push subrepos depth-first for coherent ordering
5706 # push subrepos depth-first for coherent ordering
5707 c = repo['']
5707 c = repo['']
5708 subs = c.substate # only repos that are committed
5708 subs = c.substate # only repos that are committed
5709 for s in sorted(subs):
5709 for s in sorted(subs):
5710 result = c.sub(s).push(opts)
5710 result = c.sub(s).push(opts)
5711 if result == 0:
5711 if result == 0:
5712 return not result
5712 return not result
5713 finally:
5713 finally:
5714 del repo._subtoppath
5714 del repo._subtoppath
5715 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5715 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5716 newbranch=opts.get('new_branch'),
5716 newbranch=opts.get('new_branch'),
5717 bookmarks=opts.get('bookmark', ()),
5717 bookmarks=opts.get('bookmark', ()),
5718 opargs=opts.get('opargs'))
5718 opargs=opts.get('opargs'))
5719
5719
5720 result = not pushop.cgresult
5720 result = not pushop.cgresult
5721
5721
5722 if pushop.bkresult is not None:
5722 if pushop.bkresult is not None:
5723 if pushop.bkresult == 2:
5723 if pushop.bkresult == 2:
5724 result = 2
5724 result = 2
5725 elif not result and pushop.bkresult:
5725 elif not result and pushop.bkresult:
5726 result = 2
5726 result = 2
5727
5727
5728 return result
5728 return result
5729
5729
5730 @command('recover', [])
5730 @command('recover', [])
5731 def recover(ui, repo):
5731 def recover(ui, repo):
5732 """roll back an interrupted transaction
5732 """roll back an interrupted transaction
5733
5733
5734 Recover from an interrupted commit or pull.
5734 Recover from an interrupted commit or pull.
5735
5735
5736 This command tries to fix the repository status after an
5736 This command tries to fix the repository status after an
5737 interrupted operation. It should only be necessary when Mercurial
5737 interrupted operation. It should only be necessary when Mercurial
5738 suggests it.
5738 suggests it.
5739
5739
5740 Returns 0 if successful, 1 if nothing to recover or verify fails.
5740 Returns 0 if successful, 1 if nothing to recover or verify fails.
5741 """
5741 """
5742 if repo.recover():
5742 if repo.recover():
5743 return hg.verify(repo)
5743 return hg.verify(repo)
5744 return 1
5744 return 1
5745
5745
5746 @command('^remove|rm',
5746 @command('^remove|rm',
5747 [('A', 'after', None, _('record delete for missing files')),
5747 [('A', 'after', None, _('record delete for missing files')),
5748 ('f', 'force', None,
5748 ('f', 'force', None,
5749 _('remove (and delete) file even if added or modified')),
5749 _('remove (and delete) file even if added or modified')),
5750 ] + subrepoopts + walkopts,
5750 ] + subrepoopts + walkopts,
5751 _('[OPTION]... FILE...'),
5751 _('[OPTION]... FILE...'),
5752 inferrepo=True)
5752 inferrepo=True)
5753 def remove(ui, repo, *pats, **opts):
5753 def remove(ui, repo, *pats, **opts):
5754 """remove the specified files on the next commit
5754 """remove the specified files on the next commit
5755
5755
5756 Schedule the indicated files for removal from the current branch.
5756 Schedule the indicated files for removal from the current branch.
5757
5757
5758 This command schedules the files to be removed at the next commit.
5758 This command schedules the files to be removed at the next commit.
5759 To undo a remove before that, see :hg:`revert`. To undo added
5759 To undo a remove before that, see :hg:`revert`. To undo added
5760 files, see :hg:`forget`.
5760 files, see :hg:`forget`.
5761
5761
5762 .. container:: verbose
5762 .. container:: verbose
5763
5763
5764 -A/--after can be used to remove only files that have already
5764 -A/--after can be used to remove only files that have already
5765 been deleted, -f/--force can be used to force deletion, and -Af
5765 been deleted, -f/--force can be used to force deletion, and -Af
5766 can be used to remove files from the next revision without
5766 can be used to remove files from the next revision without
5767 deleting them from the working directory.
5767 deleting them from the working directory.
5768
5768
5769 The following table details the behavior of remove for different
5769 The following table details the behavior of remove for different
5770 file states (columns) and option combinations (rows). The file
5770 file states (columns) and option combinations (rows). The file
5771 states are Added [A], Clean [C], Modified [M] and Missing [!]
5771 states are Added [A], Clean [C], Modified [M] and Missing [!]
5772 (as reported by :hg:`status`). The actions are Warn, Remove
5772 (as reported by :hg:`status`). The actions are Warn, Remove
5773 (from branch) and Delete (from disk):
5773 (from branch) and Delete (from disk):
5774
5774
5775 ========= == == == ==
5775 ========= == == == ==
5776 opt/state A C M !
5776 opt/state A C M !
5777 ========= == == == ==
5777 ========= == == == ==
5778 none W RD W R
5778 none W RD W R
5779 -f R RD RD R
5779 -f R RD RD R
5780 -A W W W R
5780 -A W W W R
5781 -Af R R R R
5781 -Af R R R R
5782 ========= == == == ==
5782 ========= == == == ==
5783
5783
5784 .. note::
5784 .. note::
5785
5785
5786 :hg:`remove` never deletes files in Added [A] state from the
5786 :hg:`remove` never deletes files in Added [A] state from the
5787 working directory, not even if ``--force`` is specified.
5787 working directory, not even if ``--force`` is specified.
5788
5788
5789 Returns 0 on success, 1 if any warnings encountered.
5789 Returns 0 on success, 1 if any warnings encountered.
5790 """
5790 """
5791
5791
5792 after, force = opts.get('after'), opts.get('force')
5792 after, force = opts.get('after'), opts.get('force')
5793 if not pats and not after:
5793 if not pats and not after:
5794 raise error.Abort(_('no files specified'))
5794 raise error.Abort(_('no files specified'))
5795
5795
5796 m = scmutil.match(repo[None], pats, opts)
5796 m = scmutil.match(repo[None], pats, opts)
5797 subrepos = opts.get('subrepos')
5797 subrepos = opts.get('subrepos')
5798 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5798 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5799
5799
5800 @command('rename|move|mv',
5800 @command('rename|move|mv',
5801 [('A', 'after', None, _('record a rename that has already occurred')),
5801 [('A', 'after', None, _('record a rename that has already occurred')),
5802 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5802 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5803 ] + walkopts + dryrunopts,
5803 ] + walkopts + dryrunopts,
5804 _('[OPTION]... SOURCE... DEST'))
5804 _('[OPTION]... SOURCE... DEST'))
5805 def rename(ui, repo, *pats, **opts):
5805 def rename(ui, repo, *pats, **opts):
5806 """rename files; equivalent of copy + remove
5806 """rename files; equivalent of copy + remove
5807
5807
5808 Mark dest as copies of sources; mark sources for deletion. If dest
5808 Mark dest as copies of sources; mark sources for deletion. If dest
5809 is a directory, copies are put in that directory. If dest is a
5809 is a directory, copies are put in that directory. If dest is a
5810 file, there can only be one source.
5810 file, there can only be one source.
5811
5811
5812 By default, this command copies the contents of files as they
5812 By default, this command copies the contents of files as they
5813 exist in the working directory. If invoked with -A/--after, the
5813 exist in the working directory. If invoked with -A/--after, the
5814 operation is recorded, but no copying is performed.
5814 operation is recorded, but no copying is performed.
5815
5815
5816 This command takes effect at the next commit. To undo a rename
5816 This command takes effect at the next commit. To undo a rename
5817 before that, see :hg:`revert`.
5817 before that, see :hg:`revert`.
5818
5818
5819 Returns 0 on success, 1 if errors are encountered.
5819 Returns 0 on success, 1 if errors are encountered.
5820 """
5820 """
5821 wlock = repo.wlock(False)
5821 wlock = repo.wlock(False)
5822 try:
5822 try:
5823 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5823 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5824 finally:
5824 finally:
5825 wlock.release()
5825 wlock.release()
5826
5826
5827 @command('resolve',
5827 @command('resolve',
5828 [('a', 'all', None, _('select all unresolved files')),
5828 [('a', 'all', None, _('select all unresolved files')),
5829 ('l', 'list', None, _('list state of files needing merge')),
5829 ('l', 'list', None, _('list state of files needing merge')),
5830 ('m', 'mark', None, _('mark files as resolved')),
5830 ('m', 'mark', None, _('mark files as resolved')),
5831 ('u', 'unmark', None, _('mark files as unresolved')),
5831 ('u', 'unmark', None, _('mark files as unresolved')),
5832 ('n', 'no-status', None, _('hide status prefix'))]
5832 ('n', 'no-status', None, _('hide status prefix'))]
5833 + mergetoolopts + walkopts + formatteropts,
5833 + mergetoolopts + walkopts + formatteropts,
5834 _('[OPTION]... [FILE]...'),
5834 _('[OPTION]... [FILE]...'),
5835 inferrepo=True)
5835 inferrepo=True)
5836 def resolve(ui, repo, *pats, **opts):
5836 def resolve(ui, repo, *pats, **opts):
5837 """redo merges or set/view the merge status of files
5837 """redo merges or set/view the merge status of files
5838
5838
5839 Merges with unresolved conflicts are often the result of
5839 Merges with unresolved conflicts are often the result of
5840 non-interactive merging using the ``internal:merge`` configuration
5840 non-interactive merging using the ``internal:merge`` configuration
5841 setting, or a command-line merge tool like ``diff3``. The resolve
5841 setting, or a command-line merge tool like ``diff3``. The resolve
5842 command is used to manage the files involved in a merge, after
5842 command is used to manage the files involved in a merge, after
5843 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5843 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5844 working directory must have two parents). See :hg:`help
5844 working directory must have two parents). See :hg:`help
5845 merge-tools` for information on configuring merge tools.
5845 merge-tools` for information on configuring merge tools.
5846
5846
5847 The resolve command can be used in the following ways:
5847 The resolve command can be used in the following ways:
5848
5848
5849 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5849 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5850 files, discarding any previous merge attempts. Re-merging is not
5850 files, discarding any previous merge attempts. Re-merging is not
5851 performed for files already marked as resolved. Use ``--all/-a``
5851 performed for files already marked as resolved. Use ``--all/-a``
5852 to select all unresolved files. ``--tool`` can be used to specify
5852 to select all unresolved files. ``--tool`` can be used to specify
5853 the merge tool used for the given files. It overrides the HGMERGE
5853 the merge tool used for the given files. It overrides the HGMERGE
5854 environment variable and your configuration files. Previous file
5854 environment variable and your configuration files. Previous file
5855 contents are saved with a ``.orig`` suffix.
5855 contents are saved with a ``.orig`` suffix.
5856
5856
5857 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5857 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5858 (e.g. after having manually fixed-up the files). The default is
5858 (e.g. after having manually fixed-up the files). The default is
5859 to mark all unresolved files.
5859 to mark all unresolved files.
5860
5860
5861 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5861 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5862 default is to mark all resolved files.
5862 default is to mark all resolved files.
5863
5863
5864 - :hg:`resolve -l`: list files which had or still have conflicts.
5864 - :hg:`resolve -l`: list files which had or still have conflicts.
5865 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5865 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5866
5866
5867 .. note::
5867 .. note::
5868
5868
5869 Mercurial will not let you commit files with unresolved merge
5869 Mercurial will not let you commit files with unresolved merge
5870 conflicts. You must use :hg:`resolve -m ...` before you can
5870 conflicts. You must use :hg:`resolve -m ...` before you can
5871 commit after a conflicting merge.
5871 commit after a conflicting merge.
5872
5872
5873 Returns 0 on success, 1 if any files fail a resolve attempt.
5873 Returns 0 on success, 1 if any files fail a resolve attempt.
5874 """
5874 """
5875
5875
5876 all, mark, unmark, show, nostatus = \
5876 all, mark, unmark, show, nostatus = \
5877 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5877 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5878
5878
5879 if (show and (mark or unmark)) or (mark and unmark):
5879 if (show and (mark or unmark)) or (mark and unmark):
5880 raise error.Abort(_("too many options specified"))
5880 raise error.Abort(_("too many options specified"))
5881 if pats and all:
5881 if pats and all:
5882 raise error.Abort(_("can't specify --all and patterns"))
5882 raise error.Abort(_("can't specify --all and patterns"))
5883 if not (all or pats or show or mark or unmark):
5883 if not (all or pats or show or mark or unmark):
5884 raise error.Abort(_('no files or directories specified'),
5884 raise error.Abort(_('no files or directories specified'),
5885 hint=('use --all to re-merge all unresolved files'))
5885 hint=('use --all to re-merge all unresolved files'))
5886
5886
5887 if show:
5887 if show:
5888 fm = ui.formatter('resolve', opts)
5888 fm = ui.formatter('resolve', opts)
5889 ms = mergemod.mergestate.read(repo)
5889 ms = mergemod.mergestate.read(repo)
5890 m = scmutil.match(repo[None], pats, opts)
5890 m = scmutil.match(repo[None], pats, opts)
5891 for f in ms:
5891 for f in ms:
5892 if not m(f):
5892 if not m(f):
5893 continue
5893 continue
5894 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5894 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5895 'd': 'driverresolved'}[ms[f]]
5895 'd': 'driverresolved'}[ms[f]]
5896 fm.startitem()
5896 fm.startitem()
5897 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5897 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5898 fm.write('path', '%s\n', f, label=l)
5898 fm.write('path', '%s\n', f, label=l)
5899 fm.end()
5899 fm.end()
5900 return 0
5900 return 0
5901
5901
5902 wlock = repo.wlock()
5902 wlock = repo.wlock()
5903 try:
5903 try:
5904 ms = mergemod.mergestate.read(repo)
5904 ms = mergemod.mergestate.read(repo)
5905
5905
5906 if not (ms.active() or repo.dirstate.p2() != nullid):
5906 if not (ms.active() or repo.dirstate.p2() != nullid):
5907 raise error.Abort(
5907 raise error.Abort(
5908 _('resolve command not applicable when not merging'))
5908 _('resolve command not applicable when not merging'))
5909
5909
5910 wctx = repo[None]
5910 wctx = repo[None]
5911
5911
5912 if ms.mergedriver and ms.mdstate() == 'u':
5912 if ms.mergedriver and ms.mdstate() == 'u':
5913 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5913 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5914 ms.commit()
5914 ms.commit()
5915 # allow mark and unmark to go through
5915 # allow mark and unmark to go through
5916 if not mark and not unmark and not proceed:
5916 if not mark and not unmark and not proceed:
5917 return 1
5917 return 1
5918
5918
5919 m = scmutil.match(wctx, pats, opts)
5919 m = scmutil.match(wctx, pats, opts)
5920 ret = 0
5920 ret = 0
5921 didwork = False
5921 didwork = False
5922 runconclude = False
5922 runconclude = False
5923
5923
5924 tocomplete = []
5924 tocomplete = []
5925 for f in ms:
5925 for f in ms:
5926 if not m(f):
5926 if not m(f):
5927 continue
5927 continue
5928
5928
5929 didwork = True
5929 didwork = True
5930
5930
5931 # don't let driver-resolved files be marked, and run the conclude
5931 # don't let driver-resolved files be marked, and run the conclude
5932 # step if asked to resolve
5932 # step if asked to resolve
5933 if ms[f] == "d":
5933 if ms[f] == "d":
5934 exact = m.exact(f)
5934 exact = m.exact(f)
5935 if mark:
5935 if mark:
5936 if exact:
5936 if exact:
5937 ui.warn(_('not marking %s as it is driver-resolved\n')
5937 ui.warn(_('not marking %s as it is driver-resolved\n')
5938 % f)
5938 % f)
5939 elif unmark:
5939 elif unmark:
5940 if exact:
5940 if exact:
5941 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5941 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5942 % f)
5942 % f)
5943 else:
5943 else:
5944 runconclude = True
5944 runconclude = True
5945 continue
5945 continue
5946
5946
5947 if mark:
5947 if mark:
5948 ms.mark(f, "r")
5948 ms.mark(f, "r")
5949 elif unmark:
5949 elif unmark:
5950 ms.mark(f, "u")
5950 ms.mark(f, "u")
5951 else:
5951 else:
5952 # backup pre-resolve (merge uses .orig for its own purposes)
5952 # backup pre-resolve (merge uses .orig for its own purposes)
5953 a = repo.wjoin(f)
5953 a = repo.wjoin(f)
5954 try:
5954 try:
5955 util.copyfile(a, a + ".resolve")
5955 util.copyfile(a, a + ".resolve")
5956 except (IOError, OSError) as inst:
5956 except (IOError, OSError) as inst:
5957 if inst.errno != errno.ENOENT:
5957 if inst.errno != errno.ENOENT:
5958 raise
5958 raise
5959
5959
5960 try:
5960 try:
5961 # preresolve file
5961 # preresolve file
5962 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5962 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5963 'resolve')
5963 'resolve')
5964 complete, r = ms.preresolve(f, wctx)
5964 complete, r = ms.preresolve(f, wctx)
5965 if not complete:
5965 if not complete:
5966 tocomplete.append(f)
5966 tocomplete.append(f)
5967 elif r:
5967 elif r:
5968 ret = 1
5968 ret = 1
5969 finally:
5969 finally:
5970 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5970 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5971 ms.commit()
5971 ms.commit()
5972
5972
5973 # replace filemerge's .orig file with our resolve file, but only
5973 # replace filemerge's .orig file with our resolve file, but only
5974 # for merges that are complete
5974 # for merges that are complete
5975 if complete:
5975 if complete:
5976 try:
5976 try:
5977 util.rename(a + ".resolve",
5977 util.rename(a + ".resolve",
5978 scmutil.origpath(ui, repo, a))
5978 scmutil.origpath(ui, repo, a))
5979 except OSError as inst:
5979 except OSError as inst:
5980 if inst.errno != errno.ENOENT:
5980 if inst.errno != errno.ENOENT:
5981 raise
5981 raise
5982
5982
5983 for f in tocomplete:
5983 for f in tocomplete:
5984 try:
5984 try:
5985 # resolve file
5985 # resolve file
5986 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5986 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5987 'resolve')
5987 'resolve')
5988 r = ms.resolve(f, wctx)
5988 r = ms.resolve(f, wctx)
5989 if r:
5989 if r:
5990 ret = 1
5990 ret = 1
5991 finally:
5991 finally:
5992 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5992 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5993 ms.commit()
5993 ms.commit()
5994
5994
5995 # replace filemerge's .orig file with our resolve file
5995 # replace filemerge's .orig file with our resolve file
5996 a = repo.wjoin(f)
5996 a = repo.wjoin(f)
5997 try:
5997 try:
5998 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5998 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5999 except OSError as inst:
5999 except OSError as inst:
6000 if inst.errno != errno.ENOENT:
6000 if inst.errno != errno.ENOENT:
6001 raise
6001 raise
6002
6002
6003 ms.commit()
6003 ms.commit()
6004 ms.recordactions()
6004 ms.recordactions()
6005
6005
6006 if not didwork and pats:
6006 if not didwork and pats:
6007 ui.warn(_("arguments do not match paths that need resolving\n"))
6007 ui.warn(_("arguments do not match paths that need resolving\n"))
6008 elif ms.mergedriver and ms.mdstate() != 's':
6008 elif ms.mergedriver and ms.mdstate() != 's':
6009 # run conclude step when either a driver-resolved file is requested
6009 # run conclude step when either a driver-resolved file is requested
6010 # or there are no driver-resolved files
6010 # or there are no driver-resolved files
6011 # we can't use 'ret' to determine whether any files are unresolved
6011 # we can't use 'ret' to determine whether any files are unresolved
6012 # because we might not have tried to resolve some
6012 # because we might not have tried to resolve some
6013 if ((runconclude or not list(ms.driverresolved()))
6013 if ((runconclude or not list(ms.driverresolved()))
6014 and not list(ms.unresolved())):
6014 and not list(ms.unresolved())):
6015 proceed = mergemod.driverconclude(repo, ms, wctx)
6015 proceed = mergemod.driverconclude(repo, ms, wctx)
6016 ms.commit()
6016 ms.commit()
6017 if not proceed:
6017 if not proceed:
6018 return 1
6018 return 1
6019
6019
6020 finally:
6020 finally:
6021 wlock.release()
6021 wlock.release()
6022
6022
6023 # Nudge users into finishing an unfinished operation
6023 # Nudge users into finishing an unfinished operation
6024 unresolvedf = list(ms.unresolved())
6024 unresolvedf = list(ms.unresolved())
6025 driverresolvedf = list(ms.driverresolved())
6025 driverresolvedf = list(ms.driverresolved())
6026 if not unresolvedf and not driverresolvedf:
6026 if not unresolvedf and not driverresolvedf:
6027 ui.status(_('(no more unresolved files)\n'))
6027 ui.status(_('(no more unresolved files)\n'))
6028 cmdutil.checkafterresolved(repo)
6028 cmdutil.checkafterresolved(repo)
6029 elif not unresolvedf:
6029 elif not unresolvedf:
6030 ui.status(_('(no more unresolved files -- '
6030 ui.status(_('(no more unresolved files -- '
6031 'run "hg resolve --all" to conclude)\n'))
6031 'run "hg resolve --all" to conclude)\n'))
6032
6032
6033 return ret
6033 return ret
6034
6034
6035 @command('revert',
6035 @command('revert',
6036 [('a', 'all', None, _('revert all changes when no arguments given')),
6036 [('a', 'all', None, _('revert all changes when no arguments given')),
6037 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6037 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6038 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6038 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6039 ('C', 'no-backup', None, _('do not save backup copies of files')),
6039 ('C', 'no-backup', None, _('do not save backup copies of files')),
6040 ('i', 'interactive', None,
6040 ('i', 'interactive', None,
6041 _('interactively select the changes (EXPERIMENTAL)')),
6041 _('interactively select the changes (EXPERIMENTAL)')),
6042 ] + walkopts + dryrunopts,
6042 ] + walkopts + dryrunopts,
6043 _('[OPTION]... [-r REV] [NAME]...'))
6043 _('[OPTION]... [-r REV] [NAME]...'))
6044 def revert(ui, repo, *pats, **opts):
6044 def revert(ui, repo, *pats, **opts):
6045 """restore files to their checkout state
6045 """restore files to their checkout state
6046
6046
6047 .. note::
6047 .. note::
6048
6048
6049 To check out earlier revisions, you should use :hg:`update REV`.
6049 To check out earlier revisions, you should use :hg:`update REV`.
6050 To cancel an uncommitted merge (and lose your changes),
6050 To cancel an uncommitted merge (and lose your changes),
6051 use :hg:`update --clean .`.
6051 use :hg:`update --clean .`.
6052
6052
6053 With no revision specified, revert the specified files or directories
6053 With no revision specified, revert the specified files or directories
6054 to the contents they had in the parent of the working directory.
6054 to the contents they had in the parent of the working directory.
6055 This restores the contents of files to an unmodified
6055 This restores the contents of files to an unmodified
6056 state and unschedules adds, removes, copies, and renames. If the
6056 state and unschedules adds, removes, copies, and renames. If the
6057 working directory has two parents, you must explicitly specify a
6057 working directory has two parents, you must explicitly specify a
6058 revision.
6058 revision.
6059
6059
6060 Using the -r/--rev or -d/--date options, revert the given files or
6060 Using the -r/--rev or -d/--date options, revert the given files or
6061 directories to their states as of a specific revision. Because
6061 directories to their states as of a specific revision. Because
6062 revert does not change the working directory parents, this will
6062 revert does not change the working directory parents, this will
6063 cause these files to appear modified. This can be helpful to "back
6063 cause these files to appear modified. This can be helpful to "back
6064 out" some or all of an earlier change. See :hg:`backout` for a
6064 out" some or all of an earlier change. See :hg:`backout` for a
6065 related method.
6065 related method.
6066
6066
6067 Modified files are saved with a .orig suffix before reverting.
6067 Modified files are saved with a .orig suffix before reverting.
6068 To disable these backups, use --no-backup.
6068 To disable these backups, use --no-backup.
6069
6069
6070 See :hg:`help dates` for a list of formats valid for -d/--date.
6070 See :hg:`help dates` for a list of formats valid for -d/--date.
6071
6071
6072 See :hg:`help backout` for a way to reverse the effect of an
6072 See :hg:`help backout` for a way to reverse the effect of an
6073 earlier changeset.
6073 earlier changeset.
6074
6074
6075 Returns 0 on success.
6075 Returns 0 on success.
6076 """
6076 """
6077
6077
6078 if opts.get("date"):
6078 if opts.get("date"):
6079 if opts.get("rev"):
6079 if opts.get("rev"):
6080 raise error.Abort(_("you can't specify a revision and a date"))
6080 raise error.Abort(_("you can't specify a revision and a date"))
6081 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6081 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6082
6082
6083 parent, p2 = repo.dirstate.parents()
6083 parent, p2 = repo.dirstate.parents()
6084 if not opts.get('rev') and p2 != nullid:
6084 if not opts.get('rev') and p2 != nullid:
6085 # revert after merge is a trap for new users (issue2915)
6085 # revert after merge is a trap for new users (issue2915)
6086 raise error.Abort(_('uncommitted merge with no revision specified'),
6086 raise error.Abort(_('uncommitted merge with no revision specified'),
6087 hint=_('use "hg update" or see "hg help revert"'))
6087 hint=_('use "hg update" or see "hg help revert"'))
6088
6088
6089 ctx = scmutil.revsingle(repo, opts.get('rev'))
6089 ctx = scmutil.revsingle(repo, opts.get('rev'))
6090
6090
6091 if (not (pats or opts.get('include') or opts.get('exclude') or
6091 if (not (pats or opts.get('include') or opts.get('exclude') or
6092 opts.get('all') or opts.get('interactive'))):
6092 opts.get('all') or opts.get('interactive'))):
6093 msg = _("no files or directories specified")
6093 msg = _("no files or directories specified")
6094 if p2 != nullid:
6094 if p2 != nullid:
6095 hint = _("uncommitted merge, use --all to discard all changes,"
6095 hint = _("uncommitted merge, use --all to discard all changes,"
6096 " or 'hg update -C .' to abort the merge")
6096 " or 'hg update -C .' to abort the merge")
6097 raise error.Abort(msg, hint=hint)
6097 raise error.Abort(msg, hint=hint)
6098 dirty = any(repo.status())
6098 dirty = any(repo.status())
6099 node = ctx.node()
6099 node = ctx.node()
6100 if node != parent:
6100 if node != parent:
6101 if dirty:
6101 if dirty:
6102 hint = _("uncommitted changes, use --all to discard all"
6102 hint = _("uncommitted changes, use --all to discard all"
6103 " changes, or 'hg update %s' to update") % ctx.rev()
6103 " changes, or 'hg update %s' to update") % ctx.rev()
6104 else:
6104 else:
6105 hint = _("use --all to revert all files,"
6105 hint = _("use --all to revert all files,"
6106 " or 'hg update %s' to update") % ctx.rev()
6106 " or 'hg update %s' to update") % ctx.rev()
6107 elif dirty:
6107 elif dirty:
6108 hint = _("uncommitted changes, use --all to discard all changes")
6108 hint = _("uncommitted changes, use --all to discard all changes")
6109 else:
6109 else:
6110 hint = _("use --all to revert all files")
6110 hint = _("use --all to revert all files")
6111 raise error.Abort(msg, hint=hint)
6111 raise error.Abort(msg, hint=hint)
6112
6112
6113 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6113 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6114
6114
6115 @command('rollback', dryrunopts +
6115 @command('rollback', dryrunopts +
6116 [('f', 'force', False, _('ignore safety measures'))])
6116 [('f', 'force', False, _('ignore safety measures'))])
6117 def rollback(ui, repo, **opts):
6117 def rollback(ui, repo, **opts):
6118 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6118 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6119
6119
6120 Please use :hg:`commit --amend` instead of rollback to correct
6120 Please use :hg:`commit --amend` instead of rollback to correct
6121 mistakes in the last commit.
6121 mistakes in the last commit.
6122
6122
6123 This command should be used with care. There is only one level of
6123 This command should be used with care. There is only one level of
6124 rollback, and there is no way to undo a rollback. It will also
6124 rollback, and there is no way to undo a rollback. It will also
6125 restore the dirstate at the time of the last transaction, losing
6125 restore the dirstate at the time of the last transaction, losing
6126 any dirstate changes since that time. This command does not alter
6126 any dirstate changes since that time. This command does not alter
6127 the working directory.
6127 the working directory.
6128
6128
6129 Transactions are used to encapsulate the effects of all commands
6129 Transactions are used to encapsulate the effects of all commands
6130 that create new changesets or propagate existing changesets into a
6130 that create new changesets or propagate existing changesets into a
6131 repository.
6131 repository.
6132
6132
6133 .. container:: verbose
6133 .. container:: verbose
6134
6134
6135 For example, the following commands are transactional, and their
6135 For example, the following commands are transactional, and their
6136 effects can be rolled back:
6136 effects can be rolled back:
6137
6137
6138 - commit
6138 - commit
6139 - import
6139 - import
6140 - pull
6140 - pull
6141 - push (with this repository as the destination)
6141 - push (with this repository as the destination)
6142 - unbundle
6142 - unbundle
6143
6143
6144 To avoid permanent data loss, rollback will refuse to rollback a
6144 To avoid permanent data loss, rollback will refuse to rollback a
6145 commit transaction if it isn't checked out. Use --force to
6145 commit transaction if it isn't checked out. Use --force to
6146 override this protection.
6146 override this protection.
6147
6147
6148 This command is not intended for use on public repositories. Once
6148 This command is not intended for use on public repositories. Once
6149 changes are visible for pull by other users, rolling a transaction
6149 changes are visible for pull by other users, rolling a transaction
6150 back locally is ineffective (someone else may already have pulled
6150 back locally is ineffective (someone else may already have pulled
6151 the changes). Furthermore, a race is possible with readers of the
6151 the changes). Furthermore, a race is possible with readers of the
6152 repository; for example an in-progress pull from the repository
6152 repository; for example an in-progress pull from the repository
6153 may fail if a rollback is performed.
6153 may fail if a rollback is performed.
6154
6154
6155 Returns 0 on success, 1 if no rollback data is available.
6155 Returns 0 on success, 1 if no rollback data is available.
6156 """
6156 """
6157 return repo.rollback(dryrun=opts.get('dry_run'),
6157 return repo.rollback(dryrun=opts.get('dry_run'),
6158 force=opts.get('force'))
6158 force=opts.get('force'))
6159
6159
6160 @command('root', [])
6160 @command('root', [])
6161 def root(ui, repo):
6161 def root(ui, repo):
6162 """print the root (top) of the current working directory
6162 """print the root (top) of the current working directory
6163
6163
6164 Print the root directory of the current repository.
6164 Print the root directory of the current repository.
6165
6165
6166 Returns 0 on success.
6166 Returns 0 on success.
6167 """
6167 """
6168 ui.write(repo.root + "\n")
6168 ui.write(repo.root + "\n")
6169
6169
6170 @command('^serve',
6170 @command('^serve',
6171 [('A', 'accesslog', '', _('name of access log file to write to'),
6171 [('A', 'accesslog', '', _('name of access log file to write to'),
6172 _('FILE')),
6172 _('FILE')),
6173 ('d', 'daemon', None, _('run server in background')),
6173 ('d', 'daemon', None, _('run server in background')),
6174 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6174 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6175 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6175 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6176 # use string type, then we can check if something was passed
6176 # use string type, then we can check if something was passed
6177 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6177 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6178 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6178 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6179 _('ADDR')),
6179 _('ADDR')),
6180 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6180 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6181 _('PREFIX')),
6181 _('PREFIX')),
6182 ('n', 'name', '',
6182 ('n', 'name', '',
6183 _('name to show in web pages (default: working directory)'), _('NAME')),
6183 _('name to show in web pages (default: working directory)'), _('NAME')),
6184 ('', 'web-conf', '',
6184 ('', 'web-conf', '',
6185 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6185 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6186 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6186 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6187 _('FILE')),
6187 _('FILE')),
6188 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6188 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6189 ('', 'stdio', None, _('for remote clients')),
6189 ('', 'stdio', None, _('for remote clients')),
6190 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6190 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6191 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6191 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6192 ('', 'style', '', _('template style to use'), _('STYLE')),
6192 ('', 'style', '', _('template style to use'), _('STYLE')),
6193 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6193 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6194 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6194 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6195 _('[OPTION]...'),
6195 _('[OPTION]...'),
6196 optionalrepo=True)
6196 optionalrepo=True)
6197 def serve(ui, repo, **opts):
6197 def serve(ui, repo, **opts):
6198 """start stand-alone webserver
6198 """start stand-alone webserver
6199
6199
6200 Start a local HTTP repository browser and pull server. You can use
6200 Start a local HTTP repository browser and pull server. You can use
6201 this for ad-hoc sharing and browsing of repositories. It is
6201 this for ad-hoc sharing and browsing of repositories. It is
6202 recommended to use a real web server to serve a repository for
6202 recommended to use a real web server to serve a repository for
6203 longer periods of time.
6203 longer periods of time.
6204
6204
6205 Please note that the server does not implement access control.
6205 Please note that the server does not implement access control.
6206 This means that, by default, anybody can read from the server and
6206 This means that, by default, anybody can read from the server and
6207 nobody can write to it by default. Set the ``web.allow_push``
6207 nobody can write to it by default. Set the ``web.allow_push``
6208 option to ``*`` to allow everybody to push to the server. You
6208 option to ``*`` to allow everybody to push to the server. You
6209 should use a real web server if you need to authenticate users.
6209 should use a real web server if you need to authenticate users.
6210
6210
6211 By default, the server logs accesses to stdout and errors to
6211 By default, the server logs accesses to stdout and errors to
6212 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6212 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6213 files.
6213 files.
6214
6214
6215 To have the server choose a free port number to listen on, specify
6215 To have the server choose a free port number to listen on, specify
6216 a port number of 0; in this case, the server will print the port
6216 a port number of 0; in this case, the server will print the port
6217 number it uses.
6217 number it uses.
6218
6218
6219 Returns 0 on success.
6219 Returns 0 on success.
6220 """
6220 """
6221
6221
6222 if opts["stdio"] and opts["cmdserver"]:
6222 if opts["stdio"] and opts["cmdserver"]:
6223 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6223 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6224
6224
6225 if opts["stdio"]:
6225 if opts["stdio"]:
6226 if repo is None:
6226 if repo is None:
6227 raise error.RepoError(_("there is no Mercurial repository here"
6227 raise error.RepoError(_("there is no Mercurial repository here"
6228 " (.hg not found)"))
6228 " (.hg not found)"))
6229 s = sshserver.sshserver(ui, repo)
6229 s = sshserver.sshserver(ui, repo)
6230 s.serve_forever()
6230 s.serve_forever()
6231
6231
6232 if opts["cmdserver"]:
6232 if opts["cmdserver"]:
6233 service = commandserver.createservice(ui, repo, opts)
6233 service = commandserver.createservice(ui, repo, opts)
6234 else:
6234 else:
6235 service = hgweb.createservice(ui, repo, opts)
6235 service = hgweb.createservice(ui, repo, opts)
6236 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6236 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6237
6237
6238 @command('^status|st',
6238 @command('^status|st',
6239 [('A', 'all', None, _('show status of all files')),
6239 [('A', 'all', None, _('show status of all files')),
6240 ('m', 'modified', None, _('show only modified files')),
6240 ('m', 'modified', None, _('show only modified files')),
6241 ('a', 'added', None, _('show only added files')),
6241 ('a', 'added', None, _('show only added files')),
6242 ('r', 'removed', None, _('show only removed files')),
6242 ('r', 'removed', None, _('show only removed files')),
6243 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6243 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6244 ('c', 'clean', None, _('show only files without changes')),
6244 ('c', 'clean', None, _('show only files without changes')),
6245 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6245 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6246 ('i', 'ignored', None, _('show only ignored files')),
6246 ('i', 'ignored', None, _('show only ignored files')),
6247 ('n', 'no-status', None, _('hide status prefix')),
6247 ('n', 'no-status', None, _('hide status prefix')),
6248 ('C', 'copies', None, _('show source of copied files')),
6248 ('C', 'copies', None, _('show source of copied files')),
6249 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6249 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6250 ('', 'rev', [], _('show difference from revision'), _('REV')),
6250 ('', 'rev', [], _('show difference from revision'), _('REV')),
6251 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6251 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6252 ] + walkopts + subrepoopts + formatteropts,
6252 ] + walkopts + subrepoopts + formatteropts,
6253 _('[OPTION]... [FILE]...'),
6253 _('[OPTION]... [FILE]...'),
6254 inferrepo=True)
6254 inferrepo=True)
6255 def status(ui, repo, *pats, **opts):
6255 def status(ui, repo, *pats, **opts):
6256 """show changed files in the working directory
6256 """show changed files in the working directory
6257
6257
6258 Show status of files in the repository. If names are given, only
6258 Show status of files in the repository. If names are given, only
6259 files that match are shown. Files that are clean or ignored or
6259 files that match are shown. Files that are clean or ignored or
6260 the source of a copy/move operation, are not listed unless
6260 the source of a copy/move operation, are not listed unless
6261 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6261 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6262 Unless options described with "show only ..." are given, the
6262 Unless options described with "show only ..." are given, the
6263 options -mardu are used.
6263 options -mardu are used.
6264
6264
6265 Option -q/--quiet hides untracked (unknown and ignored) files
6265 Option -q/--quiet hides untracked (unknown and ignored) files
6266 unless explicitly requested with -u/--unknown or -i/--ignored.
6266 unless explicitly requested with -u/--unknown or -i/--ignored.
6267
6267
6268 .. note::
6268 .. note::
6269
6269
6270 :hg:`status` may appear to disagree with diff if permissions have
6270 :hg:`status` may appear to disagree with diff if permissions have
6271 changed or a merge has occurred. The standard diff format does
6271 changed or a merge has occurred. The standard diff format does
6272 not report permission changes and diff only reports changes
6272 not report permission changes and diff only reports changes
6273 relative to one merge parent.
6273 relative to one merge parent.
6274
6274
6275 If one revision is given, it is used as the base revision.
6275 If one revision is given, it is used as the base revision.
6276 If two revisions are given, the differences between them are
6276 If two revisions are given, the differences between them are
6277 shown. The --change option can also be used as a shortcut to list
6277 shown. The --change option can also be used as a shortcut to list
6278 the changed files of a revision from its first parent.
6278 the changed files of a revision from its first parent.
6279
6279
6280 The codes used to show the status of files are::
6280 The codes used to show the status of files are::
6281
6281
6282 M = modified
6282 M = modified
6283 A = added
6283 A = added
6284 R = removed
6284 R = removed
6285 C = clean
6285 C = clean
6286 ! = missing (deleted by non-hg command, but still tracked)
6286 ! = missing (deleted by non-hg command, but still tracked)
6287 ? = not tracked
6287 ? = not tracked
6288 I = ignored
6288 I = ignored
6289 = origin of the previous file (with --copies)
6289 = origin of the previous file (with --copies)
6290
6290
6291 .. container:: verbose
6291 .. container:: verbose
6292
6292
6293 Examples:
6293 Examples:
6294
6294
6295 - show changes in the working directory relative to a
6295 - show changes in the working directory relative to a
6296 changeset::
6296 changeset::
6297
6297
6298 hg status --rev 9353
6298 hg status --rev 9353
6299
6299
6300 - show changes in the working directory relative to the
6300 - show changes in the working directory relative to the
6301 current directory (see :hg:`help patterns` for more information)::
6301 current directory (see :hg:`help patterns` for more information)::
6302
6302
6303 hg status re:
6303 hg status re:
6304
6304
6305 - show all changes including copies in an existing changeset::
6305 - show all changes including copies in an existing changeset::
6306
6306
6307 hg status --copies --change 9353
6307 hg status --copies --change 9353
6308
6308
6309 - get a NUL separated list of added files, suitable for xargs::
6309 - get a NUL separated list of added files, suitable for xargs::
6310
6310
6311 hg status -an0
6311 hg status -an0
6312
6312
6313 Returns 0 on success.
6313 Returns 0 on success.
6314 """
6314 """
6315
6315
6316 revs = opts.get('rev')
6316 revs = opts.get('rev')
6317 change = opts.get('change')
6317 change = opts.get('change')
6318
6318
6319 if revs and change:
6319 if revs and change:
6320 msg = _('cannot specify --rev and --change at the same time')
6320 msg = _('cannot specify --rev and --change at the same time')
6321 raise error.Abort(msg)
6321 raise error.Abort(msg)
6322 elif change:
6322 elif change:
6323 node2 = scmutil.revsingle(repo, change, None).node()
6323 node2 = scmutil.revsingle(repo, change, None).node()
6324 node1 = repo[node2].p1().node()
6324 node1 = repo[node2].p1().node()
6325 else:
6325 else:
6326 node1, node2 = scmutil.revpair(repo, revs)
6326 node1, node2 = scmutil.revpair(repo, revs)
6327
6327
6328 if pats:
6328 if pats:
6329 cwd = repo.getcwd()
6329 cwd = repo.getcwd()
6330 else:
6330 else:
6331 cwd = ''
6331 cwd = ''
6332
6332
6333 if opts.get('print0'):
6333 if opts.get('print0'):
6334 end = '\0'
6334 end = '\0'
6335 else:
6335 else:
6336 end = '\n'
6336 end = '\n'
6337 copy = {}
6337 copy = {}
6338 states = 'modified added removed deleted unknown ignored clean'.split()
6338 states = 'modified added removed deleted unknown ignored clean'.split()
6339 show = [k for k in states if opts.get(k)]
6339 show = [k for k in states if opts.get(k)]
6340 if opts.get('all'):
6340 if opts.get('all'):
6341 show += ui.quiet and (states[:4] + ['clean']) or states
6341 show += ui.quiet and (states[:4] + ['clean']) or states
6342 if not show:
6342 if not show:
6343 if ui.quiet:
6343 if ui.quiet:
6344 show = states[:4]
6344 show = states[:4]
6345 else:
6345 else:
6346 show = states[:5]
6346 show = states[:5]
6347
6347
6348 m = scmutil.match(repo[node2], pats, opts)
6348 m = scmutil.match(repo[node2], pats, opts)
6349 stat = repo.status(node1, node2, m,
6349 stat = repo.status(node1, node2, m,
6350 'ignored' in show, 'clean' in show, 'unknown' in show,
6350 'ignored' in show, 'clean' in show, 'unknown' in show,
6351 opts.get('subrepos'))
6351 opts.get('subrepos'))
6352 changestates = zip(states, 'MAR!?IC', stat)
6352 changestates = zip(states, 'MAR!?IC', stat)
6353
6353
6354 if (opts.get('all') or opts.get('copies')
6354 if (opts.get('all') or opts.get('copies')
6355 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6355 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6356 copy = copies.pathcopies(repo[node1], repo[node2], m)
6356 copy = copies.pathcopies(repo[node1], repo[node2], m)
6357
6357
6358 fm = ui.formatter('status', opts)
6358 fm = ui.formatter('status', opts)
6359 fmt = '%s' + end
6359 fmt = '%s' + end
6360 showchar = not opts.get('no_status')
6360 showchar = not opts.get('no_status')
6361
6361
6362 for state, char, files in changestates:
6362 for state, char, files in changestates:
6363 if state in show:
6363 if state in show:
6364 label = 'status.' + state
6364 label = 'status.' + state
6365 for f in files:
6365 for f in files:
6366 fm.startitem()
6366 fm.startitem()
6367 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6367 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6368 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6368 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6369 if f in copy:
6369 if f in copy:
6370 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6370 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6371 label='status.copied')
6371 label='status.copied')
6372 fm.end()
6372 fm.end()
6373
6373
6374 @command('^summary|sum',
6374 @command('^summary|sum',
6375 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6375 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6376 def summary(ui, repo, **opts):
6376 def summary(ui, repo, **opts):
6377 """summarize working directory state
6377 """summarize working directory state
6378
6378
6379 This generates a brief summary of the working directory state,
6379 This generates a brief summary of the working directory state,
6380 including parents, branch, commit status, phase and available updates.
6380 including parents, branch, commit status, phase and available updates.
6381
6381
6382 With the --remote option, this will check the default paths for
6382 With the --remote option, this will check the default paths for
6383 incoming and outgoing changes. This can be time-consuming.
6383 incoming and outgoing changes. This can be time-consuming.
6384
6384
6385 Returns 0 on success.
6385 Returns 0 on success.
6386 """
6386 """
6387
6387
6388 ctx = repo[None]
6388 ctx = repo[None]
6389 parents = ctx.parents()
6389 parents = ctx.parents()
6390 pnode = parents[0].node()
6390 pnode = parents[0].node()
6391 marks = []
6391 marks = []
6392
6392
6393 for p in parents:
6393 for p in parents:
6394 # label with log.changeset (instead of log.parent) since this
6394 # label with log.changeset (instead of log.parent) since this
6395 # shows a working directory parent *changeset*:
6395 # shows a working directory parent *changeset*:
6396 # i18n: column positioning for "hg summary"
6396 # i18n: column positioning for "hg summary"
6397 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6397 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6398 label='log.changeset changeset.%s' % p.phasestr())
6398 label='log.changeset changeset.%s' % p.phasestr())
6399 ui.write(' '.join(p.tags()), label='log.tag')
6399 ui.write(' '.join(p.tags()), label='log.tag')
6400 if p.bookmarks():
6400 if p.bookmarks():
6401 marks.extend(p.bookmarks())
6401 marks.extend(p.bookmarks())
6402 if p.rev() == -1:
6402 if p.rev() == -1:
6403 if not len(repo):
6403 if not len(repo):
6404 ui.write(_(' (empty repository)'))
6404 ui.write(_(' (empty repository)'))
6405 else:
6405 else:
6406 ui.write(_(' (no revision checked out)'))
6406 ui.write(_(' (no revision checked out)'))
6407 ui.write('\n')
6407 ui.write('\n')
6408 if p.description():
6408 if p.description():
6409 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6409 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6410 label='log.summary')
6410 label='log.summary')
6411
6411
6412 branch = ctx.branch()
6412 branch = ctx.branch()
6413 bheads = repo.branchheads(branch)
6413 bheads = repo.branchheads(branch)
6414 # i18n: column positioning for "hg summary"
6414 # i18n: column positioning for "hg summary"
6415 m = _('branch: %s\n') % branch
6415 m = _('branch: %s\n') % branch
6416 if branch != 'default':
6416 if branch != 'default':
6417 ui.write(m, label='log.branch')
6417 ui.write(m, label='log.branch')
6418 else:
6418 else:
6419 ui.status(m, label='log.branch')
6419 ui.status(m, label='log.branch')
6420
6420
6421 if marks:
6421 if marks:
6422 active = repo._activebookmark
6422 active = repo._activebookmark
6423 # i18n: column positioning for "hg summary"
6423 # i18n: column positioning for "hg summary"
6424 ui.write(_('bookmarks:'), label='log.bookmark')
6424 ui.write(_('bookmarks:'), label='log.bookmark')
6425 if active is not None:
6425 if active is not None:
6426 if active in marks:
6426 if active in marks:
6427 ui.write(' *' + active, label=activebookmarklabel)
6427 ui.write(' *' + active, label=activebookmarklabel)
6428 marks.remove(active)
6428 marks.remove(active)
6429 else:
6429 else:
6430 ui.write(' [%s]' % active, label=activebookmarklabel)
6430 ui.write(' [%s]' % active, label=activebookmarklabel)
6431 for m in marks:
6431 for m in marks:
6432 ui.write(' ' + m, label='log.bookmark')
6432 ui.write(' ' + m, label='log.bookmark')
6433 ui.write('\n', label='log.bookmark')
6433 ui.write('\n', label='log.bookmark')
6434
6434
6435 status = repo.status(unknown=True)
6435 status = repo.status(unknown=True)
6436
6436
6437 c = repo.dirstate.copies()
6437 c = repo.dirstate.copies()
6438 copied, renamed = [], []
6438 copied, renamed = [], []
6439 for d, s in c.iteritems():
6439 for d, s in c.iteritems():
6440 if s in status.removed:
6440 if s in status.removed:
6441 status.removed.remove(s)
6441 status.removed.remove(s)
6442 renamed.append(d)
6442 renamed.append(d)
6443 else:
6443 else:
6444 copied.append(d)
6444 copied.append(d)
6445 if d in status.added:
6445 if d in status.added:
6446 status.added.remove(d)
6446 status.added.remove(d)
6447
6447
6448 try:
6448 try:
6449 ms = mergemod.mergestate.read(repo)
6449 ms = mergemod.mergestate.read(repo)
6450 except error.UnsupportedMergeRecords as e:
6450 except error.UnsupportedMergeRecords as e:
6451 s = ' '.join(e.recordtypes)
6451 s = ' '.join(e.recordtypes)
6452 ui.warn(
6452 ui.warn(
6453 _('warning: merge state has unsupported record types: %s\n') % s)
6453 _('warning: merge state has unsupported record types: %s\n') % s)
6454 unresolved = 0
6454 unresolved = 0
6455 else:
6455 else:
6456 unresolved = [f for f in ms if ms[f] == 'u']
6456 unresolved = [f for f in ms if ms[f] == 'u']
6457
6457
6458 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6458 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6459
6459
6460 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6460 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6461 (ui.label(_('%d added'), 'status.added'), status.added),
6461 (ui.label(_('%d added'), 'status.added'), status.added),
6462 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6462 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6463 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6463 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6464 (ui.label(_('%d copied'), 'status.copied'), copied),
6464 (ui.label(_('%d copied'), 'status.copied'), copied),
6465 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6465 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6466 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6466 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6467 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6467 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6468 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6468 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6469 t = []
6469 t = []
6470 for l, s in labels:
6470 for l, s in labels:
6471 if s:
6471 if s:
6472 t.append(l % len(s))
6472 t.append(l % len(s))
6473
6473
6474 t = ', '.join(t)
6474 t = ', '.join(t)
6475 cleanworkdir = False
6475 cleanworkdir = False
6476
6476
6477 if repo.vfs.exists('graftstate'):
6477 if repo.vfs.exists('graftstate'):
6478 t += _(' (graft in progress)')
6478 t += _(' (graft in progress)')
6479 if repo.vfs.exists('updatestate'):
6479 if repo.vfs.exists('updatestate'):
6480 t += _(' (interrupted update)')
6480 t += _(' (interrupted update)')
6481 elif len(parents) > 1:
6481 elif len(parents) > 1:
6482 t += _(' (merge)')
6482 t += _(' (merge)')
6483 elif branch != parents[0].branch():
6483 elif branch != parents[0].branch():
6484 t += _(' (new branch)')
6484 t += _(' (new branch)')
6485 elif (parents[0].closesbranch() and
6485 elif (parents[0].closesbranch() and
6486 pnode in repo.branchheads(branch, closed=True)):
6486 pnode in repo.branchheads(branch, closed=True)):
6487 t += _(' (head closed)')
6487 t += _(' (head closed)')
6488 elif not (status.modified or status.added or status.removed or renamed or
6488 elif not (status.modified or status.added or status.removed or renamed or
6489 copied or subs):
6489 copied or subs):
6490 t += _(' (clean)')
6490 t += _(' (clean)')
6491 cleanworkdir = True
6491 cleanworkdir = True
6492 elif pnode not in bheads:
6492 elif pnode not in bheads:
6493 t += _(' (new branch head)')
6493 t += _(' (new branch head)')
6494
6494
6495 if parents:
6495 if parents:
6496 pendingphase = max(p.phase() for p in parents)
6496 pendingphase = max(p.phase() for p in parents)
6497 else:
6497 else:
6498 pendingphase = phases.public
6498 pendingphase = phases.public
6499
6499
6500 if pendingphase > phases.newcommitphase(ui):
6500 if pendingphase > phases.newcommitphase(ui):
6501 t += ' (%s)' % phases.phasenames[pendingphase]
6501 t += ' (%s)' % phases.phasenames[pendingphase]
6502
6502
6503 if cleanworkdir:
6503 if cleanworkdir:
6504 # i18n: column positioning for "hg summary"
6504 # i18n: column positioning for "hg summary"
6505 ui.status(_('commit: %s\n') % t.strip())
6505 ui.status(_('commit: %s\n') % t.strip())
6506 else:
6506 else:
6507 # i18n: column positioning for "hg summary"
6507 # i18n: column positioning for "hg summary"
6508 ui.write(_('commit: %s\n') % t.strip())
6508 ui.write(_('commit: %s\n') % t.strip())
6509
6509
6510 # all ancestors of branch heads - all ancestors of parent = new csets
6510 # all ancestors of branch heads - all ancestors of parent = new csets
6511 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6511 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6512 bheads))
6512 bheads))
6513
6513
6514 if new == 0:
6514 if new == 0:
6515 # i18n: column positioning for "hg summary"
6515 # i18n: column positioning for "hg summary"
6516 ui.status(_('update: (current)\n'))
6516 ui.status(_('update: (current)\n'))
6517 elif pnode not in bheads:
6517 elif pnode not in bheads:
6518 # i18n: column positioning for "hg summary"
6518 # i18n: column positioning for "hg summary"
6519 ui.write(_('update: %d new changesets (update)\n') % new)
6519 ui.write(_('update: %d new changesets (update)\n') % new)
6520 else:
6520 else:
6521 # i18n: column positioning for "hg summary"
6521 # i18n: column positioning for "hg summary"
6522 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6522 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6523 (new, len(bheads)))
6523 (new, len(bheads)))
6524
6524
6525 t = []
6525 t = []
6526 draft = len(repo.revs('draft()'))
6526 draft = len(repo.revs('draft()'))
6527 if draft:
6527 if draft:
6528 t.append(_('%d draft') % draft)
6528 t.append(_('%d draft') % draft)
6529 secret = len(repo.revs('secret()'))
6529 secret = len(repo.revs('secret()'))
6530 if secret:
6530 if secret:
6531 t.append(_('%d secret') % secret)
6531 t.append(_('%d secret') % secret)
6532
6532
6533 if draft or secret:
6533 if draft or secret:
6534 ui.status(_('phases: %s\n') % ', '.join(t))
6534 ui.status(_('phases: %s\n') % ', '.join(t))
6535
6535
6536 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6536 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6537 for trouble in ("unstable", "divergent", "bumped"):
6537 for trouble in ("unstable", "divergent", "bumped"):
6538 numtrouble = len(repo.revs(trouble + "()"))
6538 numtrouble = len(repo.revs(trouble + "()"))
6539 # We write all the possibilities to ease translation
6539 # We write all the possibilities to ease translation
6540 troublemsg = {
6540 troublemsg = {
6541 "unstable": _("unstable: %d changesets"),
6541 "unstable": _("unstable: %d changesets"),
6542 "divergent": _("divergent: %d changesets"),
6542 "divergent": _("divergent: %d changesets"),
6543 "bumped": _("bumped: %d changesets"),
6543 "bumped": _("bumped: %d changesets"),
6544 }
6544 }
6545 if numtrouble > 0:
6545 if numtrouble > 0:
6546 ui.status(troublemsg[trouble] % numtrouble + "\n")
6546 ui.status(troublemsg[trouble] % numtrouble + "\n")
6547
6547
6548 cmdutil.summaryhooks(ui, repo)
6548 cmdutil.summaryhooks(ui, repo)
6549
6549
6550 if opts.get('remote'):
6550 if opts.get('remote'):
6551 needsincoming, needsoutgoing = True, True
6551 needsincoming, needsoutgoing = True, True
6552 else:
6552 else:
6553 needsincoming, needsoutgoing = False, False
6553 needsincoming, needsoutgoing = False, False
6554 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6554 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6555 if i:
6555 if i:
6556 needsincoming = True
6556 needsincoming = True
6557 if o:
6557 if o:
6558 needsoutgoing = True
6558 needsoutgoing = True
6559 if not needsincoming and not needsoutgoing:
6559 if not needsincoming and not needsoutgoing:
6560 return
6560 return
6561
6561
6562 def getincoming():
6562 def getincoming():
6563 source, branches = hg.parseurl(ui.expandpath('default'))
6563 source, branches = hg.parseurl(ui.expandpath('default'))
6564 sbranch = branches[0]
6564 sbranch = branches[0]
6565 try:
6565 try:
6566 other = hg.peer(repo, {}, source)
6566 other = hg.peer(repo, {}, source)
6567 except error.RepoError:
6567 except error.RepoError:
6568 if opts.get('remote'):
6568 if opts.get('remote'):
6569 raise
6569 raise
6570 return source, sbranch, None, None, None
6570 return source, sbranch, None, None, None
6571 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6571 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6572 if revs:
6572 if revs:
6573 revs = [other.lookup(rev) for rev in revs]
6573 revs = [other.lookup(rev) for rev in revs]
6574 ui.debug('comparing with %s\n' % util.hidepassword(source))
6574 ui.debug('comparing with %s\n' % util.hidepassword(source))
6575 repo.ui.pushbuffer()
6575 repo.ui.pushbuffer()
6576 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6576 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6577 repo.ui.popbuffer()
6577 repo.ui.popbuffer()
6578 return source, sbranch, other, commoninc, commoninc[1]
6578 return source, sbranch, other, commoninc, commoninc[1]
6579
6579
6580 if needsincoming:
6580 if needsincoming:
6581 source, sbranch, sother, commoninc, incoming = getincoming()
6581 source, sbranch, sother, commoninc, incoming = getincoming()
6582 else:
6582 else:
6583 source = sbranch = sother = commoninc = incoming = None
6583 source = sbranch = sother = commoninc = incoming = None
6584
6584
6585 def getoutgoing():
6585 def getoutgoing():
6586 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6586 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6587 dbranch = branches[0]
6587 dbranch = branches[0]
6588 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6588 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6589 if source != dest:
6589 if source != dest:
6590 try:
6590 try:
6591 dother = hg.peer(repo, {}, dest)
6591 dother = hg.peer(repo, {}, dest)
6592 except error.RepoError:
6592 except error.RepoError:
6593 if opts.get('remote'):
6593 if opts.get('remote'):
6594 raise
6594 raise
6595 return dest, dbranch, None, None
6595 return dest, dbranch, None, None
6596 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6596 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6597 elif sother is None:
6597 elif sother is None:
6598 # there is no explicit destination peer, but source one is invalid
6598 # there is no explicit destination peer, but source one is invalid
6599 return dest, dbranch, None, None
6599 return dest, dbranch, None, None
6600 else:
6600 else:
6601 dother = sother
6601 dother = sother
6602 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6602 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6603 common = None
6603 common = None
6604 else:
6604 else:
6605 common = commoninc
6605 common = commoninc
6606 if revs:
6606 if revs:
6607 revs = [repo.lookup(rev) for rev in revs]
6607 revs = [repo.lookup(rev) for rev in revs]
6608 repo.ui.pushbuffer()
6608 repo.ui.pushbuffer()
6609 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6609 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6610 commoninc=common)
6610 commoninc=common)
6611 repo.ui.popbuffer()
6611 repo.ui.popbuffer()
6612 return dest, dbranch, dother, outgoing
6612 return dest, dbranch, dother, outgoing
6613
6613
6614 if needsoutgoing:
6614 if needsoutgoing:
6615 dest, dbranch, dother, outgoing = getoutgoing()
6615 dest, dbranch, dother, outgoing = getoutgoing()
6616 else:
6616 else:
6617 dest = dbranch = dother = outgoing = None
6617 dest = dbranch = dother = outgoing = None
6618
6618
6619 if opts.get('remote'):
6619 if opts.get('remote'):
6620 t = []
6620 t = []
6621 if incoming:
6621 if incoming:
6622 t.append(_('1 or more incoming'))
6622 t.append(_('1 or more incoming'))
6623 o = outgoing.missing
6623 o = outgoing.missing
6624 if o:
6624 if o:
6625 t.append(_('%d outgoing') % len(o))
6625 t.append(_('%d outgoing') % len(o))
6626 other = dother or sother
6626 other = dother or sother
6627 if 'bookmarks' in other.listkeys('namespaces'):
6627 if 'bookmarks' in other.listkeys('namespaces'):
6628 counts = bookmarks.summary(repo, other)
6628 counts = bookmarks.summary(repo, other)
6629 if counts[0] > 0:
6629 if counts[0] > 0:
6630 t.append(_('%d incoming bookmarks') % counts[0])
6630 t.append(_('%d incoming bookmarks') % counts[0])
6631 if counts[1] > 0:
6631 if counts[1] > 0:
6632 t.append(_('%d outgoing bookmarks') % counts[1])
6632 t.append(_('%d outgoing bookmarks') % counts[1])
6633
6633
6634 if t:
6634 if t:
6635 # i18n: column positioning for "hg summary"
6635 # i18n: column positioning for "hg summary"
6636 ui.write(_('remote: %s\n') % (', '.join(t)))
6636 ui.write(_('remote: %s\n') % (', '.join(t)))
6637 else:
6637 else:
6638 # i18n: column positioning for "hg summary"
6638 # i18n: column positioning for "hg summary"
6639 ui.status(_('remote: (synced)\n'))
6639 ui.status(_('remote: (synced)\n'))
6640
6640
6641 cmdutil.summaryremotehooks(ui, repo, opts,
6641 cmdutil.summaryremotehooks(ui, repo, opts,
6642 ((source, sbranch, sother, commoninc),
6642 ((source, sbranch, sother, commoninc),
6643 (dest, dbranch, dother, outgoing)))
6643 (dest, dbranch, dother, outgoing)))
6644
6644
6645 @command('tag',
6645 @command('tag',
6646 [('f', 'force', None, _('force tag')),
6646 [('f', 'force', None, _('force tag')),
6647 ('l', 'local', None, _('make the tag local')),
6647 ('l', 'local', None, _('make the tag local')),
6648 ('r', 'rev', '', _('revision to tag'), _('REV')),
6648 ('r', 'rev', '', _('revision to tag'), _('REV')),
6649 ('', 'remove', None, _('remove a tag')),
6649 ('', 'remove', None, _('remove a tag')),
6650 # -l/--local is already there, commitopts cannot be used
6650 # -l/--local is already there, commitopts cannot be used
6651 ('e', 'edit', None, _('invoke editor on commit messages')),
6651 ('e', 'edit', None, _('invoke editor on commit messages')),
6652 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6652 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6653 ] + commitopts2,
6653 ] + commitopts2,
6654 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6654 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6655 def tag(ui, repo, name1, *names, **opts):
6655 def tag(ui, repo, name1, *names, **opts):
6656 """add one or more tags for the current or given revision
6656 """add one or more tags for the current or given revision
6657
6657
6658 Name a particular revision using <name>.
6658 Name a particular revision using <name>.
6659
6659
6660 Tags are used to name particular revisions of the repository and are
6660 Tags are used to name particular revisions of the repository and are
6661 very useful to compare different revisions, to go back to significant
6661 very useful to compare different revisions, to go back to significant
6662 earlier versions or to mark branch points as releases, etc. Changing
6662 earlier versions or to mark branch points as releases, etc. Changing
6663 an existing tag is normally disallowed; use -f/--force to override.
6663 an existing tag is normally disallowed; use -f/--force to override.
6664
6664
6665 If no revision is given, the parent of the working directory is
6665 If no revision is given, the parent of the working directory is
6666 used.
6666 used.
6667
6667
6668 To facilitate version control, distribution, and merging of tags,
6668 To facilitate version control, distribution, and merging of tags,
6669 they are stored as a file named ".hgtags" which is managed similarly
6669 they are stored as a file named ".hgtags" which is managed similarly
6670 to other project files and can be hand-edited if necessary. This
6670 to other project files and can be hand-edited if necessary. This
6671 also means that tagging creates a new commit. The file
6671 also means that tagging creates a new commit. The file
6672 ".hg/localtags" is used for local tags (not shared among
6672 ".hg/localtags" is used for local tags (not shared among
6673 repositories).
6673 repositories).
6674
6674
6675 Tag commits are usually made at the head of a branch. If the parent
6675 Tag commits are usually made at the head of a branch. If the parent
6676 of the working directory is not a branch head, :hg:`tag` aborts; use
6676 of the working directory is not a branch head, :hg:`tag` aborts; use
6677 -f/--force to force the tag commit to be based on a non-head
6677 -f/--force to force the tag commit to be based on a non-head
6678 changeset.
6678 changeset.
6679
6679
6680 See :hg:`help dates` for a list of formats valid for -d/--date.
6680 See :hg:`help dates` for a list of formats valid for -d/--date.
6681
6681
6682 Since tag names have priority over branch names during revision
6682 Since tag names have priority over branch names during revision
6683 lookup, using an existing branch name as a tag name is discouraged.
6683 lookup, using an existing branch name as a tag name is discouraged.
6684
6684
6685 Returns 0 on success.
6685 Returns 0 on success.
6686 """
6686 """
6687 wlock = lock = None
6687 wlock = lock = None
6688 try:
6688 try:
6689 wlock = repo.wlock()
6689 wlock = repo.wlock()
6690 lock = repo.lock()
6690 lock = repo.lock()
6691 rev_ = "."
6691 rev_ = "."
6692 names = [t.strip() for t in (name1,) + names]
6692 names = [t.strip() for t in (name1,) + names]
6693 if len(names) != len(set(names)):
6693 if len(names) != len(set(names)):
6694 raise error.Abort(_('tag names must be unique'))
6694 raise error.Abort(_('tag names must be unique'))
6695 for n in names:
6695 for n in names:
6696 scmutil.checknewlabel(repo, n, 'tag')
6696 scmutil.checknewlabel(repo, n, 'tag')
6697 if not n:
6697 if not n:
6698 raise error.Abort(_('tag names cannot consist entirely of '
6698 raise error.Abort(_('tag names cannot consist entirely of '
6699 'whitespace'))
6699 'whitespace'))
6700 if opts.get('rev') and opts.get('remove'):
6700 if opts.get('rev') and opts.get('remove'):
6701 raise error.Abort(_("--rev and --remove are incompatible"))
6701 raise error.Abort(_("--rev and --remove are incompatible"))
6702 if opts.get('rev'):
6702 if opts.get('rev'):
6703 rev_ = opts['rev']
6703 rev_ = opts['rev']
6704 message = opts.get('message')
6704 message = opts.get('message')
6705 if opts.get('remove'):
6705 if opts.get('remove'):
6706 if opts.get('local'):
6706 if opts.get('local'):
6707 expectedtype = 'local'
6707 expectedtype = 'local'
6708 else:
6708 else:
6709 expectedtype = 'global'
6709 expectedtype = 'global'
6710
6710
6711 for n in names:
6711 for n in names:
6712 if not repo.tagtype(n):
6712 if not repo.tagtype(n):
6713 raise error.Abort(_("tag '%s' does not exist") % n)
6713 raise error.Abort(_("tag '%s' does not exist") % n)
6714 if repo.tagtype(n) != expectedtype:
6714 if repo.tagtype(n) != expectedtype:
6715 if expectedtype == 'global':
6715 if expectedtype == 'global':
6716 raise error.Abort(_("tag '%s' is not a global tag") % n)
6716 raise error.Abort(_("tag '%s' is not a global tag") % n)
6717 else:
6717 else:
6718 raise error.Abort(_("tag '%s' is not a local tag") % n)
6718 raise error.Abort(_("tag '%s' is not a local tag") % n)
6719 rev_ = 'null'
6719 rev_ = 'null'
6720 if not message:
6720 if not message:
6721 # we don't translate commit messages
6721 # we don't translate commit messages
6722 message = 'Removed tag %s' % ', '.join(names)
6722 message = 'Removed tag %s' % ', '.join(names)
6723 elif not opts.get('force'):
6723 elif not opts.get('force'):
6724 for n in names:
6724 for n in names:
6725 if n in repo.tags():
6725 if n in repo.tags():
6726 raise error.Abort(_("tag '%s' already exists "
6726 raise error.Abort(_("tag '%s' already exists "
6727 "(use -f to force)") % n)
6727 "(use -f to force)") % n)
6728 if not opts.get('local'):
6728 if not opts.get('local'):
6729 p1, p2 = repo.dirstate.parents()
6729 p1, p2 = repo.dirstate.parents()
6730 if p2 != nullid:
6730 if p2 != nullid:
6731 raise error.Abort(_('uncommitted merge'))
6731 raise error.Abort(_('uncommitted merge'))
6732 bheads = repo.branchheads()
6732 bheads = repo.branchheads()
6733 if not opts.get('force') and bheads and p1 not in bheads:
6733 if not opts.get('force') and bheads and p1 not in bheads:
6734 raise error.Abort(_('not at a branch head (use -f to force)'))
6734 raise error.Abort(_('not at a branch head (use -f to force)'))
6735 r = scmutil.revsingle(repo, rev_).node()
6735 r = scmutil.revsingle(repo, rev_).node()
6736
6736
6737 if not message:
6737 if not message:
6738 # we don't translate commit messages
6738 # we don't translate commit messages
6739 message = ('Added tag %s for changeset %s' %
6739 message = ('Added tag %s for changeset %s' %
6740 (', '.join(names), short(r)))
6740 (', '.join(names), short(r)))
6741
6741
6742 date = opts.get('date')
6742 date = opts.get('date')
6743 if date:
6743 if date:
6744 date = util.parsedate(date)
6744 date = util.parsedate(date)
6745
6745
6746 if opts.get('remove'):
6746 if opts.get('remove'):
6747 editform = 'tag.remove'
6747 editform = 'tag.remove'
6748 else:
6748 else:
6749 editform = 'tag.add'
6749 editform = 'tag.add'
6750 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6750 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6751
6751
6752 # don't allow tagging the null rev
6752 # don't allow tagging the null rev
6753 if (not opts.get('remove') and
6753 if (not opts.get('remove') and
6754 scmutil.revsingle(repo, rev_).rev() == nullrev):
6754 scmutil.revsingle(repo, rev_).rev() == nullrev):
6755 raise error.Abort(_("cannot tag null revision"))
6755 raise error.Abort(_("cannot tag null revision"))
6756
6756
6757 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6757 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6758 editor=editor)
6758 editor=editor)
6759 finally:
6759 finally:
6760 release(lock, wlock)
6760 release(lock, wlock)
6761
6761
6762 @command('tags', formatteropts, '')
6762 @command('tags', formatteropts, '')
6763 def tags(ui, repo, **opts):
6763 def tags(ui, repo, **opts):
6764 """list repository tags
6764 """list repository tags
6765
6765
6766 This lists both regular and local tags. When the -v/--verbose
6766 This lists both regular and local tags. When the -v/--verbose
6767 switch is used, a third column "local" is printed for local tags.
6767 switch is used, a third column "local" is printed for local tags.
6768 When the -q/--quiet switch is used, only the tag name is printed.
6768 When the -q/--quiet switch is used, only the tag name is printed.
6769
6769
6770 Returns 0 on success.
6770 Returns 0 on success.
6771 """
6771 """
6772
6772
6773 fm = ui.formatter('tags', opts)
6773 fm = ui.formatter('tags', opts)
6774 hexfunc = fm.hexfunc
6774 hexfunc = fm.hexfunc
6775 tagtype = ""
6775 tagtype = ""
6776
6776
6777 for t, n in reversed(repo.tagslist()):
6777 for t, n in reversed(repo.tagslist()):
6778 hn = hexfunc(n)
6778 hn = hexfunc(n)
6779 label = 'tags.normal'
6779 label = 'tags.normal'
6780 tagtype = ''
6780 tagtype = ''
6781 if repo.tagtype(t) == 'local':
6781 if repo.tagtype(t) == 'local':
6782 label = 'tags.local'
6782 label = 'tags.local'
6783 tagtype = 'local'
6783 tagtype = 'local'
6784
6784
6785 fm.startitem()
6785 fm.startitem()
6786 fm.write('tag', '%s', t, label=label)
6786 fm.write('tag', '%s', t, label=label)
6787 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6787 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6788 fm.condwrite(not ui.quiet, 'rev node', fmt,
6788 fm.condwrite(not ui.quiet, 'rev node', fmt,
6789 repo.changelog.rev(n), hn, label=label)
6789 repo.changelog.rev(n), hn, label=label)
6790 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6790 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6791 tagtype, label=label)
6791 tagtype, label=label)
6792 fm.plain('\n')
6792 fm.plain('\n')
6793 fm.end()
6793 fm.end()
6794
6794
6795 @command('tip',
6795 @command('tip',
6796 [('p', 'patch', None, _('show patch')),
6796 [('p', 'patch', None, _('show patch')),
6797 ('g', 'git', None, _('use git extended diff format')),
6797 ('g', 'git', None, _('use git extended diff format')),
6798 ] + templateopts,
6798 ] + templateopts,
6799 _('[-p] [-g]'))
6799 _('[-p] [-g]'))
6800 def tip(ui, repo, **opts):
6800 def tip(ui, repo, **opts):
6801 """show the tip revision (DEPRECATED)
6801 """show the tip revision (DEPRECATED)
6802
6802
6803 The tip revision (usually just called the tip) is the changeset
6803 The tip revision (usually just called the tip) is the changeset
6804 most recently added to the repository (and therefore the most
6804 most recently added to the repository (and therefore the most
6805 recently changed head).
6805 recently changed head).
6806
6806
6807 If you have just made a commit, that commit will be the tip. If
6807 If you have just made a commit, that commit will be the tip. If
6808 you have just pulled changes from another repository, the tip of
6808 you have just pulled changes from another repository, the tip of
6809 that repository becomes the current tip. The "tip" tag is special
6809 that repository becomes the current tip. The "tip" tag is special
6810 and cannot be renamed or assigned to a different changeset.
6810 and cannot be renamed or assigned to a different changeset.
6811
6811
6812 This command is deprecated, please use :hg:`heads` instead.
6812 This command is deprecated, please use :hg:`heads` instead.
6813
6813
6814 Returns 0 on success.
6814 Returns 0 on success.
6815 """
6815 """
6816 displayer = cmdutil.show_changeset(ui, repo, opts)
6816 displayer = cmdutil.show_changeset(ui, repo, opts)
6817 displayer.show(repo['tip'])
6817 displayer.show(repo['tip'])
6818 displayer.close()
6818 displayer.close()
6819
6819
6820 @command('unbundle',
6820 @command('unbundle',
6821 [('u', 'update', None,
6821 [('u', 'update', None,
6822 _('update to new branch head if changesets were unbundled'))],
6822 _('update to new branch head if changesets were unbundled'))],
6823 _('[-u] FILE...'))
6823 _('[-u] FILE...'))
6824 def unbundle(ui, repo, fname1, *fnames, **opts):
6824 def unbundle(ui, repo, fname1, *fnames, **opts):
6825 """apply one or more changegroup files
6825 """apply one or more changegroup files
6826
6826
6827 Apply one or more compressed changegroup files generated by the
6827 Apply one or more compressed changegroup files generated by the
6828 bundle command.
6828 bundle command.
6829
6829
6830 Returns 0 on success, 1 if an update has unresolved files.
6830 Returns 0 on success, 1 if an update has unresolved files.
6831 """
6831 """
6832 fnames = (fname1,) + fnames
6832 fnames = (fname1,) + fnames
6833
6833
6834 lock = repo.lock()
6834 lock = repo.lock()
6835 try:
6835 try:
6836 for fname in fnames:
6836 for fname in fnames:
6837 f = hg.openpath(ui, fname)
6837 f = hg.openpath(ui, fname)
6838 gen = exchange.readbundle(ui, f, fname)
6838 gen = exchange.readbundle(ui, f, fname)
6839 if isinstance(gen, bundle2.unbundle20):
6839 if isinstance(gen, bundle2.unbundle20):
6840 tr = repo.transaction('unbundle')
6840 tr = repo.transaction('unbundle')
6841 try:
6841 try:
6842 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6842 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6843 url='bundle:' + fname)
6843 url='bundle:' + fname)
6844 tr.close()
6844 tr.close()
6845 except error.BundleUnknownFeatureError as exc:
6845 except error.BundleUnknownFeatureError as exc:
6846 raise error.Abort(_('%s: unknown bundle feature, %s')
6846 raise error.Abort(_('%s: unknown bundle feature, %s')
6847 % (fname, exc),
6847 % (fname, exc),
6848 hint=_("see https://mercurial-scm.org/"
6848 hint=_("see https://mercurial-scm.org/"
6849 "wiki/BundleFeature for more "
6849 "wiki/BundleFeature for more "
6850 "information"))
6850 "information"))
6851 finally:
6851 finally:
6852 if tr:
6852 if tr:
6853 tr.release()
6853 tr.release()
6854 changes = [r.get('return', 0)
6854 changes = [r.get('return', 0)
6855 for r in op.records['changegroup']]
6855 for r in op.records['changegroup']]
6856 modheads = changegroup.combineresults(changes)
6856 modheads = changegroup.combineresults(changes)
6857 elif isinstance(gen, streamclone.streamcloneapplier):
6857 elif isinstance(gen, streamclone.streamcloneapplier):
6858 raise error.Abort(
6858 raise error.Abort(
6859 _('packed bundles cannot be applied with '
6859 _('packed bundles cannot be applied with '
6860 '"hg unbundle"'),
6860 '"hg unbundle"'),
6861 hint=_('use "hg debugapplystreamclonebundle"'))
6861 hint=_('use "hg debugapplystreamclonebundle"'))
6862 else:
6862 else:
6863 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6863 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6864 finally:
6864 finally:
6865 lock.release()
6865 lock.release()
6866
6866
6867 return postincoming(ui, repo, modheads, opts.get('update'), None)
6867 return postincoming(ui, repo, modheads, opts.get('update'), None)
6868
6868
6869 @command('^update|up|checkout|co',
6869 @command('^update|up|checkout|co',
6870 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6870 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6871 ('c', 'check', None,
6871 ('c', 'check', None,
6872 _('update across branches if no uncommitted changes')),
6872 _('update across branches if no uncommitted changes')),
6873 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6873 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6874 ('r', 'rev', '', _('revision'), _('REV'))
6874 ('r', 'rev', '', _('revision'), _('REV'))
6875 ] + mergetoolopts,
6875 ] + mergetoolopts,
6876 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6876 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6877 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6877 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6878 tool=None):
6878 tool=None):
6879 """update working directory (or switch revisions)
6879 """update working directory (or switch revisions)
6880
6880
6881 Update the repository's working directory to the specified
6881 Update the repository's working directory to the specified
6882 changeset. If no changeset is specified, update to the tip of the
6882 changeset. If no changeset is specified, update to the tip of the
6883 current named branch and move the active bookmark (see :hg:`help
6883 current named branch and move the active bookmark (see :hg:`help
6884 bookmarks`).
6884 bookmarks`).
6885
6885
6886 Update sets the working directory's parent revision to the specified
6886 Update sets the working directory's parent revision to the specified
6887 changeset (see :hg:`help parents`).
6887 changeset (see :hg:`help parents`).
6888
6888
6889 If the changeset is not a descendant or ancestor of the working
6889 If the changeset is not a descendant or ancestor of the working
6890 directory's parent, the update is aborted. With the -c/--check
6890 directory's parent, the update is aborted. With the -c/--check
6891 option, the working directory is checked for uncommitted changes; if
6891 option, the working directory is checked for uncommitted changes; if
6892 none are found, the working directory is updated to the specified
6892 none are found, the working directory is updated to the specified
6893 changeset.
6893 changeset.
6894
6894
6895 .. container:: verbose
6895 .. container:: verbose
6896
6896
6897 The following rules apply when the working directory contains
6897 The following rules apply when the working directory contains
6898 uncommitted changes:
6898 uncommitted changes:
6899
6899
6900 1. If neither -c/--check nor -C/--clean is specified, and if
6900 1. If neither -c/--check nor -C/--clean is specified, and if
6901 the requested changeset is an ancestor or descendant of
6901 the requested changeset is an ancestor or descendant of
6902 the working directory's parent, the uncommitted changes
6902 the working directory's parent, the uncommitted changes
6903 are merged into the requested changeset and the merged
6903 are merged into the requested changeset and the merged
6904 result is left uncommitted. If the requested changeset is
6904 result is left uncommitted. If the requested changeset is
6905 not an ancestor or descendant (that is, it is on another
6905 not an ancestor or descendant (that is, it is on another
6906 branch), the update is aborted and the uncommitted changes
6906 branch), the update is aborted and the uncommitted changes
6907 are preserved.
6907 are preserved.
6908
6908
6909 2. With the -c/--check option, the update is aborted and the
6909 2. With the -c/--check option, the update is aborted and the
6910 uncommitted changes are preserved.
6910 uncommitted changes are preserved.
6911
6911
6912 3. With the -C/--clean option, uncommitted changes are discarded and
6912 3. With the -C/--clean option, uncommitted changes are discarded and
6913 the working directory is updated to the requested changeset.
6913 the working directory is updated to the requested changeset.
6914
6914
6915 To cancel an uncommitted merge (and lose your changes), use
6915 To cancel an uncommitted merge (and lose your changes), use
6916 :hg:`update --clean .`.
6916 :hg:`update --clean .`.
6917
6917
6918 Use null as the changeset to remove the working directory (like
6918 Use null as the changeset to remove the working directory (like
6919 :hg:`clone -U`).
6919 :hg:`clone -U`).
6920
6920
6921 If you want to revert just one file to an older revision, use
6921 If you want to revert just one file to an older revision, use
6922 :hg:`revert [-r REV] NAME`.
6922 :hg:`revert [-r REV] NAME`.
6923
6923
6924 See :hg:`help dates` for a list of formats valid for -d/--date.
6924 See :hg:`help dates` for a list of formats valid for -d/--date.
6925
6925
6926 Returns 0 on success, 1 if there are unresolved files.
6926 Returns 0 on success, 1 if there are unresolved files.
6927 """
6927 """
6928 movemarkfrom = None
6928 movemarkfrom = None
6929 if rev and node:
6929 if rev and node:
6930 raise error.Abort(_("please specify just one revision"))
6930 raise error.Abort(_("please specify just one revision"))
6931
6931
6932 if rev is None or rev == '':
6932 if rev is None or rev == '':
6933 rev = node
6933 rev = node
6934
6934
6935 wlock = repo.wlock()
6935 with repo.wlock():
6936 try:
6937 cmdutil.clearunfinished(repo)
6936 cmdutil.clearunfinished(repo)
6938
6937
6939 if date:
6938 if date:
6940 if rev is not None:
6939 if rev is not None:
6941 raise error.Abort(_("you can't specify a revision and a date"))
6940 raise error.Abort(_("you can't specify a revision and a date"))
6942 rev = cmdutil.finddate(ui, repo, date)
6941 rev = cmdutil.finddate(ui, repo, date)
6943
6942
6944 # if we defined a bookmark, we have to remember the original name
6943 # if we defined a bookmark, we have to remember the original name
6945 brev = rev
6944 brev = rev
6946 rev = scmutil.revsingle(repo, rev, rev).rev()
6945 rev = scmutil.revsingle(repo, rev, rev).rev()
6947
6946
6948 if check and clean:
6947 if check and clean:
6949 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6948 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6950 )
6949 )
6951
6950
6952 if check:
6951 if check:
6953 cmdutil.bailifchanged(repo, merge=False)
6952 cmdutil.bailifchanged(repo, merge=False)
6954 if rev is None:
6953 if rev is None:
6955 updata = destutil.destupdate(repo, clean=clean, check=check)
6954 updata = destutil.destupdate(repo, clean=clean, check=check)
6956 rev, movemarkfrom, brev = updata
6955 rev, movemarkfrom, brev = updata
6957
6956
6958 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6957 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6959
6958
6960 if clean:
6959 if clean:
6961 ret = hg.clean(repo, rev)
6960 ret = hg.clean(repo, rev)
6962 else:
6961 else:
6963 ret = hg.update(repo, rev)
6962 ret = hg.update(repo, rev)
6964
6963
6965 if not ret and movemarkfrom:
6964 if not ret and movemarkfrom:
6966 if movemarkfrom == repo['.'].node():
6965 if movemarkfrom == repo['.'].node():
6967 pass # no-op update
6966 pass # no-op update
6968 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6967 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6969 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6968 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6970 else:
6969 else:
6971 # this can happen with a non-linear update
6970 # this can happen with a non-linear update
6972 ui.status(_("(leaving bookmark %s)\n") %
6971 ui.status(_("(leaving bookmark %s)\n") %
6973 repo._activebookmark)
6972 repo._activebookmark)
6974 bookmarks.deactivate(repo)
6973 bookmarks.deactivate(repo)
6975 elif brev in repo._bookmarks:
6974 elif brev in repo._bookmarks:
6976 bookmarks.activate(repo, brev)
6975 bookmarks.activate(repo, brev)
6977 ui.status(_("(activating bookmark %s)\n") % brev)
6976 ui.status(_("(activating bookmark %s)\n") % brev)
6978 elif brev:
6977 elif brev:
6979 if repo._activebookmark:
6978 if repo._activebookmark:
6980 ui.status(_("(leaving bookmark %s)\n") %
6979 ui.status(_("(leaving bookmark %s)\n") %
6981 repo._activebookmark)
6980 repo._activebookmark)
6982 bookmarks.deactivate(repo)
6981 bookmarks.deactivate(repo)
6983 finally:
6984 wlock.release()
6985
6982
6986 return ret
6983 return ret
6987
6984
6988 @command('verify', [])
6985 @command('verify', [])
6989 def verify(ui, repo):
6986 def verify(ui, repo):
6990 """verify the integrity of the repository
6987 """verify the integrity of the repository
6991
6988
6992 Verify the integrity of the current repository.
6989 Verify the integrity of the current repository.
6993
6990
6994 This will perform an extensive check of the repository's
6991 This will perform an extensive check of the repository's
6995 integrity, validating the hashes and checksums of each entry in
6992 integrity, validating the hashes and checksums of each entry in
6996 the changelog, manifest, and tracked files, as well as the
6993 the changelog, manifest, and tracked files, as well as the
6997 integrity of their crosslinks and indices.
6994 integrity of their crosslinks and indices.
6998
6995
6999 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6996 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7000 for more information about recovery from corruption of the
6997 for more information about recovery from corruption of the
7001 repository.
6998 repository.
7002
6999
7003 Returns 0 on success, 1 if errors are encountered.
7000 Returns 0 on success, 1 if errors are encountered.
7004 """
7001 """
7005 return hg.verify(repo)
7002 return hg.verify(repo)
7006
7003
7007 @command('version', [], norepo=True)
7004 @command('version', [], norepo=True)
7008 def version_(ui):
7005 def version_(ui):
7009 """output version and copyright information"""
7006 """output version and copyright information"""
7010 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7007 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7011 % util.version())
7008 % util.version())
7012 ui.status(_(
7009 ui.status(_(
7013 "(see https://mercurial-scm.org for more information)\n"
7010 "(see https://mercurial-scm.org for more information)\n"
7014 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7011 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7015 "This is free software; see the source for copying conditions. "
7012 "This is free software; see the source for copying conditions. "
7016 "There is NO\nwarranty; "
7013 "There is NO\nwarranty; "
7017 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7014 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7018 ))
7015 ))
7019
7016
7020 ui.note(_("\nEnabled extensions:\n\n"))
7017 ui.note(_("\nEnabled extensions:\n\n"))
7021 if ui.verbose:
7018 if ui.verbose:
7022 # format names and versions into columns
7019 # format names and versions into columns
7023 names = []
7020 names = []
7024 vers = []
7021 vers = []
7025 for name, module in extensions.extensions():
7022 for name, module in extensions.extensions():
7026 names.append(name)
7023 names.append(name)
7027 vers.append(extensions.moduleversion(module))
7024 vers.append(extensions.moduleversion(module))
7028 if names:
7025 if names:
7029 maxnamelen = max(len(n) for n in names)
7026 maxnamelen = max(len(n) for n in names)
7030 for i, name in enumerate(names):
7027 for i, name in enumerate(names):
7031 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7028 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now