##// END OF EJS Templates
update: also use 'destupdate' for pull and unbundle...
Pierre-Yves David -
r26642:70ac5f72 default
parent child Browse files
Show More
@@ -1,6677 +1,6681 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, nullid, nullrev, short
8 from node import hex, bin, 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 from hgweb import server as hgweb_server
18 from hgweb import server as hgweb_server
19 import merge as mergemod
19 import merge as mergemod
20 import minirst, revset, fileset
20 import minirst, revset, fileset
21 import dagparser, context, simplemerge, graphmod, copies
21 import dagparser, context, simplemerge, graphmod, copies
22 import random, operator
22 import random, operator
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
24 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
24 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
25 import ui as uimod
25 import ui as uimod
26
26
27 table = {}
27 table = {}
28
28
29 command = cmdutil.command(table)
29 command = cmdutil.command(table)
30
30
31 # Space delimited list of commands that don't require local repositories.
31 # Space delimited list of commands that don't require local repositories.
32 # This should be populated by passing norepo=True into the @command decorator.
32 # This should be populated by passing norepo=True into the @command decorator.
33 norepo = ''
33 norepo = ''
34 # Space delimited list of commands that optionally require local repositories.
34 # Space delimited list of commands that optionally require local repositories.
35 # This should be populated by passing optionalrepo=True into the @command
35 # This should be populated by passing optionalrepo=True into the @command
36 # decorator.
36 # decorator.
37 optionalrepo = ''
37 optionalrepo = ''
38 # Space delimited list of commands that will examine arguments looking for
38 # Space delimited list of commands that will examine arguments looking for
39 # a repository. This should be populated by passing inferrepo=True into the
39 # a repository. This should be populated by passing inferrepo=True into the
40 # @command decorator.
40 # @command decorator.
41 inferrepo = ''
41 inferrepo = ''
42
42
43 # label constants
43 # label constants
44 # until 3.5, bookmarks.current was the advertised name, not
44 # until 3.5, bookmarks.current was the advertised name, not
45 # bookmarks.active, so we must use both to avoid breaking old
45 # bookmarks.active, so we must use both to avoid breaking old
46 # custom styles
46 # custom styles
47 activebookmarklabel = 'bookmarks.active bookmarks.current'
47 activebookmarklabel = 'bookmarks.active bookmarks.current'
48
48
49 # common command options
49 # common command options
50
50
51 globalopts = [
51 globalopts = [
52 ('R', 'repository', '',
52 ('R', 'repository', '',
53 _('repository root directory or name of overlay bundle file'),
53 _('repository root directory or name of overlay bundle file'),
54 _('REPO')),
54 _('REPO')),
55 ('', 'cwd', '',
55 ('', 'cwd', '',
56 _('change working directory'), _('DIR')),
56 _('change working directory'), _('DIR')),
57 ('y', 'noninteractive', None,
57 ('y', 'noninteractive', None,
58 _('do not prompt, automatically pick the first choice for all prompts')),
58 _('do not prompt, automatically pick the first choice for all prompts')),
59 ('q', 'quiet', None, _('suppress output')),
59 ('q', 'quiet', None, _('suppress output')),
60 ('v', 'verbose', None, _('enable additional output')),
60 ('v', 'verbose', None, _('enable additional output')),
61 ('', 'config', [],
61 ('', 'config', [],
62 _('set/override config option (use \'section.name=value\')'),
62 _('set/override config option (use \'section.name=value\')'),
63 _('CONFIG')),
63 _('CONFIG')),
64 ('', 'debug', None, _('enable debugging output')),
64 ('', 'debug', None, _('enable debugging output')),
65 ('', 'debugger', None, _('start debugger')),
65 ('', 'debugger', None, _('start debugger')),
66 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
66 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
67 _('ENCODE')),
67 _('ENCODE')),
68 ('', 'encodingmode', encoding.encodingmode,
68 ('', 'encodingmode', encoding.encodingmode,
69 _('set the charset encoding mode'), _('MODE')),
69 _('set the charset encoding mode'), _('MODE')),
70 ('', 'traceback', None, _('always print a traceback on exception')),
70 ('', 'traceback', None, _('always print a traceback on exception')),
71 ('', 'time', None, _('time how long the command takes')),
71 ('', 'time', None, _('time how long the command takes')),
72 ('', 'profile', None, _('print command execution profile')),
72 ('', 'profile', None, _('print command execution profile')),
73 ('', 'version', None, _('output version information and exit')),
73 ('', 'version', None, _('output version information and exit')),
74 ('h', 'help', None, _('display help and exit')),
74 ('h', 'help', None, _('display help and exit')),
75 ('', 'hidden', False, _('consider hidden changesets')),
75 ('', 'hidden', False, _('consider hidden changesets')),
76 ]
76 ]
77
77
78 dryrunopts = [('n', 'dry-run', None,
78 dryrunopts = [('n', 'dry-run', None,
79 _('do not perform actions, just print output'))]
79 _('do not perform actions, just print output'))]
80
80
81 remoteopts = [
81 remoteopts = [
82 ('e', 'ssh', '',
82 ('e', 'ssh', '',
83 _('specify ssh command to use'), _('CMD')),
83 _('specify ssh command to use'), _('CMD')),
84 ('', 'remotecmd', '',
84 ('', 'remotecmd', '',
85 _('specify hg command to run on the remote side'), _('CMD')),
85 _('specify hg command to run on the remote side'), _('CMD')),
86 ('', 'insecure', None,
86 ('', 'insecure', None,
87 _('do not verify server certificate (ignoring web.cacerts config)')),
87 _('do not verify server certificate (ignoring web.cacerts config)')),
88 ]
88 ]
89
89
90 walkopts = [
90 walkopts = [
91 ('I', 'include', [],
91 ('I', 'include', [],
92 _('include names matching the given patterns'), _('PATTERN')),
92 _('include names matching the given patterns'), _('PATTERN')),
93 ('X', 'exclude', [],
93 ('X', 'exclude', [],
94 _('exclude names matching the given patterns'), _('PATTERN')),
94 _('exclude names matching the given patterns'), _('PATTERN')),
95 ]
95 ]
96
96
97 commitopts = [
97 commitopts = [
98 ('m', 'message', '',
98 ('m', 'message', '',
99 _('use text as commit message'), _('TEXT')),
99 _('use text as commit message'), _('TEXT')),
100 ('l', 'logfile', '',
100 ('l', 'logfile', '',
101 _('read commit message from file'), _('FILE')),
101 _('read commit message from file'), _('FILE')),
102 ]
102 ]
103
103
104 commitopts2 = [
104 commitopts2 = [
105 ('d', 'date', '',
105 ('d', 'date', '',
106 _('record the specified date as commit date'), _('DATE')),
106 _('record the specified date as commit date'), _('DATE')),
107 ('u', 'user', '',
107 ('u', 'user', '',
108 _('record the specified user as committer'), _('USER')),
108 _('record the specified user as committer'), _('USER')),
109 ]
109 ]
110
110
111 # hidden for now
111 # hidden for now
112 formatteropts = [
112 formatteropts = [
113 ('T', 'template', '',
113 ('T', 'template', '',
114 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
114 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
115 ]
115 ]
116
116
117 templateopts = [
117 templateopts = [
118 ('', 'style', '',
118 ('', 'style', '',
119 _('display using template map file (DEPRECATED)'), _('STYLE')),
119 _('display using template map file (DEPRECATED)'), _('STYLE')),
120 ('T', 'template', '',
120 ('T', 'template', '',
121 _('display with template'), _('TEMPLATE')),
121 _('display with template'), _('TEMPLATE')),
122 ]
122 ]
123
123
124 logopts = [
124 logopts = [
125 ('p', 'patch', None, _('show patch')),
125 ('p', 'patch', None, _('show patch')),
126 ('g', 'git', None, _('use git extended diff format')),
126 ('g', 'git', None, _('use git extended diff format')),
127 ('l', 'limit', '',
127 ('l', 'limit', '',
128 _('limit number of changes displayed'), _('NUM')),
128 _('limit number of changes displayed'), _('NUM')),
129 ('M', 'no-merges', None, _('do not show merges')),
129 ('M', 'no-merges', None, _('do not show merges')),
130 ('', 'stat', None, _('output diffstat-style summary of changes')),
130 ('', 'stat', None, _('output diffstat-style summary of changes')),
131 ('G', 'graph', None, _("show the revision DAG")),
131 ('G', 'graph', None, _("show the revision DAG")),
132 ] + templateopts
132 ] + templateopts
133
133
134 diffopts = [
134 diffopts = [
135 ('a', 'text', None, _('treat all files as text')),
135 ('a', 'text', None, _('treat all files as text')),
136 ('g', 'git', None, _('use git extended diff format')),
136 ('g', 'git', None, _('use git extended diff format')),
137 ('', 'nodates', None, _('omit dates from diff headers'))
137 ('', 'nodates', None, _('omit dates from diff headers'))
138 ]
138 ]
139
139
140 diffwsopts = [
140 diffwsopts = [
141 ('w', 'ignore-all-space', None,
141 ('w', 'ignore-all-space', None,
142 _('ignore white space when comparing lines')),
142 _('ignore white space when comparing lines')),
143 ('b', 'ignore-space-change', None,
143 ('b', 'ignore-space-change', None,
144 _('ignore changes in the amount of white space')),
144 _('ignore changes in the amount of white space')),
145 ('B', 'ignore-blank-lines', None,
145 ('B', 'ignore-blank-lines', None,
146 _('ignore changes whose lines are all blank')),
146 _('ignore changes whose lines are all blank')),
147 ]
147 ]
148
148
149 diffopts2 = [
149 diffopts2 = [
150 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
150 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
151 ('p', 'show-function', None, _('show which function each change is in')),
151 ('p', 'show-function', None, _('show which function each change is in')),
152 ('', 'reverse', None, _('produce a diff that undoes the changes')),
152 ('', 'reverse', None, _('produce a diff that undoes the changes')),
153 ] + diffwsopts + [
153 ] + diffwsopts + [
154 ('U', 'unified', '',
154 ('U', 'unified', '',
155 _('number of lines of context to show'), _('NUM')),
155 _('number of lines of context to show'), _('NUM')),
156 ('', 'stat', None, _('output diffstat-style summary of changes')),
156 ('', 'stat', None, _('output diffstat-style summary of changes')),
157 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
157 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
158 ]
158 ]
159
159
160 mergetoolopts = [
160 mergetoolopts = [
161 ('t', 'tool', '', _('specify merge tool')),
161 ('t', 'tool', '', _('specify merge tool')),
162 ]
162 ]
163
163
164 similarityopts = [
164 similarityopts = [
165 ('s', 'similarity', '',
165 ('s', 'similarity', '',
166 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
166 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
167 ]
167 ]
168
168
169 subrepoopts = [
169 subrepoopts = [
170 ('S', 'subrepos', None,
170 ('S', 'subrepos', None,
171 _('recurse into subrepositories'))
171 _('recurse into subrepositories'))
172 ]
172 ]
173
173
174 # Commands start here, listed alphabetically
174 # Commands start here, listed alphabetically
175
175
176 @command('^add',
176 @command('^add',
177 walkopts + subrepoopts + dryrunopts,
177 walkopts + subrepoopts + dryrunopts,
178 _('[OPTION]... [FILE]...'),
178 _('[OPTION]... [FILE]...'),
179 inferrepo=True)
179 inferrepo=True)
180 def add(ui, repo, *pats, **opts):
180 def add(ui, repo, *pats, **opts):
181 """add the specified files on the next commit
181 """add the specified files on the next commit
182
182
183 Schedule files to be version controlled and added to the
183 Schedule files to be version controlled and added to the
184 repository.
184 repository.
185
185
186 The files will be added to the repository at the next commit. To
186 The files will be added to the repository at the next commit. To
187 undo an add before that, see :hg:`forget`.
187 undo an add before that, see :hg:`forget`.
188
188
189 If no names are given, add all files to the repository.
189 If no names are given, add all files to the repository.
190
190
191 .. container:: verbose
191 .. container:: verbose
192
192
193 An example showing how new (unknown) files are added
193 An example showing how new (unknown) files are added
194 automatically by :hg:`add`::
194 automatically by :hg:`add`::
195
195
196 $ ls
196 $ ls
197 foo.c
197 foo.c
198 $ hg status
198 $ hg status
199 ? foo.c
199 ? foo.c
200 $ hg add
200 $ hg add
201 adding foo.c
201 adding foo.c
202 $ hg status
202 $ hg status
203 A foo.c
203 A foo.c
204
204
205 Returns 0 if all files are successfully added.
205 Returns 0 if all files are successfully added.
206 """
206 """
207
207
208 m = scmutil.match(repo[None], pats, opts)
208 m = scmutil.match(repo[None], pats, opts)
209 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
209 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
210 return rejected and 1 or 0
210 return rejected and 1 or 0
211
211
212 @command('addremove',
212 @command('addremove',
213 similarityopts + subrepoopts + walkopts + dryrunopts,
213 similarityopts + subrepoopts + walkopts + dryrunopts,
214 _('[OPTION]... [FILE]...'),
214 _('[OPTION]... [FILE]...'),
215 inferrepo=True)
215 inferrepo=True)
216 def addremove(ui, repo, *pats, **opts):
216 def addremove(ui, repo, *pats, **opts):
217 """add all new files, delete all missing files
217 """add all new files, delete all missing files
218
218
219 Add all new files and remove all missing files from the
219 Add all new files and remove all missing files from the
220 repository.
220 repository.
221
221
222 New files are ignored if they match any of the patterns in
222 New files are ignored if they match any of the patterns in
223 ``.hgignore``. As with add, these changes take effect at the next
223 ``.hgignore``. As with add, these changes take effect at the next
224 commit.
224 commit.
225
225
226 Use the -s/--similarity option to detect renamed files. This
226 Use the -s/--similarity option to detect renamed files. This
227 option takes a percentage between 0 (disabled) and 100 (files must
227 option takes a percentage between 0 (disabled) and 100 (files must
228 be identical) as its parameter. With a parameter greater than 0,
228 be identical) as its parameter. With a parameter greater than 0,
229 this compares every removed file with every added file and records
229 this compares every removed file with every added file and records
230 those similar enough as renames. Detecting renamed files this way
230 those similar enough as renames. Detecting renamed files this way
231 can be expensive. After using this option, :hg:`status -C` can be
231 can be expensive. After using this option, :hg:`status -C` can be
232 used to check which files were identified as moved or renamed. If
232 used to check which files were identified as moved or renamed. If
233 not specified, -s/--similarity defaults to 100 and only renames of
233 not specified, -s/--similarity defaults to 100 and only renames of
234 identical files are detected.
234 identical files are detected.
235
235
236 Returns 0 if all files are successfully added.
236 Returns 0 if all files are successfully added.
237 """
237 """
238 try:
238 try:
239 sim = float(opts.get('similarity') or 100)
239 sim = float(opts.get('similarity') or 100)
240 except ValueError:
240 except ValueError:
241 raise error.Abort(_('similarity must be a number'))
241 raise error.Abort(_('similarity must be a number'))
242 if sim < 0 or sim > 100:
242 if sim < 0 or sim > 100:
243 raise error.Abort(_('similarity must be between 0 and 100'))
243 raise error.Abort(_('similarity must be between 0 and 100'))
244 matcher = scmutil.match(repo[None], pats, opts)
244 matcher = scmutil.match(repo[None], pats, opts)
245 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
245 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
246
246
247 @command('^annotate|blame',
247 @command('^annotate|blame',
248 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
248 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
249 ('', 'follow', None,
249 ('', 'follow', None,
250 _('follow copies/renames and list the filename (DEPRECATED)')),
250 _('follow copies/renames and list the filename (DEPRECATED)')),
251 ('', 'no-follow', None, _("don't follow copies and renames")),
251 ('', 'no-follow', None, _("don't follow copies and renames")),
252 ('a', 'text', None, _('treat all files as text')),
252 ('a', 'text', None, _('treat all files as text')),
253 ('u', 'user', None, _('list the author (long with -v)')),
253 ('u', 'user', None, _('list the author (long with -v)')),
254 ('f', 'file', None, _('list the filename')),
254 ('f', 'file', None, _('list the filename')),
255 ('d', 'date', None, _('list the date (short with -q)')),
255 ('d', 'date', None, _('list the date (short with -q)')),
256 ('n', 'number', None, _('list the revision number (default)')),
256 ('n', 'number', None, _('list the revision number (default)')),
257 ('c', 'changeset', None, _('list the changeset')),
257 ('c', 'changeset', None, _('list the changeset')),
258 ('l', 'line-number', None, _('show line number at the first appearance'))
258 ('l', 'line-number', None, _('show line number at the first appearance'))
259 ] + diffwsopts + walkopts + formatteropts,
259 ] + diffwsopts + walkopts + formatteropts,
260 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
260 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
261 inferrepo=True)
261 inferrepo=True)
262 def annotate(ui, repo, *pats, **opts):
262 def annotate(ui, repo, *pats, **opts):
263 """show changeset information by line for each file
263 """show changeset information by line for each file
264
264
265 List changes in files, showing the revision id responsible for
265 List changes in files, showing the revision id responsible for
266 each line
266 each line
267
267
268 This command is useful for discovering when a change was made and
268 This command is useful for discovering when a change was made and
269 by whom.
269 by whom.
270
270
271 Without the -a/--text option, annotate will avoid processing files
271 Without the -a/--text option, annotate will avoid processing files
272 it detects as binary. With -a, annotate will annotate the file
272 it detects as binary. With -a, annotate will annotate the file
273 anyway, although the results will probably be neither useful
273 anyway, although the results will probably be neither useful
274 nor desirable.
274 nor desirable.
275
275
276 Returns 0 on success.
276 Returns 0 on success.
277 """
277 """
278 if not pats:
278 if not pats:
279 raise error.Abort(_('at least one filename or pattern is required'))
279 raise error.Abort(_('at least one filename or pattern is required'))
280
280
281 if opts.get('follow'):
281 if opts.get('follow'):
282 # --follow is deprecated and now just an alias for -f/--file
282 # --follow is deprecated and now just an alias for -f/--file
283 # to mimic the behavior of Mercurial before version 1.5
283 # to mimic the behavior of Mercurial before version 1.5
284 opts['file'] = True
284 opts['file'] = True
285
285
286 ctx = scmutil.revsingle(repo, opts.get('rev'))
286 ctx = scmutil.revsingle(repo, opts.get('rev'))
287
287
288 fm = ui.formatter('annotate', opts)
288 fm = ui.formatter('annotate', opts)
289 if ui.quiet:
289 if ui.quiet:
290 datefunc = util.shortdate
290 datefunc = util.shortdate
291 else:
291 else:
292 datefunc = util.datestr
292 datefunc = util.datestr
293 if ctx.rev() is None:
293 if ctx.rev() is None:
294 def hexfn(node):
294 def hexfn(node):
295 if node is None:
295 if node is None:
296 return None
296 return None
297 else:
297 else:
298 return fm.hexfunc(node)
298 return fm.hexfunc(node)
299 if opts.get('changeset'):
299 if opts.get('changeset'):
300 # omit "+" suffix which is appended to node hex
300 # omit "+" suffix which is appended to node hex
301 def formatrev(rev):
301 def formatrev(rev):
302 if rev is None:
302 if rev is None:
303 return '%d' % ctx.p1().rev()
303 return '%d' % ctx.p1().rev()
304 else:
304 else:
305 return '%d' % rev
305 return '%d' % rev
306 else:
306 else:
307 def formatrev(rev):
307 def formatrev(rev):
308 if rev is None:
308 if rev is None:
309 return '%d+' % ctx.p1().rev()
309 return '%d+' % ctx.p1().rev()
310 else:
310 else:
311 return '%d ' % rev
311 return '%d ' % rev
312 def formathex(hex):
312 def formathex(hex):
313 if hex is None:
313 if hex is None:
314 return '%s+' % fm.hexfunc(ctx.p1().node())
314 return '%s+' % fm.hexfunc(ctx.p1().node())
315 else:
315 else:
316 return '%s ' % hex
316 return '%s ' % hex
317 else:
317 else:
318 hexfn = fm.hexfunc
318 hexfn = fm.hexfunc
319 formatrev = formathex = str
319 formatrev = formathex = str
320
320
321 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
321 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
322 ('number', ' ', lambda x: x[0].rev(), formatrev),
322 ('number', ' ', lambda x: x[0].rev(), formatrev),
323 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
323 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
324 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
324 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
325 ('file', ' ', lambda x: x[0].path(), str),
325 ('file', ' ', lambda x: x[0].path(), str),
326 ('line_number', ':', lambda x: x[1], str),
326 ('line_number', ':', lambda x: x[1], str),
327 ]
327 ]
328 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
328 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
329
329
330 if (not opts.get('user') and not opts.get('changeset')
330 if (not opts.get('user') and not opts.get('changeset')
331 and not opts.get('date') and not opts.get('file')):
331 and not opts.get('date') and not opts.get('file')):
332 opts['number'] = True
332 opts['number'] = True
333
333
334 linenumber = opts.get('line_number') is not None
334 linenumber = opts.get('line_number') is not None
335 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
335 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
336 raise error.Abort(_('at least one of -n/-c is required for -l'))
336 raise error.Abort(_('at least one of -n/-c is required for -l'))
337
337
338 if fm:
338 if fm:
339 def makefunc(get, fmt):
339 def makefunc(get, fmt):
340 return get
340 return get
341 else:
341 else:
342 def makefunc(get, fmt):
342 def makefunc(get, fmt):
343 return lambda x: fmt(get(x))
343 return lambda x: fmt(get(x))
344 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
344 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
345 if opts.get(op)]
345 if opts.get(op)]
346 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
346 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
347 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
347 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
348 if opts.get(op))
348 if opts.get(op))
349
349
350 def bad(x, y):
350 def bad(x, y):
351 raise error.Abort("%s: %s" % (x, y))
351 raise error.Abort("%s: %s" % (x, y))
352
352
353 m = scmutil.match(ctx, pats, opts, badfn=bad)
353 m = scmutil.match(ctx, pats, opts, badfn=bad)
354
354
355 follow = not opts.get('no_follow')
355 follow = not opts.get('no_follow')
356 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
356 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
357 whitespace=True)
357 whitespace=True)
358 for abs in ctx.walk(m):
358 for abs in ctx.walk(m):
359 fctx = ctx[abs]
359 fctx = ctx[abs]
360 if not opts.get('text') and util.binary(fctx.data()):
360 if not opts.get('text') and util.binary(fctx.data()):
361 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
361 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
362 continue
362 continue
363
363
364 lines = fctx.annotate(follow=follow, linenumber=linenumber,
364 lines = fctx.annotate(follow=follow, linenumber=linenumber,
365 diffopts=diffopts)
365 diffopts=diffopts)
366 formats = []
366 formats = []
367 pieces = []
367 pieces = []
368
368
369 for f, sep in funcmap:
369 for f, sep in funcmap:
370 l = [f(n) for n, dummy in lines]
370 l = [f(n) for n, dummy in lines]
371 if l:
371 if l:
372 if fm:
372 if fm:
373 formats.append(['%s' for x in l])
373 formats.append(['%s' for x in l])
374 else:
374 else:
375 sizes = [encoding.colwidth(x) for x in l]
375 sizes = [encoding.colwidth(x) for x in l]
376 ml = max(sizes)
376 ml = max(sizes)
377 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
377 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
378 pieces.append(l)
378 pieces.append(l)
379
379
380 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
380 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
381 fm.startitem()
381 fm.startitem()
382 fm.write(fields, "".join(f), *p)
382 fm.write(fields, "".join(f), *p)
383 fm.write('line', ": %s", l[1])
383 fm.write('line', ": %s", l[1])
384
384
385 if lines and not lines[-1][1].endswith('\n'):
385 if lines and not lines[-1][1].endswith('\n'):
386 fm.plain('\n')
386 fm.plain('\n')
387
387
388 fm.end()
388 fm.end()
389
389
390 @command('archive',
390 @command('archive',
391 [('', 'no-decode', None, _('do not pass files through decoders')),
391 [('', 'no-decode', None, _('do not pass files through decoders')),
392 ('p', 'prefix', '', _('directory prefix for files in archive'),
392 ('p', 'prefix', '', _('directory prefix for files in archive'),
393 _('PREFIX')),
393 _('PREFIX')),
394 ('r', 'rev', '', _('revision to distribute'), _('REV')),
394 ('r', 'rev', '', _('revision to distribute'), _('REV')),
395 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
395 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
396 ] + subrepoopts + walkopts,
396 ] + subrepoopts + walkopts,
397 _('[OPTION]... DEST'))
397 _('[OPTION]... DEST'))
398 def archive(ui, repo, dest, **opts):
398 def archive(ui, repo, dest, **opts):
399 '''create an unversioned archive of a repository revision
399 '''create an unversioned archive of a repository revision
400
400
401 By default, the revision used is the parent of the working
401 By default, the revision used is the parent of the working
402 directory; use -r/--rev to specify a different revision.
402 directory; use -r/--rev to specify a different revision.
403
403
404 The archive type is automatically detected based on file
404 The archive type is automatically detected based on file
405 extension (or override using -t/--type).
405 extension (or override using -t/--type).
406
406
407 .. container:: verbose
407 .. container:: verbose
408
408
409 Examples:
409 Examples:
410
410
411 - create a zip file containing the 1.0 release::
411 - create a zip file containing the 1.0 release::
412
412
413 hg archive -r 1.0 project-1.0.zip
413 hg archive -r 1.0 project-1.0.zip
414
414
415 - create a tarball excluding .hg files::
415 - create a tarball excluding .hg files::
416
416
417 hg archive project.tar.gz -X ".hg*"
417 hg archive project.tar.gz -X ".hg*"
418
418
419 Valid types are:
419 Valid types are:
420
420
421 :``files``: a directory full of files (default)
421 :``files``: a directory full of files (default)
422 :``tar``: tar archive, uncompressed
422 :``tar``: tar archive, uncompressed
423 :``tbz2``: tar archive, compressed using bzip2
423 :``tbz2``: tar archive, compressed using bzip2
424 :``tgz``: tar archive, compressed using gzip
424 :``tgz``: tar archive, compressed using gzip
425 :``uzip``: zip archive, uncompressed
425 :``uzip``: zip archive, uncompressed
426 :``zip``: zip archive, compressed using deflate
426 :``zip``: zip archive, compressed using deflate
427
427
428 The exact name of the destination archive or directory is given
428 The exact name of the destination archive or directory is given
429 using a format string; see :hg:`help export` for details.
429 using a format string; see :hg:`help export` for details.
430
430
431 Each member added to an archive file has a directory prefix
431 Each member added to an archive file has a directory prefix
432 prepended. Use -p/--prefix to specify a format string for the
432 prepended. Use -p/--prefix to specify a format string for the
433 prefix. The default is the basename of the archive, with suffixes
433 prefix. The default is the basename of the archive, with suffixes
434 removed.
434 removed.
435
435
436 Returns 0 on success.
436 Returns 0 on success.
437 '''
437 '''
438
438
439 ctx = scmutil.revsingle(repo, opts.get('rev'))
439 ctx = scmutil.revsingle(repo, opts.get('rev'))
440 if not ctx:
440 if not ctx:
441 raise error.Abort(_('no working directory: please specify a revision'))
441 raise error.Abort(_('no working directory: please specify a revision'))
442 node = ctx.node()
442 node = ctx.node()
443 dest = cmdutil.makefilename(repo, dest, node)
443 dest = cmdutil.makefilename(repo, dest, node)
444 if os.path.realpath(dest) == repo.root:
444 if os.path.realpath(dest) == repo.root:
445 raise error.Abort(_('repository root cannot be destination'))
445 raise error.Abort(_('repository root cannot be destination'))
446
446
447 kind = opts.get('type') or archival.guesskind(dest) or 'files'
447 kind = opts.get('type') or archival.guesskind(dest) or 'files'
448 prefix = opts.get('prefix')
448 prefix = opts.get('prefix')
449
449
450 if dest == '-':
450 if dest == '-':
451 if kind == 'files':
451 if kind == 'files':
452 raise error.Abort(_('cannot archive plain files to stdout'))
452 raise error.Abort(_('cannot archive plain files to stdout'))
453 dest = cmdutil.makefileobj(repo, dest)
453 dest = cmdutil.makefileobj(repo, dest)
454 if not prefix:
454 if not prefix:
455 prefix = os.path.basename(repo.root) + '-%h'
455 prefix = os.path.basename(repo.root) + '-%h'
456
456
457 prefix = cmdutil.makefilename(repo, prefix, node)
457 prefix = cmdutil.makefilename(repo, prefix, node)
458 matchfn = scmutil.match(ctx, [], opts)
458 matchfn = scmutil.match(ctx, [], opts)
459 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
459 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
460 matchfn, prefix, subrepos=opts.get('subrepos'))
460 matchfn, prefix, subrepos=opts.get('subrepos'))
461
461
462 @command('backout',
462 @command('backout',
463 [('', 'merge', None, _('merge with old dirstate parent after backout')),
463 [('', 'merge', None, _('merge with old dirstate parent after backout')),
464 ('', 'commit', None, _('commit if no conflicts were encountered')),
464 ('', 'commit', None, _('commit if no conflicts were encountered')),
465 ('', 'parent', '',
465 ('', 'parent', '',
466 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
466 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
467 ('r', 'rev', '', _('revision to backout'), _('REV')),
467 ('r', 'rev', '', _('revision to backout'), _('REV')),
468 ('e', 'edit', False, _('invoke editor on commit messages')),
468 ('e', 'edit', False, _('invoke editor on commit messages')),
469 ] + mergetoolopts + walkopts + commitopts + commitopts2,
469 ] + mergetoolopts + walkopts + commitopts + commitopts2,
470 _('[OPTION]... [-r] REV'))
470 _('[OPTION]... [-r] REV'))
471 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
471 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
472 '''reverse effect of earlier changeset
472 '''reverse effect of earlier changeset
473
473
474 Prepare a new changeset with the effect of REV undone in the
474 Prepare a new changeset with the effect of REV undone in the
475 current working directory.
475 current working directory.
476
476
477 If REV is the parent of the working directory, then this new changeset
477 If REV is the parent of the working directory, then this new changeset
478 is committed automatically. Otherwise, hg needs to merge the
478 is committed automatically. Otherwise, hg needs to merge the
479 changes and the merged result is left uncommitted.
479 changes and the merged result is left uncommitted.
480
480
481 .. note::
481 .. note::
482
482
483 backout cannot be used to fix either an unwanted or
483 backout cannot be used to fix either an unwanted or
484 incorrect merge.
484 incorrect merge.
485
485
486 .. container:: verbose
486 .. container:: verbose
487
487
488 By default, the pending changeset will have one parent,
488 By default, the pending changeset will have one parent,
489 maintaining a linear history. With --merge, the pending
489 maintaining a linear history. With --merge, the pending
490 changeset will instead have two parents: the old parent of the
490 changeset will instead have two parents: the old parent of the
491 working directory and a new child of REV that simply undoes REV.
491 working directory and a new child of REV that simply undoes REV.
492
492
493 Before version 1.7, the behavior without --merge was equivalent
493 Before version 1.7, the behavior without --merge was equivalent
494 to specifying --merge followed by :hg:`update --clean .` to
494 to specifying --merge followed by :hg:`update --clean .` to
495 cancel the merge and leave the child of REV as a head to be
495 cancel the merge and leave the child of REV as a head to be
496 merged separately.
496 merged separately.
497
497
498 See :hg:`help dates` for a list of formats valid for -d/--date.
498 See :hg:`help dates` for a list of formats valid for -d/--date.
499
499
500 See :hg:`help revert` for a way to restore files to the state
500 See :hg:`help revert` for a way to restore files to the state
501 of another revision.
501 of another revision.
502
502
503 Returns 0 on success, 1 if nothing to backout or there are unresolved
503 Returns 0 on success, 1 if nothing to backout or there are unresolved
504 files.
504 files.
505 '''
505 '''
506 if rev and node:
506 if rev and node:
507 raise error.Abort(_("please specify just one revision"))
507 raise error.Abort(_("please specify just one revision"))
508
508
509 if not rev:
509 if not rev:
510 rev = node
510 rev = node
511
511
512 if not rev:
512 if not rev:
513 raise error.Abort(_("please specify a revision to backout"))
513 raise error.Abort(_("please specify a revision to backout"))
514
514
515 date = opts.get('date')
515 date = opts.get('date')
516 if date:
516 if date:
517 opts['date'] = util.parsedate(date)
517 opts['date'] = util.parsedate(date)
518
518
519 cmdutil.checkunfinished(repo)
519 cmdutil.checkunfinished(repo)
520 cmdutil.bailifchanged(repo)
520 cmdutil.bailifchanged(repo)
521 node = scmutil.revsingle(repo, rev).node()
521 node = scmutil.revsingle(repo, rev).node()
522
522
523 op1, op2 = repo.dirstate.parents()
523 op1, op2 = repo.dirstate.parents()
524 if not repo.changelog.isancestor(node, op1):
524 if not repo.changelog.isancestor(node, op1):
525 raise error.Abort(_('cannot backout change that is not an ancestor'))
525 raise error.Abort(_('cannot backout change that is not an ancestor'))
526
526
527 p1, p2 = repo.changelog.parents(node)
527 p1, p2 = repo.changelog.parents(node)
528 if p1 == nullid:
528 if p1 == nullid:
529 raise error.Abort(_('cannot backout a change with no parents'))
529 raise error.Abort(_('cannot backout a change with no parents'))
530 if p2 != nullid:
530 if p2 != nullid:
531 if not opts.get('parent'):
531 if not opts.get('parent'):
532 raise error.Abort(_('cannot backout a merge changeset'))
532 raise error.Abort(_('cannot backout a merge changeset'))
533 p = repo.lookup(opts['parent'])
533 p = repo.lookup(opts['parent'])
534 if p not in (p1, p2):
534 if p not in (p1, p2):
535 raise error.Abort(_('%s is not a parent of %s') %
535 raise error.Abort(_('%s is not a parent of %s') %
536 (short(p), short(node)))
536 (short(p), short(node)))
537 parent = p
537 parent = p
538 else:
538 else:
539 if opts.get('parent'):
539 if opts.get('parent'):
540 raise error.Abort(_('cannot use --parent on non-merge changeset'))
540 raise error.Abort(_('cannot use --parent on non-merge changeset'))
541 parent = p1
541 parent = p1
542
542
543 # the backout should appear on the same branch
543 # the backout should appear on the same branch
544 wlock = repo.wlock()
544 wlock = repo.wlock()
545 try:
545 try:
546 branch = repo.dirstate.branch()
546 branch = repo.dirstate.branch()
547 bheads = repo.branchheads(branch)
547 bheads = repo.branchheads(branch)
548 rctx = scmutil.revsingle(repo, hex(parent))
548 rctx = scmutil.revsingle(repo, hex(parent))
549 if not opts.get('merge') and op1 != node:
549 if not opts.get('merge') and op1 != node:
550 dsguard = cmdutil.dirstateguard(repo, 'backout')
550 dsguard = cmdutil.dirstateguard(repo, 'backout')
551 try:
551 try:
552 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
552 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
553 'backout')
553 'backout')
554 stats = mergemod.update(repo, parent, True, True, False,
554 stats = mergemod.update(repo, parent, True, True, False,
555 node, False)
555 node, False)
556 repo.setparents(op1, op2)
556 repo.setparents(op1, op2)
557 dsguard.close()
557 dsguard.close()
558 hg._showstats(repo, stats)
558 hg._showstats(repo, stats)
559 if stats[3]:
559 if stats[3]:
560 repo.ui.status(_("use 'hg resolve' to retry unresolved "
560 repo.ui.status(_("use 'hg resolve' to retry unresolved "
561 "file merges\n"))
561 "file merges\n"))
562 return 1
562 return 1
563 elif not commit:
563 elif not commit:
564 msg = _("changeset %s backed out, "
564 msg = _("changeset %s backed out, "
565 "don't forget to commit.\n")
565 "don't forget to commit.\n")
566 ui.status(msg % short(node))
566 ui.status(msg % short(node))
567 return 0
567 return 0
568 finally:
568 finally:
569 ui.setconfig('ui', 'forcemerge', '', '')
569 ui.setconfig('ui', 'forcemerge', '', '')
570 lockmod.release(dsguard)
570 lockmod.release(dsguard)
571 else:
571 else:
572 hg.clean(repo, node, show_stats=False)
572 hg.clean(repo, node, show_stats=False)
573 repo.dirstate.setbranch(branch)
573 repo.dirstate.setbranch(branch)
574 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
574 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
575
575
576
576
577 def commitfunc(ui, repo, message, match, opts):
577 def commitfunc(ui, repo, message, match, opts):
578 editform = 'backout'
578 editform = 'backout'
579 e = cmdutil.getcommiteditor(editform=editform, **opts)
579 e = cmdutil.getcommiteditor(editform=editform, **opts)
580 if not message:
580 if not message:
581 # we don't translate commit messages
581 # we don't translate commit messages
582 message = "Backed out changeset %s" % short(node)
582 message = "Backed out changeset %s" % short(node)
583 e = cmdutil.getcommiteditor(edit=True, editform=editform)
583 e = cmdutil.getcommiteditor(edit=True, editform=editform)
584 return repo.commit(message, opts.get('user'), opts.get('date'),
584 return repo.commit(message, opts.get('user'), opts.get('date'),
585 match, editor=e)
585 match, editor=e)
586 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
586 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
587 if not newnode:
587 if not newnode:
588 ui.status(_("nothing changed\n"))
588 ui.status(_("nothing changed\n"))
589 return 1
589 return 1
590 cmdutil.commitstatus(repo, newnode, branch, bheads)
590 cmdutil.commitstatus(repo, newnode, branch, bheads)
591
591
592 def nice(node):
592 def nice(node):
593 return '%d:%s' % (repo.changelog.rev(node), short(node))
593 return '%d:%s' % (repo.changelog.rev(node), short(node))
594 ui.status(_('changeset %s backs out changeset %s\n') %
594 ui.status(_('changeset %s backs out changeset %s\n') %
595 (nice(repo.changelog.tip()), nice(node)))
595 (nice(repo.changelog.tip()), nice(node)))
596 if opts.get('merge') and op1 != node:
596 if opts.get('merge') and op1 != node:
597 hg.clean(repo, op1, show_stats=False)
597 hg.clean(repo, op1, show_stats=False)
598 ui.status(_('merging with changeset %s\n')
598 ui.status(_('merging with changeset %s\n')
599 % nice(repo.changelog.tip()))
599 % nice(repo.changelog.tip()))
600 try:
600 try:
601 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
601 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
602 'backout')
602 'backout')
603 return hg.merge(repo, hex(repo.changelog.tip()))
603 return hg.merge(repo, hex(repo.changelog.tip()))
604 finally:
604 finally:
605 ui.setconfig('ui', 'forcemerge', '', '')
605 ui.setconfig('ui', 'forcemerge', '', '')
606 finally:
606 finally:
607 wlock.release()
607 wlock.release()
608 return 0
608 return 0
609
609
610 @command('bisect',
610 @command('bisect',
611 [('r', 'reset', False, _('reset bisect state')),
611 [('r', 'reset', False, _('reset bisect state')),
612 ('g', 'good', False, _('mark changeset good')),
612 ('g', 'good', False, _('mark changeset good')),
613 ('b', 'bad', False, _('mark changeset bad')),
613 ('b', 'bad', False, _('mark changeset bad')),
614 ('s', 'skip', False, _('skip testing changeset')),
614 ('s', 'skip', False, _('skip testing changeset')),
615 ('e', 'extend', False, _('extend the bisect range')),
615 ('e', 'extend', False, _('extend the bisect range')),
616 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
616 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
617 ('U', 'noupdate', False, _('do not update to target'))],
617 ('U', 'noupdate', False, _('do not update to target'))],
618 _("[-gbsr] [-U] [-c CMD] [REV]"))
618 _("[-gbsr] [-U] [-c CMD] [REV]"))
619 def bisect(ui, repo, rev=None, extra=None, command=None,
619 def bisect(ui, repo, rev=None, extra=None, command=None,
620 reset=None, good=None, bad=None, skip=None, extend=None,
620 reset=None, good=None, bad=None, skip=None, extend=None,
621 noupdate=None):
621 noupdate=None):
622 """subdivision search of changesets
622 """subdivision search of changesets
623
623
624 This command helps to find changesets which introduce problems. To
624 This command helps to find changesets which introduce problems. To
625 use, mark the earliest changeset you know exhibits the problem as
625 use, mark the earliest changeset you know exhibits the problem as
626 bad, then mark the latest changeset which is free from the problem
626 bad, then mark the latest changeset which is free from the problem
627 as good. Bisect will update your working directory to a revision
627 as good. Bisect will update your working directory to a revision
628 for testing (unless the -U/--noupdate option is specified). Once
628 for testing (unless the -U/--noupdate option is specified). Once
629 you have performed tests, mark the working directory as good or
629 you have performed tests, mark the working directory as good or
630 bad, and bisect will either update to another candidate changeset
630 bad, and bisect will either update to another candidate changeset
631 or announce that it has found the bad revision.
631 or announce that it has found the bad revision.
632
632
633 As a shortcut, you can also use the revision argument to mark a
633 As a shortcut, you can also use the revision argument to mark a
634 revision as good or bad without checking it out first.
634 revision as good or bad without checking it out first.
635
635
636 If you supply a command, it will be used for automatic bisection.
636 If you supply a command, it will be used for automatic bisection.
637 The environment variable HG_NODE will contain the ID of the
637 The environment variable HG_NODE will contain the ID of the
638 changeset being tested. The exit status of the command will be
638 changeset being tested. The exit status of the command will be
639 used to mark revisions as good or bad: status 0 means good, 125
639 used to mark revisions as good or bad: status 0 means good, 125
640 means to skip the revision, 127 (command not found) will abort the
640 means to skip the revision, 127 (command not found) will abort the
641 bisection, and any other non-zero exit status means the revision
641 bisection, and any other non-zero exit status means the revision
642 is bad.
642 is bad.
643
643
644 .. container:: verbose
644 .. container:: verbose
645
645
646 Some examples:
646 Some examples:
647
647
648 - start a bisection with known bad revision 34, and good revision 12::
648 - start a bisection with known bad revision 34, and good revision 12::
649
649
650 hg bisect --bad 34
650 hg bisect --bad 34
651 hg bisect --good 12
651 hg bisect --good 12
652
652
653 - advance the current bisection by marking current revision as good or
653 - advance the current bisection by marking current revision as good or
654 bad::
654 bad::
655
655
656 hg bisect --good
656 hg bisect --good
657 hg bisect --bad
657 hg bisect --bad
658
658
659 - mark the current revision, or a known revision, to be skipped (e.g. if
659 - mark the current revision, or a known revision, to be skipped (e.g. if
660 that revision is not usable because of another issue)::
660 that revision is not usable because of another issue)::
661
661
662 hg bisect --skip
662 hg bisect --skip
663 hg bisect --skip 23
663 hg bisect --skip 23
664
664
665 - skip all revisions that do not touch directories ``foo`` or ``bar``::
665 - skip all revisions that do not touch directories ``foo`` or ``bar``::
666
666
667 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
667 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
668
668
669 - forget the current bisection::
669 - forget the current bisection::
670
670
671 hg bisect --reset
671 hg bisect --reset
672
672
673 - use 'make && make tests' to automatically find the first broken
673 - use 'make && make tests' to automatically find the first broken
674 revision::
674 revision::
675
675
676 hg bisect --reset
676 hg bisect --reset
677 hg bisect --bad 34
677 hg bisect --bad 34
678 hg bisect --good 12
678 hg bisect --good 12
679 hg bisect --command "make && make tests"
679 hg bisect --command "make && make tests"
680
680
681 - see all changesets whose states are already known in the current
681 - see all changesets whose states are already known in the current
682 bisection::
682 bisection::
683
683
684 hg log -r "bisect(pruned)"
684 hg log -r "bisect(pruned)"
685
685
686 - see the changeset currently being bisected (especially useful
686 - see the changeset currently being bisected (especially useful
687 if running with -U/--noupdate)::
687 if running with -U/--noupdate)::
688
688
689 hg log -r "bisect(current)"
689 hg log -r "bisect(current)"
690
690
691 - see all changesets that took part in the current bisection::
691 - see all changesets that took part in the current bisection::
692
692
693 hg log -r "bisect(range)"
693 hg log -r "bisect(range)"
694
694
695 - you can even get a nice graph::
695 - you can even get a nice graph::
696
696
697 hg log --graph -r "bisect(range)"
697 hg log --graph -r "bisect(range)"
698
698
699 See :hg:`help revsets` for more about the `bisect()` keyword.
699 See :hg:`help revsets` for more about the `bisect()` keyword.
700
700
701 Returns 0 on success.
701 Returns 0 on success.
702 """
702 """
703 def extendbisectrange(nodes, good):
703 def extendbisectrange(nodes, good):
704 # bisect is incomplete when it ends on a merge node and
704 # bisect is incomplete when it ends on a merge node and
705 # one of the parent was not checked.
705 # one of the parent was not checked.
706 parents = repo[nodes[0]].parents()
706 parents = repo[nodes[0]].parents()
707 if len(parents) > 1:
707 if len(parents) > 1:
708 if good:
708 if good:
709 side = state['bad']
709 side = state['bad']
710 else:
710 else:
711 side = state['good']
711 side = state['good']
712 num = len(set(i.node() for i in parents) & set(side))
712 num = len(set(i.node() for i in parents) & set(side))
713 if num == 1:
713 if num == 1:
714 return parents[0].ancestor(parents[1])
714 return parents[0].ancestor(parents[1])
715 return None
715 return None
716
716
717 def print_result(nodes, good):
717 def print_result(nodes, good):
718 displayer = cmdutil.show_changeset(ui, repo, {})
718 displayer = cmdutil.show_changeset(ui, repo, {})
719 if len(nodes) == 1:
719 if len(nodes) == 1:
720 # narrowed it down to a single revision
720 # narrowed it down to a single revision
721 if good:
721 if good:
722 ui.write(_("The first good revision is:\n"))
722 ui.write(_("The first good revision is:\n"))
723 else:
723 else:
724 ui.write(_("The first bad revision is:\n"))
724 ui.write(_("The first bad revision is:\n"))
725 displayer.show(repo[nodes[0]])
725 displayer.show(repo[nodes[0]])
726 extendnode = extendbisectrange(nodes, good)
726 extendnode = extendbisectrange(nodes, good)
727 if extendnode is not None:
727 if extendnode is not None:
728 ui.write(_('Not all ancestors of this changeset have been'
728 ui.write(_('Not all ancestors of this changeset have been'
729 ' checked.\nUse bisect --extend to continue the '
729 ' checked.\nUse bisect --extend to continue the '
730 'bisection from\nthe common ancestor, %s.\n')
730 'bisection from\nthe common ancestor, %s.\n')
731 % extendnode)
731 % extendnode)
732 else:
732 else:
733 # multiple possible revisions
733 # multiple possible revisions
734 if good:
734 if good:
735 ui.write(_("Due to skipped revisions, the first "
735 ui.write(_("Due to skipped revisions, the first "
736 "good revision could be any of:\n"))
736 "good revision could be any of:\n"))
737 else:
737 else:
738 ui.write(_("Due to skipped revisions, the first "
738 ui.write(_("Due to skipped revisions, the first "
739 "bad revision could be any of:\n"))
739 "bad revision could be any of:\n"))
740 for n in nodes:
740 for n in nodes:
741 displayer.show(repo[n])
741 displayer.show(repo[n])
742 displayer.close()
742 displayer.close()
743
743
744 def check_state(state, interactive=True):
744 def check_state(state, interactive=True):
745 if not state['good'] or not state['bad']:
745 if not state['good'] or not state['bad']:
746 if (good or bad or skip or reset) and interactive:
746 if (good or bad or skip or reset) and interactive:
747 return
747 return
748 if not state['good']:
748 if not state['good']:
749 raise error.Abort(_('cannot bisect (no known good revisions)'))
749 raise error.Abort(_('cannot bisect (no known good revisions)'))
750 else:
750 else:
751 raise error.Abort(_('cannot bisect (no known bad revisions)'))
751 raise error.Abort(_('cannot bisect (no known bad revisions)'))
752 return True
752 return True
753
753
754 # backward compatibility
754 # backward compatibility
755 if rev in "good bad reset init".split():
755 if rev in "good bad reset init".split():
756 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
756 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
757 cmd, rev, extra = rev, extra, None
757 cmd, rev, extra = rev, extra, None
758 if cmd == "good":
758 if cmd == "good":
759 good = True
759 good = True
760 elif cmd == "bad":
760 elif cmd == "bad":
761 bad = True
761 bad = True
762 else:
762 else:
763 reset = True
763 reset = True
764 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
764 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
765 raise error.Abort(_('incompatible arguments'))
765 raise error.Abort(_('incompatible arguments'))
766
766
767 cmdutil.checkunfinished(repo)
767 cmdutil.checkunfinished(repo)
768
768
769 if reset:
769 if reset:
770 p = repo.join("bisect.state")
770 p = repo.join("bisect.state")
771 if os.path.exists(p):
771 if os.path.exists(p):
772 os.unlink(p)
772 os.unlink(p)
773 return
773 return
774
774
775 state = hbisect.load_state(repo)
775 state = hbisect.load_state(repo)
776
776
777 if command:
777 if command:
778 changesets = 1
778 changesets = 1
779 if noupdate:
779 if noupdate:
780 try:
780 try:
781 node = state['current'][0]
781 node = state['current'][0]
782 except LookupError:
782 except LookupError:
783 raise error.Abort(_('current bisect revision is unknown - '
783 raise error.Abort(_('current bisect revision is unknown - '
784 'start a new bisect to fix'))
784 'start a new bisect to fix'))
785 else:
785 else:
786 node, p2 = repo.dirstate.parents()
786 node, p2 = repo.dirstate.parents()
787 if p2 != nullid:
787 if p2 != nullid:
788 raise error.Abort(_('current bisect revision is a merge'))
788 raise error.Abort(_('current bisect revision is a merge'))
789 try:
789 try:
790 while changesets:
790 while changesets:
791 # update state
791 # update state
792 state['current'] = [node]
792 state['current'] = [node]
793 hbisect.save_state(repo, state)
793 hbisect.save_state(repo, state)
794 status = ui.system(command, environ={'HG_NODE': hex(node)})
794 status = ui.system(command, environ={'HG_NODE': hex(node)})
795 if status == 125:
795 if status == 125:
796 transition = "skip"
796 transition = "skip"
797 elif status == 0:
797 elif status == 0:
798 transition = "good"
798 transition = "good"
799 # status < 0 means process was killed
799 # status < 0 means process was killed
800 elif status == 127:
800 elif status == 127:
801 raise error.Abort(_("failed to execute %s") % command)
801 raise error.Abort(_("failed to execute %s") % command)
802 elif status < 0:
802 elif status < 0:
803 raise error.Abort(_("%s killed") % command)
803 raise error.Abort(_("%s killed") % command)
804 else:
804 else:
805 transition = "bad"
805 transition = "bad"
806 ctx = scmutil.revsingle(repo, rev, node)
806 ctx = scmutil.revsingle(repo, rev, node)
807 rev = None # clear for future iterations
807 rev = None # clear for future iterations
808 state[transition].append(ctx.node())
808 state[transition].append(ctx.node())
809 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
809 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
810 check_state(state, interactive=False)
810 check_state(state, interactive=False)
811 # bisect
811 # bisect
812 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
812 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
813 # update to next check
813 # update to next check
814 node = nodes[0]
814 node = nodes[0]
815 if not noupdate:
815 if not noupdate:
816 cmdutil.bailifchanged(repo)
816 cmdutil.bailifchanged(repo)
817 hg.clean(repo, node, show_stats=False)
817 hg.clean(repo, node, show_stats=False)
818 finally:
818 finally:
819 state['current'] = [node]
819 state['current'] = [node]
820 hbisect.save_state(repo, state)
820 hbisect.save_state(repo, state)
821 print_result(nodes, bgood)
821 print_result(nodes, bgood)
822 return
822 return
823
823
824 # update state
824 # update state
825
825
826 if rev:
826 if rev:
827 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
827 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
828 else:
828 else:
829 nodes = [repo.lookup('.')]
829 nodes = [repo.lookup('.')]
830
830
831 if good or bad or skip:
831 if good or bad or skip:
832 if good:
832 if good:
833 state['good'] += nodes
833 state['good'] += nodes
834 elif bad:
834 elif bad:
835 state['bad'] += nodes
835 state['bad'] += nodes
836 elif skip:
836 elif skip:
837 state['skip'] += nodes
837 state['skip'] += nodes
838 hbisect.save_state(repo, state)
838 hbisect.save_state(repo, state)
839
839
840 if not check_state(state):
840 if not check_state(state):
841 return
841 return
842
842
843 # actually bisect
843 # actually bisect
844 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
844 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
845 if extend:
845 if extend:
846 if not changesets:
846 if not changesets:
847 extendnode = extendbisectrange(nodes, good)
847 extendnode = extendbisectrange(nodes, good)
848 if extendnode is not None:
848 if extendnode is not None:
849 ui.write(_("Extending search to changeset %d:%s\n")
849 ui.write(_("Extending search to changeset %d:%s\n")
850 % (extendnode.rev(), extendnode))
850 % (extendnode.rev(), extendnode))
851 state['current'] = [extendnode.node()]
851 state['current'] = [extendnode.node()]
852 hbisect.save_state(repo, state)
852 hbisect.save_state(repo, state)
853 if noupdate:
853 if noupdate:
854 return
854 return
855 cmdutil.bailifchanged(repo)
855 cmdutil.bailifchanged(repo)
856 return hg.clean(repo, extendnode.node())
856 return hg.clean(repo, extendnode.node())
857 raise error.Abort(_("nothing to extend"))
857 raise error.Abort(_("nothing to extend"))
858
858
859 if changesets == 0:
859 if changesets == 0:
860 print_result(nodes, good)
860 print_result(nodes, good)
861 else:
861 else:
862 assert len(nodes) == 1 # only a single node can be tested next
862 assert len(nodes) == 1 # only a single node can be tested next
863 node = nodes[0]
863 node = nodes[0]
864 # compute the approximate number of remaining tests
864 # compute the approximate number of remaining tests
865 tests, size = 0, 2
865 tests, size = 0, 2
866 while size <= changesets:
866 while size <= changesets:
867 tests, size = tests + 1, size * 2
867 tests, size = tests + 1, size * 2
868 rev = repo.changelog.rev(node)
868 rev = repo.changelog.rev(node)
869 ui.write(_("Testing changeset %d:%s "
869 ui.write(_("Testing changeset %d:%s "
870 "(%d changesets remaining, ~%d tests)\n")
870 "(%d changesets remaining, ~%d tests)\n")
871 % (rev, short(node), changesets, tests))
871 % (rev, short(node), changesets, tests))
872 state['current'] = [node]
872 state['current'] = [node]
873 hbisect.save_state(repo, state)
873 hbisect.save_state(repo, state)
874 if not noupdate:
874 if not noupdate:
875 cmdutil.bailifchanged(repo)
875 cmdutil.bailifchanged(repo)
876 return hg.clean(repo, node)
876 return hg.clean(repo, node)
877
877
878 @command('bookmarks|bookmark',
878 @command('bookmarks|bookmark',
879 [('f', 'force', False, _('force')),
879 [('f', 'force', False, _('force')),
880 ('r', 'rev', '', _('revision'), _('REV')),
880 ('r', 'rev', '', _('revision'), _('REV')),
881 ('d', 'delete', False, _('delete a given bookmark')),
881 ('d', 'delete', False, _('delete a given bookmark')),
882 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
882 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
883 ('i', 'inactive', False, _('mark a bookmark inactive')),
883 ('i', 'inactive', False, _('mark a bookmark inactive')),
884 ] + formatteropts,
884 ] + formatteropts,
885 _('hg bookmarks [OPTIONS]... [NAME]...'))
885 _('hg bookmarks [OPTIONS]... [NAME]...'))
886 def bookmark(ui, repo, *names, **opts):
886 def bookmark(ui, repo, *names, **opts):
887 '''create a new bookmark or list existing bookmarks
887 '''create a new bookmark or list existing bookmarks
888
888
889 Bookmarks are labels on changesets to help track lines of development.
889 Bookmarks are labels on changesets to help track lines of development.
890 Bookmarks are unversioned and can be moved, renamed and deleted.
890 Bookmarks are unversioned and can be moved, renamed and deleted.
891 Deleting or moving a bookmark has no effect on the associated changesets.
891 Deleting or moving a bookmark has no effect on the associated changesets.
892
892
893 Creating or updating to a bookmark causes it to be marked as 'active'.
893 Creating or updating to a bookmark causes it to be marked as 'active'.
894 The active bookmark is indicated with a '*'.
894 The active bookmark is indicated with a '*'.
895 When a commit is made, the active bookmark will advance to the new commit.
895 When a commit is made, the active bookmark will advance to the new commit.
896 A plain :hg:`update` will also advance an active bookmark, if possible.
896 A plain :hg:`update` will also advance an active bookmark, if possible.
897 Updating away from a bookmark will cause it to be deactivated.
897 Updating away from a bookmark will cause it to be deactivated.
898
898
899 Bookmarks can be pushed and pulled between repositories (see
899 Bookmarks can be pushed and pulled between repositories (see
900 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
900 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
901 diverged, a new 'divergent bookmark' of the form 'name@path' will
901 diverged, a new 'divergent bookmark' of the form 'name@path' will
902 be created. Using :hg:`merge` will resolve the divergence.
902 be created. Using :hg:`merge` will resolve the divergence.
903
903
904 A bookmark named '@' has the special property that :hg:`clone` will
904 A bookmark named '@' has the special property that :hg:`clone` will
905 check it out by default if it exists.
905 check it out by default if it exists.
906
906
907 .. container:: verbose
907 .. container:: verbose
908
908
909 Examples:
909 Examples:
910
910
911 - create an active bookmark for a new line of development::
911 - create an active bookmark for a new line of development::
912
912
913 hg book new-feature
913 hg book new-feature
914
914
915 - create an inactive bookmark as a place marker::
915 - create an inactive bookmark as a place marker::
916
916
917 hg book -i reviewed
917 hg book -i reviewed
918
918
919 - create an inactive bookmark on another changeset::
919 - create an inactive bookmark on another changeset::
920
920
921 hg book -r .^ tested
921 hg book -r .^ tested
922
922
923 - rename bookmark turkey to dinner::
923 - rename bookmark turkey to dinner::
924
924
925 hg book -m turkey dinner
925 hg book -m turkey dinner
926
926
927 - move the '@' bookmark from another branch::
927 - move the '@' bookmark from another branch::
928
928
929 hg book -f @
929 hg book -f @
930 '''
930 '''
931 force = opts.get('force')
931 force = opts.get('force')
932 rev = opts.get('rev')
932 rev = opts.get('rev')
933 delete = opts.get('delete')
933 delete = opts.get('delete')
934 rename = opts.get('rename')
934 rename = opts.get('rename')
935 inactive = opts.get('inactive')
935 inactive = opts.get('inactive')
936
936
937 def checkformat(mark):
937 def checkformat(mark):
938 mark = mark.strip()
938 mark = mark.strip()
939 if not mark:
939 if not mark:
940 raise error.Abort(_("bookmark names cannot consist entirely of "
940 raise error.Abort(_("bookmark names cannot consist entirely of "
941 "whitespace"))
941 "whitespace"))
942 scmutil.checknewlabel(repo, mark, 'bookmark')
942 scmutil.checknewlabel(repo, mark, 'bookmark')
943 return mark
943 return mark
944
944
945 def checkconflict(repo, mark, cur, force=False, target=None):
945 def checkconflict(repo, mark, cur, force=False, target=None):
946 if mark in marks and not force:
946 if mark in marks and not force:
947 if target:
947 if target:
948 if marks[mark] == target and target == cur:
948 if marks[mark] == target and target == cur:
949 # re-activating a bookmark
949 # re-activating a bookmark
950 return
950 return
951 anc = repo.changelog.ancestors([repo[target].rev()])
951 anc = repo.changelog.ancestors([repo[target].rev()])
952 bmctx = repo[marks[mark]]
952 bmctx = repo[marks[mark]]
953 divs = [repo[b].node() for b in marks
953 divs = [repo[b].node() for b in marks
954 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
954 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
955
955
956 # allow resolving a single divergent bookmark even if moving
956 # allow resolving a single divergent bookmark even if moving
957 # the bookmark across branches when a revision is specified
957 # the bookmark across branches when a revision is specified
958 # that contains a divergent bookmark
958 # that contains a divergent bookmark
959 if bmctx.rev() not in anc and target in divs:
959 if bmctx.rev() not in anc and target in divs:
960 bookmarks.deletedivergent(repo, [target], mark)
960 bookmarks.deletedivergent(repo, [target], mark)
961 return
961 return
962
962
963 deletefrom = [b for b in divs
963 deletefrom = [b for b in divs
964 if repo[b].rev() in anc or b == target]
964 if repo[b].rev() in anc or b == target]
965 bookmarks.deletedivergent(repo, deletefrom, mark)
965 bookmarks.deletedivergent(repo, deletefrom, mark)
966 if bookmarks.validdest(repo, bmctx, repo[target]):
966 if bookmarks.validdest(repo, bmctx, repo[target]):
967 ui.status(_("moving bookmark '%s' forward from %s\n") %
967 ui.status(_("moving bookmark '%s' forward from %s\n") %
968 (mark, short(bmctx.node())))
968 (mark, short(bmctx.node())))
969 return
969 return
970 raise error.Abort(_("bookmark '%s' already exists "
970 raise error.Abort(_("bookmark '%s' already exists "
971 "(use -f to force)") % mark)
971 "(use -f to force)") % mark)
972 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
972 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
973 and not force):
973 and not force):
974 raise error.Abort(
974 raise error.Abort(
975 _("a bookmark cannot have the name of an existing branch"))
975 _("a bookmark cannot have the name of an existing branch"))
976
976
977 if delete and rename:
977 if delete and rename:
978 raise error.Abort(_("--delete and --rename are incompatible"))
978 raise error.Abort(_("--delete and --rename are incompatible"))
979 if delete and rev:
979 if delete and rev:
980 raise error.Abort(_("--rev is incompatible with --delete"))
980 raise error.Abort(_("--rev is incompatible with --delete"))
981 if rename and rev:
981 if rename and rev:
982 raise error.Abort(_("--rev is incompatible with --rename"))
982 raise error.Abort(_("--rev is incompatible with --rename"))
983 if not names and (delete or rev):
983 if not names and (delete or rev):
984 raise error.Abort(_("bookmark name required"))
984 raise error.Abort(_("bookmark name required"))
985
985
986 if delete or rename or names or inactive:
986 if delete or rename or names or inactive:
987 wlock = lock = tr = None
987 wlock = lock = tr = None
988 try:
988 try:
989 wlock = repo.wlock()
989 wlock = repo.wlock()
990 lock = repo.lock()
990 lock = repo.lock()
991 cur = repo.changectx('.').node()
991 cur = repo.changectx('.').node()
992 marks = repo._bookmarks
992 marks = repo._bookmarks
993 if delete:
993 if delete:
994 tr = repo.transaction('bookmark')
994 tr = repo.transaction('bookmark')
995 for mark in names:
995 for mark in names:
996 if mark not in marks:
996 if mark not in marks:
997 raise error.Abort(_("bookmark '%s' does not exist") %
997 raise error.Abort(_("bookmark '%s' does not exist") %
998 mark)
998 mark)
999 if mark == repo._activebookmark:
999 if mark == repo._activebookmark:
1000 bookmarks.deactivate(repo)
1000 bookmarks.deactivate(repo)
1001 del marks[mark]
1001 del marks[mark]
1002
1002
1003 elif rename:
1003 elif rename:
1004 tr = repo.transaction('bookmark')
1004 tr = repo.transaction('bookmark')
1005 if not names:
1005 if not names:
1006 raise error.Abort(_("new bookmark name required"))
1006 raise error.Abort(_("new bookmark name required"))
1007 elif len(names) > 1:
1007 elif len(names) > 1:
1008 raise error.Abort(_("only one new bookmark name allowed"))
1008 raise error.Abort(_("only one new bookmark name allowed"))
1009 mark = checkformat(names[0])
1009 mark = checkformat(names[0])
1010 if rename not in marks:
1010 if rename not in marks:
1011 raise error.Abort(_("bookmark '%s' does not exist")
1011 raise error.Abort(_("bookmark '%s' does not exist")
1012 % rename)
1012 % rename)
1013 checkconflict(repo, mark, cur, force)
1013 checkconflict(repo, mark, cur, force)
1014 marks[mark] = marks[rename]
1014 marks[mark] = marks[rename]
1015 if repo._activebookmark == rename and not inactive:
1015 if repo._activebookmark == rename and not inactive:
1016 bookmarks.activate(repo, mark)
1016 bookmarks.activate(repo, mark)
1017 del marks[rename]
1017 del marks[rename]
1018 elif names:
1018 elif names:
1019 tr = repo.transaction('bookmark')
1019 tr = repo.transaction('bookmark')
1020 newact = None
1020 newact = None
1021 for mark in names:
1021 for mark in names:
1022 mark = checkformat(mark)
1022 mark = checkformat(mark)
1023 if newact is None:
1023 if newact is None:
1024 newact = mark
1024 newact = mark
1025 if inactive and mark == repo._activebookmark:
1025 if inactive and mark == repo._activebookmark:
1026 bookmarks.deactivate(repo)
1026 bookmarks.deactivate(repo)
1027 return
1027 return
1028 tgt = cur
1028 tgt = cur
1029 if rev:
1029 if rev:
1030 tgt = scmutil.revsingle(repo, rev).node()
1030 tgt = scmutil.revsingle(repo, rev).node()
1031 checkconflict(repo, mark, cur, force, tgt)
1031 checkconflict(repo, mark, cur, force, tgt)
1032 marks[mark] = tgt
1032 marks[mark] = tgt
1033 if not inactive and cur == marks[newact] and not rev:
1033 if not inactive and cur == marks[newact] and not rev:
1034 bookmarks.activate(repo, newact)
1034 bookmarks.activate(repo, newact)
1035 elif cur != tgt and newact == repo._activebookmark:
1035 elif cur != tgt and newact == repo._activebookmark:
1036 bookmarks.deactivate(repo)
1036 bookmarks.deactivate(repo)
1037 elif inactive:
1037 elif inactive:
1038 if len(marks) == 0:
1038 if len(marks) == 0:
1039 ui.status(_("no bookmarks set\n"))
1039 ui.status(_("no bookmarks set\n"))
1040 elif not repo._activebookmark:
1040 elif not repo._activebookmark:
1041 ui.status(_("no active bookmark\n"))
1041 ui.status(_("no active bookmark\n"))
1042 else:
1042 else:
1043 bookmarks.deactivate(repo)
1043 bookmarks.deactivate(repo)
1044 if tr is not None:
1044 if tr is not None:
1045 marks.recordchange(tr)
1045 marks.recordchange(tr)
1046 tr.close()
1046 tr.close()
1047 finally:
1047 finally:
1048 lockmod.release(tr, lock, wlock)
1048 lockmod.release(tr, lock, wlock)
1049 else: # show bookmarks
1049 else: # show bookmarks
1050 fm = ui.formatter('bookmarks', opts)
1050 fm = ui.formatter('bookmarks', opts)
1051 hexfn = fm.hexfunc
1051 hexfn = fm.hexfunc
1052 marks = repo._bookmarks
1052 marks = repo._bookmarks
1053 if len(marks) == 0 and not fm:
1053 if len(marks) == 0 and not fm:
1054 ui.status(_("no bookmarks set\n"))
1054 ui.status(_("no bookmarks set\n"))
1055 for bmark, n in sorted(marks.iteritems()):
1055 for bmark, n in sorted(marks.iteritems()):
1056 active = repo._activebookmark
1056 active = repo._activebookmark
1057 if bmark == active:
1057 if bmark == active:
1058 prefix, label = '*', activebookmarklabel
1058 prefix, label = '*', activebookmarklabel
1059 else:
1059 else:
1060 prefix, label = ' ', ''
1060 prefix, label = ' ', ''
1061
1061
1062 fm.startitem()
1062 fm.startitem()
1063 if not ui.quiet:
1063 if not ui.quiet:
1064 fm.plain(' %s ' % prefix, label=label)
1064 fm.plain(' %s ' % prefix, label=label)
1065 fm.write('bookmark', '%s', bmark, label=label)
1065 fm.write('bookmark', '%s', bmark, label=label)
1066 pad = " " * (25 - encoding.colwidth(bmark))
1066 pad = " " * (25 - encoding.colwidth(bmark))
1067 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1067 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1068 repo.changelog.rev(n), hexfn(n), label=label)
1068 repo.changelog.rev(n), hexfn(n), label=label)
1069 fm.data(active=(bmark == active))
1069 fm.data(active=(bmark == active))
1070 fm.plain('\n')
1070 fm.plain('\n')
1071 fm.end()
1071 fm.end()
1072
1072
1073 @command('branch',
1073 @command('branch',
1074 [('f', 'force', None,
1074 [('f', 'force', None,
1075 _('set branch name even if it shadows an existing branch')),
1075 _('set branch name even if it shadows an existing branch')),
1076 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1076 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1077 _('[-fC] [NAME]'))
1077 _('[-fC] [NAME]'))
1078 def branch(ui, repo, label=None, **opts):
1078 def branch(ui, repo, label=None, **opts):
1079 """set or show the current branch name
1079 """set or show the current branch name
1080
1080
1081 .. note::
1081 .. note::
1082
1082
1083 Branch names are permanent and global. Use :hg:`bookmark` to create a
1083 Branch names are permanent and global. Use :hg:`bookmark` to create a
1084 light-weight bookmark instead. See :hg:`help glossary` for more
1084 light-weight bookmark instead. See :hg:`help glossary` for more
1085 information about named branches and bookmarks.
1085 information about named branches and bookmarks.
1086
1086
1087 With no argument, show the current branch name. With one argument,
1087 With no argument, show the current branch name. With one argument,
1088 set the working directory branch name (the branch will not exist
1088 set the working directory branch name (the branch will not exist
1089 in the repository until the next commit). Standard practice
1089 in the repository until the next commit). Standard practice
1090 recommends that primary development take place on the 'default'
1090 recommends that primary development take place on the 'default'
1091 branch.
1091 branch.
1092
1092
1093 Unless -f/--force is specified, branch will not let you set a
1093 Unless -f/--force is specified, branch will not let you set a
1094 branch name that already exists.
1094 branch name that already exists.
1095
1095
1096 Use -C/--clean to reset the working directory branch to that of
1096 Use -C/--clean to reset the working directory branch to that of
1097 the parent of the working directory, negating a previous branch
1097 the parent of the working directory, negating a previous branch
1098 change.
1098 change.
1099
1099
1100 Use the command :hg:`update` to switch to an existing branch. Use
1100 Use the command :hg:`update` to switch to an existing branch. Use
1101 :hg:`commit --close-branch` to mark this branch head as closed.
1101 :hg:`commit --close-branch` to mark this branch head as closed.
1102 When all heads of the branch are closed, the branch will be
1102 When all heads of the branch are closed, the branch will be
1103 considered closed.
1103 considered closed.
1104
1104
1105 Returns 0 on success.
1105 Returns 0 on success.
1106 """
1106 """
1107 if label:
1107 if label:
1108 label = label.strip()
1108 label = label.strip()
1109
1109
1110 if not opts.get('clean') and not label:
1110 if not opts.get('clean') and not label:
1111 ui.write("%s\n" % repo.dirstate.branch())
1111 ui.write("%s\n" % repo.dirstate.branch())
1112 return
1112 return
1113
1113
1114 wlock = repo.wlock()
1114 wlock = repo.wlock()
1115 try:
1115 try:
1116 if opts.get('clean'):
1116 if opts.get('clean'):
1117 label = repo[None].p1().branch()
1117 label = repo[None].p1().branch()
1118 repo.dirstate.setbranch(label)
1118 repo.dirstate.setbranch(label)
1119 ui.status(_('reset working directory to branch %s\n') % label)
1119 ui.status(_('reset working directory to branch %s\n') % label)
1120 elif label:
1120 elif label:
1121 if not opts.get('force') and label in repo.branchmap():
1121 if not opts.get('force') and label in repo.branchmap():
1122 if label not in [p.branch() for p in repo.parents()]:
1122 if label not in [p.branch() for p in repo.parents()]:
1123 raise error.Abort(_('a branch of the same name already'
1123 raise error.Abort(_('a branch of the same name already'
1124 ' exists'),
1124 ' exists'),
1125 # i18n: "it" refers to an existing branch
1125 # i18n: "it" refers to an existing branch
1126 hint=_("use 'hg update' to switch to it"))
1126 hint=_("use 'hg update' to switch to it"))
1127 scmutil.checknewlabel(repo, label, 'branch')
1127 scmutil.checknewlabel(repo, label, 'branch')
1128 repo.dirstate.setbranch(label)
1128 repo.dirstate.setbranch(label)
1129 ui.status(_('marked working directory as branch %s\n') % label)
1129 ui.status(_('marked working directory as branch %s\n') % label)
1130
1130
1131 # find any open named branches aside from default
1131 # find any open named branches aside from default
1132 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1132 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1133 if n != "default" and not c]
1133 if n != "default" and not c]
1134 if not others:
1134 if not others:
1135 ui.status(_('(branches are permanent and global, '
1135 ui.status(_('(branches are permanent and global, '
1136 'did you want a bookmark?)\n'))
1136 'did you want a bookmark?)\n'))
1137 finally:
1137 finally:
1138 wlock.release()
1138 wlock.release()
1139
1139
1140 @command('branches',
1140 @command('branches',
1141 [('a', 'active', False,
1141 [('a', 'active', False,
1142 _('show only branches that have unmerged heads (DEPRECATED)')),
1142 _('show only branches that have unmerged heads (DEPRECATED)')),
1143 ('c', 'closed', False, _('show normal and closed branches')),
1143 ('c', 'closed', False, _('show normal and closed branches')),
1144 ] + formatteropts,
1144 ] + formatteropts,
1145 _('[-ac]'))
1145 _('[-ac]'))
1146 def branches(ui, repo, active=False, closed=False, **opts):
1146 def branches(ui, repo, active=False, closed=False, **opts):
1147 """list repository named branches
1147 """list repository named branches
1148
1148
1149 List the repository's named branches, indicating which ones are
1149 List the repository's named branches, indicating which ones are
1150 inactive. If -c/--closed is specified, also list branches which have
1150 inactive. If -c/--closed is specified, also list branches which have
1151 been marked closed (see :hg:`commit --close-branch`).
1151 been marked closed (see :hg:`commit --close-branch`).
1152
1152
1153 Use the command :hg:`update` to switch to an existing branch.
1153 Use the command :hg:`update` to switch to an existing branch.
1154
1154
1155 Returns 0.
1155 Returns 0.
1156 """
1156 """
1157
1157
1158 fm = ui.formatter('branches', opts)
1158 fm = ui.formatter('branches', opts)
1159 hexfunc = fm.hexfunc
1159 hexfunc = fm.hexfunc
1160
1160
1161 allheads = set(repo.heads())
1161 allheads = set(repo.heads())
1162 branches = []
1162 branches = []
1163 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1163 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1164 isactive = not isclosed and bool(set(heads) & allheads)
1164 isactive = not isclosed and bool(set(heads) & allheads)
1165 branches.append((tag, repo[tip], isactive, not isclosed))
1165 branches.append((tag, repo[tip], isactive, not isclosed))
1166 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1166 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1167 reverse=True)
1167 reverse=True)
1168
1168
1169 for tag, ctx, isactive, isopen in branches:
1169 for tag, ctx, isactive, isopen in branches:
1170 if active and not isactive:
1170 if active and not isactive:
1171 continue
1171 continue
1172 if isactive:
1172 if isactive:
1173 label = 'branches.active'
1173 label = 'branches.active'
1174 notice = ''
1174 notice = ''
1175 elif not isopen:
1175 elif not isopen:
1176 if not closed:
1176 if not closed:
1177 continue
1177 continue
1178 label = 'branches.closed'
1178 label = 'branches.closed'
1179 notice = _(' (closed)')
1179 notice = _(' (closed)')
1180 else:
1180 else:
1181 label = 'branches.inactive'
1181 label = 'branches.inactive'
1182 notice = _(' (inactive)')
1182 notice = _(' (inactive)')
1183 current = (tag == repo.dirstate.branch())
1183 current = (tag == repo.dirstate.branch())
1184 if current:
1184 if current:
1185 label = 'branches.current'
1185 label = 'branches.current'
1186
1186
1187 fm.startitem()
1187 fm.startitem()
1188 fm.write('branch', '%s', tag, label=label)
1188 fm.write('branch', '%s', tag, label=label)
1189 rev = ctx.rev()
1189 rev = ctx.rev()
1190 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1190 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1191 fmt = ' ' * padsize + ' %d:%s'
1191 fmt = ' ' * padsize + ' %d:%s'
1192 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1192 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1193 label='log.changeset changeset.%s' % ctx.phasestr())
1193 label='log.changeset changeset.%s' % ctx.phasestr())
1194 fm.data(active=isactive, closed=not isopen, current=current)
1194 fm.data(active=isactive, closed=not isopen, current=current)
1195 if not ui.quiet:
1195 if not ui.quiet:
1196 fm.plain(notice)
1196 fm.plain(notice)
1197 fm.plain('\n')
1197 fm.plain('\n')
1198 fm.end()
1198 fm.end()
1199
1199
1200 @command('bundle',
1200 @command('bundle',
1201 [('f', 'force', None, _('run even when the destination is unrelated')),
1201 [('f', 'force', None, _('run even when the destination is unrelated')),
1202 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1202 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1203 _('REV')),
1203 _('REV')),
1204 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1204 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1205 _('BRANCH')),
1205 _('BRANCH')),
1206 ('', 'base', [],
1206 ('', 'base', [],
1207 _('a base changeset assumed to be available at the destination'),
1207 _('a base changeset assumed to be available at the destination'),
1208 _('REV')),
1208 _('REV')),
1209 ('a', 'all', None, _('bundle all changesets in the repository')),
1209 ('a', 'all', None, _('bundle all changesets in the repository')),
1210 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1210 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1211 ] + remoteopts,
1211 ] + remoteopts,
1212 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1212 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1213 def bundle(ui, repo, fname, dest=None, **opts):
1213 def bundle(ui, repo, fname, dest=None, **opts):
1214 """create a changegroup file
1214 """create a changegroup file
1215
1215
1216 Generate a compressed changegroup file collecting changesets not
1216 Generate a compressed changegroup file collecting changesets not
1217 known to be in another repository.
1217 known to be in another repository.
1218
1218
1219 If you omit the destination repository, then hg assumes the
1219 If you omit the destination repository, then hg assumes the
1220 destination will have all the nodes you specify with --base
1220 destination will have all the nodes you specify with --base
1221 parameters. To create a bundle containing all changesets, use
1221 parameters. To create a bundle containing all changesets, use
1222 -a/--all (or --base null).
1222 -a/--all (or --base null).
1223
1223
1224 You can change bundle format with the -t/--type option. You can
1224 You can change bundle format with the -t/--type option. You can
1225 specify a compression, a bundle version or both using a dash
1225 specify a compression, a bundle version or both using a dash
1226 (comp-version). The available compression methods are: none, bzip2,
1226 (comp-version). The available compression methods are: none, bzip2,
1227 and gzip (by default, bundles are compressed using bzip2). The
1227 and gzip (by default, bundles are compressed using bzip2). The
1228 available format are: v1, v2 (default to most suitable).
1228 available format are: v1, v2 (default to most suitable).
1229
1229
1230 The bundle file can then be transferred using conventional means
1230 The bundle file can then be transferred using conventional means
1231 and applied to another repository with the unbundle or pull
1231 and applied to another repository with the unbundle or pull
1232 command. This is useful when direct push and pull are not
1232 command. This is useful when direct push and pull are not
1233 available or when exporting an entire repository is undesirable.
1233 available or when exporting an entire repository is undesirable.
1234
1234
1235 Applying bundles preserves all changeset contents including
1235 Applying bundles preserves all changeset contents including
1236 permissions, copy/rename information, and revision history.
1236 permissions, copy/rename information, and revision history.
1237
1237
1238 Returns 0 on success, 1 if no changes found.
1238 Returns 0 on success, 1 if no changes found.
1239 """
1239 """
1240 revs = None
1240 revs = None
1241 if 'rev' in opts:
1241 if 'rev' in opts:
1242 revs = scmutil.revrange(repo, opts['rev'])
1242 revs = scmutil.revrange(repo, opts['rev'])
1243
1243
1244 bundletype = opts.get('type', 'bzip2').lower()
1244 bundletype = opts.get('type', 'bzip2').lower()
1245 try:
1245 try:
1246 bcompression, cgversion = exchange.parsebundlespec(
1246 bcompression, cgversion = exchange.parsebundlespec(
1247 repo, bundletype, strict=False)
1247 repo, bundletype, strict=False)
1248 except error.UnsupportedBundleSpecification as e:
1248 except error.UnsupportedBundleSpecification as e:
1249 raise error.Abort(str(e),
1249 raise error.Abort(str(e),
1250 hint=_('see "hg help bundle" for supported '
1250 hint=_('see "hg help bundle" for supported '
1251 'values for --type'))
1251 'values for --type'))
1252
1252
1253 if opts.get('all'):
1253 if opts.get('all'):
1254 base = ['null']
1254 base = ['null']
1255 else:
1255 else:
1256 base = scmutil.revrange(repo, opts.get('base'))
1256 base = scmutil.revrange(repo, opts.get('base'))
1257 # TODO: get desired bundlecaps from command line.
1257 # TODO: get desired bundlecaps from command line.
1258 bundlecaps = None
1258 bundlecaps = None
1259 if base:
1259 if base:
1260 if dest:
1260 if dest:
1261 raise error.Abort(_("--base is incompatible with specifying "
1261 raise error.Abort(_("--base is incompatible with specifying "
1262 "a destination"))
1262 "a destination"))
1263 common = [repo.lookup(rev) for rev in base]
1263 common = [repo.lookup(rev) for rev in base]
1264 heads = revs and map(repo.lookup, revs) or revs
1264 heads = revs and map(repo.lookup, revs) or revs
1265 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1265 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1266 common=common, bundlecaps=bundlecaps,
1266 common=common, bundlecaps=bundlecaps,
1267 version=cgversion)
1267 version=cgversion)
1268 outgoing = None
1268 outgoing = None
1269 else:
1269 else:
1270 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1270 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1271 dest, branches = hg.parseurl(dest, opts.get('branch'))
1271 dest, branches = hg.parseurl(dest, opts.get('branch'))
1272 other = hg.peer(repo, opts, dest)
1272 other = hg.peer(repo, opts, dest)
1273 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1273 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1274 heads = revs and map(repo.lookup, revs) or revs
1274 heads = revs and map(repo.lookup, revs) or revs
1275 outgoing = discovery.findcommonoutgoing(repo, other,
1275 outgoing = discovery.findcommonoutgoing(repo, other,
1276 onlyheads=heads,
1276 onlyheads=heads,
1277 force=opts.get('force'),
1277 force=opts.get('force'),
1278 portable=True)
1278 portable=True)
1279 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1279 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1280 bundlecaps, version=cgversion)
1280 bundlecaps, version=cgversion)
1281 if not cg:
1281 if not cg:
1282 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1282 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1283 return 1
1283 return 1
1284
1284
1285 if cgversion == '01': #bundle1
1285 if cgversion == '01': #bundle1
1286 if bcompression is None:
1286 if bcompression is None:
1287 bcompression = 'UN'
1287 bcompression = 'UN'
1288 bversion = 'HG10' + bcompression
1288 bversion = 'HG10' + bcompression
1289 bcompression = None
1289 bcompression = None
1290 else:
1290 else:
1291 assert cgversion == '02'
1291 assert cgversion == '02'
1292 bversion = 'HG20'
1292 bversion = 'HG20'
1293
1293
1294
1294
1295 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1295 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1296
1296
1297 @command('cat',
1297 @command('cat',
1298 [('o', 'output', '',
1298 [('o', 'output', '',
1299 _('print output to file with formatted name'), _('FORMAT')),
1299 _('print output to file with formatted name'), _('FORMAT')),
1300 ('r', 'rev', '', _('print the given revision'), _('REV')),
1300 ('r', 'rev', '', _('print the given revision'), _('REV')),
1301 ('', 'decode', None, _('apply any matching decode filter')),
1301 ('', 'decode', None, _('apply any matching decode filter')),
1302 ] + walkopts,
1302 ] + walkopts,
1303 _('[OPTION]... FILE...'),
1303 _('[OPTION]... FILE...'),
1304 inferrepo=True)
1304 inferrepo=True)
1305 def cat(ui, repo, file1, *pats, **opts):
1305 def cat(ui, repo, file1, *pats, **opts):
1306 """output the current or given revision of files
1306 """output the current or given revision of files
1307
1307
1308 Print the specified files as they were at the given revision. If
1308 Print the specified files as they were at the given revision. If
1309 no revision is given, the parent of the working directory is used.
1309 no revision is given, the parent of the working directory is used.
1310
1310
1311 Output may be to a file, in which case the name of the file is
1311 Output may be to a file, in which case the name of the file is
1312 given using a format string. The formatting rules as follows:
1312 given using a format string. The formatting rules as follows:
1313
1313
1314 :``%%``: literal "%" character
1314 :``%%``: literal "%" character
1315 :``%s``: basename of file being printed
1315 :``%s``: basename of file being printed
1316 :``%d``: dirname of file being printed, or '.' if in repository root
1316 :``%d``: dirname of file being printed, or '.' if in repository root
1317 :``%p``: root-relative path name of file being printed
1317 :``%p``: root-relative path name of file being printed
1318 :``%H``: changeset hash (40 hexadecimal digits)
1318 :``%H``: changeset hash (40 hexadecimal digits)
1319 :``%R``: changeset revision number
1319 :``%R``: changeset revision number
1320 :``%h``: short-form changeset hash (12 hexadecimal digits)
1320 :``%h``: short-form changeset hash (12 hexadecimal digits)
1321 :``%r``: zero-padded changeset revision number
1321 :``%r``: zero-padded changeset revision number
1322 :``%b``: basename of the exporting repository
1322 :``%b``: basename of the exporting repository
1323
1323
1324 Returns 0 on success.
1324 Returns 0 on success.
1325 """
1325 """
1326 ctx = scmutil.revsingle(repo, opts.get('rev'))
1326 ctx = scmutil.revsingle(repo, opts.get('rev'))
1327 m = scmutil.match(ctx, (file1,) + pats, opts)
1327 m = scmutil.match(ctx, (file1,) + pats, opts)
1328
1328
1329 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1329 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1330
1330
1331 @command('^clone',
1331 @command('^clone',
1332 [('U', 'noupdate', None, _('the clone will include an empty working '
1332 [('U', 'noupdate', None, _('the clone will include an empty working '
1333 'directory (only a repository)')),
1333 'directory (only a repository)')),
1334 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1334 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1335 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1335 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1336 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1336 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1337 ('', 'pull', None, _('use pull protocol to copy metadata')),
1337 ('', 'pull', None, _('use pull protocol to copy metadata')),
1338 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1338 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1339 ] + remoteopts,
1339 ] + remoteopts,
1340 _('[OPTION]... SOURCE [DEST]'),
1340 _('[OPTION]... SOURCE [DEST]'),
1341 norepo=True)
1341 norepo=True)
1342 def clone(ui, source, dest=None, **opts):
1342 def clone(ui, source, dest=None, **opts):
1343 """make a copy of an existing repository
1343 """make a copy of an existing repository
1344
1344
1345 Create a copy of an existing repository in a new directory.
1345 Create a copy of an existing repository in a new directory.
1346
1346
1347 If no destination directory name is specified, it defaults to the
1347 If no destination directory name is specified, it defaults to the
1348 basename of the source.
1348 basename of the source.
1349
1349
1350 The location of the source is added to the new repository's
1350 The location of the source is added to the new repository's
1351 ``.hg/hgrc`` file, as the default to be used for future pulls.
1351 ``.hg/hgrc`` file, as the default to be used for future pulls.
1352
1352
1353 Only local paths and ``ssh://`` URLs are supported as
1353 Only local paths and ``ssh://`` URLs are supported as
1354 destinations. For ``ssh://`` destinations, no working directory or
1354 destinations. For ``ssh://`` destinations, no working directory or
1355 ``.hg/hgrc`` will be created on the remote side.
1355 ``.hg/hgrc`` will be created on the remote side.
1356
1356
1357 To pull only a subset of changesets, specify one or more revisions
1357 To pull only a subset of changesets, specify one or more revisions
1358 identifiers with -r/--rev or branches with -b/--branch. The
1358 identifiers with -r/--rev or branches with -b/--branch. The
1359 resulting clone will contain only the specified changesets and
1359 resulting clone will contain only the specified changesets and
1360 their ancestors. These options (or 'clone src#rev dest') imply
1360 their ancestors. These options (or 'clone src#rev dest') imply
1361 --pull, even for local source repositories. Note that specifying a
1361 --pull, even for local source repositories. Note that specifying a
1362 tag will include the tagged changeset but not the changeset
1362 tag will include the tagged changeset but not the changeset
1363 containing the tag.
1363 containing the tag.
1364
1364
1365 If the source repository has a bookmark called '@' set, that
1365 If the source repository has a bookmark called '@' set, that
1366 revision will be checked out in the new repository by default.
1366 revision will be checked out in the new repository by default.
1367
1367
1368 To check out a particular version, use -u/--update, or
1368 To check out a particular version, use -u/--update, or
1369 -U/--noupdate to create a clone with no working directory.
1369 -U/--noupdate to create a clone with no working directory.
1370
1370
1371 .. container:: verbose
1371 .. container:: verbose
1372
1372
1373 For efficiency, hardlinks are used for cloning whenever the
1373 For efficiency, hardlinks are used for cloning whenever the
1374 source and destination are on the same filesystem (note this
1374 source and destination are on the same filesystem (note this
1375 applies only to the repository data, not to the working
1375 applies only to the repository data, not to the working
1376 directory). Some filesystems, such as AFS, implement hardlinking
1376 directory). Some filesystems, such as AFS, implement hardlinking
1377 incorrectly, but do not report errors. In these cases, use the
1377 incorrectly, but do not report errors. In these cases, use the
1378 --pull option to avoid hardlinking.
1378 --pull option to avoid hardlinking.
1379
1379
1380 In some cases, you can clone repositories and the working
1380 In some cases, you can clone repositories and the working
1381 directory using full hardlinks with ::
1381 directory using full hardlinks with ::
1382
1382
1383 $ cp -al REPO REPOCLONE
1383 $ cp -al REPO REPOCLONE
1384
1384
1385 This is the fastest way to clone, but it is not always safe. The
1385 This is the fastest way to clone, but it is not always safe. The
1386 operation is not atomic (making sure REPO is not modified during
1386 operation is not atomic (making sure REPO is not modified during
1387 the operation is up to you) and you have to make sure your
1387 the operation is up to you) and you have to make sure your
1388 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1388 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1389 so). Also, this is not compatible with certain extensions that
1389 so). Also, this is not compatible with certain extensions that
1390 place their metadata under the .hg directory, such as mq.
1390 place their metadata under the .hg directory, such as mq.
1391
1391
1392 Mercurial will update the working directory to the first applicable
1392 Mercurial will update the working directory to the first applicable
1393 revision from this list:
1393 revision from this list:
1394
1394
1395 a) null if -U or the source repository has no changesets
1395 a) null if -U or the source repository has no changesets
1396 b) if -u . and the source repository is local, the first parent of
1396 b) if -u . and the source repository is local, the first parent of
1397 the source repository's working directory
1397 the source repository's working directory
1398 c) the changeset specified with -u (if a branch name, this means the
1398 c) the changeset specified with -u (if a branch name, this means the
1399 latest head of that branch)
1399 latest head of that branch)
1400 d) the changeset specified with -r
1400 d) the changeset specified with -r
1401 e) the tipmost head specified with -b
1401 e) the tipmost head specified with -b
1402 f) the tipmost head specified with the url#branch source syntax
1402 f) the tipmost head specified with the url#branch source syntax
1403 g) the revision marked with the '@' bookmark, if present
1403 g) the revision marked with the '@' bookmark, if present
1404 h) the tipmost head of the default branch
1404 h) the tipmost head of the default branch
1405 i) tip
1405 i) tip
1406
1406
1407 Examples:
1407 Examples:
1408
1408
1409 - clone a remote repository to a new directory named hg/::
1409 - clone a remote repository to a new directory named hg/::
1410
1410
1411 hg clone http://selenic.com/hg
1411 hg clone http://selenic.com/hg
1412
1412
1413 - create a lightweight local clone::
1413 - create a lightweight local clone::
1414
1414
1415 hg clone project/ project-feature/
1415 hg clone project/ project-feature/
1416
1416
1417 - clone from an absolute path on an ssh server (note double-slash)::
1417 - clone from an absolute path on an ssh server (note double-slash)::
1418
1418
1419 hg clone ssh://user@server//home/projects/alpha/
1419 hg clone ssh://user@server//home/projects/alpha/
1420
1420
1421 - do a high-speed clone over a LAN while checking out a
1421 - do a high-speed clone over a LAN while checking out a
1422 specified version::
1422 specified version::
1423
1423
1424 hg clone --uncompressed http://server/repo -u 1.5
1424 hg clone --uncompressed http://server/repo -u 1.5
1425
1425
1426 - create a repository without changesets after a particular revision::
1426 - create a repository without changesets after a particular revision::
1427
1427
1428 hg clone -r 04e544 experimental/ good/
1428 hg clone -r 04e544 experimental/ good/
1429
1429
1430 - clone (and track) a particular named branch::
1430 - clone (and track) a particular named branch::
1431
1431
1432 hg clone http://selenic.com/hg#stable
1432 hg clone http://selenic.com/hg#stable
1433
1433
1434 See :hg:`help urls` for details on specifying URLs.
1434 See :hg:`help urls` for details on specifying URLs.
1435
1435
1436 Returns 0 on success.
1436 Returns 0 on success.
1437 """
1437 """
1438 if opts.get('noupdate') and opts.get('updaterev'):
1438 if opts.get('noupdate') and opts.get('updaterev'):
1439 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1439 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1440
1440
1441 r = hg.clone(ui, opts, source, dest,
1441 r = hg.clone(ui, opts, source, dest,
1442 pull=opts.get('pull'),
1442 pull=opts.get('pull'),
1443 stream=opts.get('uncompressed'),
1443 stream=opts.get('uncompressed'),
1444 rev=opts.get('rev'),
1444 rev=opts.get('rev'),
1445 update=opts.get('updaterev') or not opts.get('noupdate'),
1445 update=opts.get('updaterev') or not opts.get('noupdate'),
1446 branch=opts.get('branch'),
1446 branch=opts.get('branch'),
1447 shareopts=opts.get('shareopts'))
1447 shareopts=opts.get('shareopts'))
1448
1448
1449 return r is None
1449 return r is None
1450
1450
1451 @command('^commit|ci',
1451 @command('^commit|ci',
1452 [('A', 'addremove', None,
1452 [('A', 'addremove', None,
1453 _('mark new/missing files as added/removed before committing')),
1453 _('mark new/missing files as added/removed before committing')),
1454 ('', 'close-branch', None,
1454 ('', 'close-branch', None,
1455 _('mark a branch head as closed')),
1455 _('mark a branch head as closed')),
1456 ('', 'amend', None, _('amend the parent of the working directory')),
1456 ('', 'amend', None, _('amend the parent of the working directory')),
1457 ('s', 'secret', None, _('use the secret phase for committing')),
1457 ('s', 'secret', None, _('use the secret phase for committing')),
1458 ('e', 'edit', None, _('invoke editor on commit messages')),
1458 ('e', 'edit', None, _('invoke editor on commit messages')),
1459 ('i', 'interactive', None, _('use interactive mode')),
1459 ('i', 'interactive', None, _('use interactive mode')),
1460 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1460 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1461 _('[OPTION]... [FILE]...'),
1461 _('[OPTION]... [FILE]...'),
1462 inferrepo=True)
1462 inferrepo=True)
1463 def commit(ui, repo, *pats, **opts):
1463 def commit(ui, repo, *pats, **opts):
1464 """commit the specified files or all outstanding changes
1464 """commit the specified files or all outstanding changes
1465
1465
1466 Commit changes to the given files into the repository. Unlike a
1466 Commit changes to the given files into the repository. Unlike a
1467 centralized SCM, this operation is a local operation. See
1467 centralized SCM, this operation is a local operation. See
1468 :hg:`push` for a way to actively distribute your changes.
1468 :hg:`push` for a way to actively distribute your changes.
1469
1469
1470 If a list of files is omitted, all changes reported by :hg:`status`
1470 If a list of files is omitted, all changes reported by :hg:`status`
1471 will be committed.
1471 will be committed.
1472
1472
1473 If you are committing the result of a merge, do not provide any
1473 If you are committing the result of a merge, do not provide any
1474 filenames or -I/-X filters.
1474 filenames or -I/-X filters.
1475
1475
1476 If no commit message is specified, Mercurial starts your
1476 If no commit message is specified, Mercurial starts your
1477 configured editor where you can enter a message. In case your
1477 configured editor where you can enter a message. In case your
1478 commit fails, you will find a backup of your message in
1478 commit fails, you will find a backup of your message in
1479 ``.hg/last-message.txt``.
1479 ``.hg/last-message.txt``.
1480
1480
1481 The --close-branch flag can be used to mark the current branch
1481 The --close-branch flag can be used to mark the current branch
1482 head closed. When all heads of a branch are closed, the branch
1482 head closed. When all heads of a branch are closed, the branch
1483 will be considered closed and no longer listed.
1483 will be considered closed and no longer listed.
1484
1484
1485 The --amend flag can be used to amend the parent of the
1485 The --amend flag can be used to amend the parent of the
1486 working directory with a new commit that contains the changes
1486 working directory with a new commit that contains the changes
1487 in the parent in addition to those currently reported by :hg:`status`,
1487 in the parent in addition to those currently reported by :hg:`status`,
1488 if there are any. The old commit is stored in a backup bundle in
1488 if there are any. The old commit is stored in a backup bundle in
1489 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1489 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1490 on how to restore it).
1490 on how to restore it).
1491
1491
1492 Message, user and date are taken from the amended commit unless
1492 Message, user and date are taken from the amended commit unless
1493 specified. When a message isn't specified on the command line,
1493 specified. When a message isn't specified on the command line,
1494 the editor will open with the message of the amended commit.
1494 the editor will open with the message of the amended commit.
1495
1495
1496 It is not possible to amend public changesets (see :hg:`help phases`)
1496 It is not possible to amend public changesets (see :hg:`help phases`)
1497 or changesets that have children.
1497 or changesets that have children.
1498
1498
1499 See :hg:`help dates` for a list of formats valid for -d/--date.
1499 See :hg:`help dates` for a list of formats valid for -d/--date.
1500
1500
1501 Returns 0 on success, 1 if nothing changed.
1501 Returns 0 on success, 1 if nothing changed.
1502 """
1502 """
1503 if opts.get('interactive'):
1503 if opts.get('interactive'):
1504 opts.pop('interactive')
1504 opts.pop('interactive')
1505 cmdutil.dorecord(ui, repo, commit, None, False,
1505 cmdutil.dorecord(ui, repo, commit, None, False,
1506 cmdutil.recordfilter, *pats, **opts)
1506 cmdutil.recordfilter, *pats, **opts)
1507 return
1507 return
1508
1508
1509 if opts.get('subrepos'):
1509 if opts.get('subrepos'):
1510 if opts.get('amend'):
1510 if opts.get('amend'):
1511 raise error.Abort(_('cannot amend with --subrepos'))
1511 raise error.Abort(_('cannot amend with --subrepos'))
1512 # Let --subrepos on the command line override config setting.
1512 # Let --subrepos on the command line override config setting.
1513 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1513 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1514
1514
1515 cmdutil.checkunfinished(repo, commit=True)
1515 cmdutil.checkunfinished(repo, commit=True)
1516
1516
1517 branch = repo[None].branch()
1517 branch = repo[None].branch()
1518 bheads = repo.branchheads(branch)
1518 bheads = repo.branchheads(branch)
1519
1519
1520 extra = {}
1520 extra = {}
1521 if opts.get('close_branch'):
1521 if opts.get('close_branch'):
1522 extra['close'] = 1
1522 extra['close'] = 1
1523
1523
1524 if not bheads:
1524 if not bheads:
1525 raise error.Abort(_('can only close branch heads'))
1525 raise error.Abort(_('can only close branch heads'))
1526 elif opts.get('amend'):
1526 elif opts.get('amend'):
1527 if repo.parents()[0].p1().branch() != branch and \
1527 if repo.parents()[0].p1().branch() != branch and \
1528 repo.parents()[0].p2().branch() != branch:
1528 repo.parents()[0].p2().branch() != branch:
1529 raise error.Abort(_('can only close branch heads'))
1529 raise error.Abort(_('can only close branch heads'))
1530
1530
1531 if opts.get('amend'):
1531 if opts.get('amend'):
1532 if ui.configbool('ui', 'commitsubrepos'):
1532 if ui.configbool('ui', 'commitsubrepos'):
1533 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1533 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1534
1534
1535 old = repo['.']
1535 old = repo['.']
1536 if not old.mutable():
1536 if not old.mutable():
1537 raise error.Abort(_('cannot amend public changesets'))
1537 raise error.Abort(_('cannot amend public changesets'))
1538 if len(repo[None].parents()) > 1:
1538 if len(repo[None].parents()) > 1:
1539 raise error.Abort(_('cannot amend while merging'))
1539 raise error.Abort(_('cannot amend while merging'))
1540 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1540 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1541 if not allowunstable and old.children():
1541 if not allowunstable and old.children():
1542 raise error.Abort(_('cannot amend changeset with children'))
1542 raise error.Abort(_('cannot amend changeset with children'))
1543
1543
1544 # commitfunc is used only for temporary amend commit by cmdutil.amend
1544 # commitfunc is used only for temporary amend commit by cmdutil.amend
1545 def commitfunc(ui, repo, message, match, opts):
1545 def commitfunc(ui, repo, message, match, opts):
1546 return repo.commit(message,
1546 return repo.commit(message,
1547 opts.get('user') or old.user(),
1547 opts.get('user') or old.user(),
1548 opts.get('date') or old.date(),
1548 opts.get('date') or old.date(),
1549 match,
1549 match,
1550 extra=extra)
1550 extra=extra)
1551
1551
1552 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1552 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1553 if node == old.node():
1553 if node == old.node():
1554 ui.status(_("nothing changed\n"))
1554 ui.status(_("nothing changed\n"))
1555 return 1
1555 return 1
1556 else:
1556 else:
1557 def commitfunc(ui, repo, message, match, opts):
1557 def commitfunc(ui, repo, message, match, opts):
1558 backup = ui.backupconfig('phases', 'new-commit')
1558 backup = ui.backupconfig('phases', 'new-commit')
1559 baseui = repo.baseui
1559 baseui = repo.baseui
1560 basebackup = baseui.backupconfig('phases', 'new-commit')
1560 basebackup = baseui.backupconfig('phases', 'new-commit')
1561 try:
1561 try:
1562 if opts.get('secret'):
1562 if opts.get('secret'):
1563 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1563 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1564 # Propagate to subrepos
1564 # Propagate to subrepos
1565 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1565 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1566
1566
1567 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1567 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1568 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1568 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1569 return repo.commit(message, opts.get('user'), opts.get('date'),
1569 return repo.commit(message, opts.get('user'), opts.get('date'),
1570 match,
1570 match,
1571 editor=editor,
1571 editor=editor,
1572 extra=extra)
1572 extra=extra)
1573 finally:
1573 finally:
1574 ui.restoreconfig(backup)
1574 ui.restoreconfig(backup)
1575 repo.baseui.restoreconfig(basebackup)
1575 repo.baseui.restoreconfig(basebackup)
1576
1576
1577
1577
1578 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1578 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1579
1579
1580 if not node:
1580 if not node:
1581 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1581 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1582 if stat[3]:
1582 if stat[3]:
1583 ui.status(_("nothing changed (%d missing files, see "
1583 ui.status(_("nothing changed (%d missing files, see "
1584 "'hg status')\n") % len(stat[3]))
1584 "'hg status')\n") % len(stat[3]))
1585 else:
1585 else:
1586 ui.status(_("nothing changed\n"))
1586 ui.status(_("nothing changed\n"))
1587 return 1
1587 return 1
1588
1588
1589 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1589 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1590
1590
1591 @command('config|showconfig|debugconfig',
1591 @command('config|showconfig|debugconfig',
1592 [('u', 'untrusted', None, _('show untrusted configuration options')),
1592 [('u', 'untrusted', None, _('show untrusted configuration options')),
1593 ('e', 'edit', None, _('edit user config')),
1593 ('e', 'edit', None, _('edit user config')),
1594 ('l', 'local', None, _('edit repository config')),
1594 ('l', 'local', None, _('edit repository config')),
1595 ('g', 'global', None, _('edit global config'))],
1595 ('g', 'global', None, _('edit global config'))],
1596 _('[-u] [NAME]...'),
1596 _('[-u] [NAME]...'),
1597 optionalrepo=True)
1597 optionalrepo=True)
1598 def config(ui, repo, *values, **opts):
1598 def config(ui, repo, *values, **opts):
1599 """show combined config settings from all hgrc files
1599 """show combined config settings from all hgrc files
1600
1600
1601 With no arguments, print names and values of all config items.
1601 With no arguments, print names and values of all config items.
1602
1602
1603 With one argument of the form section.name, print just the value
1603 With one argument of the form section.name, print just the value
1604 of that config item.
1604 of that config item.
1605
1605
1606 With multiple arguments, print names and values of all config
1606 With multiple arguments, print names and values of all config
1607 items with matching section names.
1607 items with matching section names.
1608
1608
1609 With --edit, start an editor on the user-level config file. With
1609 With --edit, start an editor on the user-level config file. With
1610 --global, edit the system-wide config file. With --local, edit the
1610 --global, edit the system-wide config file. With --local, edit the
1611 repository-level config file.
1611 repository-level config file.
1612
1612
1613 With --debug, the source (filename and line number) is printed
1613 With --debug, the source (filename and line number) is printed
1614 for each config item.
1614 for each config item.
1615
1615
1616 See :hg:`help config` for more information about config files.
1616 See :hg:`help config` for more information about config files.
1617
1617
1618 Returns 0 on success, 1 if NAME does not exist.
1618 Returns 0 on success, 1 if NAME does not exist.
1619
1619
1620 """
1620 """
1621
1621
1622 if opts.get('edit') or opts.get('local') or opts.get('global'):
1622 if opts.get('edit') or opts.get('local') or opts.get('global'):
1623 if opts.get('local') and opts.get('global'):
1623 if opts.get('local') and opts.get('global'):
1624 raise error.Abort(_("can't use --local and --global together"))
1624 raise error.Abort(_("can't use --local and --global together"))
1625
1625
1626 if opts.get('local'):
1626 if opts.get('local'):
1627 if not repo:
1627 if not repo:
1628 raise error.Abort(_("can't use --local outside a repository"))
1628 raise error.Abort(_("can't use --local outside a repository"))
1629 paths = [repo.join('hgrc')]
1629 paths = [repo.join('hgrc')]
1630 elif opts.get('global'):
1630 elif opts.get('global'):
1631 paths = scmutil.systemrcpath()
1631 paths = scmutil.systemrcpath()
1632 else:
1632 else:
1633 paths = scmutil.userrcpath()
1633 paths = scmutil.userrcpath()
1634
1634
1635 for f in paths:
1635 for f in paths:
1636 if os.path.exists(f):
1636 if os.path.exists(f):
1637 break
1637 break
1638 else:
1638 else:
1639 if opts.get('global'):
1639 if opts.get('global'):
1640 samplehgrc = uimod.samplehgrcs['global']
1640 samplehgrc = uimod.samplehgrcs['global']
1641 elif opts.get('local'):
1641 elif opts.get('local'):
1642 samplehgrc = uimod.samplehgrcs['local']
1642 samplehgrc = uimod.samplehgrcs['local']
1643 else:
1643 else:
1644 samplehgrc = uimod.samplehgrcs['user']
1644 samplehgrc = uimod.samplehgrcs['user']
1645
1645
1646 f = paths[0]
1646 f = paths[0]
1647 fp = open(f, "w")
1647 fp = open(f, "w")
1648 fp.write(samplehgrc)
1648 fp.write(samplehgrc)
1649 fp.close()
1649 fp.close()
1650
1650
1651 editor = ui.geteditor()
1651 editor = ui.geteditor()
1652 ui.system("%s \"%s\"" % (editor, f),
1652 ui.system("%s \"%s\"" % (editor, f),
1653 onerr=error.Abort, errprefix=_("edit failed"))
1653 onerr=error.Abort, errprefix=_("edit failed"))
1654 return
1654 return
1655
1655
1656 for f in scmutil.rcpath():
1656 for f in scmutil.rcpath():
1657 ui.debug('read config from: %s\n' % f)
1657 ui.debug('read config from: %s\n' % f)
1658 untrusted = bool(opts.get('untrusted'))
1658 untrusted = bool(opts.get('untrusted'))
1659 if values:
1659 if values:
1660 sections = [v for v in values if '.' not in v]
1660 sections = [v for v in values if '.' not in v]
1661 items = [v for v in values if '.' in v]
1661 items = [v for v in values if '.' in v]
1662 if len(items) > 1 or items and sections:
1662 if len(items) > 1 or items and sections:
1663 raise error.Abort(_('only one config item permitted'))
1663 raise error.Abort(_('only one config item permitted'))
1664 matched = False
1664 matched = False
1665 for section, name, value in ui.walkconfig(untrusted=untrusted):
1665 for section, name, value in ui.walkconfig(untrusted=untrusted):
1666 value = str(value).replace('\n', '\\n')
1666 value = str(value).replace('\n', '\\n')
1667 sectname = section + '.' + name
1667 sectname = section + '.' + name
1668 if values:
1668 if values:
1669 for v in values:
1669 for v in values:
1670 if v == section:
1670 if v == section:
1671 ui.debug('%s: ' %
1671 ui.debug('%s: ' %
1672 ui.configsource(section, name, untrusted))
1672 ui.configsource(section, name, untrusted))
1673 ui.write('%s=%s\n' % (sectname, value))
1673 ui.write('%s=%s\n' % (sectname, value))
1674 matched = True
1674 matched = True
1675 elif v == sectname:
1675 elif v == sectname:
1676 ui.debug('%s: ' %
1676 ui.debug('%s: ' %
1677 ui.configsource(section, name, untrusted))
1677 ui.configsource(section, name, untrusted))
1678 ui.write(value, '\n')
1678 ui.write(value, '\n')
1679 matched = True
1679 matched = True
1680 else:
1680 else:
1681 ui.debug('%s: ' %
1681 ui.debug('%s: ' %
1682 ui.configsource(section, name, untrusted))
1682 ui.configsource(section, name, untrusted))
1683 ui.write('%s=%s\n' % (sectname, value))
1683 ui.write('%s=%s\n' % (sectname, value))
1684 matched = True
1684 matched = True
1685 if matched:
1685 if matched:
1686 return 0
1686 return 0
1687 return 1
1687 return 1
1688
1688
1689 @command('copy|cp',
1689 @command('copy|cp',
1690 [('A', 'after', None, _('record a copy that has already occurred')),
1690 [('A', 'after', None, _('record a copy that has already occurred')),
1691 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1691 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1692 ] + walkopts + dryrunopts,
1692 ] + walkopts + dryrunopts,
1693 _('[OPTION]... [SOURCE]... DEST'))
1693 _('[OPTION]... [SOURCE]... DEST'))
1694 def copy(ui, repo, *pats, **opts):
1694 def copy(ui, repo, *pats, **opts):
1695 """mark files as copied for the next commit
1695 """mark files as copied for the next commit
1696
1696
1697 Mark dest as having copies of source files. If dest is a
1697 Mark dest as having copies of source files. If dest is a
1698 directory, copies are put in that directory. If dest is a file,
1698 directory, copies are put in that directory. If dest is a file,
1699 the source must be a single file.
1699 the source must be a single file.
1700
1700
1701 By default, this command copies the contents of files as they
1701 By default, this command copies the contents of files as they
1702 exist in the working directory. If invoked with -A/--after, the
1702 exist in the working directory. If invoked with -A/--after, the
1703 operation is recorded, but no copying is performed.
1703 operation is recorded, but no copying is performed.
1704
1704
1705 This command takes effect with the next commit. To undo a copy
1705 This command takes effect with the next commit. To undo a copy
1706 before that, see :hg:`revert`.
1706 before that, see :hg:`revert`.
1707
1707
1708 Returns 0 on success, 1 if errors are encountered.
1708 Returns 0 on success, 1 if errors are encountered.
1709 """
1709 """
1710 wlock = repo.wlock(False)
1710 wlock = repo.wlock(False)
1711 try:
1711 try:
1712 return cmdutil.copy(ui, repo, pats, opts)
1712 return cmdutil.copy(ui, repo, pats, opts)
1713 finally:
1713 finally:
1714 wlock.release()
1714 wlock.release()
1715
1715
1716 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1716 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1717 def debugancestor(ui, repo, *args):
1717 def debugancestor(ui, repo, *args):
1718 """find the ancestor revision of two revisions in a given index"""
1718 """find the ancestor revision of two revisions in a given index"""
1719 if len(args) == 3:
1719 if len(args) == 3:
1720 index, rev1, rev2 = args
1720 index, rev1, rev2 = args
1721 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1721 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1722 lookup = r.lookup
1722 lookup = r.lookup
1723 elif len(args) == 2:
1723 elif len(args) == 2:
1724 if not repo:
1724 if not repo:
1725 raise error.Abort(_("there is no Mercurial repository here "
1725 raise error.Abort(_("there is no Mercurial repository here "
1726 "(.hg not found)"))
1726 "(.hg not found)"))
1727 rev1, rev2 = args
1727 rev1, rev2 = args
1728 r = repo.changelog
1728 r = repo.changelog
1729 lookup = repo.lookup
1729 lookup = repo.lookup
1730 else:
1730 else:
1731 raise error.Abort(_('either two or three arguments required'))
1731 raise error.Abort(_('either two or three arguments required'))
1732 a = r.ancestor(lookup(rev1), lookup(rev2))
1732 a = r.ancestor(lookup(rev1), lookup(rev2))
1733 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1733 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1734
1734
1735 @command('debugbuilddag',
1735 @command('debugbuilddag',
1736 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1736 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1737 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1737 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1738 ('n', 'new-file', None, _('add new file at each rev'))],
1738 ('n', 'new-file', None, _('add new file at each rev'))],
1739 _('[OPTION]... [TEXT]'))
1739 _('[OPTION]... [TEXT]'))
1740 def debugbuilddag(ui, repo, text=None,
1740 def debugbuilddag(ui, repo, text=None,
1741 mergeable_file=False,
1741 mergeable_file=False,
1742 overwritten_file=False,
1742 overwritten_file=False,
1743 new_file=False):
1743 new_file=False):
1744 """builds a repo with a given DAG from scratch in the current empty repo
1744 """builds a repo with a given DAG from scratch in the current empty repo
1745
1745
1746 The description of the DAG is read from stdin if not given on the
1746 The description of the DAG is read from stdin if not given on the
1747 command line.
1747 command line.
1748
1748
1749 Elements:
1749 Elements:
1750
1750
1751 - "+n" is a linear run of n nodes based on the current default parent
1751 - "+n" is a linear run of n nodes based on the current default parent
1752 - "." is a single node based on the current default parent
1752 - "." is a single node based on the current default parent
1753 - "$" resets the default parent to null (implied at the start);
1753 - "$" resets the default parent to null (implied at the start);
1754 otherwise the default parent is always the last node created
1754 otherwise the default parent is always the last node created
1755 - "<p" sets the default parent to the backref p
1755 - "<p" sets the default parent to the backref p
1756 - "*p" is a fork at parent p, which is a backref
1756 - "*p" is a fork at parent p, which is a backref
1757 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1757 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1758 - "/p2" is a merge of the preceding node and p2
1758 - "/p2" is a merge of the preceding node and p2
1759 - ":tag" defines a local tag for the preceding node
1759 - ":tag" defines a local tag for the preceding node
1760 - "@branch" sets the named branch for subsequent nodes
1760 - "@branch" sets the named branch for subsequent nodes
1761 - "#...\\n" is a comment up to the end of the line
1761 - "#...\\n" is a comment up to the end of the line
1762
1762
1763 Whitespace between the above elements is ignored.
1763 Whitespace between the above elements is ignored.
1764
1764
1765 A backref is either
1765 A backref is either
1766
1766
1767 - a number n, which references the node curr-n, where curr is the current
1767 - a number n, which references the node curr-n, where curr is the current
1768 node, or
1768 node, or
1769 - the name of a local tag you placed earlier using ":tag", or
1769 - the name of a local tag you placed earlier using ":tag", or
1770 - empty to denote the default parent.
1770 - empty to denote the default parent.
1771
1771
1772 All string valued-elements are either strictly alphanumeric, or must
1772 All string valued-elements are either strictly alphanumeric, or must
1773 be enclosed in double quotes ("..."), with "\\" as escape character.
1773 be enclosed in double quotes ("..."), with "\\" as escape character.
1774 """
1774 """
1775
1775
1776 if text is None:
1776 if text is None:
1777 ui.status(_("reading DAG from stdin\n"))
1777 ui.status(_("reading DAG from stdin\n"))
1778 text = ui.fin.read()
1778 text = ui.fin.read()
1779
1779
1780 cl = repo.changelog
1780 cl = repo.changelog
1781 if len(cl) > 0:
1781 if len(cl) > 0:
1782 raise error.Abort(_('repository is not empty'))
1782 raise error.Abort(_('repository is not empty'))
1783
1783
1784 # determine number of revs in DAG
1784 # determine number of revs in DAG
1785 total = 0
1785 total = 0
1786 for type, data in dagparser.parsedag(text):
1786 for type, data in dagparser.parsedag(text):
1787 if type == 'n':
1787 if type == 'n':
1788 total += 1
1788 total += 1
1789
1789
1790 if mergeable_file:
1790 if mergeable_file:
1791 linesperrev = 2
1791 linesperrev = 2
1792 # make a file with k lines per rev
1792 # make a file with k lines per rev
1793 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1793 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1794 initialmergedlines.append("")
1794 initialmergedlines.append("")
1795
1795
1796 tags = []
1796 tags = []
1797
1797
1798 lock = tr = None
1798 lock = tr = None
1799 try:
1799 try:
1800 lock = repo.lock()
1800 lock = repo.lock()
1801 tr = repo.transaction("builddag")
1801 tr = repo.transaction("builddag")
1802
1802
1803 at = -1
1803 at = -1
1804 atbranch = 'default'
1804 atbranch = 'default'
1805 nodeids = []
1805 nodeids = []
1806 id = 0
1806 id = 0
1807 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1807 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1808 for type, data in dagparser.parsedag(text):
1808 for type, data in dagparser.parsedag(text):
1809 if type == 'n':
1809 if type == 'n':
1810 ui.note(('node %s\n' % str(data)))
1810 ui.note(('node %s\n' % str(data)))
1811 id, ps = data
1811 id, ps = data
1812
1812
1813 files = []
1813 files = []
1814 fctxs = {}
1814 fctxs = {}
1815
1815
1816 p2 = None
1816 p2 = None
1817 if mergeable_file:
1817 if mergeable_file:
1818 fn = "mf"
1818 fn = "mf"
1819 p1 = repo[ps[0]]
1819 p1 = repo[ps[0]]
1820 if len(ps) > 1:
1820 if len(ps) > 1:
1821 p2 = repo[ps[1]]
1821 p2 = repo[ps[1]]
1822 pa = p1.ancestor(p2)
1822 pa = p1.ancestor(p2)
1823 base, local, other = [x[fn].data() for x in (pa, p1,
1823 base, local, other = [x[fn].data() for x in (pa, p1,
1824 p2)]
1824 p2)]
1825 m3 = simplemerge.Merge3Text(base, local, other)
1825 m3 = simplemerge.Merge3Text(base, local, other)
1826 ml = [l.strip() for l in m3.merge_lines()]
1826 ml = [l.strip() for l in m3.merge_lines()]
1827 ml.append("")
1827 ml.append("")
1828 elif at > 0:
1828 elif at > 0:
1829 ml = p1[fn].data().split("\n")
1829 ml = p1[fn].data().split("\n")
1830 else:
1830 else:
1831 ml = initialmergedlines
1831 ml = initialmergedlines
1832 ml[id * linesperrev] += " r%i" % id
1832 ml[id * linesperrev] += " r%i" % id
1833 mergedtext = "\n".join(ml)
1833 mergedtext = "\n".join(ml)
1834 files.append(fn)
1834 files.append(fn)
1835 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1835 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1836
1836
1837 if overwritten_file:
1837 if overwritten_file:
1838 fn = "of"
1838 fn = "of"
1839 files.append(fn)
1839 files.append(fn)
1840 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1840 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1841
1841
1842 if new_file:
1842 if new_file:
1843 fn = "nf%i" % id
1843 fn = "nf%i" % id
1844 files.append(fn)
1844 files.append(fn)
1845 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1845 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1846 if len(ps) > 1:
1846 if len(ps) > 1:
1847 if not p2:
1847 if not p2:
1848 p2 = repo[ps[1]]
1848 p2 = repo[ps[1]]
1849 for fn in p2:
1849 for fn in p2:
1850 if fn.startswith("nf"):
1850 if fn.startswith("nf"):
1851 files.append(fn)
1851 files.append(fn)
1852 fctxs[fn] = p2[fn]
1852 fctxs[fn] = p2[fn]
1853
1853
1854 def fctxfn(repo, cx, path):
1854 def fctxfn(repo, cx, path):
1855 return fctxs.get(path)
1855 return fctxs.get(path)
1856
1856
1857 if len(ps) == 0 or ps[0] < 0:
1857 if len(ps) == 0 or ps[0] < 0:
1858 pars = [None, None]
1858 pars = [None, None]
1859 elif len(ps) == 1:
1859 elif len(ps) == 1:
1860 pars = [nodeids[ps[0]], None]
1860 pars = [nodeids[ps[0]], None]
1861 else:
1861 else:
1862 pars = [nodeids[p] for p in ps]
1862 pars = [nodeids[p] for p in ps]
1863 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1863 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1864 date=(id, 0),
1864 date=(id, 0),
1865 user="debugbuilddag",
1865 user="debugbuilddag",
1866 extra={'branch': atbranch})
1866 extra={'branch': atbranch})
1867 nodeid = repo.commitctx(cx)
1867 nodeid = repo.commitctx(cx)
1868 nodeids.append(nodeid)
1868 nodeids.append(nodeid)
1869 at = id
1869 at = id
1870 elif type == 'l':
1870 elif type == 'l':
1871 id, name = data
1871 id, name = data
1872 ui.note(('tag %s\n' % name))
1872 ui.note(('tag %s\n' % name))
1873 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1873 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1874 elif type == 'a':
1874 elif type == 'a':
1875 ui.note(('branch %s\n' % data))
1875 ui.note(('branch %s\n' % data))
1876 atbranch = data
1876 atbranch = data
1877 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1877 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1878 tr.close()
1878 tr.close()
1879
1879
1880 if tags:
1880 if tags:
1881 repo.vfs.write("localtags", "".join(tags))
1881 repo.vfs.write("localtags", "".join(tags))
1882 finally:
1882 finally:
1883 ui.progress(_('building'), None)
1883 ui.progress(_('building'), None)
1884 release(tr, lock)
1884 release(tr, lock)
1885
1885
1886 @command('debugbundle',
1886 @command('debugbundle',
1887 [('a', 'all', None, _('show all details'))],
1887 [('a', 'all', None, _('show all details'))],
1888 _('FILE'),
1888 _('FILE'),
1889 norepo=True)
1889 norepo=True)
1890 def debugbundle(ui, bundlepath, all=None, **opts):
1890 def debugbundle(ui, bundlepath, all=None, **opts):
1891 """lists the contents of a bundle"""
1891 """lists the contents of a bundle"""
1892 f = hg.openpath(ui, bundlepath)
1892 f = hg.openpath(ui, bundlepath)
1893 try:
1893 try:
1894 gen = exchange.readbundle(ui, f, bundlepath)
1894 gen = exchange.readbundle(ui, f, bundlepath)
1895 if isinstance(gen, bundle2.unbundle20):
1895 if isinstance(gen, bundle2.unbundle20):
1896 return _debugbundle2(ui, gen, all=all, **opts)
1896 return _debugbundle2(ui, gen, all=all, **opts)
1897 if all:
1897 if all:
1898 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1898 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1899
1899
1900 def showchunks(named):
1900 def showchunks(named):
1901 ui.write("\n%s\n" % named)
1901 ui.write("\n%s\n" % named)
1902 chain = None
1902 chain = None
1903 while True:
1903 while True:
1904 chunkdata = gen.deltachunk(chain)
1904 chunkdata = gen.deltachunk(chain)
1905 if not chunkdata:
1905 if not chunkdata:
1906 break
1906 break
1907 node = chunkdata['node']
1907 node = chunkdata['node']
1908 p1 = chunkdata['p1']
1908 p1 = chunkdata['p1']
1909 p2 = chunkdata['p2']
1909 p2 = chunkdata['p2']
1910 cs = chunkdata['cs']
1910 cs = chunkdata['cs']
1911 deltabase = chunkdata['deltabase']
1911 deltabase = chunkdata['deltabase']
1912 delta = chunkdata['delta']
1912 delta = chunkdata['delta']
1913 ui.write("%s %s %s %s %s %s\n" %
1913 ui.write("%s %s %s %s %s %s\n" %
1914 (hex(node), hex(p1), hex(p2),
1914 (hex(node), hex(p1), hex(p2),
1915 hex(cs), hex(deltabase), len(delta)))
1915 hex(cs), hex(deltabase), len(delta)))
1916 chain = node
1916 chain = node
1917
1917
1918 chunkdata = gen.changelogheader()
1918 chunkdata = gen.changelogheader()
1919 showchunks("changelog")
1919 showchunks("changelog")
1920 chunkdata = gen.manifestheader()
1920 chunkdata = gen.manifestheader()
1921 showchunks("manifest")
1921 showchunks("manifest")
1922 while True:
1922 while True:
1923 chunkdata = gen.filelogheader()
1923 chunkdata = gen.filelogheader()
1924 if not chunkdata:
1924 if not chunkdata:
1925 break
1925 break
1926 fname = chunkdata['filename']
1926 fname = chunkdata['filename']
1927 showchunks(fname)
1927 showchunks(fname)
1928 else:
1928 else:
1929 if isinstance(gen, bundle2.unbundle20):
1929 if isinstance(gen, bundle2.unbundle20):
1930 raise error.Abort(_('use debugbundle2 for this file'))
1930 raise error.Abort(_('use debugbundle2 for this file'))
1931 chunkdata = gen.changelogheader()
1931 chunkdata = gen.changelogheader()
1932 chain = None
1932 chain = None
1933 while True:
1933 while True:
1934 chunkdata = gen.deltachunk(chain)
1934 chunkdata = gen.deltachunk(chain)
1935 if not chunkdata:
1935 if not chunkdata:
1936 break
1936 break
1937 node = chunkdata['node']
1937 node = chunkdata['node']
1938 ui.write("%s\n" % hex(node))
1938 ui.write("%s\n" % hex(node))
1939 chain = node
1939 chain = node
1940 finally:
1940 finally:
1941 f.close()
1941 f.close()
1942
1942
1943 def _debugbundle2(ui, gen, **opts):
1943 def _debugbundle2(ui, gen, **opts):
1944 """lists the contents of a bundle2"""
1944 """lists the contents of a bundle2"""
1945 if not isinstance(gen, bundle2.unbundle20):
1945 if not isinstance(gen, bundle2.unbundle20):
1946 raise error.Abort(_('not a bundle2 file'))
1946 raise error.Abort(_('not a bundle2 file'))
1947 ui.write(('Stream params: %s\n' % repr(gen.params)))
1947 ui.write(('Stream params: %s\n' % repr(gen.params)))
1948 for part in gen.iterparts():
1948 for part in gen.iterparts():
1949 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1949 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1950 if part.type == 'changegroup':
1950 if part.type == 'changegroup':
1951 version = part.params.get('version', '01')
1951 version = part.params.get('version', '01')
1952 cg = changegroup.packermap[version][1](part, 'UN')
1952 cg = changegroup.packermap[version][1](part, 'UN')
1953 chunkdata = cg.changelogheader()
1953 chunkdata = cg.changelogheader()
1954 chain = None
1954 chain = None
1955 while True:
1955 while True:
1956 chunkdata = cg.deltachunk(chain)
1956 chunkdata = cg.deltachunk(chain)
1957 if not chunkdata:
1957 if not chunkdata:
1958 break
1958 break
1959 node = chunkdata['node']
1959 node = chunkdata['node']
1960 ui.write(" %s\n" % hex(node))
1960 ui.write(" %s\n" % hex(node))
1961 chain = node
1961 chain = node
1962
1962
1963 @command('debugcheckstate', [], '')
1963 @command('debugcheckstate', [], '')
1964 def debugcheckstate(ui, repo):
1964 def debugcheckstate(ui, repo):
1965 """validate the correctness of the current dirstate"""
1965 """validate the correctness of the current dirstate"""
1966 parent1, parent2 = repo.dirstate.parents()
1966 parent1, parent2 = repo.dirstate.parents()
1967 m1 = repo[parent1].manifest()
1967 m1 = repo[parent1].manifest()
1968 m2 = repo[parent2].manifest()
1968 m2 = repo[parent2].manifest()
1969 errors = 0
1969 errors = 0
1970 for f in repo.dirstate:
1970 for f in repo.dirstate:
1971 state = repo.dirstate[f]
1971 state = repo.dirstate[f]
1972 if state in "nr" and f not in m1:
1972 if state in "nr" and f not in m1:
1973 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1973 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1974 errors += 1
1974 errors += 1
1975 if state in "a" and f in m1:
1975 if state in "a" and f in m1:
1976 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1976 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1977 errors += 1
1977 errors += 1
1978 if state in "m" and f not in m1 and f not in m2:
1978 if state in "m" and f not in m1 and f not in m2:
1979 ui.warn(_("%s in state %s, but not in either manifest\n") %
1979 ui.warn(_("%s in state %s, but not in either manifest\n") %
1980 (f, state))
1980 (f, state))
1981 errors += 1
1981 errors += 1
1982 for f in m1:
1982 for f in m1:
1983 state = repo.dirstate[f]
1983 state = repo.dirstate[f]
1984 if state not in "nrm":
1984 if state not in "nrm":
1985 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1985 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1986 errors += 1
1986 errors += 1
1987 if errors:
1987 if errors:
1988 error = _(".hg/dirstate inconsistent with current parent's manifest")
1988 error = _(".hg/dirstate inconsistent with current parent's manifest")
1989 raise error.Abort(error)
1989 raise error.Abort(error)
1990
1990
1991 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1991 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1992 def debugcommands(ui, cmd='', *args):
1992 def debugcommands(ui, cmd='', *args):
1993 """list all available commands and options"""
1993 """list all available commands and options"""
1994 for cmd, vals in sorted(table.iteritems()):
1994 for cmd, vals in sorted(table.iteritems()):
1995 cmd = cmd.split('|')[0].strip('^')
1995 cmd = cmd.split('|')[0].strip('^')
1996 opts = ', '.join([i[1] for i in vals[1]])
1996 opts = ', '.join([i[1] for i in vals[1]])
1997 ui.write('%s: %s\n' % (cmd, opts))
1997 ui.write('%s: %s\n' % (cmd, opts))
1998
1998
1999 @command('debugcomplete',
1999 @command('debugcomplete',
2000 [('o', 'options', None, _('show the command options'))],
2000 [('o', 'options', None, _('show the command options'))],
2001 _('[-o] CMD'),
2001 _('[-o] CMD'),
2002 norepo=True)
2002 norepo=True)
2003 def debugcomplete(ui, cmd='', **opts):
2003 def debugcomplete(ui, cmd='', **opts):
2004 """returns the completion list associated with the given command"""
2004 """returns the completion list associated with the given command"""
2005
2005
2006 if opts.get('options'):
2006 if opts.get('options'):
2007 options = []
2007 options = []
2008 otables = [globalopts]
2008 otables = [globalopts]
2009 if cmd:
2009 if cmd:
2010 aliases, entry = cmdutil.findcmd(cmd, table, False)
2010 aliases, entry = cmdutil.findcmd(cmd, table, False)
2011 otables.append(entry[1])
2011 otables.append(entry[1])
2012 for t in otables:
2012 for t in otables:
2013 for o in t:
2013 for o in t:
2014 if "(DEPRECATED)" in o[3]:
2014 if "(DEPRECATED)" in o[3]:
2015 continue
2015 continue
2016 if o[0]:
2016 if o[0]:
2017 options.append('-%s' % o[0])
2017 options.append('-%s' % o[0])
2018 options.append('--%s' % o[1])
2018 options.append('--%s' % o[1])
2019 ui.write("%s\n" % "\n".join(options))
2019 ui.write("%s\n" % "\n".join(options))
2020 return
2020 return
2021
2021
2022 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2022 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2023 if ui.verbose:
2023 if ui.verbose:
2024 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2024 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2025 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2025 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2026
2026
2027 @command('debugdag',
2027 @command('debugdag',
2028 [('t', 'tags', None, _('use tags as labels')),
2028 [('t', 'tags', None, _('use tags as labels')),
2029 ('b', 'branches', None, _('annotate with branch names')),
2029 ('b', 'branches', None, _('annotate with branch names')),
2030 ('', 'dots', None, _('use dots for runs')),
2030 ('', 'dots', None, _('use dots for runs')),
2031 ('s', 'spaces', None, _('separate elements by spaces'))],
2031 ('s', 'spaces', None, _('separate elements by spaces'))],
2032 _('[OPTION]... [FILE [REV]...]'),
2032 _('[OPTION]... [FILE [REV]...]'),
2033 optionalrepo=True)
2033 optionalrepo=True)
2034 def debugdag(ui, repo, file_=None, *revs, **opts):
2034 def debugdag(ui, repo, file_=None, *revs, **opts):
2035 """format the changelog or an index DAG as a concise textual description
2035 """format the changelog or an index DAG as a concise textual description
2036
2036
2037 If you pass a revlog index, the revlog's DAG is emitted. If you list
2037 If you pass a revlog index, the revlog's DAG is emitted. If you list
2038 revision numbers, they get labeled in the output as rN.
2038 revision numbers, they get labeled in the output as rN.
2039
2039
2040 Otherwise, the changelog DAG of the current repo is emitted.
2040 Otherwise, the changelog DAG of the current repo is emitted.
2041 """
2041 """
2042 spaces = opts.get('spaces')
2042 spaces = opts.get('spaces')
2043 dots = opts.get('dots')
2043 dots = opts.get('dots')
2044 if file_:
2044 if file_:
2045 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2045 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2046 revs = set((int(r) for r in revs))
2046 revs = set((int(r) for r in revs))
2047 def events():
2047 def events():
2048 for r in rlog:
2048 for r in rlog:
2049 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2049 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2050 if p != -1))
2050 if p != -1))
2051 if r in revs:
2051 if r in revs:
2052 yield 'l', (r, "r%i" % r)
2052 yield 'l', (r, "r%i" % r)
2053 elif repo:
2053 elif repo:
2054 cl = repo.changelog
2054 cl = repo.changelog
2055 tags = opts.get('tags')
2055 tags = opts.get('tags')
2056 branches = opts.get('branches')
2056 branches = opts.get('branches')
2057 if tags:
2057 if tags:
2058 labels = {}
2058 labels = {}
2059 for l, n in repo.tags().items():
2059 for l, n in repo.tags().items():
2060 labels.setdefault(cl.rev(n), []).append(l)
2060 labels.setdefault(cl.rev(n), []).append(l)
2061 def events():
2061 def events():
2062 b = "default"
2062 b = "default"
2063 for r in cl:
2063 for r in cl:
2064 if branches:
2064 if branches:
2065 newb = cl.read(cl.node(r))[5]['branch']
2065 newb = cl.read(cl.node(r))[5]['branch']
2066 if newb != b:
2066 if newb != b:
2067 yield 'a', newb
2067 yield 'a', newb
2068 b = newb
2068 b = newb
2069 yield 'n', (r, list(p for p in cl.parentrevs(r)
2069 yield 'n', (r, list(p for p in cl.parentrevs(r)
2070 if p != -1))
2070 if p != -1))
2071 if tags:
2071 if tags:
2072 ls = labels.get(r)
2072 ls = labels.get(r)
2073 if ls:
2073 if ls:
2074 for l in ls:
2074 for l in ls:
2075 yield 'l', (r, l)
2075 yield 'l', (r, l)
2076 else:
2076 else:
2077 raise error.Abort(_('need repo for changelog dag'))
2077 raise error.Abort(_('need repo for changelog dag'))
2078
2078
2079 for line in dagparser.dagtextlines(events(),
2079 for line in dagparser.dagtextlines(events(),
2080 addspaces=spaces,
2080 addspaces=spaces,
2081 wraplabels=True,
2081 wraplabels=True,
2082 wrapannotations=True,
2082 wrapannotations=True,
2083 wrapnonlinear=dots,
2083 wrapnonlinear=dots,
2084 usedots=dots,
2084 usedots=dots,
2085 maxlinewidth=70):
2085 maxlinewidth=70):
2086 ui.write(line)
2086 ui.write(line)
2087 ui.write("\n")
2087 ui.write("\n")
2088
2088
2089 @command('debugdata',
2089 @command('debugdata',
2090 [('c', 'changelog', False, _('open changelog')),
2090 [('c', 'changelog', False, _('open changelog')),
2091 ('m', 'manifest', False, _('open manifest')),
2091 ('m', 'manifest', False, _('open manifest')),
2092 ('', 'dir', False, _('open directory manifest'))],
2092 ('', 'dir', False, _('open directory manifest'))],
2093 _('-c|-m|FILE REV'))
2093 _('-c|-m|FILE REV'))
2094 def debugdata(ui, repo, file_, rev=None, **opts):
2094 def debugdata(ui, repo, file_, rev=None, **opts):
2095 """dump the contents of a data file revision"""
2095 """dump the contents of a data file revision"""
2096 if opts.get('changelog') or opts.get('manifest'):
2096 if opts.get('changelog') or opts.get('manifest'):
2097 file_, rev = None, file_
2097 file_, rev = None, file_
2098 elif rev is None:
2098 elif rev is None:
2099 raise error.CommandError('debugdata', _('invalid arguments'))
2099 raise error.CommandError('debugdata', _('invalid arguments'))
2100 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2100 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2101 try:
2101 try:
2102 ui.write(r.revision(r.lookup(rev)))
2102 ui.write(r.revision(r.lookup(rev)))
2103 except KeyError:
2103 except KeyError:
2104 raise error.Abort(_('invalid revision identifier %s') % rev)
2104 raise error.Abort(_('invalid revision identifier %s') % rev)
2105
2105
2106 @command('debugdate',
2106 @command('debugdate',
2107 [('e', 'extended', None, _('try extended date formats'))],
2107 [('e', 'extended', None, _('try extended date formats'))],
2108 _('[-e] DATE [RANGE]'),
2108 _('[-e] DATE [RANGE]'),
2109 norepo=True, optionalrepo=True)
2109 norepo=True, optionalrepo=True)
2110 def debugdate(ui, date, range=None, **opts):
2110 def debugdate(ui, date, range=None, **opts):
2111 """parse and display a date"""
2111 """parse and display a date"""
2112 if opts["extended"]:
2112 if opts["extended"]:
2113 d = util.parsedate(date, util.extendeddateformats)
2113 d = util.parsedate(date, util.extendeddateformats)
2114 else:
2114 else:
2115 d = util.parsedate(date)
2115 d = util.parsedate(date)
2116 ui.write(("internal: %s %s\n") % d)
2116 ui.write(("internal: %s %s\n") % d)
2117 ui.write(("standard: %s\n") % util.datestr(d))
2117 ui.write(("standard: %s\n") % util.datestr(d))
2118 if range:
2118 if range:
2119 m = util.matchdate(range)
2119 m = util.matchdate(range)
2120 ui.write(("match: %s\n") % m(d[0]))
2120 ui.write(("match: %s\n") % m(d[0]))
2121
2121
2122 @command('debugdiscovery',
2122 @command('debugdiscovery',
2123 [('', 'old', None, _('use old-style discovery')),
2123 [('', 'old', None, _('use old-style discovery')),
2124 ('', 'nonheads', None,
2124 ('', 'nonheads', None,
2125 _('use old-style discovery with non-heads included')),
2125 _('use old-style discovery with non-heads included')),
2126 ] + remoteopts,
2126 ] + remoteopts,
2127 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2127 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2128 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2128 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2129 """runs the changeset discovery protocol in isolation"""
2129 """runs the changeset discovery protocol in isolation"""
2130 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2130 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2131 opts.get('branch'))
2131 opts.get('branch'))
2132 remote = hg.peer(repo, opts, remoteurl)
2132 remote = hg.peer(repo, opts, remoteurl)
2133 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2133 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2134
2134
2135 # make sure tests are repeatable
2135 # make sure tests are repeatable
2136 random.seed(12323)
2136 random.seed(12323)
2137
2137
2138 def doit(localheads, remoteheads, remote=remote):
2138 def doit(localheads, remoteheads, remote=remote):
2139 if opts.get('old'):
2139 if opts.get('old'):
2140 if localheads:
2140 if localheads:
2141 raise error.Abort('cannot use localheads with old style '
2141 raise error.Abort('cannot use localheads with old style '
2142 'discovery')
2142 'discovery')
2143 if not util.safehasattr(remote, 'branches'):
2143 if not util.safehasattr(remote, 'branches'):
2144 # enable in-client legacy support
2144 # enable in-client legacy support
2145 remote = localrepo.locallegacypeer(remote.local())
2145 remote = localrepo.locallegacypeer(remote.local())
2146 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2146 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2147 force=True)
2147 force=True)
2148 common = set(common)
2148 common = set(common)
2149 if not opts.get('nonheads'):
2149 if not opts.get('nonheads'):
2150 ui.write(("unpruned common: %s\n") %
2150 ui.write(("unpruned common: %s\n") %
2151 " ".join(sorted(short(n) for n in common)))
2151 " ".join(sorted(short(n) for n in common)))
2152 dag = dagutil.revlogdag(repo.changelog)
2152 dag = dagutil.revlogdag(repo.changelog)
2153 all = dag.ancestorset(dag.internalizeall(common))
2153 all = dag.ancestorset(dag.internalizeall(common))
2154 common = dag.externalizeall(dag.headsetofconnecteds(all))
2154 common = dag.externalizeall(dag.headsetofconnecteds(all))
2155 else:
2155 else:
2156 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2156 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2157 common = set(common)
2157 common = set(common)
2158 rheads = set(hds)
2158 rheads = set(hds)
2159 lheads = set(repo.heads())
2159 lheads = set(repo.heads())
2160 ui.write(("common heads: %s\n") %
2160 ui.write(("common heads: %s\n") %
2161 " ".join(sorted(short(n) for n in common)))
2161 " ".join(sorted(short(n) for n in common)))
2162 if lheads <= common:
2162 if lheads <= common:
2163 ui.write(("local is subset\n"))
2163 ui.write(("local is subset\n"))
2164 elif rheads <= common:
2164 elif rheads <= common:
2165 ui.write(("remote is subset\n"))
2165 ui.write(("remote is subset\n"))
2166
2166
2167 serverlogs = opts.get('serverlog')
2167 serverlogs = opts.get('serverlog')
2168 if serverlogs:
2168 if serverlogs:
2169 for filename in serverlogs:
2169 for filename in serverlogs:
2170 logfile = open(filename, 'r')
2170 logfile = open(filename, 'r')
2171 try:
2171 try:
2172 line = logfile.readline()
2172 line = logfile.readline()
2173 while line:
2173 while line:
2174 parts = line.strip().split(';')
2174 parts = line.strip().split(';')
2175 op = parts[1]
2175 op = parts[1]
2176 if op == 'cg':
2176 if op == 'cg':
2177 pass
2177 pass
2178 elif op == 'cgss':
2178 elif op == 'cgss':
2179 doit(parts[2].split(' '), parts[3].split(' '))
2179 doit(parts[2].split(' '), parts[3].split(' '))
2180 elif op == 'unb':
2180 elif op == 'unb':
2181 doit(parts[3].split(' '), parts[2].split(' '))
2181 doit(parts[3].split(' '), parts[2].split(' '))
2182 line = logfile.readline()
2182 line = logfile.readline()
2183 finally:
2183 finally:
2184 logfile.close()
2184 logfile.close()
2185
2185
2186 else:
2186 else:
2187 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2187 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2188 opts.get('remote_head'))
2188 opts.get('remote_head'))
2189 localrevs = opts.get('local_head')
2189 localrevs = opts.get('local_head')
2190 doit(localrevs, remoterevs)
2190 doit(localrevs, remoterevs)
2191
2191
2192 @command('debugextensions', formatteropts, [], norepo=True)
2192 @command('debugextensions', formatteropts, [], norepo=True)
2193 def debugextensions(ui, **opts):
2193 def debugextensions(ui, **opts):
2194 '''show information about active extensions'''
2194 '''show information about active extensions'''
2195 exts = extensions.extensions(ui)
2195 exts = extensions.extensions(ui)
2196 fm = ui.formatter('debugextensions', opts)
2196 fm = ui.formatter('debugextensions', opts)
2197 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2197 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2198 extsource = extmod.__file__
2198 extsource = extmod.__file__
2199 exttestedwith = getattr(extmod, 'testedwith', None)
2199 exttestedwith = getattr(extmod, 'testedwith', None)
2200 if exttestedwith is not None:
2200 if exttestedwith is not None:
2201 exttestedwith = exttestedwith.split()
2201 exttestedwith = exttestedwith.split()
2202 extbuglink = getattr(extmod, 'buglink', None)
2202 extbuglink = getattr(extmod, 'buglink', None)
2203
2203
2204 fm.startitem()
2204 fm.startitem()
2205
2205
2206 if ui.quiet or ui.verbose:
2206 if ui.quiet or ui.verbose:
2207 fm.write('name', '%s\n', extname)
2207 fm.write('name', '%s\n', extname)
2208 else:
2208 else:
2209 fm.write('name', '%s', extname)
2209 fm.write('name', '%s', extname)
2210 if not exttestedwith:
2210 if not exttestedwith:
2211 fm.plain(_(' (untested!)\n'))
2211 fm.plain(_(' (untested!)\n'))
2212 else:
2212 else:
2213 if exttestedwith == ['internal'] or \
2213 if exttestedwith == ['internal'] or \
2214 util.version() in exttestedwith:
2214 util.version() in exttestedwith:
2215 fm.plain('\n')
2215 fm.plain('\n')
2216 else:
2216 else:
2217 lasttestedversion = exttestedwith[-1]
2217 lasttestedversion = exttestedwith[-1]
2218 fm.plain(' (%s!)\n' % lasttestedversion)
2218 fm.plain(' (%s!)\n' % lasttestedversion)
2219
2219
2220 fm.condwrite(ui.verbose and extsource, 'source',
2220 fm.condwrite(ui.verbose and extsource, 'source',
2221 _(' location: %s\n'), extsource or "")
2221 _(' location: %s\n'), extsource or "")
2222
2222
2223 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2223 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2224 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2224 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2225
2225
2226 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2226 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2227 _(' bug reporting: %s\n'), extbuglink or "")
2227 _(' bug reporting: %s\n'), extbuglink or "")
2228
2228
2229 fm.end()
2229 fm.end()
2230
2230
2231 @command('debugfileset',
2231 @command('debugfileset',
2232 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2232 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2233 _('[-r REV] FILESPEC'))
2233 _('[-r REV] FILESPEC'))
2234 def debugfileset(ui, repo, expr, **opts):
2234 def debugfileset(ui, repo, expr, **opts):
2235 '''parse and apply a fileset specification'''
2235 '''parse and apply a fileset specification'''
2236 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2236 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2237 if ui.verbose:
2237 if ui.verbose:
2238 tree = fileset.parse(expr)
2238 tree = fileset.parse(expr)
2239 ui.note(fileset.prettyformat(tree), "\n")
2239 ui.note(fileset.prettyformat(tree), "\n")
2240
2240
2241 for f in ctx.getfileset(expr):
2241 for f in ctx.getfileset(expr):
2242 ui.write("%s\n" % f)
2242 ui.write("%s\n" % f)
2243
2243
2244 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2244 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2245 def debugfsinfo(ui, path="."):
2245 def debugfsinfo(ui, path="."):
2246 """show information detected about current filesystem"""
2246 """show information detected about current filesystem"""
2247 util.writefile('.debugfsinfo', '')
2247 util.writefile('.debugfsinfo', '')
2248 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2248 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2249 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2249 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2250 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2250 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2251 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2251 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2252 and 'yes' or 'no'))
2252 and 'yes' or 'no'))
2253 os.unlink('.debugfsinfo')
2253 os.unlink('.debugfsinfo')
2254
2254
2255 @command('debuggetbundle',
2255 @command('debuggetbundle',
2256 [('H', 'head', [], _('id of head node'), _('ID')),
2256 [('H', 'head', [], _('id of head node'), _('ID')),
2257 ('C', 'common', [], _('id of common node'), _('ID')),
2257 ('C', 'common', [], _('id of common node'), _('ID')),
2258 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2258 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2259 _('REPO FILE [-H|-C ID]...'),
2259 _('REPO FILE [-H|-C ID]...'),
2260 norepo=True)
2260 norepo=True)
2261 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2261 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2262 """retrieves a bundle from a repo
2262 """retrieves a bundle from a repo
2263
2263
2264 Every ID must be a full-length hex node id string. Saves the bundle to the
2264 Every ID must be a full-length hex node id string. Saves the bundle to the
2265 given file.
2265 given file.
2266 """
2266 """
2267 repo = hg.peer(ui, opts, repopath)
2267 repo = hg.peer(ui, opts, repopath)
2268 if not repo.capable('getbundle'):
2268 if not repo.capable('getbundle'):
2269 raise error.Abort("getbundle() not supported by target repository")
2269 raise error.Abort("getbundle() not supported by target repository")
2270 args = {}
2270 args = {}
2271 if common:
2271 if common:
2272 args['common'] = [bin(s) for s in common]
2272 args['common'] = [bin(s) for s in common]
2273 if head:
2273 if head:
2274 args['heads'] = [bin(s) for s in head]
2274 args['heads'] = [bin(s) for s in head]
2275 # TODO: get desired bundlecaps from command line.
2275 # TODO: get desired bundlecaps from command line.
2276 args['bundlecaps'] = None
2276 args['bundlecaps'] = None
2277 bundle = repo.getbundle('debug', **args)
2277 bundle = repo.getbundle('debug', **args)
2278
2278
2279 bundletype = opts.get('type', 'bzip2').lower()
2279 bundletype = opts.get('type', 'bzip2').lower()
2280 btypes = {'none': 'HG10UN',
2280 btypes = {'none': 'HG10UN',
2281 'bzip2': 'HG10BZ',
2281 'bzip2': 'HG10BZ',
2282 'gzip': 'HG10GZ',
2282 'gzip': 'HG10GZ',
2283 'bundle2': 'HG20'}
2283 'bundle2': 'HG20'}
2284 bundletype = btypes.get(bundletype)
2284 bundletype = btypes.get(bundletype)
2285 if bundletype not in changegroup.bundletypes:
2285 if bundletype not in changegroup.bundletypes:
2286 raise error.Abort(_('unknown bundle type specified with --type'))
2286 raise error.Abort(_('unknown bundle type specified with --type'))
2287 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2287 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2288
2288
2289 @command('debugignore', [], '')
2289 @command('debugignore', [], '')
2290 def debugignore(ui, repo, *values, **opts):
2290 def debugignore(ui, repo, *values, **opts):
2291 """display the combined ignore pattern"""
2291 """display the combined ignore pattern"""
2292 ignore = repo.dirstate._ignore
2292 ignore = repo.dirstate._ignore
2293 includepat = getattr(ignore, 'includepat', None)
2293 includepat = getattr(ignore, 'includepat', None)
2294 if includepat is not None:
2294 if includepat is not None:
2295 ui.write("%s\n" % includepat)
2295 ui.write("%s\n" % includepat)
2296 else:
2296 else:
2297 raise error.Abort(_("no ignore patterns found"))
2297 raise error.Abort(_("no ignore patterns found"))
2298
2298
2299 @command('debugindex',
2299 @command('debugindex',
2300 [('c', 'changelog', False, _('open changelog')),
2300 [('c', 'changelog', False, _('open changelog')),
2301 ('m', 'manifest', False, _('open manifest')),
2301 ('m', 'manifest', False, _('open manifest')),
2302 ('', 'dir', False, _('open directory manifest')),
2302 ('', 'dir', False, _('open directory manifest')),
2303 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2303 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2304 _('[-f FORMAT] -c|-m|FILE'),
2304 _('[-f FORMAT] -c|-m|FILE'),
2305 optionalrepo=True)
2305 optionalrepo=True)
2306 def debugindex(ui, repo, file_=None, **opts):
2306 def debugindex(ui, repo, file_=None, **opts):
2307 """dump the contents of an index file"""
2307 """dump the contents of an index file"""
2308 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2308 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2309 format = opts.get('format', 0)
2309 format = opts.get('format', 0)
2310 if format not in (0, 1):
2310 if format not in (0, 1):
2311 raise error.Abort(_("unknown format %d") % format)
2311 raise error.Abort(_("unknown format %d") % format)
2312
2312
2313 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2313 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2314 if generaldelta:
2314 if generaldelta:
2315 basehdr = ' delta'
2315 basehdr = ' delta'
2316 else:
2316 else:
2317 basehdr = ' base'
2317 basehdr = ' base'
2318
2318
2319 if ui.debugflag:
2319 if ui.debugflag:
2320 shortfn = hex
2320 shortfn = hex
2321 else:
2321 else:
2322 shortfn = short
2322 shortfn = short
2323
2323
2324 # There might not be anything in r, so have a sane default
2324 # There might not be anything in r, so have a sane default
2325 idlen = 12
2325 idlen = 12
2326 for i in r:
2326 for i in r:
2327 idlen = len(shortfn(r.node(i)))
2327 idlen = len(shortfn(r.node(i)))
2328 break
2328 break
2329
2329
2330 if format == 0:
2330 if format == 0:
2331 ui.write(" rev offset length " + basehdr + " linkrev"
2331 ui.write(" rev offset length " + basehdr + " linkrev"
2332 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2332 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2333 elif format == 1:
2333 elif format == 1:
2334 ui.write(" rev flag offset length"
2334 ui.write(" rev flag offset length"
2335 " size " + basehdr + " link p1 p2"
2335 " size " + basehdr + " link p1 p2"
2336 " %s\n" % "nodeid".rjust(idlen))
2336 " %s\n" % "nodeid".rjust(idlen))
2337
2337
2338 for i in r:
2338 for i in r:
2339 node = r.node(i)
2339 node = r.node(i)
2340 if generaldelta:
2340 if generaldelta:
2341 base = r.deltaparent(i)
2341 base = r.deltaparent(i)
2342 else:
2342 else:
2343 base = r.chainbase(i)
2343 base = r.chainbase(i)
2344 if format == 0:
2344 if format == 0:
2345 try:
2345 try:
2346 pp = r.parents(node)
2346 pp = r.parents(node)
2347 except Exception:
2347 except Exception:
2348 pp = [nullid, nullid]
2348 pp = [nullid, nullid]
2349 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2349 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2350 i, r.start(i), r.length(i), base, r.linkrev(i),
2350 i, r.start(i), r.length(i), base, r.linkrev(i),
2351 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2351 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2352 elif format == 1:
2352 elif format == 1:
2353 pr = r.parentrevs(i)
2353 pr = r.parentrevs(i)
2354 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2354 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2355 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2355 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2356 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2356 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2357
2357
2358 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2358 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2359 def debugindexdot(ui, repo, file_):
2359 def debugindexdot(ui, repo, file_):
2360 """dump an index DAG as a graphviz dot file"""
2360 """dump an index DAG as a graphviz dot file"""
2361 r = None
2361 r = None
2362 if repo:
2362 if repo:
2363 filelog = repo.file(file_)
2363 filelog = repo.file(file_)
2364 if len(filelog):
2364 if len(filelog):
2365 r = filelog
2365 r = filelog
2366 if not r:
2366 if not r:
2367 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2367 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2368 ui.write(("digraph G {\n"))
2368 ui.write(("digraph G {\n"))
2369 for i in r:
2369 for i in r:
2370 node = r.node(i)
2370 node = r.node(i)
2371 pp = r.parents(node)
2371 pp = r.parents(node)
2372 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2372 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2373 if pp[1] != nullid:
2373 if pp[1] != nullid:
2374 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2374 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2375 ui.write("}\n")
2375 ui.write("}\n")
2376
2376
2377 @command('debuginstall', [], '', norepo=True)
2377 @command('debuginstall', [], '', norepo=True)
2378 def debuginstall(ui):
2378 def debuginstall(ui):
2379 '''test Mercurial installation
2379 '''test Mercurial installation
2380
2380
2381 Returns 0 on success.
2381 Returns 0 on success.
2382 '''
2382 '''
2383
2383
2384 def writetemp(contents):
2384 def writetemp(contents):
2385 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2385 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2386 f = os.fdopen(fd, "wb")
2386 f = os.fdopen(fd, "wb")
2387 f.write(contents)
2387 f.write(contents)
2388 f.close()
2388 f.close()
2389 return name
2389 return name
2390
2390
2391 problems = 0
2391 problems = 0
2392
2392
2393 # encoding
2393 # encoding
2394 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2394 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2395 try:
2395 try:
2396 encoding.fromlocal("test")
2396 encoding.fromlocal("test")
2397 except error.Abort as inst:
2397 except error.Abort as inst:
2398 ui.write(" %s\n" % inst)
2398 ui.write(" %s\n" % inst)
2399 ui.write(_(" (check that your locale is properly set)\n"))
2399 ui.write(_(" (check that your locale is properly set)\n"))
2400 problems += 1
2400 problems += 1
2401
2401
2402 # Python
2402 # Python
2403 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2403 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2404 ui.status(_("checking Python version (%s)\n")
2404 ui.status(_("checking Python version (%s)\n")
2405 % ("%s.%s.%s" % sys.version_info[:3]))
2405 % ("%s.%s.%s" % sys.version_info[:3]))
2406 ui.status(_("checking Python lib (%s)...\n")
2406 ui.status(_("checking Python lib (%s)...\n")
2407 % os.path.dirname(os.__file__))
2407 % os.path.dirname(os.__file__))
2408
2408
2409 # compiled modules
2409 # compiled modules
2410 ui.status(_("checking installed modules (%s)...\n")
2410 ui.status(_("checking installed modules (%s)...\n")
2411 % os.path.dirname(__file__))
2411 % os.path.dirname(__file__))
2412 try:
2412 try:
2413 import bdiff, mpatch, base85, osutil
2413 import bdiff, mpatch, base85, osutil
2414 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2414 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2415 except Exception as inst:
2415 except Exception as inst:
2416 ui.write(" %s\n" % inst)
2416 ui.write(" %s\n" % inst)
2417 ui.write(_(" One or more extensions could not be found"))
2417 ui.write(_(" One or more extensions could not be found"))
2418 ui.write(_(" (check that you compiled the extensions)\n"))
2418 ui.write(_(" (check that you compiled the extensions)\n"))
2419 problems += 1
2419 problems += 1
2420
2420
2421 # templates
2421 # templates
2422 import templater
2422 import templater
2423 p = templater.templatepaths()
2423 p = templater.templatepaths()
2424 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2424 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2425 if p:
2425 if p:
2426 m = templater.templatepath("map-cmdline.default")
2426 m = templater.templatepath("map-cmdline.default")
2427 if m:
2427 if m:
2428 # template found, check if it is working
2428 # template found, check if it is working
2429 try:
2429 try:
2430 templater.templater(m)
2430 templater.templater(m)
2431 except Exception as inst:
2431 except Exception as inst:
2432 ui.write(" %s\n" % inst)
2432 ui.write(" %s\n" % inst)
2433 p = None
2433 p = None
2434 else:
2434 else:
2435 ui.write(_(" template 'default' not found\n"))
2435 ui.write(_(" template 'default' not found\n"))
2436 p = None
2436 p = None
2437 else:
2437 else:
2438 ui.write(_(" no template directories found\n"))
2438 ui.write(_(" no template directories found\n"))
2439 if not p:
2439 if not p:
2440 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2440 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2441 problems += 1
2441 problems += 1
2442
2442
2443 # editor
2443 # editor
2444 ui.status(_("checking commit editor...\n"))
2444 ui.status(_("checking commit editor...\n"))
2445 editor = ui.geteditor()
2445 editor = ui.geteditor()
2446 editor = util.expandpath(editor)
2446 editor = util.expandpath(editor)
2447 cmdpath = util.findexe(shlex.split(editor)[0])
2447 cmdpath = util.findexe(shlex.split(editor)[0])
2448 if not cmdpath:
2448 if not cmdpath:
2449 if editor == 'vi':
2449 if editor == 'vi':
2450 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2450 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2451 ui.write(_(" (specify a commit editor in your configuration"
2451 ui.write(_(" (specify a commit editor in your configuration"
2452 " file)\n"))
2452 " file)\n"))
2453 else:
2453 else:
2454 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2454 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2455 ui.write(_(" (specify a commit editor in your configuration"
2455 ui.write(_(" (specify a commit editor in your configuration"
2456 " file)\n"))
2456 " file)\n"))
2457 problems += 1
2457 problems += 1
2458
2458
2459 # check username
2459 # check username
2460 ui.status(_("checking username...\n"))
2460 ui.status(_("checking username...\n"))
2461 try:
2461 try:
2462 ui.username()
2462 ui.username()
2463 except error.Abort as e:
2463 except error.Abort as e:
2464 ui.write(" %s\n" % e)
2464 ui.write(" %s\n" % e)
2465 ui.write(_(" (specify a username in your configuration file)\n"))
2465 ui.write(_(" (specify a username in your configuration file)\n"))
2466 problems += 1
2466 problems += 1
2467
2467
2468 if not problems:
2468 if not problems:
2469 ui.status(_("no problems detected\n"))
2469 ui.status(_("no problems detected\n"))
2470 else:
2470 else:
2471 ui.write(_("%s problems detected,"
2471 ui.write(_("%s problems detected,"
2472 " please check your install!\n") % problems)
2472 " please check your install!\n") % problems)
2473
2473
2474 return problems
2474 return problems
2475
2475
2476 @command('debugknown', [], _('REPO ID...'), norepo=True)
2476 @command('debugknown', [], _('REPO ID...'), norepo=True)
2477 def debugknown(ui, repopath, *ids, **opts):
2477 def debugknown(ui, repopath, *ids, **opts):
2478 """test whether node ids are known to a repo
2478 """test whether node ids are known to a repo
2479
2479
2480 Every ID must be a full-length hex node id string. Returns a list of 0s
2480 Every ID must be a full-length hex node id string. Returns a list of 0s
2481 and 1s indicating unknown/known.
2481 and 1s indicating unknown/known.
2482 """
2482 """
2483 repo = hg.peer(ui, opts, repopath)
2483 repo = hg.peer(ui, opts, repopath)
2484 if not repo.capable('known'):
2484 if not repo.capable('known'):
2485 raise error.Abort("known() not supported by target repository")
2485 raise error.Abort("known() not supported by target repository")
2486 flags = repo.known([bin(s) for s in ids])
2486 flags = repo.known([bin(s) for s in ids])
2487 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2487 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2488
2488
2489 @command('debuglabelcomplete', [], _('LABEL...'))
2489 @command('debuglabelcomplete', [], _('LABEL...'))
2490 def debuglabelcomplete(ui, repo, *args):
2490 def debuglabelcomplete(ui, repo, *args):
2491 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2491 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2492 debugnamecomplete(ui, repo, *args)
2492 debugnamecomplete(ui, repo, *args)
2493
2493
2494 @command('debugmergestate', [], '')
2494 @command('debugmergestate', [], '')
2495 def debugmergestate(ui, repo, *args):
2495 def debugmergestate(ui, repo, *args):
2496 """print merge state
2496 """print merge state
2497
2497
2498 Use --verbose to print out information about whether v1 or v2 merge state
2498 Use --verbose to print out information about whether v1 or v2 merge state
2499 was chosen."""
2499 was chosen."""
2500 def printrecords(version):
2500 def printrecords(version):
2501 ui.write(('* version %s records\n') % version)
2501 ui.write(('* version %s records\n') % version)
2502 if version == 1:
2502 if version == 1:
2503 records = v1records
2503 records = v1records
2504 else:
2504 else:
2505 records = v2records
2505 records = v2records
2506
2506
2507 for rtype, record in records:
2507 for rtype, record in records:
2508 # pretty print some record types
2508 # pretty print some record types
2509 if rtype == 'L':
2509 if rtype == 'L':
2510 ui.write(('local: %s\n') % record)
2510 ui.write(('local: %s\n') % record)
2511 elif rtype == 'O':
2511 elif rtype == 'O':
2512 ui.write(('other: %s\n') % record)
2512 ui.write(('other: %s\n') % record)
2513 elif rtype == 'F':
2513 elif rtype == 'F':
2514 r = record.split('\0')
2514 r = record.split('\0')
2515 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2515 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2516 if version == 1:
2516 if version == 1:
2517 onode = 'not stored in v1 format'
2517 onode = 'not stored in v1 format'
2518 flags = r[7]
2518 flags = r[7]
2519 else:
2519 else:
2520 onode, flags = r[7:9]
2520 onode, flags = r[7:9]
2521 ui.write(('file: %s (state "%s", hash %s)\n')
2521 ui.write(('file: %s (state "%s", hash %s)\n')
2522 % (f, state, hash))
2522 % (f, state, hash))
2523 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2523 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2524 ui.write((' ancestor path: %s (node %s)\n') % (afile, anode))
2524 ui.write((' ancestor path: %s (node %s)\n') % (afile, anode))
2525 ui.write((' other path: %s (node %s)\n') % (ofile, onode))
2525 ui.write((' other path: %s (node %s)\n') % (ofile, onode))
2526 else:
2526 else:
2527 ui.write(('unrecognized entry: %s\t%s\n')
2527 ui.write(('unrecognized entry: %s\t%s\n')
2528 % (rtype, record.replace('\0', '\t')))
2528 % (rtype, record.replace('\0', '\t')))
2529
2529
2530 ms = mergemod.mergestate(repo)
2530 ms = mergemod.mergestate(repo)
2531
2531
2532 # sort so that reasonable information is on top
2532 # sort so that reasonable information is on top
2533 v1records = ms._readrecordsv1()
2533 v1records = ms._readrecordsv1()
2534 v2records = ms._readrecordsv2()
2534 v2records = ms._readrecordsv2()
2535 order = 'LO'
2535 order = 'LO'
2536 def key(r):
2536 def key(r):
2537 idx = order.find(r[0])
2537 idx = order.find(r[0])
2538 if idx == -1:
2538 if idx == -1:
2539 return (1, r[1])
2539 return (1, r[1])
2540 else:
2540 else:
2541 return (0, idx)
2541 return (0, idx)
2542 v1records.sort(key=key)
2542 v1records.sort(key=key)
2543 v2records.sort(key=key)
2543 v2records.sort(key=key)
2544
2544
2545 if not v1records and not v2records:
2545 if not v1records and not v2records:
2546 ui.write(('no merge state found\n'))
2546 ui.write(('no merge state found\n'))
2547 elif not v2records:
2547 elif not v2records:
2548 ui.note(('no version 2 merge state\n'))
2548 ui.note(('no version 2 merge state\n'))
2549 printrecords(1)
2549 printrecords(1)
2550 elif ms._v1v2match(v1records, v2records):
2550 elif ms._v1v2match(v1records, v2records):
2551 ui.note(('v1 and v2 states match: using v2\n'))
2551 ui.note(('v1 and v2 states match: using v2\n'))
2552 printrecords(2)
2552 printrecords(2)
2553 else:
2553 else:
2554 ui.note(('v1 and v2 states mismatch: using v1\n'))
2554 ui.note(('v1 and v2 states mismatch: using v1\n'))
2555 printrecords(1)
2555 printrecords(1)
2556 if ui.verbose:
2556 if ui.verbose:
2557 printrecords(2)
2557 printrecords(2)
2558
2558
2559 @command('debugnamecomplete', [], _('NAME...'))
2559 @command('debugnamecomplete', [], _('NAME...'))
2560 def debugnamecomplete(ui, repo, *args):
2560 def debugnamecomplete(ui, repo, *args):
2561 '''complete "names" - tags, open branch names, bookmark names'''
2561 '''complete "names" - tags, open branch names, bookmark names'''
2562
2562
2563 names = set()
2563 names = set()
2564 # since we previously only listed open branches, we will handle that
2564 # since we previously only listed open branches, we will handle that
2565 # specially (after this for loop)
2565 # specially (after this for loop)
2566 for name, ns in repo.names.iteritems():
2566 for name, ns in repo.names.iteritems():
2567 if name != 'branches':
2567 if name != 'branches':
2568 names.update(ns.listnames(repo))
2568 names.update(ns.listnames(repo))
2569 names.update(tag for (tag, heads, tip, closed)
2569 names.update(tag for (tag, heads, tip, closed)
2570 in repo.branchmap().iterbranches() if not closed)
2570 in repo.branchmap().iterbranches() if not closed)
2571 completions = set()
2571 completions = set()
2572 if not args:
2572 if not args:
2573 args = ['']
2573 args = ['']
2574 for a in args:
2574 for a in args:
2575 completions.update(n for n in names if n.startswith(a))
2575 completions.update(n for n in names if n.startswith(a))
2576 ui.write('\n'.join(sorted(completions)))
2576 ui.write('\n'.join(sorted(completions)))
2577 ui.write('\n')
2577 ui.write('\n')
2578
2578
2579 @command('debuglocks',
2579 @command('debuglocks',
2580 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2580 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2581 ('W', 'force-wlock', None,
2581 ('W', 'force-wlock', None,
2582 _('free the working state lock (DANGEROUS)'))],
2582 _('free the working state lock (DANGEROUS)'))],
2583 _('[OPTION]...'))
2583 _('[OPTION]...'))
2584 def debuglocks(ui, repo, **opts):
2584 def debuglocks(ui, repo, **opts):
2585 """show or modify state of locks
2585 """show or modify state of locks
2586
2586
2587 By default, this command will show which locks are held. This
2587 By default, this command will show which locks are held. This
2588 includes the user and process holding the lock, the amount of time
2588 includes the user and process holding the lock, the amount of time
2589 the lock has been held, and the machine name where the process is
2589 the lock has been held, and the machine name where the process is
2590 running if it's not local.
2590 running if it's not local.
2591
2591
2592 Locks protect the integrity of Mercurial's data, so should be
2592 Locks protect the integrity of Mercurial's data, so should be
2593 treated with care. System crashes or other interruptions may cause
2593 treated with care. System crashes or other interruptions may cause
2594 locks to not be properly released, though Mercurial will usually
2594 locks to not be properly released, though Mercurial will usually
2595 detect and remove such stale locks automatically.
2595 detect and remove such stale locks automatically.
2596
2596
2597 However, detecting stale locks may not always be possible (for
2597 However, detecting stale locks may not always be possible (for
2598 instance, on a shared filesystem). Removing locks may also be
2598 instance, on a shared filesystem). Removing locks may also be
2599 blocked by filesystem permissions.
2599 blocked by filesystem permissions.
2600
2600
2601 Returns 0 if no locks are held.
2601 Returns 0 if no locks are held.
2602
2602
2603 """
2603 """
2604
2604
2605 if opts.get('force_lock'):
2605 if opts.get('force_lock'):
2606 repo.svfs.unlink('lock')
2606 repo.svfs.unlink('lock')
2607 if opts.get('force_wlock'):
2607 if opts.get('force_wlock'):
2608 repo.vfs.unlink('wlock')
2608 repo.vfs.unlink('wlock')
2609 if opts.get('force_lock') or opts.get('force_lock'):
2609 if opts.get('force_lock') or opts.get('force_lock'):
2610 return 0
2610 return 0
2611
2611
2612 now = time.time()
2612 now = time.time()
2613 held = 0
2613 held = 0
2614
2614
2615 def report(vfs, name, method):
2615 def report(vfs, name, method):
2616 # this causes stale locks to get reaped for more accurate reporting
2616 # this causes stale locks to get reaped for more accurate reporting
2617 try:
2617 try:
2618 l = method(False)
2618 l = method(False)
2619 except error.LockHeld:
2619 except error.LockHeld:
2620 l = None
2620 l = None
2621
2621
2622 if l:
2622 if l:
2623 l.release()
2623 l.release()
2624 else:
2624 else:
2625 try:
2625 try:
2626 stat = vfs.lstat(name)
2626 stat = vfs.lstat(name)
2627 age = now - stat.st_mtime
2627 age = now - stat.st_mtime
2628 user = util.username(stat.st_uid)
2628 user = util.username(stat.st_uid)
2629 locker = vfs.readlock(name)
2629 locker = vfs.readlock(name)
2630 if ":" in locker:
2630 if ":" in locker:
2631 host, pid = locker.split(':')
2631 host, pid = locker.split(':')
2632 if host == socket.gethostname():
2632 if host == socket.gethostname():
2633 locker = 'user %s, process %s' % (user, pid)
2633 locker = 'user %s, process %s' % (user, pid)
2634 else:
2634 else:
2635 locker = 'user %s, process %s, host %s' \
2635 locker = 'user %s, process %s, host %s' \
2636 % (user, pid, host)
2636 % (user, pid, host)
2637 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2637 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2638 return 1
2638 return 1
2639 except OSError as e:
2639 except OSError as e:
2640 if e.errno != errno.ENOENT:
2640 if e.errno != errno.ENOENT:
2641 raise
2641 raise
2642
2642
2643 ui.write("%-6s free\n" % (name + ":"))
2643 ui.write("%-6s free\n" % (name + ":"))
2644 return 0
2644 return 0
2645
2645
2646 held += report(repo.svfs, "lock", repo.lock)
2646 held += report(repo.svfs, "lock", repo.lock)
2647 held += report(repo.vfs, "wlock", repo.wlock)
2647 held += report(repo.vfs, "wlock", repo.wlock)
2648
2648
2649 return held
2649 return held
2650
2650
2651 @command('debugobsolete',
2651 @command('debugobsolete',
2652 [('', 'flags', 0, _('markers flag')),
2652 [('', 'flags', 0, _('markers flag')),
2653 ('', 'record-parents', False,
2653 ('', 'record-parents', False,
2654 _('record parent information for the precursor')),
2654 _('record parent information for the precursor')),
2655 ('r', 'rev', [], _('display markers relevant to REV')),
2655 ('r', 'rev', [], _('display markers relevant to REV')),
2656 ] + commitopts2,
2656 ] + commitopts2,
2657 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2657 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2658 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2658 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2659 """create arbitrary obsolete marker
2659 """create arbitrary obsolete marker
2660
2660
2661 With no arguments, displays the list of obsolescence markers."""
2661 With no arguments, displays the list of obsolescence markers."""
2662
2662
2663 def parsenodeid(s):
2663 def parsenodeid(s):
2664 try:
2664 try:
2665 # We do not use revsingle/revrange functions here to accept
2665 # We do not use revsingle/revrange functions here to accept
2666 # arbitrary node identifiers, possibly not present in the
2666 # arbitrary node identifiers, possibly not present in the
2667 # local repository.
2667 # local repository.
2668 n = bin(s)
2668 n = bin(s)
2669 if len(n) != len(nullid):
2669 if len(n) != len(nullid):
2670 raise TypeError()
2670 raise TypeError()
2671 return n
2671 return n
2672 except TypeError:
2672 except TypeError:
2673 raise error.Abort('changeset references must be full hexadecimal '
2673 raise error.Abort('changeset references must be full hexadecimal '
2674 'node identifiers')
2674 'node identifiers')
2675
2675
2676 if precursor is not None:
2676 if precursor is not None:
2677 if opts['rev']:
2677 if opts['rev']:
2678 raise error.Abort('cannot select revision when creating marker')
2678 raise error.Abort('cannot select revision when creating marker')
2679 metadata = {}
2679 metadata = {}
2680 metadata['user'] = opts['user'] or ui.username()
2680 metadata['user'] = opts['user'] or ui.username()
2681 succs = tuple(parsenodeid(succ) for succ in successors)
2681 succs = tuple(parsenodeid(succ) for succ in successors)
2682 l = repo.lock()
2682 l = repo.lock()
2683 try:
2683 try:
2684 tr = repo.transaction('debugobsolete')
2684 tr = repo.transaction('debugobsolete')
2685 try:
2685 try:
2686 date = opts.get('date')
2686 date = opts.get('date')
2687 if date:
2687 if date:
2688 date = util.parsedate(date)
2688 date = util.parsedate(date)
2689 else:
2689 else:
2690 date = None
2690 date = None
2691 prec = parsenodeid(precursor)
2691 prec = parsenodeid(precursor)
2692 parents = None
2692 parents = None
2693 if opts['record_parents']:
2693 if opts['record_parents']:
2694 if prec not in repo.unfiltered():
2694 if prec not in repo.unfiltered():
2695 raise error.Abort('cannot used --record-parents on '
2695 raise error.Abort('cannot used --record-parents on '
2696 'unknown changesets')
2696 'unknown changesets')
2697 parents = repo.unfiltered()[prec].parents()
2697 parents = repo.unfiltered()[prec].parents()
2698 parents = tuple(p.node() for p in parents)
2698 parents = tuple(p.node() for p in parents)
2699 repo.obsstore.create(tr, prec, succs, opts['flags'],
2699 repo.obsstore.create(tr, prec, succs, opts['flags'],
2700 parents=parents, date=date,
2700 parents=parents, date=date,
2701 metadata=metadata)
2701 metadata=metadata)
2702 tr.close()
2702 tr.close()
2703 except ValueError as exc:
2703 except ValueError as exc:
2704 raise error.Abort(_('bad obsmarker input: %s') % exc)
2704 raise error.Abort(_('bad obsmarker input: %s') % exc)
2705 finally:
2705 finally:
2706 tr.release()
2706 tr.release()
2707 finally:
2707 finally:
2708 l.release()
2708 l.release()
2709 else:
2709 else:
2710 if opts['rev']:
2710 if opts['rev']:
2711 revs = scmutil.revrange(repo, opts['rev'])
2711 revs = scmutil.revrange(repo, opts['rev'])
2712 nodes = [repo[r].node() for r in revs]
2712 nodes = [repo[r].node() for r in revs]
2713 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2713 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2714 markers.sort(key=lambda x: x._data)
2714 markers.sort(key=lambda x: x._data)
2715 else:
2715 else:
2716 markers = obsolete.getmarkers(repo)
2716 markers = obsolete.getmarkers(repo)
2717
2717
2718 for m in markers:
2718 for m in markers:
2719 cmdutil.showmarker(ui, m)
2719 cmdutil.showmarker(ui, m)
2720
2720
2721 @command('debugpathcomplete',
2721 @command('debugpathcomplete',
2722 [('f', 'full', None, _('complete an entire path')),
2722 [('f', 'full', None, _('complete an entire path')),
2723 ('n', 'normal', None, _('show only normal files')),
2723 ('n', 'normal', None, _('show only normal files')),
2724 ('a', 'added', None, _('show only added files')),
2724 ('a', 'added', None, _('show only added files')),
2725 ('r', 'removed', None, _('show only removed files'))],
2725 ('r', 'removed', None, _('show only removed files'))],
2726 _('FILESPEC...'))
2726 _('FILESPEC...'))
2727 def debugpathcomplete(ui, repo, *specs, **opts):
2727 def debugpathcomplete(ui, repo, *specs, **opts):
2728 '''complete part or all of a tracked path
2728 '''complete part or all of a tracked path
2729
2729
2730 This command supports shells that offer path name completion. It
2730 This command supports shells that offer path name completion. It
2731 currently completes only files already known to the dirstate.
2731 currently completes only files already known to the dirstate.
2732
2732
2733 Completion extends only to the next path segment unless
2733 Completion extends only to the next path segment unless
2734 --full is specified, in which case entire paths are used.'''
2734 --full is specified, in which case entire paths are used.'''
2735
2735
2736 def complete(path, acceptable):
2736 def complete(path, acceptable):
2737 dirstate = repo.dirstate
2737 dirstate = repo.dirstate
2738 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2738 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2739 rootdir = repo.root + os.sep
2739 rootdir = repo.root + os.sep
2740 if spec != repo.root and not spec.startswith(rootdir):
2740 if spec != repo.root and not spec.startswith(rootdir):
2741 return [], []
2741 return [], []
2742 if os.path.isdir(spec):
2742 if os.path.isdir(spec):
2743 spec += '/'
2743 spec += '/'
2744 spec = spec[len(rootdir):]
2744 spec = spec[len(rootdir):]
2745 fixpaths = os.sep != '/'
2745 fixpaths = os.sep != '/'
2746 if fixpaths:
2746 if fixpaths:
2747 spec = spec.replace(os.sep, '/')
2747 spec = spec.replace(os.sep, '/')
2748 speclen = len(spec)
2748 speclen = len(spec)
2749 fullpaths = opts['full']
2749 fullpaths = opts['full']
2750 files, dirs = set(), set()
2750 files, dirs = set(), set()
2751 adddir, addfile = dirs.add, files.add
2751 adddir, addfile = dirs.add, files.add
2752 for f, st in dirstate.iteritems():
2752 for f, st in dirstate.iteritems():
2753 if f.startswith(spec) and st[0] in acceptable:
2753 if f.startswith(spec) and st[0] in acceptable:
2754 if fixpaths:
2754 if fixpaths:
2755 f = f.replace('/', os.sep)
2755 f = f.replace('/', os.sep)
2756 if fullpaths:
2756 if fullpaths:
2757 addfile(f)
2757 addfile(f)
2758 continue
2758 continue
2759 s = f.find(os.sep, speclen)
2759 s = f.find(os.sep, speclen)
2760 if s >= 0:
2760 if s >= 0:
2761 adddir(f[:s])
2761 adddir(f[:s])
2762 else:
2762 else:
2763 addfile(f)
2763 addfile(f)
2764 return files, dirs
2764 return files, dirs
2765
2765
2766 acceptable = ''
2766 acceptable = ''
2767 if opts['normal']:
2767 if opts['normal']:
2768 acceptable += 'nm'
2768 acceptable += 'nm'
2769 if opts['added']:
2769 if opts['added']:
2770 acceptable += 'a'
2770 acceptable += 'a'
2771 if opts['removed']:
2771 if opts['removed']:
2772 acceptable += 'r'
2772 acceptable += 'r'
2773 cwd = repo.getcwd()
2773 cwd = repo.getcwd()
2774 if not specs:
2774 if not specs:
2775 specs = ['.']
2775 specs = ['.']
2776
2776
2777 files, dirs = set(), set()
2777 files, dirs = set(), set()
2778 for spec in specs:
2778 for spec in specs:
2779 f, d = complete(spec, acceptable or 'nmar')
2779 f, d = complete(spec, acceptable or 'nmar')
2780 files.update(f)
2780 files.update(f)
2781 dirs.update(d)
2781 dirs.update(d)
2782 files.update(dirs)
2782 files.update(dirs)
2783 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2783 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2784 ui.write('\n')
2784 ui.write('\n')
2785
2785
2786 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2786 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2787 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2787 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2788 '''access the pushkey key/value protocol
2788 '''access the pushkey key/value protocol
2789
2789
2790 With two args, list the keys in the given namespace.
2790 With two args, list the keys in the given namespace.
2791
2791
2792 With five args, set a key to new if it currently is set to old.
2792 With five args, set a key to new if it currently is set to old.
2793 Reports success or failure.
2793 Reports success or failure.
2794 '''
2794 '''
2795
2795
2796 target = hg.peer(ui, {}, repopath)
2796 target = hg.peer(ui, {}, repopath)
2797 if keyinfo:
2797 if keyinfo:
2798 key, old, new = keyinfo
2798 key, old, new = keyinfo
2799 r = target.pushkey(namespace, key, old, new)
2799 r = target.pushkey(namespace, key, old, new)
2800 ui.status(str(r) + '\n')
2800 ui.status(str(r) + '\n')
2801 return not r
2801 return not r
2802 else:
2802 else:
2803 for k, v in sorted(target.listkeys(namespace).iteritems()):
2803 for k, v in sorted(target.listkeys(namespace).iteritems()):
2804 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2804 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2805 v.encode('string-escape')))
2805 v.encode('string-escape')))
2806
2806
2807 @command('debugpvec', [], _('A B'))
2807 @command('debugpvec', [], _('A B'))
2808 def debugpvec(ui, repo, a, b=None):
2808 def debugpvec(ui, repo, a, b=None):
2809 ca = scmutil.revsingle(repo, a)
2809 ca = scmutil.revsingle(repo, a)
2810 cb = scmutil.revsingle(repo, b)
2810 cb = scmutil.revsingle(repo, b)
2811 pa = pvec.ctxpvec(ca)
2811 pa = pvec.ctxpvec(ca)
2812 pb = pvec.ctxpvec(cb)
2812 pb = pvec.ctxpvec(cb)
2813 if pa == pb:
2813 if pa == pb:
2814 rel = "="
2814 rel = "="
2815 elif pa > pb:
2815 elif pa > pb:
2816 rel = ">"
2816 rel = ">"
2817 elif pa < pb:
2817 elif pa < pb:
2818 rel = "<"
2818 rel = "<"
2819 elif pa | pb:
2819 elif pa | pb:
2820 rel = "|"
2820 rel = "|"
2821 ui.write(_("a: %s\n") % pa)
2821 ui.write(_("a: %s\n") % pa)
2822 ui.write(_("b: %s\n") % pb)
2822 ui.write(_("b: %s\n") % pb)
2823 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2823 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2824 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2824 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2825 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2825 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2826 pa.distance(pb), rel))
2826 pa.distance(pb), rel))
2827
2827
2828 @command('debugrebuilddirstate|debugrebuildstate',
2828 @command('debugrebuilddirstate|debugrebuildstate',
2829 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2829 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2830 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2830 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2831 'the working copy parent')),
2831 'the working copy parent')),
2832 ],
2832 ],
2833 _('[-r REV]'))
2833 _('[-r REV]'))
2834 def debugrebuilddirstate(ui, repo, rev, **opts):
2834 def debugrebuilddirstate(ui, repo, rev, **opts):
2835 """rebuild the dirstate as it would look like for the given revision
2835 """rebuild the dirstate as it would look like for the given revision
2836
2836
2837 If no revision is specified the first current parent will be used.
2837 If no revision is specified the first current parent will be used.
2838
2838
2839 The dirstate will be set to the files of the given revision.
2839 The dirstate will be set to the files of the given revision.
2840 The actual working directory content or existing dirstate
2840 The actual working directory content or existing dirstate
2841 information such as adds or removes is not considered.
2841 information such as adds or removes is not considered.
2842
2842
2843 ``minimal`` will only rebuild the dirstate status for files that claim to be
2843 ``minimal`` will only rebuild the dirstate status for files that claim to be
2844 tracked but are not in the parent manifest, or that exist in the parent
2844 tracked but are not in the parent manifest, or that exist in the parent
2845 manifest but are not in the dirstate. It will not change adds, removes, or
2845 manifest but are not in the dirstate. It will not change adds, removes, or
2846 modified files that are in the working copy parent.
2846 modified files that are in the working copy parent.
2847
2847
2848 One use of this command is to make the next :hg:`status` invocation
2848 One use of this command is to make the next :hg:`status` invocation
2849 check the actual file content.
2849 check the actual file content.
2850 """
2850 """
2851 ctx = scmutil.revsingle(repo, rev)
2851 ctx = scmutil.revsingle(repo, rev)
2852 wlock = repo.wlock()
2852 wlock = repo.wlock()
2853 try:
2853 try:
2854 dirstate = repo.dirstate
2854 dirstate = repo.dirstate
2855
2855
2856 # See command doc for what minimal does.
2856 # See command doc for what minimal does.
2857 if opts.get('minimal'):
2857 if opts.get('minimal'):
2858 dirstatefiles = set(dirstate)
2858 dirstatefiles = set(dirstate)
2859 ctxfiles = set(ctx.manifest().keys())
2859 ctxfiles = set(ctx.manifest().keys())
2860 for file in (dirstatefiles | ctxfiles):
2860 for file in (dirstatefiles | ctxfiles):
2861 indirstate = file in dirstatefiles
2861 indirstate = file in dirstatefiles
2862 inctx = file in ctxfiles
2862 inctx = file in ctxfiles
2863
2863
2864 if indirstate and not inctx and dirstate[file] != 'a':
2864 if indirstate and not inctx and dirstate[file] != 'a':
2865 dirstate.drop(file)
2865 dirstate.drop(file)
2866 elif inctx and not indirstate:
2866 elif inctx and not indirstate:
2867 dirstate.normallookup(file)
2867 dirstate.normallookup(file)
2868 else:
2868 else:
2869 dirstate.rebuild(ctx.node(), ctx.manifest())
2869 dirstate.rebuild(ctx.node(), ctx.manifest())
2870 finally:
2870 finally:
2871 wlock.release()
2871 wlock.release()
2872
2872
2873 @command('debugrebuildfncache', [], '')
2873 @command('debugrebuildfncache', [], '')
2874 def debugrebuildfncache(ui, repo):
2874 def debugrebuildfncache(ui, repo):
2875 """rebuild the fncache file"""
2875 """rebuild the fncache file"""
2876 repair.rebuildfncache(ui, repo)
2876 repair.rebuildfncache(ui, repo)
2877
2877
2878 @command('debugrename',
2878 @command('debugrename',
2879 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2879 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2880 _('[-r REV] FILE'))
2880 _('[-r REV] FILE'))
2881 def debugrename(ui, repo, file1, *pats, **opts):
2881 def debugrename(ui, repo, file1, *pats, **opts):
2882 """dump rename information"""
2882 """dump rename information"""
2883
2883
2884 ctx = scmutil.revsingle(repo, opts.get('rev'))
2884 ctx = scmutil.revsingle(repo, opts.get('rev'))
2885 m = scmutil.match(ctx, (file1,) + pats, opts)
2885 m = scmutil.match(ctx, (file1,) + pats, opts)
2886 for abs in ctx.walk(m):
2886 for abs in ctx.walk(m):
2887 fctx = ctx[abs]
2887 fctx = ctx[abs]
2888 o = fctx.filelog().renamed(fctx.filenode())
2888 o = fctx.filelog().renamed(fctx.filenode())
2889 rel = m.rel(abs)
2889 rel = m.rel(abs)
2890 if o:
2890 if o:
2891 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2891 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2892 else:
2892 else:
2893 ui.write(_("%s not renamed\n") % rel)
2893 ui.write(_("%s not renamed\n") % rel)
2894
2894
2895 @command('debugrevlog',
2895 @command('debugrevlog',
2896 [('c', 'changelog', False, _('open changelog')),
2896 [('c', 'changelog', False, _('open changelog')),
2897 ('m', 'manifest', False, _('open manifest')),
2897 ('m', 'manifest', False, _('open manifest')),
2898 ('', 'dir', False, _('open directory manifest')),
2898 ('', 'dir', False, _('open directory manifest')),
2899 ('d', 'dump', False, _('dump index data'))],
2899 ('d', 'dump', False, _('dump index data'))],
2900 _('-c|-m|FILE'),
2900 _('-c|-m|FILE'),
2901 optionalrepo=True)
2901 optionalrepo=True)
2902 def debugrevlog(ui, repo, file_=None, **opts):
2902 def debugrevlog(ui, repo, file_=None, **opts):
2903 """show data and statistics about a revlog"""
2903 """show data and statistics about a revlog"""
2904 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2904 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2905
2905
2906 if opts.get("dump"):
2906 if opts.get("dump"):
2907 numrevs = len(r)
2907 numrevs = len(r)
2908 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2908 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2909 " rawsize totalsize compression heads chainlen\n")
2909 " rawsize totalsize compression heads chainlen\n")
2910 ts = 0
2910 ts = 0
2911 heads = set()
2911 heads = set()
2912
2912
2913 for rev in xrange(numrevs):
2913 for rev in xrange(numrevs):
2914 dbase = r.deltaparent(rev)
2914 dbase = r.deltaparent(rev)
2915 if dbase == -1:
2915 if dbase == -1:
2916 dbase = rev
2916 dbase = rev
2917 cbase = r.chainbase(rev)
2917 cbase = r.chainbase(rev)
2918 clen = r.chainlen(rev)
2918 clen = r.chainlen(rev)
2919 p1, p2 = r.parentrevs(rev)
2919 p1, p2 = r.parentrevs(rev)
2920 rs = r.rawsize(rev)
2920 rs = r.rawsize(rev)
2921 ts = ts + rs
2921 ts = ts + rs
2922 heads -= set(r.parentrevs(rev))
2922 heads -= set(r.parentrevs(rev))
2923 heads.add(rev)
2923 heads.add(rev)
2924 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2924 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2925 "%11d %5d %8d\n" %
2925 "%11d %5d %8d\n" %
2926 (rev, p1, p2, r.start(rev), r.end(rev),
2926 (rev, p1, p2, r.start(rev), r.end(rev),
2927 r.start(dbase), r.start(cbase),
2927 r.start(dbase), r.start(cbase),
2928 r.start(p1), r.start(p2),
2928 r.start(p1), r.start(p2),
2929 rs, ts, ts / r.end(rev), len(heads), clen))
2929 rs, ts, ts / r.end(rev), len(heads), clen))
2930 return 0
2930 return 0
2931
2931
2932 v = r.version
2932 v = r.version
2933 format = v & 0xFFFF
2933 format = v & 0xFFFF
2934 flags = []
2934 flags = []
2935 gdelta = False
2935 gdelta = False
2936 if v & revlog.REVLOGNGINLINEDATA:
2936 if v & revlog.REVLOGNGINLINEDATA:
2937 flags.append('inline')
2937 flags.append('inline')
2938 if v & revlog.REVLOGGENERALDELTA:
2938 if v & revlog.REVLOGGENERALDELTA:
2939 gdelta = True
2939 gdelta = True
2940 flags.append('generaldelta')
2940 flags.append('generaldelta')
2941 if not flags:
2941 if not flags:
2942 flags = ['(none)']
2942 flags = ['(none)']
2943
2943
2944 nummerges = 0
2944 nummerges = 0
2945 numfull = 0
2945 numfull = 0
2946 numprev = 0
2946 numprev = 0
2947 nump1 = 0
2947 nump1 = 0
2948 nump2 = 0
2948 nump2 = 0
2949 numother = 0
2949 numother = 0
2950 nump1prev = 0
2950 nump1prev = 0
2951 nump2prev = 0
2951 nump2prev = 0
2952 chainlengths = []
2952 chainlengths = []
2953
2953
2954 datasize = [None, 0, 0L]
2954 datasize = [None, 0, 0L]
2955 fullsize = [None, 0, 0L]
2955 fullsize = [None, 0, 0L]
2956 deltasize = [None, 0, 0L]
2956 deltasize = [None, 0, 0L]
2957
2957
2958 def addsize(size, l):
2958 def addsize(size, l):
2959 if l[0] is None or size < l[0]:
2959 if l[0] is None or size < l[0]:
2960 l[0] = size
2960 l[0] = size
2961 if size > l[1]:
2961 if size > l[1]:
2962 l[1] = size
2962 l[1] = size
2963 l[2] += size
2963 l[2] += size
2964
2964
2965 numrevs = len(r)
2965 numrevs = len(r)
2966 for rev in xrange(numrevs):
2966 for rev in xrange(numrevs):
2967 p1, p2 = r.parentrevs(rev)
2967 p1, p2 = r.parentrevs(rev)
2968 delta = r.deltaparent(rev)
2968 delta = r.deltaparent(rev)
2969 if format > 0:
2969 if format > 0:
2970 addsize(r.rawsize(rev), datasize)
2970 addsize(r.rawsize(rev), datasize)
2971 if p2 != nullrev:
2971 if p2 != nullrev:
2972 nummerges += 1
2972 nummerges += 1
2973 size = r.length(rev)
2973 size = r.length(rev)
2974 if delta == nullrev:
2974 if delta == nullrev:
2975 chainlengths.append(0)
2975 chainlengths.append(0)
2976 numfull += 1
2976 numfull += 1
2977 addsize(size, fullsize)
2977 addsize(size, fullsize)
2978 else:
2978 else:
2979 chainlengths.append(chainlengths[delta] + 1)
2979 chainlengths.append(chainlengths[delta] + 1)
2980 addsize(size, deltasize)
2980 addsize(size, deltasize)
2981 if delta == rev - 1:
2981 if delta == rev - 1:
2982 numprev += 1
2982 numprev += 1
2983 if delta == p1:
2983 if delta == p1:
2984 nump1prev += 1
2984 nump1prev += 1
2985 elif delta == p2:
2985 elif delta == p2:
2986 nump2prev += 1
2986 nump2prev += 1
2987 elif delta == p1:
2987 elif delta == p1:
2988 nump1 += 1
2988 nump1 += 1
2989 elif delta == p2:
2989 elif delta == p2:
2990 nump2 += 1
2990 nump2 += 1
2991 elif delta != nullrev:
2991 elif delta != nullrev:
2992 numother += 1
2992 numother += 1
2993
2993
2994 # Adjust size min value for empty cases
2994 # Adjust size min value for empty cases
2995 for size in (datasize, fullsize, deltasize):
2995 for size in (datasize, fullsize, deltasize):
2996 if size[0] is None:
2996 if size[0] is None:
2997 size[0] = 0
2997 size[0] = 0
2998
2998
2999 numdeltas = numrevs - numfull
2999 numdeltas = numrevs - numfull
3000 numoprev = numprev - nump1prev - nump2prev
3000 numoprev = numprev - nump1prev - nump2prev
3001 totalrawsize = datasize[2]
3001 totalrawsize = datasize[2]
3002 datasize[2] /= numrevs
3002 datasize[2] /= numrevs
3003 fulltotal = fullsize[2]
3003 fulltotal = fullsize[2]
3004 fullsize[2] /= numfull
3004 fullsize[2] /= numfull
3005 deltatotal = deltasize[2]
3005 deltatotal = deltasize[2]
3006 if numrevs - numfull > 0:
3006 if numrevs - numfull > 0:
3007 deltasize[2] /= numrevs - numfull
3007 deltasize[2] /= numrevs - numfull
3008 totalsize = fulltotal + deltatotal
3008 totalsize = fulltotal + deltatotal
3009 avgchainlen = sum(chainlengths) / numrevs
3009 avgchainlen = sum(chainlengths) / numrevs
3010 maxchainlen = max(chainlengths)
3010 maxchainlen = max(chainlengths)
3011 compratio = totalrawsize / totalsize
3011 compratio = totalrawsize / totalsize
3012
3012
3013 basedfmtstr = '%%%dd\n'
3013 basedfmtstr = '%%%dd\n'
3014 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3014 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3015
3015
3016 def dfmtstr(max):
3016 def dfmtstr(max):
3017 return basedfmtstr % len(str(max))
3017 return basedfmtstr % len(str(max))
3018 def pcfmtstr(max, padding=0):
3018 def pcfmtstr(max, padding=0):
3019 return basepcfmtstr % (len(str(max)), ' ' * padding)
3019 return basepcfmtstr % (len(str(max)), ' ' * padding)
3020
3020
3021 def pcfmt(value, total):
3021 def pcfmt(value, total):
3022 return (value, 100 * float(value) / total)
3022 return (value, 100 * float(value) / total)
3023
3023
3024 ui.write(('format : %d\n') % format)
3024 ui.write(('format : %d\n') % format)
3025 ui.write(('flags : %s\n') % ', '.join(flags))
3025 ui.write(('flags : %s\n') % ', '.join(flags))
3026
3026
3027 ui.write('\n')
3027 ui.write('\n')
3028 fmt = pcfmtstr(totalsize)
3028 fmt = pcfmtstr(totalsize)
3029 fmt2 = dfmtstr(totalsize)
3029 fmt2 = dfmtstr(totalsize)
3030 ui.write(('revisions : ') + fmt2 % numrevs)
3030 ui.write(('revisions : ') + fmt2 % numrevs)
3031 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3031 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3032 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3032 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3033 ui.write(('revisions : ') + fmt2 % numrevs)
3033 ui.write(('revisions : ') + fmt2 % numrevs)
3034 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3034 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3035 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3035 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3036 ui.write(('revision size : ') + fmt2 % totalsize)
3036 ui.write(('revision size : ') + fmt2 % totalsize)
3037 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3037 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3038 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3038 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3039
3039
3040 ui.write('\n')
3040 ui.write('\n')
3041 fmt = dfmtstr(max(avgchainlen, compratio))
3041 fmt = dfmtstr(max(avgchainlen, compratio))
3042 ui.write(('avg chain length : ') + fmt % avgchainlen)
3042 ui.write(('avg chain length : ') + fmt % avgchainlen)
3043 ui.write(('max chain length : ') + fmt % maxchainlen)
3043 ui.write(('max chain length : ') + fmt % maxchainlen)
3044 ui.write(('compression ratio : ') + fmt % compratio)
3044 ui.write(('compression ratio : ') + fmt % compratio)
3045
3045
3046 if format > 0:
3046 if format > 0:
3047 ui.write('\n')
3047 ui.write('\n')
3048 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3048 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3049 % tuple(datasize))
3049 % tuple(datasize))
3050 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3050 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3051 % tuple(fullsize))
3051 % tuple(fullsize))
3052 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3052 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3053 % tuple(deltasize))
3053 % tuple(deltasize))
3054
3054
3055 if numdeltas > 0:
3055 if numdeltas > 0:
3056 ui.write('\n')
3056 ui.write('\n')
3057 fmt = pcfmtstr(numdeltas)
3057 fmt = pcfmtstr(numdeltas)
3058 fmt2 = pcfmtstr(numdeltas, 4)
3058 fmt2 = pcfmtstr(numdeltas, 4)
3059 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3059 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3060 if numprev > 0:
3060 if numprev > 0:
3061 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3061 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3062 numprev))
3062 numprev))
3063 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3063 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3064 numprev))
3064 numprev))
3065 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3065 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3066 numprev))
3066 numprev))
3067 if gdelta:
3067 if gdelta:
3068 ui.write(('deltas against p1 : ')
3068 ui.write(('deltas against p1 : ')
3069 + fmt % pcfmt(nump1, numdeltas))
3069 + fmt % pcfmt(nump1, numdeltas))
3070 ui.write(('deltas against p2 : ')
3070 ui.write(('deltas against p2 : ')
3071 + fmt % pcfmt(nump2, numdeltas))
3071 + fmt % pcfmt(nump2, numdeltas))
3072 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3072 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3073 numdeltas))
3073 numdeltas))
3074
3074
3075 @command('debugrevspec',
3075 @command('debugrevspec',
3076 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3076 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3077 ('REVSPEC'))
3077 ('REVSPEC'))
3078 def debugrevspec(ui, repo, expr, **opts):
3078 def debugrevspec(ui, repo, expr, **opts):
3079 """parse and apply a revision specification
3079 """parse and apply a revision specification
3080
3080
3081 Use --verbose to print the parsed tree before and after aliases
3081 Use --verbose to print the parsed tree before and after aliases
3082 expansion.
3082 expansion.
3083 """
3083 """
3084 if ui.verbose:
3084 if ui.verbose:
3085 tree = revset.parse(expr, lookup=repo.__contains__)
3085 tree = revset.parse(expr, lookup=repo.__contains__)
3086 ui.note(revset.prettyformat(tree), "\n")
3086 ui.note(revset.prettyformat(tree), "\n")
3087 newtree = revset.findaliases(ui, tree)
3087 newtree = revset.findaliases(ui, tree)
3088 if newtree != tree:
3088 if newtree != tree:
3089 ui.note(revset.prettyformat(newtree), "\n")
3089 ui.note(revset.prettyformat(newtree), "\n")
3090 tree = newtree
3090 tree = newtree
3091 newtree = revset.foldconcat(tree)
3091 newtree = revset.foldconcat(tree)
3092 if newtree != tree:
3092 if newtree != tree:
3093 ui.note(revset.prettyformat(newtree), "\n")
3093 ui.note(revset.prettyformat(newtree), "\n")
3094 if opts["optimize"]:
3094 if opts["optimize"]:
3095 weight, optimizedtree = revset.optimize(newtree, True)
3095 weight, optimizedtree = revset.optimize(newtree, True)
3096 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3096 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3097 func = revset.match(ui, expr, repo)
3097 func = revset.match(ui, expr, repo)
3098 revs = func(repo)
3098 revs = func(repo)
3099 if ui.verbose:
3099 if ui.verbose:
3100 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3100 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3101 for c in revs:
3101 for c in revs:
3102 ui.write("%s\n" % c)
3102 ui.write("%s\n" % c)
3103
3103
3104 @command('debugsetparents', [], _('REV1 [REV2]'))
3104 @command('debugsetparents', [], _('REV1 [REV2]'))
3105 def debugsetparents(ui, repo, rev1, rev2=None):
3105 def debugsetparents(ui, repo, rev1, rev2=None):
3106 """manually set the parents of the current working directory
3106 """manually set the parents of the current working directory
3107
3107
3108 This is useful for writing repository conversion tools, but should
3108 This is useful for writing repository conversion tools, but should
3109 be used with care. For example, neither the working directory nor the
3109 be used with care. For example, neither the working directory nor the
3110 dirstate is updated, so file status may be incorrect after running this
3110 dirstate is updated, so file status may be incorrect after running this
3111 command.
3111 command.
3112
3112
3113 Returns 0 on success.
3113 Returns 0 on success.
3114 """
3114 """
3115
3115
3116 r1 = scmutil.revsingle(repo, rev1).node()
3116 r1 = scmutil.revsingle(repo, rev1).node()
3117 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3117 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3118
3118
3119 wlock = repo.wlock()
3119 wlock = repo.wlock()
3120 try:
3120 try:
3121 repo.dirstate.beginparentchange()
3121 repo.dirstate.beginparentchange()
3122 repo.setparents(r1, r2)
3122 repo.setparents(r1, r2)
3123 repo.dirstate.endparentchange()
3123 repo.dirstate.endparentchange()
3124 finally:
3124 finally:
3125 wlock.release()
3125 wlock.release()
3126
3126
3127 @command('debugdirstate|debugstate',
3127 @command('debugdirstate|debugstate',
3128 [('', 'nodates', None, _('do not display the saved mtime')),
3128 [('', 'nodates', None, _('do not display the saved mtime')),
3129 ('', 'datesort', None, _('sort by saved mtime'))],
3129 ('', 'datesort', None, _('sort by saved mtime'))],
3130 _('[OPTION]...'))
3130 _('[OPTION]...'))
3131 def debugstate(ui, repo, nodates=None, datesort=None):
3131 def debugstate(ui, repo, nodates=None, datesort=None):
3132 """show the contents of the current dirstate"""
3132 """show the contents of the current dirstate"""
3133 timestr = ""
3133 timestr = ""
3134 if datesort:
3134 if datesort:
3135 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3135 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3136 else:
3136 else:
3137 keyfunc = None # sort by filename
3137 keyfunc = None # sort by filename
3138 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3138 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3139 if ent[3] == -1:
3139 if ent[3] == -1:
3140 timestr = 'unset '
3140 timestr = 'unset '
3141 elif nodates:
3141 elif nodates:
3142 timestr = 'set '
3142 timestr = 'set '
3143 else:
3143 else:
3144 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3144 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3145 time.localtime(ent[3]))
3145 time.localtime(ent[3]))
3146 if ent[1] & 0o20000:
3146 if ent[1] & 0o20000:
3147 mode = 'lnk'
3147 mode = 'lnk'
3148 else:
3148 else:
3149 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3149 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3150 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3150 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3151 for f in repo.dirstate.copies():
3151 for f in repo.dirstate.copies():
3152 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3152 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3153
3153
3154 @command('debugsub',
3154 @command('debugsub',
3155 [('r', 'rev', '',
3155 [('r', 'rev', '',
3156 _('revision to check'), _('REV'))],
3156 _('revision to check'), _('REV'))],
3157 _('[-r REV] [REV]'))
3157 _('[-r REV] [REV]'))
3158 def debugsub(ui, repo, rev=None):
3158 def debugsub(ui, repo, rev=None):
3159 ctx = scmutil.revsingle(repo, rev, None)
3159 ctx = scmutil.revsingle(repo, rev, None)
3160 for k, v in sorted(ctx.substate.items()):
3160 for k, v in sorted(ctx.substate.items()):
3161 ui.write(('path %s\n') % k)
3161 ui.write(('path %s\n') % k)
3162 ui.write((' source %s\n') % v[0])
3162 ui.write((' source %s\n') % v[0])
3163 ui.write((' revision %s\n') % v[1])
3163 ui.write((' revision %s\n') % v[1])
3164
3164
3165 @command('debugsuccessorssets',
3165 @command('debugsuccessorssets',
3166 [],
3166 [],
3167 _('[REV]'))
3167 _('[REV]'))
3168 def debugsuccessorssets(ui, repo, *revs):
3168 def debugsuccessorssets(ui, repo, *revs):
3169 """show set of successors for revision
3169 """show set of successors for revision
3170
3170
3171 A successors set of changeset A is a consistent group of revisions that
3171 A successors set of changeset A is a consistent group of revisions that
3172 succeed A. It contains non-obsolete changesets only.
3172 succeed A. It contains non-obsolete changesets only.
3173
3173
3174 In most cases a changeset A has a single successors set containing a single
3174 In most cases a changeset A has a single successors set containing a single
3175 successor (changeset A replaced by A').
3175 successor (changeset A replaced by A').
3176
3176
3177 A changeset that is made obsolete with no successors are called "pruned".
3177 A changeset that is made obsolete with no successors are called "pruned".
3178 Such changesets have no successors sets at all.
3178 Such changesets have no successors sets at all.
3179
3179
3180 A changeset that has been "split" will have a successors set containing
3180 A changeset that has been "split" will have a successors set containing
3181 more than one successor.
3181 more than one successor.
3182
3182
3183 A changeset that has been rewritten in multiple different ways is called
3183 A changeset that has been rewritten in multiple different ways is called
3184 "divergent". Such changesets have multiple successor sets (each of which
3184 "divergent". Such changesets have multiple successor sets (each of which
3185 may also be split, i.e. have multiple successors).
3185 may also be split, i.e. have multiple successors).
3186
3186
3187 Results are displayed as follows::
3187 Results are displayed as follows::
3188
3188
3189 <rev1>
3189 <rev1>
3190 <successors-1A>
3190 <successors-1A>
3191 <rev2>
3191 <rev2>
3192 <successors-2A>
3192 <successors-2A>
3193 <successors-2B1> <successors-2B2> <successors-2B3>
3193 <successors-2B1> <successors-2B2> <successors-2B3>
3194
3194
3195 Here rev2 has two possible (i.e. divergent) successors sets. The first
3195 Here rev2 has two possible (i.e. divergent) successors sets. The first
3196 holds one element, whereas the second holds three (i.e. the changeset has
3196 holds one element, whereas the second holds three (i.e. the changeset has
3197 been split).
3197 been split).
3198 """
3198 """
3199 # passed to successorssets caching computation from one call to another
3199 # passed to successorssets caching computation from one call to another
3200 cache = {}
3200 cache = {}
3201 ctx2str = str
3201 ctx2str = str
3202 node2str = short
3202 node2str = short
3203 if ui.debug():
3203 if ui.debug():
3204 def ctx2str(ctx):
3204 def ctx2str(ctx):
3205 return ctx.hex()
3205 return ctx.hex()
3206 node2str = hex
3206 node2str = hex
3207 for rev in scmutil.revrange(repo, revs):
3207 for rev in scmutil.revrange(repo, revs):
3208 ctx = repo[rev]
3208 ctx = repo[rev]
3209 ui.write('%s\n'% ctx2str(ctx))
3209 ui.write('%s\n'% ctx2str(ctx))
3210 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3210 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3211 if succsset:
3211 if succsset:
3212 ui.write(' ')
3212 ui.write(' ')
3213 ui.write(node2str(succsset[0]))
3213 ui.write(node2str(succsset[0]))
3214 for node in succsset[1:]:
3214 for node in succsset[1:]:
3215 ui.write(' ')
3215 ui.write(' ')
3216 ui.write(node2str(node))
3216 ui.write(node2str(node))
3217 ui.write('\n')
3217 ui.write('\n')
3218
3218
3219 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3219 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3220 def debugwalk(ui, repo, *pats, **opts):
3220 def debugwalk(ui, repo, *pats, **opts):
3221 """show how files match on given patterns"""
3221 """show how files match on given patterns"""
3222 m = scmutil.match(repo[None], pats, opts)
3222 m = scmutil.match(repo[None], pats, opts)
3223 items = list(repo.walk(m))
3223 items = list(repo.walk(m))
3224 if not items:
3224 if not items:
3225 return
3225 return
3226 f = lambda fn: fn
3226 f = lambda fn: fn
3227 if ui.configbool('ui', 'slash') and os.sep != '/':
3227 if ui.configbool('ui', 'slash') and os.sep != '/':
3228 f = lambda fn: util.normpath(fn)
3228 f = lambda fn: util.normpath(fn)
3229 fmt = 'f %%-%ds %%-%ds %%s' % (
3229 fmt = 'f %%-%ds %%-%ds %%s' % (
3230 max([len(abs) for abs in items]),
3230 max([len(abs) for abs in items]),
3231 max([len(m.rel(abs)) for abs in items]))
3231 max([len(m.rel(abs)) for abs in items]))
3232 for abs in items:
3232 for abs in items:
3233 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3233 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3234 ui.write("%s\n" % line.rstrip())
3234 ui.write("%s\n" % line.rstrip())
3235
3235
3236 @command('debugwireargs',
3236 @command('debugwireargs',
3237 [('', 'three', '', 'three'),
3237 [('', 'three', '', 'three'),
3238 ('', 'four', '', 'four'),
3238 ('', 'four', '', 'four'),
3239 ('', 'five', '', 'five'),
3239 ('', 'five', '', 'five'),
3240 ] + remoteopts,
3240 ] + remoteopts,
3241 _('REPO [OPTIONS]... [ONE [TWO]]'),
3241 _('REPO [OPTIONS]... [ONE [TWO]]'),
3242 norepo=True)
3242 norepo=True)
3243 def debugwireargs(ui, repopath, *vals, **opts):
3243 def debugwireargs(ui, repopath, *vals, **opts):
3244 repo = hg.peer(ui, opts, repopath)
3244 repo = hg.peer(ui, opts, repopath)
3245 for opt in remoteopts:
3245 for opt in remoteopts:
3246 del opts[opt[1]]
3246 del opts[opt[1]]
3247 args = {}
3247 args = {}
3248 for k, v in opts.iteritems():
3248 for k, v in opts.iteritems():
3249 if v:
3249 if v:
3250 args[k] = v
3250 args[k] = v
3251 # run twice to check that we don't mess up the stream for the next command
3251 # run twice to check that we don't mess up the stream for the next command
3252 res1 = repo.debugwireargs(*vals, **args)
3252 res1 = repo.debugwireargs(*vals, **args)
3253 res2 = repo.debugwireargs(*vals, **args)
3253 res2 = repo.debugwireargs(*vals, **args)
3254 ui.write("%s\n" % res1)
3254 ui.write("%s\n" % res1)
3255 if res1 != res2:
3255 if res1 != res2:
3256 ui.warn("%s\n" % res2)
3256 ui.warn("%s\n" % res2)
3257
3257
3258 @command('^diff',
3258 @command('^diff',
3259 [('r', 'rev', [], _('revision'), _('REV')),
3259 [('r', 'rev', [], _('revision'), _('REV')),
3260 ('c', 'change', '', _('change made by revision'), _('REV'))
3260 ('c', 'change', '', _('change made by revision'), _('REV'))
3261 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3261 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3262 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3262 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3263 inferrepo=True)
3263 inferrepo=True)
3264 def diff(ui, repo, *pats, **opts):
3264 def diff(ui, repo, *pats, **opts):
3265 """diff repository (or selected files)
3265 """diff repository (or selected files)
3266
3266
3267 Show differences between revisions for the specified files.
3267 Show differences between revisions for the specified files.
3268
3268
3269 Differences between files are shown using the unified diff format.
3269 Differences between files are shown using the unified diff format.
3270
3270
3271 .. note::
3271 .. note::
3272
3272
3273 diff may generate unexpected results for merges, as it will
3273 diff may generate unexpected results for merges, as it will
3274 default to comparing against the working directory's first
3274 default to comparing against the working directory's first
3275 parent changeset if no revisions are specified.
3275 parent changeset if no revisions are specified.
3276
3276
3277 When two revision arguments are given, then changes are shown
3277 When two revision arguments are given, then changes are shown
3278 between those revisions. If only one revision is specified then
3278 between those revisions. If only one revision is specified then
3279 that revision is compared to the working directory, and, when no
3279 that revision is compared to the working directory, and, when no
3280 revisions are specified, the working directory files are compared
3280 revisions are specified, the working directory files are compared
3281 to its parent.
3281 to its parent.
3282
3282
3283 Alternatively you can specify -c/--change with a revision to see
3283 Alternatively you can specify -c/--change with a revision to see
3284 the changes in that changeset relative to its first parent.
3284 the changes in that changeset relative to its first parent.
3285
3285
3286 Without the -a/--text option, diff will avoid generating diffs of
3286 Without the -a/--text option, diff will avoid generating diffs of
3287 files it detects as binary. With -a, diff will generate a diff
3287 files it detects as binary. With -a, diff will generate a diff
3288 anyway, probably with undesirable results.
3288 anyway, probably with undesirable results.
3289
3289
3290 Use the -g/--git option to generate diffs in the git extended diff
3290 Use the -g/--git option to generate diffs in the git extended diff
3291 format. For more information, read :hg:`help diffs`.
3291 format. For more information, read :hg:`help diffs`.
3292
3292
3293 .. container:: verbose
3293 .. container:: verbose
3294
3294
3295 Examples:
3295 Examples:
3296
3296
3297 - compare a file in the current working directory to its parent::
3297 - compare a file in the current working directory to its parent::
3298
3298
3299 hg diff foo.c
3299 hg diff foo.c
3300
3300
3301 - compare two historical versions of a directory, with rename info::
3301 - compare two historical versions of a directory, with rename info::
3302
3302
3303 hg diff --git -r 1.0:1.2 lib/
3303 hg diff --git -r 1.0:1.2 lib/
3304
3304
3305 - get change stats relative to the last change on some date::
3305 - get change stats relative to the last change on some date::
3306
3306
3307 hg diff --stat -r "date('may 2')"
3307 hg diff --stat -r "date('may 2')"
3308
3308
3309 - diff all newly-added files that contain a keyword::
3309 - diff all newly-added files that contain a keyword::
3310
3310
3311 hg diff "set:added() and grep(GNU)"
3311 hg diff "set:added() and grep(GNU)"
3312
3312
3313 - compare a revision and its parents::
3313 - compare a revision and its parents::
3314
3314
3315 hg diff -c 9353 # compare against first parent
3315 hg diff -c 9353 # compare against first parent
3316 hg diff -r 9353^:9353 # same using revset syntax
3316 hg diff -r 9353^:9353 # same using revset syntax
3317 hg diff -r 9353^2:9353 # compare against the second parent
3317 hg diff -r 9353^2:9353 # compare against the second parent
3318
3318
3319 Returns 0 on success.
3319 Returns 0 on success.
3320 """
3320 """
3321
3321
3322 revs = opts.get('rev')
3322 revs = opts.get('rev')
3323 change = opts.get('change')
3323 change = opts.get('change')
3324 stat = opts.get('stat')
3324 stat = opts.get('stat')
3325 reverse = opts.get('reverse')
3325 reverse = opts.get('reverse')
3326
3326
3327 if revs and change:
3327 if revs and change:
3328 msg = _('cannot specify --rev and --change at the same time')
3328 msg = _('cannot specify --rev and --change at the same time')
3329 raise error.Abort(msg)
3329 raise error.Abort(msg)
3330 elif change:
3330 elif change:
3331 node2 = scmutil.revsingle(repo, change, None).node()
3331 node2 = scmutil.revsingle(repo, change, None).node()
3332 node1 = repo[node2].p1().node()
3332 node1 = repo[node2].p1().node()
3333 else:
3333 else:
3334 node1, node2 = scmutil.revpair(repo, revs)
3334 node1, node2 = scmutil.revpair(repo, revs)
3335
3335
3336 if reverse:
3336 if reverse:
3337 node1, node2 = node2, node1
3337 node1, node2 = node2, node1
3338
3338
3339 diffopts = patch.diffallopts(ui, opts)
3339 diffopts = patch.diffallopts(ui, opts)
3340 m = scmutil.match(repo[node2], pats, opts)
3340 m = scmutil.match(repo[node2], pats, opts)
3341 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3341 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3342 listsubrepos=opts.get('subrepos'),
3342 listsubrepos=opts.get('subrepos'),
3343 root=opts.get('root'))
3343 root=opts.get('root'))
3344
3344
3345 @command('^export',
3345 @command('^export',
3346 [('o', 'output', '',
3346 [('o', 'output', '',
3347 _('print output to file with formatted name'), _('FORMAT')),
3347 _('print output to file with formatted name'), _('FORMAT')),
3348 ('', 'switch-parent', None, _('diff against the second parent')),
3348 ('', 'switch-parent', None, _('diff against the second parent')),
3349 ('r', 'rev', [], _('revisions to export'), _('REV')),
3349 ('r', 'rev', [], _('revisions to export'), _('REV')),
3350 ] + diffopts,
3350 ] + diffopts,
3351 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3351 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3352 def export(ui, repo, *changesets, **opts):
3352 def export(ui, repo, *changesets, **opts):
3353 """dump the header and diffs for one or more changesets
3353 """dump the header and diffs for one or more changesets
3354
3354
3355 Print the changeset header and diffs for one or more revisions.
3355 Print the changeset header and diffs for one or more revisions.
3356 If no revision is given, the parent of the working directory is used.
3356 If no revision is given, the parent of the working directory is used.
3357
3357
3358 The information shown in the changeset header is: author, date,
3358 The information shown in the changeset header is: author, date,
3359 branch name (if non-default), changeset hash, parent(s) and commit
3359 branch name (if non-default), changeset hash, parent(s) and commit
3360 comment.
3360 comment.
3361
3361
3362 .. note::
3362 .. note::
3363
3363
3364 export may generate unexpected diff output for merge
3364 export may generate unexpected diff output for merge
3365 changesets, as it will compare the merge changeset against its
3365 changesets, as it will compare the merge changeset against its
3366 first parent only.
3366 first parent only.
3367
3367
3368 Output may be to a file, in which case the name of the file is
3368 Output may be to a file, in which case the name of the file is
3369 given using a format string. The formatting rules are as follows:
3369 given using a format string. The formatting rules are as follows:
3370
3370
3371 :``%%``: literal "%" character
3371 :``%%``: literal "%" character
3372 :``%H``: changeset hash (40 hexadecimal digits)
3372 :``%H``: changeset hash (40 hexadecimal digits)
3373 :``%N``: number of patches being generated
3373 :``%N``: number of patches being generated
3374 :``%R``: changeset revision number
3374 :``%R``: changeset revision number
3375 :``%b``: basename of the exporting repository
3375 :``%b``: basename of the exporting repository
3376 :``%h``: short-form changeset hash (12 hexadecimal digits)
3376 :``%h``: short-form changeset hash (12 hexadecimal digits)
3377 :``%m``: first line of the commit message (only alphanumeric characters)
3377 :``%m``: first line of the commit message (only alphanumeric characters)
3378 :``%n``: zero-padded sequence number, starting at 1
3378 :``%n``: zero-padded sequence number, starting at 1
3379 :``%r``: zero-padded changeset revision number
3379 :``%r``: zero-padded changeset revision number
3380
3380
3381 Without the -a/--text option, export will avoid generating diffs
3381 Without the -a/--text option, export will avoid generating diffs
3382 of files it detects as binary. With -a, export will generate a
3382 of files it detects as binary. With -a, export will generate a
3383 diff anyway, probably with undesirable results.
3383 diff anyway, probably with undesirable results.
3384
3384
3385 Use the -g/--git option to generate diffs in the git extended diff
3385 Use the -g/--git option to generate diffs in the git extended diff
3386 format. See :hg:`help diffs` for more information.
3386 format. See :hg:`help diffs` for more information.
3387
3387
3388 With the --switch-parent option, the diff will be against the
3388 With the --switch-parent option, the diff will be against the
3389 second parent. It can be useful to review a merge.
3389 second parent. It can be useful to review a merge.
3390
3390
3391 .. container:: verbose
3391 .. container:: verbose
3392
3392
3393 Examples:
3393 Examples:
3394
3394
3395 - use export and import to transplant a bugfix to the current
3395 - use export and import to transplant a bugfix to the current
3396 branch::
3396 branch::
3397
3397
3398 hg export -r 9353 | hg import -
3398 hg export -r 9353 | hg import -
3399
3399
3400 - export all the changesets between two revisions to a file with
3400 - export all the changesets between two revisions to a file with
3401 rename information::
3401 rename information::
3402
3402
3403 hg export --git -r 123:150 > changes.txt
3403 hg export --git -r 123:150 > changes.txt
3404
3404
3405 - split outgoing changes into a series of patches with
3405 - split outgoing changes into a series of patches with
3406 descriptive names::
3406 descriptive names::
3407
3407
3408 hg export -r "outgoing()" -o "%n-%m.patch"
3408 hg export -r "outgoing()" -o "%n-%m.patch"
3409
3409
3410 Returns 0 on success.
3410 Returns 0 on success.
3411 """
3411 """
3412 changesets += tuple(opts.get('rev', []))
3412 changesets += tuple(opts.get('rev', []))
3413 if not changesets:
3413 if not changesets:
3414 changesets = ['.']
3414 changesets = ['.']
3415 revs = scmutil.revrange(repo, changesets)
3415 revs = scmutil.revrange(repo, changesets)
3416 if not revs:
3416 if not revs:
3417 raise error.Abort(_("export requires at least one changeset"))
3417 raise error.Abort(_("export requires at least one changeset"))
3418 if len(revs) > 1:
3418 if len(revs) > 1:
3419 ui.note(_('exporting patches:\n'))
3419 ui.note(_('exporting patches:\n'))
3420 else:
3420 else:
3421 ui.note(_('exporting patch:\n'))
3421 ui.note(_('exporting patch:\n'))
3422 cmdutil.export(repo, revs, template=opts.get('output'),
3422 cmdutil.export(repo, revs, template=opts.get('output'),
3423 switch_parent=opts.get('switch_parent'),
3423 switch_parent=opts.get('switch_parent'),
3424 opts=patch.diffallopts(ui, opts))
3424 opts=patch.diffallopts(ui, opts))
3425
3425
3426 @command('files',
3426 @command('files',
3427 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3427 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3428 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3428 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3429 ] + walkopts + formatteropts + subrepoopts,
3429 ] + walkopts + formatteropts + subrepoopts,
3430 _('[OPTION]... [PATTERN]...'))
3430 _('[OPTION]... [PATTERN]...'))
3431 def files(ui, repo, *pats, **opts):
3431 def files(ui, repo, *pats, **opts):
3432 """list tracked files
3432 """list tracked files
3433
3433
3434 Print files under Mercurial control in the working directory or
3434 Print files under Mercurial control in the working directory or
3435 specified revision whose names match the given patterns (excluding
3435 specified revision whose names match the given patterns (excluding
3436 removed files).
3436 removed files).
3437
3437
3438 If no patterns are given to match, this command prints the names
3438 If no patterns are given to match, this command prints the names
3439 of all files under Mercurial control in the working directory.
3439 of all files under Mercurial control in the working directory.
3440
3440
3441 .. container:: verbose
3441 .. container:: verbose
3442
3442
3443 Examples:
3443 Examples:
3444
3444
3445 - list all files under the current directory::
3445 - list all files under the current directory::
3446
3446
3447 hg files .
3447 hg files .
3448
3448
3449 - shows sizes and flags for current revision::
3449 - shows sizes and flags for current revision::
3450
3450
3451 hg files -vr .
3451 hg files -vr .
3452
3452
3453 - list all files named README::
3453 - list all files named README::
3454
3454
3455 hg files -I "**/README"
3455 hg files -I "**/README"
3456
3456
3457 - list all binary files::
3457 - list all binary files::
3458
3458
3459 hg files "set:binary()"
3459 hg files "set:binary()"
3460
3460
3461 - find files containing a regular expression::
3461 - find files containing a regular expression::
3462
3462
3463 hg files "set:grep('bob')"
3463 hg files "set:grep('bob')"
3464
3464
3465 - search tracked file contents with xargs and grep::
3465 - search tracked file contents with xargs and grep::
3466
3466
3467 hg files -0 | xargs -0 grep foo
3467 hg files -0 | xargs -0 grep foo
3468
3468
3469 See :hg:`help patterns` and :hg:`help filesets` for more information
3469 See :hg:`help patterns` and :hg:`help filesets` for more information
3470 on specifying file patterns.
3470 on specifying file patterns.
3471
3471
3472 Returns 0 if a match is found, 1 otherwise.
3472 Returns 0 if a match is found, 1 otherwise.
3473
3473
3474 """
3474 """
3475 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3475 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3476
3476
3477 end = '\n'
3477 end = '\n'
3478 if opts.get('print0'):
3478 if opts.get('print0'):
3479 end = '\0'
3479 end = '\0'
3480 fm = ui.formatter('files', opts)
3480 fm = ui.formatter('files', opts)
3481 fmt = '%s' + end
3481 fmt = '%s' + end
3482
3482
3483 m = scmutil.match(ctx, pats, opts)
3483 m = scmutil.match(ctx, pats, opts)
3484 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3484 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3485
3485
3486 fm.end()
3486 fm.end()
3487
3487
3488 return ret
3488 return ret
3489
3489
3490 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3490 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3491 def forget(ui, repo, *pats, **opts):
3491 def forget(ui, repo, *pats, **opts):
3492 """forget the specified files on the next commit
3492 """forget the specified files on the next commit
3493
3493
3494 Mark the specified files so they will no longer be tracked
3494 Mark the specified files so they will no longer be tracked
3495 after the next commit.
3495 after the next commit.
3496
3496
3497 This only removes files from the current branch, not from the
3497 This only removes files from the current branch, not from the
3498 entire project history, and it does not delete them from the
3498 entire project history, and it does not delete them from the
3499 working directory.
3499 working directory.
3500
3500
3501 To delete the file from the working directory, see :hg:`remove`.
3501 To delete the file from the working directory, see :hg:`remove`.
3502
3502
3503 To undo a forget before the next commit, see :hg:`add`.
3503 To undo a forget before the next commit, see :hg:`add`.
3504
3504
3505 .. container:: verbose
3505 .. container:: verbose
3506
3506
3507 Examples:
3507 Examples:
3508
3508
3509 - forget newly-added binary files::
3509 - forget newly-added binary files::
3510
3510
3511 hg forget "set:added() and binary()"
3511 hg forget "set:added() and binary()"
3512
3512
3513 - forget files that would be excluded by .hgignore::
3513 - forget files that would be excluded by .hgignore::
3514
3514
3515 hg forget "set:hgignore()"
3515 hg forget "set:hgignore()"
3516
3516
3517 Returns 0 on success.
3517 Returns 0 on success.
3518 """
3518 """
3519
3519
3520 if not pats:
3520 if not pats:
3521 raise error.Abort(_('no files specified'))
3521 raise error.Abort(_('no files specified'))
3522
3522
3523 m = scmutil.match(repo[None], pats, opts)
3523 m = scmutil.match(repo[None], pats, opts)
3524 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3524 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3525 return rejected and 1 or 0
3525 return rejected and 1 or 0
3526
3526
3527 @command(
3527 @command(
3528 'graft',
3528 'graft',
3529 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3529 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3530 ('c', 'continue', False, _('resume interrupted graft')),
3530 ('c', 'continue', False, _('resume interrupted graft')),
3531 ('e', 'edit', False, _('invoke editor on commit messages')),
3531 ('e', 'edit', False, _('invoke editor on commit messages')),
3532 ('', 'log', None, _('append graft info to log message')),
3532 ('', 'log', None, _('append graft info to log message')),
3533 ('f', 'force', False, _('force graft')),
3533 ('f', 'force', False, _('force graft')),
3534 ('D', 'currentdate', False,
3534 ('D', 'currentdate', False,
3535 _('record the current date as commit date')),
3535 _('record the current date as commit date')),
3536 ('U', 'currentuser', False,
3536 ('U', 'currentuser', False,
3537 _('record the current user as committer'), _('DATE'))]
3537 _('record the current user as committer'), _('DATE'))]
3538 + commitopts2 + mergetoolopts + dryrunopts,
3538 + commitopts2 + mergetoolopts + dryrunopts,
3539 _('[OPTION]... [-r] REV...'))
3539 _('[OPTION]... [-r] REV...'))
3540 def graft(ui, repo, *revs, **opts):
3540 def graft(ui, repo, *revs, **opts):
3541 '''copy changes from other branches onto the current branch
3541 '''copy changes from other branches onto the current branch
3542
3542
3543 This command uses Mercurial's merge logic to copy individual
3543 This command uses Mercurial's merge logic to copy individual
3544 changes from other branches without merging branches in the
3544 changes from other branches without merging branches in the
3545 history graph. This is sometimes known as 'backporting' or
3545 history graph. This is sometimes known as 'backporting' or
3546 'cherry-picking'. By default, graft will copy user, date, and
3546 'cherry-picking'. By default, graft will copy user, date, and
3547 description from the source changesets.
3547 description from the source changesets.
3548
3548
3549 Changesets that are ancestors of the current revision, that have
3549 Changesets that are ancestors of the current revision, that have
3550 already been grafted, or that are merges will be skipped.
3550 already been grafted, or that are merges will be skipped.
3551
3551
3552 If --log is specified, log messages will have a comment appended
3552 If --log is specified, log messages will have a comment appended
3553 of the form::
3553 of the form::
3554
3554
3555 (grafted from CHANGESETHASH)
3555 (grafted from CHANGESETHASH)
3556
3556
3557 If --force is specified, revisions will be grafted even if they
3557 If --force is specified, revisions will be grafted even if they
3558 are already ancestors of or have been grafted to the destination.
3558 are already ancestors of or have been grafted to the destination.
3559 This is useful when the revisions have since been backed out.
3559 This is useful when the revisions have since been backed out.
3560
3560
3561 If a graft merge results in conflicts, the graft process is
3561 If a graft merge results in conflicts, the graft process is
3562 interrupted so that the current merge can be manually resolved.
3562 interrupted so that the current merge can be manually resolved.
3563 Once all conflicts are addressed, the graft process can be
3563 Once all conflicts are addressed, the graft process can be
3564 continued with the -c/--continue option.
3564 continued with the -c/--continue option.
3565
3565
3566 .. note::
3566 .. note::
3567
3567
3568 The -c/--continue option does not reapply earlier options, except
3568 The -c/--continue option does not reapply earlier options, except
3569 for --force.
3569 for --force.
3570
3570
3571 .. container:: verbose
3571 .. container:: verbose
3572
3572
3573 Examples:
3573 Examples:
3574
3574
3575 - copy a single change to the stable branch and edit its description::
3575 - copy a single change to the stable branch and edit its description::
3576
3576
3577 hg update stable
3577 hg update stable
3578 hg graft --edit 9393
3578 hg graft --edit 9393
3579
3579
3580 - graft a range of changesets with one exception, updating dates::
3580 - graft a range of changesets with one exception, updating dates::
3581
3581
3582 hg graft -D "2085::2093 and not 2091"
3582 hg graft -D "2085::2093 and not 2091"
3583
3583
3584 - continue a graft after resolving conflicts::
3584 - continue a graft after resolving conflicts::
3585
3585
3586 hg graft -c
3586 hg graft -c
3587
3587
3588 - show the source of a grafted changeset::
3588 - show the source of a grafted changeset::
3589
3589
3590 hg log --debug -r .
3590 hg log --debug -r .
3591
3591
3592 See :hg:`help revisions` and :hg:`help revsets` for more about
3592 See :hg:`help revisions` and :hg:`help revsets` for more about
3593 specifying revisions.
3593 specifying revisions.
3594
3594
3595 Returns 0 on successful completion.
3595 Returns 0 on successful completion.
3596 '''
3596 '''
3597
3597
3598 revs = list(revs)
3598 revs = list(revs)
3599 revs.extend(opts['rev'])
3599 revs.extend(opts['rev'])
3600
3600
3601 if not opts.get('user') and opts.get('currentuser'):
3601 if not opts.get('user') and opts.get('currentuser'):
3602 opts['user'] = ui.username()
3602 opts['user'] = ui.username()
3603 if not opts.get('date') and opts.get('currentdate'):
3603 if not opts.get('date') and opts.get('currentdate'):
3604 opts['date'] = "%d %d" % util.makedate()
3604 opts['date'] = "%d %d" % util.makedate()
3605
3605
3606 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3606 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3607
3607
3608 cont = False
3608 cont = False
3609 if opts['continue']:
3609 if opts['continue']:
3610 cont = True
3610 cont = True
3611 if revs:
3611 if revs:
3612 raise error.Abort(_("can't specify --continue and revisions"))
3612 raise error.Abort(_("can't specify --continue and revisions"))
3613 # read in unfinished revisions
3613 # read in unfinished revisions
3614 try:
3614 try:
3615 nodes = repo.vfs.read('graftstate').splitlines()
3615 nodes = repo.vfs.read('graftstate').splitlines()
3616 revs = [repo[node].rev() for node in nodes]
3616 revs = [repo[node].rev() for node in nodes]
3617 except IOError as inst:
3617 except IOError as inst:
3618 if inst.errno != errno.ENOENT:
3618 if inst.errno != errno.ENOENT:
3619 raise
3619 raise
3620 raise error.Abort(_("no graft state found, can't continue"))
3620 raise error.Abort(_("no graft state found, can't continue"))
3621 else:
3621 else:
3622 cmdutil.checkunfinished(repo)
3622 cmdutil.checkunfinished(repo)
3623 cmdutil.bailifchanged(repo)
3623 cmdutil.bailifchanged(repo)
3624 if not revs:
3624 if not revs:
3625 raise error.Abort(_('no revisions specified'))
3625 raise error.Abort(_('no revisions specified'))
3626 revs = scmutil.revrange(repo, revs)
3626 revs = scmutil.revrange(repo, revs)
3627
3627
3628 skipped = set()
3628 skipped = set()
3629 # check for merges
3629 # check for merges
3630 for rev in repo.revs('%ld and merge()', revs):
3630 for rev in repo.revs('%ld and merge()', revs):
3631 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3631 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3632 skipped.add(rev)
3632 skipped.add(rev)
3633 revs = [r for r in revs if r not in skipped]
3633 revs = [r for r in revs if r not in skipped]
3634 if not revs:
3634 if not revs:
3635 return -1
3635 return -1
3636
3636
3637 # Don't check in the --continue case, in effect retaining --force across
3637 # Don't check in the --continue case, in effect retaining --force across
3638 # --continues. That's because without --force, any revisions we decided to
3638 # --continues. That's because without --force, any revisions we decided to
3639 # skip would have been filtered out here, so they wouldn't have made their
3639 # skip would have been filtered out here, so they wouldn't have made their
3640 # way to the graftstate. With --force, any revisions we would have otherwise
3640 # way to the graftstate. With --force, any revisions we would have otherwise
3641 # skipped would not have been filtered out, and if they hadn't been applied
3641 # skipped would not have been filtered out, and if they hadn't been applied
3642 # already, they'd have been in the graftstate.
3642 # already, they'd have been in the graftstate.
3643 if not (cont or opts.get('force')):
3643 if not (cont or opts.get('force')):
3644 # check for ancestors of dest branch
3644 # check for ancestors of dest branch
3645 crev = repo['.'].rev()
3645 crev = repo['.'].rev()
3646 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3646 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3647 # Cannot use x.remove(y) on smart set, this has to be a list.
3647 # Cannot use x.remove(y) on smart set, this has to be a list.
3648 # XXX make this lazy in the future
3648 # XXX make this lazy in the future
3649 revs = list(revs)
3649 revs = list(revs)
3650 # don't mutate while iterating, create a copy
3650 # don't mutate while iterating, create a copy
3651 for rev in list(revs):
3651 for rev in list(revs):
3652 if rev in ancestors:
3652 if rev in ancestors:
3653 ui.warn(_('skipping ancestor revision %d:%s\n') %
3653 ui.warn(_('skipping ancestor revision %d:%s\n') %
3654 (rev, repo[rev]))
3654 (rev, repo[rev]))
3655 # XXX remove on list is slow
3655 # XXX remove on list is slow
3656 revs.remove(rev)
3656 revs.remove(rev)
3657 if not revs:
3657 if not revs:
3658 return -1
3658 return -1
3659
3659
3660 # analyze revs for earlier grafts
3660 # analyze revs for earlier grafts
3661 ids = {}
3661 ids = {}
3662 for ctx in repo.set("%ld", revs):
3662 for ctx in repo.set("%ld", revs):
3663 ids[ctx.hex()] = ctx.rev()
3663 ids[ctx.hex()] = ctx.rev()
3664 n = ctx.extra().get('source')
3664 n = ctx.extra().get('source')
3665 if n:
3665 if n:
3666 ids[n] = ctx.rev()
3666 ids[n] = ctx.rev()
3667
3667
3668 # check ancestors for earlier grafts
3668 # check ancestors for earlier grafts
3669 ui.debug('scanning for duplicate grafts\n')
3669 ui.debug('scanning for duplicate grafts\n')
3670
3670
3671 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3671 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3672 ctx = repo[rev]
3672 ctx = repo[rev]
3673 n = ctx.extra().get('source')
3673 n = ctx.extra().get('source')
3674 if n in ids:
3674 if n in ids:
3675 try:
3675 try:
3676 r = repo[n].rev()
3676 r = repo[n].rev()
3677 except error.RepoLookupError:
3677 except error.RepoLookupError:
3678 r = None
3678 r = None
3679 if r in revs:
3679 if r in revs:
3680 ui.warn(_('skipping revision %d:%s '
3680 ui.warn(_('skipping revision %d:%s '
3681 '(already grafted to %d:%s)\n')
3681 '(already grafted to %d:%s)\n')
3682 % (r, repo[r], rev, ctx))
3682 % (r, repo[r], rev, ctx))
3683 revs.remove(r)
3683 revs.remove(r)
3684 elif ids[n] in revs:
3684 elif ids[n] in revs:
3685 if r is None:
3685 if r is None:
3686 ui.warn(_('skipping already grafted revision %d:%s '
3686 ui.warn(_('skipping already grafted revision %d:%s '
3687 '(%d:%s also has unknown origin %s)\n')
3687 '(%d:%s also has unknown origin %s)\n')
3688 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3688 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3689 else:
3689 else:
3690 ui.warn(_('skipping already grafted revision %d:%s '
3690 ui.warn(_('skipping already grafted revision %d:%s '
3691 '(%d:%s also has origin %d:%s)\n')
3691 '(%d:%s also has origin %d:%s)\n')
3692 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3692 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3693 revs.remove(ids[n])
3693 revs.remove(ids[n])
3694 elif ctx.hex() in ids:
3694 elif ctx.hex() in ids:
3695 r = ids[ctx.hex()]
3695 r = ids[ctx.hex()]
3696 ui.warn(_('skipping already grafted revision %d:%s '
3696 ui.warn(_('skipping already grafted revision %d:%s '
3697 '(was grafted from %d:%s)\n') %
3697 '(was grafted from %d:%s)\n') %
3698 (r, repo[r], rev, ctx))
3698 (r, repo[r], rev, ctx))
3699 revs.remove(r)
3699 revs.remove(r)
3700 if not revs:
3700 if not revs:
3701 return -1
3701 return -1
3702
3702
3703 wlock = repo.wlock()
3703 wlock = repo.wlock()
3704 try:
3704 try:
3705 for pos, ctx in enumerate(repo.set("%ld", revs)):
3705 for pos, ctx in enumerate(repo.set("%ld", revs)):
3706 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3706 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3707 ctx.description().split('\n', 1)[0])
3707 ctx.description().split('\n', 1)[0])
3708 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3708 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3709 if names:
3709 if names:
3710 desc += ' (%s)' % ' '.join(names)
3710 desc += ' (%s)' % ' '.join(names)
3711 ui.status(_('grafting %s\n') % desc)
3711 ui.status(_('grafting %s\n') % desc)
3712 if opts.get('dry_run'):
3712 if opts.get('dry_run'):
3713 continue
3713 continue
3714
3714
3715 source = ctx.extra().get('source')
3715 source = ctx.extra().get('source')
3716 extra = {}
3716 extra = {}
3717 if source:
3717 if source:
3718 extra['source'] = source
3718 extra['source'] = source
3719 extra['intermediate-source'] = ctx.hex()
3719 extra['intermediate-source'] = ctx.hex()
3720 else:
3720 else:
3721 extra['source'] = ctx.hex()
3721 extra['source'] = ctx.hex()
3722 user = ctx.user()
3722 user = ctx.user()
3723 if opts.get('user'):
3723 if opts.get('user'):
3724 user = opts['user']
3724 user = opts['user']
3725 date = ctx.date()
3725 date = ctx.date()
3726 if opts.get('date'):
3726 if opts.get('date'):
3727 date = opts['date']
3727 date = opts['date']
3728 message = ctx.description()
3728 message = ctx.description()
3729 if opts.get('log'):
3729 if opts.get('log'):
3730 message += '\n(grafted from %s)' % ctx.hex()
3730 message += '\n(grafted from %s)' % ctx.hex()
3731
3731
3732 # we don't merge the first commit when continuing
3732 # we don't merge the first commit when continuing
3733 if not cont:
3733 if not cont:
3734 # perform the graft merge with p1(rev) as 'ancestor'
3734 # perform the graft merge with p1(rev) as 'ancestor'
3735 try:
3735 try:
3736 # ui.forcemerge is an internal variable, do not document
3736 # ui.forcemerge is an internal variable, do not document
3737 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3737 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3738 'graft')
3738 'graft')
3739 stats = mergemod.graft(repo, ctx, ctx.p1(),
3739 stats = mergemod.graft(repo, ctx, ctx.p1(),
3740 ['local', 'graft'])
3740 ['local', 'graft'])
3741 finally:
3741 finally:
3742 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3742 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3743 # report any conflicts
3743 # report any conflicts
3744 if stats and stats[3] > 0:
3744 if stats and stats[3] > 0:
3745 # write out state for --continue
3745 # write out state for --continue
3746 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3746 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3747 repo.vfs.write('graftstate', ''.join(nodelines))
3747 repo.vfs.write('graftstate', ''.join(nodelines))
3748 raise error.Abort(
3748 raise error.Abort(
3749 _("unresolved conflicts, can't continue"),
3749 _("unresolved conflicts, can't continue"),
3750 hint=_('use hg resolve and hg graft --continue'))
3750 hint=_('use hg resolve and hg graft --continue'))
3751 else:
3751 else:
3752 cont = False
3752 cont = False
3753
3753
3754 # commit
3754 # commit
3755 node = repo.commit(text=message, user=user,
3755 node = repo.commit(text=message, user=user,
3756 date=date, extra=extra, editor=editor)
3756 date=date, extra=extra, editor=editor)
3757 if node is None:
3757 if node is None:
3758 ui.warn(
3758 ui.warn(
3759 _('note: graft of %d:%s created no changes to commit\n') %
3759 _('note: graft of %d:%s created no changes to commit\n') %
3760 (ctx.rev(), ctx))
3760 (ctx.rev(), ctx))
3761 finally:
3761 finally:
3762 wlock.release()
3762 wlock.release()
3763
3763
3764 # remove state when we complete successfully
3764 # remove state when we complete successfully
3765 if not opts.get('dry_run'):
3765 if not opts.get('dry_run'):
3766 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3766 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3767
3767
3768 return 0
3768 return 0
3769
3769
3770 @command('grep',
3770 @command('grep',
3771 [('0', 'print0', None, _('end fields with NUL')),
3771 [('0', 'print0', None, _('end fields with NUL')),
3772 ('', 'all', None, _('print all revisions that match')),
3772 ('', 'all', None, _('print all revisions that match')),
3773 ('a', 'text', None, _('treat all files as text')),
3773 ('a', 'text', None, _('treat all files as text')),
3774 ('f', 'follow', None,
3774 ('f', 'follow', None,
3775 _('follow changeset history,'
3775 _('follow changeset history,'
3776 ' or file history across copies and renames')),
3776 ' or file history across copies and renames')),
3777 ('i', 'ignore-case', None, _('ignore case when matching')),
3777 ('i', 'ignore-case', None, _('ignore case when matching')),
3778 ('l', 'files-with-matches', None,
3778 ('l', 'files-with-matches', None,
3779 _('print only filenames and revisions that match')),
3779 _('print only filenames and revisions that match')),
3780 ('n', 'line-number', None, _('print matching line numbers')),
3780 ('n', 'line-number', None, _('print matching line numbers')),
3781 ('r', 'rev', [],
3781 ('r', 'rev', [],
3782 _('only search files changed within revision range'), _('REV')),
3782 _('only search files changed within revision range'), _('REV')),
3783 ('u', 'user', None, _('list the author (long with -v)')),
3783 ('u', 'user', None, _('list the author (long with -v)')),
3784 ('d', 'date', None, _('list the date (short with -q)')),
3784 ('d', 'date', None, _('list the date (short with -q)')),
3785 ] + walkopts,
3785 ] + walkopts,
3786 _('[OPTION]... PATTERN [FILE]...'),
3786 _('[OPTION]... PATTERN [FILE]...'),
3787 inferrepo=True)
3787 inferrepo=True)
3788 def grep(ui, repo, pattern, *pats, **opts):
3788 def grep(ui, repo, pattern, *pats, **opts):
3789 """search for a pattern in specified files and revisions
3789 """search for a pattern in specified files and revisions
3790
3790
3791 Search revisions of files for a regular expression.
3791 Search revisions of files for a regular expression.
3792
3792
3793 This command behaves differently than Unix grep. It only accepts
3793 This command behaves differently than Unix grep. It only accepts
3794 Python/Perl regexps. It searches repository history, not the
3794 Python/Perl regexps. It searches repository history, not the
3795 working directory. It always prints the revision number in which a
3795 working directory. It always prints the revision number in which a
3796 match appears.
3796 match appears.
3797
3797
3798 By default, grep only prints output for the first revision of a
3798 By default, grep only prints output for the first revision of a
3799 file in which it finds a match. To get it to print every revision
3799 file in which it finds a match. To get it to print every revision
3800 that contains a change in match status ("-" for a match that
3800 that contains a change in match status ("-" for a match that
3801 becomes a non-match, or "+" for a non-match that becomes a match),
3801 becomes a non-match, or "+" for a non-match that becomes a match),
3802 use the --all flag.
3802 use the --all flag.
3803
3803
3804 Returns 0 if a match is found, 1 otherwise.
3804 Returns 0 if a match is found, 1 otherwise.
3805 """
3805 """
3806 reflags = re.M
3806 reflags = re.M
3807 if opts.get('ignore_case'):
3807 if opts.get('ignore_case'):
3808 reflags |= re.I
3808 reflags |= re.I
3809 try:
3809 try:
3810 regexp = util.re.compile(pattern, reflags)
3810 regexp = util.re.compile(pattern, reflags)
3811 except re.error as inst:
3811 except re.error as inst:
3812 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3812 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3813 return 1
3813 return 1
3814 sep, eol = ':', '\n'
3814 sep, eol = ':', '\n'
3815 if opts.get('print0'):
3815 if opts.get('print0'):
3816 sep = eol = '\0'
3816 sep = eol = '\0'
3817
3817
3818 getfile = util.lrucachefunc(repo.file)
3818 getfile = util.lrucachefunc(repo.file)
3819
3819
3820 def matchlines(body):
3820 def matchlines(body):
3821 begin = 0
3821 begin = 0
3822 linenum = 0
3822 linenum = 0
3823 while begin < len(body):
3823 while begin < len(body):
3824 match = regexp.search(body, begin)
3824 match = regexp.search(body, begin)
3825 if not match:
3825 if not match:
3826 break
3826 break
3827 mstart, mend = match.span()
3827 mstart, mend = match.span()
3828 linenum += body.count('\n', begin, mstart) + 1
3828 linenum += body.count('\n', begin, mstart) + 1
3829 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3829 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3830 begin = body.find('\n', mend) + 1 or len(body) + 1
3830 begin = body.find('\n', mend) + 1 or len(body) + 1
3831 lend = begin - 1
3831 lend = begin - 1
3832 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3832 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3833
3833
3834 class linestate(object):
3834 class linestate(object):
3835 def __init__(self, line, linenum, colstart, colend):
3835 def __init__(self, line, linenum, colstart, colend):
3836 self.line = line
3836 self.line = line
3837 self.linenum = linenum
3837 self.linenum = linenum
3838 self.colstart = colstart
3838 self.colstart = colstart
3839 self.colend = colend
3839 self.colend = colend
3840
3840
3841 def __hash__(self):
3841 def __hash__(self):
3842 return hash((self.linenum, self.line))
3842 return hash((self.linenum, self.line))
3843
3843
3844 def __eq__(self, other):
3844 def __eq__(self, other):
3845 return self.line == other.line
3845 return self.line == other.line
3846
3846
3847 def __iter__(self):
3847 def __iter__(self):
3848 yield (self.line[:self.colstart], '')
3848 yield (self.line[:self.colstart], '')
3849 yield (self.line[self.colstart:self.colend], 'grep.match')
3849 yield (self.line[self.colstart:self.colend], 'grep.match')
3850 rest = self.line[self.colend:]
3850 rest = self.line[self.colend:]
3851 while rest != '':
3851 while rest != '':
3852 match = regexp.search(rest)
3852 match = regexp.search(rest)
3853 if not match:
3853 if not match:
3854 yield (rest, '')
3854 yield (rest, '')
3855 break
3855 break
3856 mstart, mend = match.span()
3856 mstart, mend = match.span()
3857 yield (rest[:mstart], '')
3857 yield (rest[:mstart], '')
3858 yield (rest[mstart:mend], 'grep.match')
3858 yield (rest[mstart:mend], 'grep.match')
3859 rest = rest[mend:]
3859 rest = rest[mend:]
3860
3860
3861 matches = {}
3861 matches = {}
3862 copies = {}
3862 copies = {}
3863 def grepbody(fn, rev, body):
3863 def grepbody(fn, rev, body):
3864 matches[rev].setdefault(fn, [])
3864 matches[rev].setdefault(fn, [])
3865 m = matches[rev][fn]
3865 m = matches[rev][fn]
3866 for lnum, cstart, cend, line in matchlines(body):
3866 for lnum, cstart, cend, line in matchlines(body):
3867 s = linestate(line, lnum, cstart, cend)
3867 s = linestate(line, lnum, cstart, cend)
3868 m.append(s)
3868 m.append(s)
3869
3869
3870 def difflinestates(a, b):
3870 def difflinestates(a, b):
3871 sm = difflib.SequenceMatcher(None, a, b)
3871 sm = difflib.SequenceMatcher(None, a, b)
3872 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3872 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3873 if tag == 'insert':
3873 if tag == 'insert':
3874 for i in xrange(blo, bhi):
3874 for i in xrange(blo, bhi):
3875 yield ('+', b[i])
3875 yield ('+', b[i])
3876 elif tag == 'delete':
3876 elif tag == 'delete':
3877 for i in xrange(alo, ahi):
3877 for i in xrange(alo, ahi):
3878 yield ('-', a[i])
3878 yield ('-', a[i])
3879 elif tag == 'replace':
3879 elif tag == 'replace':
3880 for i in xrange(alo, ahi):
3880 for i in xrange(alo, ahi):
3881 yield ('-', a[i])
3881 yield ('-', a[i])
3882 for i in xrange(blo, bhi):
3882 for i in xrange(blo, bhi):
3883 yield ('+', b[i])
3883 yield ('+', b[i])
3884
3884
3885 def display(fn, ctx, pstates, states):
3885 def display(fn, ctx, pstates, states):
3886 rev = ctx.rev()
3886 rev = ctx.rev()
3887 if ui.quiet:
3887 if ui.quiet:
3888 datefunc = util.shortdate
3888 datefunc = util.shortdate
3889 else:
3889 else:
3890 datefunc = util.datestr
3890 datefunc = util.datestr
3891 found = False
3891 found = False
3892 @util.cachefunc
3892 @util.cachefunc
3893 def binary():
3893 def binary():
3894 flog = getfile(fn)
3894 flog = getfile(fn)
3895 return util.binary(flog.read(ctx.filenode(fn)))
3895 return util.binary(flog.read(ctx.filenode(fn)))
3896
3896
3897 if opts.get('all'):
3897 if opts.get('all'):
3898 iter = difflinestates(pstates, states)
3898 iter = difflinestates(pstates, states)
3899 else:
3899 else:
3900 iter = [('', l) for l in states]
3900 iter = [('', l) for l in states]
3901 for change, l in iter:
3901 for change, l in iter:
3902 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3902 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3903
3903
3904 if opts.get('line_number'):
3904 if opts.get('line_number'):
3905 cols.append((str(l.linenum), 'grep.linenumber'))
3905 cols.append((str(l.linenum), 'grep.linenumber'))
3906 if opts.get('all'):
3906 if opts.get('all'):
3907 cols.append((change, 'grep.change'))
3907 cols.append((change, 'grep.change'))
3908 if opts.get('user'):
3908 if opts.get('user'):
3909 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3909 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3910 if opts.get('date'):
3910 if opts.get('date'):
3911 cols.append((datefunc(ctx.date()), 'grep.date'))
3911 cols.append((datefunc(ctx.date()), 'grep.date'))
3912 for col, label in cols[:-1]:
3912 for col, label in cols[:-1]:
3913 ui.write(col, label=label)
3913 ui.write(col, label=label)
3914 ui.write(sep, label='grep.sep')
3914 ui.write(sep, label='grep.sep')
3915 ui.write(cols[-1][0], label=cols[-1][1])
3915 ui.write(cols[-1][0], label=cols[-1][1])
3916 if not opts.get('files_with_matches'):
3916 if not opts.get('files_with_matches'):
3917 ui.write(sep, label='grep.sep')
3917 ui.write(sep, label='grep.sep')
3918 if not opts.get('text') and binary():
3918 if not opts.get('text') and binary():
3919 ui.write(" Binary file matches")
3919 ui.write(" Binary file matches")
3920 else:
3920 else:
3921 for s, label in l:
3921 for s, label in l:
3922 ui.write(s, label=label)
3922 ui.write(s, label=label)
3923 ui.write(eol)
3923 ui.write(eol)
3924 found = True
3924 found = True
3925 if opts.get('files_with_matches'):
3925 if opts.get('files_with_matches'):
3926 break
3926 break
3927 return found
3927 return found
3928
3928
3929 skip = {}
3929 skip = {}
3930 revfiles = {}
3930 revfiles = {}
3931 matchfn = scmutil.match(repo[None], pats, opts)
3931 matchfn = scmutil.match(repo[None], pats, opts)
3932 found = False
3932 found = False
3933 follow = opts.get('follow')
3933 follow = opts.get('follow')
3934
3934
3935 def prep(ctx, fns):
3935 def prep(ctx, fns):
3936 rev = ctx.rev()
3936 rev = ctx.rev()
3937 pctx = ctx.p1()
3937 pctx = ctx.p1()
3938 parent = pctx.rev()
3938 parent = pctx.rev()
3939 matches.setdefault(rev, {})
3939 matches.setdefault(rev, {})
3940 matches.setdefault(parent, {})
3940 matches.setdefault(parent, {})
3941 files = revfiles.setdefault(rev, [])
3941 files = revfiles.setdefault(rev, [])
3942 for fn in fns:
3942 for fn in fns:
3943 flog = getfile(fn)
3943 flog = getfile(fn)
3944 try:
3944 try:
3945 fnode = ctx.filenode(fn)
3945 fnode = ctx.filenode(fn)
3946 except error.LookupError:
3946 except error.LookupError:
3947 continue
3947 continue
3948
3948
3949 copied = flog.renamed(fnode)
3949 copied = flog.renamed(fnode)
3950 copy = follow and copied and copied[0]
3950 copy = follow and copied and copied[0]
3951 if copy:
3951 if copy:
3952 copies.setdefault(rev, {})[fn] = copy
3952 copies.setdefault(rev, {})[fn] = copy
3953 if fn in skip:
3953 if fn in skip:
3954 if copy:
3954 if copy:
3955 skip[copy] = True
3955 skip[copy] = True
3956 continue
3956 continue
3957 files.append(fn)
3957 files.append(fn)
3958
3958
3959 if fn not in matches[rev]:
3959 if fn not in matches[rev]:
3960 grepbody(fn, rev, flog.read(fnode))
3960 grepbody(fn, rev, flog.read(fnode))
3961
3961
3962 pfn = copy or fn
3962 pfn = copy or fn
3963 if pfn not in matches[parent]:
3963 if pfn not in matches[parent]:
3964 try:
3964 try:
3965 fnode = pctx.filenode(pfn)
3965 fnode = pctx.filenode(pfn)
3966 grepbody(pfn, parent, flog.read(fnode))
3966 grepbody(pfn, parent, flog.read(fnode))
3967 except error.LookupError:
3967 except error.LookupError:
3968 pass
3968 pass
3969
3969
3970 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3970 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3971 rev = ctx.rev()
3971 rev = ctx.rev()
3972 parent = ctx.p1().rev()
3972 parent = ctx.p1().rev()
3973 for fn in sorted(revfiles.get(rev, [])):
3973 for fn in sorted(revfiles.get(rev, [])):
3974 states = matches[rev][fn]
3974 states = matches[rev][fn]
3975 copy = copies.get(rev, {}).get(fn)
3975 copy = copies.get(rev, {}).get(fn)
3976 if fn in skip:
3976 if fn in skip:
3977 if copy:
3977 if copy:
3978 skip[copy] = True
3978 skip[copy] = True
3979 continue
3979 continue
3980 pstates = matches.get(parent, {}).get(copy or fn, [])
3980 pstates = matches.get(parent, {}).get(copy or fn, [])
3981 if pstates or states:
3981 if pstates or states:
3982 r = display(fn, ctx, pstates, states)
3982 r = display(fn, ctx, pstates, states)
3983 found = found or r
3983 found = found or r
3984 if r and not opts.get('all'):
3984 if r and not opts.get('all'):
3985 skip[fn] = True
3985 skip[fn] = True
3986 if copy:
3986 if copy:
3987 skip[copy] = True
3987 skip[copy] = True
3988 del matches[rev]
3988 del matches[rev]
3989 del revfiles[rev]
3989 del revfiles[rev]
3990
3990
3991 return not found
3991 return not found
3992
3992
3993 @command('heads',
3993 @command('heads',
3994 [('r', 'rev', '',
3994 [('r', 'rev', '',
3995 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3995 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3996 ('t', 'topo', False, _('show topological heads only')),
3996 ('t', 'topo', False, _('show topological heads only')),
3997 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3997 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3998 ('c', 'closed', False, _('show normal and closed branch heads')),
3998 ('c', 'closed', False, _('show normal and closed branch heads')),
3999 ] + templateopts,
3999 ] + templateopts,
4000 _('[-ct] [-r STARTREV] [REV]...'))
4000 _('[-ct] [-r STARTREV] [REV]...'))
4001 def heads(ui, repo, *branchrevs, **opts):
4001 def heads(ui, repo, *branchrevs, **opts):
4002 """show branch heads
4002 """show branch heads
4003
4003
4004 With no arguments, show all open branch heads in the repository.
4004 With no arguments, show all open branch heads in the repository.
4005 Branch heads are changesets that have no descendants on the
4005 Branch heads are changesets that have no descendants on the
4006 same branch. They are where development generally takes place and
4006 same branch. They are where development generally takes place and
4007 are the usual targets for update and merge operations.
4007 are the usual targets for update and merge operations.
4008
4008
4009 If one or more REVs are given, only open branch heads on the
4009 If one or more REVs are given, only open branch heads on the
4010 branches associated with the specified changesets are shown. This
4010 branches associated with the specified changesets are shown. This
4011 means that you can use :hg:`heads .` to see the heads on the
4011 means that you can use :hg:`heads .` to see the heads on the
4012 currently checked-out branch.
4012 currently checked-out branch.
4013
4013
4014 If -c/--closed is specified, also show branch heads marked closed
4014 If -c/--closed is specified, also show branch heads marked closed
4015 (see :hg:`commit --close-branch`).
4015 (see :hg:`commit --close-branch`).
4016
4016
4017 If STARTREV is specified, only those heads that are descendants of
4017 If STARTREV is specified, only those heads that are descendants of
4018 STARTREV will be displayed.
4018 STARTREV will be displayed.
4019
4019
4020 If -t/--topo is specified, named branch mechanics will be ignored and only
4020 If -t/--topo is specified, named branch mechanics will be ignored and only
4021 topological heads (changesets with no children) will be shown.
4021 topological heads (changesets with no children) will be shown.
4022
4022
4023 Returns 0 if matching heads are found, 1 if not.
4023 Returns 0 if matching heads are found, 1 if not.
4024 """
4024 """
4025
4025
4026 start = None
4026 start = None
4027 if 'rev' in opts:
4027 if 'rev' in opts:
4028 start = scmutil.revsingle(repo, opts['rev'], None).node()
4028 start = scmutil.revsingle(repo, opts['rev'], None).node()
4029
4029
4030 if opts.get('topo'):
4030 if opts.get('topo'):
4031 heads = [repo[h] for h in repo.heads(start)]
4031 heads = [repo[h] for h in repo.heads(start)]
4032 else:
4032 else:
4033 heads = []
4033 heads = []
4034 for branch in repo.branchmap():
4034 for branch in repo.branchmap():
4035 heads += repo.branchheads(branch, start, opts.get('closed'))
4035 heads += repo.branchheads(branch, start, opts.get('closed'))
4036 heads = [repo[h] for h in heads]
4036 heads = [repo[h] for h in heads]
4037
4037
4038 if branchrevs:
4038 if branchrevs:
4039 branches = set(repo[br].branch() for br in branchrevs)
4039 branches = set(repo[br].branch() for br in branchrevs)
4040 heads = [h for h in heads if h.branch() in branches]
4040 heads = [h for h in heads if h.branch() in branches]
4041
4041
4042 if opts.get('active') and branchrevs:
4042 if opts.get('active') and branchrevs:
4043 dagheads = repo.heads(start)
4043 dagheads = repo.heads(start)
4044 heads = [h for h in heads if h.node() in dagheads]
4044 heads = [h for h in heads if h.node() in dagheads]
4045
4045
4046 if branchrevs:
4046 if branchrevs:
4047 haveheads = set(h.branch() for h in heads)
4047 haveheads = set(h.branch() for h in heads)
4048 if branches - haveheads:
4048 if branches - haveheads:
4049 headless = ', '.join(b for b in branches - haveheads)
4049 headless = ', '.join(b for b in branches - haveheads)
4050 msg = _('no open branch heads found on branches %s')
4050 msg = _('no open branch heads found on branches %s')
4051 if opts.get('rev'):
4051 if opts.get('rev'):
4052 msg += _(' (started at %s)') % opts['rev']
4052 msg += _(' (started at %s)') % opts['rev']
4053 ui.warn((msg + '\n') % headless)
4053 ui.warn((msg + '\n') % headless)
4054
4054
4055 if not heads:
4055 if not heads:
4056 return 1
4056 return 1
4057
4057
4058 heads = sorted(heads, key=lambda x: -x.rev())
4058 heads = sorted(heads, key=lambda x: -x.rev())
4059 displayer = cmdutil.show_changeset(ui, repo, opts)
4059 displayer = cmdutil.show_changeset(ui, repo, opts)
4060 for ctx in heads:
4060 for ctx in heads:
4061 displayer.show(ctx)
4061 displayer.show(ctx)
4062 displayer.close()
4062 displayer.close()
4063
4063
4064 @command('help',
4064 @command('help',
4065 [('e', 'extension', None, _('show only help for extensions')),
4065 [('e', 'extension', None, _('show only help for extensions')),
4066 ('c', 'command', None, _('show only help for commands')),
4066 ('c', 'command', None, _('show only help for commands')),
4067 ('k', 'keyword', None, _('show topics matching keyword')),
4067 ('k', 'keyword', None, _('show topics matching keyword')),
4068 ],
4068 ],
4069 _('[-eck] [TOPIC]'),
4069 _('[-eck] [TOPIC]'),
4070 norepo=True)
4070 norepo=True)
4071 def help_(ui, name=None, **opts):
4071 def help_(ui, name=None, **opts):
4072 """show help for a given topic or a help overview
4072 """show help for a given topic or a help overview
4073
4073
4074 With no arguments, print a list of commands with short help messages.
4074 With no arguments, print a list of commands with short help messages.
4075
4075
4076 Given a topic, extension, or command name, print help for that
4076 Given a topic, extension, or command name, print help for that
4077 topic.
4077 topic.
4078
4078
4079 Returns 0 if successful.
4079 Returns 0 if successful.
4080 """
4080 """
4081
4081
4082 textwidth = min(ui.termwidth(), 80) - 2
4082 textwidth = min(ui.termwidth(), 80) - 2
4083
4083
4084 keep = []
4084 keep = []
4085 if ui.verbose:
4085 if ui.verbose:
4086 keep.append('verbose')
4086 keep.append('verbose')
4087 if sys.platform.startswith('win'):
4087 if sys.platform.startswith('win'):
4088 keep.append('windows')
4088 keep.append('windows')
4089 elif sys.platform == 'OpenVMS':
4089 elif sys.platform == 'OpenVMS':
4090 keep.append('vms')
4090 keep.append('vms')
4091 elif sys.platform == 'plan9':
4091 elif sys.platform == 'plan9':
4092 keep.append('plan9')
4092 keep.append('plan9')
4093 else:
4093 else:
4094 keep.append('unix')
4094 keep.append('unix')
4095 keep.append(sys.platform.lower())
4095 keep.append(sys.platform.lower())
4096
4096
4097 section = None
4097 section = None
4098 if name and '.' in name:
4098 if name and '.' in name:
4099 name, section = name.split('.', 1)
4099 name, section = name.split('.', 1)
4100 section = section.lower()
4100 section = section.lower()
4101
4101
4102 text = help.help_(ui, name, **opts)
4102 text = help.help_(ui, name, **opts)
4103
4103
4104 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4104 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4105 section=section)
4105 section=section)
4106
4106
4107 # We could have been given a weird ".foo" section without a name
4107 # We could have been given a weird ".foo" section without a name
4108 # to look for, or we could have simply failed to found "foo.bar"
4108 # to look for, or we could have simply failed to found "foo.bar"
4109 # because bar isn't a section of foo
4109 # because bar isn't a section of foo
4110 if section and not (formatted and name):
4110 if section and not (formatted and name):
4111 raise error.Abort(_("help section not found"))
4111 raise error.Abort(_("help section not found"))
4112
4112
4113 if 'verbose' in pruned:
4113 if 'verbose' in pruned:
4114 keep.append('omitted')
4114 keep.append('omitted')
4115 else:
4115 else:
4116 keep.append('notomitted')
4116 keep.append('notomitted')
4117 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4117 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4118 section=section)
4118 section=section)
4119 ui.write(formatted)
4119 ui.write(formatted)
4120
4120
4121
4121
4122 @command('identify|id',
4122 @command('identify|id',
4123 [('r', 'rev', '',
4123 [('r', 'rev', '',
4124 _('identify the specified revision'), _('REV')),
4124 _('identify the specified revision'), _('REV')),
4125 ('n', 'num', None, _('show local revision number')),
4125 ('n', 'num', None, _('show local revision number')),
4126 ('i', 'id', None, _('show global revision id')),
4126 ('i', 'id', None, _('show global revision id')),
4127 ('b', 'branch', None, _('show branch')),
4127 ('b', 'branch', None, _('show branch')),
4128 ('t', 'tags', None, _('show tags')),
4128 ('t', 'tags', None, _('show tags')),
4129 ('B', 'bookmarks', None, _('show bookmarks')),
4129 ('B', 'bookmarks', None, _('show bookmarks')),
4130 ] + remoteopts,
4130 ] + remoteopts,
4131 _('[-nibtB] [-r REV] [SOURCE]'),
4131 _('[-nibtB] [-r REV] [SOURCE]'),
4132 optionalrepo=True)
4132 optionalrepo=True)
4133 def identify(ui, repo, source=None, rev=None,
4133 def identify(ui, repo, source=None, rev=None,
4134 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4134 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4135 """identify the working directory or specified revision
4135 """identify the working directory or specified revision
4136
4136
4137 Print a summary identifying the repository state at REV using one or
4137 Print a summary identifying the repository state at REV using one or
4138 two parent hash identifiers, followed by a "+" if the working
4138 two parent hash identifiers, followed by a "+" if the working
4139 directory has uncommitted changes, the branch name (if not default),
4139 directory has uncommitted changes, the branch name (if not default),
4140 a list of tags, and a list of bookmarks.
4140 a list of tags, and a list of bookmarks.
4141
4141
4142 When REV is not given, print a summary of the current state of the
4142 When REV is not given, print a summary of the current state of the
4143 repository.
4143 repository.
4144
4144
4145 Specifying a path to a repository root or Mercurial bundle will
4145 Specifying a path to a repository root or Mercurial bundle will
4146 cause lookup to operate on that repository/bundle.
4146 cause lookup to operate on that repository/bundle.
4147
4147
4148 .. container:: verbose
4148 .. container:: verbose
4149
4149
4150 Examples:
4150 Examples:
4151
4151
4152 - generate a build identifier for the working directory::
4152 - generate a build identifier for the working directory::
4153
4153
4154 hg id --id > build-id.dat
4154 hg id --id > build-id.dat
4155
4155
4156 - find the revision corresponding to a tag::
4156 - find the revision corresponding to a tag::
4157
4157
4158 hg id -n -r 1.3
4158 hg id -n -r 1.3
4159
4159
4160 - check the most recent revision of a remote repository::
4160 - check the most recent revision of a remote repository::
4161
4161
4162 hg id -r tip http://selenic.com/hg/
4162 hg id -r tip http://selenic.com/hg/
4163
4163
4164 Returns 0 if successful.
4164 Returns 0 if successful.
4165 """
4165 """
4166
4166
4167 if not repo and not source:
4167 if not repo and not source:
4168 raise error.Abort(_("there is no Mercurial repository here "
4168 raise error.Abort(_("there is no Mercurial repository here "
4169 "(.hg not found)"))
4169 "(.hg not found)"))
4170
4170
4171 if ui.debugflag:
4171 if ui.debugflag:
4172 hexfunc = hex
4172 hexfunc = hex
4173 else:
4173 else:
4174 hexfunc = short
4174 hexfunc = short
4175 default = not (num or id or branch or tags or bookmarks)
4175 default = not (num or id or branch or tags or bookmarks)
4176 output = []
4176 output = []
4177 revs = []
4177 revs = []
4178
4178
4179 if source:
4179 if source:
4180 source, branches = hg.parseurl(ui.expandpath(source))
4180 source, branches = hg.parseurl(ui.expandpath(source))
4181 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4181 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4182 repo = peer.local()
4182 repo = peer.local()
4183 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4183 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4184
4184
4185 if not repo:
4185 if not repo:
4186 if num or branch or tags:
4186 if num or branch or tags:
4187 raise error.Abort(
4187 raise error.Abort(
4188 _("can't query remote revision number, branch, or tags"))
4188 _("can't query remote revision number, branch, or tags"))
4189 if not rev and revs:
4189 if not rev and revs:
4190 rev = revs[0]
4190 rev = revs[0]
4191 if not rev:
4191 if not rev:
4192 rev = "tip"
4192 rev = "tip"
4193
4193
4194 remoterev = peer.lookup(rev)
4194 remoterev = peer.lookup(rev)
4195 if default or id:
4195 if default or id:
4196 output = [hexfunc(remoterev)]
4196 output = [hexfunc(remoterev)]
4197
4197
4198 def getbms():
4198 def getbms():
4199 bms = []
4199 bms = []
4200
4200
4201 if 'bookmarks' in peer.listkeys('namespaces'):
4201 if 'bookmarks' in peer.listkeys('namespaces'):
4202 hexremoterev = hex(remoterev)
4202 hexremoterev = hex(remoterev)
4203 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4203 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4204 if bmr == hexremoterev]
4204 if bmr == hexremoterev]
4205
4205
4206 return sorted(bms)
4206 return sorted(bms)
4207
4207
4208 if bookmarks:
4208 if bookmarks:
4209 output.extend(getbms())
4209 output.extend(getbms())
4210 elif default and not ui.quiet:
4210 elif default and not ui.quiet:
4211 # multiple bookmarks for a single parent separated by '/'
4211 # multiple bookmarks for a single parent separated by '/'
4212 bm = '/'.join(getbms())
4212 bm = '/'.join(getbms())
4213 if bm:
4213 if bm:
4214 output.append(bm)
4214 output.append(bm)
4215 else:
4215 else:
4216 ctx = scmutil.revsingle(repo, rev, None)
4216 ctx = scmutil.revsingle(repo, rev, None)
4217
4217
4218 if ctx.rev() is None:
4218 if ctx.rev() is None:
4219 ctx = repo[None]
4219 ctx = repo[None]
4220 parents = ctx.parents()
4220 parents = ctx.parents()
4221 taglist = []
4221 taglist = []
4222 for p in parents:
4222 for p in parents:
4223 taglist.extend(p.tags())
4223 taglist.extend(p.tags())
4224
4224
4225 changed = ""
4225 changed = ""
4226 if default or id or num:
4226 if default or id or num:
4227 if (any(repo.status())
4227 if (any(repo.status())
4228 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4228 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4229 changed = '+'
4229 changed = '+'
4230 if default or id:
4230 if default or id:
4231 output = ["%s%s" %
4231 output = ["%s%s" %
4232 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4232 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4233 if num:
4233 if num:
4234 output.append("%s%s" %
4234 output.append("%s%s" %
4235 ('+'.join([str(p.rev()) for p in parents]), changed))
4235 ('+'.join([str(p.rev()) for p in parents]), changed))
4236 else:
4236 else:
4237 if default or id:
4237 if default or id:
4238 output = [hexfunc(ctx.node())]
4238 output = [hexfunc(ctx.node())]
4239 if num:
4239 if num:
4240 output.append(str(ctx.rev()))
4240 output.append(str(ctx.rev()))
4241 taglist = ctx.tags()
4241 taglist = ctx.tags()
4242
4242
4243 if default and not ui.quiet:
4243 if default and not ui.quiet:
4244 b = ctx.branch()
4244 b = ctx.branch()
4245 if b != 'default':
4245 if b != 'default':
4246 output.append("(%s)" % b)
4246 output.append("(%s)" % b)
4247
4247
4248 # multiple tags for a single parent separated by '/'
4248 # multiple tags for a single parent separated by '/'
4249 t = '/'.join(taglist)
4249 t = '/'.join(taglist)
4250 if t:
4250 if t:
4251 output.append(t)
4251 output.append(t)
4252
4252
4253 # multiple bookmarks for a single parent separated by '/'
4253 # multiple bookmarks for a single parent separated by '/'
4254 bm = '/'.join(ctx.bookmarks())
4254 bm = '/'.join(ctx.bookmarks())
4255 if bm:
4255 if bm:
4256 output.append(bm)
4256 output.append(bm)
4257 else:
4257 else:
4258 if branch:
4258 if branch:
4259 output.append(ctx.branch())
4259 output.append(ctx.branch())
4260
4260
4261 if tags:
4261 if tags:
4262 output.extend(taglist)
4262 output.extend(taglist)
4263
4263
4264 if bookmarks:
4264 if bookmarks:
4265 output.extend(ctx.bookmarks())
4265 output.extend(ctx.bookmarks())
4266
4266
4267 ui.write("%s\n" % ' '.join(output))
4267 ui.write("%s\n" % ' '.join(output))
4268
4268
4269 @command('import|patch',
4269 @command('import|patch',
4270 [('p', 'strip', 1,
4270 [('p', 'strip', 1,
4271 _('directory strip option for patch. This has the same '
4271 _('directory strip option for patch. This has the same '
4272 'meaning as the corresponding patch option'), _('NUM')),
4272 'meaning as the corresponding patch option'), _('NUM')),
4273 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4273 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4274 ('e', 'edit', False, _('invoke editor on commit messages')),
4274 ('e', 'edit', False, _('invoke editor on commit messages')),
4275 ('f', 'force', None,
4275 ('f', 'force', None,
4276 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4276 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4277 ('', 'no-commit', None,
4277 ('', 'no-commit', None,
4278 _("don't commit, just update the working directory")),
4278 _("don't commit, just update the working directory")),
4279 ('', 'bypass', None,
4279 ('', 'bypass', None,
4280 _("apply patch without touching the working directory")),
4280 _("apply patch without touching the working directory")),
4281 ('', 'partial', None,
4281 ('', 'partial', None,
4282 _('commit even if some hunks fail')),
4282 _('commit even if some hunks fail')),
4283 ('', 'exact', None,
4283 ('', 'exact', None,
4284 _('apply patch to the nodes from which it was generated')),
4284 _('apply patch to the nodes from which it was generated')),
4285 ('', 'prefix', '',
4285 ('', 'prefix', '',
4286 _('apply patch to subdirectory'), _('DIR')),
4286 _('apply patch to subdirectory'), _('DIR')),
4287 ('', 'import-branch', None,
4287 ('', 'import-branch', None,
4288 _('use any branch information in patch (implied by --exact)'))] +
4288 _('use any branch information in patch (implied by --exact)'))] +
4289 commitopts + commitopts2 + similarityopts,
4289 commitopts + commitopts2 + similarityopts,
4290 _('[OPTION]... PATCH...'))
4290 _('[OPTION]... PATCH...'))
4291 def import_(ui, repo, patch1=None, *patches, **opts):
4291 def import_(ui, repo, patch1=None, *patches, **opts):
4292 """import an ordered set of patches
4292 """import an ordered set of patches
4293
4293
4294 Import a list of patches and commit them individually (unless
4294 Import a list of patches and commit them individually (unless
4295 --no-commit is specified).
4295 --no-commit is specified).
4296
4296
4297 Because import first applies changes to the working directory,
4297 Because import first applies changes to the working directory,
4298 import will abort if there are outstanding changes.
4298 import will abort if there are outstanding changes.
4299
4299
4300 You can import a patch straight from a mail message. Even patches
4300 You can import a patch straight from a mail message. Even patches
4301 as attachments work (to use the body part, it must have type
4301 as attachments work (to use the body part, it must have type
4302 text/plain or text/x-patch). From and Subject headers of email
4302 text/plain or text/x-patch). From and Subject headers of email
4303 message are used as default committer and commit message. All
4303 message are used as default committer and commit message. All
4304 text/plain body parts before first diff are added to commit
4304 text/plain body parts before first diff are added to commit
4305 message.
4305 message.
4306
4306
4307 If the imported patch was generated by :hg:`export`, user and
4307 If the imported patch was generated by :hg:`export`, user and
4308 description from patch override values from message headers and
4308 description from patch override values from message headers and
4309 body. Values given on command line with -m/--message and -u/--user
4309 body. Values given on command line with -m/--message and -u/--user
4310 override these.
4310 override these.
4311
4311
4312 If --exact is specified, import will set the working directory to
4312 If --exact is specified, import will set the working directory to
4313 the parent of each patch before applying it, and will abort if the
4313 the parent of each patch before applying it, and will abort if the
4314 resulting changeset has a different ID than the one recorded in
4314 resulting changeset has a different ID than the one recorded in
4315 the patch. This may happen due to character set problems or other
4315 the patch. This may happen due to character set problems or other
4316 deficiencies in the text patch format.
4316 deficiencies in the text patch format.
4317
4317
4318 Use --bypass to apply and commit patches directly to the
4318 Use --bypass to apply and commit patches directly to the
4319 repository, not touching the working directory. Without --exact,
4319 repository, not touching the working directory. Without --exact,
4320 patches will be applied on top of the working directory parent
4320 patches will be applied on top of the working directory parent
4321 revision.
4321 revision.
4322
4322
4323 With -s/--similarity, hg will attempt to discover renames and
4323 With -s/--similarity, hg will attempt to discover renames and
4324 copies in the patch in the same way as :hg:`addremove`.
4324 copies in the patch in the same way as :hg:`addremove`.
4325
4325
4326 Use --partial to ensure a changeset will be created from the patch
4326 Use --partial to ensure a changeset will be created from the patch
4327 even if some hunks fail to apply. Hunks that fail to apply will be
4327 even if some hunks fail to apply. Hunks that fail to apply will be
4328 written to a <target-file>.rej file. Conflicts can then be resolved
4328 written to a <target-file>.rej file. Conflicts can then be resolved
4329 by hand before :hg:`commit --amend` is run to update the created
4329 by hand before :hg:`commit --amend` is run to update the created
4330 changeset. This flag exists to let people import patches that
4330 changeset. This flag exists to let people import patches that
4331 partially apply without losing the associated metadata (author,
4331 partially apply without losing the associated metadata (author,
4332 date, description, ...). Note that when none of the hunk applies
4332 date, description, ...). Note that when none of the hunk applies
4333 cleanly, :hg:`import --partial` will create an empty changeset,
4333 cleanly, :hg:`import --partial` will create an empty changeset,
4334 importing only the patch metadata.
4334 importing only the patch metadata.
4335
4335
4336 It is possible to use external patch programs to perform the patch
4336 It is possible to use external patch programs to perform the patch
4337 by setting the ``ui.patch`` configuration option. For the default
4337 by setting the ``ui.patch`` configuration option. For the default
4338 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4338 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4339 See :hg:`help config` for more information about configuration
4339 See :hg:`help config` for more information about configuration
4340 files and how to use these options.
4340 files and how to use these options.
4341
4341
4342 To read a patch from standard input, use "-" as the patch name. If
4342 To read a patch from standard input, use "-" as the patch name. If
4343 a URL is specified, the patch will be downloaded from it.
4343 a URL is specified, the patch will be downloaded from it.
4344 See :hg:`help dates` for a list of formats valid for -d/--date.
4344 See :hg:`help dates` for a list of formats valid for -d/--date.
4345
4345
4346 .. container:: verbose
4346 .. container:: verbose
4347
4347
4348 Examples:
4348 Examples:
4349
4349
4350 - import a traditional patch from a website and detect renames::
4350 - import a traditional patch from a website and detect renames::
4351
4351
4352 hg import -s 80 http://example.com/bugfix.patch
4352 hg import -s 80 http://example.com/bugfix.patch
4353
4353
4354 - import a changeset from an hgweb server::
4354 - import a changeset from an hgweb server::
4355
4355
4356 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4356 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4357
4357
4358 - import all the patches in an Unix-style mbox::
4358 - import all the patches in an Unix-style mbox::
4359
4359
4360 hg import incoming-patches.mbox
4360 hg import incoming-patches.mbox
4361
4361
4362 - attempt to exactly restore an exported changeset (not always
4362 - attempt to exactly restore an exported changeset (not always
4363 possible)::
4363 possible)::
4364
4364
4365 hg import --exact proposed-fix.patch
4365 hg import --exact proposed-fix.patch
4366
4366
4367 - use an external tool to apply a patch which is too fuzzy for
4367 - use an external tool to apply a patch which is too fuzzy for
4368 the default internal tool.
4368 the default internal tool.
4369
4369
4370 hg import --config ui.patch="patch --merge" fuzzy.patch
4370 hg import --config ui.patch="patch --merge" fuzzy.patch
4371
4371
4372 - change the default fuzzing from 2 to a less strict 7
4372 - change the default fuzzing from 2 to a less strict 7
4373
4373
4374 hg import --config ui.fuzz=7 fuzz.patch
4374 hg import --config ui.fuzz=7 fuzz.patch
4375
4375
4376 Returns 0 on success, 1 on partial success (see --partial).
4376 Returns 0 on success, 1 on partial success (see --partial).
4377 """
4377 """
4378
4378
4379 if not patch1:
4379 if not patch1:
4380 raise error.Abort(_('need at least one patch to import'))
4380 raise error.Abort(_('need at least one patch to import'))
4381
4381
4382 patches = (patch1,) + patches
4382 patches = (patch1,) + patches
4383
4383
4384 date = opts.get('date')
4384 date = opts.get('date')
4385 if date:
4385 if date:
4386 opts['date'] = util.parsedate(date)
4386 opts['date'] = util.parsedate(date)
4387
4387
4388 update = not opts.get('bypass')
4388 update = not opts.get('bypass')
4389 if not update and opts.get('no_commit'):
4389 if not update and opts.get('no_commit'):
4390 raise error.Abort(_('cannot use --no-commit with --bypass'))
4390 raise error.Abort(_('cannot use --no-commit with --bypass'))
4391 try:
4391 try:
4392 sim = float(opts.get('similarity') or 0)
4392 sim = float(opts.get('similarity') or 0)
4393 except ValueError:
4393 except ValueError:
4394 raise error.Abort(_('similarity must be a number'))
4394 raise error.Abort(_('similarity must be a number'))
4395 if sim < 0 or sim > 100:
4395 if sim < 0 or sim > 100:
4396 raise error.Abort(_('similarity must be between 0 and 100'))
4396 raise error.Abort(_('similarity must be between 0 and 100'))
4397 if sim and not update:
4397 if sim and not update:
4398 raise error.Abort(_('cannot use --similarity with --bypass'))
4398 raise error.Abort(_('cannot use --similarity with --bypass'))
4399 if opts.get('exact') and opts.get('edit'):
4399 if opts.get('exact') and opts.get('edit'):
4400 raise error.Abort(_('cannot use --exact with --edit'))
4400 raise error.Abort(_('cannot use --exact with --edit'))
4401 if opts.get('exact') and opts.get('prefix'):
4401 if opts.get('exact') and opts.get('prefix'):
4402 raise error.Abort(_('cannot use --exact with --prefix'))
4402 raise error.Abort(_('cannot use --exact with --prefix'))
4403
4403
4404 if update:
4404 if update:
4405 cmdutil.checkunfinished(repo)
4405 cmdutil.checkunfinished(repo)
4406 if (opts.get('exact') or not opts.get('force')) and update:
4406 if (opts.get('exact') or not opts.get('force')) and update:
4407 cmdutil.bailifchanged(repo)
4407 cmdutil.bailifchanged(repo)
4408
4408
4409 base = opts["base"]
4409 base = opts["base"]
4410 wlock = dsguard = lock = tr = None
4410 wlock = dsguard = lock = tr = None
4411 msgs = []
4411 msgs = []
4412 ret = 0
4412 ret = 0
4413
4413
4414
4414
4415 try:
4415 try:
4416 try:
4416 try:
4417 wlock = repo.wlock()
4417 wlock = repo.wlock()
4418 if not opts.get('no_commit'):
4418 if not opts.get('no_commit'):
4419 lock = repo.lock()
4419 lock = repo.lock()
4420 tr = repo.transaction('import')
4420 tr = repo.transaction('import')
4421 else:
4421 else:
4422 dsguard = cmdutil.dirstateguard(repo, 'import')
4422 dsguard = cmdutil.dirstateguard(repo, 'import')
4423 parents = repo.parents()
4423 parents = repo.parents()
4424 for patchurl in patches:
4424 for patchurl in patches:
4425 if patchurl == '-':
4425 if patchurl == '-':
4426 ui.status(_('applying patch from stdin\n'))
4426 ui.status(_('applying patch from stdin\n'))
4427 patchfile = ui.fin
4427 patchfile = ui.fin
4428 patchurl = 'stdin' # for error message
4428 patchurl = 'stdin' # for error message
4429 else:
4429 else:
4430 patchurl = os.path.join(base, patchurl)
4430 patchurl = os.path.join(base, patchurl)
4431 ui.status(_('applying %s\n') % patchurl)
4431 ui.status(_('applying %s\n') % patchurl)
4432 patchfile = hg.openpath(ui, patchurl)
4432 patchfile = hg.openpath(ui, patchurl)
4433
4433
4434 haspatch = False
4434 haspatch = False
4435 for hunk in patch.split(patchfile):
4435 for hunk in patch.split(patchfile):
4436 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4436 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4437 parents, opts,
4437 parents, opts,
4438 msgs, hg.clean)
4438 msgs, hg.clean)
4439 if msg:
4439 if msg:
4440 haspatch = True
4440 haspatch = True
4441 ui.note(msg + '\n')
4441 ui.note(msg + '\n')
4442 if update or opts.get('exact'):
4442 if update or opts.get('exact'):
4443 parents = repo.parents()
4443 parents = repo.parents()
4444 else:
4444 else:
4445 parents = [repo[node]]
4445 parents = [repo[node]]
4446 if rej:
4446 if rej:
4447 ui.write_err(_("patch applied partially\n"))
4447 ui.write_err(_("patch applied partially\n"))
4448 ui.write_err(_("(fix the .rej files and run "
4448 ui.write_err(_("(fix the .rej files and run "
4449 "`hg commit --amend`)\n"))
4449 "`hg commit --amend`)\n"))
4450 ret = 1
4450 ret = 1
4451 break
4451 break
4452
4452
4453 if not haspatch:
4453 if not haspatch:
4454 raise error.Abort(_('%s: no diffs found') % patchurl)
4454 raise error.Abort(_('%s: no diffs found') % patchurl)
4455
4455
4456 if tr:
4456 if tr:
4457 tr.close()
4457 tr.close()
4458 if msgs:
4458 if msgs:
4459 repo.savecommitmessage('\n* * *\n'.join(msgs))
4459 repo.savecommitmessage('\n* * *\n'.join(msgs))
4460 if dsguard:
4460 if dsguard:
4461 dsguard.close()
4461 dsguard.close()
4462 return ret
4462 return ret
4463 finally:
4463 finally:
4464 # TODO: get rid of this meaningless try/finally enclosing.
4464 # TODO: get rid of this meaningless try/finally enclosing.
4465 # this is kept only to reduce changes in a patch.
4465 # this is kept only to reduce changes in a patch.
4466 pass
4466 pass
4467 finally:
4467 finally:
4468 if tr:
4468 if tr:
4469 tr.release()
4469 tr.release()
4470 release(lock, dsguard, wlock)
4470 release(lock, dsguard, wlock)
4471
4471
4472 @command('incoming|in',
4472 @command('incoming|in',
4473 [('f', 'force', None,
4473 [('f', 'force', None,
4474 _('run even if remote repository is unrelated')),
4474 _('run even if remote repository is unrelated')),
4475 ('n', 'newest-first', None, _('show newest record first')),
4475 ('n', 'newest-first', None, _('show newest record first')),
4476 ('', 'bundle', '',
4476 ('', 'bundle', '',
4477 _('file to store the bundles into'), _('FILE')),
4477 _('file to store the bundles into'), _('FILE')),
4478 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4478 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4479 ('B', 'bookmarks', False, _("compare bookmarks")),
4479 ('B', 'bookmarks', False, _("compare bookmarks")),
4480 ('b', 'branch', [],
4480 ('b', 'branch', [],
4481 _('a specific branch you would like to pull'), _('BRANCH')),
4481 _('a specific branch you would like to pull'), _('BRANCH')),
4482 ] + logopts + remoteopts + subrepoopts,
4482 ] + logopts + remoteopts + subrepoopts,
4483 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4483 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4484 def incoming(ui, repo, source="default", **opts):
4484 def incoming(ui, repo, source="default", **opts):
4485 """show new changesets found in source
4485 """show new changesets found in source
4486
4486
4487 Show new changesets found in the specified path/URL or the default
4487 Show new changesets found in the specified path/URL or the default
4488 pull location. These are the changesets that would have been pulled
4488 pull location. These are the changesets that would have been pulled
4489 if a pull at the time you issued this command.
4489 if a pull at the time you issued this command.
4490
4490
4491 See pull for valid source format details.
4491 See pull for valid source format details.
4492
4492
4493 .. container:: verbose
4493 .. container:: verbose
4494
4494
4495 With -B/--bookmarks, the result of bookmark comparison between
4495 With -B/--bookmarks, the result of bookmark comparison between
4496 local and remote repositories is displayed. With -v/--verbose,
4496 local and remote repositories is displayed. With -v/--verbose,
4497 status is also displayed for each bookmark like below::
4497 status is also displayed for each bookmark like below::
4498
4498
4499 BM1 01234567890a added
4499 BM1 01234567890a added
4500 BM2 1234567890ab advanced
4500 BM2 1234567890ab advanced
4501 BM3 234567890abc diverged
4501 BM3 234567890abc diverged
4502 BM4 34567890abcd changed
4502 BM4 34567890abcd changed
4503
4503
4504 The action taken locally when pulling depends on the
4504 The action taken locally when pulling depends on the
4505 status of each bookmark:
4505 status of each bookmark:
4506
4506
4507 :``added``: pull will create it
4507 :``added``: pull will create it
4508 :``advanced``: pull will update it
4508 :``advanced``: pull will update it
4509 :``diverged``: pull will create a divergent bookmark
4509 :``diverged``: pull will create a divergent bookmark
4510 :``changed``: result depends on remote changesets
4510 :``changed``: result depends on remote changesets
4511
4511
4512 From the point of view of pulling behavior, bookmark
4512 From the point of view of pulling behavior, bookmark
4513 existing only in the remote repository are treated as ``added``,
4513 existing only in the remote repository are treated as ``added``,
4514 even if it is in fact locally deleted.
4514 even if it is in fact locally deleted.
4515
4515
4516 .. container:: verbose
4516 .. container:: verbose
4517
4517
4518 For remote repository, using --bundle avoids downloading the
4518 For remote repository, using --bundle avoids downloading the
4519 changesets twice if the incoming is followed by a pull.
4519 changesets twice if the incoming is followed by a pull.
4520
4520
4521 Examples:
4521 Examples:
4522
4522
4523 - show incoming changes with patches and full description::
4523 - show incoming changes with patches and full description::
4524
4524
4525 hg incoming -vp
4525 hg incoming -vp
4526
4526
4527 - show incoming changes excluding merges, store a bundle::
4527 - show incoming changes excluding merges, store a bundle::
4528
4528
4529 hg in -vpM --bundle incoming.hg
4529 hg in -vpM --bundle incoming.hg
4530 hg pull incoming.hg
4530 hg pull incoming.hg
4531
4531
4532 - briefly list changes inside a bundle::
4532 - briefly list changes inside a bundle::
4533
4533
4534 hg in changes.hg -T "{desc|firstline}\\n"
4534 hg in changes.hg -T "{desc|firstline}\\n"
4535
4535
4536 Returns 0 if there are incoming changes, 1 otherwise.
4536 Returns 0 if there are incoming changes, 1 otherwise.
4537 """
4537 """
4538 if opts.get('graph'):
4538 if opts.get('graph'):
4539 cmdutil.checkunsupportedgraphflags([], opts)
4539 cmdutil.checkunsupportedgraphflags([], opts)
4540 def display(other, chlist, displayer):
4540 def display(other, chlist, displayer):
4541 revdag = cmdutil.graphrevs(other, chlist, opts)
4541 revdag = cmdutil.graphrevs(other, chlist, opts)
4542 showparents = [ctx.node() for ctx in repo[None].parents()]
4542 showparents = [ctx.node() for ctx in repo[None].parents()]
4543 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4543 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4544 graphmod.asciiedges)
4544 graphmod.asciiedges)
4545
4545
4546 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4546 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4547 return 0
4547 return 0
4548
4548
4549 if opts.get('bundle') and opts.get('subrepos'):
4549 if opts.get('bundle') and opts.get('subrepos'):
4550 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4550 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4551
4551
4552 if opts.get('bookmarks'):
4552 if opts.get('bookmarks'):
4553 source, branches = hg.parseurl(ui.expandpath(source),
4553 source, branches = hg.parseurl(ui.expandpath(source),
4554 opts.get('branch'))
4554 opts.get('branch'))
4555 other = hg.peer(repo, opts, source)
4555 other = hg.peer(repo, opts, source)
4556 if 'bookmarks' not in other.listkeys('namespaces'):
4556 if 'bookmarks' not in other.listkeys('namespaces'):
4557 ui.warn(_("remote doesn't support bookmarks\n"))
4557 ui.warn(_("remote doesn't support bookmarks\n"))
4558 return 0
4558 return 0
4559 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4559 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4560 return bookmarks.incoming(ui, repo, other)
4560 return bookmarks.incoming(ui, repo, other)
4561
4561
4562 repo._subtoppath = ui.expandpath(source)
4562 repo._subtoppath = ui.expandpath(source)
4563 try:
4563 try:
4564 return hg.incoming(ui, repo, source, opts)
4564 return hg.incoming(ui, repo, source, opts)
4565 finally:
4565 finally:
4566 del repo._subtoppath
4566 del repo._subtoppath
4567
4567
4568
4568
4569 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4569 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4570 norepo=True)
4570 norepo=True)
4571 def init(ui, dest=".", **opts):
4571 def init(ui, dest=".", **opts):
4572 """create a new repository in the given directory
4572 """create a new repository in the given directory
4573
4573
4574 Initialize a new repository in the given directory. If the given
4574 Initialize a new repository in the given directory. If the given
4575 directory does not exist, it will be created.
4575 directory does not exist, it will be created.
4576
4576
4577 If no directory is given, the current directory is used.
4577 If no directory is given, the current directory is used.
4578
4578
4579 It is possible to specify an ``ssh://`` URL as the destination.
4579 It is possible to specify an ``ssh://`` URL as the destination.
4580 See :hg:`help urls` for more information.
4580 See :hg:`help urls` for more information.
4581
4581
4582 Returns 0 on success.
4582 Returns 0 on success.
4583 """
4583 """
4584 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4584 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4585
4585
4586 @command('locate',
4586 @command('locate',
4587 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4587 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4588 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4588 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4589 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4589 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4590 ] + walkopts,
4590 ] + walkopts,
4591 _('[OPTION]... [PATTERN]...'))
4591 _('[OPTION]... [PATTERN]...'))
4592 def locate(ui, repo, *pats, **opts):
4592 def locate(ui, repo, *pats, **opts):
4593 """locate files matching specific patterns (DEPRECATED)
4593 """locate files matching specific patterns (DEPRECATED)
4594
4594
4595 Print files under Mercurial control in the working directory whose
4595 Print files under Mercurial control in the working directory whose
4596 names match the given patterns.
4596 names match the given patterns.
4597
4597
4598 By default, this command searches all directories in the working
4598 By default, this command searches all directories in the working
4599 directory. To search just the current directory and its
4599 directory. To search just the current directory and its
4600 subdirectories, use "--include .".
4600 subdirectories, use "--include .".
4601
4601
4602 If no patterns are given to match, this command prints the names
4602 If no patterns are given to match, this command prints the names
4603 of all files under Mercurial control in the working directory.
4603 of all files under Mercurial control in the working directory.
4604
4604
4605 If you want to feed the output of this command into the "xargs"
4605 If you want to feed the output of this command into the "xargs"
4606 command, use the -0 option to both this command and "xargs". This
4606 command, use the -0 option to both this command and "xargs". This
4607 will avoid the problem of "xargs" treating single filenames that
4607 will avoid the problem of "xargs" treating single filenames that
4608 contain whitespace as multiple filenames.
4608 contain whitespace as multiple filenames.
4609
4609
4610 See :hg:`help files` for a more versatile command.
4610 See :hg:`help files` for a more versatile command.
4611
4611
4612 Returns 0 if a match is found, 1 otherwise.
4612 Returns 0 if a match is found, 1 otherwise.
4613 """
4613 """
4614 if opts.get('print0'):
4614 if opts.get('print0'):
4615 end = '\0'
4615 end = '\0'
4616 else:
4616 else:
4617 end = '\n'
4617 end = '\n'
4618 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4618 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4619
4619
4620 ret = 1
4620 ret = 1
4621 ctx = repo[rev]
4621 ctx = repo[rev]
4622 m = scmutil.match(ctx, pats, opts, default='relglob',
4622 m = scmutil.match(ctx, pats, opts, default='relglob',
4623 badfn=lambda x, y: False)
4623 badfn=lambda x, y: False)
4624
4624
4625 for abs in ctx.matches(m):
4625 for abs in ctx.matches(m):
4626 if opts.get('fullpath'):
4626 if opts.get('fullpath'):
4627 ui.write(repo.wjoin(abs), end)
4627 ui.write(repo.wjoin(abs), end)
4628 else:
4628 else:
4629 ui.write(((pats and m.rel(abs)) or abs), end)
4629 ui.write(((pats and m.rel(abs)) or abs), end)
4630 ret = 0
4630 ret = 0
4631
4631
4632 return ret
4632 return ret
4633
4633
4634 @command('^log|history',
4634 @command('^log|history',
4635 [('f', 'follow', None,
4635 [('f', 'follow', None,
4636 _('follow changeset history, or file history across copies and renames')),
4636 _('follow changeset history, or file history across copies and renames')),
4637 ('', 'follow-first', None,
4637 ('', 'follow-first', None,
4638 _('only follow the first parent of merge changesets (DEPRECATED)')),
4638 _('only follow the first parent of merge changesets (DEPRECATED)')),
4639 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4639 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4640 ('C', 'copies', None, _('show copied files')),
4640 ('C', 'copies', None, _('show copied files')),
4641 ('k', 'keyword', [],
4641 ('k', 'keyword', [],
4642 _('do case-insensitive search for a given text'), _('TEXT')),
4642 _('do case-insensitive search for a given text'), _('TEXT')),
4643 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4643 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4644 ('', 'removed', None, _('include revisions where files were removed')),
4644 ('', 'removed', None, _('include revisions where files were removed')),
4645 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4645 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4646 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4646 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4647 ('', 'only-branch', [],
4647 ('', 'only-branch', [],
4648 _('show only changesets within the given named branch (DEPRECATED)'),
4648 _('show only changesets within the given named branch (DEPRECATED)'),
4649 _('BRANCH')),
4649 _('BRANCH')),
4650 ('b', 'branch', [],
4650 ('b', 'branch', [],
4651 _('show changesets within the given named branch'), _('BRANCH')),
4651 _('show changesets within the given named branch'), _('BRANCH')),
4652 ('P', 'prune', [],
4652 ('P', 'prune', [],
4653 _('do not display revision or any of its ancestors'), _('REV')),
4653 _('do not display revision or any of its ancestors'), _('REV')),
4654 ] + logopts + walkopts,
4654 ] + logopts + walkopts,
4655 _('[OPTION]... [FILE]'),
4655 _('[OPTION]... [FILE]'),
4656 inferrepo=True)
4656 inferrepo=True)
4657 def log(ui, repo, *pats, **opts):
4657 def log(ui, repo, *pats, **opts):
4658 """show revision history of entire repository or files
4658 """show revision history of entire repository or files
4659
4659
4660 Print the revision history of the specified files or the entire
4660 Print the revision history of the specified files or the entire
4661 project.
4661 project.
4662
4662
4663 If no revision range is specified, the default is ``tip:0`` unless
4663 If no revision range is specified, the default is ``tip:0`` unless
4664 --follow is set, in which case the working directory parent is
4664 --follow is set, in which case the working directory parent is
4665 used as the starting revision.
4665 used as the starting revision.
4666
4666
4667 File history is shown without following rename or copy history of
4667 File history is shown without following rename or copy history of
4668 files. Use -f/--follow with a filename to follow history across
4668 files. Use -f/--follow with a filename to follow history across
4669 renames and copies. --follow without a filename will only show
4669 renames and copies. --follow without a filename will only show
4670 ancestors or descendants of the starting revision.
4670 ancestors or descendants of the starting revision.
4671
4671
4672 By default this command prints revision number and changeset id,
4672 By default this command prints revision number and changeset id,
4673 tags, non-trivial parents, user, date and time, and a summary for
4673 tags, non-trivial parents, user, date and time, and a summary for
4674 each commit. When the -v/--verbose switch is used, the list of
4674 each commit. When the -v/--verbose switch is used, the list of
4675 changed files and full commit message are shown.
4675 changed files and full commit message are shown.
4676
4676
4677 With --graph the revisions are shown as an ASCII art DAG with the most
4677 With --graph the revisions are shown as an ASCII art DAG with the most
4678 recent changeset at the top.
4678 recent changeset at the top.
4679 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4679 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4680 and '+' represents a fork where the changeset from the lines below is a
4680 and '+' represents a fork where the changeset from the lines below is a
4681 parent of the 'o' merge on the same line.
4681 parent of the 'o' merge on the same line.
4682
4682
4683 .. note::
4683 .. note::
4684
4684
4685 log -p/--patch may generate unexpected diff output for merge
4685 log -p/--patch may generate unexpected diff output for merge
4686 changesets, as it will only compare the merge changeset against
4686 changesets, as it will only compare the merge changeset against
4687 its first parent. Also, only files different from BOTH parents
4687 its first parent. Also, only files different from BOTH parents
4688 will appear in files:.
4688 will appear in files:.
4689
4689
4690 .. note::
4690 .. note::
4691
4691
4692 for performance reasons, log FILE may omit duplicate changes
4692 for performance reasons, log FILE may omit duplicate changes
4693 made on branches and will not show removals or mode changes. To
4693 made on branches and will not show removals or mode changes. To
4694 see all such changes, use the --removed switch.
4694 see all such changes, use the --removed switch.
4695
4695
4696 .. container:: verbose
4696 .. container:: verbose
4697
4697
4698 Some examples:
4698 Some examples:
4699
4699
4700 - changesets with full descriptions and file lists::
4700 - changesets with full descriptions and file lists::
4701
4701
4702 hg log -v
4702 hg log -v
4703
4703
4704 - changesets ancestral to the working directory::
4704 - changesets ancestral to the working directory::
4705
4705
4706 hg log -f
4706 hg log -f
4707
4707
4708 - last 10 commits on the current branch::
4708 - last 10 commits on the current branch::
4709
4709
4710 hg log -l 10 -b .
4710 hg log -l 10 -b .
4711
4711
4712 - changesets showing all modifications of a file, including removals::
4712 - changesets showing all modifications of a file, including removals::
4713
4713
4714 hg log --removed file.c
4714 hg log --removed file.c
4715
4715
4716 - all changesets that touch a directory, with diffs, excluding merges::
4716 - all changesets that touch a directory, with diffs, excluding merges::
4717
4717
4718 hg log -Mp lib/
4718 hg log -Mp lib/
4719
4719
4720 - all revision numbers that match a keyword::
4720 - all revision numbers that match a keyword::
4721
4721
4722 hg log -k bug --template "{rev}\\n"
4722 hg log -k bug --template "{rev}\\n"
4723
4723
4724 - list available log templates::
4724 - list available log templates::
4725
4725
4726 hg log -T list
4726 hg log -T list
4727
4727
4728 - check if a given changeset is included in a tagged release::
4728 - check if a given changeset is included in a tagged release::
4729
4729
4730 hg log -r "a21ccf and ancestor(1.9)"
4730 hg log -r "a21ccf and ancestor(1.9)"
4731
4731
4732 - find all changesets by some user in a date range::
4732 - find all changesets by some user in a date range::
4733
4733
4734 hg log -k alice -d "may 2008 to jul 2008"
4734 hg log -k alice -d "may 2008 to jul 2008"
4735
4735
4736 - summary of all changesets after the last tag::
4736 - summary of all changesets after the last tag::
4737
4737
4738 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4738 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4739
4739
4740 See :hg:`help dates` for a list of formats valid for -d/--date.
4740 See :hg:`help dates` for a list of formats valid for -d/--date.
4741
4741
4742 See :hg:`help revisions` and :hg:`help revsets` for more about
4742 See :hg:`help revisions` and :hg:`help revsets` for more about
4743 specifying revisions.
4743 specifying revisions.
4744
4744
4745 See :hg:`help templates` for more about pre-packaged styles and
4745 See :hg:`help templates` for more about pre-packaged styles and
4746 specifying custom templates.
4746 specifying custom templates.
4747
4747
4748 Returns 0 on success.
4748 Returns 0 on success.
4749
4749
4750 """
4750 """
4751 if opts.get('follow') and opts.get('rev'):
4751 if opts.get('follow') and opts.get('rev'):
4752 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4752 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4753 del opts['follow']
4753 del opts['follow']
4754
4754
4755 if opts.get('graph'):
4755 if opts.get('graph'):
4756 return cmdutil.graphlog(ui, repo, *pats, **opts)
4756 return cmdutil.graphlog(ui, repo, *pats, **opts)
4757
4757
4758 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4758 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4759 limit = cmdutil.loglimit(opts)
4759 limit = cmdutil.loglimit(opts)
4760 count = 0
4760 count = 0
4761
4761
4762 getrenamed = None
4762 getrenamed = None
4763 if opts.get('copies'):
4763 if opts.get('copies'):
4764 endrev = None
4764 endrev = None
4765 if opts.get('rev'):
4765 if opts.get('rev'):
4766 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4766 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4767 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4767 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4768
4768
4769 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4769 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4770 for rev in revs:
4770 for rev in revs:
4771 if count == limit:
4771 if count == limit:
4772 break
4772 break
4773 ctx = repo[rev]
4773 ctx = repo[rev]
4774 copies = None
4774 copies = None
4775 if getrenamed is not None and rev:
4775 if getrenamed is not None and rev:
4776 copies = []
4776 copies = []
4777 for fn in ctx.files():
4777 for fn in ctx.files():
4778 rename = getrenamed(fn, rev)
4778 rename = getrenamed(fn, rev)
4779 if rename:
4779 if rename:
4780 copies.append((fn, rename[0]))
4780 copies.append((fn, rename[0]))
4781 if filematcher:
4781 if filematcher:
4782 revmatchfn = filematcher(ctx.rev())
4782 revmatchfn = filematcher(ctx.rev())
4783 else:
4783 else:
4784 revmatchfn = None
4784 revmatchfn = None
4785 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4785 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4786 if displayer.flush(ctx):
4786 if displayer.flush(ctx):
4787 count += 1
4787 count += 1
4788
4788
4789 displayer.close()
4789 displayer.close()
4790
4790
4791 @command('manifest',
4791 @command('manifest',
4792 [('r', 'rev', '', _('revision to display'), _('REV')),
4792 [('r', 'rev', '', _('revision to display'), _('REV')),
4793 ('', 'all', False, _("list files from all revisions"))]
4793 ('', 'all', False, _("list files from all revisions"))]
4794 + formatteropts,
4794 + formatteropts,
4795 _('[-r REV]'))
4795 _('[-r REV]'))
4796 def manifest(ui, repo, node=None, rev=None, **opts):
4796 def manifest(ui, repo, node=None, rev=None, **opts):
4797 """output the current or given revision of the project manifest
4797 """output the current or given revision of the project manifest
4798
4798
4799 Print a list of version controlled files for the given revision.
4799 Print a list of version controlled files for the given revision.
4800 If no revision is given, the first parent of the working directory
4800 If no revision is given, the first parent of the working directory
4801 is used, or the null revision if no revision is checked out.
4801 is used, or the null revision if no revision is checked out.
4802
4802
4803 With -v, print file permissions, symlink and executable bits.
4803 With -v, print file permissions, symlink and executable bits.
4804 With --debug, print file revision hashes.
4804 With --debug, print file revision hashes.
4805
4805
4806 If option --all is specified, the list of all files from all revisions
4806 If option --all is specified, the list of all files from all revisions
4807 is printed. This includes deleted and renamed files.
4807 is printed. This includes deleted and renamed files.
4808
4808
4809 Returns 0 on success.
4809 Returns 0 on success.
4810 """
4810 """
4811
4811
4812 fm = ui.formatter('manifest', opts)
4812 fm = ui.formatter('manifest', opts)
4813
4813
4814 if opts.get('all'):
4814 if opts.get('all'):
4815 if rev or node:
4815 if rev or node:
4816 raise error.Abort(_("can't specify a revision with --all"))
4816 raise error.Abort(_("can't specify a revision with --all"))
4817
4817
4818 res = []
4818 res = []
4819 prefix = "data/"
4819 prefix = "data/"
4820 suffix = ".i"
4820 suffix = ".i"
4821 plen = len(prefix)
4821 plen = len(prefix)
4822 slen = len(suffix)
4822 slen = len(suffix)
4823 lock = repo.lock()
4823 lock = repo.lock()
4824 try:
4824 try:
4825 for fn, b, size in repo.store.datafiles():
4825 for fn, b, size in repo.store.datafiles():
4826 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4826 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4827 res.append(fn[plen:-slen])
4827 res.append(fn[plen:-slen])
4828 finally:
4828 finally:
4829 lock.release()
4829 lock.release()
4830 for f in res:
4830 for f in res:
4831 fm.startitem()
4831 fm.startitem()
4832 fm.write("path", '%s\n', f)
4832 fm.write("path", '%s\n', f)
4833 fm.end()
4833 fm.end()
4834 return
4834 return
4835
4835
4836 if rev and node:
4836 if rev and node:
4837 raise error.Abort(_("please specify just one revision"))
4837 raise error.Abort(_("please specify just one revision"))
4838
4838
4839 if not node:
4839 if not node:
4840 node = rev
4840 node = rev
4841
4841
4842 char = {'l': '@', 'x': '*', '': ''}
4842 char = {'l': '@', 'x': '*', '': ''}
4843 mode = {'l': '644', 'x': '755', '': '644'}
4843 mode = {'l': '644', 'x': '755', '': '644'}
4844 ctx = scmutil.revsingle(repo, node)
4844 ctx = scmutil.revsingle(repo, node)
4845 mf = ctx.manifest()
4845 mf = ctx.manifest()
4846 for f in ctx:
4846 for f in ctx:
4847 fm.startitem()
4847 fm.startitem()
4848 fl = ctx[f].flags()
4848 fl = ctx[f].flags()
4849 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4849 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4850 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4850 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4851 fm.write('path', '%s\n', f)
4851 fm.write('path', '%s\n', f)
4852 fm.end()
4852 fm.end()
4853
4853
4854 @command('^merge',
4854 @command('^merge',
4855 [('f', 'force', None,
4855 [('f', 'force', None,
4856 _('force a merge including outstanding changes (DEPRECATED)')),
4856 _('force a merge including outstanding changes (DEPRECATED)')),
4857 ('r', 'rev', '', _('revision to merge'), _('REV')),
4857 ('r', 'rev', '', _('revision to merge'), _('REV')),
4858 ('P', 'preview', None,
4858 ('P', 'preview', None,
4859 _('review revisions to merge (no merge is performed)'))
4859 _('review revisions to merge (no merge is performed)'))
4860 ] + mergetoolopts,
4860 ] + mergetoolopts,
4861 _('[-P] [-f] [[-r] REV]'))
4861 _('[-P] [-f] [[-r] REV]'))
4862 def merge(ui, repo, node=None, **opts):
4862 def merge(ui, repo, node=None, **opts):
4863 """merge another revision into working directory
4863 """merge another revision into working directory
4864
4864
4865 The current working directory is updated with all changes made in
4865 The current working directory is updated with all changes made in
4866 the requested revision since the last common predecessor revision.
4866 the requested revision since the last common predecessor revision.
4867
4867
4868 Files that changed between either parent are marked as changed for
4868 Files that changed between either parent are marked as changed for
4869 the next commit and a commit must be performed before any further
4869 the next commit and a commit must be performed before any further
4870 updates to the repository are allowed. The next commit will have
4870 updates to the repository are allowed. The next commit will have
4871 two parents.
4871 two parents.
4872
4872
4873 ``--tool`` can be used to specify the merge tool used for file
4873 ``--tool`` can be used to specify the merge tool used for file
4874 merges. It overrides the HGMERGE environment variable and your
4874 merges. It overrides the HGMERGE environment variable and your
4875 configuration files. See :hg:`help merge-tools` for options.
4875 configuration files. See :hg:`help merge-tools` for options.
4876
4876
4877 If no revision is specified, the working directory's parent is a
4877 If no revision is specified, the working directory's parent is a
4878 head revision, and the current branch contains exactly one other
4878 head revision, and the current branch contains exactly one other
4879 head, the other head is merged with by default. Otherwise, an
4879 head, the other head is merged with by default. Otherwise, an
4880 explicit revision with which to merge with must be provided.
4880 explicit revision with which to merge with must be provided.
4881
4881
4882 :hg:`resolve` must be used to resolve unresolved files.
4882 :hg:`resolve` must be used to resolve unresolved files.
4883
4883
4884 To undo an uncommitted merge, use :hg:`update --clean .` which
4884 To undo an uncommitted merge, use :hg:`update --clean .` which
4885 will check out a clean copy of the original merge parent, losing
4885 will check out a clean copy of the original merge parent, losing
4886 all changes.
4886 all changes.
4887
4887
4888 Returns 0 on success, 1 if there are unresolved files.
4888 Returns 0 on success, 1 if there are unresolved files.
4889 """
4889 """
4890
4890
4891 if opts.get('rev') and node:
4891 if opts.get('rev') and node:
4892 raise error.Abort(_("please specify just one revision"))
4892 raise error.Abort(_("please specify just one revision"))
4893 if not node:
4893 if not node:
4894 node = opts.get('rev')
4894 node = opts.get('rev')
4895
4895
4896 if node:
4896 if node:
4897 node = scmutil.revsingle(repo, node).node()
4897 node = scmutil.revsingle(repo, node).node()
4898
4898
4899 if not node:
4899 if not node:
4900 node = scmutil.revsingle(repo, '_mergedefaultdest()').node()
4900 node = scmutil.revsingle(repo, '_mergedefaultdest()').node()
4901
4901
4902 if opts.get('preview'):
4902 if opts.get('preview'):
4903 # find nodes that are ancestors of p2 but not of p1
4903 # find nodes that are ancestors of p2 but not of p1
4904 p1 = repo.lookup('.')
4904 p1 = repo.lookup('.')
4905 p2 = repo.lookup(node)
4905 p2 = repo.lookup(node)
4906 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4906 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4907
4907
4908 displayer = cmdutil.show_changeset(ui, repo, opts)
4908 displayer = cmdutil.show_changeset(ui, repo, opts)
4909 for node in nodes:
4909 for node in nodes:
4910 displayer.show(repo[node])
4910 displayer.show(repo[node])
4911 displayer.close()
4911 displayer.close()
4912 return 0
4912 return 0
4913
4913
4914 try:
4914 try:
4915 # ui.forcemerge is an internal variable, do not document
4915 # ui.forcemerge is an internal variable, do not document
4916 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4916 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4917 return hg.merge(repo, node, force=opts.get('force'))
4917 return hg.merge(repo, node, force=opts.get('force'))
4918 finally:
4918 finally:
4919 ui.setconfig('ui', 'forcemerge', '', 'merge')
4919 ui.setconfig('ui', 'forcemerge', '', 'merge')
4920
4920
4921 @command('outgoing|out',
4921 @command('outgoing|out',
4922 [('f', 'force', None, _('run even when the destination is unrelated')),
4922 [('f', 'force', None, _('run even when the destination is unrelated')),
4923 ('r', 'rev', [],
4923 ('r', 'rev', [],
4924 _('a changeset intended to be included in the destination'), _('REV')),
4924 _('a changeset intended to be included in the destination'), _('REV')),
4925 ('n', 'newest-first', None, _('show newest record first')),
4925 ('n', 'newest-first', None, _('show newest record first')),
4926 ('B', 'bookmarks', False, _('compare bookmarks')),
4926 ('B', 'bookmarks', False, _('compare bookmarks')),
4927 ('b', 'branch', [], _('a specific branch you would like to push'),
4927 ('b', 'branch', [], _('a specific branch you would like to push'),
4928 _('BRANCH')),
4928 _('BRANCH')),
4929 ] + logopts + remoteopts + subrepoopts,
4929 ] + logopts + remoteopts + subrepoopts,
4930 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4930 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4931 def outgoing(ui, repo, dest=None, **opts):
4931 def outgoing(ui, repo, dest=None, **opts):
4932 """show changesets not found in the destination
4932 """show changesets not found in the destination
4933
4933
4934 Show changesets not found in the specified destination repository
4934 Show changesets not found in the specified destination repository
4935 or the default push location. These are the changesets that would
4935 or the default push location. These are the changesets that would
4936 be pushed if a push was requested.
4936 be pushed if a push was requested.
4937
4937
4938 See pull for details of valid destination formats.
4938 See pull for details of valid destination formats.
4939
4939
4940 .. container:: verbose
4940 .. container:: verbose
4941
4941
4942 With -B/--bookmarks, the result of bookmark comparison between
4942 With -B/--bookmarks, the result of bookmark comparison between
4943 local and remote repositories is displayed. With -v/--verbose,
4943 local and remote repositories is displayed. With -v/--verbose,
4944 status is also displayed for each bookmark like below::
4944 status is also displayed for each bookmark like below::
4945
4945
4946 BM1 01234567890a added
4946 BM1 01234567890a added
4947 BM2 deleted
4947 BM2 deleted
4948 BM3 234567890abc advanced
4948 BM3 234567890abc advanced
4949 BM4 34567890abcd diverged
4949 BM4 34567890abcd diverged
4950 BM5 4567890abcde changed
4950 BM5 4567890abcde changed
4951
4951
4952 The action taken when pushing depends on the
4952 The action taken when pushing depends on the
4953 status of each bookmark:
4953 status of each bookmark:
4954
4954
4955 :``added``: push with ``-B`` will create it
4955 :``added``: push with ``-B`` will create it
4956 :``deleted``: push with ``-B`` will delete it
4956 :``deleted``: push with ``-B`` will delete it
4957 :``advanced``: push will update it
4957 :``advanced``: push will update it
4958 :``diverged``: push with ``-B`` will update it
4958 :``diverged``: push with ``-B`` will update it
4959 :``changed``: push with ``-B`` will update it
4959 :``changed``: push with ``-B`` will update it
4960
4960
4961 From the point of view of pushing behavior, bookmarks
4961 From the point of view of pushing behavior, bookmarks
4962 existing only in the remote repository are treated as
4962 existing only in the remote repository are treated as
4963 ``deleted``, even if it is in fact added remotely.
4963 ``deleted``, even if it is in fact added remotely.
4964
4964
4965 Returns 0 if there are outgoing changes, 1 otherwise.
4965 Returns 0 if there are outgoing changes, 1 otherwise.
4966 """
4966 """
4967 if opts.get('graph'):
4967 if opts.get('graph'):
4968 cmdutil.checkunsupportedgraphflags([], opts)
4968 cmdutil.checkunsupportedgraphflags([], opts)
4969 o, other = hg._outgoing(ui, repo, dest, opts)
4969 o, other = hg._outgoing(ui, repo, dest, opts)
4970 if not o:
4970 if not o:
4971 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4971 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4972 return
4972 return
4973
4973
4974 revdag = cmdutil.graphrevs(repo, o, opts)
4974 revdag = cmdutil.graphrevs(repo, o, opts)
4975 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4975 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4976 showparents = [ctx.node() for ctx in repo[None].parents()]
4976 showparents = [ctx.node() for ctx in repo[None].parents()]
4977 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4977 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4978 graphmod.asciiedges)
4978 graphmod.asciiedges)
4979 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4979 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4980 return 0
4980 return 0
4981
4981
4982 if opts.get('bookmarks'):
4982 if opts.get('bookmarks'):
4983 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4983 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4984 dest, branches = hg.parseurl(dest, opts.get('branch'))
4984 dest, branches = hg.parseurl(dest, opts.get('branch'))
4985 other = hg.peer(repo, opts, dest)
4985 other = hg.peer(repo, opts, dest)
4986 if 'bookmarks' not in other.listkeys('namespaces'):
4986 if 'bookmarks' not in other.listkeys('namespaces'):
4987 ui.warn(_("remote doesn't support bookmarks\n"))
4987 ui.warn(_("remote doesn't support bookmarks\n"))
4988 return 0
4988 return 0
4989 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4989 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4990 return bookmarks.outgoing(ui, repo, other)
4990 return bookmarks.outgoing(ui, repo, other)
4991
4991
4992 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4992 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4993 try:
4993 try:
4994 return hg.outgoing(ui, repo, dest, opts)
4994 return hg.outgoing(ui, repo, dest, opts)
4995 finally:
4995 finally:
4996 del repo._subtoppath
4996 del repo._subtoppath
4997
4997
4998 @command('parents',
4998 @command('parents',
4999 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4999 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5000 ] + templateopts,
5000 ] + templateopts,
5001 _('[-r REV] [FILE]'),
5001 _('[-r REV] [FILE]'),
5002 inferrepo=True)
5002 inferrepo=True)
5003 def parents(ui, repo, file_=None, **opts):
5003 def parents(ui, repo, file_=None, **opts):
5004 """show the parents of the working directory or revision (DEPRECATED)
5004 """show the parents of the working directory or revision (DEPRECATED)
5005
5005
5006 Print the working directory's parent revisions. If a revision is
5006 Print the working directory's parent revisions. If a revision is
5007 given via -r/--rev, the parent of that revision will be printed.
5007 given via -r/--rev, the parent of that revision will be printed.
5008 If a file argument is given, the revision in which the file was
5008 If a file argument is given, the revision in which the file was
5009 last changed (before the working directory revision or the
5009 last changed (before the working directory revision or the
5010 argument to --rev if given) is printed.
5010 argument to --rev if given) is printed.
5011
5011
5012 See :hg:`summary` and :hg:`help revsets` for related information.
5012 See :hg:`summary` and :hg:`help revsets` for related information.
5013
5013
5014 Returns 0 on success.
5014 Returns 0 on success.
5015 """
5015 """
5016
5016
5017 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5017 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5018
5018
5019 if file_:
5019 if file_:
5020 m = scmutil.match(ctx, (file_,), opts)
5020 m = scmutil.match(ctx, (file_,), opts)
5021 if m.anypats() or len(m.files()) != 1:
5021 if m.anypats() or len(m.files()) != 1:
5022 raise error.Abort(_('can only specify an explicit filename'))
5022 raise error.Abort(_('can only specify an explicit filename'))
5023 file_ = m.files()[0]
5023 file_ = m.files()[0]
5024 filenodes = []
5024 filenodes = []
5025 for cp in ctx.parents():
5025 for cp in ctx.parents():
5026 if not cp:
5026 if not cp:
5027 continue
5027 continue
5028 try:
5028 try:
5029 filenodes.append(cp.filenode(file_))
5029 filenodes.append(cp.filenode(file_))
5030 except error.LookupError:
5030 except error.LookupError:
5031 pass
5031 pass
5032 if not filenodes:
5032 if not filenodes:
5033 raise error.Abort(_("'%s' not found in manifest!") % file_)
5033 raise error.Abort(_("'%s' not found in manifest!") % file_)
5034 p = []
5034 p = []
5035 for fn in filenodes:
5035 for fn in filenodes:
5036 fctx = repo.filectx(file_, fileid=fn)
5036 fctx = repo.filectx(file_, fileid=fn)
5037 p.append(fctx.node())
5037 p.append(fctx.node())
5038 else:
5038 else:
5039 p = [cp.node() for cp in ctx.parents()]
5039 p = [cp.node() for cp in ctx.parents()]
5040
5040
5041 displayer = cmdutil.show_changeset(ui, repo, opts)
5041 displayer = cmdutil.show_changeset(ui, repo, opts)
5042 for n in p:
5042 for n in p:
5043 if n != nullid:
5043 if n != nullid:
5044 displayer.show(repo[n])
5044 displayer.show(repo[n])
5045 displayer.close()
5045 displayer.close()
5046
5046
5047 @command('paths', [], _('[NAME]'), optionalrepo=True)
5047 @command('paths', [], _('[NAME]'), optionalrepo=True)
5048 def paths(ui, repo, search=None):
5048 def paths(ui, repo, search=None):
5049 """show aliases for remote repositories
5049 """show aliases for remote repositories
5050
5050
5051 Show definition of symbolic path name NAME. If no name is given,
5051 Show definition of symbolic path name NAME. If no name is given,
5052 show definition of all available names.
5052 show definition of all available names.
5053
5053
5054 Option -q/--quiet suppresses all output when searching for NAME
5054 Option -q/--quiet suppresses all output when searching for NAME
5055 and shows only the path names when listing all definitions.
5055 and shows only the path names when listing all definitions.
5056
5056
5057 Path names are defined in the [paths] section of your
5057 Path names are defined in the [paths] section of your
5058 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5058 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5059 repository, ``.hg/hgrc`` is used, too.
5059 repository, ``.hg/hgrc`` is used, too.
5060
5060
5061 The path names ``default`` and ``default-push`` have a special
5061 The path names ``default`` and ``default-push`` have a special
5062 meaning. When performing a push or pull operation, they are used
5062 meaning. When performing a push or pull operation, they are used
5063 as fallbacks if no location is specified on the command-line.
5063 as fallbacks if no location is specified on the command-line.
5064 When ``default-push`` is set, it will be used for push and
5064 When ``default-push`` is set, it will be used for push and
5065 ``default`` will be used for pull; otherwise ``default`` is used
5065 ``default`` will be used for pull; otherwise ``default`` is used
5066 as the fallback for both. When cloning a repository, the clone
5066 as the fallback for both. When cloning a repository, the clone
5067 source is written as ``default`` in ``.hg/hgrc``. Note that
5067 source is written as ``default`` in ``.hg/hgrc``. Note that
5068 ``default`` and ``default-push`` apply to all inbound (e.g.
5068 ``default`` and ``default-push`` apply to all inbound (e.g.
5069 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
5069 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
5070 :hg:`bundle`) operations.
5070 :hg:`bundle`) operations.
5071
5071
5072 See :hg:`help urls` for more information.
5072 See :hg:`help urls` for more information.
5073
5073
5074 Returns 0 on success.
5074 Returns 0 on success.
5075 """
5075 """
5076 if search:
5076 if search:
5077 for name, path in sorted(ui.paths.iteritems()):
5077 for name, path in sorted(ui.paths.iteritems()):
5078 if name == search:
5078 if name == search:
5079 ui.status("%s\n" % util.hidepassword(path.loc))
5079 ui.status("%s\n" % util.hidepassword(path.loc))
5080 return
5080 return
5081 if not ui.quiet:
5081 if not ui.quiet:
5082 ui.warn(_("not found!\n"))
5082 ui.warn(_("not found!\n"))
5083 return 1
5083 return 1
5084 else:
5084 else:
5085 for name, path in sorted(ui.paths.iteritems()):
5085 for name, path in sorted(ui.paths.iteritems()):
5086 if ui.quiet:
5086 if ui.quiet:
5087 ui.write("%s\n" % name)
5087 ui.write("%s\n" % name)
5088 else:
5088 else:
5089 ui.write("%s = %s\n" % (name,
5089 ui.write("%s = %s\n" % (name,
5090 util.hidepassword(path.loc)))
5090 util.hidepassword(path.loc)))
5091
5091
5092 @command('phase',
5092 @command('phase',
5093 [('p', 'public', False, _('set changeset phase to public')),
5093 [('p', 'public', False, _('set changeset phase to public')),
5094 ('d', 'draft', False, _('set changeset phase to draft')),
5094 ('d', 'draft', False, _('set changeset phase to draft')),
5095 ('s', 'secret', False, _('set changeset phase to secret')),
5095 ('s', 'secret', False, _('set changeset phase to secret')),
5096 ('f', 'force', False, _('allow to move boundary backward')),
5096 ('f', 'force', False, _('allow to move boundary backward')),
5097 ('r', 'rev', [], _('target revision'), _('REV')),
5097 ('r', 'rev', [], _('target revision'), _('REV')),
5098 ],
5098 ],
5099 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5099 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5100 def phase(ui, repo, *revs, **opts):
5100 def phase(ui, repo, *revs, **opts):
5101 """set or show the current phase name
5101 """set or show the current phase name
5102
5102
5103 With no argument, show the phase name of the current revision(s).
5103 With no argument, show the phase name of the current revision(s).
5104
5104
5105 With one of -p/--public, -d/--draft or -s/--secret, change the
5105 With one of -p/--public, -d/--draft or -s/--secret, change the
5106 phase value of the specified revisions.
5106 phase value of the specified revisions.
5107
5107
5108 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5108 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5109 lower phase to an higher phase. Phases are ordered as follows::
5109 lower phase to an higher phase. Phases are ordered as follows::
5110
5110
5111 public < draft < secret
5111 public < draft < secret
5112
5112
5113 Returns 0 on success, 1 if some phases could not be changed.
5113 Returns 0 on success, 1 if some phases could not be changed.
5114
5114
5115 (For more information about the phases concept, see :hg:`help phases`.)
5115 (For more information about the phases concept, see :hg:`help phases`.)
5116 """
5116 """
5117 # search for a unique phase argument
5117 # search for a unique phase argument
5118 targetphase = None
5118 targetphase = None
5119 for idx, name in enumerate(phases.phasenames):
5119 for idx, name in enumerate(phases.phasenames):
5120 if opts[name]:
5120 if opts[name]:
5121 if targetphase is not None:
5121 if targetphase is not None:
5122 raise error.Abort(_('only one phase can be specified'))
5122 raise error.Abort(_('only one phase can be specified'))
5123 targetphase = idx
5123 targetphase = idx
5124
5124
5125 # look for specified revision
5125 # look for specified revision
5126 revs = list(revs)
5126 revs = list(revs)
5127 revs.extend(opts['rev'])
5127 revs.extend(opts['rev'])
5128 if not revs:
5128 if not revs:
5129 # display both parents as the second parent phase can influence
5129 # display both parents as the second parent phase can influence
5130 # the phase of a merge commit
5130 # the phase of a merge commit
5131 revs = [c.rev() for c in repo[None].parents()]
5131 revs = [c.rev() for c in repo[None].parents()]
5132
5132
5133 revs = scmutil.revrange(repo, revs)
5133 revs = scmutil.revrange(repo, revs)
5134
5134
5135 lock = None
5135 lock = None
5136 ret = 0
5136 ret = 0
5137 if targetphase is None:
5137 if targetphase is None:
5138 # display
5138 # display
5139 for r in revs:
5139 for r in revs:
5140 ctx = repo[r]
5140 ctx = repo[r]
5141 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5141 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5142 else:
5142 else:
5143 tr = None
5143 tr = None
5144 lock = repo.lock()
5144 lock = repo.lock()
5145 try:
5145 try:
5146 tr = repo.transaction("phase")
5146 tr = repo.transaction("phase")
5147 # set phase
5147 # set phase
5148 if not revs:
5148 if not revs:
5149 raise error.Abort(_('empty revision set'))
5149 raise error.Abort(_('empty revision set'))
5150 nodes = [repo[r].node() for r in revs]
5150 nodes = [repo[r].node() for r in revs]
5151 # moving revision from public to draft may hide them
5151 # moving revision from public to draft may hide them
5152 # We have to check result on an unfiltered repository
5152 # We have to check result on an unfiltered repository
5153 unfi = repo.unfiltered()
5153 unfi = repo.unfiltered()
5154 getphase = unfi._phasecache.phase
5154 getphase = unfi._phasecache.phase
5155 olddata = [getphase(unfi, r) for r in unfi]
5155 olddata = [getphase(unfi, r) for r in unfi]
5156 phases.advanceboundary(repo, tr, targetphase, nodes)
5156 phases.advanceboundary(repo, tr, targetphase, nodes)
5157 if opts['force']:
5157 if opts['force']:
5158 phases.retractboundary(repo, tr, targetphase, nodes)
5158 phases.retractboundary(repo, tr, targetphase, nodes)
5159 tr.close()
5159 tr.close()
5160 finally:
5160 finally:
5161 if tr is not None:
5161 if tr is not None:
5162 tr.release()
5162 tr.release()
5163 lock.release()
5163 lock.release()
5164 getphase = unfi._phasecache.phase
5164 getphase = unfi._phasecache.phase
5165 newdata = [getphase(unfi, r) for r in unfi]
5165 newdata = [getphase(unfi, r) for r in unfi]
5166 changes = sum(newdata[r] != olddata[r] for r in unfi)
5166 changes = sum(newdata[r] != olddata[r] for r in unfi)
5167 cl = unfi.changelog
5167 cl = unfi.changelog
5168 rejected = [n for n in nodes
5168 rejected = [n for n in nodes
5169 if newdata[cl.rev(n)] < targetphase]
5169 if newdata[cl.rev(n)] < targetphase]
5170 if rejected:
5170 if rejected:
5171 ui.warn(_('cannot move %i changesets to a higher '
5171 ui.warn(_('cannot move %i changesets to a higher '
5172 'phase, use --force\n') % len(rejected))
5172 'phase, use --force\n') % len(rejected))
5173 ret = 1
5173 ret = 1
5174 if changes:
5174 if changes:
5175 msg = _('phase changed for %i changesets\n') % changes
5175 msg = _('phase changed for %i changesets\n') % changes
5176 if ret:
5176 if ret:
5177 ui.status(msg)
5177 ui.status(msg)
5178 else:
5178 else:
5179 ui.note(msg)
5179 ui.note(msg)
5180 else:
5180 else:
5181 ui.warn(_('no phases changed\n'))
5181 ui.warn(_('no phases changed\n'))
5182 return ret
5182 return ret
5183
5183
5184 def postincoming(ui, repo, modheads, optupdate, checkout):
5184 def postincoming(ui, repo, modheads, optupdate, checkout):
5185 if modheads == 0:
5185 if modheads == 0:
5186 return
5186 return
5187 if optupdate:
5187 if optupdate:
5188 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5189 try:
5188 try:
5189 brev = checkout
5190 movemarkfrom = None
5191 if not checkout:
5192 updata = destutil.destupdate(repo)
5193 checkout, movemarkfrom, brev = updata
5190 ret = hg.update(repo, checkout)
5194 ret = hg.update(repo, checkout)
5191 except error.Abort as inst:
5195 except error.Abort as inst:
5192 ui.warn(_("not updating: %s\n") % str(inst))
5196 ui.warn(_("not updating: %s\n") % str(inst))
5193 if inst.hint:
5197 if inst.hint:
5194 ui.warn(_("(%s)\n") % inst.hint)
5198 ui.warn(_("(%s)\n") % inst.hint)
5195 return 0
5199 return 0
5196 if not ret and not checkout:
5200 if not ret and not checkout:
5197 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5201 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5198 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5202 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5199 return ret
5203 return ret
5200 if modheads > 1:
5204 if modheads > 1:
5201 currentbranchheads = len(repo.branchheads())
5205 currentbranchheads = len(repo.branchheads())
5202 if currentbranchheads == modheads:
5206 if currentbranchheads == modheads:
5203 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5207 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5204 elif currentbranchheads > 1:
5208 elif currentbranchheads > 1:
5205 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5209 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5206 "merge)\n"))
5210 "merge)\n"))
5207 else:
5211 else:
5208 ui.status(_("(run 'hg heads' to see heads)\n"))
5212 ui.status(_("(run 'hg heads' to see heads)\n"))
5209 else:
5213 else:
5210 ui.status(_("(run 'hg update' to get a working copy)\n"))
5214 ui.status(_("(run 'hg update' to get a working copy)\n"))
5211
5215
5212 @command('^pull',
5216 @command('^pull',
5213 [('u', 'update', None,
5217 [('u', 'update', None,
5214 _('update to new branch head if changesets were pulled')),
5218 _('update to new branch head if changesets were pulled')),
5215 ('f', 'force', None, _('run even when remote repository is unrelated')),
5219 ('f', 'force', None, _('run even when remote repository is unrelated')),
5216 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5220 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5217 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5221 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5218 ('b', 'branch', [], _('a specific branch you would like to pull'),
5222 ('b', 'branch', [], _('a specific branch you would like to pull'),
5219 _('BRANCH')),
5223 _('BRANCH')),
5220 ] + remoteopts,
5224 ] + remoteopts,
5221 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5225 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5222 def pull(ui, repo, source="default", **opts):
5226 def pull(ui, repo, source="default", **opts):
5223 """pull changes from the specified source
5227 """pull changes from the specified source
5224
5228
5225 Pull changes from a remote repository to a local one.
5229 Pull changes from a remote repository to a local one.
5226
5230
5227 This finds all changes from the repository at the specified path
5231 This finds all changes from the repository at the specified path
5228 or URL and adds them to a local repository (the current one unless
5232 or URL and adds them to a local repository (the current one unless
5229 -R is specified). By default, this does not update the copy of the
5233 -R is specified). By default, this does not update the copy of the
5230 project in the working directory.
5234 project in the working directory.
5231
5235
5232 Use :hg:`incoming` if you want to see what would have been added
5236 Use :hg:`incoming` if you want to see what would have been added
5233 by a pull at the time you issued this command. If you then decide
5237 by a pull at the time you issued this command. If you then decide
5234 to add those changes to the repository, you should use :hg:`pull
5238 to add those changes to the repository, you should use :hg:`pull
5235 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5239 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5236
5240
5237 If SOURCE is omitted, the 'default' path will be used.
5241 If SOURCE is omitted, the 'default' path will be used.
5238 See :hg:`help urls` for more information.
5242 See :hg:`help urls` for more information.
5239
5243
5240 Returns 0 on success, 1 if an update had unresolved files.
5244 Returns 0 on success, 1 if an update had unresolved files.
5241 """
5245 """
5242 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5246 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5243 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5247 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5244 other = hg.peer(repo, opts, source)
5248 other = hg.peer(repo, opts, source)
5245 try:
5249 try:
5246 revs, checkout = hg.addbranchrevs(repo, other, branches,
5250 revs, checkout = hg.addbranchrevs(repo, other, branches,
5247 opts.get('rev'))
5251 opts.get('rev'))
5248
5252
5249
5253
5250 pullopargs = {}
5254 pullopargs = {}
5251 if opts.get('bookmark'):
5255 if opts.get('bookmark'):
5252 if not revs:
5256 if not revs:
5253 revs = []
5257 revs = []
5254 # The list of bookmark used here is not the one used to actually
5258 # The list of bookmark used here is not the one used to actually
5255 # update the bookmark name. This can result in the revision pulled
5259 # update the bookmark name. This can result in the revision pulled
5256 # not ending up with the name of the bookmark because of a race
5260 # not ending up with the name of the bookmark because of a race
5257 # condition on the server. (See issue 4689 for details)
5261 # condition on the server. (See issue 4689 for details)
5258 remotebookmarks = other.listkeys('bookmarks')
5262 remotebookmarks = other.listkeys('bookmarks')
5259 pullopargs['remotebookmarks'] = remotebookmarks
5263 pullopargs['remotebookmarks'] = remotebookmarks
5260 for b in opts['bookmark']:
5264 for b in opts['bookmark']:
5261 if b not in remotebookmarks:
5265 if b not in remotebookmarks:
5262 raise error.Abort(_('remote bookmark %s not found!') % b)
5266 raise error.Abort(_('remote bookmark %s not found!') % b)
5263 revs.append(remotebookmarks[b])
5267 revs.append(remotebookmarks[b])
5264
5268
5265 if revs:
5269 if revs:
5266 try:
5270 try:
5267 # When 'rev' is a bookmark name, we cannot guarantee that it
5271 # When 'rev' is a bookmark name, we cannot guarantee that it
5268 # will be updated with that name because of a race condition
5272 # will be updated with that name because of a race condition
5269 # server side. (See issue 4689 for details)
5273 # server side. (See issue 4689 for details)
5270 oldrevs = revs
5274 oldrevs = revs
5271 revs = [] # actually, nodes
5275 revs = [] # actually, nodes
5272 for r in oldrevs:
5276 for r in oldrevs:
5273 node = other.lookup(r)
5277 node = other.lookup(r)
5274 revs.append(node)
5278 revs.append(node)
5275 if r == checkout:
5279 if r == checkout:
5276 checkout = node
5280 checkout = node
5277 except error.CapabilityError:
5281 except error.CapabilityError:
5278 err = _("other repository doesn't support revision lookup, "
5282 err = _("other repository doesn't support revision lookup, "
5279 "so a rev cannot be specified.")
5283 "so a rev cannot be specified.")
5280 raise error.Abort(err)
5284 raise error.Abort(err)
5281
5285
5282 modheads = exchange.pull(repo, other, heads=revs,
5286 modheads = exchange.pull(repo, other, heads=revs,
5283 force=opts.get('force'),
5287 force=opts.get('force'),
5284 bookmarks=opts.get('bookmark', ()),
5288 bookmarks=opts.get('bookmark', ()),
5285 opargs=pullopargs).cgresult
5289 opargs=pullopargs).cgresult
5286 if checkout:
5290 if checkout:
5287 checkout = str(repo.changelog.rev(checkout))
5291 checkout = str(repo.changelog.rev(checkout))
5288 repo._subtoppath = source
5292 repo._subtoppath = source
5289 try:
5293 try:
5290 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5294 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5291
5295
5292 finally:
5296 finally:
5293 del repo._subtoppath
5297 del repo._subtoppath
5294
5298
5295 finally:
5299 finally:
5296 other.close()
5300 other.close()
5297 return ret
5301 return ret
5298
5302
5299 @command('^push',
5303 @command('^push',
5300 [('f', 'force', None, _('force push')),
5304 [('f', 'force', None, _('force push')),
5301 ('r', 'rev', [],
5305 ('r', 'rev', [],
5302 _('a changeset intended to be included in the destination'),
5306 _('a changeset intended to be included in the destination'),
5303 _('REV')),
5307 _('REV')),
5304 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5308 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5305 ('b', 'branch', [],
5309 ('b', 'branch', [],
5306 _('a specific branch you would like to push'), _('BRANCH')),
5310 _('a specific branch you would like to push'), _('BRANCH')),
5307 ('', 'new-branch', False, _('allow pushing a new branch')),
5311 ('', 'new-branch', False, _('allow pushing a new branch')),
5308 ] + remoteopts,
5312 ] + remoteopts,
5309 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5313 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5310 def push(ui, repo, dest=None, **opts):
5314 def push(ui, repo, dest=None, **opts):
5311 """push changes to the specified destination
5315 """push changes to the specified destination
5312
5316
5313 Push changesets from the local repository to the specified
5317 Push changesets from the local repository to the specified
5314 destination.
5318 destination.
5315
5319
5316 This operation is symmetrical to pull: it is identical to a pull
5320 This operation is symmetrical to pull: it is identical to a pull
5317 in the destination repository from the current one.
5321 in the destination repository from the current one.
5318
5322
5319 By default, push will not allow creation of new heads at the
5323 By default, push will not allow creation of new heads at the
5320 destination, since multiple heads would make it unclear which head
5324 destination, since multiple heads would make it unclear which head
5321 to use. In this situation, it is recommended to pull and merge
5325 to use. In this situation, it is recommended to pull and merge
5322 before pushing.
5326 before pushing.
5323
5327
5324 Use --new-branch if you want to allow push to create a new named
5328 Use --new-branch if you want to allow push to create a new named
5325 branch that is not present at the destination. This allows you to
5329 branch that is not present at the destination. This allows you to
5326 only create a new branch without forcing other changes.
5330 only create a new branch without forcing other changes.
5327
5331
5328 .. note::
5332 .. note::
5329
5333
5330 Extra care should be taken with the -f/--force option,
5334 Extra care should be taken with the -f/--force option,
5331 which will push all new heads on all branches, an action which will
5335 which will push all new heads on all branches, an action which will
5332 almost always cause confusion for collaborators.
5336 almost always cause confusion for collaborators.
5333
5337
5334 If -r/--rev is used, the specified revision and all its ancestors
5338 If -r/--rev is used, the specified revision and all its ancestors
5335 will be pushed to the remote repository.
5339 will be pushed to the remote repository.
5336
5340
5337 If -B/--bookmark is used, the specified bookmarked revision, its
5341 If -B/--bookmark is used, the specified bookmarked revision, its
5338 ancestors, and the bookmark will be pushed to the remote
5342 ancestors, and the bookmark will be pushed to the remote
5339 repository.
5343 repository.
5340
5344
5341 Please see :hg:`help urls` for important details about ``ssh://``
5345 Please see :hg:`help urls` for important details about ``ssh://``
5342 URLs. If DESTINATION is omitted, a default path will be used.
5346 URLs. If DESTINATION is omitted, a default path will be used.
5343
5347
5344 Returns 0 if push was successful, 1 if nothing to push.
5348 Returns 0 if push was successful, 1 if nothing to push.
5345 """
5349 """
5346
5350
5347 if opts.get('bookmark'):
5351 if opts.get('bookmark'):
5348 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5352 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5349 for b in opts['bookmark']:
5353 for b in opts['bookmark']:
5350 # translate -B options to -r so changesets get pushed
5354 # translate -B options to -r so changesets get pushed
5351 if b in repo._bookmarks:
5355 if b in repo._bookmarks:
5352 opts.setdefault('rev', []).append(b)
5356 opts.setdefault('rev', []).append(b)
5353 else:
5357 else:
5354 # if we try to push a deleted bookmark, translate it to null
5358 # if we try to push a deleted bookmark, translate it to null
5355 # this lets simultaneous -r, -b options continue working
5359 # this lets simultaneous -r, -b options continue working
5356 opts.setdefault('rev', []).append("null")
5360 opts.setdefault('rev', []).append("null")
5357
5361
5358 path = ui.paths.getpath(dest, default='default')
5362 path = ui.paths.getpath(dest, default='default')
5359 if not path:
5363 if not path:
5360 raise error.Abort(_('default repository not configured!'),
5364 raise error.Abort(_('default repository not configured!'),
5361 hint=_('see the "path" section in "hg help config"'))
5365 hint=_('see the "path" section in "hg help config"'))
5362 dest, branches = path.pushloc, (path.branch, opts.get('branch') or [])
5366 dest, branches = path.pushloc, (path.branch, opts.get('branch') or [])
5363 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5367 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5364 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5368 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5365 other = hg.peer(repo, opts, dest)
5369 other = hg.peer(repo, opts, dest)
5366
5370
5367 if revs:
5371 if revs:
5368 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5372 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5369 if not revs:
5373 if not revs:
5370 raise error.Abort(_("specified revisions evaluate to an empty set"),
5374 raise error.Abort(_("specified revisions evaluate to an empty set"),
5371 hint=_("use different revision arguments"))
5375 hint=_("use different revision arguments"))
5372
5376
5373 repo._subtoppath = dest
5377 repo._subtoppath = dest
5374 try:
5378 try:
5375 # push subrepos depth-first for coherent ordering
5379 # push subrepos depth-first for coherent ordering
5376 c = repo['']
5380 c = repo['']
5377 subs = c.substate # only repos that are committed
5381 subs = c.substate # only repos that are committed
5378 for s in sorted(subs):
5382 for s in sorted(subs):
5379 result = c.sub(s).push(opts)
5383 result = c.sub(s).push(opts)
5380 if result == 0:
5384 if result == 0:
5381 return not result
5385 return not result
5382 finally:
5386 finally:
5383 del repo._subtoppath
5387 del repo._subtoppath
5384 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5388 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5385 newbranch=opts.get('new_branch'),
5389 newbranch=opts.get('new_branch'),
5386 bookmarks=opts.get('bookmark', ()))
5390 bookmarks=opts.get('bookmark', ()))
5387
5391
5388 result = not pushop.cgresult
5392 result = not pushop.cgresult
5389
5393
5390 if pushop.bkresult is not None:
5394 if pushop.bkresult is not None:
5391 if pushop.bkresult == 2:
5395 if pushop.bkresult == 2:
5392 result = 2
5396 result = 2
5393 elif not result and pushop.bkresult:
5397 elif not result and pushop.bkresult:
5394 result = 2
5398 result = 2
5395
5399
5396 return result
5400 return result
5397
5401
5398 @command('recover', [])
5402 @command('recover', [])
5399 def recover(ui, repo):
5403 def recover(ui, repo):
5400 """roll back an interrupted transaction
5404 """roll back an interrupted transaction
5401
5405
5402 Recover from an interrupted commit or pull.
5406 Recover from an interrupted commit or pull.
5403
5407
5404 This command tries to fix the repository status after an
5408 This command tries to fix the repository status after an
5405 interrupted operation. It should only be necessary when Mercurial
5409 interrupted operation. It should only be necessary when Mercurial
5406 suggests it.
5410 suggests it.
5407
5411
5408 Returns 0 if successful, 1 if nothing to recover or verify fails.
5412 Returns 0 if successful, 1 if nothing to recover or verify fails.
5409 """
5413 """
5410 if repo.recover():
5414 if repo.recover():
5411 return hg.verify(repo)
5415 return hg.verify(repo)
5412 return 1
5416 return 1
5413
5417
5414 @command('^remove|rm',
5418 @command('^remove|rm',
5415 [('A', 'after', None, _('record delete for missing files')),
5419 [('A', 'after', None, _('record delete for missing files')),
5416 ('f', 'force', None,
5420 ('f', 'force', None,
5417 _('remove (and delete) file even if added or modified')),
5421 _('remove (and delete) file even if added or modified')),
5418 ] + subrepoopts + walkopts,
5422 ] + subrepoopts + walkopts,
5419 _('[OPTION]... FILE...'),
5423 _('[OPTION]... FILE...'),
5420 inferrepo=True)
5424 inferrepo=True)
5421 def remove(ui, repo, *pats, **opts):
5425 def remove(ui, repo, *pats, **opts):
5422 """remove the specified files on the next commit
5426 """remove the specified files on the next commit
5423
5427
5424 Schedule the indicated files for removal from the current branch.
5428 Schedule the indicated files for removal from the current branch.
5425
5429
5426 This command schedules the files to be removed at the next commit.
5430 This command schedules the files to be removed at the next commit.
5427 To undo a remove before that, see :hg:`revert`. To undo added
5431 To undo a remove before that, see :hg:`revert`. To undo added
5428 files, see :hg:`forget`.
5432 files, see :hg:`forget`.
5429
5433
5430 .. container:: verbose
5434 .. container:: verbose
5431
5435
5432 -A/--after can be used to remove only files that have already
5436 -A/--after can be used to remove only files that have already
5433 been deleted, -f/--force can be used to force deletion, and -Af
5437 been deleted, -f/--force can be used to force deletion, and -Af
5434 can be used to remove files from the next revision without
5438 can be used to remove files from the next revision without
5435 deleting them from the working directory.
5439 deleting them from the working directory.
5436
5440
5437 The following table details the behavior of remove for different
5441 The following table details the behavior of remove for different
5438 file states (columns) and option combinations (rows). The file
5442 file states (columns) and option combinations (rows). The file
5439 states are Added [A], Clean [C], Modified [M] and Missing [!]
5443 states are Added [A], Clean [C], Modified [M] and Missing [!]
5440 (as reported by :hg:`status`). The actions are Warn, Remove
5444 (as reported by :hg:`status`). The actions are Warn, Remove
5441 (from branch) and Delete (from disk):
5445 (from branch) and Delete (from disk):
5442
5446
5443 ========= == == == ==
5447 ========= == == == ==
5444 opt/state A C M !
5448 opt/state A C M !
5445 ========= == == == ==
5449 ========= == == == ==
5446 none W RD W R
5450 none W RD W R
5447 -f R RD RD R
5451 -f R RD RD R
5448 -A W W W R
5452 -A W W W R
5449 -Af R R R R
5453 -Af R R R R
5450 ========= == == == ==
5454 ========= == == == ==
5451
5455
5452 Note that remove never deletes files in Added [A] state from the
5456 Note that remove never deletes files in Added [A] state from the
5453 working directory, not even if option --force is specified.
5457 working directory, not even if option --force is specified.
5454
5458
5455 Returns 0 on success, 1 if any warnings encountered.
5459 Returns 0 on success, 1 if any warnings encountered.
5456 """
5460 """
5457
5461
5458 after, force = opts.get('after'), opts.get('force')
5462 after, force = opts.get('after'), opts.get('force')
5459 if not pats and not after:
5463 if not pats and not after:
5460 raise error.Abort(_('no files specified'))
5464 raise error.Abort(_('no files specified'))
5461
5465
5462 m = scmutil.match(repo[None], pats, opts)
5466 m = scmutil.match(repo[None], pats, opts)
5463 subrepos = opts.get('subrepos')
5467 subrepos = opts.get('subrepos')
5464 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5468 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5465
5469
5466 @command('rename|move|mv',
5470 @command('rename|move|mv',
5467 [('A', 'after', None, _('record a rename that has already occurred')),
5471 [('A', 'after', None, _('record a rename that has already occurred')),
5468 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5472 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5469 ] + walkopts + dryrunopts,
5473 ] + walkopts + dryrunopts,
5470 _('[OPTION]... SOURCE... DEST'))
5474 _('[OPTION]... SOURCE... DEST'))
5471 def rename(ui, repo, *pats, **opts):
5475 def rename(ui, repo, *pats, **opts):
5472 """rename files; equivalent of copy + remove
5476 """rename files; equivalent of copy + remove
5473
5477
5474 Mark dest as copies of sources; mark sources for deletion. If dest
5478 Mark dest as copies of sources; mark sources for deletion. If dest
5475 is a directory, copies are put in that directory. If dest is a
5479 is a directory, copies are put in that directory. If dest is a
5476 file, there can only be one source.
5480 file, there can only be one source.
5477
5481
5478 By default, this command copies the contents of files as they
5482 By default, this command copies the contents of files as they
5479 exist in the working directory. If invoked with -A/--after, the
5483 exist in the working directory. If invoked with -A/--after, the
5480 operation is recorded, but no copying is performed.
5484 operation is recorded, but no copying is performed.
5481
5485
5482 This command takes effect at the next commit. To undo a rename
5486 This command takes effect at the next commit. To undo a rename
5483 before that, see :hg:`revert`.
5487 before that, see :hg:`revert`.
5484
5488
5485 Returns 0 on success, 1 if errors are encountered.
5489 Returns 0 on success, 1 if errors are encountered.
5486 """
5490 """
5487 wlock = repo.wlock(False)
5491 wlock = repo.wlock(False)
5488 try:
5492 try:
5489 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5493 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5490 finally:
5494 finally:
5491 wlock.release()
5495 wlock.release()
5492
5496
5493 @command('resolve',
5497 @command('resolve',
5494 [('a', 'all', None, _('select all unresolved files')),
5498 [('a', 'all', None, _('select all unresolved files')),
5495 ('l', 'list', None, _('list state of files needing merge')),
5499 ('l', 'list', None, _('list state of files needing merge')),
5496 ('m', 'mark', None, _('mark files as resolved')),
5500 ('m', 'mark', None, _('mark files as resolved')),
5497 ('u', 'unmark', None, _('mark files as unresolved')),
5501 ('u', 'unmark', None, _('mark files as unresolved')),
5498 ('n', 'no-status', None, _('hide status prefix'))]
5502 ('n', 'no-status', None, _('hide status prefix'))]
5499 + mergetoolopts + walkopts + formatteropts,
5503 + mergetoolopts + walkopts + formatteropts,
5500 _('[OPTION]... [FILE]...'),
5504 _('[OPTION]... [FILE]...'),
5501 inferrepo=True)
5505 inferrepo=True)
5502 def resolve(ui, repo, *pats, **opts):
5506 def resolve(ui, repo, *pats, **opts):
5503 """redo merges or set/view the merge status of files
5507 """redo merges or set/view the merge status of files
5504
5508
5505 Merges with unresolved conflicts are often the result of
5509 Merges with unresolved conflicts are often the result of
5506 non-interactive merging using the ``internal:merge`` configuration
5510 non-interactive merging using the ``internal:merge`` configuration
5507 setting, or a command-line merge tool like ``diff3``. The resolve
5511 setting, or a command-line merge tool like ``diff3``. The resolve
5508 command is used to manage the files involved in a merge, after
5512 command is used to manage the files involved in a merge, after
5509 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5513 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5510 working directory must have two parents). See :hg:`help
5514 working directory must have two parents). See :hg:`help
5511 merge-tools` for information on configuring merge tools.
5515 merge-tools` for information on configuring merge tools.
5512
5516
5513 The resolve command can be used in the following ways:
5517 The resolve command can be used in the following ways:
5514
5518
5515 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5519 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5516 files, discarding any previous merge attempts. Re-merging is not
5520 files, discarding any previous merge attempts. Re-merging is not
5517 performed for files already marked as resolved. Use ``--all/-a``
5521 performed for files already marked as resolved. Use ``--all/-a``
5518 to select all unresolved files. ``--tool`` can be used to specify
5522 to select all unresolved files. ``--tool`` can be used to specify
5519 the merge tool used for the given files. It overrides the HGMERGE
5523 the merge tool used for the given files. It overrides the HGMERGE
5520 environment variable and your configuration files. Previous file
5524 environment variable and your configuration files. Previous file
5521 contents are saved with a ``.orig`` suffix.
5525 contents are saved with a ``.orig`` suffix.
5522
5526
5523 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5527 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5524 (e.g. after having manually fixed-up the files). The default is
5528 (e.g. after having manually fixed-up the files). The default is
5525 to mark all unresolved files.
5529 to mark all unresolved files.
5526
5530
5527 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5531 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5528 default is to mark all resolved files.
5532 default is to mark all resolved files.
5529
5533
5530 - :hg:`resolve -l`: list files which had or still have conflicts.
5534 - :hg:`resolve -l`: list files which had or still have conflicts.
5531 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5535 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5532
5536
5533 Note that Mercurial will not let you commit files with unresolved
5537 Note that Mercurial will not let you commit files with unresolved
5534 merge conflicts. You must use :hg:`resolve -m ...` before you can
5538 merge conflicts. You must use :hg:`resolve -m ...` before you can
5535 commit after a conflicting merge.
5539 commit after a conflicting merge.
5536
5540
5537 Returns 0 on success, 1 if any files fail a resolve attempt.
5541 Returns 0 on success, 1 if any files fail a resolve attempt.
5538 """
5542 """
5539
5543
5540 all, mark, unmark, show, nostatus = \
5544 all, mark, unmark, show, nostatus = \
5541 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5545 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5542
5546
5543 if (show and (mark or unmark)) or (mark and unmark):
5547 if (show and (mark or unmark)) or (mark and unmark):
5544 raise error.Abort(_("too many options specified"))
5548 raise error.Abort(_("too many options specified"))
5545 if pats and all:
5549 if pats and all:
5546 raise error.Abort(_("can't specify --all and patterns"))
5550 raise error.Abort(_("can't specify --all and patterns"))
5547 if not (all or pats or show or mark or unmark):
5551 if not (all or pats or show or mark or unmark):
5548 raise error.Abort(_('no files or directories specified'),
5552 raise error.Abort(_('no files or directories specified'),
5549 hint=('use --all to re-merge all unresolved files'))
5553 hint=('use --all to re-merge all unresolved files'))
5550
5554
5551 if show:
5555 if show:
5552 fm = ui.formatter('resolve', opts)
5556 fm = ui.formatter('resolve', opts)
5553 ms = mergemod.mergestate(repo)
5557 ms = mergemod.mergestate(repo)
5554 m = scmutil.match(repo[None], pats, opts)
5558 m = scmutil.match(repo[None], pats, opts)
5555 for f in ms:
5559 for f in ms:
5556 if not m(f):
5560 if not m(f):
5557 continue
5561 continue
5558 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5562 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5559 fm.startitem()
5563 fm.startitem()
5560 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5564 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5561 fm.write('path', '%s\n', f, label=l)
5565 fm.write('path', '%s\n', f, label=l)
5562 fm.end()
5566 fm.end()
5563 return 0
5567 return 0
5564
5568
5565 wlock = repo.wlock()
5569 wlock = repo.wlock()
5566 try:
5570 try:
5567 ms = mergemod.mergestate(repo)
5571 ms = mergemod.mergestate(repo)
5568
5572
5569 if not (ms.active() or repo.dirstate.p2() != nullid):
5573 if not (ms.active() or repo.dirstate.p2() != nullid):
5570 raise error.Abort(
5574 raise error.Abort(
5571 _('resolve command not applicable when not merging'))
5575 _('resolve command not applicable when not merging'))
5572
5576
5573 m = scmutil.match(repo[None], pats, opts)
5577 m = scmutil.match(repo[None], pats, opts)
5574 ret = 0
5578 ret = 0
5575 didwork = False
5579 didwork = False
5576
5580
5577 tocomplete = []
5581 tocomplete = []
5578 for f in ms:
5582 for f in ms:
5579 if not m(f):
5583 if not m(f):
5580 continue
5584 continue
5581
5585
5582 didwork = True
5586 didwork = True
5583
5587
5584 if mark:
5588 if mark:
5585 ms.mark(f, "r")
5589 ms.mark(f, "r")
5586 elif unmark:
5590 elif unmark:
5587 ms.mark(f, "u")
5591 ms.mark(f, "u")
5588 else:
5592 else:
5589 wctx = repo[None]
5593 wctx = repo[None]
5590
5594
5591 # backup pre-resolve (merge uses .orig for its own purposes)
5595 # backup pre-resolve (merge uses .orig for its own purposes)
5592 a = repo.wjoin(f)
5596 a = repo.wjoin(f)
5593 util.copyfile(a, a + ".resolve")
5597 util.copyfile(a, a + ".resolve")
5594
5598
5595 try:
5599 try:
5596 # preresolve file
5600 # preresolve file
5597 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5601 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5598 'resolve')
5602 'resolve')
5599 complete, r = ms.preresolve(f, wctx)
5603 complete, r = ms.preresolve(f, wctx)
5600 if not complete:
5604 if not complete:
5601 tocomplete.append(f)
5605 tocomplete.append(f)
5602 elif r:
5606 elif r:
5603 ret = 1
5607 ret = 1
5604 finally:
5608 finally:
5605 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5609 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5606 ms.commit()
5610 ms.commit()
5607
5611
5608 # replace filemerge's .orig file with our resolve file
5612 # replace filemerge's .orig file with our resolve file
5609 # for files in tocomplete, ms.resolve will not overwrite
5613 # for files in tocomplete, ms.resolve will not overwrite
5610 # .orig -- only preresolve does
5614 # .orig -- only preresolve does
5611 util.rename(a + ".resolve", a + ".orig")
5615 util.rename(a + ".resolve", a + ".orig")
5612
5616
5613 for f in tocomplete:
5617 for f in tocomplete:
5614 try:
5618 try:
5615 # resolve file
5619 # resolve file
5616 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5620 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5617 'resolve')
5621 'resolve')
5618 r = ms.resolve(f, wctx)
5622 r = ms.resolve(f, wctx)
5619 if r:
5623 if r:
5620 ret = 1
5624 ret = 1
5621 finally:
5625 finally:
5622 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5626 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5623 ms.commit()
5627 ms.commit()
5624
5628
5625 ms.commit()
5629 ms.commit()
5626
5630
5627 if not didwork and pats:
5631 if not didwork and pats:
5628 ui.warn(_("arguments do not match paths that need resolving\n"))
5632 ui.warn(_("arguments do not match paths that need resolving\n"))
5629
5633
5630 finally:
5634 finally:
5631 wlock.release()
5635 wlock.release()
5632
5636
5633 # Nudge users into finishing an unfinished operation
5637 # Nudge users into finishing an unfinished operation
5634 if not list(ms.unresolved()):
5638 if not list(ms.unresolved()):
5635 ui.status(_('(no more unresolved files)\n'))
5639 ui.status(_('(no more unresolved files)\n'))
5636
5640
5637 return ret
5641 return ret
5638
5642
5639 @command('revert',
5643 @command('revert',
5640 [('a', 'all', None, _('revert all changes when no arguments given')),
5644 [('a', 'all', None, _('revert all changes when no arguments given')),
5641 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5645 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5642 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5646 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5643 ('C', 'no-backup', None, _('do not save backup copies of files')),
5647 ('C', 'no-backup', None, _('do not save backup copies of files')),
5644 ('i', 'interactive', None,
5648 ('i', 'interactive', None,
5645 _('interactively select the changes (EXPERIMENTAL)')),
5649 _('interactively select the changes (EXPERIMENTAL)')),
5646 ] + walkopts + dryrunopts,
5650 ] + walkopts + dryrunopts,
5647 _('[OPTION]... [-r REV] [NAME]...'))
5651 _('[OPTION]... [-r REV] [NAME]...'))
5648 def revert(ui, repo, *pats, **opts):
5652 def revert(ui, repo, *pats, **opts):
5649 """restore files to their checkout state
5653 """restore files to their checkout state
5650
5654
5651 .. note::
5655 .. note::
5652
5656
5653 To check out earlier revisions, you should use :hg:`update REV`.
5657 To check out earlier revisions, you should use :hg:`update REV`.
5654 To cancel an uncommitted merge (and lose your changes),
5658 To cancel an uncommitted merge (and lose your changes),
5655 use :hg:`update --clean .`.
5659 use :hg:`update --clean .`.
5656
5660
5657 With no revision specified, revert the specified files or directories
5661 With no revision specified, revert the specified files or directories
5658 to the contents they had in the parent of the working directory.
5662 to the contents they had in the parent of the working directory.
5659 This restores the contents of files to an unmodified
5663 This restores the contents of files to an unmodified
5660 state and unschedules adds, removes, copies, and renames. If the
5664 state and unschedules adds, removes, copies, and renames. If the
5661 working directory has two parents, you must explicitly specify a
5665 working directory has two parents, you must explicitly specify a
5662 revision.
5666 revision.
5663
5667
5664 Using the -r/--rev or -d/--date options, revert the given files or
5668 Using the -r/--rev or -d/--date options, revert the given files or
5665 directories to their states as of a specific revision. Because
5669 directories to their states as of a specific revision. Because
5666 revert does not change the working directory parents, this will
5670 revert does not change the working directory parents, this will
5667 cause these files to appear modified. This can be helpful to "back
5671 cause these files to appear modified. This can be helpful to "back
5668 out" some or all of an earlier change. See :hg:`backout` for a
5672 out" some or all of an earlier change. See :hg:`backout` for a
5669 related method.
5673 related method.
5670
5674
5671 Modified files are saved with a .orig suffix before reverting.
5675 Modified files are saved with a .orig suffix before reverting.
5672 To disable these backups, use --no-backup.
5676 To disable these backups, use --no-backup.
5673
5677
5674 See :hg:`help dates` for a list of formats valid for -d/--date.
5678 See :hg:`help dates` for a list of formats valid for -d/--date.
5675
5679
5676 See :hg:`help backout` for a way to reverse the effect of an
5680 See :hg:`help backout` for a way to reverse the effect of an
5677 earlier changeset.
5681 earlier changeset.
5678
5682
5679 Returns 0 on success.
5683 Returns 0 on success.
5680 """
5684 """
5681
5685
5682 if opts.get("date"):
5686 if opts.get("date"):
5683 if opts.get("rev"):
5687 if opts.get("rev"):
5684 raise error.Abort(_("you can't specify a revision and a date"))
5688 raise error.Abort(_("you can't specify a revision and a date"))
5685 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5689 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5686
5690
5687 parent, p2 = repo.dirstate.parents()
5691 parent, p2 = repo.dirstate.parents()
5688 if not opts.get('rev') and p2 != nullid:
5692 if not opts.get('rev') and p2 != nullid:
5689 # revert after merge is a trap for new users (issue2915)
5693 # revert after merge is a trap for new users (issue2915)
5690 raise error.Abort(_('uncommitted merge with no revision specified'),
5694 raise error.Abort(_('uncommitted merge with no revision specified'),
5691 hint=_('use "hg update" or see "hg help revert"'))
5695 hint=_('use "hg update" or see "hg help revert"'))
5692
5696
5693 ctx = scmutil.revsingle(repo, opts.get('rev'))
5697 ctx = scmutil.revsingle(repo, opts.get('rev'))
5694
5698
5695 if (not (pats or opts.get('include') or opts.get('exclude') or
5699 if (not (pats or opts.get('include') or opts.get('exclude') or
5696 opts.get('all') or opts.get('interactive'))):
5700 opts.get('all') or opts.get('interactive'))):
5697 msg = _("no files or directories specified")
5701 msg = _("no files or directories specified")
5698 if p2 != nullid:
5702 if p2 != nullid:
5699 hint = _("uncommitted merge, use --all to discard all changes,"
5703 hint = _("uncommitted merge, use --all to discard all changes,"
5700 " or 'hg update -C .' to abort the merge")
5704 " or 'hg update -C .' to abort the merge")
5701 raise error.Abort(msg, hint=hint)
5705 raise error.Abort(msg, hint=hint)
5702 dirty = any(repo.status())
5706 dirty = any(repo.status())
5703 node = ctx.node()
5707 node = ctx.node()
5704 if node != parent:
5708 if node != parent:
5705 if dirty:
5709 if dirty:
5706 hint = _("uncommitted changes, use --all to discard all"
5710 hint = _("uncommitted changes, use --all to discard all"
5707 " changes, or 'hg update %s' to update") % ctx.rev()
5711 " changes, or 'hg update %s' to update") % ctx.rev()
5708 else:
5712 else:
5709 hint = _("use --all to revert all files,"
5713 hint = _("use --all to revert all files,"
5710 " or 'hg update %s' to update") % ctx.rev()
5714 " or 'hg update %s' to update") % ctx.rev()
5711 elif dirty:
5715 elif dirty:
5712 hint = _("uncommitted changes, use --all to discard all changes")
5716 hint = _("uncommitted changes, use --all to discard all changes")
5713 else:
5717 else:
5714 hint = _("use --all to revert all files")
5718 hint = _("use --all to revert all files")
5715 raise error.Abort(msg, hint=hint)
5719 raise error.Abort(msg, hint=hint)
5716
5720
5717 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5721 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5718
5722
5719 @command('rollback', dryrunopts +
5723 @command('rollback', dryrunopts +
5720 [('f', 'force', False, _('ignore safety measures'))])
5724 [('f', 'force', False, _('ignore safety measures'))])
5721 def rollback(ui, repo, **opts):
5725 def rollback(ui, repo, **opts):
5722 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5726 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5723
5727
5724 Please use :hg:`commit --amend` instead of rollback to correct
5728 Please use :hg:`commit --amend` instead of rollback to correct
5725 mistakes in the last commit.
5729 mistakes in the last commit.
5726
5730
5727 This command should be used with care. There is only one level of
5731 This command should be used with care. There is only one level of
5728 rollback, and there is no way to undo a rollback. It will also
5732 rollback, and there is no way to undo a rollback. It will also
5729 restore the dirstate at the time of the last transaction, losing
5733 restore the dirstate at the time of the last transaction, losing
5730 any dirstate changes since that time. This command does not alter
5734 any dirstate changes since that time. This command does not alter
5731 the working directory.
5735 the working directory.
5732
5736
5733 Transactions are used to encapsulate the effects of all commands
5737 Transactions are used to encapsulate the effects of all commands
5734 that create new changesets or propagate existing changesets into a
5738 that create new changesets or propagate existing changesets into a
5735 repository.
5739 repository.
5736
5740
5737 .. container:: verbose
5741 .. container:: verbose
5738
5742
5739 For example, the following commands are transactional, and their
5743 For example, the following commands are transactional, and their
5740 effects can be rolled back:
5744 effects can be rolled back:
5741
5745
5742 - commit
5746 - commit
5743 - import
5747 - import
5744 - pull
5748 - pull
5745 - push (with this repository as the destination)
5749 - push (with this repository as the destination)
5746 - unbundle
5750 - unbundle
5747
5751
5748 To avoid permanent data loss, rollback will refuse to rollback a
5752 To avoid permanent data loss, rollback will refuse to rollback a
5749 commit transaction if it isn't checked out. Use --force to
5753 commit transaction if it isn't checked out. Use --force to
5750 override this protection.
5754 override this protection.
5751
5755
5752 This command is not intended for use on public repositories. Once
5756 This command is not intended for use on public repositories. Once
5753 changes are visible for pull by other users, rolling a transaction
5757 changes are visible for pull by other users, rolling a transaction
5754 back locally is ineffective (someone else may already have pulled
5758 back locally is ineffective (someone else may already have pulled
5755 the changes). Furthermore, a race is possible with readers of the
5759 the changes). Furthermore, a race is possible with readers of the
5756 repository; for example an in-progress pull from the repository
5760 repository; for example an in-progress pull from the repository
5757 may fail if a rollback is performed.
5761 may fail if a rollback is performed.
5758
5762
5759 Returns 0 on success, 1 if no rollback data is available.
5763 Returns 0 on success, 1 if no rollback data is available.
5760 """
5764 """
5761 return repo.rollback(dryrun=opts.get('dry_run'),
5765 return repo.rollback(dryrun=opts.get('dry_run'),
5762 force=opts.get('force'))
5766 force=opts.get('force'))
5763
5767
5764 @command('root', [])
5768 @command('root', [])
5765 def root(ui, repo):
5769 def root(ui, repo):
5766 """print the root (top) of the current working directory
5770 """print the root (top) of the current working directory
5767
5771
5768 Print the root directory of the current repository.
5772 Print the root directory of the current repository.
5769
5773
5770 Returns 0 on success.
5774 Returns 0 on success.
5771 """
5775 """
5772 ui.write(repo.root + "\n")
5776 ui.write(repo.root + "\n")
5773
5777
5774 @command('^serve',
5778 @command('^serve',
5775 [('A', 'accesslog', '', _('name of access log file to write to'),
5779 [('A', 'accesslog', '', _('name of access log file to write to'),
5776 _('FILE')),
5780 _('FILE')),
5777 ('d', 'daemon', None, _('run server in background')),
5781 ('d', 'daemon', None, _('run server in background')),
5778 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5782 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5779 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5783 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5780 # use string type, then we can check if something was passed
5784 # use string type, then we can check if something was passed
5781 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5785 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5782 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5786 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5783 _('ADDR')),
5787 _('ADDR')),
5784 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5788 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5785 _('PREFIX')),
5789 _('PREFIX')),
5786 ('n', 'name', '',
5790 ('n', 'name', '',
5787 _('name to show in web pages (default: working directory)'), _('NAME')),
5791 _('name to show in web pages (default: working directory)'), _('NAME')),
5788 ('', 'web-conf', '',
5792 ('', 'web-conf', '',
5789 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5793 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5790 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5794 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5791 _('FILE')),
5795 _('FILE')),
5792 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5796 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5793 ('', 'stdio', None, _('for remote clients')),
5797 ('', 'stdio', None, _('for remote clients')),
5794 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5798 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5795 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5799 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5796 ('', 'style', '', _('template style to use'), _('STYLE')),
5800 ('', 'style', '', _('template style to use'), _('STYLE')),
5797 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5801 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5798 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5802 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5799 _('[OPTION]...'),
5803 _('[OPTION]...'),
5800 optionalrepo=True)
5804 optionalrepo=True)
5801 def serve(ui, repo, **opts):
5805 def serve(ui, repo, **opts):
5802 """start stand-alone webserver
5806 """start stand-alone webserver
5803
5807
5804 Start a local HTTP repository browser and pull server. You can use
5808 Start a local HTTP repository browser and pull server. You can use
5805 this for ad-hoc sharing and browsing of repositories. It is
5809 this for ad-hoc sharing and browsing of repositories. It is
5806 recommended to use a real web server to serve a repository for
5810 recommended to use a real web server to serve a repository for
5807 longer periods of time.
5811 longer periods of time.
5808
5812
5809 Please note that the server does not implement access control.
5813 Please note that the server does not implement access control.
5810 This means that, by default, anybody can read from the server and
5814 This means that, by default, anybody can read from the server and
5811 nobody can write to it by default. Set the ``web.allow_push``
5815 nobody can write to it by default. Set the ``web.allow_push``
5812 option to ``*`` to allow everybody to push to the server. You
5816 option to ``*`` to allow everybody to push to the server. You
5813 should use a real web server if you need to authenticate users.
5817 should use a real web server if you need to authenticate users.
5814
5818
5815 By default, the server logs accesses to stdout and errors to
5819 By default, the server logs accesses to stdout and errors to
5816 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5820 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5817 files.
5821 files.
5818
5822
5819 To have the server choose a free port number to listen on, specify
5823 To have the server choose a free port number to listen on, specify
5820 a port number of 0; in this case, the server will print the port
5824 a port number of 0; in this case, the server will print the port
5821 number it uses.
5825 number it uses.
5822
5826
5823 Returns 0 on success.
5827 Returns 0 on success.
5824 """
5828 """
5825
5829
5826 if opts["stdio"] and opts["cmdserver"]:
5830 if opts["stdio"] and opts["cmdserver"]:
5827 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5831 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5828
5832
5829 if opts["stdio"]:
5833 if opts["stdio"]:
5830 if repo is None:
5834 if repo is None:
5831 raise error.RepoError(_("there is no Mercurial repository here"
5835 raise error.RepoError(_("there is no Mercurial repository here"
5832 " (.hg not found)"))
5836 " (.hg not found)"))
5833 s = sshserver.sshserver(ui, repo)
5837 s = sshserver.sshserver(ui, repo)
5834 s.serve_forever()
5838 s.serve_forever()
5835
5839
5836 if opts["cmdserver"]:
5840 if opts["cmdserver"]:
5837 import commandserver
5841 import commandserver
5838 service = commandserver.createservice(ui, repo, opts)
5842 service = commandserver.createservice(ui, repo, opts)
5839 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5843 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5840
5844
5841 # this way we can check if something was given in the command-line
5845 # this way we can check if something was given in the command-line
5842 if opts.get('port'):
5846 if opts.get('port'):
5843 opts['port'] = util.getport(opts.get('port'))
5847 opts['port'] = util.getport(opts.get('port'))
5844
5848
5845 if repo:
5849 if repo:
5846 baseui = repo.baseui
5850 baseui = repo.baseui
5847 else:
5851 else:
5848 baseui = ui
5852 baseui = ui
5849 optlist = ("name templates style address port prefix ipv6"
5853 optlist = ("name templates style address port prefix ipv6"
5850 " accesslog errorlog certificate encoding")
5854 " accesslog errorlog certificate encoding")
5851 for o in optlist.split():
5855 for o in optlist.split():
5852 val = opts.get(o, '')
5856 val = opts.get(o, '')
5853 if val in (None, ''): # should check against default options instead
5857 if val in (None, ''): # should check against default options instead
5854 continue
5858 continue
5855 baseui.setconfig("web", o, val, 'serve')
5859 baseui.setconfig("web", o, val, 'serve')
5856 if repo and repo.ui != baseui:
5860 if repo and repo.ui != baseui:
5857 repo.ui.setconfig("web", o, val, 'serve')
5861 repo.ui.setconfig("web", o, val, 'serve')
5858
5862
5859 o = opts.get('web_conf') or opts.get('webdir_conf')
5863 o = opts.get('web_conf') or opts.get('webdir_conf')
5860 if not o:
5864 if not o:
5861 if not repo:
5865 if not repo:
5862 raise error.RepoError(_("there is no Mercurial repository"
5866 raise error.RepoError(_("there is no Mercurial repository"
5863 " here (.hg not found)"))
5867 " here (.hg not found)"))
5864 o = repo
5868 o = repo
5865
5869
5866 app = hgweb.hgweb(o, baseui=baseui)
5870 app = hgweb.hgweb(o, baseui=baseui)
5867 service = httpservice(ui, app, opts)
5871 service = httpservice(ui, app, opts)
5868 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5872 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5869
5873
5870 class httpservice(object):
5874 class httpservice(object):
5871 def __init__(self, ui, app, opts):
5875 def __init__(self, ui, app, opts):
5872 self.ui = ui
5876 self.ui = ui
5873 self.app = app
5877 self.app = app
5874 self.opts = opts
5878 self.opts = opts
5875
5879
5876 def init(self):
5880 def init(self):
5877 util.setsignalhandler()
5881 util.setsignalhandler()
5878 self.httpd = hgweb_server.create_server(self.ui, self.app)
5882 self.httpd = hgweb_server.create_server(self.ui, self.app)
5879
5883
5880 if self.opts['port'] and not self.ui.verbose:
5884 if self.opts['port'] and not self.ui.verbose:
5881 return
5885 return
5882
5886
5883 if self.httpd.prefix:
5887 if self.httpd.prefix:
5884 prefix = self.httpd.prefix.strip('/') + '/'
5888 prefix = self.httpd.prefix.strip('/') + '/'
5885 else:
5889 else:
5886 prefix = ''
5890 prefix = ''
5887
5891
5888 port = ':%d' % self.httpd.port
5892 port = ':%d' % self.httpd.port
5889 if port == ':80':
5893 if port == ':80':
5890 port = ''
5894 port = ''
5891
5895
5892 bindaddr = self.httpd.addr
5896 bindaddr = self.httpd.addr
5893 if bindaddr == '0.0.0.0':
5897 if bindaddr == '0.0.0.0':
5894 bindaddr = '*'
5898 bindaddr = '*'
5895 elif ':' in bindaddr: # IPv6
5899 elif ':' in bindaddr: # IPv6
5896 bindaddr = '[%s]' % bindaddr
5900 bindaddr = '[%s]' % bindaddr
5897
5901
5898 fqaddr = self.httpd.fqaddr
5902 fqaddr = self.httpd.fqaddr
5899 if ':' in fqaddr:
5903 if ':' in fqaddr:
5900 fqaddr = '[%s]' % fqaddr
5904 fqaddr = '[%s]' % fqaddr
5901 if self.opts['port']:
5905 if self.opts['port']:
5902 write = self.ui.status
5906 write = self.ui.status
5903 else:
5907 else:
5904 write = self.ui.write
5908 write = self.ui.write
5905 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5909 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5906 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5910 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5907 self.ui.flush() # avoid buffering of status message
5911 self.ui.flush() # avoid buffering of status message
5908
5912
5909 def run(self):
5913 def run(self):
5910 self.httpd.serve_forever()
5914 self.httpd.serve_forever()
5911
5915
5912
5916
5913 @command('^status|st',
5917 @command('^status|st',
5914 [('A', 'all', None, _('show status of all files')),
5918 [('A', 'all', None, _('show status of all files')),
5915 ('m', 'modified', None, _('show only modified files')),
5919 ('m', 'modified', None, _('show only modified files')),
5916 ('a', 'added', None, _('show only added files')),
5920 ('a', 'added', None, _('show only added files')),
5917 ('r', 'removed', None, _('show only removed files')),
5921 ('r', 'removed', None, _('show only removed files')),
5918 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5922 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5919 ('c', 'clean', None, _('show only files without changes')),
5923 ('c', 'clean', None, _('show only files without changes')),
5920 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5924 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5921 ('i', 'ignored', None, _('show only ignored files')),
5925 ('i', 'ignored', None, _('show only ignored files')),
5922 ('n', 'no-status', None, _('hide status prefix')),
5926 ('n', 'no-status', None, _('hide status prefix')),
5923 ('C', 'copies', None, _('show source of copied files')),
5927 ('C', 'copies', None, _('show source of copied files')),
5924 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5928 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5925 ('', 'rev', [], _('show difference from revision'), _('REV')),
5929 ('', 'rev', [], _('show difference from revision'), _('REV')),
5926 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5930 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5927 ] + walkopts + subrepoopts + formatteropts,
5931 ] + walkopts + subrepoopts + formatteropts,
5928 _('[OPTION]... [FILE]...'),
5932 _('[OPTION]... [FILE]...'),
5929 inferrepo=True)
5933 inferrepo=True)
5930 def status(ui, repo, *pats, **opts):
5934 def status(ui, repo, *pats, **opts):
5931 """show changed files in the working directory
5935 """show changed files in the working directory
5932
5936
5933 Show status of files in the repository. If names are given, only
5937 Show status of files in the repository. If names are given, only
5934 files that match are shown. Files that are clean or ignored or
5938 files that match are shown. Files that are clean or ignored or
5935 the source of a copy/move operation, are not listed unless
5939 the source of a copy/move operation, are not listed unless
5936 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5940 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5937 Unless options described with "show only ..." are given, the
5941 Unless options described with "show only ..." are given, the
5938 options -mardu are used.
5942 options -mardu are used.
5939
5943
5940 Option -q/--quiet hides untracked (unknown and ignored) files
5944 Option -q/--quiet hides untracked (unknown and ignored) files
5941 unless explicitly requested with -u/--unknown or -i/--ignored.
5945 unless explicitly requested with -u/--unknown or -i/--ignored.
5942
5946
5943 .. note::
5947 .. note::
5944
5948
5945 status may appear to disagree with diff if permissions have
5949 status may appear to disagree with diff if permissions have
5946 changed or a merge has occurred. The standard diff format does
5950 changed or a merge has occurred. The standard diff format does
5947 not report permission changes and diff only reports changes
5951 not report permission changes and diff only reports changes
5948 relative to one merge parent.
5952 relative to one merge parent.
5949
5953
5950 If one revision is given, it is used as the base revision.
5954 If one revision is given, it is used as the base revision.
5951 If two revisions are given, the differences between them are
5955 If two revisions are given, the differences between them are
5952 shown. The --change option can also be used as a shortcut to list
5956 shown. The --change option can also be used as a shortcut to list
5953 the changed files of a revision from its first parent.
5957 the changed files of a revision from its first parent.
5954
5958
5955 The codes used to show the status of files are::
5959 The codes used to show the status of files are::
5956
5960
5957 M = modified
5961 M = modified
5958 A = added
5962 A = added
5959 R = removed
5963 R = removed
5960 C = clean
5964 C = clean
5961 ! = missing (deleted by non-hg command, but still tracked)
5965 ! = missing (deleted by non-hg command, but still tracked)
5962 ? = not tracked
5966 ? = not tracked
5963 I = ignored
5967 I = ignored
5964 = origin of the previous file (with --copies)
5968 = origin of the previous file (with --copies)
5965
5969
5966 .. container:: verbose
5970 .. container:: verbose
5967
5971
5968 Examples:
5972 Examples:
5969
5973
5970 - show changes in the working directory relative to a
5974 - show changes in the working directory relative to a
5971 changeset::
5975 changeset::
5972
5976
5973 hg status --rev 9353
5977 hg status --rev 9353
5974
5978
5975 - show changes in the working directory relative to the
5979 - show changes in the working directory relative to the
5976 current directory (see :hg:`help patterns` for more information)::
5980 current directory (see :hg:`help patterns` for more information)::
5977
5981
5978 hg status re:
5982 hg status re:
5979
5983
5980 - show all changes including copies in an existing changeset::
5984 - show all changes including copies in an existing changeset::
5981
5985
5982 hg status --copies --change 9353
5986 hg status --copies --change 9353
5983
5987
5984 - get a NUL separated list of added files, suitable for xargs::
5988 - get a NUL separated list of added files, suitable for xargs::
5985
5989
5986 hg status -an0
5990 hg status -an0
5987
5991
5988 Returns 0 on success.
5992 Returns 0 on success.
5989 """
5993 """
5990
5994
5991 revs = opts.get('rev')
5995 revs = opts.get('rev')
5992 change = opts.get('change')
5996 change = opts.get('change')
5993
5997
5994 if revs and change:
5998 if revs and change:
5995 msg = _('cannot specify --rev and --change at the same time')
5999 msg = _('cannot specify --rev and --change at the same time')
5996 raise error.Abort(msg)
6000 raise error.Abort(msg)
5997 elif change:
6001 elif change:
5998 node2 = scmutil.revsingle(repo, change, None).node()
6002 node2 = scmutil.revsingle(repo, change, None).node()
5999 node1 = repo[node2].p1().node()
6003 node1 = repo[node2].p1().node()
6000 else:
6004 else:
6001 node1, node2 = scmutil.revpair(repo, revs)
6005 node1, node2 = scmutil.revpair(repo, revs)
6002
6006
6003 if pats:
6007 if pats:
6004 cwd = repo.getcwd()
6008 cwd = repo.getcwd()
6005 else:
6009 else:
6006 cwd = ''
6010 cwd = ''
6007
6011
6008 if opts.get('print0'):
6012 if opts.get('print0'):
6009 end = '\0'
6013 end = '\0'
6010 else:
6014 else:
6011 end = '\n'
6015 end = '\n'
6012 copy = {}
6016 copy = {}
6013 states = 'modified added removed deleted unknown ignored clean'.split()
6017 states = 'modified added removed deleted unknown ignored clean'.split()
6014 show = [k for k in states if opts.get(k)]
6018 show = [k for k in states if opts.get(k)]
6015 if opts.get('all'):
6019 if opts.get('all'):
6016 show += ui.quiet and (states[:4] + ['clean']) or states
6020 show += ui.quiet and (states[:4] + ['clean']) or states
6017 if not show:
6021 if not show:
6018 if ui.quiet:
6022 if ui.quiet:
6019 show = states[:4]
6023 show = states[:4]
6020 else:
6024 else:
6021 show = states[:5]
6025 show = states[:5]
6022
6026
6023 m = scmutil.match(repo[node2], pats, opts)
6027 m = scmutil.match(repo[node2], pats, opts)
6024 stat = repo.status(node1, node2, m,
6028 stat = repo.status(node1, node2, m,
6025 'ignored' in show, 'clean' in show, 'unknown' in show,
6029 'ignored' in show, 'clean' in show, 'unknown' in show,
6026 opts.get('subrepos'))
6030 opts.get('subrepos'))
6027 changestates = zip(states, 'MAR!?IC', stat)
6031 changestates = zip(states, 'MAR!?IC', stat)
6028
6032
6029 if (opts.get('all') or opts.get('copies')
6033 if (opts.get('all') or opts.get('copies')
6030 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6034 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6031 copy = copies.pathcopies(repo[node1], repo[node2], m)
6035 copy = copies.pathcopies(repo[node1], repo[node2], m)
6032
6036
6033 fm = ui.formatter('status', opts)
6037 fm = ui.formatter('status', opts)
6034 fmt = '%s' + end
6038 fmt = '%s' + end
6035 showchar = not opts.get('no_status')
6039 showchar = not opts.get('no_status')
6036
6040
6037 for state, char, files in changestates:
6041 for state, char, files in changestates:
6038 if state in show:
6042 if state in show:
6039 label = 'status.' + state
6043 label = 'status.' + state
6040 for f in files:
6044 for f in files:
6041 fm.startitem()
6045 fm.startitem()
6042 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6046 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6043 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6047 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6044 if f in copy:
6048 if f in copy:
6045 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6049 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6046 label='status.copied')
6050 label='status.copied')
6047 fm.end()
6051 fm.end()
6048
6052
6049 @command('^summary|sum',
6053 @command('^summary|sum',
6050 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6054 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6051 def summary(ui, repo, **opts):
6055 def summary(ui, repo, **opts):
6052 """summarize working directory state
6056 """summarize working directory state
6053
6057
6054 This generates a brief summary of the working directory state,
6058 This generates a brief summary of the working directory state,
6055 including parents, branch, commit status, phase and available updates.
6059 including parents, branch, commit status, phase and available updates.
6056
6060
6057 With the --remote option, this will check the default paths for
6061 With the --remote option, this will check the default paths for
6058 incoming and outgoing changes. This can be time-consuming.
6062 incoming and outgoing changes. This can be time-consuming.
6059
6063
6060 Returns 0 on success.
6064 Returns 0 on success.
6061 """
6065 """
6062
6066
6063 ctx = repo[None]
6067 ctx = repo[None]
6064 parents = ctx.parents()
6068 parents = ctx.parents()
6065 pnode = parents[0].node()
6069 pnode = parents[0].node()
6066 marks = []
6070 marks = []
6067
6071
6068 for p in parents:
6072 for p in parents:
6069 # label with log.changeset (instead of log.parent) since this
6073 # label with log.changeset (instead of log.parent) since this
6070 # shows a working directory parent *changeset*:
6074 # shows a working directory parent *changeset*:
6071 # i18n: column positioning for "hg summary"
6075 # i18n: column positioning for "hg summary"
6072 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6076 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6073 label='log.changeset changeset.%s' % p.phasestr())
6077 label='log.changeset changeset.%s' % p.phasestr())
6074 ui.write(' '.join(p.tags()), label='log.tag')
6078 ui.write(' '.join(p.tags()), label='log.tag')
6075 if p.bookmarks():
6079 if p.bookmarks():
6076 marks.extend(p.bookmarks())
6080 marks.extend(p.bookmarks())
6077 if p.rev() == -1:
6081 if p.rev() == -1:
6078 if not len(repo):
6082 if not len(repo):
6079 ui.write(_(' (empty repository)'))
6083 ui.write(_(' (empty repository)'))
6080 else:
6084 else:
6081 ui.write(_(' (no revision checked out)'))
6085 ui.write(_(' (no revision checked out)'))
6082 ui.write('\n')
6086 ui.write('\n')
6083 if p.description():
6087 if p.description():
6084 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6088 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6085 label='log.summary')
6089 label='log.summary')
6086
6090
6087 branch = ctx.branch()
6091 branch = ctx.branch()
6088 bheads = repo.branchheads(branch)
6092 bheads = repo.branchheads(branch)
6089 # i18n: column positioning for "hg summary"
6093 # i18n: column positioning for "hg summary"
6090 m = _('branch: %s\n') % branch
6094 m = _('branch: %s\n') % branch
6091 if branch != 'default':
6095 if branch != 'default':
6092 ui.write(m, label='log.branch')
6096 ui.write(m, label='log.branch')
6093 else:
6097 else:
6094 ui.status(m, label='log.branch')
6098 ui.status(m, label='log.branch')
6095
6099
6096 if marks:
6100 if marks:
6097 active = repo._activebookmark
6101 active = repo._activebookmark
6098 # i18n: column positioning for "hg summary"
6102 # i18n: column positioning for "hg summary"
6099 ui.write(_('bookmarks:'), label='log.bookmark')
6103 ui.write(_('bookmarks:'), label='log.bookmark')
6100 if active is not None:
6104 if active is not None:
6101 if active in marks:
6105 if active in marks:
6102 ui.write(' *' + active, label=activebookmarklabel)
6106 ui.write(' *' + active, label=activebookmarklabel)
6103 marks.remove(active)
6107 marks.remove(active)
6104 else:
6108 else:
6105 ui.write(' [%s]' % active, label=activebookmarklabel)
6109 ui.write(' [%s]' % active, label=activebookmarklabel)
6106 for m in marks:
6110 for m in marks:
6107 ui.write(' ' + m, label='log.bookmark')
6111 ui.write(' ' + m, label='log.bookmark')
6108 ui.write('\n', label='log.bookmark')
6112 ui.write('\n', label='log.bookmark')
6109
6113
6110 status = repo.status(unknown=True)
6114 status = repo.status(unknown=True)
6111
6115
6112 c = repo.dirstate.copies()
6116 c = repo.dirstate.copies()
6113 copied, renamed = [], []
6117 copied, renamed = [], []
6114 for d, s in c.iteritems():
6118 for d, s in c.iteritems():
6115 if s in status.removed:
6119 if s in status.removed:
6116 status.removed.remove(s)
6120 status.removed.remove(s)
6117 renamed.append(d)
6121 renamed.append(d)
6118 else:
6122 else:
6119 copied.append(d)
6123 copied.append(d)
6120 if d in status.added:
6124 if d in status.added:
6121 status.added.remove(d)
6125 status.added.remove(d)
6122
6126
6123 ms = mergemod.mergestate(repo)
6127 ms = mergemod.mergestate(repo)
6124 unresolved = [f for f in ms if ms[f] == 'u']
6128 unresolved = [f for f in ms if ms[f] == 'u']
6125
6129
6126 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6130 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6127
6131
6128 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6132 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6129 (ui.label(_('%d added'), 'status.added'), status.added),
6133 (ui.label(_('%d added'), 'status.added'), status.added),
6130 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6134 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6131 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6135 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6132 (ui.label(_('%d copied'), 'status.copied'), copied),
6136 (ui.label(_('%d copied'), 'status.copied'), copied),
6133 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6137 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6134 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6138 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6135 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6139 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6136 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6140 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6137 t = []
6141 t = []
6138 for l, s in labels:
6142 for l, s in labels:
6139 if s:
6143 if s:
6140 t.append(l % len(s))
6144 t.append(l % len(s))
6141
6145
6142 t = ', '.join(t)
6146 t = ', '.join(t)
6143 cleanworkdir = False
6147 cleanworkdir = False
6144
6148
6145 if repo.vfs.exists('updatestate'):
6149 if repo.vfs.exists('updatestate'):
6146 t += _(' (interrupted update)')
6150 t += _(' (interrupted update)')
6147 elif len(parents) > 1:
6151 elif len(parents) > 1:
6148 t += _(' (merge)')
6152 t += _(' (merge)')
6149 elif branch != parents[0].branch():
6153 elif branch != parents[0].branch():
6150 t += _(' (new branch)')
6154 t += _(' (new branch)')
6151 elif (parents[0].closesbranch() and
6155 elif (parents[0].closesbranch() and
6152 pnode in repo.branchheads(branch, closed=True)):
6156 pnode in repo.branchheads(branch, closed=True)):
6153 t += _(' (head closed)')
6157 t += _(' (head closed)')
6154 elif not (status.modified or status.added or status.removed or renamed or
6158 elif not (status.modified or status.added or status.removed or renamed or
6155 copied or subs):
6159 copied or subs):
6156 t += _(' (clean)')
6160 t += _(' (clean)')
6157 cleanworkdir = True
6161 cleanworkdir = True
6158 elif pnode not in bheads:
6162 elif pnode not in bheads:
6159 t += _(' (new branch head)')
6163 t += _(' (new branch head)')
6160
6164
6161 if parents:
6165 if parents:
6162 pendingphase = max(p.phase() for p in parents)
6166 pendingphase = max(p.phase() for p in parents)
6163 else:
6167 else:
6164 pendingphase = phases.public
6168 pendingphase = phases.public
6165
6169
6166 if pendingphase > phases.newcommitphase(ui):
6170 if pendingphase > phases.newcommitphase(ui):
6167 t += ' (%s)' % phases.phasenames[pendingphase]
6171 t += ' (%s)' % phases.phasenames[pendingphase]
6168
6172
6169 if cleanworkdir:
6173 if cleanworkdir:
6170 # i18n: column positioning for "hg summary"
6174 # i18n: column positioning for "hg summary"
6171 ui.status(_('commit: %s\n') % t.strip())
6175 ui.status(_('commit: %s\n') % t.strip())
6172 else:
6176 else:
6173 # i18n: column positioning for "hg summary"
6177 # i18n: column positioning for "hg summary"
6174 ui.write(_('commit: %s\n') % t.strip())
6178 ui.write(_('commit: %s\n') % t.strip())
6175
6179
6176 # all ancestors of branch heads - all ancestors of parent = new csets
6180 # all ancestors of branch heads - all ancestors of parent = new csets
6177 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6181 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6178 bheads))
6182 bheads))
6179
6183
6180 if new == 0:
6184 if new == 0:
6181 # i18n: column positioning for "hg summary"
6185 # i18n: column positioning for "hg summary"
6182 ui.status(_('update: (current)\n'))
6186 ui.status(_('update: (current)\n'))
6183 elif pnode not in bheads:
6187 elif pnode not in bheads:
6184 # i18n: column positioning for "hg summary"
6188 # i18n: column positioning for "hg summary"
6185 ui.write(_('update: %d new changesets (update)\n') % new)
6189 ui.write(_('update: %d new changesets (update)\n') % new)
6186 else:
6190 else:
6187 # i18n: column positioning for "hg summary"
6191 # i18n: column positioning for "hg summary"
6188 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6192 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6189 (new, len(bheads)))
6193 (new, len(bheads)))
6190
6194
6191 t = []
6195 t = []
6192 draft = len(repo.revs('draft()'))
6196 draft = len(repo.revs('draft()'))
6193 if draft:
6197 if draft:
6194 t.append(_('%d draft') % draft)
6198 t.append(_('%d draft') % draft)
6195 secret = len(repo.revs('secret()'))
6199 secret = len(repo.revs('secret()'))
6196 if secret:
6200 if secret:
6197 t.append(_('%d secret') % secret)
6201 t.append(_('%d secret') % secret)
6198
6202
6199 if draft or secret:
6203 if draft or secret:
6200 ui.status(_('phases: %s\n') % ', '.join(t))
6204 ui.status(_('phases: %s\n') % ', '.join(t))
6201
6205
6202 cmdutil.summaryhooks(ui, repo)
6206 cmdutil.summaryhooks(ui, repo)
6203
6207
6204 if opts.get('remote'):
6208 if opts.get('remote'):
6205 needsincoming, needsoutgoing = True, True
6209 needsincoming, needsoutgoing = True, True
6206 else:
6210 else:
6207 needsincoming, needsoutgoing = False, False
6211 needsincoming, needsoutgoing = False, False
6208 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6212 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6209 if i:
6213 if i:
6210 needsincoming = True
6214 needsincoming = True
6211 if o:
6215 if o:
6212 needsoutgoing = True
6216 needsoutgoing = True
6213 if not needsincoming and not needsoutgoing:
6217 if not needsincoming and not needsoutgoing:
6214 return
6218 return
6215
6219
6216 def getincoming():
6220 def getincoming():
6217 source, branches = hg.parseurl(ui.expandpath('default'))
6221 source, branches = hg.parseurl(ui.expandpath('default'))
6218 sbranch = branches[0]
6222 sbranch = branches[0]
6219 try:
6223 try:
6220 other = hg.peer(repo, {}, source)
6224 other = hg.peer(repo, {}, source)
6221 except error.RepoError:
6225 except error.RepoError:
6222 if opts.get('remote'):
6226 if opts.get('remote'):
6223 raise
6227 raise
6224 return source, sbranch, None, None, None
6228 return source, sbranch, None, None, None
6225 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6229 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6226 if revs:
6230 if revs:
6227 revs = [other.lookup(rev) for rev in revs]
6231 revs = [other.lookup(rev) for rev in revs]
6228 ui.debug('comparing with %s\n' % util.hidepassword(source))
6232 ui.debug('comparing with %s\n' % util.hidepassword(source))
6229 repo.ui.pushbuffer()
6233 repo.ui.pushbuffer()
6230 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6234 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6231 repo.ui.popbuffer()
6235 repo.ui.popbuffer()
6232 return source, sbranch, other, commoninc, commoninc[1]
6236 return source, sbranch, other, commoninc, commoninc[1]
6233
6237
6234 if needsincoming:
6238 if needsincoming:
6235 source, sbranch, sother, commoninc, incoming = getincoming()
6239 source, sbranch, sother, commoninc, incoming = getincoming()
6236 else:
6240 else:
6237 source = sbranch = sother = commoninc = incoming = None
6241 source = sbranch = sother = commoninc = incoming = None
6238
6242
6239 def getoutgoing():
6243 def getoutgoing():
6240 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6244 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6241 dbranch = branches[0]
6245 dbranch = branches[0]
6242 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6246 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6243 if source != dest:
6247 if source != dest:
6244 try:
6248 try:
6245 dother = hg.peer(repo, {}, dest)
6249 dother = hg.peer(repo, {}, dest)
6246 except error.RepoError:
6250 except error.RepoError:
6247 if opts.get('remote'):
6251 if opts.get('remote'):
6248 raise
6252 raise
6249 return dest, dbranch, None, None
6253 return dest, dbranch, None, None
6250 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6254 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6251 elif sother is None:
6255 elif sother is None:
6252 # there is no explicit destination peer, but source one is invalid
6256 # there is no explicit destination peer, but source one is invalid
6253 return dest, dbranch, None, None
6257 return dest, dbranch, None, None
6254 else:
6258 else:
6255 dother = sother
6259 dother = sother
6256 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6260 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6257 common = None
6261 common = None
6258 else:
6262 else:
6259 common = commoninc
6263 common = commoninc
6260 if revs:
6264 if revs:
6261 revs = [repo.lookup(rev) for rev in revs]
6265 revs = [repo.lookup(rev) for rev in revs]
6262 repo.ui.pushbuffer()
6266 repo.ui.pushbuffer()
6263 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6267 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6264 commoninc=common)
6268 commoninc=common)
6265 repo.ui.popbuffer()
6269 repo.ui.popbuffer()
6266 return dest, dbranch, dother, outgoing
6270 return dest, dbranch, dother, outgoing
6267
6271
6268 if needsoutgoing:
6272 if needsoutgoing:
6269 dest, dbranch, dother, outgoing = getoutgoing()
6273 dest, dbranch, dother, outgoing = getoutgoing()
6270 else:
6274 else:
6271 dest = dbranch = dother = outgoing = None
6275 dest = dbranch = dother = outgoing = None
6272
6276
6273 if opts.get('remote'):
6277 if opts.get('remote'):
6274 t = []
6278 t = []
6275 if incoming:
6279 if incoming:
6276 t.append(_('1 or more incoming'))
6280 t.append(_('1 or more incoming'))
6277 o = outgoing.missing
6281 o = outgoing.missing
6278 if o:
6282 if o:
6279 t.append(_('%d outgoing') % len(o))
6283 t.append(_('%d outgoing') % len(o))
6280 other = dother or sother
6284 other = dother or sother
6281 if 'bookmarks' in other.listkeys('namespaces'):
6285 if 'bookmarks' in other.listkeys('namespaces'):
6282 counts = bookmarks.summary(repo, other)
6286 counts = bookmarks.summary(repo, other)
6283 if counts[0] > 0:
6287 if counts[0] > 0:
6284 t.append(_('%d incoming bookmarks') % counts[0])
6288 t.append(_('%d incoming bookmarks') % counts[0])
6285 if counts[1] > 0:
6289 if counts[1] > 0:
6286 t.append(_('%d outgoing bookmarks') % counts[1])
6290 t.append(_('%d outgoing bookmarks') % counts[1])
6287
6291
6288 if t:
6292 if t:
6289 # i18n: column positioning for "hg summary"
6293 # i18n: column positioning for "hg summary"
6290 ui.write(_('remote: %s\n') % (', '.join(t)))
6294 ui.write(_('remote: %s\n') % (', '.join(t)))
6291 else:
6295 else:
6292 # i18n: column positioning for "hg summary"
6296 # i18n: column positioning for "hg summary"
6293 ui.status(_('remote: (synced)\n'))
6297 ui.status(_('remote: (synced)\n'))
6294
6298
6295 cmdutil.summaryremotehooks(ui, repo, opts,
6299 cmdutil.summaryremotehooks(ui, repo, opts,
6296 ((source, sbranch, sother, commoninc),
6300 ((source, sbranch, sother, commoninc),
6297 (dest, dbranch, dother, outgoing)))
6301 (dest, dbranch, dother, outgoing)))
6298
6302
6299 @command('tag',
6303 @command('tag',
6300 [('f', 'force', None, _('force tag')),
6304 [('f', 'force', None, _('force tag')),
6301 ('l', 'local', None, _('make the tag local')),
6305 ('l', 'local', None, _('make the tag local')),
6302 ('r', 'rev', '', _('revision to tag'), _('REV')),
6306 ('r', 'rev', '', _('revision to tag'), _('REV')),
6303 ('', 'remove', None, _('remove a tag')),
6307 ('', 'remove', None, _('remove a tag')),
6304 # -l/--local is already there, commitopts cannot be used
6308 # -l/--local is already there, commitopts cannot be used
6305 ('e', 'edit', None, _('invoke editor on commit messages')),
6309 ('e', 'edit', None, _('invoke editor on commit messages')),
6306 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6310 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6307 ] + commitopts2,
6311 ] + commitopts2,
6308 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6312 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6309 def tag(ui, repo, name1, *names, **opts):
6313 def tag(ui, repo, name1, *names, **opts):
6310 """add one or more tags for the current or given revision
6314 """add one or more tags for the current or given revision
6311
6315
6312 Name a particular revision using <name>.
6316 Name a particular revision using <name>.
6313
6317
6314 Tags are used to name particular revisions of the repository and are
6318 Tags are used to name particular revisions of the repository and are
6315 very useful to compare different revisions, to go back to significant
6319 very useful to compare different revisions, to go back to significant
6316 earlier versions or to mark branch points as releases, etc. Changing
6320 earlier versions or to mark branch points as releases, etc. Changing
6317 an existing tag is normally disallowed; use -f/--force to override.
6321 an existing tag is normally disallowed; use -f/--force to override.
6318
6322
6319 If no revision is given, the parent of the working directory is
6323 If no revision is given, the parent of the working directory is
6320 used.
6324 used.
6321
6325
6322 To facilitate version control, distribution, and merging of tags,
6326 To facilitate version control, distribution, and merging of tags,
6323 they are stored as a file named ".hgtags" which is managed similarly
6327 they are stored as a file named ".hgtags" which is managed similarly
6324 to other project files and can be hand-edited if necessary. This
6328 to other project files and can be hand-edited if necessary. This
6325 also means that tagging creates a new commit. The file
6329 also means that tagging creates a new commit. The file
6326 ".hg/localtags" is used for local tags (not shared among
6330 ".hg/localtags" is used for local tags (not shared among
6327 repositories).
6331 repositories).
6328
6332
6329 Tag commits are usually made at the head of a branch. If the parent
6333 Tag commits are usually made at the head of a branch. If the parent
6330 of the working directory is not a branch head, :hg:`tag` aborts; use
6334 of the working directory is not a branch head, :hg:`tag` aborts; use
6331 -f/--force to force the tag commit to be based on a non-head
6335 -f/--force to force the tag commit to be based on a non-head
6332 changeset.
6336 changeset.
6333
6337
6334 See :hg:`help dates` for a list of formats valid for -d/--date.
6338 See :hg:`help dates` for a list of formats valid for -d/--date.
6335
6339
6336 Since tag names have priority over branch names during revision
6340 Since tag names have priority over branch names during revision
6337 lookup, using an existing branch name as a tag name is discouraged.
6341 lookup, using an existing branch name as a tag name is discouraged.
6338
6342
6339 Returns 0 on success.
6343 Returns 0 on success.
6340 """
6344 """
6341 wlock = lock = None
6345 wlock = lock = None
6342 try:
6346 try:
6343 wlock = repo.wlock()
6347 wlock = repo.wlock()
6344 lock = repo.lock()
6348 lock = repo.lock()
6345 rev_ = "."
6349 rev_ = "."
6346 names = [t.strip() for t in (name1,) + names]
6350 names = [t.strip() for t in (name1,) + names]
6347 if len(names) != len(set(names)):
6351 if len(names) != len(set(names)):
6348 raise error.Abort(_('tag names must be unique'))
6352 raise error.Abort(_('tag names must be unique'))
6349 for n in names:
6353 for n in names:
6350 scmutil.checknewlabel(repo, n, 'tag')
6354 scmutil.checknewlabel(repo, n, 'tag')
6351 if not n:
6355 if not n:
6352 raise error.Abort(_('tag names cannot consist entirely of '
6356 raise error.Abort(_('tag names cannot consist entirely of '
6353 'whitespace'))
6357 'whitespace'))
6354 if opts.get('rev') and opts.get('remove'):
6358 if opts.get('rev') and opts.get('remove'):
6355 raise error.Abort(_("--rev and --remove are incompatible"))
6359 raise error.Abort(_("--rev and --remove are incompatible"))
6356 if opts.get('rev'):
6360 if opts.get('rev'):
6357 rev_ = opts['rev']
6361 rev_ = opts['rev']
6358 message = opts.get('message')
6362 message = opts.get('message')
6359 if opts.get('remove'):
6363 if opts.get('remove'):
6360 if opts.get('local'):
6364 if opts.get('local'):
6361 expectedtype = 'local'
6365 expectedtype = 'local'
6362 else:
6366 else:
6363 expectedtype = 'global'
6367 expectedtype = 'global'
6364
6368
6365 for n in names:
6369 for n in names:
6366 if not repo.tagtype(n):
6370 if not repo.tagtype(n):
6367 raise error.Abort(_("tag '%s' does not exist") % n)
6371 raise error.Abort(_("tag '%s' does not exist") % n)
6368 if repo.tagtype(n) != expectedtype:
6372 if repo.tagtype(n) != expectedtype:
6369 if expectedtype == 'global':
6373 if expectedtype == 'global':
6370 raise error.Abort(_("tag '%s' is not a global tag") % n)
6374 raise error.Abort(_("tag '%s' is not a global tag") % n)
6371 else:
6375 else:
6372 raise error.Abort(_("tag '%s' is not a local tag") % n)
6376 raise error.Abort(_("tag '%s' is not a local tag") % n)
6373 rev_ = 'null'
6377 rev_ = 'null'
6374 if not message:
6378 if not message:
6375 # we don't translate commit messages
6379 # we don't translate commit messages
6376 message = 'Removed tag %s' % ', '.join(names)
6380 message = 'Removed tag %s' % ', '.join(names)
6377 elif not opts.get('force'):
6381 elif not opts.get('force'):
6378 for n in names:
6382 for n in names:
6379 if n in repo.tags():
6383 if n in repo.tags():
6380 raise error.Abort(_("tag '%s' already exists "
6384 raise error.Abort(_("tag '%s' already exists "
6381 "(use -f to force)") % n)
6385 "(use -f to force)") % n)
6382 if not opts.get('local'):
6386 if not opts.get('local'):
6383 p1, p2 = repo.dirstate.parents()
6387 p1, p2 = repo.dirstate.parents()
6384 if p2 != nullid:
6388 if p2 != nullid:
6385 raise error.Abort(_('uncommitted merge'))
6389 raise error.Abort(_('uncommitted merge'))
6386 bheads = repo.branchheads()
6390 bheads = repo.branchheads()
6387 if not opts.get('force') and bheads and p1 not in bheads:
6391 if not opts.get('force') and bheads and p1 not in bheads:
6388 raise error.Abort(_('not at a branch head (use -f to force)'))
6392 raise error.Abort(_('not at a branch head (use -f to force)'))
6389 r = scmutil.revsingle(repo, rev_).node()
6393 r = scmutil.revsingle(repo, rev_).node()
6390
6394
6391 if not message:
6395 if not message:
6392 # we don't translate commit messages
6396 # we don't translate commit messages
6393 message = ('Added tag %s for changeset %s' %
6397 message = ('Added tag %s for changeset %s' %
6394 (', '.join(names), short(r)))
6398 (', '.join(names), short(r)))
6395
6399
6396 date = opts.get('date')
6400 date = opts.get('date')
6397 if date:
6401 if date:
6398 date = util.parsedate(date)
6402 date = util.parsedate(date)
6399
6403
6400 if opts.get('remove'):
6404 if opts.get('remove'):
6401 editform = 'tag.remove'
6405 editform = 'tag.remove'
6402 else:
6406 else:
6403 editform = 'tag.add'
6407 editform = 'tag.add'
6404 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6408 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6405
6409
6406 # don't allow tagging the null rev
6410 # don't allow tagging the null rev
6407 if (not opts.get('remove') and
6411 if (not opts.get('remove') and
6408 scmutil.revsingle(repo, rev_).rev() == nullrev):
6412 scmutil.revsingle(repo, rev_).rev() == nullrev):
6409 raise error.Abort(_("cannot tag null revision"))
6413 raise error.Abort(_("cannot tag null revision"))
6410
6414
6411 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6415 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6412 editor=editor)
6416 editor=editor)
6413 finally:
6417 finally:
6414 release(lock, wlock)
6418 release(lock, wlock)
6415
6419
6416 @command('tags', formatteropts, '')
6420 @command('tags', formatteropts, '')
6417 def tags(ui, repo, **opts):
6421 def tags(ui, repo, **opts):
6418 """list repository tags
6422 """list repository tags
6419
6423
6420 This lists both regular and local tags. When the -v/--verbose
6424 This lists both regular and local tags. When the -v/--verbose
6421 switch is used, a third column "local" is printed for local tags.
6425 switch is used, a third column "local" is printed for local tags.
6422
6426
6423 Returns 0 on success.
6427 Returns 0 on success.
6424 """
6428 """
6425
6429
6426 fm = ui.formatter('tags', opts)
6430 fm = ui.formatter('tags', opts)
6427 hexfunc = fm.hexfunc
6431 hexfunc = fm.hexfunc
6428 tagtype = ""
6432 tagtype = ""
6429
6433
6430 for t, n in reversed(repo.tagslist()):
6434 for t, n in reversed(repo.tagslist()):
6431 hn = hexfunc(n)
6435 hn = hexfunc(n)
6432 label = 'tags.normal'
6436 label = 'tags.normal'
6433 tagtype = ''
6437 tagtype = ''
6434 if repo.tagtype(t) == 'local':
6438 if repo.tagtype(t) == 'local':
6435 label = 'tags.local'
6439 label = 'tags.local'
6436 tagtype = 'local'
6440 tagtype = 'local'
6437
6441
6438 fm.startitem()
6442 fm.startitem()
6439 fm.write('tag', '%s', t, label=label)
6443 fm.write('tag', '%s', t, label=label)
6440 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6444 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6441 fm.condwrite(not ui.quiet, 'rev node', fmt,
6445 fm.condwrite(not ui.quiet, 'rev node', fmt,
6442 repo.changelog.rev(n), hn, label=label)
6446 repo.changelog.rev(n), hn, label=label)
6443 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6447 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6444 tagtype, label=label)
6448 tagtype, label=label)
6445 fm.plain('\n')
6449 fm.plain('\n')
6446 fm.end()
6450 fm.end()
6447
6451
6448 @command('tip',
6452 @command('tip',
6449 [('p', 'patch', None, _('show patch')),
6453 [('p', 'patch', None, _('show patch')),
6450 ('g', 'git', None, _('use git extended diff format')),
6454 ('g', 'git', None, _('use git extended diff format')),
6451 ] + templateopts,
6455 ] + templateopts,
6452 _('[-p] [-g]'))
6456 _('[-p] [-g]'))
6453 def tip(ui, repo, **opts):
6457 def tip(ui, repo, **opts):
6454 """show the tip revision (DEPRECATED)
6458 """show the tip revision (DEPRECATED)
6455
6459
6456 The tip revision (usually just called the tip) is the changeset
6460 The tip revision (usually just called the tip) is the changeset
6457 most recently added to the repository (and therefore the most
6461 most recently added to the repository (and therefore the most
6458 recently changed head).
6462 recently changed head).
6459
6463
6460 If you have just made a commit, that commit will be the tip. If
6464 If you have just made a commit, that commit will be the tip. If
6461 you have just pulled changes from another repository, the tip of
6465 you have just pulled changes from another repository, the tip of
6462 that repository becomes the current tip. The "tip" tag is special
6466 that repository becomes the current tip. The "tip" tag is special
6463 and cannot be renamed or assigned to a different changeset.
6467 and cannot be renamed or assigned to a different changeset.
6464
6468
6465 This command is deprecated, please use :hg:`heads` instead.
6469 This command is deprecated, please use :hg:`heads` instead.
6466
6470
6467 Returns 0 on success.
6471 Returns 0 on success.
6468 """
6472 """
6469 displayer = cmdutil.show_changeset(ui, repo, opts)
6473 displayer = cmdutil.show_changeset(ui, repo, opts)
6470 displayer.show(repo['tip'])
6474 displayer.show(repo['tip'])
6471 displayer.close()
6475 displayer.close()
6472
6476
6473 @command('unbundle',
6477 @command('unbundle',
6474 [('u', 'update', None,
6478 [('u', 'update', None,
6475 _('update to new branch head if changesets were unbundled'))],
6479 _('update to new branch head if changesets were unbundled'))],
6476 _('[-u] FILE...'))
6480 _('[-u] FILE...'))
6477 def unbundle(ui, repo, fname1, *fnames, **opts):
6481 def unbundle(ui, repo, fname1, *fnames, **opts):
6478 """apply one or more changegroup files
6482 """apply one or more changegroup files
6479
6483
6480 Apply one or more compressed changegroup files generated by the
6484 Apply one or more compressed changegroup files generated by the
6481 bundle command.
6485 bundle command.
6482
6486
6483 Returns 0 on success, 1 if an update has unresolved files.
6487 Returns 0 on success, 1 if an update has unresolved files.
6484 """
6488 """
6485 fnames = (fname1,) + fnames
6489 fnames = (fname1,) + fnames
6486
6490
6487 lock = repo.lock()
6491 lock = repo.lock()
6488 try:
6492 try:
6489 for fname in fnames:
6493 for fname in fnames:
6490 f = hg.openpath(ui, fname)
6494 f = hg.openpath(ui, fname)
6491 gen = exchange.readbundle(ui, f, fname)
6495 gen = exchange.readbundle(ui, f, fname)
6492 if isinstance(gen, bundle2.unbundle20):
6496 if isinstance(gen, bundle2.unbundle20):
6493 tr = repo.transaction('unbundle')
6497 tr = repo.transaction('unbundle')
6494 try:
6498 try:
6495 op = bundle2.processbundle(repo, gen, lambda: tr)
6499 op = bundle2.processbundle(repo, gen, lambda: tr)
6496 tr.close()
6500 tr.close()
6497 except error.BundleUnknownFeatureError as exc:
6501 except error.BundleUnknownFeatureError as exc:
6498 raise error.Abort(_('%s: unknown bundle feature, %s')
6502 raise error.Abort(_('%s: unknown bundle feature, %s')
6499 % (fname, exc),
6503 % (fname, exc),
6500 hint=_("see https://mercurial-scm.org/"
6504 hint=_("see https://mercurial-scm.org/"
6501 "wiki/BundleFeature for more "
6505 "wiki/BundleFeature for more "
6502 "information"))
6506 "information"))
6503 finally:
6507 finally:
6504 if tr:
6508 if tr:
6505 tr.release()
6509 tr.release()
6506 changes = [r.get('return', 0)
6510 changes = [r.get('return', 0)
6507 for r in op.records['changegroup']]
6511 for r in op.records['changegroup']]
6508 modheads = changegroup.combineresults(changes)
6512 modheads = changegroup.combineresults(changes)
6509 else:
6513 else:
6510 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6514 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6511 'bundle:' + fname)
6515 'bundle:' + fname)
6512 finally:
6516 finally:
6513 lock.release()
6517 lock.release()
6514
6518
6515 return postincoming(ui, repo, modheads, opts.get('update'), None)
6519 return postincoming(ui, repo, modheads, opts.get('update'), None)
6516
6520
6517 @command('^update|up|checkout|co',
6521 @command('^update|up|checkout|co',
6518 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6522 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6519 ('c', 'check', None,
6523 ('c', 'check', None,
6520 _('update across branches if no uncommitted changes')),
6524 _('update across branches if no uncommitted changes')),
6521 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6525 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6522 ('r', 'rev', '', _('revision'), _('REV'))
6526 ('r', 'rev', '', _('revision'), _('REV'))
6523 ] + mergetoolopts,
6527 ] + mergetoolopts,
6524 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6528 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6525 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6529 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6526 tool=None):
6530 tool=None):
6527 """update working directory (or switch revisions)
6531 """update working directory (or switch revisions)
6528
6532
6529 Update the repository's working directory to the specified
6533 Update the repository's working directory to the specified
6530 changeset. If no changeset is specified, update to the tip of the
6534 changeset. If no changeset is specified, update to the tip of the
6531 current named branch and move the active bookmark (see :hg:`help
6535 current named branch and move the active bookmark (see :hg:`help
6532 bookmarks`).
6536 bookmarks`).
6533
6537
6534 Update sets the working directory's parent revision to the specified
6538 Update sets the working directory's parent revision to the specified
6535 changeset (see :hg:`help parents`).
6539 changeset (see :hg:`help parents`).
6536
6540
6537 If the changeset is not a descendant or ancestor of the working
6541 If the changeset is not a descendant or ancestor of the working
6538 directory's parent, the update is aborted. With the -c/--check
6542 directory's parent, the update is aborted. With the -c/--check
6539 option, the working directory is checked for uncommitted changes; if
6543 option, the working directory is checked for uncommitted changes; if
6540 none are found, the working directory is updated to the specified
6544 none are found, the working directory is updated to the specified
6541 changeset.
6545 changeset.
6542
6546
6543 .. container:: verbose
6547 .. container:: verbose
6544
6548
6545 The following rules apply when the working directory contains
6549 The following rules apply when the working directory contains
6546 uncommitted changes:
6550 uncommitted changes:
6547
6551
6548 1. If neither -c/--check nor -C/--clean is specified, and if
6552 1. If neither -c/--check nor -C/--clean is specified, and if
6549 the requested changeset is an ancestor or descendant of
6553 the requested changeset is an ancestor or descendant of
6550 the working directory's parent, the uncommitted changes
6554 the working directory's parent, the uncommitted changes
6551 are merged into the requested changeset and the merged
6555 are merged into the requested changeset and the merged
6552 result is left uncommitted. If the requested changeset is
6556 result is left uncommitted. If the requested changeset is
6553 not an ancestor or descendant (that is, it is on another
6557 not an ancestor or descendant (that is, it is on another
6554 branch), the update is aborted and the uncommitted changes
6558 branch), the update is aborted and the uncommitted changes
6555 are preserved.
6559 are preserved.
6556
6560
6557 2. With the -c/--check option, the update is aborted and the
6561 2. With the -c/--check option, the update is aborted and the
6558 uncommitted changes are preserved.
6562 uncommitted changes are preserved.
6559
6563
6560 3. With the -C/--clean option, uncommitted changes are discarded and
6564 3. With the -C/--clean option, uncommitted changes are discarded and
6561 the working directory is updated to the requested changeset.
6565 the working directory is updated to the requested changeset.
6562
6566
6563 To cancel an uncommitted merge (and lose your changes), use
6567 To cancel an uncommitted merge (and lose your changes), use
6564 :hg:`update --clean .`.
6568 :hg:`update --clean .`.
6565
6569
6566 Use null as the changeset to remove the working directory (like
6570 Use null as the changeset to remove the working directory (like
6567 :hg:`clone -U`).
6571 :hg:`clone -U`).
6568
6572
6569 If you want to revert just one file to an older revision, use
6573 If you want to revert just one file to an older revision, use
6570 :hg:`revert [-r REV] NAME`.
6574 :hg:`revert [-r REV] NAME`.
6571
6575
6572 See :hg:`help dates` for a list of formats valid for -d/--date.
6576 See :hg:`help dates` for a list of formats valid for -d/--date.
6573
6577
6574 Returns 0 on success, 1 if there are unresolved files.
6578 Returns 0 on success, 1 if there are unresolved files.
6575 """
6579 """
6576 movemarkfrom = None
6580 movemarkfrom = None
6577 if rev and node:
6581 if rev and node:
6578 raise error.Abort(_("please specify just one revision"))
6582 raise error.Abort(_("please specify just one revision"))
6579
6583
6580 if rev is None or rev == '':
6584 if rev is None or rev == '':
6581 rev = node
6585 rev = node
6582
6586
6583 wlock = repo.wlock()
6587 wlock = repo.wlock()
6584 try:
6588 try:
6585 cmdutil.clearunfinished(repo)
6589 cmdutil.clearunfinished(repo)
6586
6590
6587 if date:
6591 if date:
6588 if rev is not None:
6592 if rev is not None:
6589 raise error.Abort(_("you can't specify a revision and a date"))
6593 raise error.Abort(_("you can't specify a revision and a date"))
6590 rev = cmdutil.finddate(ui, repo, date)
6594 rev = cmdutil.finddate(ui, repo, date)
6591
6595
6592 # if we defined a bookmark, we have to remember the original name
6596 # if we defined a bookmark, we have to remember the original name
6593 brev = rev
6597 brev = rev
6594 rev = scmutil.revsingle(repo, rev, rev).rev()
6598 rev = scmutil.revsingle(repo, rev, rev).rev()
6595
6599
6596 if check and clean:
6600 if check and clean:
6597 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6601 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6598 )
6602 )
6599
6603
6600 if check:
6604 if check:
6601 cmdutil.bailifchanged(repo, merge=False)
6605 cmdutil.bailifchanged(repo, merge=False)
6602 if rev is None:
6606 if rev is None:
6603 updata = destutil.destupdate(repo, clean=clean, check=check)
6607 updata = destutil.destupdate(repo, clean=clean, check=check)
6604 rev, movemarkfrom, brev = updata
6608 rev, movemarkfrom, brev = updata
6605
6609
6606 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6610 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6607
6611
6608 if clean:
6612 if clean:
6609 ret = hg.clean(repo, rev)
6613 ret = hg.clean(repo, rev)
6610 else:
6614 else:
6611 ret = hg.update(repo, rev)
6615 ret = hg.update(repo, rev)
6612
6616
6613 if not ret and movemarkfrom:
6617 if not ret and movemarkfrom:
6614 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6618 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6615 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6619 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6616 else:
6620 else:
6617 # this can happen with a non-linear update
6621 # this can happen with a non-linear update
6618 ui.status(_("(leaving bookmark %s)\n") %
6622 ui.status(_("(leaving bookmark %s)\n") %
6619 repo._activebookmark)
6623 repo._activebookmark)
6620 bookmarks.deactivate(repo)
6624 bookmarks.deactivate(repo)
6621 elif brev in repo._bookmarks:
6625 elif brev in repo._bookmarks:
6622 bookmarks.activate(repo, brev)
6626 bookmarks.activate(repo, brev)
6623 ui.status(_("(activating bookmark %s)\n") % brev)
6627 ui.status(_("(activating bookmark %s)\n") % brev)
6624 elif brev:
6628 elif brev:
6625 if repo._activebookmark:
6629 if repo._activebookmark:
6626 ui.status(_("(leaving bookmark %s)\n") %
6630 ui.status(_("(leaving bookmark %s)\n") %
6627 repo._activebookmark)
6631 repo._activebookmark)
6628 bookmarks.deactivate(repo)
6632 bookmarks.deactivate(repo)
6629 finally:
6633 finally:
6630 wlock.release()
6634 wlock.release()
6631
6635
6632 return ret
6636 return ret
6633
6637
6634 @command('verify', [])
6638 @command('verify', [])
6635 def verify(ui, repo):
6639 def verify(ui, repo):
6636 """verify the integrity of the repository
6640 """verify the integrity of the repository
6637
6641
6638 Verify the integrity of the current repository.
6642 Verify the integrity of the current repository.
6639
6643
6640 This will perform an extensive check of the repository's
6644 This will perform an extensive check of the repository's
6641 integrity, validating the hashes and checksums of each entry in
6645 integrity, validating the hashes and checksums of each entry in
6642 the changelog, manifest, and tracked files, as well as the
6646 the changelog, manifest, and tracked files, as well as the
6643 integrity of their crosslinks and indices.
6647 integrity of their crosslinks and indices.
6644
6648
6645 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6649 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6646 for more information about recovery from corruption of the
6650 for more information about recovery from corruption of the
6647 repository.
6651 repository.
6648
6652
6649 Returns 0 on success, 1 if errors are encountered.
6653 Returns 0 on success, 1 if errors are encountered.
6650 """
6654 """
6651 return hg.verify(repo)
6655 return hg.verify(repo)
6652
6656
6653 @command('version', [], norepo=True)
6657 @command('version', [], norepo=True)
6654 def version_(ui):
6658 def version_(ui):
6655 """output version and copyright information"""
6659 """output version and copyright information"""
6656 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6660 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6657 % util.version())
6661 % util.version())
6658 ui.status(_(
6662 ui.status(_(
6659 "(see https://mercurial-scm.org for more information)\n"
6663 "(see https://mercurial-scm.org for more information)\n"
6660 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6664 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6661 "This is free software; see the source for copying conditions. "
6665 "This is free software; see the source for copying conditions. "
6662 "There is NO\nwarranty; "
6666 "There is NO\nwarranty; "
6663 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6667 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6664 ))
6668 ))
6665
6669
6666 ui.note(_("\nEnabled extensions:\n\n"))
6670 ui.note(_("\nEnabled extensions:\n\n"))
6667 if ui.verbose:
6671 if ui.verbose:
6668 # format names and versions into columns
6672 # format names and versions into columns
6669 names = []
6673 names = []
6670 vers = []
6674 vers = []
6671 for name, module in extensions.extensions():
6675 for name, module in extensions.extensions():
6672 names.append(name)
6676 names.append(name)
6673 vers.append(extensions.moduleversion(module))
6677 vers.append(extensions.moduleversion(module))
6674 if names:
6678 if names:
6675 maxnamelen = max(len(n) for n in names)
6679 maxnamelen = max(len(n) for n in names)
6676 for i, name in enumerate(names):
6680 for i, name in enumerate(names):
6677 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6681 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now