##// END OF EJS Templates
commands: use the optional badfn argument when building a matcher
Matt Harbison -
r25468:72edd54d default
parent child Browse files
Show More
@@ -1,6517 +1,6517 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, commandserver
16 import sshserver, hgweb, commandserver
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
22 import random
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
24 import phases, obsolete, exchange, bundle2
24 import phases, obsolete, exchange, bundle2
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 util.Abort(_('similarity must be a number'))
241 raise util.Abort(_('similarity must be a number'))
242 if sim < 0 or sim > 100:
242 if sim < 0 or sim > 100:
243 raise util.Abort(_('similarity must be between 0 and 100'))
243 raise util.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 util.Abort(_('at least one filename or pattern is required'))
279 raise util.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 util.Abort(_('at least one of -n/-c is required for -l'))
336 raise util.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 util.Abort("%s: %s" % (x, y))
351 raise util.Abort("%s: %s" % (x, y))
352
352
353 m = scmutil.match(ctx, pats, opts)
353 m = scmutil.match(ctx, pats, opts, badfn=bad)
354 m.bad = bad
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 util.Abort(_('no working directory: please specify a revision'))
441 raise util.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 util.Abort(_('repository root cannot be destination'))
445 raise util.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 util.Abort(_('cannot archive plain files to stdout'))
452 raise util.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 Returns 0 on success, 1 if nothing to backout or there are unresolved
500 Returns 0 on success, 1 if nothing to backout or there are unresolved
501 files.
501 files.
502 '''
502 '''
503 if rev and node:
503 if rev and node:
504 raise util.Abort(_("please specify just one revision"))
504 raise util.Abort(_("please specify just one revision"))
505
505
506 if not rev:
506 if not rev:
507 rev = node
507 rev = node
508
508
509 if not rev:
509 if not rev:
510 raise util.Abort(_("please specify a revision to backout"))
510 raise util.Abort(_("please specify a revision to backout"))
511
511
512 date = opts.get('date')
512 date = opts.get('date')
513 if date:
513 if date:
514 opts['date'] = util.parsedate(date)
514 opts['date'] = util.parsedate(date)
515
515
516 cmdutil.checkunfinished(repo)
516 cmdutil.checkunfinished(repo)
517 cmdutil.bailifchanged(repo)
517 cmdutil.bailifchanged(repo)
518 node = scmutil.revsingle(repo, rev).node()
518 node = scmutil.revsingle(repo, rev).node()
519
519
520 op1, op2 = repo.dirstate.parents()
520 op1, op2 = repo.dirstate.parents()
521 if not repo.changelog.isancestor(node, op1):
521 if not repo.changelog.isancestor(node, op1):
522 raise util.Abort(_('cannot backout change that is not an ancestor'))
522 raise util.Abort(_('cannot backout change that is not an ancestor'))
523
523
524 p1, p2 = repo.changelog.parents(node)
524 p1, p2 = repo.changelog.parents(node)
525 if p1 == nullid:
525 if p1 == nullid:
526 raise util.Abort(_('cannot backout a change with no parents'))
526 raise util.Abort(_('cannot backout a change with no parents'))
527 if p2 != nullid:
527 if p2 != nullid:
528 if not opts.get('parent'):
528 if not opts.get('parent'):
529 raise util.Abort(_('cannot backout a merge changeset'))
529 raise util.Abort(_('cannot backout a merge changeset'))
530 p = repo.lookup(opts['parent'])
530 p = repo.lookup(opts['parent'])
531 if p not in (p1, p2):
531 if p not in (p1, p2):
532 raise util.Abort(_('%s is not a parent of %s') %
532 raise util.Abort(_('%s is not a parent of %s') %
533 (short(p), short(node)))
533 (short(p), short(node)))
534 parent = p
534 parent = p
535 else:
535 else:
536 if opts.get('parent'):
536 if opts.get('parent'):
537 raise util.Abort(_('cannot use --parent on non-merge changeset'))
537 raise util.Abort(_('cannot use --parent on non-merge changeset'))
538 parent = p1
538 parent = p1
539
539
540 # the backout should appear on the same branch
540 # the backout should appear on the same branch
541 wlock = repo.wlock()
541 wlock = repo.wlock()
542 try:
542 try:
543 branch = repo.dirstate.branch()
543 branch = repo.dirstate.branch()
544 bheads = repo.branchheads(branch)
544 bheads = repo.branchheads(branch)
545 rctx = scmutil.revsingle(repo, hex(parent))
545 rctx = scmutil.revsingle(repo, hex(parent))
546 if not opts.get('merge') and op1 != node:
546 if not opts.get('merge') and op1 != node:
547 try:
547 try:
548 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
548 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
549 'backout')
549 'backout')
550 repo.dirstate.beginparentchange()
550 repo.dirstate.beginparentchange()
551 stats = mergemod.update(repo, parent, True, True, False,
551 stats = mergemod.update(repo, parent, True, True, False,
552 node, False)
552 node, False)
553 repo.setparents(op1, op2)
553 repo.setparents(op1, op2)
554 repo.dirstate.endparentchange()
554 repo.dirstate.endparentchange()
555 hg._showstats(repo, stats)
555 hg._showstats(repo, stats)
556 if stats[3]:
556 if stats[3]:
557 repo.ui.status(_("use 'hg resolve' to retry unresolved "
557 repo.ui.status(_("use 'hg resolve' to retry unresolved "
558 "file merges\n"))
558 "file merges\n"))
559 return 1
559 return 1
560 elif not commit:
560 elif not commit:
561 msg = _("changeset %s backed out, "
561 msg = _("changeset %s backed out, "
562 "don't forget to commit.\n")
562 "don't forget to commit.\n")
563 ui.status(msg % short(node))
563 ui.status(msg % short(node))
564 return 0
564 return 0
565 finally:
565 finally:
566 ui.setconfig('ui', 'forcemerge', '', '')
566 ui.setconfig('ui', 'forcemerge', '', '')
567 else:
567 else:
568 hg.clean(repo, node, show_stats=False)
568 hg.clean(repo, node, show_stats=False)
569 repo.dirstate.setbranch(branch)
569 repo.dirstate.setbranch(branch)
570 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
570 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
571
571
572
572
573 def commitfunc(ui, repo, message, match, opts):
573 def commitfunc(ui, repo, message, match, opts):
574 editform = 'backout'
574 editform = 'backout'
575 e = cmdutil.getcommiteditor(editform=editform, **opts)
575 e = cmdutil.getcommiteditor(editform=editform, **opts)
576 if not message:
576 if not message:
577 # we don't translate commit messages
577 # we don't translate commit messages
578 message = "Backed out changeset %s" % short(node)
578 message = "Backed out changeset %s" % short(node)
579 e = cmdutil.getcommiteditor(edit=True, editform=editform)
579 e = cmdutil.getcommiteditor(edit=True, editform=editform)
580 return repo.commit(message, opts.get('user'), opts.get('date'),
580 return repo.commit(message, opts.get('user'), opts.get('date'),
581 match, editor=e)
581 match, editor=e)
582 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
582 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
583 if not newnode:
583 if not newnode:
584 ui.status(_("nothing changed\n"))
584 ui.status(_("nothing changed\n"))
585 return 1
585 return 1
586 cmdutil.commitstatus(repo, newnode, branch, bheads)
586 cmdutil.commitstatus(repo, newnode, branch, bheads)
587
587
588 def nice(node):
588 def nice(node):
589 return '%d:%s' % (repo.changelog.rev(node), short(node))
589 return '%d:%s' % (repo.changelog.rev(node), short(node))
590 ui.status(_('changeset %s backs out changeset %s\n') %
590 ui.status(_('changeset %s backs out changeset %s\n') %
591 (nice(repo.changelog.tip()), nice(node)))
591 (nice(repo.changelog.tip()), nice(node)))
592 if opts.get('merge') and op1 != node:
592 if opts.get('merge') and op1 != node:
593 hg.clean(repo, op1, show_stats=False)
593 hg.clean(repo, op1, show_stats=False)
594 ui.status(_('merging with changeset %s\n')
594 ui.status(_('merging with changeset %s\n')
595 % nice(repo.changelog.tip()))
595 % nice(repo.changelog.tip()))
596 try:
596 try:
597 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
597 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
598 'backout')
598 'backout')
599 return hg.merge(repo, hex(repo.changelog.tip()))
599 return hg.merge(repo, hex(repo.changelog.tip()))
600 finally:
600 finally:
601 ui.setconfig('ui', 'forcemerge', '', '')
601 ui.setconfig('ui', 'forcemerge', '', '')
602 finally:
602 finally:
603 wlock.release()
603 wlock.release()
604 return 0
604 return 0
605
605
606 @command('bisect',
606 @command('bisect',
607 [('r', 'reset', False, _('reset bisect state')),
607 [('r', 'reset', False, _('reset bisect state')),
608 ('g', 'good', False, _('mark changeset good')),
608 ('g', 'good', False, _('mark changeset good')),
609 ('b', 'bad', False, _('mark changeset bad')),
609 ('b', 'bad', False, _('mark changeset bad')),
610 ('s', 'skip', False, _('skip testing changeset')),
610 ('s', 'skip', False, _('skip testing changeset')),
611 ('e', 'extend', False, _('extend the bisect range')),
611 ('e', 'extend', False, _('extend the bisect range')),
612 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
612 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
613 ('U', 'noupdate', False, _('do not update to target'))],
613 ('U', 'noupdate', False, _('do not update to target'))],
614 _("[-gbsr] [-U] [-c CMD] [REV]"))
614 _("[-gbsr] [-U] [-c CMD] [REV]"))
615 def bisect(ui, repo, rev=None, extra=None, command=None,
615 def bisect(ui, repo, rev=None, extra=None, command=None,
616 reset=None, good=None, bad=None, skip=None, extend=None,
616 reset=None, good=None, bad=None, skip=None, extend=None,
617 noupdate=None):
617 noupdate=None):
618 """subdivision search of changesets
618 """subdivision search of changesets
619
619
620 This command helps to find changesets which introduce problems. To
620 This command helps to find changesets which introduce problems. To
621 use, mark the earliest changeset you know exhibits the problem as
621 use, mark the earliest changeset you know exhibits the problem as
622 bad, then mark the latest changeset which is free from the problem
622 bad, then mark the latest changeset which is free from the problem
623 as good. Bisect will update your working directory to a revision
623 as good. Bisect will update your working directory to a revision
624 for testing (unless the -U/--noupdate option is specified). Once
624 for testing (unless the -U/--noupdate option is specified). Once
625 you have performed tests, mark the working directory as good or
625 you have performed tests, mark the working directory as good or
626 bad, and bisect will either update to another candidate changeset
626 bad, and bisect will either update to another candidate changeset
627 or announce that it has found the bad revision.
627 or announce that it has found the bad revision.
628
628
629 As a shortcut, you can also use the revision argument to mark a
629 As a shortcut, you can also use the revision argument to mark a
630 revision as good or bad without checking it out first.
630 revision as good or bad without checking it out first.
631
631
632 If you supply a command, it will be used for automatic bisection.
632 If you supply a command, it will be used for automatic bisection.
633 The environment variable HG_NODE will contain the ID of the
633 The environment variable HG_NODE will contain the ID of the
634 changeset being tested. The exit status of the command will be
634 changeset being tested. The exit status of the command will be
635 used to mark revisions as good or bad: status 0 means good, 125
635 used to mark revisions as good or bad: status 0 means good, 125
636 means to skip the revision, 127 (command not found) will abort the
636 means to skip the revision, 127 (command not found) will abort the
637 bisection, and any other non-zero exit status means the revision
637 bisection, and any other non-zero exit status means the revision
638 is bad.
638 is bad.
639
639
640 .. container:: verbose
640 .. container:: verbose
641
641
642 Some examples:
642 Some examples:
643
643
644 - start a bisection with known bad revision 34, and good revision 12::
644 - start a bisection with known bad revision 34, and good revision 12::
645
645
646 hg bisect --bad 34
646 hg bisect --bad 34
647 hg bisect --good 12
647 hg bisect --good 12
648
648
649 - advance the current bisection by marking current revision as good or
649 - advance the current bisection by marking current revision as good or
650 bad::
650 bad::
651
651
652 hg bisect --good
652 hg bisect --good
653 hg bisect --bad
653 hg bisect --bad
654
654
655 - mark the current revision, or a known revision, to be skipped (e.g. if
655 - mark the current revision, or a known revision, to be skipped (e.g. if
656 that revision is not usable because of another issue)::
656 that revision is not usable because of another issue)::
657
657
658 hg bisect --skip
658 hg bisect --skip
659 hg bisect --skip 23
659 hg bisect --skip 23
660
660
661 - skip all revisions that do not touch directories ``foo`` or ``bar``::
661 - skip all revisions that do not touch directories ``foo`` or ``bar``::
662
662
663 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
663 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
664
664
665 - forget the current bisection::
665 - forget the current bisection::
666
666
667 hg bisect --reset
667 hg bisect --reset
668
668
669 - use 'make && make tests' to automatically find the first broken
669 - use 'make && make tests' to automatically find the first broken
670 revision::
670 revision::
671
671
672 hg bisect --reset
672 hg bisect --reset
673 hg bisect --bad 34
673 hg bisect --bad 34
674 hg bisect --good 12
674 hg bisect --good 12
675 hg bisect --command "make && make tests"
675 hg bisect --command "make && make tests"
676
676
677 - see all changesets whose states are already known in the current
677 - see all changesets whose states are already known in the current
678 bisection::
678 bisection::
679
679
680 hg log -r "bisect(pruned)"
680 hg log -r "bisect(pruned)"
681
681
682 - see the changeset currently being bisected (especially useful
682 - see the changeset currently being bisected (especially useful
683 if running with -U/--noupdate)::
683 if running with -U/--noupdate)::
684
684
685 hg log -r "bisect(current)"
685 hg log -r "bisect(current)"
686
686
687 - see all changesets that took part in the current bisection::
687 - see all changesets that took part in the current bisection::
688
688
689 hg log -r "bisect(range)"
689 hg log -r "bisect(range)"
690
690
691 - you can even get a nice graph::
691 - you can even get a nice graph::
692
692
693 hg log --graph -r "bisect(range)"
693 hg log --graph -r "bisect(range)"
694
694
695 See :hg:`help revsets` for more about the `bisect()` keyword.
695 See :hg:`help revsets` for more about the `bisect()` keyword.
696
696
697 Returns 0 on success.
697 Returns 0 on success.
698 """
698 """
699 def extendbisectrange(nodes, good):
699 def extendbisectrange(nodes, good):
700 # bisect is incomplete when it ends on a merge node and
700 # bisect is incomplete when it ends on a merge node and
701 # one of the parent was not checked.
701 # one of the parent was not checked.
702 parents = repo[nodes[0]].parents()
702 parents = repo[nodes[0]].parents()
703 if len(parents) > 1:
703 if len(parents) > 1:
704 if good:
704 if good:
705 side = state['bad']
705 side = state['bad']
706 else:
706 else:
707 side = state['good']
707 side = state['good']
708 num = len(set(i.node() for i in parents) & set(side))
708 num = len(set(i.node() for i in parents) & set(side))
709 if num == 1:
709 if num == 1:
710 return parents[0].ancestor(parents[1])
710 return parents[0].ancestor(parents[1])
711 return None
711 return None
712
712
713 def print_result(nodes, good):
713 def print_result(nodes, good):
714 displayer = cmdutil.show_changeset(ui, repo, {})
714 displayer = cmdutil.show_changeset(ui, repo, {})
715 if len(nodes) == 1:
715 if len(nodes) == 1:
716 # narrowed it down to a single revision
716 # narrowed it down to a single revision
717 if good:
717 if good:
718 ui.write(_("The first good revision is:\n"))
718 ui.write(_("The first good revision is:\n"))
719 else:
719 else:
720 ui.write(_("The first bad revision is:\n"))
720 ui.write(_("The first bad revision is:\n"))
721 displayer.show(repo[nodes[0]])
721 displayer.show(repo[nodes[0]])
722 extendnode = extendbisectrange(nodes, good)
722 extendnode = extendbisectrange(nodes, good)
723 if extendnode is not None:
723 if extendnode is not None:
724 ui.write(_('Not all ancestors of this changeset have been'
724 ui.write(_('Not all ancestors of this changeset have been'
725 ' checked.\nUse bisect --extend to continue the '
725 ' checked.\nUse bisect --extend to continue the '
726 'bisection from\nthe common ancestor, %s.\n')
726 'bisection from\nthe common ancestor, %s.\n')
727 % extendnode)
727 % extendnode)
728 else:
728 else:
729 # multiple possible revisions
729 # multiple possible revisions
730 if good:
730 if good:
731 ui.write(_("Due to skipped revisions, the first "
731 ui.write(_("Due to skipped revisions, the first "
732 "good revision could be any of:\n"))
732 "good revision could be any of:\n"))
733 else:
733 else:
734 ui.write(_("Due to skipped revisions, the first "
734 ui.write(_("Due to skipped revisions, the first "
735 "bad revision could be any of:\n"))
735 "bad revision could be any of:\n"))
736 for n in nodes:
736 for n in nodes:
737 displayer.show(repo[n])
737 displayer.show(repo[n])
738 displayer.close()
738 displayer.close()
739
739
740 def check_state(state, interactive=True):
740 def check_state(state, interactive=True):
741 if not state['good'] or not state['bad']:
741 if not state['good'] or not state['bad']:
742 if (good or bad or skip or reset) and interactive:
742 if (good or bad or skip or reset) and interactive:
743 return
743 return
744 if not state['good']:
744 if not state['good']:
745 raise util.Abort(_('cannot bisect (no known good revisions)'))
745 raise util.Abort(_('cannot bisect (no known good revisions)'))
746 else:
746 else:
747 raise util.Abort(_('cannot bisect (no known bad revisions)'))
747 raise util.Abort(_('cannot bisect (no known bad revisions)'))
748 return True
748 return True
749
749
750 # backward compatibility
750 # backward compatibility
751 if rev in "good bad reset init".split():
751 if rev in "good bad reset init".split():
752 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
752 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
753 cmd, rev, extra = rev, extra, None
753 cmd, rev, extra = rev, extra, None
754 if cmd == "good":
754 if cmd == "good":
755 good = True
755 good = True
756 elif cmd == "bad":
756 elif cmd == "bad":
757 bad = True
757 bad = True
758 else:
758 else:
759 reset = True
759 reset = True
760 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
760 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
761 raise util.Abort(_('incompatible arguments'))
761 raise util.Abort(_('incompatible arguments'))
762
762
763 cmdutil.checkunfinished(repo)
763 cmdutil.checkunfinished(repo)
764
764
765 if reset:
765 if reset:
766 p = repo.join("bisect.state")
766 p = repo.join("bisect.state")
767 if os.path.exists(p):
767 if os.path.exists(p):
768 os.unlink(p)
768 os.unlink(p)
769 return
769 return
770
770
771 state = hbisect.load_state(repo)
771 state = hbisect.load_state(repo)
772
772
773 if command:
773 if command:
774 changesets = 1
774 changesets = 1
775 if noupdate:
775 if noupdate:
776 try:
776 try:
777 node = state['current'][0]
777 node = state['current'][0]
778 except LookupError:
778 except LookupError:
779 raise util.Abort(_('current bisect revision is unknown - '
779 raise util.Abort(_('current bisect revision is unknown - '
780 'start a new bisect to fix'))
780 'start a new bisect to fix'))
781 else:
781 else:
782 node, p2 = repo.dirstate.parents()
782 node, p2 = repo.dirstate.parents()
783 if p2 != nullid:
783 if p2 != nullid:
784 raise util.Abort(_('current bisect revision is a merge'))
784 raise util.Abort(_('current bisect revision is a merge'))
785 try:
785 try:
786 while changesets:
786 while changesets:
787 # update state
787 # update state
788 state['current'] = [node]
788 state['current'] = [node]
789 hbisect.save_state(repo, state)
789 hbisect.save_state(repo, state)
790 status = ui.system(command, environ={'HG_NODE': hex(node)})
790 status = ui.system(command, environ={'HG_NODE': hex(node)})
791 if status == 125:
791 if status == 125:
792 transition = "skip"
792 transition = "skip"
793 elif status == 0:
793 elif status == 0:
794 transition = "good"
794 transition = "good"
795 # status < 0 means process was killed
795 # status < 0 means process was killed
796 elif status == 127:
796 elif status == 127:
797 raise util.Abort(_("failed to execute %s") % command)
797 raise util.Abort(_("failed to execute %s") % command)
798 elif status < 0:
798 elif status < 0:
799 raise util.Abort(_("%s killed") % command)
799 raise util.Abort(_("%s killed") % command)
800 else:
800 else:
801 transition = "bad"
801 transition = "bad"
802 ctx = scmutil.revsingle(repo, rev, node)
802 ctx = scmutil.revsingle(repo, rev, node)
803 rev = None # clear for future iterations
803 rev = None # clear for future iterations
804 state[transition].append(ctx.node())
804 state[transition].append(ctx.node())
805 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
805 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
806 check_state(state, interactive=False)
806 check_state(state, interactive=False)
807 # bisect
807 # bisect
808 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
808 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
809 # update to next check
809 # update to next check
810 node = nodes[0]
810 node = nodes[0]
811 if not noupdate:
811 if not noupdate:
812 cmdutil.bailifchanged(repo)
812 cmdutil.bailifchanged(repo)
813 hg.clean(repo, node, show_stats=False)
813 hg.clean(repo, node, show_stats=False)
814 finally:
814 finally:
815 state['current'] = [node]
815 state['current'] = [node]
816 hbisect.save_state(repo, state)
816 hbisect.save_state(repo, state)
817 print_result(nodes, bgood)
817 print_result(nodes, bgood)
818 return
818 return
819
819
820 # update state
820 # update state
821
821
822 if rev:
822 if rev:
823 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
823 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
824 else:
824 else:
825 nodes = [repo.lookup('.')]
825 nodes = [repo.lookup('.')]
826
826
827 if good or bad or skip:
827 if good or bad or skip:
828 if good:
828 if good:
829 state['good'] += nodes
829 state['good'] += nodes
830 elif bad:
830 elif bad:
831 state['bad'] += nodes
831 state['bad'] += nodes
832 elif skip:
832 elif skip:
833 state['skip'] += nodes
833 state['skip'] += nodes
834 hbisect.save_state(repo, state)
834 hbisect.save_state(repo, state)
835
835
836 if not check_state(state):
836 if not check_state(state):
837 return
837 return
838
838
839 # actually bisect
839 # actually bisect
840 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
840 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
841 if extend:
841 if extend:
842 if not changesets:
842 if not changesets:
843 extendnode = extendbisectrange(nodes, good)
843 extendnode = extendbisectrange(nodes, good)
844 if extendnode is not None:
844 if extendnode is not None:
845 ui.write(_("Extending search to changeset %d:%s\n")
845 ui.write(_("Extending search to changeset %d:%s\n")
846 % (extendnode.rev(), extendnode))
846 % (extendnode.rev(), extendnode))
847 state['current'] = [extendnode.node()]
847 state['current'] = [extendnode.node()]
848 hbisect.save_state(repo, state)
848 hbisect.save_state(repo, state)
849 if noupdate:
849 if noupdate:
850 return
850 return
851 cmdutil.bailifchanged(repo)
851 cmdutil.bailifchanged(repo)
852 return hg.clean(repo, extendnode.node())
852 return hg.clean(repo, extendnode.node())
853 raise util.Abort(_("nothing to extend"))
853 raise util.Abort(_("nothing to extend"))
854
854
855 if changesets == 0:
855 if changesets == 0:
856 print_result(nodes, good)
856 print_result(nodes, good)
857 else:
857 else:
858 assert len(nodes) == 1 # only a single node can be tested next
858 assert len(nodes) == 1 # only a single node can be tested next
859 node = nodes[0]
859 node = nodes[0]
860 # compute the approximate number of remaining tests
860 # compute the approximate number of remaining tests
861 tests, size = 0, 2
861 tests, size = 0, 2
862 while size <= changesets:
862 while size <= changesets:
863 tests, size = tests + 1, size * 2
863 tests, size = tests + 1, size * 2
864 rev = repo.changelog.rev(node)
864 rev = repo.changelog.rev(node)
865 ui.write(_("Testing changeset %d:%s "
865 ui.write(_("Testing changeset %d:%s "
866 "(%d changesets remaining, ~%d tests)\n")
866 "(%d changesets remaining, ~%d tests)\n")
867 % (rev, short(node), changesets, tests))
867 % (rev, short(node), changesets, tests))
868 state['current'] = [node]
868 state['current'] = [node]
869 hbisect.save_state(repo, state)
869 hbisect.save_state(repo, state)
870 if not noupdate:
870 if not noupdate:
871 cmdutil.bailifchanged(repo)
871 cmdutil.bailifchanged(repo)
872 return hg.clean(repo, node)
872 return hg.clean(repo, node)
873
873
874 @command('bookmarks|bookmark',
874 @command('bookmarks|bookmark',
875 [('f', 'force', False, _('force')),
875 [('f', 'force', False, _('force')),
876 ('r', 'rev', '', _('revision'), _('REV')),
876 ('r', 'rev', '', _('revision'), _('REV')),
877 ('d', 'delete', False, _('delete a given bookmark')),
877 ('d', 'delete', False, _('delete a given bookmark')),
878 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
878 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
879 ('i', 'inactive', False, _('mark a bookmark inactive')),
879 ('i', 'inactive', False, _('mark a bookmark inactive')),
880 ] + formatteropts,
880 ] + formatteropts,
881 _('hg bookmarks [OPTIONS]... [NAME]...'))
881 _('hg bookmarks [OPTIONS]... [NAME]...'))
882 def bookmark(ui, repo, *names, **opts):
882 def bookmark(ui, repo, *names, **opts):
883 '''create a new bookmark or list existing bookmarks
883 '''create a new bookmark or list existing bookmarks
884
884
885 Bookmarks are labels on changesets to help track lines of development.
885 Bookmarks are labels on changesets to help track lines of development.
886 Bookmarks are unversioned and can be moved, renamed and deleted.
886 Bookmarks are unversioned and can be moved, renamed and deleted.
887 Deleting or moving a bookmark has no effect on the associated changesets.
887 Deleting or moving a bookmark has no effect on the associated changesets.
888
888
889 Creating or updating to a bookmark causes it to be marked as 'active'.
889 Creating or updating to a bookmark causes it to be marked as 'active'.
890 The active bookmark is indicated with a '*'.
890 The active bookmark is indicated with a '*'.
891 When a commit is made, the active bookmark will advance to the new commit.
891 When a commit is made, the active bookmark will advance to the new commit.
892 A plain :hg:`update` will also advance an active bookmark, if possible.
892 A plain :hg:`update` will also advance an active bookmark, if possible.
893 Updating away from a bookmark will cause it to be deactivated.
893 Updating away from a bookmark will cause it to be deactivated.
894
894
895 Bookmarks can be pushed and pulled between repositories (see
895 Bookmarks can be pushed and pulled between repositories (see
896 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
896 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
897 diverged, a new 'divergent bookmark' of the form 'name@path' will
897 diverged, a new 'divergent bookmark' of the form 'name@path' will
898 be created. Using :hg:`merge` will resolve the divergence.
898 be created. Using :hg:`merge` will resolve the divergence.
899
899
900 A bookmark named '@' has the special property that :hg:`clone` will
900 A bookmark named '@' has the special property that :hg:`clone` will
901 check it out by default if it exists.
901 check it out by default if it exists.
902
902
903 .. container:: verbose
903 .. container:: verbose
904
904
905 Examples:
905 Examples:
906
906
907 - create an active bookmark for a new line of development::
907 - create an active bookmark for a new line of development::
908
908
909 hg book new-feature
909 hg book new-feature
910
910
911 - create an inactive bookmark as a place marker::
911 - create an inactive bookmark as a place marker::
912
912
913 hg book -i reviewed
913 hg book -i reviewed
914
914
915 - create an inactive bookmark on another changeset::
915 - create an inactive bookmark on another changeset::
916
916
917 hg book -r .^ tested
917 hg book -r .^ tested
918
918
919 - move the '@' bookmark from another branch::
919 - move the '@' bookmark from another branch::
920
920
921 hg book -f @
921 hg book -f @
922 '''
922 '''
923 force = opts.get('force')
923 force = opts.get('force')
924 rev = opts.get('rev')
924 rev = opts.get('rev')
925 delete = opts.get('delete')
925 delete = opts.get('delete')
926 rename = opts.get('rename')
926 rename = opts.get('rename')
927 inactive = opts.get('inactive')
927 inactive = opts.get('inactive')
928
928
929 def checkformat(mark):
929 def checkformat(mark):
930 mark = mark.strip()
930 mark = mark.strip()
931 if not mark:
931 if not mark:
932 raise util.Abort(_("bookmark names cannot consist entirely of "
932 raise util.Abort(_("bookmark names cannot consist entirely of "
933 "whitespace"))
933 "whitespace"))
934 scmutil.checknewlabel(repo, mark, 'bookmark')
934 scmutil.checknewlabel(repo, mark, 'bookmark')
935 return mark
935 return mark
936
936
937 def checkconflict(repo, mark, cur, force=False, target=None):
937 def checkconflict(repo, mark, cur, force=False, target=None):
938 if mark in marks and not force:
938 if mark in marks and not force:
939 if target:
939 if target:
940 if marks[mark] == target and target == cur:
940 if marks[mark] == target and target == cur:
941 # re-activating a bookmark
941 # re-activating a bookmark
942 return
942 return
943 anc = repo.changelog.ancestors([repo[target].rev()])
943 anc = repo.changelog.ancestors([repo[target].rev()])
944 bmctx = repo[marks[mark]]
944 bmctx = repo[marks[mark]]
945 divs = [repo[b].node() for b in marks
945 divs = [repo[b].node() for b in marks
946 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
946 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
947
947
948 # allow resolving a single divergent bookmark even if moving
948 # allow resolving a single divergent bookmark even if moving
949 # the bookmark across branches when a revision is specified
949 # the bookmark across branches when a revision is specified
950 # that contains a divergent bookmark
950 # that contains a divergent bookmark
951 if bmctx.rev() not in anc and target in divs:
951 if bmctx.rev() not in anc and target in divs:
952 bookmarks.deletedivergent(repo, [target], mark)
952 bookmarks.deletedivergent(repo, [target], mark)
953 return
953 return
954
954
955 deletefrom = [b for b in divs
955 deletefrom = [b for b in divs
956 if repo[b].rev() in anc or b == target]
956 if repo[b].rev() in anc or b == target]
957 bookmarks.deletedivergent(repo, deletefrom, mark)
957 bookmarks.deletedivergent(repo, deletefrom, mark)
958 if bookmarks.validdest(repo, bmctx, repo[target]):
958 if bookmarks.validdest(repo, bmctx, repo[target]):
959 ui.status(_("moving bookmark '%s' forward from %s\n") %
959 ui.status(_("moving bookmark '%s' forward from %s\n") %
960 (mark, short(bmctx.node())))
960 (mark, short(bmctx.node())))
961 return
961 return
962 raise util.Abort(_("bookmark '%s' already exists "
962 raise util.Abort(_("bookmark '%s' already exists "
963 "(use -f to force)") % mark)
963 "(use -f to force)") % mark)
964 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
964 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
965 and not force):
965 and not force):
966 raise util.Abort(
966 raise util.Abort(
967 _("a bookmark cannot have the name of an existing branch"))
967 _("a bookmark cannot have the name of an existing branch"))
968
968
969 if delete and rename:
969 if delete and rename:
970 raise util.Abort(_("--delete and --rename are incompatible"))
970 raise util.Abort(_("--delete and --rename are incompatible"))
971 if delete and rev:
971 if delete and rev:
972 raise util.Abort(_("--rev is incompatible with --delete"))
972 raise util.Abort(_("--rev is incompatible with --delete"))
973 if rename and rev:
973 if rename and rev:
974 raise util.Abort(_("--rev is incompatible with --rename"))
974 raise util.Abort(_("--rev is incompatible with --rename"))
975 if not names and (delete or rev):
975 if not names and (delete or rev):
976 raise util.Abort(_("bookmark name required"))
976 raise util.Abort(_("bookmark name required"))
977
977
978 if delete or rename or names or inactive:
978 if delete or rename or names or inactive:
979 wlock = repo.wlock()
979 wlock = repo.wlock()
980 try:
980 try:
981 cur = repo.changectx('.').node()
981 cur = repo.changectx('.').node()
982 marks = repo._bookmarks
982 marks = repo._bookmarks
983 if delete:
983 if delete:
984 for mark in names:
984 for mark in names:
985 if mark not in marks:
985 if mark not in marks:
986 raise util.Abort(_("bookmark '%s' does not exist") %
986 raise util.Abort(_("bookmark '%s' does not exist") %
987 mark)
987 mark)
988 if mark == repo._activebookmark:
988 if mark == repo._activebookmark:
989 bookmarks.deactivate(repo)
989 bookmarks.deactivate(repo)
990 del marks[mark]
990 del marks[mark]
991 marks.write()
991 marks.write()
992
992
993 elif rename:
993 elif rename:
994 if not names:
994 if not names:
995 raise util.Abort(_("new bookmark name required"))
995 raise util.Abort(_("new bookmark name required"))
996 elif len(names) > 1:
996 elif len(names) > 1:
997 raise util.Abort(_("only one new bookmark name allowed"))
997 raise util.Abort(_("only one new bookmark name allowed"))
998 mark = checkformat(names[0])
998 mark = checkformat(names[0])
999 if rename not in marks:
999 if rename not in marks:
1000 raise util.Abort(_("bookmark '%s' does not exist") % rename)
1000 raise util.Abort(_("bookmark '%s' does not exist") % rename)
1001 checkconflict(repo, mark, cur, force)
1001 checkconflict(repo, mark, cur, force)
1002 marks[mark] = marks[rename]
1002 marks[mark] = marks[rename]
1003 if repo._activebookmark == rename and not inactive:
1003 if repo._activebookmark == rename and not inactive:
1004 bookmarks.activate(repo, mark)
1004 bookmarks.activate(repo, mark)
1005 del marks[rename]
1005 del marks[rename]
1006 marks.write()
1006 marks.write()
1007
1007
1008 elif names:
1008 elif names:
1009 newact = None
1009 newact = None
1010 for mark in names:
1010 for mark in names:
1011 mark = checkformat(mark)
1011 mark = checkformat(mark)
1012 if newact is None:
1012 if newact is None:
1013 newact = mark
1013 newact = mark
1014 if inactive and mark == repo._activebookmark:
1014 if inactive and mark == repo._activebookmark:
1015 bookmarks.deactivate(repo)
1015 bookmarks.deactivate(repo)
1016 return
1016 return
1017 tgt = cur
1017 tgt = cur
1018 if rev:
1018 if rev:
1019 tgt = scmutil.revsingle(repo, rev).node()
1019 tgt = scmutil.revsingle(repo, rev).node()
1020 checkconflict(repo, mark, cur, force, tgt)
1020 checkconflict(repo, mark, cur, force, tgt)
1021 marks[mark] = tgt
1021 marks[mark] = tgt
1022 if not inactive and cur == marks[newact] and not rev:
1022 if not inactive and cur == marks[newact] and not rev:
1023 bookmarks.activate(repo, newact)
1023 bookmarks.activate(repo, newact)
1024 elif cur != tgt and newact == repo._activebookmark:
1024 elif cur != tgt and newact == repo._activebookmark:
1025 bookmarks.deactivate(repo)
1025 bookmarks.deactivate(repo)
1026 marks.write()
1026 marks.write()
1027
1027
1028 elif inactive:
1028 elif inactive:
1029 if len(marks) == 0:
1029 if len(marks) == 0:
1030 ui.status(_("no bookmarks set\n"))
1030 ui.status(_("no bookmarks set\n"))
1031 elif not repo._activebookmark:
1031 elif not repo._activebookmark:
1032 ui.status(_("no active bookmark\n"))
1032 ui.status(_("no active bookmark\n"))
1033 else:
1033 else:
1034 bookmarks.deactivate(repo)
1034 bookmarks.deactivate(repo)
1035 finally:
1035 finally:
1036 wlock.release()
1036 wlock.release()
1037 else: # show bookmarks
1037 else: # show bookmarks
1038 fm = ui.formatter('bookmarks', opts)
1038 fm = ui.formatter('bookmarks', opts)
1039 hexfn = fm.hexfunc
1039 hexfn = fm.hexfunc
1040 marks = repo._bookmarks
1040 marks = repo._bookmarks
1041 if len(marks) == 0 and not fm:
1041 if len(marks) == 0 and not fm:
1042 ui.status(_("no bookmarks set\n"))
1042 ui.status(_("no bookmarks set\n"))
1043 for bmark, n in sorted(marks.iteritems()):
1043 for bmark, n in sorted(marks.iteritems()):
1044 active = repo._activebookmark
1044 active = repo._activebookmark
1045 if bmark == active:
1045 if bmark == active:
1046 prefix, label = '*', activebookmarklabel
1046 prefix, label = '*', activebookmarklabel
1047 else:
1047 else:
1048 prefix, label = ' ', ''
1048 prefix, label = ' ', ''
1049
1049
1050 fm.startitem()
1050 fm.startitem()
1051 if not ui.quiet:
1051 if not ui.quiet:
1052 fm.plain(' %s ' % prefix, label=label)
1052 fm.plain(' %s ' % prefix, label=label)
1053 fm.write('bookmark', '%s', bmark, label=label)
1053 fm.write('bookmark', '%s', bmark, label=label)
1054 pad = " " * (25 - encoding.colwidth(bmark))
1054 pad = " " * (25 - encoding.colwidth(bmark))
1055 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1055 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1056 repo.changelog.rev(n), hexfn(n), label=label)
1056 repo.changelog.rev(n), hexfn(n), label=label)
1057 fm.data(active=(bmark == active))
1057 fm.data(active=(bmark == active))
1058 fm.plain('\n')
1058 fm.plain('\n')
1059 fm.end()
1059 fm.end()
1060
1060
1061 @command('branch',
1061 @command('branch',
1062 [('f', 'force', None,
1062 [('f', 'force', None,
1063 _('set branch name even if it shadows an existing branch')),
1063 _('set branch name even if it shadows an existing branch')),
1064 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1064 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1065 _('[-fC] [NAME]'))
1065 _('[-fC] [NAME]'))
1066 def branch(ui, repo, label=None, **opts):
1066 def branch(ui, repo, label=None, **opts):
1067 """set or show the current branch name
1067 """set or show the current branch name
1068
1068
1069 .. note::
1069 .. note::
1070
1070
1071 Branch names are permanent and global. Use :hg:`bookmark` to create a
1071 Branch names are permanent and global. Use :hg:`bookmark` to create a
1072 light-weight bookmark instead. See :hg:`help glossary` for more
1072 light-weight bookmark instead. See :hg:`help glossary` for more
1073 information about named branches and bookmarks.
1073 information about named branches and bookmarks.
1074
1074
1075 With no argument, show the current branch name. With one argument,
1075 With no argument, show the current branch name. With one argument,
1076 set the working directory branch name (the branch will not exist
1076 set the working directory branch name (the branch will not exist
1077 in the repository until the next commit). Standard practice
1077 in the repository until the next commit). Standard practice
1078 recommends that primary development take place on the 'default'
1078 recommends that primary development take place on the 'default'
1079 branch.
1079 branch.
1080
1080
1081 Unless -f/--force is specified, branch will not let you set a
1081 Unless -f/--force is specified, branch will not let you set a
1082 branch name that already exists.
1082 branch name that already exists.
1083
1083
1084 Use -C/--clean to reset the working directory branch to that of
1084 Use -C/--clean to reset the working directory branch to that of
1085 the parent of the working directory, negating a previous branch
1085 the parent of the working directory, negating a previous branch
1086 change.
1086 change.
1087
1087
1088 Use the command :hg:`update` to switch to an existing branch. Use
1088 Use the command :hg:`update` to switch to an existing branch. Use
1089 :hg:`commit --close-branch` to mark this branch head as closed.
1089 :hg:`commit --close-branch` to mark this branch head as closed.
1090 When all heads of the branch are closed, the branch will be
1090 When all heads of the branch are closed, the branch will be
1091 considered closed.
1091 considered closed.
1092
1092
1093 Returns 0 on success.
1093 Returns 0 on success.
1094 """
1094 """
1095 if label:
1095 if label:
1096 label = label.strip()
1096 label = label.strip()
1097
1097
1098 if not opts.get('clean') and not label:
1098 if not opts.get('clean') and not label:
1099 ui.write("%s\n" % repo.dirstate.branch())
1099 ui.write("%s\n" % repo.dirstate.branch())
1100 return
1100 return
1101
1101
1102 wlock = repo.wlock()
1102 wlock = repo.wlock()
1103 try:
1103 try:
1104 if opts.get('clean'):
1104 if opts.get('clean'):
1105 label = repo[None].p1().branch()
1105 label = repo[None].p1().branch()
1106 repo.dirstate.setbranch(label)
1106 repo.dirstate.setbranch(label)
1107 ui.status(_('reset working directory to branch %s\n') % label)
1107 ui.status(_('reset working directory to branch %s\n') % label)
1108 elif label:
1108 elif label:
1109 if not opts.get('force') and label in repo.branchmap():
1109 if not opts.get('force') and label in repo.branchmap():
1110 if label not in [p.branch() for p in repo.parents()]:
1110 if label not in [p.branch() for p in repo.parents()]:
1111 raise util.Abort(_('a branch of the same name already'
1111 raise util.Abort(_('a branch of the same name already'
1112 ' exists'),
1112 ' exists'),
1113 # i18n: "it" refers to an existing branch
1113 # i18n: "it" refers to an existing branch
1114 hint=_("use 'hg update' to switch to it"))
1114 hint=_("use 'hg update' to switch to it"))
1115 scmutil.checknewlabel(repo, label, 'branch')
1115 scmutil.checknewlabel(repo, label, 'branch')
1116 repo.dirstate.setbranch(label)
1116 repo.dirstate.setbranch(label)
1117 ui.status(_('marked working directory as branch %s\n') % label)
1117 ui.status(_('marked working directory as branch %s\n') % label)
1118
1118
1119 # find any open named branches aside from default
1119 # find any open named branches aside from default
1120 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1120 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1121 if n != "default" and not c]
1121 if n != "default" and not c]
1122 if not others:
1122 if not others:
1123 ui.status(_('(branches are permanent and global, '
1123 ui.status(_('(branches are permanent and global, '
1124 'did you want a bookmark?)\n'))
1124 'did you want a bookmark?)\n'))
1125 finally:
1125 finally:
1126 wlock.release()
1126 wlock.release()
1127
1127
1128 @command('branches',
1128 @command('branches',
1129 [('a', 'active', False,
1129 [('a', 'active', False,
1130 _('show only branches that have unmerged heads (DEPRECATED)')),
1130 _('show only branches that have unmerged heads (DEPRECATED)')),
1131 ('c', 'closed', False, _('show normal and closed branches')),
1131 ('c', 'closed', False, _('show normal and closed branches')),
1132 ] + formatteropts,
1132 ] + formatteropts,
1133 _('[-ac]'))
1133 _('[-ac]'))
1134 def branches(ui, repo, active=False, closed=False, **opts):
1134 def branches(ui, repo, active=False, closed=False, **opts):
1135 """list repository named branches
1135 """list repository named branches
1136
1136
1137 List the repository's named branches, indicating which ones are
1137 List the repository's named branches, indicating which ones are
1138 inactive. If -c/--closed is specified, also list branches which have
1138 inactive. If -c/--closed is specified, also list branches which have
1139 been marked closed (see :hg:`commit --close-branch`).
1139 been marked closed (see :hg:`commit --close-branch`).
1140
1140
1141 Use the command :hg:`update` to switch to an existing branch.
1141 Use the command :hg:`update` to switch to an existing branch.
1142
1142
1143 Returns 0.
1143 Returns 0.
1144 """
1144 """
1145
1145
1146 fm = ui.formatter('branches', opts)
1146 fm = ui.formatter('branches', opts)
1147 hexfunc = fm.hexfunc
1147 hexfunc = fm.hexfunc
1148
1148
1149 allheads = set(repo.heads())
1149 allheads = set(repo.heads())
1150 branches = []
1150 branches = []
1151 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1151 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1152 isactive = not isclosed and bool(set(heads) & allheads)
1152 isactive = not isclosed and bool(set(heads) & allheads)
1153 branches.append((tag, repo[tip], isactive, not isclosed))
1153 branches.append((tag, repo[tip], isactive, not isclosed))
1154 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1154 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1155 reverse=True)
1155 reverse=True)
1156
1156
1157 for tag, ctx, isactive, isopen in branches:
1157 for tag, ctx, isactive, isopen in branches:
1158 if active and not isactive:
1158 if active and not isactive:
1159 continue
1159 continue
1160 if isactive:
1160 if isactive:
1161 label = 'branches.active'
1161 label = 'branches.active'
1162 notice = ''
1162 notice = ''
1163 elif not isopen:
1163 elif not isopen:
1164 if not closed:
1164 if not closed:
1165 continue
1165 continue
1166 label = 'branches.closed'
1166 label = 'branches.closed'
1167 notice = _(' (closed)')
1167 notice = _(' (closed)')
1168 else:
1168 else:
1169 label = 'branches.inactive'
1169 label = 'branches.inactive'
1170 notice = _(' (inactive)')
1170 notice = _(' (inactive)')
1171 current = (tag == repo.dirstate.branch())
1171 current = (tag == repo.dirstate.branch())
1172 if current:
1172 if current:
1173 label = 'branches.current'
1173 label = 'branches.current'
1174
1174
1175 fm.startitem()
1175 fm.startitem()
1176 fm.write('branch', '%s', tag, label=label)
1176 fm.write('branch', '%s', tag, label=label)
1177 rev = ctx.rev()
1177 rev = ctx.rev()
1178 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1178 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1179 fmt = ' ' * padsize + ' %d:%s'
1179 fmt = ' ' * padsize + ' %d:%s'
1180 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1180 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1181 label='log.changeset changeset.%s' % ctx.phasestr())
1181 label='log.changeset changeset.%s' % ctx.phasestr())
1182 fm.data(active=isactive, closed=not isopen, current=current)
1182 fm.data(active=isactive, closed=not isopen, current=current)
1183 if not ui.quiet:
1183 if not ui.quiet:
1184 fm.plain(notice)
1184 fm.plain(notice)
1185 fm.plain('\n')
1185 fm.plain('\n')
1186 fm.end()
1186 fm.end()
1187
1187
1188 @command('bundle',
1188 @command('bundle',
1189 [('f', 'force', None, _('run even when the destination is unrelated')),
1189 [('f', 'force', None, _('run even when the destination is unrelated')),
1190 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1190 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1191 _('REV')),
1191 _('REV')),
1192 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1192 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1193 _('BRANCH')),
1193 _('BRANCH')),
1194 ('', 'base', [],
1194 ('', 'base', [],
1195 _('a base changeset assumed to be available at the destination'),
1195 _('a base changeset assumed to be available at the destination'),
1196 _('REV')),
1196 _('REV')),
1197 ('a', 'all', None, _('bundle all changesets in the repository')),
1197 ('a', 'all', None, _('bundle all changesets in the repository')),
1198 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1198 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1199 ] + remoteopts,
1199 ] + remoteopts,
1200 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1200 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1201 def bundle(ui, repo, fname, dest=None, **opts):
1201 def bundle(ui, repo, fname, dest=None, **opts):
1202 """create a changegroup file
1202 """create a changegroup file
1203
1203
1204 Generate a compressed changegroup file collecting changesets not
1204 Generate a compressed changegroup file collecting changesets not
1205 known to be in another repository.
1205 known to be in another repository.
1206
1206
1207 If you omit the destination repository, then hg assumes the
1207 If you omit the destination repository, then hg assumes the
1208 destination will have all the nodes you specify with --base
1208 destination will have all the nodes you specify with --base
1209 parameters. To create a bundle containing all changesets, use
1209 parameters. To create a bundle containing all changesets, use
1210 -a/--all (or --base null).
1210 -a/--all (or --base null).
1211
1211
1212 You can change compression method with the -t/--type option.
1212 You can change compression method with the -t/--type option.
1213 The available compression methods are: none, bzip2, and
1213 The available compression methods are: none, bzip2, and
1214 gzip (by default, bundles are compressed using bzip2).
1214 gzip (by default, bundles are compressed using bzip2).
1215
1215
1216 The bundle file can then be transferred using conventional means
1216 The bundle file can then be transferred using conventional means
1217 and applied to another repository with the unbundle or pull
1217 and applied to another repository with the unbundle or pull
1218 command. This is useful when direct push and pull are not
1218 command. This is useful when direct push and pull are not
1219 available or when exporting an entire repository is undesirable.
1219 available or when exporting an entire repository is undesirable.
1220
1220
1221 Applying bundles preserves all changeset contents including
1221 Applying bundles preserves all changeset contents including
1222 permissions, copy/rename information, and revision history.
1222 permissions, copy/rename information, and revision history.
1223
1223
1224 Returns 0 on success, 1 if no changes found.
1224 Returns 0 on success, 1 if no changes found.
1225 """
1225 """
1226 revs = None
1226 revs = None
1227 if 'rev' in opts:
1227 if 'rev' in opts:
1228 revs = scmutil.revrange(repo, opts['rev'])
1228 revs = scmutil.revrange(repo, opts['rev'])
1229
1229
1230 bundletype = opts.get('type', 'bzip2').lower()
1230 bundletype = opts.get('type', 'bzip2').lower()
1231 btypes = {'none': 'HG10UN',
1231 btypes = {'none': 'HG10UN',
1232 'bzip2': 'HG10BZ',
1232 'bzip2': 'HG10BZ',
1233 'gzip': 'HG10GZ',
1233 'gzip': 'HG10GZ',
1234 'bundle2': 'HG20'}
1234 'bundle2': 'HG20'}
1235 bundletype = btypes.get(bundletype)
1235 bundletype = btypes.get(bundletype)
1236 if bundletype not in changegroup.bundletypes:
1236 if bundletype not in changegroup.bundletypes:
1237 raise util.Abort(_('unknown bundle type specified with --type'))
1237 raise util.Abort(_('unknown bundle type specified with --type'))
1238
1238
1239 if opts.get('all'):
1239 if opts.get('all'):
1240 base = ['null']
1240 base = ['null']
1241 else:
1241 else:
1242 base = scmutil.revrange(repo, opts.get('base'))
1242 base = scmutil.revrange(repo, opts.get('base'))
1243 # TODO: get desired bundlecaps from command line.
1243 # TODO: get desired bundlecaps from command line.
1244 bundlecaps = None
1244 bundlecaps = None
1245 if base:
1245 if base:
1246 if dest:
1246 if dest:
1247 raise util.Abort(_("--base is incompatible with specifying "
1247 raise util.Abort(_("--base is incompatible with specifying "
1248 "a destination"))
1248 "a destination"))
1249 common = [repo.lookup(rev) for rev in base]
1249 common = [repo.lookup(rev) for rev in base]
1250 heads = revs and map(repo.lookup, revs) or revs
1250 heads = revs and map(repo.lookup, revs) or revs
1251 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1251 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1252 common=common, bundlecaps=bundlecaps)
1252 common=common, bundlecaps=bundlecaps)
1253 outgoing = None
1253 outgoing = None
1254 else:
1254 else:
1255 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1255 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1256 dest, branches = hg.parseurl(dest, opts.get('branch'))
1256 dest, branches = hg.parseurl(dest, opts.get('branch'))
1257 other = hg.peer(repo, opts, dest)
1257 other = hg.peer(repo, opts, dest)
1258 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1258 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1259 heads = revs and map(repo.lookup, revs) or revs
1259 heads = revs and map(repo.lookup, revs) or revs
1260 outgoing = discovery.findcommonoutgoing(repo, other,
1260 outgoing = discovery.findcommonoutgoing(repo, other,
1261 onlyheads=heads,
1261 onlyheads=heads,
1262 force=opts.get('force'),
1262 force=opts.get('force'),
1263 portable=True)
1263 portable=True)
1264 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1264 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1265 bundlecaps)
1265 bundlecaps)
1266 if not cg:
1266 if not cg:
1267 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1267 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1268 return 1
1268 return 1
1269
1269
1270 changegroup.writebundle(ui, cg, fname, bundletype)
1270 changegroup.writebundle(ui, cg, fname, bundletype)
1271
1271
1272 @command('cat',
1272 @command('cat',
1273 [('o', 'output', '',
1273 [('o', 'output', '',
1274 _('print output to file with formatted name'), _('FORMAT')),
1274 _('print output to file with formatted name'), _('FORMAT')),
1275 ('r', 'rev', '', _('print the given revision'), _('REV')),
1275 ('r', 'rev', '', _('print the given revision'), _('REV')),
1276 ('', 'decode', None, _('apply any matching decode filter')),
1276 ('', 'decode', None, _('apply any matching decode filter')),
1277 ] + walkopts,
1277 ] + walkopts,
1278 _('[OPTION]... FILE...'),
1278 _('[OPTION]... FILE...'),
1279 inferrepo=True)
1279 inferrepo=True)
1280 def cat(ui, repo, file1, *pats, **opts):
1280 def cat(ui, repo, file1, *pats, **opts):
1281 """output the current or given revision of files
1281 """output the current or given revision of files
1282
1282
1283 Print the specified files as they were at the given revision. If
1283 Print the specified files as they were at the given revision. If
1284 no revision is given, the parent of the working directory is used.
1284 no revision is given, the parent of the working directory is used.
1285
1285
1286 Output may be to a file, in which case the name of the file is
1286 Output may be to a file, in which case the name of the file is
1287 given using a format string. The formatting rules as follows:
1287 given using a format string. The formatting rules as follows:
1288
1288
1289 :``%%``: literal "%" character
1289 :``%%``: literal "%" character
1290 :``%s``: basename of file being printed
1290 :``%s``: basename of file being printed
1291 :``%d``: dirname of file being printed, or '.' if in repository root
1291 :``%d``: dirname of file being printed, or '.' if in repository root
1292 :``%p``: root-relative path name of file being printed
1292 :``%p``: root-relative path name of file being printed
1293 :``%H``: changeset hash (40 hexadecimal digits)
1293 :``%H``: changeset hash (40 hexadecimal digits)
1294 :``%R``: changeset revision number
1294 :``%R``: changeset revision number
1295 :``%h``: short-form changeset hash (12 hexadecimal digits)
1295 :``%h``: short-form changeset hash (12 hexadecimal digits)
1296 :``%r``: zero-padded changeset revision number
1296 :``%r``: zero-padded changeset revision number
1297 :``%b``: basename of the exporting repository
1297 :``%b``: basename of the exporting repository
1298
1298
1299 Returns 0 on success.
1299 Returns 0 on success.
1300 """
1300 """
1301 ctx = scmutil.revsingle(repo, opts.get('rev'))
1301 ctx = scmutil.revsingle(repo, opts.get('rev'))
1302 m = scmutil.match(ctx, (file1,) + pats, opts)
1302 m = scmutil.match(ctx, (file1,) + pats, opts)
1303
1303
1304 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1304 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1305
1305
1306 @command('^clone',
1306 @command('^clone',
1307 [('U', 'noupdate', None, _('the clone will include an empty working '
1307 [('U', 'noupdate', None, _('the clone will include an empty working '
1308 'directory (only a repository)')),
1308 'directory (only a repository)')),
1309 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1309 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1310 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1310 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1311 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1311 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1312 ('', 'pull', None, _('use pull protocol to copy metadata')),
1312 ('', 'pull', None, _('use pull protocol to copy metadata')),
1313 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1313 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1314 ] + remoteopts,
1314 ] + remoteopts,
1315 _('[OPTION]... SOURCE [DEST]'),
1315 _('[OPTION]... SOURCE [DEST]'),
1316 norepo=True)
1316 norepo=True)
1317 def clone(ui, source, dest=None, **opts):
1317 def clone(ui, source, dest=None, **opts):
1318 """make a copy of an existing repository
1318 """make a copy of an existing repository
1319
1319
1320 Create a copy of an existing repository in a new directory.
1320 Create a copy of an existing repository in a new directory.
1321
1321
1322 If no destination directory name is specified, it defaults to the
1322 If no destination directory name is specified, it defaults to the
1323 basename of the source.
1323 basename of the source.
1324
1324
1325 The location of the source is added to the new repository's
1325 The location of the source is added to the new repository's
1326 ``.hg/hgrc`` file, as the default to be used for future pulls.
1326 ``.hg/hgrc`` file, as the default to be used for future pulls.
1327
1327
1328 Only local paths and ``ssh://`` URLs are supported as
1328 Only local paths and ``ssh://`` URLs are supported as
1329 destinations. For ``ssh://`` destinations, no working directory or
1329 destinations. For ``ssh://`` destinations, no working directory or
1330 ``.hg/hgrc`` will be created on the remote side.
1330 ``.hg/hgrc`` will be created on the remote side.
1331
1331
1332 To pull only a subset of changesets, specify one or more revisions
1332 To pull only a subset of changesets, specify one or more revisions
1333 identifiers with -r/--rev or branches with -b/--branch. The
1333 identifiers with -r/--rev or branches with -b/--branch. The
1334 resulting clone will contain only the specified changesets and
1334 resulting clone will contain only the specified changesets and
1335 their ancestors. These options (or 'clone src#rev dest') imply
1335 their ancestors. These options (or 'clone src#rev dest') imply
1336 --pull, even for local source repositories. Note that specifying a
1336 --pull, even for local source repositories. Note that specifying a
1337 tag will include the tagged changeset but not the changeset
1337 tag will include the tagged changeset but not the changeset
1338 containing the tag.
1338 containing the tag.
1339
1339
1340 If the source repository has a bookmark called '@' set, that
1340 If the source repository has a bookmark called '@' set, that
1341 revision will be checked out in the new repository by default.
1341 revision will be checked out in the new repository by default.
1342
1342
1343 To check out a particular version, use -u/--update, or
1343 To check out a particular version, use -u/--update, or
1344 -U/--noupdate to create a clone with no working directory.
1344 -U/--noupdate to create a clone with no working directory.
1345
1345
1346 .. container:: verbose
1346 .. container:: verbose
1347
1347
1348 For efficiency, hardlinks are used for cloning whenever the
1348 For efficiency, hardlinks are used for cloning whenever the
1349 source and destination are on the same filesystem (note this
1349 source and destination are on the same filesystem (note this
1350 applies only to the repository data, not to the working
1350 applies only to the repository data, not to the working
1351 directory). Some filesystems, such as AFS, implement hardlinking
1351 directory). Some filesystems, such as AFS, implement hardlinking
1352 incorrectly, but do not report errors. In these cases, use the
1352 incorrectly, but do not report errors. In these cases, use the
1353 --pull option to avoid hardlinking.
1353 --pull option to avoid hardlinking.
1354
1354
1355 In some cases, you can clone repositories and the working
1355 In some cases, you can clone repositories and the working
1356 directory using full hardlinks with ::
1356 directory using full hardlinks with ::
1357
1357
1358 $ cp -al REPO REPOCLONE
1358 $ cp -al REPO REPOCLONE
1359
1359
1360 This is the fastest way to clone, but it is not always safe. The
1360 This is the fastest way to clone, but it is not always safe. The
1361 operation is not atomic (making sure REPO is not modified during
1361 operation is not atomic (making sure REPO is not modified during
1362 the operation is up to you) and you have to make sure your
1362 the operation is up to you) and you have to make sure your
1363 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1363 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1364 so). Also, this is not compatible with certain extensions that
1364 so). Also, this is not compatible with certain extensions that
1365 place their metadata under the .hg directory, such as mq.
1365 place their metadata under the .hg directory, such as mq.
1366
1366
1367 Mercurial will update the working directory to the first applicable
1367 Mercurial will update the working directory to the first applicable
1368 revision from this list:
1368 revision from this list:
1369
1369
1370 a) null if -U or the source repository has no changesets
1370 a) null if -U or the source repository has no changesets
1371 b) if -u . and the source repository is local, the first parent of
1371 b) if -u . and the source repository is local, the first parent of
1372 the source repository's working directory
1372 the source repository's working directory
1373 c) the changeset specified with -u (if a branch name, this means the
1373 c) the changeset specified with -u (if a branch name, this means the
1374 latest head of that branch)
1374 latest head of that branch)
1375 d) the changeset specified with -r
1375 d) the changeset specified with -r
1376 e) the tipmost head specified with -b
1376 e) the tipmost head specified with -b
1377 f) the tipmost head specified with the url#branch source syntax
1377 f) the tipmost head specified with the url#branch source syntax
1378 g) the revision marked with the '@' bookmark, if present
1378 g) the revision marked with the '@' bookmark, if present
1379 h) the tipmost head of the default branch
1379 h) the tipmost head of the default branch
1380 i) tip
1380 i) tip
1381
1381
1382 Examples:
1382 Examples:
1383
1383
1384 - clone a remote repository to a new directory named hg/::
1384 - clone a remote repository to a new directory named hg/::
1385
1385
1386 hg clone http://selenic.com/hg
1386 hg clone http://selenic.com/hg
1387
1387
1388 - create a lightweight local clone::
1388 - create a lightweight local clone::
1389
1389
1390 hg clone project/ project-feature/
1390 hg clone project/ project-feature/
1391
1391
1392 - clone from an absolute path on an ssh server (note double-slash)::
1392 - clone from an absolute path on an ssh server (note double-slash)::
1393
1393
1394 hg clone ssh://user@server//home/projects/alpha/
1394 hg clone ssh://user@server//home/projects/alpha/
1395
1395
1396 - do a high-speed clone over a LAN while checking out a
1396 - do a high-speed clone over a LAN while checking out a
1397 specified version::
1397 specified version::
1398
1398
1399 hg clone --uncompressed http://server/repo -u 1.5
1399 hg clone --uncompressed http://server/repo -u 1.5
1400
1400
1401 - create a repository without changesets after a particular revision::
1401 - create a repository without changesets after a particular revision::
1402
1402
1403 hg clone -r 04e544 experimental/ good/
1403 hg clone -r 04e544 experimental/ good/
1404
1404
1405 - clone (and track) a particular named branch::
1405 - clone (and track) a particular named branch::
1406
1406
1407 hg clone http://selenic.com/hg#stable
1407 hg clone http://selenic.com/hg#stable
1408
1408
1409 See :hg:`help urls` for details on specifying URLs.
1409 See :hg:`help urls` for details on specifying URLs.
1410
1410
1411 Returns 0 on success.
1411 Returns 0 on success.
1412 """
1412 """
1413 if opts.get('noupdate') and opts.get('updaterev'):
1413 if opts.get('noupdate') and opts.get('updaterev'):
1414 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1414 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1415
1415
1416 r = hg.clone(ui, opts, source, dest,
1416 r = hg.clone(ui, opts, source, dest,
1417 pull=opts.get('pull'),
1417 pull=opts.get('pull'),
1418 stream=opts.get('uncompressed'),
1418 stream=opts.get('uncompressed'),
1419 rev=opts.get('rev'),
1419 rev=opts.get('rev'),
1420 update=opts.get('updaterev') or not opts.get('noupdate'),
1420 update=opts.get('updaterev') or not opts.get('noupdate'),
1421 branch=opts.get('branch'))
1421 branch=opts.get('branch'))
1422
1422
1423 return r is None
1423 return r is None
1424
1424
1425 @command('^commit|ci',
1425 @command('^commit|ci',
1426 [('A', 'addremove', None,
1426 [('A', 'addremove', None,
1427 _('mark new/missing files as added/removed before committing')),
1427 _('mark new/missing files as added/removed before committing')),
1428 ('', 'close-branch', None,
1428 ('', 'close-branch', None,
1429 _('mark a branch head as closed')),
1429 _('mark a branch head as closed')),
1430 ('', 'amend', None, _('amend the parent of the working directory')),
1430 ('', 'amend', None, _('amend the parent of the working directory')),
1431 ('s', 'secret', None, _('use the secret phase for committing')),
1431 ('s', 'secret', None, _('use the secret phase for committing')),
1432 ('e', 'edit', None, _('invoke editor on commit messages')),
1432 ('e', 'edit', None, _('invoke editor on commit messages')),
1433 ('i', 'interactive', None, _('use interactive mode')),
1433 ('i', 'interactive', None, _('use interactive mode')),
1434 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1434 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1435 _('[OPTION]... [FILE]...'),
1435 _('[OPTION]... [FILE]...'),
1436 inferrepo=True)
1436 inferrepo=True)
1437 def commit(ui, repo, *pats, **opts):
1437 def commit(ui, repo, *pats, **opts):
1438 """commit the specified files or all outstanding changes
1438 """commit the specified files or all outstanding changes
1439
1439
1440 Commit changes to the given files into the repository. Unlike a
1440 Commit changes to the given files into the repository. Unlike a
1441 centralized SCM, this operation is a local operation. See
1441 centralized SCM, this operation is a local operation. See
1442 :hg:`push` for a way to actively distribute your changes.
1442 :hg:`push` for a way to actively distribute your changes.
1443
1443
1444 If a list of files is omitted, all changes reported by :hg:`status`
1444 If a list of files is omitted, all changes reported by :hg:`status`
1445 will be committed.
1445 will be committed.
1446
1446
1447 If you are committing the result of a merge, do not provide any
1447 If you are committing the result of a merge, do not provide any
1448 filenames or -I/-X filters.
1448 filenames or -I/-X filters.
1449
1449
1450 If no commit message is specified, Mercurial starts your
1450 If no commit message is specified, Mercurial starts your
1451 configured editor where you can enter a message. In case your
1451 configured editor where you can enter a message. In case your
1452 commit fails, you will find a backup of your message in
1452 commit fails, you will find a backup of your message in
1453 ``.hg/last-message.txt``.
1453 ``.hg/last-message.txt``.
1454
1454
1455 The --close-branch flag can be used to mark the current branch
1455 The --close-branch flag can be used to mark the current branch
1456 head closed. When all heads of a branch are closed, the branch
1456 head closed. When all heads of a branch are closed, the branch
1457 will be considered closed and no longer listed.
1457 will be considered closed and no longer listed.
1458
1458
1459 The --amend flag can be used to amend the parent of the
1459 The --amend flag can be used to amend the parent of the
1460 working directory with a new commit that contains the changes
1460 working directory with a new commit that contains the changes
1461 in the parent in addition to those currently reported by :hg:`status`,
1461 in the parent in addition to those currently reported by :hg:`status`,
1462 if there are any. The old commit is stored in a backup bundle in
1462 if there are any. The old commit is stored in a backup bundle in
1463 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1463 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1464 on how to restore it).
1464 on how to restore it).
1465
1465
1466 Message, user and date are taken from the amended commit unless
1466 Message, user and date are taken from the amended commit unless
1467 specified. When a message isn't specified on the command line,
1467 specified. When a message isn't specified on the command line,
1468 the editor will open with the message of the amended commit.
1468 the editor will open with the message of the amended commit.
1469
1469
1470 It is not possible to amend public changesets (see :hg:`help phases`)
1470 It is not possible to amend public changesets (see :hg:`help phases`)
1471 or changesets that have children.
1471 or changesets that have children.
1472
1472
1473 See :hg:`help dates` for a list of formats valid for -d/--date.
1473 See :hg:`help dates` for a list of formats valid for -d/--date.
1474
1474
1475 Returns 0 on success, 1 if nothing changed.
1475 Returns 0 on success, 1 if nothing changed.
1476 """
1476 """
1477 if opts.get('interactive'):
1477 if opts.get('interactive'):
1478 opts.pop('interactive')
1478 opts.pop('interactive')
1479 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1479 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1480 cmdutil.recordfilter, *pats, **opts)
1480 cmdutil.recordfilter, *pats, **opts)
1481 return
1481 return
1482
1482
1483 if opts.get('subrepos'):
1483 if opts.get('subrepos'):
1484 if opts.get('amend'):
1484 if opts.get('amend'):
1485 raise util.Abort(_('cannot amend with --subrepos'))
1485 raise util.Abort(_('cannot amend with --subrepos'))
1486 # Let --subrepos on the command line override config setting.
1486 # Let --subrepos on the command line override config setting.
1487 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1487 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1488
1488
1489 cmdutil.checkunfinished(repo, commit=True)
1489 cmdutil.checkunfinished(repo, commit=True)
1490
1490
1491 branch = repo[None].branch()
1491 branch = repo[None].branch()
1492 bheads = repo.branchheads(branch)
1492 bheads = repo.branchheads(branch)
1493
1493
1494 extra = {}
1494 extra = {}
1495 if opts.get('close_branch'):
1495 if opts.get('close_branch'):
1496 extra['close'] = 1
1496 extra['close'] = 1
1497
1497
1498 if not bheads:
1498 if not bheads:
1499 raise util.Abort(_('can only close branch heads'))
1499 raise util.Abort(_('can only close branch heads'))
1500 elif opts.get('amend'):
1500 elif opts.get('amend'):
1501 if repo.parents()[0].p1().branch() != branch and \
1501 if repo.parents()[0].p1().branch() != branch and \
1502 repo.parents()[0].p2().branch() != branch:
1502 repo.parents()[0].p2().branch() != branch:
1503 raise util.Abort(_('can only close branch heads'))
1503 raise util.Abort(_('can only close branch heads'))
1504
1504
1505 if opts.get('amend'):
1505 if opts.get('amend'):
1506 if ui.configbool('ui', 'commitsubrepos'):
1506 if ui.configbool('ui', 'commitsubrepos'):
1507 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1507 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1508
1508
1509 old = repo['.']
1509 old = repo['.']
1510 if not old.mutable():
1510 if not old.mutable():
1511 raise util.Abort(_('cannot amend public changesets'))
1511 raise util.Abort(_('cannot amend public changesets'))
1512 if len(repo[None].parents()) > 1:
1512 if len(repo[None].parents()) > 1:
1513 raise util.Abort(_('cannot amend while merging'))
1513 raise util.Abort(_('cannot amend while merging'))
1514 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1514 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1515 if not allowunstable and old.children():
1515 if not allowunstable and old.children():
1516 raise util.Abort(_('cannot amend changeset with children'))
1516 raise util.Abort(_('cannot amend changeset with children'))
1517
1517
1518 # commitfunc is used only for temporary amend commit by cmdutil.amend
1518 # commitfunc is used only for temporary amend commit by cmdutil.amend
1519 def commitfunc(ui, repo, message, match, opts):
1519 def commitfunc(ui, repo, message, match, opts):
1520 return repo.commit(message,
1520 return repo.commit(message,
1521 opts.get('user') or old.user(),
1521 opts.get('user') or old.user(),
1522 opts.get('date') or old.date(),
1522 opts.get('date') or old.date(),
1523 match,
1523 match,
1524 extra=extra)
1524 extra=extra)
1525
1525
1526 active = repo._activebookmark
1526 active = repo._activebookmark
1527 marks = old.bookmarks()
1527 marks = old.bookmarks()
1528 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1528 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1529 if node == old.node():
1529 if node == old.node():
1530 ui.status(_("nothing changed\n"))
1530 ui.status(_("nothing changed\n"))
1531 return 1
1531 return 1
1532 elif marks:
1532 elif marks:
1533 ui.debug('moving bookmarks %r from %s to %s\n' %
1533 ui.debug('moving bookmarks %r from %s to %s\n' %
1534 (marks, old.hex(), hex(node)))
1534 (marks, old.hex(), hex(node)))
1535 newmarks = repo._bookmarks
1535 newmarks = repo._bookmarks
1536 for bm in marks:
1536 for bm in marks:
1537 newmarks[bm] = node
1537 newmarks[bm] = node
1538 if bm == active:
1538 if bm == active:
1539 bookmarks.activate(repo, bm)
1539 bookmarks.activate(repo, bm)
1540 newmarks.write()
1540 newmarks.write()
1541 else:
1541 else:
1542 def commitfunc(ui, repo, message, match, opts):
1542 def commitfunc(ui, repo, message, match, opts):
1543 backup = ui.backupconfig('phases', 'new-commit')
1543 backup = ui.backupconfig('phases', 'new-commit')
1544 baseui = repo.baseui
1544 baseui = repo.baseui
1545 basebackup = baseui.backupconfig('phases', 'new-commit')
1545 basebackup = baseui.backupconfig('phases', 'new-commit')
1546 try:
1546 try:
1547 if opts.get('secret'):
1547 if opts.get('secret'):
1548 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1548 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1549 # Propagate to subrepos
1549 # Propagate to subrepos
1550 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1550 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1551
1551
1552 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1552 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1553 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1553 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1554 return repo.commit(message, opts.get('user'), opts.get('date'),
1554 return repo.commit(message, opts.get('user'), opts.get('date'),
1555 match,
1555 match,
1556 editor=editor,
1556 editor=editor,
1557 extra=extra)
1557 extra=extra)
1558 finally:
1558 finally:
1559 ui.restoreconfig(backup)
1559 ui.restoreconfig(backup)
1560 repo.baseui.restoreconfig(basebackup)
1560 repo.baseui.restoreconfig(basebackup)
1561
1561
1562
1562
1563 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1563 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1564
1564
1565 if not node:
1565 if not node:
1566 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1566 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1567 if stat[3]:
1567 if stat[3]:
1568 ui.status(_("nothing changed (%d missing files, see "
1568 ui.status(_("nothing changed (%d missing files, see "
1569 "'hg status')\n") % len(stat[3]))
1569 "'hg status')\n") % len(stat[3]))
1570 else:
1570 else:
1571 ui.status(_("nothing changed\n"))
1571 ui.status(_("nothing changed\n"))
1572 return 1
1572 return 1
1573
1573
1574 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1574 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1575
1575
1576 @command('config|showconfig|debugconfig',
1576 @command('config|showconfig|debugconfig',
1577 [('u', 'untrusted', None, _('show untrusted configuration options')),
1577 [('u', 'untrusted', None, _('show untrusted configuration options')),
1578 ('e', 'edit', None, _('edit user config')),
1578 ('e', 'edit', None, _('edit user config')),
1579 ('l', 'local', None, _('edit repository config')),
1579 ('l', 'local', None, _('edit repository config')),
1580 ('g', 'global', None, _('edit global config'))],
1580 ('g', 'global', None, _('edit global config'))],
1581 _('[-u] [NAME]...'),
1581 _('[-u] [NAME]...'),
1582 optionalrepo=True)
1582 optionalrepo=True)
1583 def config(ui, repo, *values, **opts):
1583 def config(ui, repo, *values, **opts):
1584 """show combined config settings from all hgrc files
1584 """show combined config settings from all hgrc files
1585
1585
1586 With no arguments, print names and values of all config items.
1586 With no arguments, print names and values of all config items.
1587
1587
1588 With one argument of the form section.name, print just the value
1588 With one argument of the form section.name, print just the value
1589 of that config item.
1589 of that config item.
1590
1590
1591 With multiple arguments, print names and values of all config
1591 With multiple arguments, print names and values of all config
1592 items with matching section names.
1592 items with matching section names.
1593
1593
1594 With --edit, start an editor on the user-level config file. With
1594 With --edit, start an editor on the user-level config file. With
1595 --global, edit the system-wide config file. With --local, edit the
1595 --global, edit the system-wide config file. With --local, edit the
1596 repository-level config file.
1596 repository-level config file.
1597
1597
1598 With --debug, the source (filename and line number) is printed
1598 With --debug, the source (filename and line number) is printed
1599 for each config item.
1599 for each config item.
1600
1600
1601 See :hg:`help config` for more information about config files.
1601 See :hg:`help config` for more information about config files.
1602
1602
1603 Returns 0 on success, 1 if NAME does not exist.
1603 Returns 0 on success, 1 if NAME does not exist.
1604
1604
1605 """
1605 """
1606
1606
1607 if opts.get('edit') or opts.get('local') or opts.get('global'):
1607 if opts.get('edit') or opts.get('local') or opts.get('global'):
1608 if opts.get('local') and opts.get('global'):
1608 if opts.get('local') and opts.get('global'):
1609 raise util.Abort(_("can't use --local and --global together"))
1609 raise util.Abort(_("can't use --local and --global together"))
1610
1610
1611 if opts.get('local'):
1611 if opts.get('local'):
1612 if not repo:
1612 if not repo:
1613 raise util.Abort(_("can't use --local outside a repository"))
1613 raise util.Abort(_("can't use --local outside a repository"))
1614 paths = [repo.join('hgrc')]
1614 paths = [repo.join('hgrc')]
1615 elif opts.get('global'):
1615 elif opts.get('global'):
1616 paths = scmutil.systemrcpath()
1616 paths = scmutil.systemrcpath()
1617 else:
1617 else:
1618 paths = scmutil.userrcpath()
1618 paths = scmutil.userrcpath()
1619
1619
1620 for f in paths:
1620 for f in paths:
1621 if os.path.exists(f):
1621 if os.path.exists(f):
1622 break
1622 break
1623 else:
1623 else:
1624 if opts.get('global'):
1624 if opts.get('global'):
1625 samplehgrc = uimod.samplehgrcs['global']
1625 samplehgrc = uimod.samplehgrcs['global']
1626 elif opts.get('local'):
1626 elif opts.get('local'):
1627 samplehgrc = uimod.samplehgrcs['local']
1627 samplehgrc = uimod.samplehgrcs['local']
1628 else:
1628 else:
1629 samplehgrc = uimod.samplehgrcs['user']
1629 samplehgrc = uimod.samplehgrcs['user']
1630
1630
1631 f = paths[0]
1631 f = paths[0]
1632 fp = open(f, "w")
1632 fp = open(f, "w")
1633 fp.write(samplehgrc)
1633 fp.write(samplehgrc)
1634 fp.close()
1634 fp.close()
1635
1635
1636 editor = ui.geteditor()
1636 editor = ui.geteditor()
1637 ui.system("%s \"%s\"" % (editor, f),
1637 ui.system("%s \"%s\"" % (editor, f),
1638 onerr=util.Abort, errprefix=_("edit failed"))
1638 onerr=util.Abort, errprefix=_("edit failed"))
1639 return
1639 return
1640
1640
1641 for f in scmutil.rcpath():
1641 for f in scmutil.rcpath():
1642 ui.debug('read config from: %s\n' % f)
1642 ui.debug('read config from: %s\n' % f)
1643 untrusted = bool(opts.get('untrusted'))
1643 untrusted = bool(opts.get('untrusted'))
1644 if values:
1644 if values:
1645 sections = [v for v in values if '.' not in v]
1645 sections = [v for v in values if '.' not in v]
1646 items = [v for v in values if '.' in v]
1646 items = [v for v in values if '.' in v]
1647 if len(items) > 1 or items and sections:
1647 if len(items) > 1 or items and sections:
1648 raise util.Abort(_('only one config item permitted'))
1648 raise util.Abort(_('only one config item permitted'))
1649 matched = False
1649 matched = False
1650 for section, name, value in ui.walkconfig(untrusted=untrusted):
1650 for section, name, value in ui.walkconfig(untrusted=untrusted):
1651 value = str(value).replace('\n', '\\n')
1651 value = str(value).replace('\n', '\\n')
1652 sectname = section + '.' + name
1652 sectname = section + '.' + name
1653 if values:
1653 if values:
1654 for v in values:
1654 for v in values:
1655 if v == section:
1655 if v == section:
1656 ui.debug('%s: ' %
1656 ui.debug('%s: ' %
1657 ui.configsource(section, name, untrusted))
1657 ui.configsource(section, name, untrusted))
1658 ui.write('%s=%s\n' % (sectname, value))
1658 ui.write('%s=%s\n' % (sectname, value))
1659 matched = True
1659 matched = True
1660 elif v == sectname:
1660 elif v == sectname:
1661 ui.debug('%s: ' %
1661 ui.debug('%s: ' %
1662 ui.configsource(section, name, untrusted))
1662 ui.configsource(section, name, untrusted))
1663 ui.write(value, '\n')
1663 ui.write(value, '\n')
1664 matched = True
1664 matched = True
1665 else:
1665 else:
1666 ui.debug('%s: ' %
1666 ui.debug('%s: ' %
1667 ui.configsource(section, name, untrusted))
1667 ui.configsource(section, name, untrusted))
1668 ui.write('%s=%s\n' % (sectname, value))
1668 ui.write('%s=%s\n' % (sectname, value))
1669 matched = True
1669 matched = True
1670 if matched:
1670 if matched:
1671 return 0
1671 return 0
1672 return 1
1672 return 1
1673
1673
1674 @command('copy|cp',
1674 @command('copy|cp',
1675 [('A', 'after', None, _('record a copy that has already occurred')),
1675 [('A', 'after', None, _('record a copy that has already occurred')),
1676 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1676 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1677 ] + walkopts + dryrunopts,
1677 ] + walkopts + dryrunopts,
1678 _('[OPTION]... [SOURCE]... DEST'))
1678 _('[OPTION]... [SOURCE]... DEST'))
1679 def copy(ui, repo, *pats, **opts):
1679 def copy(ui, repo, *pats, **opts):
1680 """mark files as copied for the next commit
1680 """mark files as copied for the next commit
1681
1681
1682 Mark dest as having copies of source files. If dest is a
1682 Mark dest as having copies of source files. If dest is a
1683 directory, copies are put in that directory. If dest is a file,
1683 directory, copies are put in that directory. If dest is a file,
1684 the source must be a single file.
1684 the source must be a single file.
1685
1685
1686 By default, this command copies the contents of files as they
1686 By default, this command copies the contents of files as they
1687 exist in the working directory. If invoked with -A/--after, the
1687 exist in the working directory. If invoked with -A/--after, the
1688 operation is recorded, but no copying is performed.
1688 operation is recorded, but no copying is performed.
1689
1689
1690 This command takes effect with the next commit. To undo a copy
1690 This command takes effect with the next commit. To undo a copy
1691 before that, see :hg:`revert`.
1691 before that, see :hg:`revert`.
1692
1692
1693 Returns 0 on success, 1 if errors are encountered.
1693 Returns 0 on success, 1 if errors are encountered.
1694 """
1694 """
1695 wlock = repo.wlock(False)
1695 wlock = repo.wlock(False)
1696 try:
1696 try:
1697 return cmdutil.copy(ui, repo, pats, opts)
1697 return cmdutil.copy(ui, repo, pats, opts)
1698 finally:
1698 finally:
1699 wlock.release()
1699 wlock.release()
1700
1700
1701 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1701 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1702 def debugancestor(ui, repo, *args):
1702 def debugancestor(ui, repo, *args):
1703 """find the ancestor revision of two revisions in a given index"""
1703 """find the ancestor revision of two revisions in a given index"""
1704 if len(args) == 3:
1704 if len(args) == 3:
1705 index, rev1, rev2 = args
1705 index, rev1, rev2 = args
1706 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1706 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1707 lookup = r.lookup
1707 lookup = r.lookup
1708 elif len(args) == 2:
1708 elif len(args) == 2:
1709 if not repo:
1709 if not repo:
1710 raise util.Abort(_("there is no Mercurial repository here "
1710 raise util.Abort(_("there is no Mercurial repository here "
1711 "(.hg not found)"))
1711 "(.hg not found)"))
1712 rev1, rev2 = args
1712 rev1, rev2 = args
1713 r = repo.changelog
1713 r = repo.changelog
1714 lookup = repo.lookup
1714 lookup = repo.lookup
1715 else:
1715 else:
1716 raise util.Abort(_('either two or three arguments required'))
1716 raise util.Abort(_('either two or three arguments required'))
1717 a = r.ancestor(lookup(rev1), lookup(rev2))
1717 a = r.ancestor(lookup(rev1), lookup(rev2))
1718 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1718 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1719
1719
1720 @command('debugbuilddag',
1720 @command('debugbuilddag',
1721 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1721 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1722 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1722 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1723 ('n', 'new-file', None, _('add new file at each rev'))],
1723 ('n', 'new-file', None, _('add new file at each rev'))],
1724 _('[OPTION]... [TEXT]'))
1724 _('[OPTION]... [TEXT]'))
1725 def debugbuilddag(ui, repo, text=None,
1725 def debugbuilddag(ui, repo, text=None,
1726 mergeable_file=False,
1726 mergeable_file=False,
1727 overwritten_file=False,
1727 overwritten_file=False,
1728 new_file=False):
1728 new_file=False):
1729 """builds a repo with a given DAG from scratch in the current empty repo
1729 """builds a repo with a given DAG from scratch in the current empty repo
1730
1730
1731 The description of the DAG is read from stdin if not given on the
1731 The description of the DAG is read from stdin if not given on the
1732 command line.
1732 command line.
1733
1733
1734 Elements:
1734 Elements:
1735
1735
1736 - "+n" is a linear run of n nodes based on the current default parent
1736 - "+n" is a linear run of n nodes based on the current default parent
1737 - "." is a single node based on the current default parent
1737 - "." is a single node based on the current default parent
1738 - "$" resets the default parent to null (implied at the start);
1738 - "$" resets the default parent to null (implied at the start);
1739 otherwise the default parent is always the last node created
1739 otherwise the default parent is always the last node created
1740 - "<p" sets the default parent to the backref p
1740 - "<p" sets the default parent to the backref p
1741 - "*p" is a fork at parent p, which is a backref
1741 - "*p" is a fork at parent p, which is a backref
1742 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1742 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1743 - "/p2" is a merge of the preceding node and p2
1743 - "/p2" is a merge of the preceding node and p2
1744 - ":tag" defines a local tag for the preceding node
1744 - ":tag" defines a local tag for the preceding node
1745 - "@branch" sets the named branch for subsequent nodes
1745 - "@branch" sets the named branch for subsequent nodes
1746 - "#...\\n" is a comment up to the end of the line
1746 - "#...\\n" is a comment up to the end of the line
1747
1747
1748 Whitespace between the above elements is ignored.
1748 Whitespace between the above elements is ignored.
1749
1749
1750 A backref is either
1750 A backref is either
1751
1751
1752 - a number n, which references the node curr-n, where curr is the current
1752 - a number n, which references the node curr-n, where curr is the current
1753 node, or
1753 node, or
1754 - the name of a local tag you placed earlier using ":tag", or
1754 - the name of a local tag you placed earlier using ":tag", or
1755 - empty to denote the default parent.
1755 - empty to denote the default parent.
1756
1756
1757 All string valued-elements are either strictly alphanumeric, or must
1757 All string valued-elements are either strictly alphanumeric, or must
1758 be enclosed in double quotes ("..."), with "\\" as escape character.
1758 be enclosed in double quotes ("..."), with "\\" as escape character.
1759 """
1759 """
1760
1760
1761 if text is None:
1761 if text is None:
1762 ui.status(_("reading DAG from stdin\n"))
1762 ui.status(_("reading DAG from stdin\n"))
1763 text = ui.fin.read()
1763 text = ui.fin.read()
1764
1764
1765 cl = repo.changelog
1765 cl = repo.changelog
1766 if len(cl) > 0:
1766 if len(cl) > 0:
1767 raise util.Abort(_('repository is not empty'))
1767 raise util.Abort(_('repository is not empty'))
1768
1768
1769 # determine number of revs in DAG
1769 # determine number of revs in DAG
1770 total = 0
1770 total = 0
1771 for type, data in dagparser.parsedag(text):
1771 for type, data in dagparser.parsedag(text):
1772 if type == 'n':
1772 if type == 'n':
1773 total += 1
1773 total += 1
1774
1774
1775 if mergeable_file:
1775 if mergeable_file:
1776 linesperrev = 2
1776 linesperrev = 2
1777 # make a file with k lines per rev
1777 # make a file with k lines per rev
1778 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1778 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1779 initialmergedlines.append("")
1779 initialmergedlines.append("")
1780
1780
1781 tags = []
1781 tags = []
1782
1782
1783 lock = tr = None
1783 lock = tr = None
1784 try:
1784 try:
1785 lock = repo.lock()
1785 lock = repo.lock()
1786 tr = repo.transaction("builddag")
1786 tr = repo.transaction("builddag")
1787
1787
1788 at = -1
1788 at = -1
1789 atbranch = 'default'
1789 atbranch = 'default'
1790 nodeids = []
1790 nodeids = []
1791 id = 0
1791 id = 0
1792 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1792 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1793 for type, data in dagparser.parsedag(text):
1793 for type, data in dagparser.parsedag(text):
1794 if type == 'n':
1794 if type == 'n':
1795 ui.note(('node %s\n' % str(data)))
1795 ui.note(('node %s\n' % str(data)))
1796 id, ps = data
1796 id, ps = data
1797
1797
1798 files = []
1798 files = []
1799 fctxs = {}
1799 fctxs = {}
1800
1800
1801 p2 = None
1801 p2 = None
1802 if mergeable_file:
1802 if mergeable_file:
1803 fn = "mf"
1803 fn = "mf"
1804 p1 = repo[ps[0]]
1804 p1 = repo[ps[0]]
1805 if len(ps) > 1:
1805 if len(ps) > 1:
1806 p2 = repo[ps[1]]
1806 p2 = repo[ps[1]]
1807 pa = p1.ancestor(p2)
1807 pa = p1.ancestor(p2)
1808 base, local, other = [x[fn].data() for x in (pa, p1,
1808 base, local, other = [x[fn].data() for x in (pa, p1,
1809 p2)]
1809 p2)]
1810 m3 = simplemerge.Merge3Text(base, local, other)
1810 m3 = simplemerge.Merge3Text(base, local, other)
1811 ml = [l.strip() for l in m3.merge_lines()]
1811 ml = [l.strip() for l in m3.merge_lines()]
1812 ml.append("")
1812 ml.append("")
1813 elif at > 0:
1813 elif at > 0:
1814 ml = p1[fn].data().split("\n")
1814 ml = p1[fn].data().split("\n")
1815 else:
1815 else:
1816 ml = initialmergedlines
1816 ml = initialmergedlines
1817 ml[id * linesperrev] += " r%i" % id
1817 ml[id * linesperrev] += " r%i" % id
1818 mergedtext = "\n".join(ml)
1818 mergedtext = "\n".join(ml)
1819 files.append(fn)
1819 files.append(fn)
1820 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1820 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1821
1821
1822 if overwritten_file:
1822 if overwritten_file:
1823 fn = "of"
1823 fn = "of"
1824 files.append(fn)
1824 files.append(fn)
1825 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1825 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1826
1826
1827 if new_file:
1827 if new_file:
1828 fn = "nf%i" % id
1828 fn = "nf%i" % id
1829 files.append(fn)
1829 files.append(fn)
1830 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1830 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1831 if len(ps) > 1:
1831 if len(ps) > 1:
1832 if not p2:
1832 if not p2:
1833 p2 = repo[ps[1]]
1833 p2 = repo[ps[1]]
1834 for fn in p2:
1834 for fn in p2:
1835 if fn.startswith("nf"):
1835 if fn.startswith("nf"):
1836 files.append(fn)
1836 files.append(fn)
1837 fctxs[fn] = p2[fn]
1837 fctxs[fn] = p2[fn]
1838
1838
1839 def fctxfn(repo, cx, path):
1839 def fctxfn(repo, cx, path):
1840 return fctxs.get(path)
1840 return fctxs.get(path)
1841
1841
1842 if len(ps) == 0 or ps[0] < 0:
1842 if len(ps) == 0 or ps[0] < 0:
1843 pars = [None, None]
1843 pars = [None, None]
1844 elif len(ps) == 1:
1844 elif len(ps) == 1:
1845 pars = [nodeids[ps[0]], None]
1845 pars = [nodeids[ps[0]], None]
1846 else:
1846 else:
1847 pars = [nodeids[p] for p in ps]
1847 pars = [nodeids[p] for p in ps]
1848 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1848 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1849 date=(id, 0),
1849 date=(id, 0),
1850 user="debugbuilddag",
1850 user="debugbuilddag",
1851 extra={'branch': atbranch})
1851 extra={'branch': atbranch})
1852 nodeid = repo.commitctx(cx)
1852 nodeid = repo.commitctx(cx)
1853 nodeids.append(nodeid)
1853 nodeids.append(nodeid)
1854 at = id
1854 at = id
1855 elif type == 'l':
1855 elif type == 'l':
1856 id, name = data
1856 id, name = data
1857 ui.note(('tag %s\n' % name))
1857 ui.note(('tag %s\n' % name))
1858 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1858 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1859 elif type == 'a':
1859 elif type == 'a':
1860 ui.note(('branch %s\n' % data))
1860 ui.note(('branch %s\n' % data))
1861 atbranch = data
1861 atbranch = data
1862 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1862 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1863 tr.close()
1863 tr.close()
1864
1864
1865 if tags:
1865 if tags:
1866 repo.vfs.write("localtags", "".join(tags))
1866 repo.vfs.write("localtags", "".join(tags))
1867 finally:
1867 finally:
1868 ui.progress(_('building'), None)
1868 ui.progress(_('building'), None)
1869 release(tr, lock)
1869 release(tr, lock)
1870
1870
1871 @command('debugbundle',
1871 @command('debugbundle',
1872 [('a', 'all', None, _('show all details'))],
1872 [('a', 'all', None, _('show all details'))],
1873 _('FILE'),
1873 _('FILE'),
1874 norepo=True)
1874 norepo=True)
1875 def debugbundle(ui, bundlepath, all=None, **opts):
1875 def debugbundle(ui, bundlepath, all=None, **opts):
1876 """lists the contents of a bundle"""
1876 """lists the contents of a bundle"""
1877 f = hg.openpath(ui, bundlepath)
1877 f = hg.openpath(ui, bundlepath)
1878 try:
1878 try:
1879 gen = exchange.readbundle(ui, f, bundlepath)
1879 gen = exchange.readbundle(ui, f, bundlepath)
1880 if isinstance(gen, bundle2.unbundle20):
1880 if isinstance(gen, bundle2.unbundle20):
1881 return _debugbundle2(ui, gen, all=all, **opts)
1881 return _debugbundle2(ui, gen, all=all, **opts)
1882 if all:
1882 if all:
1883 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1883 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1884
1884
1885 def showchunks(named):
1885 def showchunks(named):
1886 ui.write("\n%s\n" % named)
1886 ui.write("\n%s\n" % named)
1887 chain = None
1887 chain = None
1888 while True:
1888 while True:
1889 chunkdata = gen.deltachunk(chain)
1889 chunkdata = gen.deltachunk(chain)
1890 if not chunkdata:
1890 if not chunkdata:
1891 break
1891 break
1892 node = chunkdata['node']
1892 node = chunkdata['node']
1893 p1 = chunkdata['p1']
1893 p1 = chunkdata['p1']
1894 p2 = chunkdata['p2']
1894 p2 = chunkdata['p2']
1895 cs = chunkdata['cs']
1895 cs = chunkdata['cs']
1896 deltabase = chunkdata['deltabase']
1896 deltabase = chunkdata['deltabase']
1897 delta = chunkdata['delta']
1897 delta = chunkdata['delta']
1898 ui.write("%s %s %s %s %s %s\n" %
1898 ui.write("%s %s %s %s %s %s\n" %
1899 (hex(node), hex(p1), hex(p2),
1899 (hex(node), hex(p1), hex(p2),
1900 hex(cs), hex(deltabase), len(delta)))
1900 hex(cs), hex(deltabase), len(delta)))
1901 chain = node
1901 chain = node
1902
1902
1903 chunkdata = gen.changelogheader()
1903 chunkdata = gen.changelogheader()
1904 showchunks("changelog")
1904 showchunks("changelog")
1905 chunkdata = gen.manifestheader()
1905 chunkdata = gen.manifestheader()
1906 showchunks("manifest")
1906 showchunks("manifest")
1907 while True:
1907 while True:
1908 chunkdata = gen.filelogheader()
1908 chunkdata = gen.filelogheader()
1909 if not chunkdata:
1909 if not chunkdata:
1910 break
1910 break
1911 fname = chunkdata['filename']
1911 fname = chunkdata['filename']
1912 showchunks(fname)
1912 showchunks(fname)
1913 else:
1913 else:
1914 if isinstance(gen, bundle2.unbundle20):
1914 if isinstance(gen, bundle2.unbundle20):
1915 raise util.Abort(_('use debugbundle2 for this file'))
1915 raise util.Abort(_('use debugbundle2 for this file'))
1916 chunkdata = gen.changelogheader()
1916 chunkdata = gen.changelogheader()
1917 chain = None
1917 chain = None
1918 while True:
1918 while True:
1919 chunkdata = gen.deltachunk(chain)
1919 chunkdata = gen.deltachunk(chain)
1920 if not chunkdata:
1920 if not chunkdata:
1921 break
1921 break
1922 node = chunkdata['node']
1922 node = chunkdata['node']
1923 ui.write("%s\n" % hex(node))
1923 ui.write("%s\n" % hex(node))
1924 chain = node
1924 chain = node
1925 finally:
1925 finally:
1926 f.close()
1926 f.close()
1927
1927
1928 def _debugbundle2(ui, gen, **opts):
1928 def _debugbundle2(ui, gen, **opts):
1929 """lists the contents of a bundle2"""
1929 """lists the contents of a bundle2"""
1930 if not isinstance(gen, bundle2.unbundle20):
1930 if not isinstance(gen, bundle2.unbundle20):
1931 raise util.Abort(_('not a bundle2 file'))
1931 raise util.Abort(_('not a bundle2 file'))
1932 ui.write(('Stream params: %s\n' % repr(gen.params)))
1932 ui.write(('Stream params: %s\n' % repr(gen.params)))
1933 for part in gen.iterparts():
1933 for part in gen.iterparts():
1934 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1934 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1935 if part.type == 'changegroup':
1935 if part.type == 'changegroup':
1936 version = part.params.get('version', '01')
1936 version = part.params.get('version', '01')
1937 cg = changegroup.packermap[version][1](part, 'UN')
1937 cg = changegroup.packermap[version][1](part, 'UN')
1938 chunkdata = cg.changelogheader()
1938 chunkdata = cg.changelogheader()
1939 chain = None
1939 chain = None
1940 while True:
1940 while True:
1941 chunkdata = cg.deltachunk(chain)
1941 chunkdata = cg.deltachunk(chain)
1942 if not chunkdata:
1942 if not chunkdata:
1943 break
1943 break
1944 node = chunkdata['node']
1944 node = chunkdata['node']
1945 ui.write(" %s\n" % hex(node))
1945 ui.write(" %s\n" % hex(node))
1946 chain = node
1946 chain = node
1947
1947
1948 @command('debugcheckstate', [], '')
1948 @command('debugcheckstate', [], '')
1949 def debugcheckstate(ui, repo):
1949 def debugcheckstate(ui, repo):
1950 """validate the correctness of the current dirstate"""
1950 """validate the correctness of the current dirstate"""
1951 parent1, parent2 = repo.dirstate.parents()
1951 parent1, parent2 = repo.dirstate.parents()
1952 m1 = repo[parent1].manifest()
1952 m1 = repo[parent1].manifest()
1953 m2 = repo[parent2].manifest()
1953 m2 = repo[parent2].manifest()
1954 errors = 0
1954 errors = 0
1955 for f in repo.dirstate:
1955 for f in repo.dirstate:
1956 state = repo.dirstate[f]
1956 state = repo.dirstate[f]
1957 if state in "nr" and f not in m1:
1957 if state in "nr" and f not in m1:
1958 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1958 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1959 errors += 1
1959 errors += 1
1960 if state in "a" and f in m1:
1960 if state in "a" and f in m1:
1961 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1961 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1962 errors += 1
1962 errors += 1
1963 if state in "m" and f not in m1 and f not in m2:
1963 if state in "m" and f not in m1 and f not in m2:
1964 ui.warn(_("%s in state %s, but not in either manifest\n") %
1964 ui.warn(_("%s in state %s, but not in either manifest\n") %
1965 (f, state))
1965 (f, state))
1966 errors += 1
1966 errors += 1
1967 for f in m1:
1967 for f in m1:
1968 state = repo.dirstate[f]
1968 state = repo.dirstate[f]
1969 if state not in "nrm":
1969 if state not in "nrm":
1970 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1970 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1971 errors += 1
1971 errors += 1
1972 if errors:
1972 if errors:
1973 error = _(".hg/dirstate inconsistent with current parent's manifest")
1973 error = _(".hg/dirstate inconsistent with current parent's manifest")
1974 raise util.Abort(error)
1974 raise util.Abort(error)
1975
1975
1976 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1976 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1977 def debugcommands(ui, cmd='', *args):
1977 def debugcommands(ui, cmd='', *args):
1978 """list all available commands and options"""
1978 """list all available commands and options"""
1979 for cmd, vals in sorted(table.iteritems()):
1979 for cmd, vals in sorted(table.iteritems()):
1980 cmd = cmd.split('|')[0].strip('^')
1980 cmd = cmd.split('|')[0].strip('^')
1981 opts = ', '.join([i[1] for i in vals[1]])
1981 opts = ', '.join([i[1] for i in vals[1]])
1982 ui.write('%s: %s\n' % (cmd, opts))
1982 ui.write('%s: %s\n' % (cmd, opts))
1983
1983
1984 @command('debugcomplete',
1984 @command('debugcomplete',
1985 [('o', 'options', None, _('show the command options'))],
1985 [('o', 'options', None, _('show the command options'))],
1986 _('[-o] CMD'),
1986 _('[-o] CMD'),
1987 norepo=True)
1987 norepo=True)
1988 def debugcomplete(ui, cmd='', **opts):
1988 def debugcomplete(ui, cmd='', **opts):
1989 """returns the completion list associated with the given command"""
1989 """returns the completion list associated with the given command"""
1990
1990
1991 if opts.get('options'):
1991 if opts.get('options'):
1992 options = []
1992 options = []
1993 otables = [globalopts]
1993 otables = [globalopts]
1994 if cmd:
1994 if cmd:
1995 aliases, entry = cmdutil.findcmd(cmd, table, False)
1995 aliases, entry = cmdutil.findcmd(cmd, table, False)
1996 otables.append(entry[1])
1996 otables.append(entry[1])
1997 for t in otables:
1997 for t in otables:
1998 for o in t:
1998 for o in t:
1999 if "(DEPRECATED)" in o[3]:
1999 if "(DEPRECATED)" in o[3]:
2000 continue
2000 continue
2001 if o[0]:
2001 if o[0]:
2002 options.append('-%s' % o[0])
2002 options.append('-%s' % o[0])
2003 options.append('--%s' % o[1])
2003 options.append('--%s' % o[1])
2004 ui.write("%s\n" % "\n".join(options))
2004 ui.write("%s\n" % "\n".join(options))
2005 return
2005 return
2006
2006
2007 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2007 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2008 if ui.verbose:
2008 if ui.verbose:
2009 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2009 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2010 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2010 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2011
2011
2012 @command('debugdag',
2012 @command('debugdag',
2013 [('t', 'tags', None, _('use tags as labels')),
2013 [('t', 'tags', None, _('use tags as labels')),
2014 ('b', 'branches', None, _('annotate with branch names')),
2014 ('b', 'branches', None, _('annotate with branch names')),
2015 ('', 'dots', None, _('use dots for runs')),
2015 ('', 'dots', None, _('use dots for runs')),
2016 ('s', 'spaces', None, _('separate elements by spaces'))],
2016 ('s', 'spaces', None, _('separate elements by spaces'))],
2017 _('[OPTION]... [FILE [REV]...]'),
2017 _('[OPTION]... [FILE [REV]...]'),
2018 optionalrepo=True)
2018 optionalrepo=True)
2019 def debugdag(ui, repo, file_=None, *revs, **opts):
2019 def debugdag(ui, repo, file_=None, *revs, **opts):
2020 """format the changelog or an index DAG as a concise textual description
2020 """format the changelog or an index DAG as a concise textual description
2021
2021
2022 If you pass a revlog index, the revlog's DAG is emitted. If you list
2022 If you pass a revlog index, the revlog's DAG is emitted. If you list
2023 revision numbers, they get labeled in the output as rN.
2023 revision numbers, they get labeled in the output as rN.
2024
2024
2025 Otherwise, the changelog DAG of the current repo is emitted.
2025 Otherwise, the changelog DAG of the current repo is emitted.
2026 """
2026 """
2027 spaces = opts.get('spaces')
2027 spaces = opts.get('spaces')
2028 dots = opts.get('dots')
2028 dots = opts.get('dots')
2029 if file_:
2029 if file_:
2030 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2030 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2031 revs = set((int(r) for r in revs))
2031 revs = set((int(r) for r in revs))
2032 def events():
2032 def events():
2033 for r in rlog:
2033 for r in rlog:
2034 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2034 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2035 if p != -1))
2035 if p != -1))
2036 if r in revs:
2036 if r in revs:
2037 yield 'l', (r, "r%i" % r)
2037 yield 'l', (r, "r%i" % r)
2038 elif repo:
2038 elif repo:
2039 cl = repo.changelog
2039 cl = repo.changelog
2040 tags = opts.get('tags')
2040 tags = opts.get('tags')
2041 branches = opts.get('branches')
2041 branches = opts.get('branches')
2042 if tags:
2042 if tags:
2043 labels = {}
2043 labels = {}
2044 for l, n in repo.tags().items():
2044 for l, n in repo.tags().items():
2045 labels.setdefault(cl.rev(n), []).append(l)
2045 labels.setdefault(cl.rev(n), []).append(l)
2046 def events():
2046 def events():
2047 b = "default"
2047 b = "default"
2048 for r in cl:
2048 for r in cl:
2049 if branches:
2049 if branches:
2050 newb = cl.read(cl.node(r))[5]['branch']
2050 newb = cl.read(cl.node(r))[5]['branch']
2051 if newb != b:
2051 if newb != b:
2052 yield 'a', newb
2052 yield 'a', newb
2053 b = newb
2053 b = newb
2054 yield 'n', (r, list(p for p in cl.parentrevs(r)
2054 yield 'n', (r, list(p for p in cl.parentrevs(r)
2055 if p != -1))
2055 if p != -1))
2056 if tags:
2056 if tags:
2057 ls = labels.get(r)
2057 ls = labels.get(r)
2058 if ls:
2058 if ls:
2059 for l in ls:
2059 for l in ls:
2060 yield 'l', (r, l)
2060 yield 'l', (r, l)
2061 else:
2061 else:
2062 raise util.Abort(_('need repo for changelog dag'))
2062 raise util.Abort(_('need repo for changelog dag'))
2063
2063
2064 for line in dagparser.dagtextlines(events(),
2064 for line in dagparser.dagtextlines(events(),
2065 addspaces=spaces,
2065 addspaces=spaces,
2066 wraplabels=True,
2066 wraplabels=True,
2067 wrapannotations=True,
2067 wrapannotations=True,
2068 wrapnonlinear=dots,
2068 wrapnonlinear=dots,
2069 usedots=dots,
2069 usedots=dots,
2070 maxlinewidth=70):
2070 maxlinewidth=70):
2071 ui.write(line)
2071 ui.write(line)
2072 ui.write("\n")
2072 ui.write("\n")
2073
2073
2074 @command('debugdata',
2074 @command('debugdata',
2075 [('c', 'changelog', False, _('open changelog')),
2075 [('c', 'changelog', False, _('open changelog')),
2076 ('m', 'manifest', False, _('open manifest')),
2076 ('m', 'manifest', False, _('open manifest')),
2077 ('', 'dir', False, _('open directory manifest'))],
2077 ('', 'dir', False, _('open directory manifest'))],
2078 _('-c|-m|FILE REV'))
2078 _('-c|-m|FILE REV'))
2079 def debugdata(ui, repo, file_, rev=None, **opts):
2079 def debugdata(ui, repo, file_, rev=None, **opts):
2080 """dump the contents of a data file revision"""
2080 """dump the contents of a data file revision"""
2081 if opts.get('changelog') or opts.get('manifest'):
2081 if opts.get('changelog') or opts.get('manifest'):
2082 file_, rev = None, file_
2082 file_, rev = None, file_
2083 elif rev is None:
2083 elif rev is None:
2084 raise error.CommandError('debugdata', _('invalid arguments'))
2084 raise error.CommandError('debugdata', _('invalid arguments'))
2085 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2085 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2086 try:
2086 try:
2087 ui.write(r.revision(r.lookup(rev)))
2087 ui.write(r.revision(r.lookup(rev)))
2088 except KeyError:
2088 except KeyError:
2089 raise util.Abort(_('invalid revision identifier %s') % rev)
2089 raise util.Abort(_('invalid revision identifier %s') % rev)
2090
2090
2091 @command('debugdate',
2091 @command('debugdate',
2092 [('e', 'extended', None, _('try extended date formats'))],
2092 [('e', 'extended', None, _('try extended date formats'))],
2093 _('[-e] DATE [RANGE]'),
2093 _('[-e] DATE [RANGE]'),
2094 norepo=True, optionalrepo=True)
2094 norepo=True, optionalrepo=True)
2095 def debugdate(ui, date, range=None, **opts):
2095 def debugdate(ui, date, range=None, **opts):
2096 """parse and display a date"""
2096 """parse and display a date"""
2097 if opts["extended"]:
2097 if opts["extended"]:
2098 d = util.parsedate(date, util.extendeddateformats)
2098 d = util.parsedate(date, util.extendeddateformats)
2099 else:
2099 else:
2100 d = util.parsedate(date)
2100 d = util.parsedate(date)
2101 ui.write(("internal: %s %s\n") % d)
2101 ui.write(("internal: %s %s\n") % d)
2102 ui.write(("standard: %s\n") % util.datestr(d))
2102 ui.write(("standard: %s\n") % util.datestr(d))
2103 if range:
2103 if range:
2104 m = util.matchdate(range)
2104 m = util.matchdate(range)
2105 ui.write(("match: %s\n") % m(d[0]))
2105 ui.write(("match: %s\n") % m(d[0]))
2106
2106
2107 @command('debugdiscovery',
2107 @command('debugdiscovery',
2108 [('', 'old', None, _('use old-style discovery')),
2108 [('', 'old', None, _('use old-style discovery')),
2109 ('', 'nonheads', None,
2109 ('', 'nonheads', None,
2110 _('use old-style discovery with non-heads included')),
2110 _('use old-style discovery with non-heads included')),
2111 ] + remoteopts,
2111 ] + remoteopts,
2112 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2112 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2113 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2113 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2114 """runs the changeset discovery protocol in isolation"""
2114 """runs the changeset discovery protocol in isolation"""
2115 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2115 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2116 opts.get('branch'))
2116 opts.get('branch'))
2117 remote = hg.peer(repo, opts, remoteurl)
2117 remote = hg.peer(repo, opts, remoteurl)
2118 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2118 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2119
2119
2120 # make sure tests are repeatable
2120 # make sure tests are repeatable
2121 random.seed(12323)
2121 random.seed(12323)
2122
2122
2123 def doit(localheads, remoteheads, remote=remote):
2123 def doit(localheads, remoteheads, remote=remote):
2124 if opts.get('old'):
2124 if opts.get('old'):
2125 if localheads:
2125 if localheads:
2126 raise util.Abort('cannot use localheads with old style '
2126 raise util.Abort('cannot use localheads with old style '
2127 'discovery')
2127 'discovery')
2128 if not util.safehasattr(remote, 'branches'):
2128 if not util.safehasattr(remote, 'branches'):
2129 # enable in-client legacy support
2129 # enable in-client legacy support
2130 remote = localrepo.locallegacypeer(remote.local())
2130 remote = localrepo.locallegacypeer(remote.local())
2131 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2131 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2132 force=True)
2132 force=True)
2133 common = set(common)
2133 common = set(common)
2134 if not opts.get('nonheads'):
2134 if not opts.get('nonheads'):
2135 ui.write(("unpruned common: %s\n") %
2135 ui.write(("unpruned common: %s\n") %
2136 " ".join(sorted(short(n) for n in common)))
2136 " ".join(sorted(short(n) for n in common)))
2137 dag = dagutil.revlogdag(repo.changelog)
2137 dag = dagutil.revlogdag(repo.changelog)
2138 all = dag.ancestorset(dag.internalizeall(common))
2138 all = dag.ancestorset(dag.internalizeall(common))
2139 common = dag.externalizeall(dag.headsetofconnecteds(all))
2139 common = dag.externalizeall(dag.headsetofconnecteds(all))
2140 else:
2140 else:
2141 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2141 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2142 common = set(common)
2142 common = set(common)
2143 rheads = set(hds)
2143 rheads = set(hds)
2144 lheads = set(repo.heads())
2144 lheads = set(repo.heads())
2145 ui.write(("common heads: %s\n") %
2145 ui.write(("common heads: %s\n") %
2146 " ".join(sorted(short(n) for n in common)))
2146 " ".join(sorted(short(n) for n in common)))
2147 if lheads <= common:
2147 if lheads <= common:
2148 ui.write(("local is subset\n"))
2148 ui.write(("local is subset\n"))
2149 elif rheads <= common:
2149 elif rheads <= common:
2150 ui.write(("remote is subset\n"))
2150 ui.write(("remote is subset\n"))
2151
2151
2152 serverlogs = opts.get('serverlog')
2152 serverlogs = opts.get('serverlog')
2153 if serverlogs:
2153 if serverlogs:
2154 for filename in serverlogs:
2154 for filename in serverlogs:
2155 logfile = open(filename, 'r')
2155 logfile = open(filename, 'r')
2156 try:
2156 try:
2157 line = logfile.readline()
2157 line = logfile.readline()
2158 while line:
2158 while line:
2159 parts = line.strip().split(';')
2159 parts = line.strip().split(';')
2160 op = parts[1]
2160 op = parts[1]
2161 if op == 'cg':
2161 if op == 'cg':
2162 pass
2162 pass
2163 elif op == 'cgss':
2163 elif op == 'cgss':
2164 doit(parts[2].split(' '), parts[3].split(' '))
2164 doit(parts[2].split(' '), parts[3].split(' '))
2165 elif op == 'unb':
2165 elif op == 'unb':
2166 doit(parts[3].split(' '), parts[2].split(' '))
2166 doit(parts[3].split(' '), parts[2].split(' '))
2167 line = logfile.readline()
2167 line = logfile.readline()
2168 finally:
2168 finally:
2169 logfile.close()
2169 logfile.close()
2170
2170
2171 else:
2171 else:
2172 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2172 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2173 opts.get('remote_head'))
2173 opts.get('remote_head'))
2174 localrevs = opts.get('local_head')
2174 localrevs = opts.get('local_head')
2175 doit(localrevs, remoterevs)
2175 doit(localrevs, remoterevs)
2176
2176
2177 @command('debugfileset',
2177 @command('debugfileset',
2178 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2178 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2179 _('[-r REV] FILESPEC'))
2179 _('[-r REV] FILESPEC'))
2180 def debugfileset(ui, repo, expr, **opts):
2180 def debugfileset(ui, repo, expr, **opts):
2181 '''parse and apply a fileset specification'''
2181 '''parse and apply a fileset specification'''
2182 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2182 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2183 if ui.verbose:
2183 if ui.verbose:
2184 tree = fileset.parse(expr)
2184 tree = fileset.parse(expr)
2185 ui.note(fileset.prettyformat(tree), "\n")
2185 ui.note(fileset.prettyformat(tree), "\n")
2186
2186
2187 for f in ctx.getfileset(expr):
2187 for f in ctx.getfileset(expr):
2188 ui.write("%s\n" % f)
2188 ui.write("%s\n" % f)
2189
2189
2190 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2190 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2191 def debugfsinfo(ui, path="."):
2191 def debugfsinfo(ui, path="."):
2192 """show information detected about current filesystem"""
2192 """show information detected about current filesystem"""
2193 util.writefile('.debugfsinfo', '')
2193 util.writefile('.debugfsinfo', '')
2194 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2194 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2195 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2195 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2196 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2196 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2197 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2197 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2198 and 'yes' or 'no'))
2198 and 'yes' or 'no'))
2199 os.unlink('.debugfsinfo')
2199 os.unlink('.debugfsinfo')
2200
2200
2201 @command('debuggetbundle',
2201 @command('debuggetbundle',
2202 [('H', 'head', [], _('id of head node'), _('ID')),
2202 [('H', 'head', [], _('id of head node'), _('ID')),
2203 ('C', 'common', [], _('id of common node'), _('ID')),
2203 ('C', 'common', [], _('id of common node'), _('ID')),
2204 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2204 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2205 _('REPO FILE [-H|-C ID]...'),
2205 _('REPO FILE [-H|-C ID]...'),
2206 norepo=True)
2206 norepo=True)
2207 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2207 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2208 """retrieves a bundle from a repo
2208 """retrieves a bundle from a repo
2209
2209
2210 Every ID must be a full-length hex node id string. Saves the bundle to the
2210 Every ID must be a full-length hex node id string. Saves the bundle to the
2211 given file.
2211 given file.
2212 """
2212 """
2213 repo = hg.peer(ui, opts, repopath)
2213 repo = hg.peer(ui, opts, repopath)
2214 if not repo.capable('getbundle'):
2214 if not repo.capable('getbundle'):
2215 raise util.Abort("getbundle() not supported by target repository")
2215 raise util.Abort("getbundle() not supported by target repository")
2216 args = {}
2216 args = {}
2217 if common:
2217 if common:
2218 args['common'] = [bin(s) for s in common]
2218 args['common'] = [bin(s) for s in common]
2219 if head:
2219 if head:
2220 args['heads'] = [bin(s) for s in head]
2220 args['heads'] = [bin(s) for s in head]
2221 # TODO: get desired bundlecaps from command line.
2221 # TODO: get desired bundlecaps from command line.
2222 args['bundlecaps'] = None
2222 args['bundlecaps'] = None
2223 bundle = repo.getbundle('debug', **args)
2223 bundle = repo.getbundle('debug', **args)
2224
2224
2225 bundletype = opts.get('type', 'bzip2').lower()
2225 bundletype = opts.get('type', 'bzip2').lower()
2226 btypes = {'none': 'HG10UN',
2226 btypes = {'none': 'HG10UN',
2227 'bzip2': 'HG10BZ',
2227 'bzip2': 'HG10BZ',
2228 'gzip': 'HG10GZ',
2228 'gzip': 'HG10GZ',
2229 'bundle2': 'HG20'}
2229 'bundle2': 'HG20'}
2230 bundletype = btypes.get(bundletype)
2230 bundletype = btypes.get(bundletype)
2231 if bundletype not in changegroup.bundletypes:
2231 if bundletype not in changegroup.bundletypes:
2232 raise util.Abort(_('unknown bundle type specified with --type'))
2232 raise util.Abort(_('unknown bundle type specified with --type'))
2233 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2233 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2234
2234
2235 @command('debugignore', [], '')
2235 @command('debugignore', [], '')
2236 def debugignore(ui, repo, *values, **opts):
2236 def debugignore(ui, repo, *values, **opts):
2237 """display the combined ignore pattern"""
2237 """display the combined ignore pattern"""
2238 ignore = repo.dirstate._ignore
2238 ignore = repo.dirstate._ignore
2239 includepat = getattr(ignore, 'includepat', None)
2239 includepat = getattr(ignore, 'includepat', None)
2240 if includepat is not None:
2240 if includepat is not None:
2241 ui.write("%s\n" % includepat)
2241 ui.write("%s\n" % includepat)
2242 else:
2242 else:
2243 raise util.Abort(_("no ignore patterns found"))
2243 raise util.Abort(_("no ignore patterns found"))
2244
2244
2245 @command('debugindex',
2245 @command('debugindex',
2246 [('c', 'changelog', False, _('open changelog')),
2246 [('c', 'changelog', False, _('open changelog')),
2247 ('m', 'manifest', False, _('open manifest')),
2247 ('m', 'manifest', False, _('open manifest')),
2248 ('', 'dir', False, _('open directory manifest')),
2248 ('', 'dir', False, _('open directory manifest')),
2249 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2249 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2250 _('[-f FORMAT] -c|-m|FILE'),
2250 _('[-f FORMAT] -c|-m|FILE'),
2251 optionalrepo=True)
2251 optionalrepo=True)
2252 def debugindex(ui, repo, file_=None, **opts):
2252 def debugindex(ui, repo, file_=None, **opts):
2253 """dump the contents of an index file"""
2253 """dump the contents of an index file"""
2254 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2254 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2255 format = opts.get('format', 0)
2255 format = opts.get('format', 0)
2256 if format not in (0, 1):
2256 if format not in (0, 1):
2257 raise util.Abort(_("unknown format %d") % format)
2257 raise util.Abort(_("unknown format %d") % format)
2258
2258
2259 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2259 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2260 if generaldelta:
2260 if generaldelta:
2261 basehdr = ' delta'
2261 basehdr = ' delta'
2262 else:
2262 else:
2263 basehdr = ' base'
2263 basehdr = ' base'
2264
2264
2265 if ui.debugflag:
2265 if ui.debugflag:
2266 shortfn = hex
2266 shortfn = hex
2267 else:
2267 else:
2268 shortfn = short
2268 shortfn = short
2269
2269
2270 # There might not be anything in r, so have a sane default
2270 # There might not be anything in r, so have a sane default
2271 idlen = 12
2271 idlen = 12
2272 for i in r:
2272 for i in r:
2273 idlen = len(shortfn(r.node(i)))
2273 idlen = len(shortfn(r.node(i)))
2274 break
2274 break
2275
2275
2276 if format == 0:
2276 if format == 0:
2277 ui.write(" rev offset length " + basehdr + " linkrev"
2277 ui.write(" rev offset length " + basehdr + " linkrev"
2278 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2278 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2279 elif format == 1:
2279 elif format == 1:
2280 ui.write(" rev flag offset length"
2280 ui.write(" rev flag offset length"
2281 " size " + basehdr + " link p1 p2"
2281 " size " + basehdr + " link p1 p2"
2282 " %s\n" % "nodeid".rjust(idlen))
2282 " %s\n" % "nodeid".rjust(idlen))
2283
2283
2284 for i in r:
2284 for i in r:
2285 node = r.node(i)
2285 node = r.node(i)
2286 if generaldelta:
2286 if generaldelta:
2287 base = r.deltaparent(i)
2287 base = r.deltaparent(i)
2288 else:
2288 else:
2289 base = r.chainbase(i)
2289 base = r.chainbase(i)
2290 if format == 0:
2290 if format == 0:
2291 try:
2291 try:
2292 pp = r.parents(node)
2292 pp = r.parents(node)
2293 except Exception:
2293 except Exception:
2294 pp = [nullid, nullid]
2294 pp = [nullid, nullid]
2295 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2295 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2296 i, r.start(i), r.length(i), base, r.linkrev(i),
2296 i, r.start(i), r.length(i), base, r.linkrev(i),
2297 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2297 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2298 elif format == 1:
2298 elif format == 1:
2299 pr = r.parentrevs(i)
2299 pr = r.parentrevs(i)
2300 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2300 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2301 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2301 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2302 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2302 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2303
2303
2304 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2304 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2305 def debugindexdot(ui, repo, file_):
2305 def debugindexdot(ui, repo, file_):
2306 """dump an index DAG as a graphviz dot file"""
2306 """dump an index DAG as a graphviz dot file"""
2307 r = None
2307 r = None
2308 if repo:
2308 if repo:
2309 filelog = repo.file(file_)
2309 filelog = repo.file(file_)
2310 if len(filelog):
2310 if len(filelog):
2311 r = filelog
2311 r = filelog
2312 if not r:
2312 if not r:
2313 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2313 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2314 ui.write(("digraph G {\n"))
2314 ui.write(("digraph G {\n"))
2315 for i in r:
2315 for i in r:
2316 node = r.node(i)
2316 node = r.node(i)
2317 pp = r.parents(node)
2317 pp = r.parents(node)
2318 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2318 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2319 if pp[1] != nullid:
2319 if pp[1] != nullid:
2320 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2320 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2321 ui.write("}\n")
2321 ui.write("}\n")
2322
2322
2323 @command('debuginstall', [], '', norepo=True)
2323 @command('debuginstall', [], '', norepo=True)
2324 def debuginstall(ui):
2324 def debuginstall(ui):
2325 '''test Mercurial installation
2325 '''test Mercurial installation
2326
2326
2327 Returns 0 on success.
2327 Returns 0 on success.
2328 '''
2328 '''
2329
2329
2330 def writetemp(contents):
2330 def writetemp(contents):
2331 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2331 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2332 f = os.fdopen(fd, "wb")
2332 f = os.fdopen(fd, "wb")
2333 f.write(contents)
2333 f.write(contents)
2334 f.close()
2334 f.close()
2335 return name
2335 return name
2336
2336
2337 problems = 0
2337 problems = 0
2338
2338
2339 # encoding
2339 # encoding
2340 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2340 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2341 try:
2341 try:
2342 encoding.fromlocal("test")
2342 encoding.fromlocal("test")
2343 except util.Abort, inst:
2343 except util.Abort, inst:
2344 ui.write(" %s\n" % inst)
2344 ui.write(" %s\n" % inst)
2345 ui.write(_(" (check that your locale is properly set)\n"))
2345 ui.write(_(" (check that your locale is properly set)\n"))
2346 problems += 1
2346 problems += 1
2347
2347
2348 # Python
2348 # Python
2349 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2349 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2350 ui.status(_("checking Python version (%s)\n")
2350 ui.status(_("checking Python version (%s)\n")
2351 % ("%s.%s.%s" % sys.version_info[:3]))
2351 % ("%s.%s.%s" % sys.version_info[:3]))
2352 ui.status(_("checking Python lib (%s)...\n")
2352 ui.status(_("checking Python lib (%s)...\n")
2353 % os.path.dirname(os.__file__))
2353 % os.path.dirname(os.__file__))
2354
2354
2355 # compiled modules
2355 # compiled modules
2356 ui.status(_("checking installed modules (%s)...\n")
2356 ui.status(_("checking installed modules (%s)...\n")
2357 % os.path.dirname(__file__))
2357 % os.path.dirname(__file__))
2358 try:
2358 try:
2359 import bdiff, mpatch, base85, osutil
2359 import bdiff, mpatch, base85, osutil
2360 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2360 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2361 except Exception, inst:
2361 except Exception, inst:
2362 ui.write(" %s\n" % inst)
2362 ui.write(" %s\n" % inst)
2363 ui.write(_(" One or more extensions could not be found"))
2363 ui.write(_(" One or more extensions could not be found"))
2364 ui.write(_(" (check that you compiled the extensions)\n"))
2364 ui.write(_(" (check that you compiled the extensions)\n"))
2365 problems += 1
2365 problems += 1
2366
2366
2367 # templates
2367 # templates
2368 import templater
2368 import templater
2369 p = templater.templatepaths()
2369 p = templater.templatepaths()
2370 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2370 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2371 if p:
2371 if p:
2372 m = templater.templatepath("map-cmdline.default")
2372 m = templater.templatepath("map-cmdline.default")
2373 if m:
2373 if m:
2374 # template found, check if it is working
2374 # template found, check if it is working
2375 try:
2375 try:
2376 templater.templater(m)
2376 templater.templater(m)
2377 except Exception, inst:
2377 except Exception, inst:
2378 ui.write(" %s\n" % inst)
2378 ui.write(" %s\n" % inst)
2379 p = None
2379 p = None
2380 else:
2380 else:
2381 ui.write(_(" template 'default' not found\n"))
2381 ui.write(_(" template 'default' not found\n"))
2382 p = None
2382 p = None
2383 else:
2383 else:
2384 ui.write(_(" no template directories found\n"))
2384 ui.write(_(" no template directories found\n"))
2385 if not p:
2385 if not p:
2386 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2386 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2387 problems += 1
2387 problems += 1
2388
2388
2389 # editor
2389 # editor
2390 ui.status(_("checking commit editor...\n"))
2390 ui.status(_("checking commit editor...\n"))
2391 editor = ui.geteditor()
2391 editor = ui.geteditor()
2392 editor = util.expandpath(editor)
2392 editor = util.expandpath(editor)
2393 cmdpath = util.findexe(shlex.split(editor)[0])
2393 cmdpath = util.findexe(shlex.split(editor)[0])
2394 if not cmdpath:
2394 if not cmdpath:
2395 if editor == 'vi':
2395 if editor == 'vi':
2396 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2396 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2397 ui.write(_(" (specify a commit editor in your configuration"
2397 ui.write(_(" (specify a commit editor in your configuration"
2398 " file)\n"))
2398 " file)\n"))
2399 else:
2399 else:
2400 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2400 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2401 ui.write(_(" (specify a commit editor in your configuration"
2401 ui.write(_(" (specify a commit editor in your configuration"
2402 " file)\n"))
2402 " file)\n"))
2403 problems += 1
2403 problems += 1
2404
2404
2405 # check username
2405 # check username
2406 ui.status(_("checking username...\n"))
2406 ui.status(_("checking username...\n"))
2407 try:
2407 try:
2408 ui.username()
2408 ui.username()
2409 except util.Abort, e:
2409 except util.Abort, e:
2410 ui.write(" %s\n" % e)
2410 ui.write(" %s\n" % e)
2411 ui.write(_(" (specify a username in your configuration file)\n"))
2411 ui.write(_(" (specify a username in your configuration file)\n"))
2412 problems += 1
2412 problems += 1
2413
2413
2414 if not problems:
2414 if not problems:
2415 ui.status(_("no problems detected\n"))
2415 ui.status(_("no problems detected\n"))
2416 else:
2416 else:
2417 ui.write(_("%s problems detected,"
2417 ui.write(_("%s problems detected,"
2418 " please check your install!\n") % problems)
2418 " please check your install!\n") % problems)
2419
2419
2420 return problems
2420 return problems
2421
2421
2422 @command('debugknown', [], _('REPO ID...'), norepo=True)
2422 @command('debugknown', [], _('REPO ID...'), norepo=True)
2423 def debugknown(ui, repopath, *ids, **opts):
2423 def debugknown(ui, repopath, *ids, **opts):
2424 """test whether node ids are known to a repo
2424 """test whether node ids are known to a repo
2425
2425
2426 Every ID must be a full-length hex node id string. Returns a list of 0s
2426 Every ID must be a full-length hex node id string. Returns a list of 0s
2427 and 1s indicating unknown/known.
2427 and 1s indicating unknown/known.
2428 """
2428 """
2429 repo = hg.peer(ui, opts, repopath)
2429 repo = hg.peer(ui, opts, repopath)
2430 if not repo.capable('known'):
2430 if not repo.capable('known'):
2431 raise util.Abort("known() not supported by target repository")
2431 raise util.Abort("known() not supported by target repository")
2432 flags = repo.known([bin(s) for s in ids])
2432 flags = repo.known([bin(s) for s in ids])
2433 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2433 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2434
2434
2435 @command('debuglabelcomplete', [], _('LABEL...'))
2435 @command('debuglabelcomplete', [], _('LABEL...'))
2436 def debuglabelcomplete(ui, repo, *args):
2436 def debuglabelcomplete(ui, repo, *args):
2437 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2437 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2438 debugnamecomplete(ui, repo, *args)
2438 debugnamecomplete(ui, repo, *args)
2439
2439
2440 @command('debugnamecomplete', [], _('NAME...'))
2440 @command('debugnamecomplete', [], _('NAME...'))
2441 def debugnamecomplete(ui, repo, *args):
2441 def debugnamecomplete(ui, repo, *args):
2442 '''complete "names" - tags, open branch names, bookmark names'''
2442 '''complete "names" - tags, open branch names, bookmark names'''
2443
2443
2444 names = set()
2444 names = set()
2445 # since we previously only listed open branches, we will handle that
2445 # since we previously only listed open branches, we will handle that
2446 # specially (after this for loop)
2446 # specially (after this for loop)
2447 for name, ns in repo.names.iteritems():
2447 for name, ns in repo.names.iteritems():
2448 if name != 'branches':
2448 if name != 'branches':
2449 names.update(ns.listnames(repo))
2449 names.update(ns.listnames(repo))
2450 names.update(tag for (tag, heads, tip, closed)
2450 names.update(tag for (tag, heads, tip, closed)
2451 in repo.branchmap().iterbranches() if not closed)
2451 in repo.branchmap().iterbranches() if not closed)
2452 completions = set()
2452 completions = set()
2453 if not args:
2453 if not args:
2454 args = ['']
2454 args = ['']
2455 for a in args:
2455 for a in args:
2456 completions.update(n for n in names if n.startswith(a))
2456 completions.update(n for n in names if n.startswith(a))
2457 ui.write('\n'.join(sorted(completions)))
2457 ui.write('\n'.join(sorted(completions)))
2458 ui.write('\n')
2458 ui.write('\n')
2459
2459
2460 @command('debuglocks',
2460 @command('debuglocks',
2461 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2461 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2462 ('W', 'force-wlock', None,
2462 ('W', 'force-wlock', None,
2463 _('free the working state lock (DANGEROUS)'))],
2463 _('free the working state lock (DANGEROUS)'))],
2464 _('[OPTION]...'))
2464 _('[OPTION]...'))
2465 def debuglocks(ui, repo, **opts):
2465 def debuglocks(ui, repo, **opts):
2466 """show or modify state of locks
2466 """show or modify state of locks
2467
2467
2468 By default, this command will show which locks are held. This
2468 By default, this command will show which locks are held. This
2469 includes the user and process holding the lock, the amount of time
2469 includes the user and process holding the lock, the amount of time
2470 the lock has been held, and the machine name where the process is
2470 the lock has been held, and the machine name where the process is
2471 running if it's not local.
2471 running if it's not local.
2472
2472
2473 Locks protect the integrity of Mercurial's data, so should be
2473 Locks protect the integrity of Mercurial's data, so should be
2474 treated with care. System crashes or other interruptions may cause
2474 treated with care. System crashes or other interruptions may cause
2475 locks to not be properly released, though Mercurial will usually
2475 locks to not be properly released, though Mercurial will usually
2476 detect and remove such stale locks automatically.
2476 detect and remove such stale locks automatically.
2477
2477
2478 However, detecting stale locks may not always be possible (for
2478 However, detecting stale locks may not always be possible (for
2479 instance, on a shared filesystem). Removing locks may also be
2479 instance, on a shared filesystem). Removing locks may also be
2480 blocked by filesystem permissions.
2480 blocked by filesystem permissions.
2481
2481
2482 Returns 0 if no locks are held.
2482 Returns 0 if no locks are held.
2483
2483
2484 """
2484 """
2485
2485
2486 if opts.get('force_lock'):
2486 if opts.get('force_lock'):
2487 repo.svfs.unlink('lock')
2487 repo.svfs.unlink('lock')
2488 if opts.get('force_wlock'):
2488 if opts.get('force_wlock'):
2489 repo.vfs.unlink('wlock')
2489 repo.vfs.unlink('wlock')
2490 if opts.get('force_lock') or opts.get('force_lock'):
2490 if opts.get('force_lock') or opts.get('force_lock'):
2491 return 0
2491 return 0
2492
2492
2493 now = time.time()
2493 now = time.time()
2494 held = 0
2494 held = 0
2495
2495
2496 def report(vfs, name, method):
2496 def report(vfs, name, method):
2497 # this causes stale locks to get reaped for more accurate reporting
2497 # this causes stale locks to get reaped for more accurate reporting
2498 try:
2498 try:
2499 l = method(False)
2499 l = method(False)
2500 except error.LockHeld:
2500 except error.LockHeld:
2501 l = None
2501 l = None
2502
2502
2503 if l:
2503 if l:
2504 l.release()
2504 l.release()
2505 else:
2505 else:
2506 try:
2506 try:
2507 stat = vfs.lstat(name)
2507 stat = vfs.lstat(name)
2508 age = now - stat.st_mtime
2508 age = now - stat.st_mtime
2509 user = util.username(stat.st_uid)
2509 user = util.username(stat.st_uid)
2510 locker = vfs.readlock(name)
2510 locker = vfs.readlock(name)
2511 if ":" in locker:
2511 if ":" in locker:
2512 host, pid = locker.split(':')
2512 host, pid = locker.split(':')
2513 if host == socket.gethostname():
2513 if host == socket.gethostname():
2514 locker = 'user %s, process %s' % (user, pid)
2514 locker = 'user %s, process %s' % (user, pid)
2515 else:
2515 else:
2516 locker = 'user %s, process %s, host %s' \
2516 locker = 'user %s, process %s, host %s' \
2517 % (user, pid, host)
2517 % (user, pid, host)
2518 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2518 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2519 return 1
2519 return 1
2520 except OSError, e:
2520 except OSError, e:
2521 if e.errno != errno.ENOENT:
2521 if e.errno != errno.ENOENT:
2522 raise
2522 raise
2523
2523
2524 ui.write("%-6s free\n" % (name + ":"))
2524 ui.write("%-6s free\n" % (name + ":"))
2525 return 0
2525 return 0
2526
2526
2527 held += report(repo.svfs, "lock", repo.lock)
2527 held += report(repo.svfs, "lock", repo.lock)
2528 held += report(repo.vfs, "wlock", repo.wlock)
2528 held += report(repo.vfs, "wlock", repo.wlock)
2529
2529
2530 return held
2530 return held
2531
2531
2532 @command('debugobsolete',
2532 @command('debugobsolete',
2533 [('', 'flags', 0, _('markers flag')),
2533 [('', 'flags', 0, _('markers flag')),
2534 ('', 'record-parents', False,
2534 ('', 'record-parents', False,
2535 _('record parent information for the precursor')),
2535 _('record parent information for the precursor')),
2536 ('r', 'rev', [], _('display markers relevant to REV')),
2536 ('r', 'rev', [], _('display markers relevant to REV')),
2537 ] + commitopts2,
2537 ] + commitopts2,
2538 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2538 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2539 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2539 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2540 """create arbitrary obsolete marker
2540 """create arbitrary obsolete marker
2541
2541
2542 With no arguments, displays the list of obsolescence markers."""
2542 With no arguments, displays the list of obsolescence markers."""
2543
2543
2544 def parsenodeid(s):
2544 def parsenodeid(s):
2545 try:
2545 try:
2546 # We do not use revsingle/revrange functions here to accept
2546 # We do not use revsingle/revrange functions here to accept
2547 # arbitrary node identifiers, possibly not present in the
2547 # arbitrary node identifiers, possibly not present in the
2548 # local repository.
2548 # local repository.
2549 n = bin(s)
2549 n = bin(s)
2550 if len(n) != len(nullid):
2550 if len(n) != len(nullid):
2551 raise TypeError()
2551 raise TypeError()
2552 return n
2552 return n
2553 except TypeError:
2553 except TypeError:
2554 raise util.Abort('changeset references must be full hexadecimal '
2554 raise util.Abort('changeset references must be full hexadecimal '
2555 'node identifiers')
2555 'node identifiers')
2556
2556
2557 if precursor is not None:
2557 if precursor is not None:
2558 if opts['rev']:
2558 if opts['rev']:
2559 raise util.Abort('cannot select revision when creating marker')
2559 raise util.Abort('cannot select revision when creating marker')
2560 metadata = {}
2560 metadata = {}
2561 metadata['user'] = opts['user'] or ui.username()
2561 metadata['user'] = opts['user'] or ui.username()
2562 succs = tuple(parsenodeid(succ) for succ in successors)
2562 succs = tuple(parsenodeid(succ) for succ in successors)
2563 l = repo.lock()
2563 l = repo.lock()
2564 try:
2564 try:
2565 tr = repo.transaction('debugobsolete')
2565 tr = repo.transaction('debugobsolete')
2566 try:
2566 try:
2567 date = opts.get('date')
2567 date = opts.get('date')
2568 if date:
2568 if date:
2569 date = util.parsedate(date)
2569 date = util.parsedate(date)
2570 else:
2570 else:
2571 date = None
2571 date = None
2572 prec = parsenodeid(precursor)
2572 prec = parsenodeid(precursor)
2573 parents = None
2573 parents = None
2574 if opts['record_parents']:
2574 if opts['record_parents']:
2575 if prec not in repo.unfiltered():
2575 if prec not in repo.unfiltered():
2576 raise util.Abort('cannot used --record-parents on '
2576 raise util.Abort('cannot used --record-parents on '
2577 'unknown changesets')
2577 'unknown changesets')
2578 parents = repo.unfiltered()[prec].parents()
2578 parents = repo.unfiltered()[prec].parents()
2579 parents = tuple(p.node() for p in parents)
2579 parents = tuple(p.node() for p in parents)
2580 repo.obsstore.create(tr, prec, succs, opts['flags'],
2580 repo.obsstore.create(tr, prec, succs, opts['flags'],
2581 parents=parents, date=date,
2581 parents=parents, date=date,
2582 metadata=metadata)
2582 metadata=metadata)
2583 tr.close()
2583 tr.close()
2584 except ValueError, exc:
2584 except ValueError, exc:
2585 raise util.Abort(_('bad obsmarker input: %s') % exc)
2585 raise util.Abort(_('bad obsmarker input: %s') % exc)
2586 finally:
2586 finally:
2587 tr.release()
2587 tr.release()
2588 finally:
2588 finally:
2589 l.release()
2589 l.release()
2590 else:
2590 else:
2591 if opts['rev']:
2591 if opts['rev']:
2592 revs = scmutil.revrange(repo, opts['rev'])
2592 revs = scmutil.revrange(repo, opts['rev'])
2593 nodes = [repo[r].node() for r in revs]
2593 nodes = [repo[r].node() for r in revs]
2594 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2594 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2595 markers.sort(key=lambda x: x._data)
2595 markers.sort(key=lambda x: x._data)
2596 else:
2596 else:
2597 markers = obsolete.getmarkers(repo)
2597 markers = obsolete.getmarkers(repo)
2598
2598
2599 for m in markers:
2599 for m in markers:
2600 cmdutil.showmarker(ui, m)
2600 cmdutil.showmarker(ui, m)
2601
2601
2602 @command('debugpathcomplete',
2602 @command('debugpathcomplete',
2603 [('f', 'full', None, _('complete an entire path')),
2603 [('f', 'full', None, _('complete an entire path')),
2604 ('n', 'normal', None, _('show only normal files')),
2604 ('n', 'normal', None, _('show only normal files')),
2605 ('a', 'added', None, _('show only added files')),
2605 ('a', 'added', None, _('show only added files')),
2606 ('r', 'removed', None, _('show only removed files'))],
2606 ('r', 'removed', None, _('show only removed files'))],
2607 _('FILESPEC...'))
2607 _('FILESPEC...'))
2608 def debugpathcomplete(ui, repo, *specs, **opts):
2608 def debugpathcomplete(ui, repo, *specs, **opts):
2609 '''complete part or all of a tracked path
2609 '''complete part or all of a tracked path
2610
2610
2611 This command supports shells that offer path name completion. It
2611 This command supports shells that offer path name completion. It
2612 currently completes only files already known to the dirstate.
2612 currently completes only files already known to the dirstate.
2613
2613
2614 Completion extends only to the next path segment unless
2614 Completion extends only to the next path segment unless
2615 --full is specified, in which case entire paths are used.'''
2615 --full is specified, in which case entire paths are used.'''
2616
2616
2617 def complete(path, acceptable):
2617 def complete(path, acceptable):
2618 dirstate = repo.dirstate
2618 dirstate = repo.dirstate
2619 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2619 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2620 rootdir = repo.root + os.sep
2620 rootdir = repo.root + os.sep
2621 if spec != repo.root and not spec.startswith(rootdir):
2621 if spec != repo.root and not spec.startswith(rootdir):
2622 return [], []
2622 return [], []
2623 if os.path.isdir(spec):
2623 if os.path.isdir(spec):
2624 spec += '/'
2624 spec += '/'
2625 spec = spec[len(rootdir):]
2625 spec = spec[len(rootdir):]
2626 fixpaths = os.sep != '/'
2626 fixpaths = os.sep != '/'
2627 if fixpaths:
2627 if fixpaths:
2628 spec = spec.replace(os.sep, '/')
2628 spec = spec.replace(os.sep, '/')
2629 speclen = len(spec)
2629 speclen = len(spec)
2630 fullpaths = opts['full']
2630 fullpaths = opts['full']
2631 files, dirs = set(), set()
2631 files, dirs = set(), set()
2632 adddir, addfile = dirs.add, files.add
2632 adddir, addfile = dirs.add, files.add
2633 for f, st in dirstate.iteritems():
2633 for f, st in dirstate.iteritems():
2634 if f.startswith(spec) and st[0] in acceptable:
2634 if f.startswith(spec) and st[0] in acceptable:
2635 if fixpaths:
2635 if fixpaths:
2636 f = f.replace('/', os.sep)
2636 f = f.replace('/', os.sep)
2637 if fullpaths:
2637 if fullpaths:
2638 addfile(f)
2638 addfile(f)
2639 continue
2639 continue
2640 s = f.find(os.sep, speclen)
2640 s = f.find(os.sep, speclen)
2641 if s >= 0:
2641 if s >= 0:
2642 adddir(f[:s])
2642 adddir(f[:s])
2643 else:
2643 else:
2644 addfile(f)
2644 addfile(f)
2645 return files, dirs
2645 return files, dirs
2646
2646
2647 acceptable = ''
2647 acceptable = ''
2648 if opts['normal']:
2648 if opts['normal']:
2649 acceptable += 'nm'
2649 acceptable += 'nm'
2650 if opts['added']:
2650 if opts['added']:
2651 acceptable += 'a'
2651 acceptable += 'a'
2652 if opts['removed']:
2652 if opts['removed']:
2653 acceptable += 'r'
2653 acceptable += 'r'
2654 cwd = repo.getcwd()
2654 cwd = repo.getcwd()
2655 if not specs:
2655 if not specs:
2656 specs = ['.']
2656 specs = ['.']
2657
2657
2658 files, dirs = set(), set()
2658 files, dirs = set(), set()
2659 for spec in specs:
2659 for spec in specs:
2660 f, d = complete(spec, acceptable or 'nmar')
2660 f, d = complete(spec, acceptable or 'nmar')
2661 files.update(f)
2661 files.update(f)
2662 dirs.update(d)
2662 dirs.update(d)
2663 files.update(dirs)
2663 files.update(dirs)
2664 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2664 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2665 ui.write('\n')
2665 ui.write('\n')
2666
2666
2667 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2667 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2668 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2668 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2669 '''access the pushkey key/value protocol
2669 '''access the pushkey key/value protocol
2670
2670
2671 With two args, list the keys in the given namespace.
2671 With two args, list the keys in the given namespace.
2672
2672
2673 With five args, set a key to new if it currently is set to old.
2673 With five args, set a key to new if it currently is set to old.
2674 Reports success or failure.
2674 Reports success or failure.
2675 '''
2675 '''
2676
2676
2677 target = hg.peer(ui, {}, repopath)
2677 target = hg.peer(ui, {}, repopath)
2678 if keyinfo:
2678 if keyinfo:
2679 key, old, new = keyinfo
2679 key, old, new = keyinfo
2680 r = target.pushkey(namespace, key, old, new)
2680 r = target.pushkey(namespace, key, old, new)
2681 ui.status(str(r) + '\n')
2681 ui.status(str(r) + '\n')
2682 return not r
2682 return not r
2683 else:
2683 else:
2684 for k, v in sorted(target.listkeys(namespace).iteritems()):
2684 for k, v in sorted(target.listkeys(namespace).iteritems()):
2685 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2685 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2686 v.encode('string-escape')))
2686 v.encode('string-escape')))
2687
2687
2688 @command('debugpvec', [], _('A B'))
2688 @command('debugpvec', [], _('A B'))
2689 def debugpvec(ui, repo, a, b=None):
2689 def debugpvec(ui, repo, a, b=None):
2690 ca = scmutil.revsingle(repo, a)
2690 ca = scmutil.revsingle(repo, a)
2691 cb = scmutil.revsingle(repo, b)
2691 cb = scmutil.revsingle(repo, b)
2692 pa = pvec.ctxpvec(ca)
2692 pa = pvec.ctxpvec(ca)
2693 pb = pvec.ctxpvec(cb)
2693 pb = pvec.ctxpvec(cb)
2694 if pa == pb:
2694 if pa == pb:
2695 rel = "="
2695 rel = "="
2696 elif pa > pb:
2696 elif pa > pb:
2697 rel = ">"
2697 rel = ">"
2698 elif pa < pb:
2698 elif pa < pb:
2699 rel = "<"
2699 rel = "<"
2700 elif pa | pb:
2700 elif pa | pb:
2701 rel = "|"
2701 rel = "|"
2702 ui.write(_("a: %s\n") % pa)
2702 ui.write(_("a: %s\n") % pa)
2703 ui.write(_("b: %s\n") % pb)
2703 ui.write(_("b: %s\n") % pb)
2704 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2704 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2705 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2705 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2706 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2706 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2707 pa.distance(pb), rel))
2707 pa.distance(pb), rel))
2708
2708
2709 @command('debugrebuilddirstate|debugrebuildstate',
2709 @command('debugrebuilddirstate|debugrebuildstate',
2710 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2710 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2711 _('[-r REV]'))
2711 _('[-r REV]'))
2712 def debugrebuilddirstate(ui, repo, rev):
2712 def debugrebuilddirstate(ui, repo, rev):
2713 """rebuild the dirstate as it would look like for the given revision
2713 """rebuild the dirstate as it would look like for the given revision
2714
2714
2715 If no revision is specified the first current parent will be used.
2715 If no revision is specified the first current parent will be used.
2716
2716
2717 The dirstate will be set to the files of the given revision.
2717 The dirstate will be set to the files of the given revision.
2718 The actual working directory content or existing dirstate
2718 The actual working directory content or existing dirstate
2719 information such as adds or removes is not considered.
2719 information such as adds or removes is not considered.
2720
2720
2721 One use of this command is to make the next :hg:`status` invocation
2721 One use of this command is to make the next :hg:`status` invocation
2722 check the actual file content.
2722 check the actual file content.
2723 """
2723 """
2724 ctx = scmutil.revsingle(repo, rev)
2724 ctx = scmutil.revsingle(repo, rev)
2725 wlock = repo.wlock()
2725 wlock = repo.wlock()
2726 try:
2726 try:
2727 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2727 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2728 finally:
2728 finally:
2729 wlock.release()
2729 wlock.release()
2730
2730
2731 @command('debugrename',
2731 @command('debugrename',
2732 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2732 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2733 _('[-r REV] FILE'))
2733 _('[-r REV] FILE'))
2734 def debugrename(ui, repo, file1, *pats, **opts):
2734 def debugrename(ui, repo, file1, *pats, **opts):
2735 """dump rename information"""
2735 """dump rename information"""
2736
2736
2737 ctx = scmutil.revsingle(repo, opts.get('rev'))
2737 ctx = scmutil.revsingle(repo, opts.get('rev'))
2738 m = scmutil.match(ctx, (file1,) + pats, opts)
2738 m = scmutil.match(ctx, (file1,) + pats, opts)
2739 for abs in ctx.walk(m):
2739 for abs in ctx.walk(m):
2740 fctx = ctx[abs]
2740 fctx = ctx[abs]
2741 o = fctx.filelog().renamed(fctx.filenode())
2741 o = fctx.filelog().renamed(fctx.filenode())
2742 rel = m.rel(abs)
2742 rel = m.rel(abs)
2743 if o:
2743 if o:
2744 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2744 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2745 else:
2745 else:
2746 ui.write(_("%s not renamed\n") % rel)
2746 ui.write(_("%s not renamed\n") % rel)
2747
2747
2748 @command('debugrevlog',
2748 @command('debugrevlog',
2749 [('c', 'changelog', False, _('open changelog')),
2749 [('c', 'changelog', False, _('open changelog')),
2750 ('m', 'manifest', False, _('open manifest')),
2750 ('m', 'manifest', False, _('open manifest')),
2751 ('', 'dir', False, _('open directory manifest')),
2751 ('', 'dir', False, _('open directory manifest')),
2752 ('d', 'dump', False, _('dump index data'))],
2752 ('d', 'dump', False, _('dump index data'))],
2753 _('-c|-m|FILE'),
2753 _('-c|-m|FILE'),
2754 optionalrepo=True)
2754 optionalrepo=True)
2755 def debugrevlog(ui, repo, file_=None, **opts):
2755 def debugrevlog(ui, repo, file_=None, **opts):
2756 """show data and statistics about a revlog"""
2756 """show data and statistics about a revlog"""
2757 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2757 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2758
2758
2759 if opts.get("dump"):
2759 if opts.get("dump"):
2760 numrevs = len(r)
2760 numrevs = len(r)
2761 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2761 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2762 " rawsize totalsize compression heads chainlen\n")
2762 " rawsize totalsize compression heads chainlen\n")
2763 ts = 0
2763 ts = 0
2764 heads = set()
2764 heads = set()
2765
2765
2766 for rev in xrange(numrevs):
2766 for rev in xrange(numrevs):
2767 dbase = r.deltaparent(rev)
2767 dbase = r.deltaparent(rev)
2768 if dbase == -1:
2768 if dbase == -1:
2769 dbase = rev
2769 dbase = rev
2770 cbase = r.chainbase(rev)
2770 cbase = r.chainbase(rev)
2771 clen = r.chainlen(rev)
2771 clen = r.chainlen(rev)
2772 p1, p2 = r.parentrevs(rev)
2772 p1, p2 = r.parentrevs(rev)
2773 rs = r.rawsize(rev)
2773 rs = r.rawsize(rev)
2774 ts = ts + rs
2774 ts = ts + rs
2775 heads -= set(r.parentrevs(rev))
2775 heads -= set(r.parentrevs(rev))
2776 heads.add(rev)
2776 heads.add(rev)
2777 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2777 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2778 "%11d %5d %8d\n" %
2778 "%11d %5d %8d\n" %
2779 (rev, p1, p2, r.start(rev), r.end(rev),
2779 (rev, p1, p2, r.start(rev), r.end(rev),
2780 r.start(dbase), r.start(cbase),
2780 r.start(dbase), r.start(cbase),
2781 r.start(p1), r.start(p2),
2781 r.start(p1), r.start(p2),
2782 rs, ts, ts / r.end(rev), len(heads), clen))
2782 rs, ts, ts / r.end(rev), len(heads), clen))
2783 return 0
2783 return 0
2784
2784
2785 v = r.version
2785 v = r.version
2786 format = v & 0xFFFF
2786 format = v & 0xFFFF
2787 flags = []
2787 flags = []
2788 gdelta = False
2788 gdelta = False
2789 if v & revlog.REVLOGNGINLINEDATA:
2789 if v & revlog.REVLOGNGINLINEDATA:
2790 flags.append('inline')
2790 flags.append('inline')
2791 if v & revlog.REVLOGGENERALDELTA:
2791 if v & revlog.REVLOGGENERALDELTA:
2792 gdelta = True
2792 gdelta = True
2793 flags.append('generaldelta')
2793 flags.append('generaldelta')
2794 if not flags:
2794 if not flags:
2795 flags = ['(none)']
2795 flags = ['(none)']
2796
2796
2797 nummerges = 0
2797 nummerges = 0
2798 numfull = 0
2798 numfull = 0
2799 numprev = 0
2799 numprev = 0
2800 nump1 = 0
2800 nump1 = 0
2801 nump2 = 0
2801 nump2 = 0
2802 numother = 0
2802 numother = 0
2803 nump1prev = 0
2803 nump1prev = 0
2804 nump2prev = 0
2804 nump2prev = 0
2805 chainlengths = []
2805 chainlengths = []
2806
2806
2807 datasize = [None, 0, 0L]
2807 datasize = [None, 0, 0L]
2808 fullsize = [None, 0, 0L]
2808 fullsize = [None, 0, 0L]
2809 deltasize = [None, 0, 0L]
2809 deltasize = [None, 0, 0L]
2810
2810
2811 def addsize(size, l):
2811 def addsize(size, l):
2812 if l[0] is None or size < l[0]:
2812 if l[0] is None or size < l[0]:
2813 l[0] = size
2813 l[0] = size
2814 if size > l[1]:
2814 if size > l[1]:
2815 l[1] = size
2815 l[1] = size
2816 l[2] += size
2816 l[2] += size
2817
2817
2818 numrevs = len(r)
2818 numrevs = len(r)
2819 for rev in xrange(numrevs):
2819 for rev in xrange(numrevs):
2820 p1, p2 = r.parentrevs(rev)
2820 p1, p2 = r.parentrevs(rev)
2821 delta = r.deltaparent(rev)
2821 delta = r.deltaparent(rev)
2822 if format > 0:
2822 if format > 0:
2823 addsize(r.rawsize(rev), datasize)
2823 addsize(r.rawsize(rev), datasize)
2824 if p2 != nullrev:
2824 if p2 != nullrev:
2825 nummerges += 1
2825 nummerges += 1
2826 size = r.length(rev)
2826 size = r.length(rev)
2827 if delta == nullrev:
2827 if delta == nullrev:
2828 chainlengths.append(0)
2828 chainlengths.append(0)
2829 numfull += 1
2829 numfull += 1
2830 addsize(size, fullsize)
2830 addsize(size, fullsize)
2831 else:
2831 else:
2832 chainlengths.append(chainlengths[delta] + 1)
2832 chainlengths.append(chainlengths[delta] + 1)
2833 addsize(size, deltasize)
2833 addsize(size, deltasize)
2834 if delta == rev - 1:
2834 if delta == rev - 1:
2835 numprev += 1
2835 numprev += 1
2836 if delta == p1:
2836 if delta == p1:
2837 nump1prev += 1
2837 nump1prev += 1
2838 elif delta == p2:
2838 elif delta == p2:
2839 nump2prev += 1
2839 nump2prev += 1
2840 elif delta == p1:
2840 elif delta == p1:
2841 nump1 += 1
2841 nump1 += 1
2842 elif delta == p2:
2842 elif delta == p2:
2843 nump2 += 1
2843 nump2 += 1
2844 elif delta != nullrev:
2844 elif delta != nullrev:
2845 numother += 1
2845 numother += 1
2846
2846
2847 # Adjust size min value for empty cases
2847 # Adjust size min value for empty cases
2848 for size in (datasize, fullsize, deltasize):
2848 for size in (datasize, fullsize, deltasize):
2849 if size[0] is None:
2849 if size[0] is None:
2850 size[0] = 0
2850 size[0] = 0
2851
2851
2852 numdeltas = numrevs - numfull
2852 numdeltas = numrevs - numfull
2853 numoprev = numprev - nump1prev - nump2prev
2853 numoprev = numprev - nump1prev - nump2prev
2854 totalrawsize = datasize[2]
2854 totalrawsize = datasize[2]
2855 datasize[2] /= numrevs
2855 datasize[2] /= numrevs
2856 fulltotal = fullsize[2]
2856 fulltotal = fullsize[2]
2857 fullsize[2] /= numfull
2857 fullsize[2] /= numfull
2858 deltatotal = deltasize[2]
2858 deltatotal = deltasize[2]
2859 if numrevs - numfull > 0:
2859 if numrevs - numfull > 0:
2860 deltasize[2] /= numrevs - numfull
2860 deltasize[2] /= numrevs - numfull
2861 totalsize = fulltotal + deltatotal
2861 totalsize = fulltotal + deltatotal
2862 avgchainlen = sum(chainlengths) / numrevs
2862 avgchainlen = sum(chainlengths) / numrevs
2863 maxchainlen = max(chainlengths)
2863 maxchainlen = max(chainlengths)
2864 compratio = totalrawsize / totalsize
2864 compratio = totalrawsize / totalsize
2865
2865
2866 basedfmtstr = '%%%dd\n'
2866 basedfmtstr = '%%%dd\n'
2867 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2867 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2868
2868
2869 def dfmtstr(max):
2869 def dfmtstr(max):
2870 return basedfmtstr % len(str(max))
2870 return basedfmtstr % len(str(max))
2871 def pcfmtstr(max, padding=0):
2871 def pcfmtstr(max, padding=0):
2872 return basepcfmtstr % (len(str(max)), ' ' * padding)
2872 return basepcfmtstr % (len(str(max)), ' ' * padding)
2873
2873
2874 def pcfmt(value, total):
2874 def pcfmt(value, total):
2875 return (value, 100 * float(value) / total)
2875 return (value, 100 * float(value) / total)
2876
2876
2877 ui.write(('format : %d\n') % format)
2877 ui.write(('format : %d\n') % format)
2878 ui.write(('flags : %s\n') % ', '.join(flags))
2878 ui.write(('flags : %s\n') % ', '.join(flags))
2879
2879
2880 ui.write('\n')
2880 ui.write('\n')
2881 fmt = pcfmtstr(totalsize)
2881 fmt = pcfmtstr(totalsize)
2882 fmt2 = dfmtstr(totalsize)
2882 fmt2 = dfmtstr(totalsize)
2883 ui.write(('revisions : ') + fmt2 % numrevs)
2883 ui.write(('revisions : ') + fmt2 % numrevs)
2884 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2884 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2885 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2885 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2886 ui.write(('revisions : ') + fmt2 % numrevs)
2886 ui.write(('revisions : ') + fmt2 % numrevs)
2887 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2887 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2888 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2888 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2889 ui.write(('revision size : ') + fmt2 % totalsize)
2889 ui.write(('revision size : ') + fmt2 % totalsize)
2890 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2890 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2891 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2891 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2892
2892
2893 ui.write('\n')
2893 ui.write('\n')
2894 fmt = dfmtstr(max(avgchainlen, compratio))
2894 fmt = dfmtstr(max(avgchainlen, compratio))
2895 ui.write(('avg chain length : ') + fmt % avgchainlen)
2895 ui.write(('avg chain length : ') + fmt % avgchainlen)
2896 ui.write(('max chain length : ') + fmt % maxchainlen)
2896 ui.write(('max chain length : ') + fmt % maxchainlen)
2897 ui.write(('compression ratio : ') + fmt % compratio)
2897 ui.write(('compression ratio : ') + fmt % compratio)
2898
2898
2899 if format > 0:
2899 if format > 0:
2900 ui.write('\n')
2900 ui.write('\n')
2901 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2901 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2902 % tuple(datasize))
2902 % tuple(datasize))
2903 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2903 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2904 % tuple(fullsize))
2904 % tuple(fullsize))
2905 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2905 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2906 % tuple(deltasize))
2906 % tuple(deltasize))
2907
2907
2908 if numdeltas > 0:
2908 if numdeltas > 0:
2909 ui.write('\n')
2909 ui.write('\n')
2910 fmt = pcfmtstr(numdeltas)
2910 fmt = pcfmtstr(numdeltas)
2911 fmt2 = pcfmtstr(numdeltas, 4)
2911 fmt2 = pcfmtstr(numdeltas, 4)
2912 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2912 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2913 if numprev > 0:
2913 if numprev > 0:
2914 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2914 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2915 numprev))
2915 numprev))
2916 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2916 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2917 numprev))
2917 numprev))
2918 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2918 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2919 numprev))
2919 numprev))
2920 if gdelta:
2920 if gdelta:
2921 ui.write(('deltas against p1 : ')
2921 ui.write(('deltas against p1 : ')
2922 + fmt % pcfmt(nump1, numdeltas))
2922 + fmt % pcfmt(nump1, numdeltas))
2923 ui.write(('deltas against p2 : ')
2923 ui.write(('deltas against p2 : ')
2924 + fmt % pcfmt(nump2, numdeltas))
2924 + fmt % pcfmt(nump2, numdeltas))
2925 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2925 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2926 numdeltas))
2926 numdeltas))
2927
2927
2928 @command('debugrevspec',
2928 @command('debugrevspec',
2929 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2929 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2930 ('REVSPEC'))
2930 ('REVSPEC'))
2931 def debugrevspec(ui, repo, expr, **opts):
2931 def debugrevspec(ui, repo, expr, **opts):
2932 """parse and apply a revision specification
2932 """parse and apply a revision specification
2933
2933
2934 Use --verbose to print the parsed tree before and after aliases
2934 Use --verbose to print the parsed tree before and after aliases
2935 expansion.
2935 expansion.
2936 """
2936 """
2937 if ui.verbose:
2937 if ui.verbose:
2938 tree = revset.parse(expr)
2938 tree = revset.parse(expr)
2939 ui.note(revset.prettyformat(tree), "\n")
2939 ui.note(revset.prettyformat(tree), "\n")
2940 newtree = revset.findaliases(ui, tree)
2940 newtree = revset.findaliases(ui, tree)
2941 if newtree != tree:
2941 if newtree != tree:
2942 ui.note(revset.prettyformat(newtree), "\n")
2942 ui.note(revset.prettyformat(newtree), "\n")
2943 tree = newtree
2943 tree = newtree
2944 newtree = revset.foldconcat(tree)
2944 newtree = revset.foldconcat(tree)
2945 if newtree != tree:
2945 if newtree != tree:
2946 ui.note(revset.prettyformat(newtree), "\n")
2946 ui.note(revset.prettyformat(newtree), "\n")
2947 if opts["optimize"]:
2947 if opts["optimize"]:
2948 weight, optimizedtree = revset.optimize(newtree, True)
2948 weight, optimizedtree = revset.optimize(newtree, True)
2949 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2949 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2950 func = revset.match(ui, expr)
2950 func = revset.match(ui, expr)
2951 revs = func(repo)
2951 revs = func(repo)
2952 if ui.verbose:
2952 if ui.verbose:
2953 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2953 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2954 for c in revs:
2954 for c in revs:
2955 ui.write("%s\n" % c)
2955 ui.write("%s\n" % c)
2956
2956
2957 @command('debugsetparents', [], _('REV1 [REV2]'))
2957 @command('debugsetparents', [], _('REV1 [REV2]'))
2958 def debugsetparents(ui, repo, rev1, rev2=None):
2958 def debugsetparents(ui, repo, rev1, rev2=None):
2959 """manually set the parents of the current working directory
2959 """manually set the parents of the current working directory
2960
2960
2961 This is useful for writing repository conversion tools, but should
2961 This is useful for writing repository conversion tools, but should
2962 be used with care. For example, neither the working directory nor the
2962 be used with care. For example, neither the working directory nor the
2963 dirstate is updated, so file status may be incorrect after running this
2963 dirstate is updated, so file status may be incorrect after running this
2964 command.
2964 command.
2965
2965
2966 Returns 0 on success.
2966 Returns 0 on success.
2967 """
2967 """
2968
2968
2969 r1 = scmutil.revsingle(repo, rev1).node()
2969 r1 = scmutil.revsingle(repo, rev1).node()
2970 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2970 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2971
2971
2972 wlock = repo.wlock()
2972 wlock = repo.wlock()
2973 try:
2973 try:
2974 repo.dirstate.beginparentchange()
2974 repo.dirstate.beginparentchange()
2975 repo.setparents(r1, r2)
2975 repo.setparents(r1, r2)
2976 repo.dirstate.endparentchange()
2976 repo.dirstate.endparentchange()
2977 finally:
2977 finally:
2978 wlock.release()
2978 wlock.release()
2979
2979
2980 @command('debugdirstate|debugstate',
2980 @command('debugdirstate|debugstate',
2981 [('', 'nodates', None, _('do not display the saved mtime')),
2981 [('', 'nodates', None, _('do not display the saved mtime')),
2982 ('', 'datesort', None, _('sort by saved mtime'))],
2982 ('', 'datesort', None, _('sort by saved mtime'))],
2983 _('[OPTION]...'))
2983 _('[OPTION]...'))
2984 def debugstate(ui, repo, nodates=None, datesort=None):
2984 def debugstate(ui, repo, nodates=None, datesort=None):
2985 """show the contents of the current dirstate"""
2985 """show the contents of the current dirstate"""
2986 timestr = ""
2986 timestr = ""
2987 if datesort:
2987 if datesort:
2988 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2988 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2989 else:
2989 else:
2990 keyfunc = None # sort by filename
2990 keyfunc = None # sort by filename
2991 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2991 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2992 if ent[3] == -1:
2992 if ent[3] == -1:
2993 timestr = 'unset '
2993 timestr = 'unset '
2994 elif nodates:
2994 elif nodates:
2995 timestr = 'set '
2995 timestr = 'set '
2996 else:
2996 else:
2997 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2997 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2998 time.localtime(ent[3]))
2998 time.localtime(ent[3]))
2999 if ent[1] & 020000:
2999 if ent[1] & 020000:
3000 mode = 'lnk'
3000 mode = 'lnk'
3001 else:
3001 else:
3002 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
3002 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
3003 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3003 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3004 for f in repo.dirstate.copies():
3004 for f in repo.dirstate.copies():
3005 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3005 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3006
3006
3007 @command('debugsub',
3007 @command('debugsub',
3008 [('r', 'rev', '',
3008 [('r', 'rev', '',
3009 _('revision to check'), _('REV'))],
3009 _('revision to check'), _('REV'))],
3010 _('[-r REV] [REV]'))
3010 _('[-r REV] [REV]'))
3011 def debugsub(ui, repo, rev=None):
3011 def debugsub(ui, repo, rev=None):
3012 ctx = scmutil.revsingle(repo, rev, None)
3012 ctx = scmutil.revsingle(repo, rev, None)
3013 for k, v in sorted(ctx.substate.items()):
3013 for k, v in sorted(ctx.substate.items()):
3014 ui.write(('path %s\n') % k)
3014 ui.write(('path %s\n') % k)
3015 ui.write((' source %s\n') % v[0])
3015 ui.write((' source %s\n') % v[0])
3016 ui.write((' revision %s\n') % v[1])
3016 ui.write((' revision %s\n') % v[1])
3017
3017
3018 @command('debugsuccessorssets',
3018 @command('debugsuccessorssets',
3019 [],
3019 [],
3020 _('[REV]'))
3020 _('[REV]'))
3021 def debugsuccessorssets(ui, repo, *revs):
3021 def debugsuccessorssets(ui, repo, *revs):
3022 """show set of successors for revision
3022 """show set of successors for revision
3023
3023
3024 A successors set of changeset A is a consistent group of revisions that
3024 A successors set of changeset A is a consistent group of revisions that
3025 succeed A. It contains non-obsolete changesets only.
3025 succeed A. It contains non-obsolete changesets only.
3026
3026
3027 In most cases a changeset A has a single successors set containing a single
3027 In most cases a changeset A has a single successors set containing a single
3028 successor (changeset A replaced by A').
3028 successor (changeset A replaced by A').
3029
3029
3030 A changeset that is made obsolete with no successors are called "pruned".
3030 A changeset that is made obsolete with no successors are called "pruned".
3031 Such changesets have no successors sets at all.
3031 Such changesets have no successors sets at all.
3032
3032
3033 A changeset that has been "split" will have a successors set containing
3033 A changeset that has been "split" will have a successors set containing
3034 more than one successor.
3034 more than one successor.
3035
3035
3036 A changeset that has been rewritten in multiple different ways is called
3036 A changeset that has been rewritten in multiple different ways is called
3037 "divergent". Such changesets have multiple successor sets (each of which
3037 "divergent". Such changesets have multiple successor sets (each of which
3038 may also be split, i.e. have multiple successors).
3038 may also be split, i.e. have multiple successors).
3039
3039
3040 Results are displayed as follows::
3040 Results are displayed as follows::
3041
3041
3042 <rev1>
3042 <rev1>
3043 <successors-1A>
3043 <successors-1A>
3044 <rev2>
3044 <rev2>
3045 <successors-2A>
3045 <successors-2A>
3046 <successors-2B1> <successors-2B2> <successors-2B3>
3046 <successors-2B1> <successors-2B2> <successors-2B3>
3047
3047
3048 Here rev2 has two possible (i.e. divergent) successors sets. The first
3048 Here rev2 has two possible (i.e. divergent) successors sets. The first
3049 holds one element, whereas the second holds three (i.e. the changeset has
3049 holds one element, whereas the second holds three (i.e. the changeset has
3050 been split).
3050 been split).
3051 """
3051 """
3052 # passed to successorssets caching computation from one call to another
3052 # passed to successorssets caching computation from one call to another
3053 cache = {}
3053 cache = {}
3054 ctx2str = str
3054 ctx2str = str
3055 node2str = short
3055 node2str = short
3056 if ui.debug():
3056 if ui.debug():
3057 def ctx2str(ctx):
3057 def ctx2str(ctx):
3058 return ctx.hex()
3058 return ctx.hex()
3059 node2str = hex
3059 node2str = hex
3060 for rev in scmutil.revrange(repo, revs):
3060 for rev in scmutil.revrange(repo, revs):
3061 ctx = repo[rev]
3061 ctx = repo[rev]
3062 ui.write('%s\n'% ctx2str(ctx))
3062 ui.write('%s\n'% ctx2str(ctx))
3063 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3063 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3064 if succsset:
3064 if succsset:
3065 ui.write(' ')
3065 ui.write(' ')
3066 ui.write(node2str(succsset[0]))
3066 ui.write(node2str(succsset[0]))
3067 for node in succsset[1:]:
3067 for node in succsset[1:]:
3068 ui.write(' ')
3068 ui.write(' ')
3069 ui.write(node2str(node))
3069 ui.write(node2str(node))
3070 ui.write('\n')
3070 ui.write('\n')
3071
3071
3072 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3072 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3073 def debugwalk(ui, repo, *pats, **opts):
3073 def debugwalk(ui, repo, *pats, **opts):
3074 """show how files match on given patterns"""
3074 """show how files match on given patterns"""
3075 m = scmutil.match(repo[None], pats, opts)
3075 m = scmutil.match(repo[None], pats, opts)
3076 items = list(repo.walk(m))
3076 items = list(repo.walk(m))
3077 if not items:
3077 if not items:
3078 return
3078 return
3079 f = lambda fn: fn
3079 f = lambda fn: fn
3080 if ui.configbool('ui', 'slash') and os.sep != '/':
3080 if ui.configbool('ui', 'slash') and os.sep != '/':
3081 f = lambda fn: util.normpath(fn)
3081 f = lambda fn: util.normpath(fn)
3082 fmt = 'f %%-%ds %%-%ds %%s' % (
3082 fmt = 'f %%-%ds %%-%ds %%s' % (
3083 max([len(abs) for abs in items]),
3083 max([len(abs) for abs in items]),
3084 max([len(m.rel(abs)) for abs in items]))
3084 max([len(m.rel(abs)) for abs in items]))
3085 for abs in items:
3085 for abs in items:
3086 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3086 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3087 ui.write("%s\n" % line.rstrip())
3087 ui.write("%s\n" % line.rstrip())
3088
3088
3089 @command('debugwireargs',
3089 @command('debugwireargs',
3090 [('', 'three', '', 'three'),
3090 [('', 'three', '', 'three'),
3091 ('', 'four', '', 'four'),
3091 ('', 'four', '', 'four'),
3092 ('', 'five', '', 'five'),
3092 ('', 'five', '', 'five'),
3093 ] + remoteopts,
3093 ] + remoteopts,
3094 _('REPO [OPTIONS]... [ONE [TWO]]'),
3094 _('REPO [OPTIONS]... [ONE [TWO]]'),
3095 norepo=True)
3095 norepo=True)
3096 def debugwireargs(ui, repopath, *vals, **opts):
3096 def debugwireargs(ui, repopath, *vals, **opts):
3097 repo = hg.peer(ui, opts, repopath)
3097 repo = hg.peer(ui, opts, repopath)
3098 for opt in remoteopts:
3098 for opt in remoteopts:
3099 del opts[opt[1]]
3099 del opts[opt[1]]
3100 args = {}
3100 args = {}
3101 for k, v in opts.iteritems():
3101 for k, v in opts.iteritems():
3102 if v:
3102 if v:
3103 args[k] = v
3103 args[k] = v
3104 # run twice to check that we don't mess up the stream for the next command
3104 # run twice to check that we don't mess up the stream for the next command
3105 res1 = repo.debugwireargs(*vals, **args)
3105 res1 = repo.debugwireargs(*vals, **args)
3106 res2 = repo.debugwireargs(*vals, **args)
3106 res2 = repo.debugwireargs(*vals, **args)
3107 ui.write("%s\n" % res1)
3107 ui.write("%s\n" % res1)
3108 if res1 != res2:
3108 if res1 != res2:
3109 ui.warn("%s\n" % res2)
3109 ui.warn("%s\n" % res2)
3110
3110
3111 @command('^diff',
3111 @command('^diff',
3112 [('r', 'rev', [], _('revision'), _('REV')),
3112 [('r', 'rev', [], _('revision'), _('REV')),
3113 ('c', 'change', '', _('change made by revision'), _('REV'))
3113 ('c', 'change', '', _('change made by revision'), _('REV'))
3114 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3114 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3115 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3115 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3116 inferrepo=True)
3116 inferrepo=True)
3117 def diff(ui, repo, *pats, **opts):
3117 def diff(ui, repo, *pats, **opts):
3118 """diff repository (or selected files)
3118 """diff repository (or selected files)
3119
3119
3120 Show differences between revisions for the specified files.
3120 Show differences between revisions for the specified files.
3121
3121
3122 Differences between files are shown using the unified diff format.
3122 Differences between files are shown using the unified diff format.
3123
3123
3124 .. note::
3124 .. note::
3125
3125
3126 diff may generate unexpected results for merges, as it will
3126 diff may generate unexpected results for merges, as it will
3127 default to comparing against the working directory's first
3127 default to comparing against the working directory's first
3128 parent changeset if no revisions are specified.
3128 parent changeset if no revisions are specified.
3129
3129
3130 When two revision arguments are given, then changes are shown
3130 When two revision arguments are given, then changes are shown
3131 between those revisions. If only one revision is specified then
3131 between those revisions. If only one revision is specified then
3132 that revision is compared to the working directory, and, when no
3132 that revision is compared to the working directory, and, when no
3133 revisions are specified, the working directory files are compared
3133 revisions are specified, the working directory files are compared
3134 to its parent.
3134 to its parent.
3135
3135
3136 Alternatively you can specify -c/--change with a revision to see
3136 Alternatively you can specify -c/--change with a revision to see
3137 the changes in that changeset relative to its first parent.
3137 the changes in that changeset relative to its first parent.
3138
3138
3139 Without the -a/--text option, diff will avoid generating diffs of
3139 Without the -a/--text option, diff will avoid generating diffs of
3140 files it detects as binary. With -a, diff will generate a diff
3140 files it detects as binary. With -a, diff will generate a diff
3141 anyway, probably with undesirable results.
3141 anyway, probably with undesirable results.
3142
3142
3143 Use the -g/--git option to generate diffs in the git extended diff
3143 Use the -g/--git option to generate diffs in the git extended diff
3144 format. For more information, read :hg:`help diffs`.
3144 format. For more information, read :hg:`help diffs`.
3145
3145
3146 .. container:: verbose
3146 .. container:: verbose
3147
3147
3148 Examples:
3148 Examples:
3149
3149
3150 - compare a file in the current working directory to its parent::
3150 - compare a file in the current working directory to its parent::
3151
3151
3152 hg diff foo.c
3152 hg diff foo.c
3153
3153
3154 - compare two historical versions of a directory, with rename info::
3154 - compare two historical versions of a directory, with rename info::
3155
3155
3156 hg diff --git -r 1.0:1.2 lib/
3156 hg diff --git -r 1.0:1.2 lib/
3157
3157
3158 - get change stats relative to the last change on some date::
3158 - get change stats relative to the last change on some date::
3159
3159
3160 hg diff --stat -r "date('may 2')"
3160 hg diff --stat -r "date('may 2')"
3161
3161
3162 - diff all newly-added files that contain a keyword::
3162 - diff all newly-added files that contain a keyword::
3163
3163
3164 hg diff "set:added() and grep(GNU)"
3164 hg diff "set:added() and grep(GNU)"
3165
3165
3166 - compare a revision and its parents::
3166 - compare a revision and its parents::
3167
3167
3168 hg diff -c 9353 # compare against first parent
3168 hg diff -c 9353 # compare against first parent
3169 hg diff -r 9353^:9353 # same using revset syntax
3169 hg diff -r 9353^:9353 # same using revset syntax
3170 hg diff -r 9353^2:9353 # compare against the second parent
3170 hg diff -r 9353^2:9353 # compare against the second parent
3171
3171
3172 Returns 0 on success.
3172 Returns 0 on success.
3173 """
3173 """
3174
3174
3175 revs = opts.get('rev')
3175 revs = opts.get('rev')
3176 change = opts.get('change')
3176 change = opts.get('change')
3177 stat = opts.get('stat')
3177 stat = opts.get('stat')
3178 reverse = opts.get('reverse')
3178 reverse = opts.get('reverse')
3179
3179
3180 if revs and change:
3180 if revs and change:
3181 msg = _('cannot specify --rev and --change at the same time')
3181 msg = _('cannot specify --rev and --change at the same time')
3182 raise util.Abort(msg)
3182 raise util.Abort(msg)
3183 elif change:
3183 elif change:
3184 node2 = scmutil.revsingle(repo, change, None).node()
3184 node2 = scmutil.revsingle(repo, change, None).node()
3185 node1 = repo[node2].p1().node()
3185 node1 = repo[node2].p1().node()
3186 else:
3186 else:
3187 node1, node2 = scmutil.revpair(repo, revs)
3187 node1, node2 = scmutil.revpair(repo, revs)
3188
3188
3189 if reverse:
3189 if reverse:
3190 node1, node2 = node2, node1
3190 node1, node2 = node2, node1
3191
3191
3192 diffopts = patch.diffallopts(ui, opts)
3192 diffopts = patch.diffallopts(ui, opts)
3193 m = scmutil.match(repo[node2], pats, opts)
3193 m = scmutil.match(repo[node2], pats, opts)
3194 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3194 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3195 listsubrepos=opts.get('subrepos'),
3195 listsubrepos=opts.get('subrepos'),
3196 root=opts.get('root'))
3196 root=opts.get('root'))
3197
3197
3198 @command('^export',
3198 @command('^export',
3199 [('o', 'output', '',
3199 [('o', 'output', '',
3200 _('print output to file with formatted name'), _('FORMAT')),
3200 _('print output to file with formatted name'), _('FORMAT')),
3201 ('', 'switch-parent', None, _('diff against the second parent')),
3201 ('', 'switch-parent', None, _('diff against the second parent')),
3202 ('r', 'rev', [], _('revisions to export'), _('REV')),
3202 ('r', 'rev', [], _('revisions to export'), _('REV')),
3203 ] + diffopts,
3203 ] + diffopts,
3204 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3204 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3205 def export(ui, repo, *changesets, **opts):
3205 def export(ui, repo, *changesets, **opts):
3206 """dump the header and diffs for one or more changesets
3206 """dump the header and diffs for one or more changesets
3207
3207
3208 Print the changeset header and diffs for one or more revisions.
3208 Print the changeset header and diffs for one or more revisions.
3209 If no revision is given, the parent of the working directory is used.
3209 If no revision is given, the parent of the working directory is used.
3210
3210
3211 The information shown in the changeset header is: author, date,
3211 The information shown in the changeset header is: author, date,
3212 branch name (if non-default), changeset hash, parent(s) and commit
3212 branch name (if non-default), changeset hash, parent(s) and commit
3213 comment.
3213 comment.
3214
3214
3215 .. note::
3215 .. note::
3216
3216
3217 export may generate unexpected diff output for merge
3217 export may generate unexpected diff output for merge
3218 changesets, as it will compare the merge changeset against its
3218 changesets, as it will compare the merge changeset against its
3219 first parent only.
3219 first parent only.
3220
3220
3221 Output may be to a file, in which case the name of the file is
3221 Output may be to a file, in which case the name of the file is
3222 given using a format string. The formatting rules are as follows:
3222 given using a format string. The formatting rules are as follows:
3223
3223
3224 :``%%``: literal "%" character
3224 :``%%``: literal "%" character
3225 :``%H``: changeset hash (40 hexadecimal digits)
3225 :``%H``: changeset hash (40 hexadecimal digits)
3226 :``%N``: number of patches being generated
3226 :``%N``: number of patches being generated
3227 :``%R``: changeset revision number
3227 :``%R``: changeset revision number
3228 :``%b``: basename of the exporting repository
3228 :``%b``: basename of the exporting repository
3229 :``%h``: short-form changeset hash (12 hexadecimal digits)
3229 :``%h``: short-form changeset hash (12 hexadecimal digits)
3230 :``%m``: first line of the commit message (only alphanumeric characters)
3230 :``%m``: first line of the commit message (only alphanumeric characters)
3231 :``%n``: zero-padded sequence number, starting at 1
3231 :``%n``: zero-padded sequence number, starting at 1
3232 :``%r``: zero-padded changeset revision number
3232 :``%r``: zero-padded changeset revision number
3233
3233
3234 Without the -a/--text option, export will avoid generating diffs
3234 Without the -a/--text option, export will avoid generating diffs
3235 of files it detects as binary. With -a, export will generate a
3235 of files it detects as binary. With -a, export will generate a
3236 diff anyway, probably with undesirable results.
3236 diff anyway, probably with undesirable results.
3237
3237
3238 Use the -g/--git option to generate diffs in the git extended diff
3238 Use the -g/--git option to generate diffs in the git extended diff
3239 format. See :hg:`help diffs` for more information.
3239 format. See :hg:`help diffs` for more information.
3240
3240
3241 With the --switch-parent option, the diff will be against the
3241 With the --switch-parent option, the diff will be against the
3242 second parent. It can be useful to review a merge.
3242 second parent. It can be useful to review a merge.
3243
3243
3244 .. container:: verbose
3244 .. container:: verbose
3245
3245
3246 Examples:
3246 Examples:
3247
3247
3248 - use export and import to transplant a bugfix to the current
3248 - use export and import to transplant a bugfix to the current
3249 branch::
3249 branch::
3250
3250
3251 hg export -r 9353 | hg import -
3251 hg export -r 9353 | hg import -
3252
3252
3253 - export all the changesets between two revisions to a file with
3253 - export all the changesets between two revisions to a file with
3254 rename information::
3254 rename information::
3255
3255
3256 hg export --git -r 123:150 > changes.txt
3256 hg export --git -r 123:150 > changes.txt
3257
3257
3258 - split outgoing changes into a series of patches with
3258 - split outgoing changes into a series of patches with
3259 descriptive names::
3259 descriptive names::
3260
3260
3261 hg export -r "outgoing()" -o "%n-%m.patch"
3261 hg export -r "outgoing()" -o "%n-%m.patch"
3262
3262
3263 Returns 0 on success.
3263 Returns 0 on success.
3264 """
3264 """
3265 changesets += tuple(opts.get('rev', []))
3265 changesets += tuple(opts.get('rev', []))
3266 if not changesets:
3266 if not changesets:
3267 changesets = ['.']
3267 changesets = ['.']
3268 revs = scmutil.revrange(repo, changesets)
3268 revs = scmutil.revrange(repo, changesets)
3269 if not revs:
3269 if not revs:
3270 raise util.Abort(_("export requires at least one changeset"))
3270 raise util.Abort(_("export requires at least one changeset"))
3271 if len(revs) > 1:
3271 if len(revs) > 1:
3272 ui.note(_('exporting patches:\n'))
3272 ui.note(_('exporting patches:\n'))
3273 else:
3273 else:
3274 ui.note(_('exporting patch:\n'))
3274 ui.note(_('exporting patch:\n'))
3275 cmdutil.export(repo, revs, template=opts.get('output'),
3275 cmdutil.export(repo, revs, template=opts.get('output'),
3276 switch_parent=opts.get('switch_parent'),
3276 switch_parent=opts.get('switch_parent'),
3277 opts=patch.diffallopts(ui, opts))
3277 opts=patch.diffallopts(ui, opts))
3278
3278
3279 @command('files',
3279 @command('files',
3280 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3280 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3281 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3281 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3282 ] + walkopts + formatteropts + subrepoopts,
3282 ] + walkopts + formatteropts + subrepoopts,
3283 _('[OPTION]... [PATTERN]...'))
3283 _('[OPTION]... [PATTERN]...'))
3284 def files(ui, repo, *pats, **opts):
3284 def files(ui, repo, *pats, **opts):
3285 """list tracked files
3285 """list tracked files
3286
3286
3287 Print files under Mercurial control in the working directory or
3287 Print files under Mercurial control in the working directory or
3288 specified revision whose names match the given patterns (excluding
3288 specified revision whose names match the given patterns (excluding
3289 removed files).
3289 removed files).
3290
3290
3291 If no patterns are given to match, this command prints the names
3291 If no patterns are given to match, this command prints the names
3292 of all files under Mercurial control in the working directory.
3292 of all files under Mercurial control in the working directory.
3293
3293
3294 .. container:: verbose
3294 .. container:: verbose
3295
3295
3296 Examples:
3296 Examples:
3297
3297
3298 - list all files under the current directory::
3298 - list all files under the current directory::
3299
3299
3300 hg files .
3300 hg files .
3301
3301
3302 - shows sizes and flags for current revision::
3302 - shows sizes and flags for current revision::
3303
3303
3304 hg files -vr .
3304 hg files -vr .
3305
3305
3306 - list all files named README::
3306 - list all files named README::
3307
3307
3308 hg files -I "**/README"
3308 hg files -I "**/README"
3309
3309
3310 - list all binary files::
3310 - list all binary files::
3311
3311
3312 hg files "set:binary()"
3312 hg files "set:binary()"
3313
3313
3314 - find files containing a regular expression::
3314 - find files containing a regular expression::
3315
3315
3316 hg files "set:grep('bob')"
3316 hg files "set:grep('bob')"
3317
3317
3318 - search tracked file contents with xargs and grep::
3318 - search tracked file contents with xargs and grep::
3319
3319
3320 hg files -0 | xargs -0 grep foo
3320 hg files -0 | xargs -0 grep foo
3321
3321
3322 See :hg:`help patterns` and :hg:`help filesets` for more information
3322 See :hg:`help patterns` and :hg:`help filesets` for more information
3323 on specifying file patterns.
3323 on specifying file patterns.
3324
3324
3325 Returns 0 if a match is found, 1 otherwise.
3325 Returns 0 if a match is found, 1 otherwise.
3326
3326
3327 """
3327 """
3328 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3328 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3329
3329
3330 end = '\n'
3330 end = '\n'
3331 if opts.get('print0'):
3331 if opts.get('print0'):
3332 end = '\0'
3332 end = '\0'
3333 fm = ui.formatter('files', opts)
3333 fm = ui.formatter('files', opts)
3334 fmt = '%s' + end
3334 fmt = '%s' + end
3335
3335
3336 m = scmutil.match(ctx, pats, opts)
3336 m = scmutil.match(ctx, pats, opts)
3337 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3337 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3338
3338
3339 fm.end()
3339 fm.end()
3340
3340
3341 return ret
3341 return ret
3342
3342
3343 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3343 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3344 def forget(ui, repo, *pats, **opts):
3344 def forget(ui, repo, *pats, **opts):
3345 """forget the specified files on the next commit
3345 """forget the specified files on the next commit
3346
3346
3347 Mark the specified files so they will no longer be tracked
3347 Mark the specified files so they will no longer be tracked
3348 after the next commit.
3348 after the next commit.
3349
3349
3350 This only removes files from the current branch, not from the
3350 This only removes files from the current branch, not from the
3351 entire project history, and it does not delete them from the
3351 entire project history, and it does not delete them from the
3352 working directory.
3352 working directory.
3353
3353
3354 To undo a forget before the next commit, see :hg:`add`.
3354 To undo a forget before the next commit, see :hg:`add`.
3355
3355
3356 .. container:: verbose
3356 .. container:: verbose
3357
3357
3358 Examples:
3358 Examples:
3359
3359
3360 - forget newly-added binary files::
3360 - forget newly-added binary files::
3361
3361
3362 hg forget "set:added() and binary()"
3362 hg forget "set:added() and binary()"
3363
3363
3364 - forget files that would be excluded by .hgignore::
3364 - forget files that would be excluded by .hgignore::
3365
3365
3366 hg forget "set:hgignore()"
3366 hg forget "set:hgignore()"
3367
3367
3368 Returns 0 on success.
3368 Returns 0 on success.
3369 """
3369 """
3370
3370
3371 if not pats:
3371 if not pats:
3372 raise util.Abort(_('no files specified'))
3372 raise util.Abort(_('no files specified'))
3373
3373
3374 m = scmutil.match(repo[None], pats, opts)
3374 m = scmutil.match(repo[None], pats, opts)
3375 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3375 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3376 return rejected and 1 or 0
3376 return rejected and 1 or 0
3377
3377
3378 @command(
3378 @command(
3379 'graft',
3379 'graft',
3380 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3380 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3381 ('c', 'continue', False, _('resume interrupted graft')),
3381 ('c', 'continue', False, _('resume interrupted graft')),
3382 ('e', 'edit', False, _('invoke editor on commit messages')),
3382 ('e', 'edit', False, _('invoke editor on commit messages')),
3383 ('', 'log', None, _('append graft info to log message')),
3383 ('', 'log', None, _('append graft info to log message')),
3384 ('f', 'force', False, _('force graft')),
3384 ('f', 'force', False, _('force graft')),
3385 ('D', 'currentdate', False,
3385 ('D', 'currentdate', False,
3386 _('record the current date as commit date')),
3386 _('record the current date as commit date')),
3387 ('U', 'currentuser', False,
3387 ('U', 'currentuser', False,
3388 _('record the current user as committer'), _('DATE'))]
3388 _('record the current user as committer'), _('DATE'))]
3389 + commitopts2 + mergetoolopts + dryrunopts,
3389 + commitopts2 + mergetoolopts + dryrunopts,
3390 _('[OPTION]... [-r] REV...'))
3390 _('[OPTION]... [-r] REV...'))
3391 def graft(ui, repo, *revs, **opts):
3391 def graft(ui, repo, *revs, **opts):
3392 '''copy changes from other branches onto the current branch
3392 '''copy changes from other branches onto the current branch
3393
3393
3394 This command uses Mercurial's merge logic to copy individual
3394 This command uses Mercurial's merge logic to copy individual
3395 changes from other branches without merging branches in the
3395 changes from other branches without merging branches in the
3396 history graph. This is sometimes known as 'backporting' or
3396 history graph. This is sometimes known as 'backporting' or
3397 'cherry-picking'. By default, graft will copy user, date, and
3397 'cherry-picking'. By default, graft will copy user, date, and
3398 description from the source changesets.
3398 description from the source changesets.
3399
3399
3400 Changesets that are ancestors of the current revision, that have
3400 Changesets that are ancestors of the current revision, that have
3401 already been grafted, or that are merges will be skipped.
3401 already been grafted, or that are merges will be skipped.
3402
3402
3403 If --log is specified, log messages will have a comment appended
3403 If --log is specified, log messages will have a comment appended
3404 of the form::
3404 of the form::
3405
3405
3406 (grafted from CHANGESETHASH)
3406 (grafted from CHANGESETHASH)
3407
3407
3408 If --force is specified, revisions will be grafted even if they
3408 If --force is specified, revisions will be grafted even if they
3409 are already ancestors of or have been grafted to the destination.
3409 are already ancestors of or have been grafted to the destination.
3410 This is useful when the revisions have since been backed out.
3410 This is useful when the revisions have since been backed out.
3411
3411
3412 If a graft merge results in conflicts, the graft process is
3412 If a graft merge results in conflicts, the graft process is
3413 interrupted so that the current merge can be manually resolved.
3413 interrupted so that the current merge can be manually resolved.
3414 Once all conflicts are addressed, the graft process can be
3414 Once all conflicts are addressed, the graft process can be
3415 continued with the -c/--continue option.
3415 continued with the -c/--continue option.
3416
3416
3417 .. note::
3417 .. note::
3418
3418
3419 The -c/--continue option does not reapply earlier options, except
3419 The -c/--continue option does not reapply earlier options, except
3420 for --force.
3420 for --force.
3421
3421
3422 .. container:: verbose
3422 .. container:: verbose
3423
3423
3424 Examples:
3424 Examples:
3425
3425
3426 - copy a single change to the stable branch and edit its description::
3426 - copy a single change to the stable branch and edit its description::
3427
3427
3428 hg update stable
3428 hg update stable
3429 hg graft --edit 9393
3429 hg graft --edit 9393
3430
3430
3431 - graft a range of changesets with one exception, updating dates::
3431 - graft a range of changesets with one exception, updating dates::
3432
3432
3433 hg graft -D "2085::2093 and not 2091"
3433 hg graft -D "2085::2093 and not 2091"
3434
3434
3435 - continue a graft after resolving conflicts::
3435 - continue a graft after resolving conflicts::
3436
3436
3437 hg graft -c
3437 hg graft -c
3438
3438
3439 - show the source of a grafted changeset::
3439 - show the source of a grafted changeset::
3440
3440
3441 hg log --debug -r .
3441 hg log --debug -r .
3442
3442
3443 See :hg:`help revisions` and :hg:`help revsets` for more about
3443 See :hg:`help revisions` and :hg:`help revsets` for more about
3444 specifying revisions.
3444 specifying revisions.
3445
3445
3446 Returns 0 on successful completion.
3446 Returns 0 on successful completion.
3447 '''
3447 '''
3448
3448
3449 revs = list(revs)
3449 revs = list(revs)
3450 revs.extend(opts['rev'])
3450 revs.extend(opts['rev'])
3451
3451
3452 if not opts.get('user') and opts.get('currentuser'):
3452 if not opts.get('user') and opts.get('currentuser'):
3453 opts['user'] = ui.username()
3453 opts['user'] = ui.username()
3454 if not opts.get('date') and opts.get('currentdate'):
3454 if not opts.get('date') and opts.get('currentdate'):
3455 opts['date'] = "%d %d" % util.makedate()
3455 opts['date'] = "%d %d" % util.makedate()
3456
3456
3457 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3457 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3458
3458
3459 cont = False
3459 cont = False
3460 if opts['continue']:
3460 if opts['continue']:
3461 cont = True
3461 cont = True
3462 if revs:
3462 if revs:
3463 raise util.Abort(_("can't specify --continue and revisions"))
3463 raise util.Abort(_("can't specify --continue and revisions"))
3464 # read in unfinished revisions
3464 # read in unfinished revisions
3465 try:
3465 try:
3466 nodes = repo.vfs.read('graftstate').splitlines()
3466 nodes = repo.vfs.read('graftstate').splitlines()
3467 revs = [repo[node].rev() for node in nodes]
3467 revs = [repo[node].rev() for node in nodes]
3468 except IOError, inst:
3468 except IOError, inst:
3469 if inst.errno != errno.ENOENT:
3469 if inst.errno != errno.ENOENT:
3470 raise
3470 raise
3471 raise util.Abort(_("no graft state found, can't continue"))
3471 raise util.Abort(_("no graft state found, can't continue"))
3472 else:
3472 else:
3473 cmdutil.checkunfinished(repo)
3473 cmdutil.checkunfinished(repo)
3474 cmdutil.bailifchanged(repo)
3474 cmdutil.bailifchanged(repo)
3475 if not revs:
3475 if not revs:
3476 raise util.Abort(_('no revisions specified'))
3476 raise util.Abort(_('no revisions specified'))
3477 revs = scmutil.revrange(repo, revs)
3477 revs = scmutil.revrange(repo, revs)
3478
3478
3479 skipped = set()
3479 skipped = set()
3480 # check for merges
3480 # check for merges
3481 for rev in repo.revs('%ld and merge()', revs):
3481 for rev in repo.revs('%ld and merge()', revs):
3482 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3482 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3483 skipped.add(rev)
3483 skipped.add(rev)
3484 revs = [r for r in revs if r not in skipped]
3484 revs = [r for r in revs if r not in skipped]
3485 if not revs:
3485 if not revs:
3486 return -1
3486 return -1
3487
3487
3488 # Don't check in the --continue case, in effect retaining --force across
3488 # Don't check in the --continue case, in effect retaining --force across
3489 # --continues. That's because without --force, any revisions we decided to
3489 # --continues. That's because without --force, any revisions we decided to
3490 # skip would have been filtered out here, so they wouldn't have made their
3490 # skip would have been filtered out here, so they wouldn't have made their
3491 # way to the graftstate. With --force, any revisions we would have otherwise
3491 # way to the graftstate. With --force, any revisions we would have otherwise
3492 # skipped would not have been filtered out, and if they hadn't been applied
3492 # skipped would not have been filtered out, and if they hadn't been applied
3493 # already, they'd have been in the graftstate.
3493 # already, they'd have been in the graftstate.
3494 if not (cont or opts.get('force')):
3494 if not (cont or opts.get('force')):
3495 # check for ancestors of dest branch
3495 # check for ancestors of dest branch
3496 crev = repo['.'].rev()
3496 crev = repo['.'].rev()
3497 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3497 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3498 # Cannot use x.remove(y) on smart set, this has to be a list.
3498 # Cannot use x.remove(y) on smart set, this has to be a list.
3499 # XXX make this lazy in the future
3499 # XXX make this lazy in the future
3500 revs = list(revs)
3500 revs = list(revs)
3501 # don't mutate while iterating, create a copy
3501 # don't mutate while iterating, create a copy
3502 for rev in list(revs):
3502 for rev in list(revs):
3503 if rev in ancestors:
3503 if rev in ancestors:
3504 ui.warn(_('skipping ancestor revision %d:%s\n') %
3504 ui.warn(_('skipping ancestor revision %d:%s\n') %
3505 (rev, repo[rev]))
3505 (rev, repo[rev]))
3506 # XXX remove on list is slow
3506 # XXX remove on list is slow
3507 revs.remove(rev)
3507 revs.remove(rev)
3508 if not revs:
3508 if not revs:
3509 return -1
3509 return -1
3510
3510
3511 # analyze revs for earlier grafts
3511 # analyze revs for earlier grafts
3512 ids = {}
3512 ids = {}
3513 for ctx in repo.set("%ld", revs):
3513 for ctx in repo.set("%ld", revs):
3514 ids[ctx.hex()] = ctx.rev()
3514 ids[ctx.hex()] = ctx.rev()
3515 n = ctx.extra().get('source')
3515 n = ctx.extra().get('source')
3516 if n:
3516 if n:
3517 ids[n] = ctx.rev()
3517 ids[n] = ctx.rev()
3518
3518
3519 # check ancestors for earlier grafts
3519 # check ancestors for earlier grafts
3520 ui.debug('scanning for duplicate grafts\n')
3520 ui.debug('scanning for duplicate grafts\n')
3521
3521
3522 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3522 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3523 ctx = repo[rev]
3523 ctx = repo[rev]
3524 n = ctx.extra().get('source')
3524 n = ctx.extra().get('source')
3525 if n in ids:
3525 if n in ids:
3526 try:
3526 try:
3527 r = repo[n].rev()
3527 r = repo[n].rev()
3528 except error.RepoLookupError:
3528 except error.RepoLookupError:
3529 r = None
3529 r = None
3530 if r in revs:
3530 if r in revs:
3531 ui.warn(_('skipping revision %d:%s '
3531 ui.warn(_('skipping revision %d:%s '
3532 '(already grafted to %d:%s)\n')
3532 '(already grafted to %d:%s)\n')
3533 % (r, repo[r], rev, ctx))
3533 % (r, repo[r], rev, ctx))
3534 revs.remove(r)
3534 revs.remove(r)
3535 elif ids[n] in revs:
3535 elif ids[n] in revs:
3536 if r is None:
3536 if r is None:
3537 ui.warn(_('skipping already grafted revision %d:%s '
3537 ui.warn(_('skipping already grafted revision %d:%s '
3538 '(%d:%s also has unknown origin %s)\n')
3538 '(%d:%s also has unknown origin %s)\n')
3539 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3539 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3540 else:
3540 else:
3541 ui.warn(_('skipping already grafted revision %d:%s '
3541 ui.warn(_('skipping already grafted revision %d:%s '
3542 '(%d:%s also has origin %d:%s)\n')
3542 '(%d:%s also has origin %d:%s)\n')
3543 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3543 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3544 revs.remove(ids[n])
3544 revs.remove(ids[n])
3545 elif ctx.hex() in ids:
3545 elif ctx.hex() in ids:
3546 r = ids[ctx.hex()]
3546 r = ids[ctx.hex()]
3547 ui.warn(_('skipping already grafted revision %d:%s '
3547 ui.warn(_('skipping already grafted revision %d:%s '
3548 '(was grafted from %d:%s)\n') %
3548 '(was grafted from %d:%s)\n') %
3549 (r, repo[r], rev, ctx))
3549 (r, repo[r], rev, ctx))
3550 revs.remove(r)
3550 revs.remove(r)
3551 if not revs:
3551 if not revs:
3552 return -1
3552 return -1
3553
3553
3554 wlock = repo.wlock()
3554 wlock = repo.wlock()
3555 try:
3555 try:
3556 for pos, ctx in enumerate(repo.set("%ld", revs)):
3556 for pos, ctx in enumerate(repo.set("%ld", revs)):
3557 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3557 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3558 ctx.description().split('\n', 1)[0])
3558 ctx.description().split('\n', 1)[0])
3559 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3559 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3560 if names:
3560 if names:
3561 desc += ' (%s)' % ' '.join(names)
3561 desc += ' (%s)' % ' '.join(names)
3562 ui.status(_('grafting %s\n') % desc)
3562 ui.status(_('grafting %s\n') % desc)
3563 if opts.get('dry_run'):
3563 if opts.get('dry_run'):
3564 continue
3564 continue
3565
3565
3566 source = ctx.extra().get('source')
3566 source = ctx.extra().get('source')
3567 extra = {}
3567 extra = {}
3568 if source:
3568 if source:
3569 extra['source'] = source
3569 extra['source'] = source
3570 extra['intermediate-source'] = ctx.hex()
3570 extra['intermediate-source'] = ctx.hex()
3571 else:
3571 else:
3572 extra['source'] = ctx.hex()
3572 extra['source'] = ctx.hex()
3573 user = ctx.user()
3573 user = ctx.user()
3574 if opts.get('user'):
3574 if opts.get('user'):
3575 user = opts['user']
3575 user = opts['user']
3576 date = ctx.date()
3576 date = ctx.date()
3577 if opts.get('date'):
3577 if opts.get('date'):
3578 date = opts['date']
3578 date = opts['date']
3579 message = ctx.description()
3579 message = ctx.description()
3580 if opts.get('log'):
3580 if opts.get('log'):
3581 message += '\n(grafted from %s)' % ctx.hex()
3581 message += '\n(grafted from %s)' % ctx.hex()
3582
3582
3583 # we don't merge the first commit when continuing
3583 # we don't merge the first commit when continuing
3584 if not cont:
3584 if not cont:
3585 # perform the graft merge with p1(rev) as 'ancestor'
3585 # perform the graft merge with p1(rev) as 'ancestor'
3586 try:
3586 try:
3587 # ui.forcemerge is an internal variable, do not document
3587 # ui.forcemerge is an internal variable, do not document
3588 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3588 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3589 'graft')
3589 'graft')
3590 stats = mergemod.graft(repo, ctx, ctx.p1(),
3590 stats = mergemod.graft(repo, ctx, ctx.p1(),
3591 ['local', 'graft'])
3591 ['local', 'graft'])
3592 finally:
3592 finally:
3593 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3593 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3594 # report any conflicts
3594 # report any conflicts
3595 if stats and stats[3] > 0:
3595 if stats and stats[3] > 0:
3596 # write out state for --continue
3596 # write out state for --continue
3597 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3597 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3598 repo.vfs.write('graftstate', ''.join(nodelines))
3598 repo.vfs.write('graftstate', ''.join(nodelines))
3599 raise util.Abort(
3599 raise util.Abort(
3600 _("unresolved conflicts, can't continue"),
3600 _("unresolved conflicts, can't continue"),
3601 hint=_('use hg resolve and hg graft --continue'))
3601 hint=_('use hg resolve and hg graft --continue'))
3602 else:
3602 else:
3603 cont = False
3603 cont = False
3604
3604
3605 # commit
3605 # commit
3606 node = repo.commit(text=message, user=user,
3606 node = repo.commit(text=message, user=user,
3607 date=date, extra=extra, editor=editor)
3607 date=date, extra=extra, editor=editor)
3608 if node is None:
3608 if node is None:
3609 ui.warn(
3609 ui.warn(
3610 _('note: graft of %d:%s created no changes to commit\n') %
3610 _('note: graft of %d:%s created no changes to commit\n') %
3611 (ctx.rev(), ctx))
3611 (ctx.rev(), ctx))
3612 finally:
3612 finally:
3613 wlock.release()
3613 wlock.release()
3614
3614
3615 # remove state when we complete successfully
3615 # remove state when we complete successfully
3616 if not opts.get('dry_run'):
3616 if not opts.get('dry_run'):
3617 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3617 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3618
3618
3619 return 0
3619 return 0
3620
3620
3621 @command('grep',
3621 @command('grep',
3622 [('0', 'print0', None, _('end fields with NUL')),
3622 [('0', 'print0', None, _('end fields with NUL')),
3623 ('', 'all', None, _('print all revisions that match')),
3623 ('', 'all', None, _('print all revisions that match')),
3624 ('a', 'text', None, _('treat all files as text')),
3624 ('a', 'text', None, _('treat all files as text')),
3625 ('f', 'follow', None,
3625 ('f', 'follow', None,
3626 _('follow changeset history,'
3626 _('follow changeset history,'
3627 ' or file history across copies and renames')),
3627 ' or file history across copies and renames')),
3628 ('i', 'ignore-case', None, _('ignore case when matching')),
3628 ('i', 'ignore-case', None, _('ignore case when matching')),
3629 ('l', 'files-with-matches', None,
3629 ('l', 'files-with-matches', None,
3630 _('print only filenames and revisions that match')),
3630 _('print only filenames and revisions that match')),
3631 ('n', 'line-number', None, _('print matching line numbers')),
3631 ('n', 'line-number', None, _('print matching line numbers')),
3632 ('r', 'rev', [],
3632 ('r', 'rev', [],
3633 _('only search files changed within revision range'), _('REV')),
3633 _('only search files changed within revision range'), _('REV')),
3634 ('u', 'user', None, _('list the author (long with -v)')),
3634 ('u', 'user', None, _('list the author (long with -v)')),
3635 ('d', 'date', None, _('list the date (short with -q)')),
3635 ('d', 'date', None, _('list the date (short with -q)')),
3636 ] + walkopts,
3636 ] + walkopts,
3637 _('[OPTION]... PATTERN [FILE]...'),
3637 _('[OPTION]... PATTERN [FILE]...'),
3638 inferrepo=True)
3638 inferrepo=True)
3639 def grep(ui, repo, pattern, *pats, **opts):
3639 def grep(ui, repo, pattern, *pats, **opts):
3640 """search for a pattern in specified files and revisions
3640 """search for a pattern in specified files and revisions
3641
3641
3642 Search revisions of files for a regular expression.
3642 Search revisions of files for a regular expression.
3643
3643
3644 This command behaves differently than Unix grep. It only accepts
3644 This command behaves differently than Unix grep. It only accepts
3645 Python/Perl regexps. It searches repository history, not the
3645 Python/Perl regexps. It searches repository history, not the
3646 working directory. It always prints the revision number in which a
3646 working directory. It always prints the revision number in which a
3647 match appears.
3647 match appears.
3648
3648
3649 By default, grep only prints output for the first revision of a
3649 By default, grep only prints output for the first revision of a
3650 file in which it finds a match. To get it to print every revision
3650 file in which it finds a match. To get it to print every revision
3651 that contains a change in match status ("-" for a match that
3651 that contains a change in match status ("-" for a match that
3652 becomes a non-match, or "+" for a non-match that becomes a match),
3652 becomes a non-match, or "+" for a non-match that becomes a match),
3653 use the --all flag.
3653 use the --all flag.
3654
3654
3655 Returns 0 if a match is found, 1 otherwise.
3655 Returns 0 if a match is found, 1 otherwise.
3656 """
3656 """
3657 reflags = re.M
3657 reflags = re.M
3658 if opts.get('ignore_case'):
3658 if opts.get('ignore_case'):
3659 reflags |= re.I
3659 reflags |= re.I
3660 try:
3660 try:
3661 regexp = util.re.compile(pattern, reflags)
3661 regexp = util.re.compile(pattern, reflags)
3662 except re.error, inst:
3662 except re.error, inst:
3663 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3663 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3664 return 1
3664 return 1
3665 sep, eol = ':', '\n'
3665 sep, eol = ':', '\n'
3666 if opts.get('print0'):
3666 if opts.get('print0'):
3667 sep = eol = '\0'
3667 sep = eol = '\0'
3668
3668
3669 getfile = util.lrucachefunc(repo.file)
3669 getfile = util.lrucachefunc(repo.file)
3670
3670
3671 def matchlines(body):
3671 def matchlines(body):
3672 begin = 0
3672 begin = 0
3673 linenum = 0
3673 linenum = 0
3674 while begin < len(body):
3674 while begin < len(body):
3675 match = regexp.search(body, begin)
3675 match = regexp.search(body, begin)
3676 if not match:
3676 if not match:
3677 break
3677 break
3678 mstart, mend = match.span()
3678 mstart, mend = match.span()
3679 linenum += body.count('\n', begin, mstart) + 1
3679 linenum += body.count('\n', begin, mstart) + 1
3680 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3680 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3681 begin = body.find('\n', mend) + 1 or len(body) + 1
3681 begin = body.find('\n', mend) + 1 or len(body) + 1
3682 lend = begin - 1
3682 lend = begin - 1
3683 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3683 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3684
3684
3685 class linestate(object):
3685 class linestate(object):
3686 def __init__(self, line, linenum, colstart, colend):
3686 def __init__(self, line, linenum, colstart, colend):
3687 self.line = line
3687 self.line = line
3688 self.linenum = linenum
3688 self.linenum = linenum
3689 self.colstart = colstart
3689 self.colstart = colstart
3690 self.colend = colend
3690 self.colend = colend
3691
3691
3692 def __hash__(self):
3692 def __hash__(self):
3693 return hash((self.linenum, self.line))
3693 return hash((self.linenum, self.line))
3694
3694
3695 def __eq__(self, other):
3695 def __eq__(self, other):
3696 return self.line == other.line
3696 return self.line == other.line
3697
3697
3698 def __iter__(self):
3698 def __iter__(self):
3699 yield (self.line[:self.colstart], '')
3699 yield (self.line[:self.colstart], '')
3700 yield (self.line[self.colstart:self.colend], 'grep.match')
3700 yield (self.line[self.colstart:self.colend], 'grep.match')
3701 rest = self.line[self.colend:]
3701 rest = self.line[self.colend:]
3702 while rest != '':
3702 while rest != '':
3703 match = regexp.search(rest)
3703 match = regexp.search(rest)
3704 if not match:
3704 if not match:
3705 yield (rest, '')
3705 yield (rest, '')
3706 break
3706 break
3707 mstart, mend = match.span()
3707 mstart, mend = match.span()
3708 yield (rest[:mstart], '')
3708 yield (rest[:mstart], '')
3709 yield (rest[mstart:mend], 'grep.match')
3709 yield (rest[mstart:mend], 'grep.match')
3710 rest = rest[mend:]
3710 rest = rest[mend:]
3711
3711
3712 matches = {}
3712 matches = {}
3713 copies = {}
3713 copies = {}
3714 def grepbody(fn, rev, body):
3714 def grepbody(fn, rev, body):
3715 matches[rev].setdefault(fn, [])
3715 matches[rev].setdefault(fn, [])
3716 m = matches[rev][fn]
3716 m = matches[rev][fn]
3717 for lnum, cstart, cend, line in matchlines(body):
3717 for lnum, cstart, cend, line in matchlines(body):
3718 s = linestate(line, lnum, cstart, cend)
3718 s = linestate(line, lnum, cstart, cend)
3719 m.append(s)
3719 m.append(s)
3720
3720
3721 def difflinestates(a, b):
3721 def difflinestates(a, b):
3722 sm = difflib.SequenceMatcher(None, a, b)
3722 sm = difflib.SequenceMatcher(None, a, b)
3723 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3723 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3724 if tag == 'insert':
3724 if tag == 'insert':
3725 for i in xrange(blo, bhi):
3725 for i in xrange(blo, bhi):
3726 yield ('+', b[i])
3726 yield ('+', b[i])
3727 elif tag == 'delete':
3727 elif tag == 'delete':
3728 for i in xrange(alo, ahi):
3728 for i in xrange(alo, ahi):
3729 yield ('-', a[i])
3729 yield ('-', a[i])
3730 elif tag == 'replace':
3730 elif tag == 'replace':
3731 for i in xrange(alo, ahi):
3731 for i in xrange(alo, ahi):
3732 yield ('-', a[i])
3732 yield ('-', a[i])
3733 for i in xrange(blo, bhi):
3733 for i in xrange(blo, bhi):
3734 yield ('+', b[i])
3734 yield ('+', b[i])
3735
3735
3736 def display(fn, ctx, pstates, states):
3736 def display(fn, ctx, pstates, states):
3737 rev = ctx.rev()
3737 rev = ctx.rev()
3738 if ui.quiet:
3738 if ui.quiet:
3739 datefunc = util.shortdate
3739 datefunc = util.shortdate
3740 else:
3740 else:
3741 datefunc = util.datestr
3741 datefunc = util.datestr
3742 found = False
3742 found = False
3743 @util.cachefunc
3743 @util.cachefunc
3744 def binary():
3744 def binary():
3745 flog = getfile(fn)
3745 flog = getfile(fn)
3746 return util.binary(flog.read(ctx.filenode(fn)))
3746 return util.binary(flog.read(ctx.filenode(fn)))
3747
3747
3748 if opts.get('all'):
3748 if opts.get('all'):
3749 iter = difflinestates(pstates, states)
3749 iter = difflinestates(pstates, states)
3750 else:
3750 else:
3751 iter = [('', l) for l in states]
3751 iter = [('', l) for l in states]
3752 for change, l in iter:
3752 for change, l in iter:
3753 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3753 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3754
3754
3755 if opts.get('line_number'):
3755 if opts.get('line_number'):
3756 cols.append((str(l.linenum), 'grep.linenumber'))
3756 cols.append((str(l.linenum), 'grep.linenumber'))
3757 if opts.get('all'):
3757 if opts.get('all'):
3758 cols.append((change, 'grep.change'))
3758 cols.append((change, 'grep.change'))
3759 if opts.get('user'):
3759 if opts.get('user'):
3760 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3760 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3761 if opts.get('date'):
3761 if opts.get('date'):
3762 cols.append((datefunc(ctx.date()), 'grep.date'))
3762 cols.append((datefunc(ctx.date()), 'grep.date'))
3763 for col, label in cols[:-1]:
3763 for col, label in cols[:-1]:
3764 ui.write(col, label=label)
3764 ui.write(col, label=label)
3765 ui.write(sep, label='grep.sep')
3765 ui.write(sep, label='grep.sep')
3766 ui.write(cols[-1][0], label=cols[-1][1])
3766 ui.write(cols[-1][0], label=cols[-1][1])
3767 if not opts.get('files_with_matches'):
3767 if not opts.get('files_with_matches'):
3768 ui.write(sep, label='grep.sep')
3768 ui.write(sep, label='grep.sep')
3769 if not opts.get('text') and binary():
3769 if not opts.get('text') and binary():
3770 ui.write(" Binary file matches")
3770 ui.write(" Binary file matches")
3771 else:
3771 else:
3772 for s, label in l:
3772 for s, label in l:
3773 ui.write(s, label=label)
3773 ui.write(s, label=label)
3774 ui.write(eol)
3774 ui.write(eol)
3775 found = True
3775 found = True
3776 if opts.get('files_with_matches'):
3776 if opts.get('files_with_matches'):
3777 break
3777 break
3778 return found
3778 return found
3779
3779
3780 skip = {}
3780 skip = {}
3781 revfiles = {}
3781 revfiles = {}
3782 matchfn = scmutil.match(repo[None], pats, opts)
3782 matchfn = scmutil.match(repo[None], pats, opts)
3783 found = False
3783 found = False
3784 follow = opts.get('follow')
3784 follow = opts.get('follow')
3785
3785
3786 def prep(ctx, fns):
3786 def prep(ctx, fns):
3787 rev = ctx.rev()
3787 rev = ctx.rev()
3788 pctx = ctx.p1()
3788 pctx = ctx.p1()
3789 parent = pctx.rev()
3789 parent = pctx.rev()
3790 matches.setdefault(rev, {})
3790 matches.setdefault(rev, {})
3791 matches.setdefault(parent, {})
3791 matches.setdefault(parent, {})
3792 files = revfiles.setdefault(rev, [])
3792 files = revfiles.setdefault(rev, [])
3793 for fn in fns:
3793 for fn in fns:
3794 flog = getfile(fn)
3794 flog = getfile(fn)
3795 try:
3795 try:
3796 fnode = ctx.filenode(fn)
3796 fnode = ctx.filenode(fn)
3797 except error.LookupError:
3797 except error.LookupError:
3798 continue
3798 continue
3799
3799
3800 copied = flog.renamed(fnode)
3800 copied = flog.renamed(fnode)
3801 copy = follow and copied and copied[0]
3801 copy = follow and copied and copied[0]
3802 if copy:
3802 if copy:
3803 copies.setdefault(rev, {})[fn] = copy
3803 copies.setdefault(rev, {})[fn] = copy
3804 if fn in skip:
3804 if fn in skip:
3805 if copy:
3805 if copy:
3806 skip[copy] = True
3806 skip[copy] = True
3807 continue
3807 continue
3808 files.append(fn)
3808 files.append(fn)
3809
3809
3810 if fn not in matches[rev]:
3810 if fn not in matches[rev]:
3811 grepbody(fn, rev, flog.read(fnode))
3811 grepbody(fn, rev, flog.read(fnode))
3812
3812
3813 pfn = copy or fn
3813 pfn = copy or fn
3814 if pfn not in matches[parent]:
3814 if pfn not in matches[parent]:
3815 try:
3815 try:
3816 fnode = pctx.filenode(pfn)
3816 fnode = pctx.filenode(pfn)
3817 grepbody(pfn, parent, flog.read(fnode))
3817 grepbody(pfn, parent, flog.read(fnode))
3818 except error.LookupError:
3818 except error.LookupError:
3819 pass
3819 pass
3820
3820
3821 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3821 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3822 rev = ctx.rev()
3822 rev = ctx.rev()
3823 parent = ctx.p1().rev()
3823 parent = ctx.p1().rev()
3824 for fn in sorted(revfiles.get(rev, [])):
3824 for fn in sorted(revfiles.get(rev, [])):
3825 states = matches[rev][fn]
3825 states = matches[rev][fn]
3826 copy = copies.get(rev, {}).get(fn)
3826 copy = copies.get(rev, {}).get(fn)
3827 if fn in skip:
3827 if fn in skip:
3828 if copy:
3828 if copy:
3829 skip[copy] = True
3829 skip[copy] = True
3830 continue
3830 continue
3831 pstates = matches.get(parent, {}).get(copy or fn, [])
3831 pstates = matches.get(parent, {}).get(copy or fn, [])
3832 if pstates or states:
3832 if pstates or states:
3833 r = display(fn, ctx, pstates, states)
3833 r = display(fn, ctx, pstates, states)
3834 found = found or r
3834 found = found or r
3835 if r and not opts.get('all'):
3835 if r and not opts.get('all'):
3836 skip[fn] = True
3836 skip[fn] = True
3837 if copy:
3837 if copy:
3838 skip[copy] = True
3838 skip[copy] = True
3839 del matches[rev]
3839 del matches[rev]
3840 del revfiles[rev]
3840 del revfiles[rev]
3841
3841
3842 return not found
3842 return not found
3843
3843
3844 @command('heads',
3844 @command('heads',
3845 [('r', 'rev', '',
3845 [('r', 'rev', '',
3846 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3846 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3847 ('t', 'topo', False, _('show topological heads only')),
3847 ('t', 'topo', False, _('show topological heads only')),
3848 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3848 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3849 ('c', 'closed', False, _('show normal and closed branch heads')),
3849 ('c', 'closed', False, _('show normal and closed branch heads')),
3850 ] + templateopts,
3850 ] + templateopts,
3851 _('[-ct] [-r STARTREV] [REV]...'))
3851 _('[-ct] [-r STARTREV] [REV]...'))
3852 def heads(ui, repo, *branchrevs, **opts):
3852 def heads(ui, repo, *branchrevs, **opts):
3853 """show branch heads
3853 """show branch heads
3854
3854
3855 With no arguments, show all open branch heads in the repository.
3855 With no arguments, show all open branch heads in the repository.
3856 Branch heads are changesets that have no descendants on the
3856 Branch heads are changesets that have no descendants on the
3857 same branch. They are where development generally takes place and
3857 same branch. They are where development generally takes place and
3858 are the usual targets for update and merge operations.
3858 are the usual targets for update and merge operations.
3859
3859
3860 If one or more REVs are given, only open branch heads on the
3860 If one or more REVs are given, only open branch heads on the
3861 branches associated with the specified changesets are shown. This
3861 branches associated with the specified changesets are shown. This
3862 means that you can use :hg:`heads .` to see the heads on the
3862 means that you can use :hg:`heads .` to see the heads on the
3863 currently checked-out branch.
3863 currently checked-out branch.
3864
3864
3865 If -c/--closed is specified, also show branch heads marked closed
3865 If -c/--closed is specified, also show branch heads marked closed
3866 (see :hg:`commit --close-branch`).
3866 (see :hg:`commit --close-branch`).
3867
3867
3868 If STARTREV is specified, only those heads that are descendants of
3868 If STARTREV is specified, only those heads that are descendants of
3869 STARTREV will be displayed.
3869 STARTREV will be displayed.
3870
3870
3871 If -t/--topo is specified, named branch mechanics will be ignored and only
3871 If -t/--topo is specified, named branch mechanics will be ignored and only
3872 topological heads (changesets with no children) will be shown.
3872 topological heads (changesets with no children) will be shown.
3873
3873
3874 Returns 0 if matching heads are found, 1 if not.
3874 Returns 0 if matching heads are found, 1 if not.
3875 """
3875 """
3876
3876
3877 start = None
3877 start = None
3878 if 'rev' in opts:
3878 if 'rev' in opts:
3879 start = scmutil.revsingle(repo, opts['rev'], None).node()
3879 start = scmutil.revsingle(repo, opts['rev'], None).node()
3880
3880
3881 if opts.get('topo'):
3881 if opts.get('topo'):
3882 heads = [repo[h] for h in repo.heads(start)]
3882 heads = [repo[h] for h in repo.heads(start)]
3883 else:
3883 else:
3884 heads = []
3884 heads = []
3885 for branch in repo.branchmap():
3885 for branch in repo.branchmap():
3886 heads += repo.branchheads(branch, start, opts.get('closed'))
3886 heads += repo.branchheads(branch, start, opts.get('closed'))
3887 heads = [repo[h] for h in heads]
3887 heads = [repo[h] for h in heads]
3888
3888
3889 if branchrevs:
3889 if branchrevs:
3890 branches = set(repo[br].branch() for br in branchrevs)
3890 branches = set(repo[br].branch() for br in branchrevs)
3891 heads = [h for h in heads if h.branch() in branches]
3891 heads = [h for h in heads if h.branch() in branches]
3892
3892
3893 if opts.get('active') and branchrevs:
3893 if opts.get('active') and branchrevs:
3894 dagheads = repo.heads(start)
3894 dagheads = repo.heads(start)
3895 heads = [h for h in heads if h.node() in dagheads]
3895 heads = [h for h in heads if h.node() in dagheads]
3896
3896
3897 if branchrevs:
3897 if branchrevs:
3898 haveheads = set(h.branch() for h in heads)
3898 haveheads = set(h.branch() for h in heads)
3899 if branches - haveheads:
3899 if branches - haveheads:
3900 headless = ', '.join(b for b in branches - haveheads)
3900 headless = ', '.join(b for b in branches - haveheads)
3901 msg = _('no open branch heads found on branches %s')
3901 msg = _('no open branch heads found on branches %s')
3902 if opts.get('rev'):
3902 if opts.get('rev'):
3903 msg += _(' (started at %s)') % opts['rev']
3903 msg += _(' (started at %s)') % opts['rev']
3904 ui.warn((msg + '\n') % headless)
3904 ui.warn((msg + '\n') % headless)
3905
3905
3906 if not heads:
3906 if not heads:
3907 return 1
3907 return 1
3908
3908
3909 heads = sorted(heads, key=lambda x: -x.rev())
3909 heads = sorted(heads, key=lambda x: -x.rev())
3910 displayer = cmdutil.show_changeset(ui, repo, opts)
3910 displayer = cmdutil.show_changeset(ui, repo, opts)
3911 for ctx in heads:
3911 for ctx in heads:
3912 displayer.show(ctx)
3912 displayer.show(ctx)
3913 displayer.close()
3913 displayer.close()
3914
3914
3915 @command('help',
3915 @command('help',
3916 [('e', 'extension', None, _('show only help for extensions')),
3916 [('e', 'extension', None, _('show only help for extensions')),
3917 ('c', 'command', None, _('show only help for commands')),
3917 ('c', 'command', None, _('show only help for commands')),
3918 ('k', 'keyword', '', _('show topics matching keyword')),
3918 ('k', 'keyword', '', _('show topics matching keyword')),
3919 ],
3919 ],
3920 _('[-ec] [TOPIC]'),
3920 _('[-ec] [TOPIC]'),
3921 norepo=True)
3921 norepo=True)
3922 def help_(ui, name=None, **opts):
3922 def help_(ui, name=None, **opts):
3923 """show help for a given topic or a help overview
3923 """show help for a given topic or a help overview
3924
3924
3925 With no arguments, print a list of commands with short help messages.
3925 With no arguments, print a list of commands with short help messages.
3926
3926
3927 Given a topic, extension, or command name, print help for that
3927 Given a topic, extension, or command name, print help for that
3928 topic.
3928 topic.
3929
3929
3930 Returns 0 if successful.
3930 Returns 0 if successful.
3931 """
3931 """
3932
3932
3933 textwidth = min(ui.termwidth(), 80) - 2
3933 textwidth = min(ui.termwidth(), 80) - 2
3934
3934
3935 keep = []
3935 keep = []
3936 if ui.verbose:
3936 if ui.verbose:
3937 keep.append('verbose')
3937 keep.append('verbose')
3938 if sys.platform.startswith('win'):
3938 if sys.platform.startswith('win'):
3939 keep.append('windows')
3939 keep.append('windows')
3940 elif sys.platform == 'OpenVMS':
3940 elif sys.platform == 'OpenVMS':
3941 keep.append('vms')
3941 keep.append('vms')
3942 elif sys.platform == 'plan9':
3942 elif sys.platform == 'plan9':
3943 keep.append('plan9')
3943 keep.append('plan9')
3944 else:
3944 else:
3945 keep.append('unix')
3945 keep.append('unix')
3946 keep.append(sys.platform.lower())
3946 keep.append(sys.platform.lower())
3947
3947
3948 section = None
3948 section = None
3949 if name and '.' in name:
3949 if name and '.' in name:
3950 name, section = name.split('.', 1)
3950 name, section = name.split('.', 1)
3951
3951
3952 text = help.help_(ui, name, **opts)
3952 text = help.help_(ui, name, **opts)
3953
3953
3954 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3954 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3955 section=section)
3955 section=section)
3956 if section and not formatted:
3956 if section and not formatted:
3957 raise util.Abort(_("help section not found"))
3957 raise util.Abort(_("help section not found"))
3958
3958
3959 if 'verbose' in pruned:
3959 if 'verbose' in pruned:
3960 keep.append('omitted')
3960 keep.append('omitted')
3961 else:
3961 else:
3962 keep.append('notomitted')
3962 keep.append('notomitted')
3963 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3963 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3964 section=section)
3964 section=section)
3965 ui.write(formatted)
3965 ui.write(formatted)
3966
3966
3967
3967
3968 @command('identify|id',
3968 @command('identify|id',
3969 [('r', 'rev', '',
3969 [('r', 'rev', '',
3970 _('identify the specified revision'), _('REV')),
3970 _('identify the specified revision'), _('REV')),
3971 ('n', 'num', None, _('show local revision number')),
3971 ('n', 'num', None, _('show local revision number')),
3972 ('i', 'id', None, _('show global revision id')),
3972 ('i', 'id', None, _('show global revision id')),
3973 ('b', 'branch', None, _('show branch')),
3973 ('b', 'branch', None, _('show branch')),
3974 ('t', 'tags', None, _('show tags')),
3974 ('t', 'tags', None, _('show tags')),
3975 ('B', 'bookmarks', None, _('show bookmarks')),
3975 ('B', 'bookmarks', None, _('show bookmarks')),
3976 ] + remoteopts,
3976 ] + remoteopts,
3977 _('[-nibtB] [-r REV] [SOURCE]'),
3977 _('[-nibtB] [-r REV] [SOURCE]'),
3978 optionalrepo=True)
3978 optionalrepo=True)
3979 def identify(ui, repo, source=None, rev=None,
3979 def identify(ui, repo, source=None, rev=None,
3980 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3980 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3981 """identify the working directory or specified revision
3981 """identify the working directory or specified revision
3982
3982
3983 Print a summary identifying the repository state at REV using one or
3983 Print a summary identifying the repository state at REV using one or
3984 two parent hash identifiers, followed by a "+" if the working
3984 two parent hash identifiers, followed by a "+" if the working
3985 directory has uncommitted changes, the branch name (if not default),
3985 directory has uncommitted changes, the branch name (if not default),
3986 a list of tags, and a list of bookmarks.
3986 a list of tags, and a list of bookmarks.
3987
3987
3988 When REV is not given, print a summary of the current state of the
3988 When REV is not given, print a summary of the current state of the
3989 repository.
3989 repository.
3990
3990
3991 Specifying a path to a repository root or Mercurial bundle will
3991 Specifying a path to a repository root or Mercurial bundle will
3992 cause lookup to operate on that repository/bundle.
3992 cause lookup to operate on that repository/bundle.
3993
3993
3994 .. container:: verbose
3994 .. container:: verbose
3995
3995
3996 Examples:
3996 Examples:
3997
3997
3998 - generate a build identifier for the working directory::
3998 - generate a build identifier for the working directory::
3999
3999
4000 hg id --id > build-id.dat
4000 hg id --id > build-id.dat
4001
4001
4002 - find the revision corresponding to a tag::
4002 - find the revision corresponding to a tag::
4003
4003
4004 hg id -n -r 1.3
4004 hg id -n -r 1.3
4005
4005
4006 - check the most recent revision of a remote repository::
4006 - check the most recent revision of a remote repository::
4007
4007
4008 hg id -r tip http://selenic.com/hg/
4008 hg id -r tip http://selenic.com/hg/
4009
4009
4010 Returns 0 if successful.
4010 Returns 0 if successful.
4011 """
4011 """
4012
4012
4013 if not repo and not source:
4013 if not repo and not source:
4014 raise util.Abort(_("there is no Mercurial repository here "
4014 raise util.Abort(_("there is no Mercurial repository here "
4015 "(.hg not found)"))
4015 "(.hg not found)"))
4016
4016
4017 if ui.debugflag:
4017 if ui.debugflag:
4018 hexfunc = hex
4018 hexfunc = hex
4019 else:
4019 else:
4020 hexfunc = short
4020 hexfunc = short
4021 default = not (num or id or branch or tags or bookmarks)
4021 default = not (num or id or branch or tags or bookmarks)
4022 output = []
4022 output = []
4023 revs = []
4023 revs = []
4024
4024
4025 if source:
4025 if source:
4026 source, branches = hg.parseurl(ui.expandpath(source))
4026 source, branches = hg.parseurl(ui.expandpath(source))
4027 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4027 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4028 repo = peer.local()
4028 repo = peer.local()
4029 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4029 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4030
4030
4031 if not repo:
4031 if not repo:
4032 if num or branch or tags:
4032 if num or branch or tags:
4033 raise util.Abort(
4033 raise util.Abort(
4034 _("can't query remote revision number, branch, or tags"))
4034 _("can't query remote revision number, branch, or tags"))
4035 if not rev and revs:
4035 if not rev and revs:
4036 rev = revs[0]
4036 rev = revs[0]
4037 if not rev:
4037 if not rev:
4038 rev = "tip"
4038 rev = "tip"
4039
4039
4040 remoterev = peer.lookup(rev)
4040 remoterev = peer.lookup(rev)
4041 if default or id:
4041 if default or id:
4042 output = [hexfunc(remoterev)]
4042 output = [hexfunc(remoterev)]
4043
4043
4044 def getbms():
4044 def getbms():
4045 bms = []
4045 bms = []
4046
4046
4047 if 'bookmarks' in peer.listkeys('namespaces'):
4047 if 'bookmarks' in peer.listkeys('namespaces'):
4048 hexremoterev = hex(remoterev)
4048 hexremoterev = hex(remoterev)
4049 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4049 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4050 if bmr == hexremoterev]
4050 if bmr == hexremoterev]
4051
4051
4052 return sorted(bms)
4052 return sorted(bms)
4053
4053
4054 if bookmarks:
4054 if bookmarks:
4055 output.extend(getbms())
4055 output.extend(getbms())
4056 elif default and not ui.quiet:
4056 elif default and not ui.quiet:
4057 # multiple bookmarks for a single parent separated by '/'
4057 # multiple bookmarks for a single parent separated by '/'
4058 bm = '/'.join(getbms())
4058 bm = '/'.join(getbms())
4059 if bm:
4059 if bm:
4060 output.append(bm)
4060 output.append(bm)
4061 else:
4061 else:
4062 if not rev:
4062 if not rev:
4063 ctx = repo[None]
4063 ctx = repo[None]
4064 parents = ctx.parents()
4064 parents = ctx.parents()
4065 changed = ""
4065 changed = ""
4066 if default or id or num:
4066 if default or id or num:
4067 if (any(repo.status())
4067 if (any(repo.status())
4068 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4068 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4069 changed = '+'
4069 changed = '+'
4070 if default or id:
4070 if default or id:
4071 output = ["%s%s" %
4071 output = ["%s%s" %
4072 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4072 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4073 if num:
4073 if num:
4074 output.append("%s%s" %
4074 output.append("%s%s" %
4075 ('+'.join([str(p.rev()) for p in parents]), changed))
4075 ('+'.join([str(p.rev()) for p in parents]), changed))
4076 else:
4076 else:
4077 ctx = scmutil.revsingle(repo, rev)
4077 ctx = scmutil.revsingle(repo, rev)
4078 if default or id:
4078 if default or id:
4079 output = [hexfunc(ctx.node())]
4079 output = [hexfunc(ctx.node())]
4080 if num:
4080 if num:
4081 output.append(str(ctx.rev()))
4081 output.append(str(ctx.rev()))
4082
4082
4083 if default and not ui.quiet:
4083 if default and not ui.quiet:
4084 b = ctx.branch()
4084 b = ctx.branch()
4085 if b != 'default':
4085 if b != 'default':
4086 output.append("(%s)" % b)
4086 output.append("(%s)" % b)
4087
4087
4088 # multiple tags for a single parent separated by '/'
4088 # multiple tags for a single parent separated by '/'
4089 t = '/'.join(ctx.tags())
4089 t = '/'.join(ctx.tags())
4090 if t:
4090 if t:
4091 output.append(t)
4091 output.append(t)
4092
4092
4093 # multiple bookmarks for a single parent separated by '/'
4093 # multiple bookmarks for a single parent separated by '/'
4094 bm = '/'.join(ctx.bookmarks())
4094 bm = '/'.join(ctx.bookmarks())
4095 if bm:
4095 if bm:
4096 output.append(bm)
4096 output.append(bm)
4097 else:
4097 else:
4098 if branch:
4098 if branch:
4099 output.append(ctx.branch())
4099 output.append(ctx.branch())
4100
4100
4101 if tags:
4101 if tags:
4102 output.extend(ctx.tags())
4102 output.extend(ctx.tags())
4103
4103
4104 if bookmarks:
4104 if bookmarks:
4105 output.extend(ctx.bookmarks())
4105 output.extend(ctx.bookmarks())
4106
4106
4107 ui.write("%s\n" % ' '.join(output))
4107 ui.write("%s\n" % ' '.join(output))
4108
4108
4109 @command('import|patch',
4109 @command('import|patch',
4110 [('p', 'strip', 1,
4110 [('p', 'strip', 1,
4111 _('directory strip option for patch. This has the same '
4111 _('directory strip option for patch. This has the same '
4112 'meaning as the corresponding patch option'), _('NUM')),
4112 'meaning as the corresponding patch option'), _('NUM')),
4113 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4113 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4114 ('e', 'edit', False, _('invoke editor on commit messages')),
4114 ('e', 'edit', False, _('invoke editor on commit messages')),
4115 ('f', 'force', None,
4115 ('f', 'force', None,
4116 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4116 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4117 ('', 'no-commit', None,
4117 ('', 'no-commit', None,
4118 _("don't commit, just update the working directory")),
4118 _("don't commit, just update the working directory")),
4119 ('', 'bypass', None,
4119 ('', 'bypass', None,
4120 _("apply patch without touching the working directory")),
4120 _("apply patch without touching the working directory")),
4121 ('', 'partial', None,
4121 ('', 'partial', None,
4122 _('commit even if some hunks fail')),
4122 _('commit even if some hunks fail')),
4123 ('', 'exact', None,
4123 ('', 'exact', None,
4124 _('apply patch to the nodes from which it was generated')),
4124 _('apply patch to the nodes from which it was generated')),
4125 ('', 'prefix', '',
4125 ('', 'prefix', '',
4126 _('apply patch to subdirectory'), _('DIR')),
4126 _('apply patch to subdirectory'), _('DIR')),
4127 ('', 'import-branch', None,
4127 ('', 'import-branch', None,
4128 _('use any branch information in patch (implied by --exact)'))] +
4128 _('use any branch information in patch (implied by --exact)'))] +
4129 commitopts + commitopts2 + similarityopts,
4129 commitopts + commitopts2 + similarityopts,
4130 _('[OPTION]... PATCH...'))
4130 _('[OPTION]... PATCH...'))
4131 def import_(ui, repo, patch1=None, *patches, **opts):
4131 def import_(ui, repo, patch1=None, *patches, **opts):
4132 """import an ordered set of patches
4132 """import an ordered set of patches
4133
4133
4134 Import a list of patches and commit them individually (unless
4134 Import a list of patches and commit them individually (unless
4135 --no-commit is specified).
4135 --no-commit is specified).
4136
4136
4137 Because import first applies changes to the working directory,
4137 Because import first applies changes to the working directory,
4138 import will abort if there are outstanding changes.
4138 import will abort if there are outstanding changes.
4139
4139
4140 You can import a patch straight from a mail message. Even patches
4140 You can import a patch straight from a mail message. Even patches
4141 as attachments work (to use the body part, it must have type
4141 as attachments work (to use the body part, it must have type
4142 text/plain or text/x-patch). From and Subject headers of email
4142 text/plain or text/x-patch). From and Subject headers of email
4143 message are used as default committer and commit message. All
4143 message are used as default committer and commit message. All
4144 text/plain body parts before first diff are added to commit
4144 text/plain body parts before first diff are added to commit
4145 message.
4145 message.
4146
4146
4147 If the imported patch was generated by :hg:`export`, user and
4147 If the imported patch was generated by :hg:`export`, user and
4148 description from patch override values from message headers and
4148 description from patch override values from message headers and
4149 body. Values given on command line with -m/--message and -u/--user
4149 body. Values given on command line with -m/--message and -u/--user
4150 override these.
4150 override these.
4151
4151
4152 If --exact is specified, import will set the working directory to
4152 If --exact is specified, import will set the working directory to
4153 the parent of each patch before applying it, and will abort if the
4153 the parent of each patch before applying it, and will abort if the
4154 resulting changeset has a different ID than the one recorded in
4154 resulting changeset has a different ID than the one recorded in
4155 the patch. This may happen due to character set problems or other
4155 the patch. This may happen due to character set problems or other
4156 deficiencies in the text patch format.
4156 deficiencies in the text patch format.
4157
4157
4158 Use --bypass to apply and commit patches directly to the
4158 Use --bypass to apply and commit patches directly to the
4159 repository, not touching the working directory. Without --exact,
4159 repository, not touching the working directory. Without --exact,
4160 patches will be applied on top of the working directory parent
4160 patches will be applied on top of the working directory parent
4161 revision.
4161 revision.
4162
4162
4163 With -s/--similarity, hg will attempt to discover renames and
4163 With -s/--similarity, hg will attempt to discover renames and
4164 copies in the patch in the same way as :hg:`addremove`.
4164 copies in the patch in the same way as :hg:`addremove`.
4165
4165
4166 Use --partial to ensure a changeset will be created from the patch
4166 Use --partial to ensure a changeset will be created from the patch
4167 even if some hunks fail to apply. Hunks that fail to apply will be
4167 even if some hunks fail to apply. Hunks that fail to apply will be
4168 written to a <target-file>.rej file. Conflicts can then be resolved
4168 written to a <target-file>.rej file. Conflicts can then be resolved
4169 by hand before :hg:`commit --amend` is run to update the created
4169 by hand before :hg:`commit --amend` is run to update the created
4170 changeset. This flag exists to let people import patches that
4170 changeset. This flag exists to let people import patches that
4171 partially apply without losing the associated metadata (author,
4171 partially apply without losing the associated metadata (author,
4172 date, description, ...). Note that when none of the hunk applies
4172 date, description, ...). Note that when none of the hunk applies
4173 cleanly, :hg:`import --partial` will create an empty changeset,
4173 cleanly, :hg:`import --partial` will create an empty changeset,
4174 importing only the patch metadata.
4174 importing only the patch metadata.
4175
4175
4176 To read a patch from standard input, use "-" as the patch name. If
4176 To read a patch from standard input, use "-" as the patch name. If
4177 a URL is specified, the patch will be downloaded from it.
4177 a URL is specified, the patch will be downloaded from it.
4178 See :hg:`help dates` for a list of formats valid for -d/--date.
4178 See :hg:`help dates` for a list of formats valid for -d/--date.
4179
4179
4180 .. container:: verbose
4180 .. container:: verbose
4181
4181
4182 Examples:
4182 Examples:
4183
4183
4184 - import a traditional patch from a website and detect renames::
4184 - import a traditional patch from a website and detect renames::
4185
4185
4186 hg import -s 80 http://example.com/bugfix.patch
4186 hg import -s 80 http://example.com/bugfix.patch
4187
4187
4188 - import a changeset from an hgweb server::
4188 - import a changeset from an hgweb server::
4189
4189
4190 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4190 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4191
4191
4192 - import all the patches in an Unix-style mbox::
4192 - import all the patches in an Unix-style mbox::
4193
4193
4194 hg import incoming-patches.mbox
4194 hg import incoming-patches.mbox
4195
4195
4196 - attempt to exactly restore an exported changeset (not always
4196 - attempt to exactly restore an exported changeset (not always
4197 possible)::
4197 possible)::
4198
4198
4199 hg import --exact proposed-fix.patch
4199 hg import --exact proposed-fix.patch
4200
4200
4201 Returns 0 on success, 1 on partial success (see --partial).
4201 Returns 0 on success, 1 on partial success (see --partial).
4202 """
4202 """
4203
4203
4204 if not patch1:
4204 if not patch1:
4205 raise util.Abort(_('need at least one patch to import'))
4205 raise util.Abort(_('need at least one patch to import'))
4206
4206
4207 patches = (patch1,) + patches
4207 patches = (patch1,) + patches
4208
4208
4209 date = opts.get('date')
4209 date = opts.get('date')
4210 if date:
4210 if date:
4211 opts['date'] = util.parsedate(date)
4211 opts['date'] = util.parsedate(date)
4212
4212
4213 update = not opts.get('bypass')
4213 update = not opts.get('bypass')
4214 if not update and opts.get('no_commit'):
4214 if not update and opts.get('no_commit'):
4215 raise util.Abort(_('cannot use --no-commit with --bypass'))
4215 raise util.Abort(_('cannot use --no-commit with --bypass'))
4216 try:
4216 try:
4217 sim = float(opts.get('similarity') or 0)
4217 sim = float(opts.get('similarity') or 0)
4218 except ValueError:
4218 except ValueError:
4219 raise util.Abort(_('similarity must be a number'))
4219 raise util.Abort(_('similarity must be a number'))
4220 if sim < 0 or sim > 100:
4220 if sim < 0 or sim > 100:
4221 raise util.Abort(_('similarity must be between 0 and 100'))
4221 raise util.Abort(_('similarity must be between 0 and 100'))
4222 if sim and not update:
4222 if sim and not update:
4223 raise util.Abort(_('cannot use --similarity with --bypass'))
4223 raise util.Abort(_('cannot use --similarity with --bypass'))
4224 if opts.get('exact') and opts.get('edit'):
4224 if opts.get('exact') and opts.get('edit'):
4225 raise util.Abort(_('cannot use --exact with --edit'))
4225 raise util.Abort(_('cannot use --exact with --edit'))
4226 if opts.get('exact') and opts.get('prefix'):
4226 if opts.get('exact') and opts.get('prefix'):
4227 raise util.Abort(_('cannot use --exact with --prefix'))
4227 raise util.Abort(_('cannot use --exact with --prefix'))
4228
4228
4229 if update:
4229 if update:
4230 cmdutil.checkunfinished(repo)
4230 cmdutil.checkunfinished(repo)
4231 if (opts.get('exact') or not opts.get('force')) and update:
4231 if (opts.get('exact') or not opts.get('force')) and update:
4232 cmdutil.bailifchanged(repo)
4232 cmdutil.bailifchanged(repo)
4233
4233
4234 base = opts["base"]
4234 base = opts["base"]
4235 wlock = dsguard = lock = tr = None
4235 wlock = dsguard = lock = tr = None
4236 msgs = []
4236 msgs = []
4237 ret = 0
4237 ret = 0
4238
4238
4239
4239
4240 try:
4240 try:
4241 try:
4241 try:
4242 wlock = repo.wlock()
4242 wlock = repo.wlock()
4243 dsguard = cmdutil.dirstateguard(repo, 'import')
4243 dsguard = cmdutil.dirstateguard(repo, 'import')
4244 if not opts.get('no_commit'):
4244 if not opts.get('no_commit'):
4245 lock = repo.lock()
4245 lock = repo.lock()
4246 tr = repo.transaction('import')
4246 tr = repo.transaction('import')
4247 parents = repo.parents()
4247 parents = repo.parents()
4248 for patchurl in patches:
4248 for patchurl in patches:
4249 if patchurl == '-':
4249 if patchurl == '-':
4250 ui.status(_('applying patch from stdin\n'))
4250 ui.status(_('applying patch from stdin\n'))
4251 patchfile = ui.fin
4251 patchfile = ui.fin
4252 patchurl = 'stdin' # for error message
4252 patchurl = 'stdin' # for error message
4253 else:
4253 else:
4254 patchurl = os.path.join(base, patchurl)
4254 patchurl = os.path.join(base, patchurl)
4255 ui.status(_('applying %s\n') % patchurl)
4255 ui.status(_('applying %s\n') % patchurl)
4256 patchfile = hg.openpath(ui, patchurl)
4256 patchfile = hg.openpath(ui, patchurl)
4257
4257
4258 haspatch = False
4258 haspatch = False
4259 for hunk in patch.split(patchfile):
4259 for hunk in patch.split(patchfile):
4260 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4260 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4261 parents, opts,
4261 parents, opts,
4262 msgs, hg.clean)
4262 msgs, hg.clean)
4263 if msg:
4263 if msg:
4264 haspatch = True
4264 haspatch = True
4265 ui.note(msg + '\n')
4265 ui.note(msg + '\n')
4266 if update or opts.get('exact'):
4266 if update or opts.get('exact'):
4267 parents = repo.parents()
4267 parents = repo.parents()
4268 else:
4268 else:
4269 parents = [repo[node]]
4269 parents = [repo[node]]
4270 if rej:
4270 if rej:
4271 ui.write_err(_("patch applied partially\n"))
4271 ui.write_err(_("patch applied partially\n"))
4272 ui.write_err(_("(fix the .rej files and run "
4272 ui.write_err(_("(fix the .rej files and run "
4273 "`hg commit --amend`)\n"))
4273 "`hg commit --amend`)\n"))
4274 ret = 1
4274 ret = 1
4275 break
4275 break
4276
4276
4277 if not haspatch:
4277 if not haspatch:
4278 raise util.Abort(_('%s: no diffs found') % patchurl)
4278 raise util.Abort(_('%s: no diffs found') % patchurl)
4279
4279
4280 if tr:
4280 if tr:
4281 tr.close()
4281 tr.close()
4282 if msgs:
4282 if msgs:
4283 repo.savecommitmessage('\n* * *\n'.join(msgs))
4283 repo.savecommitmessage('\n* * *\n'.join(msgs))
4284 dsguard.close()
4284 dsguard.close()
4285 return ret
4285 return ret
4286 finally:
4286 finally:
4287 # TODO: get rid of this meaningless try/finally enclosing.
4287 # TODO: get rid of this meaningless try/finally enclosing.
4288 # this is kept only to reduce changes in a patch.
4288 # this is kept only to reduce changes in a patch.
4289 pass
4289 pass
4290 finally:
4290 finally:
4291 if tr:
4291 if tr:
4292 tr.release()
4292 tr.release()
4293 release(lock, dsguard, wlock)
4293 release(lock, dsguard, wlock)
4294
4294
4295 @command('incoming|in',
4295 @command('incoming|in',
4296 [('f', 'force', None,
4296 [('f', 'force', None,
4297 _('run even if remote repository is unrelated')),
4297 _('run even if remote repository is unrelated')),
4298 ('n', 'newest-first', None, _('show newest record first')),
4298 ('n', 'newest-first', None, _('show newest record first')),
4299 ('', 'bundle', '',
4299 ('', 'bundle', '',
4300 _('file to store the bundles into'), _('FILE')),
4300 _('file to store the bundles into'), _('FILE')),
4301 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4301 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4302 ('B', 'bookmarks', False, _("compare bookmarks")),
4302 ('B', 'bookmarks', False, _("compare bookmarks")),
4303 ('b', 'branch', [],
4303 ('b', 'branch', [],
4304 _('a specific branch you would like to pull'), _('BRANCH')),
4304 _('a specific branch you would like to pull'), _('BRANCH')),
4305 ] + logopts + remoteopts + subrepoopts,
4305 ] + logopts + remoteopts + subrepoopts,
4306 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4306 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4307 def incoming(ui, repo, source="default", **opts):
4307 def incoming(ui, repo, source="default", **opts):
4308 """show new changesets found in source
4308 """show new changesets found in source
4309
4309
4310 Show new changesets found in the specified path/URL or the default
4310 Show new changesets found in the specified path/URL or the default
4311 pull location. These are the changesets that would have been pulled
4311 pull location. These are the changesets that would have been pulled
4312 if a pull at the time you issued this command.
4312 if a pull at the time you issued this command.
4313
4313
4314 See pull for valid source format details.
4314 See pull for valid source format details.
4315
4315
4316 .. container:: verbose
4316 .. container:: verbose
4317
4317
4318 With -B/--bookmarks, the result of bookmark comparison between
4318 With -B/--bookmarks, the result of bookmark comparison between
4319 local and remote repositories is displayed. With -v/--verbose,
4319 local and remote repositories is displayed. With -v/--verbose,
4320 status is also displayed for each bookmark like below::
4320 status is also displayed for each bookmark like below::
4321
4321
4322 BM1 01234567890a added
4322 BM1 01234567890a added
4323 BM2 1234567890ab advanced
4323 BM2 1234567890ab advanced
4324 BM3 234567890abc diverged
4324 BM3 234567890abc diverged
4325 BM4 34567890abcd changed
4325 BM4 34567890abcd changed
4326
4326
4327 The action taken locally when pulling depends on the
4327 The action taken locally when pulling depends on the
4328 status of each bookmark:
4328 status of each bookmark:
4329
4329
4330 :``added``: pull will create it
4330 :``added``: pull will create it
4331 :``advanced``: pull will update it
4331 :``advanced``: pull will update it
4332 :``diverged``: pull will create a divergent bookmark
4332 :``diverged``: pull will create a divergent bookmark
4333 :``changed``: result depends on remote changesets
4333 :``changed``: result depends on remote changesets
4334
4334
4335 From the point of view of pulling behavior, bookmark
4335 From the point of view of pulling behavior, bookmark
4336 existing only in the remote repository are treated as ``added``,
4336 existing only in the remote repository are treated as ``added``,
4337 even if it is in fact locally deleted.
4337 even if it is in fact locally deleted.
4338
4338
4339 .. container:: verbose
4339 .. container:: verbose
4340
4340
4341 For remote repository, using --bundle avoids downloading the
4341 For remote repository, using --bundle avoids downloading the
4342 changesets twice if the incoming is followed by a pull.
4342 changesets twice if the incoming is followed by a pull.
4343
4343
4344 Examples:
4344 Examples:
4345
4345
4346 - show incoming changes with patches and full description::
4346 - show incoming changes with patches and full description::
4347
4347
4348 hg incoming -vp
4348 hg incoming -vp
4349
4349
4350 - show incoming changes excluding merges, store a bundle::
4350 - show incoming changes excluding merges, store a bundle::
4351
4351
4352 hg in -vpM --bundle incoming.hg
4352 hg in -vpM --bundle incoming.hg
4353 hg pull incoming.hg
4353 hg pull incoming.hg
4354
4354
4355 - briefly list changes inside a bundle::
4355 - briefly list changes inside a bundle::
4356
4356
4357 hg in changes.hg -T "{desc|firstline}\\n"
4357 hg in changes.hg -T "{desc|firstline}\\n"
4358
4358
4359 Returns 0 if there are incoming changes, 1 otherwise.
4359 Returns 0 if there are incoming changes, 1 otherwise.
4360 """
4360 """
4361 if opts.get('graph'):
4361 if opts.get('graph'):
4362 cmdutil.checkunsupportedgraphflags([], opts)
4362 cmdutil.checkunsupportedgraphflags([], opts)
4363 def display(other, chlist, displayer):
4363 def display(other, chlist, displayer):
4364 revdag = cmdutil.graphrevs(other, chlist, opts)
4364 revdag = cmdutil.graphrevs(other, chlist, opts)
4365 showparents = [ctx.node() for ctx in repo[None].parents()]
4365 showparents = [ctx.node() for ctx in repo[None].parents()]
4366 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4366 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4367 graphmod.asciiedges)
4367 graphmod.asciiedges)
4368
4368
4369 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4369 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4370 return 0
4370 return 0
4371
4371
4372 if opts.get('bundle') and opts.get('subrepos'):
4372 if opts.get('bundle') and opts.get('subrepos'):
4373 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4373 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4374
4374
4375 if opts.get('bookmarks'):
4375 if opts.get('bookmarks'):
4376 source, branches = hg.parseurl(ui.expandpath(source),
4376 source, branches = hg.parseurl(ui.expandpath(source),
4377 opts.get('branch'))
4377 opts.get('branch'))
4378 other = hg.peer(repo, opts, source)
4378 other = hg.peer(repo, opts, source)
4379 if 'bookmarks' not in other.listkeys('namespaces'):
4379 if 'bookmarks' not in other.listkeys('namespaces'):
4380 ui.warn(_("remote doesn't support bookmarks\n"))
4380 ui.warn(_("remote doesn't support bookmarks\n"))
4381 return 0
4381 return 0
4382 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4382 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4383 return bookmarks.incoming(ui, repo, other)
4383 return bookmarks.incoming(ui, repo, other)
4384
4384
4385 repo._subtoppath = ui.expandpath(source)
4385 repo._subtoppath = ui.expandpath(source)
4386 try:
4386 try:
4387 return hg.incoming(ui, repo, source, opts)
4387 return hg.incoming(ui, repo, source, opts)
4388 finally:
4388 finally:
4389 del repo._subtoppath
4389 del repo._subtoppath
4390
4390
4391
4391
4392 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4392 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4393 norepo=True)
4393 norepo=True)
4394 def init(ui, dest=".", **opts):
4394 def init(ui, dest=".", **opts):
4395 """create a new repository in the given directory
4395 """create a new repository in the given directory
4396
4396
4397 Initialize a new repository in the given directory. If the given
4397 Initialize a new repository in the given directory. If the given
4398 directory does not exist, it will be created.
4398 directory does not exist, it will be created.
4399
4399
4400 If no directory is given, the current directory is used.
4400 If no directory is given, the current directory is used.
4401
4401
4402 It is possible to specify an ``ssh://`` URL as the destination.
4402 It is possible to specify an ``ssh://`` URL as the destination.
4403 See :hg:`help urls` for more information.
4403 See :hg:`help urls` for more information.
4404
4404
4405 Returns 0 on success.
4405 Returns 0 on success.
4406 """
4406 """
4407 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4407 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4408
4408
4409 @command('locate',
4409 @command('locate',
4410 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4410 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4411 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4411 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4412 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4412 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4413 ] + walkopts,
4413 ] + walkopts,
4414 _('[OPTION]... [PATTERN]...'))
4414 _('[OPTION]... [PATTERN]...'))
4415 def locate(ui, repo, *pats, **opts):
4415 def locate(ui, repo, *pats, **opts):
4416 """locate files matching specific patterns (DEPRECATED)
4416 """locate files matching specific patterns (DEPRECATED)
4417
4417
4418 Print files under Mercurial control in the working directory whose
4418 Print files under Mercurial control in the working directory whose
4419 names match the given patterns.
4419 names match the given patterns.
4420
4420
4421 By default, this command searches all directories in the working
4421 By default, this command searches all directories in the working
4422 directory. To search just the current directory and its
4422 directory. To search just the current directory and its
4423 subdirectories, use "--include .".
4423 subdirectories, use "--include .".
4424
4424
4425 If no patterns are given to match, this command prints the names
4425 If no patterns are given to match, this command prints the names
4426 of all files under Mercurial control in the working directory.
4426 of all files under Mercurial control in the working directory.
4427
4427
4428 If you want to feed the output of this command into the "xargs"
4428 If you want to feed the output of this command into the "xargs"
4429 command, use the -0 option to both this command and "xargs". This
4429 command, use the -0 option to both this command and "xargs". This
4430 will avoid the problem of "xargs" treating single filenames that
4430 will avoid the problem of "xargs" treating single filenames that
4431 contain whitespace as multiple filenames.
4431 contain whitespace as multiple filenames.
4432
4432
4433 See :hg:`help files` for a more versatile command.
4433 See :hg:`help files` for a more versatile command.
4434
4434
4435 Returns 0 if a match is found, 1 otherwise.
4435 Returns 0 if a match is found, 1 otherwise.
4436 """
4436 """
4437 if opts.get('print0'):
4437 if opts.get('print0'):
4438 end = '\0'
4438 end = '\0'
4439 else:
4439 else:
4440 end = '\n'
4440 end = '\n'
4441 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4441 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4442
4442
4443 ret = 1
4443 ret = 1
4444 ctx = repo[rev]
4444 ctx = repo[rev]
4445 m = scmutil.match(ctx, pats, opts, default='relglob')
4445 m = scmutil.match(ctx, pats, opts, default='relglob',
4446 m.bad = lambda x, y: False
4446 badfn=lambda x, y: False)
4447
4447
4448 for abs in ctx.matches(m):
4448 for abs in ctx.matches(m):
4449 if opts.get('fullpath'):
4449 if opts.get('fullpath'):
4450 ui.write(repo.wjoin(abs), end)
4450 ui.write(repo.wjoin(abs), end)
4451 else:
4451 else:
4452 ui.write(((pats and m.rel(abs)) or abs), end)
4452 ui.write(((pats and m.rel(abs)) or abs), end)
4453 ret = 0
4453 ret = 0
4454
4454
4455 return ret
4455 return ret
4456
4456
4457 @command('^log|history',
4457 @command('^log|history',
4458 [('f', 'follow', None,
4458 [('f', 'follow', None,
4459 _('follow changeset history, or file history across copies and renames')),
4459 _('follow changeset history, or file history across copies and renames')),
4460 ('', 'follow-first', None,
4460 ('', 'follow-first', None,
4461 _('only follow the first parent of merge changesets (DEPRECATED)')),
4461 _('only follow the first parent of merge changesets (DEPRECATED)')),
4462 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4462 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4463 ('C', 'copies', None, _('show copied files')),
4463 ('C', 'copies', None, _('show copied files')),
4464 ('k', 'keyword', [],
4464 ('k', 'keyword', [],
4465 _('do case-insensitive search for a given text'), _('TEXT')),
4465 _('do case-insensitive search for a given text'), _('TEXT')),
4466 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4466 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4467 ('', 'removed', None, _('include revisions where files were removed')),
4467 ('', 'removed', None, _('include revisions where files were removed')),
4468 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4468 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4469 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4469 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4470 ('', 'only-branch', [],
4470 ('', 'only-branch', [],
4471 _('show only changesets within the given named branch (DEPRECATED)'),
4471 _('show only changesets within the given named branch (DEPRECATED)'),
4472 _('BRANCH')),
4472 _('BRANCH')),
4473 ('b', 'branch', [],
4473 ('b', 'branch', [],
4474 _('show changesets within the given named branch'), _('BRANCH')),
4474 _('show changesets within the given named branch'), _('BRANCH')),
4475 ('P', 'prune', [],
4475 ('P', 'prune', [],
4476 _('do not display revision or any of its ancestors'), _('REV')),
4476 _('do not display revision or any of its ancestors'), _('REV')),
4477 ] + logopts + walkopts,
4477 ] + logopts + walkopts,
4478 _('[OPTION]... [FILE]'),
4478 _('[OPTION]... [FILE]'),
4479 inferrepo=True)
4479 inferrepo=True)
4480 def log(ui, repo, *pats, **opts):
4480 def log(ui, repo, *pats, **opts):
4481 """show revision history of entire repository or files
4481 """show revision history of entire repository or files
4482
4482
4483 Print the revision history of the specified files or the entire
4483 Print the revision history of the specified files or the entire
4484 project.
4484 project.
4485
4485
4486 If no revision range is specified, the default is ``tip:0`` unless
4486 If no revision range is specified, the default is ``tip:0`` unless
4487 --follow is set, in which case the working directory parent is
4487 --follow is set, in which case the working directory parent is
4488 used as the starting revision.
4488 used as the starting revision.
4489
4489
4490 File history is shown without following rename or copy history of
4490 File history is shown without following rename or copy history of
4491 files. Use -f/--follow with a filename to follow history across
4491 files. Use -f/--follow with a filename to follow history across
4492 renames and copies. --follow without a filename will only show
4492 renames and copies. --follow without a filename will only show
4493 ancestors or descendants of the starting revision.
4493 ancestors or descendants of the starting revision.
4494
4494
4495 By default this command prints revision number and changeset id,
4495 By default this command prints revision number and changeset id,
4496 tags, non-trivial parents, user, date and time, and a summary for
4496 tags, non-trivial parents, user, date and time, and a summary for
4497 each commit. When the -v/--verbose switch is used, the list of
4497 each commit. When the -v/--verbose switch is used, the list of
4498 changed files and full commit message are shown.
4498 changed files and full commit message are shown.
4499
4499
4500 With --graph the revisions are shown as an ASCII art DAG with the most
4500 With --graph the revisions are shown as an ASCII art DAG with the most
4501 recent changeset at the top.
4501 recent changeset at the top.
4502 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4502 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4503 and '+' represents a fork where the changeset from the lines below is a
4503 and '+' represents a fork where the changeset from the lines below is a
4504 parent of the 'o' merge on the same line.
4504 parent of the 'o' merge on the same line.
4505
4505
4506 .. note::
4506 .. note::
4507
4507
4508 log -p/--patch may generate unexpected diff output for merge
4508 log -p/--patch may generate unexpected diff output for merge
4509 changesets, as it will only compare the merge changeset against
4509 changesets, as it will only compare the merge changeset against
4510 its first parent. Also, only files different from BOTH parents
4510 its first parent. Also, only files different from BOTH parents
4511 will appear in files:.
4511 will appear in files:.
4512
4512
4513 .. note::
4513 .. note::
4514
4514
4515 for performance reasons, log FILE may omit duplicate changes
4515 for performance reasons, log FILE may omit duplicate changes
4516 made on branches and will not show removals or mode changes. To
4516 made on branches and will not show removals or mode changes. To
4517 see all such changes, use the --removed switch.
4517 see all such changes, use the --removed switch.
4518
4518
4519 .. container:: verbose
4519 .. container:: verbose
4520
4520
4521 Some examples:
4521 Some examples:
4522
4522
4523 - changesets with full descriptions and file lists::
4523 - changesets with full descriptions and file lists::
4524
4524
4525 hg log -v
4525 hg log -v
4526
4526
4527 - changesets ancestral to the working directory::
4527 - changesets ancestral to the working directory::
4528
4528
4529 hg log -f
4529 hg log -f
4530
4530
4531 - last 10 commits on the current branch::
4531 - last 10 commits on the current branch::
4532
4532
4533 hg log -l 10 -b .
4533 hg log -l 10 -b .
4534
4534
4535 - changesets showing all modifications of a file, including removals::
4535 - changesets showing all modifications of a file, including removals::
4536
4536
4537 hg log --removed file.c
4537 hg log --removed file.c
4538
4538
4539 - all changesets that touch a directory, with diffs, excluding merges::
4539 - all changesets that touch a directory, with diffs, excluding merges::
4540
4540
4541 hg log -Mp lib/
4541 hg log -Mp lib/
4542
4542
4543 - all revision numbers that match a keyword::
4543 - all revision numbers that match a keyword::
4544
4544
4545 hg log -k bug --template "{rev}\\n"
4545 hg log -k bug --template "{rev}\\n"
4546
4546
4547 - list available log templates::
4547 - list available log templates::
4548
4548
4549 hg log -T list
4549 hg log -T list
4550
4550
4551 - check if a given changeset is included in a tagged release::
4551 - check if a given changeset is included in a tagged release::
4552
4552
4553 hg log -r "a21ccf and ancestor(1.9)"
4553 hg log -r "a21ccf and ancestor(1.9)"
4554
4554
4555 - find all changesets by some user in a date range::
4555 - find all changesets by some user in a date range::
4556
4556
4557 hg log -k alice -d "may 2008 to jul 2008"
4557 hg log -k alice -d "may 2008 to jul 2008"
4558
4558
4559 - summary of all changesets after the last tag::
4559 - summary of all changesets after the last tag::
4560
4560
4561 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4561 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4562
4562
4563 See :hg:`help dates` for a list of formats valid for -d/--date.
4563 See :hg:`help dates` for a list of formats valid for -d/--date.
4564
4564
4565 See :hg:`help revisions` and :hg:`help revsets` for more about
4565 See :hg:`help revisions` and :hg:`help revsets` for more about
4566 specifying revisions.
4566 specifying revisions.
4567
4567
4568 See :hg:`help templates` for more about pre-packaged styles and
4568 See :hg:`help templates` for more about pre-packaged styles and
4569 specifying custom templates.
4569 specifying custom templates.
4570
4570
4571 Returns 0 on success.
4571 Returns 0 on success.
4572
4572
4573 """
4573 """
4574 if opts.get('follow') and opts.get('rev'):
4574 if opts.get('follow') and opts.get('rev'):
4575 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4575 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4576 del opts['follow']
4576 del opts['follow']
4577
4577
4578 if opts.get('graph'):
4578 if opts.get('graph'):
4579 return cmdutil.graphlog(ui, repo, *pats, **opts)
4579 return cmdutil.graphlog(ui, repo, *pats, **opts)
4580
4580
4581 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4581 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4582 limit = cmdutil.loglimit(opts)
4582 limit = cmdutil.loglimit(opts)
4583 count = 0
4583 count = 0
4584
4584
4585 getrenamed = None
4585 getrenamed = None
4586 if opts.get('copies'):
4586 if opts.get('copies'):
4587 endrev = None
4587 endrev = None
4588 if opts.get('rev'):
4588 if opts.get('rev'):
4589 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4589 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4590 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4590 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4591
4591
4592 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4592 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4593 for rev in revs:
4593 for rev in revs:
4594 if count == limit:
4594 if count == limit:
4595 break
4595 break
4596 ctx = repo[rev]
4596 ctx = repo[rev]
4597 copies = None
4597 copies = None
4598 if getrenamed is not None and rev:
4598 if getrenamed is not None and rev:
4599 copies = []
4599 copies = []
4600 for fn in ctx.files():
4600 for fn in ctx.files():
4601 rename = getrenamed(fn, rev)
4601 rename = getrenamed(fn, rev)
4602 if rename:
4602 if rename:
4603 copies.append((fn, rename[0]))
4603 copies.append((fn, rename[0]))
4604 if filematcher:
4604 if filematcher:
4605 revmatchfn = filematcher(ctx.rev())
4605 revmatchfn = filematcher(ctx.rev())
4606 else:
4606 else:
4607 revmatchfn = None
4607 revmatchfn = None
4608 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4608 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4609 if displayer.flush(rev):
4609 if displayer.flush(rev):
4610 count += 1
4610 count += 1
4611
4611
4612 displayer.close()
4612 displayer.close()
4613
4613
4614 @command('manifest',
4614 @command('manifest',
4615 [('r', 'rev', '', _('revision to display'), _('REV')),
4615 [('r', 'rev', '', _('revision to display'), _('REV')),
4616 ('', 'all', False, _("list files from all revisions"))]
4616 ('', 'all', False, _("list files from all revisions"))]
4617 + formatteropts,
4617 + formatteropts,
4618 _('[-r REV]'))
4618 _('[-r REV]'))
4619 def manifest(ui, repo, node=None, rev=None, **opts):
4619 def manifest(ui, repo, node=None, rev=None, **opts):
4620 """output the current or given revision of the project manifest
4620 """output the current or given revision of the project manifest
4621
4621
4622 Print a list of version controlled files for the given revision.
4622 Print a list of version controlled files for the given revision.
4623 If no revision is given, the first parent of the working directory
4623 If no revision is given, the first parent of the working directory
4624 is used, or the null revision if no revision is checked out.
4624 is used, or the null revision if no revision is checked out.
4625
4625
4626 With -v, print file permissions, symlink and executable bits.
4626 With -v, print file permissions, symlink and executable bits.
4627 With --debug, print file revision hashes.
4627 With --debug, print file revision hashes.
4628
4628
4629 If option --all is specified, the list of all files from all revisions
4629 If option --all is specified, the list of all files from all revisions
4630 is printed. This includes deleted and renamed files.
4630 is printed. This includes deleted and renamed files.
4631
4631
4632 Returns 0 on success.
4632 Returns 0 on success.
4633 """
4633 """
4634
4634
4635 fm = ui.formatter('manifest', opts)
4635 fm = ui.formatter('manifest', opts)
4636
4636
4637 if opts.get('all'):
4637 if opts.get('all'):
4638 if rev or node:
4638 if rev or node:
4639 raise util.Abort(_("can't specify a revision with --all"))
4639 raise util.Abort(_("can't specify a revision with --all"))
4640
4640
4641 res = []
4641 res = []
4642 prefix = "data/"
4642 prefix = "data/"
4643 suffix = ".i"
4643 suffix = ".i"
4644 plen = len(prefix)
4644 plen = len(prefix)
4645 slen = len(suffix)
4645 slen = len(suffix)
4646 lock = repo.lock()
4646 lock = repo.lock()
4647 try:
4647 try:
4648 for fn, b, size in repo.store.datafiles():
4648 for fn, b, size in repo.store.datafiles():
4649 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4649 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4650 res.append(fn[plen:-slen])
4650 res.append(fn[plen:-slen])
4651 finally:
4651 finally:
4652 lock.release()
4652 lock.release()
4653 for f in res:
4653 for f in res:
4654 fm.startitem()
4654 fm.startitem()
4655 fm.write("path", '%s\n', f)
4655 fm.write("path", '%s\n', f)
4656 fm.end()
4656 fm.end()
4657 return
4657 return
4658
4658
4659 if rev and node:
4659 if rev and node:
4660 raise util.Abort(_("please specify just one revision"))
4660 raise util.Abort(_("please specify just one revision"))
4661
4661
4662 if not node:
4662 if not node:
4663 node = rev
4663 node = rev
4664
4664
4665 char = {'l': '@', 'x': '*', '': ''}
4665 char = {'l': '@', 'x': '*', '': ''}
4666 mode = {'l': '644', 'x': '755', '': '644'}
4666 mode = {'l': '644', 'x': '755', '': '644'}
4667 ctx = scmutil.revsingle(repo, node)
4667 ctx = scmutil.revsingle(repo, node)
4668 mf = ctx.manifest()
4668 mf = ctx.manifest()
4669 for f in ctx:
4669 for f in ctx:
4670 fm.startitem()
4670 fm.startitem()
4671 fl = ctx[f].flags()
4671 fl = ctx[f].flags()
4672 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4672 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4673 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4673 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4674 fm.write('path', '%s\n', f)
4674 fm.write('path', '%s\n', f)
4675 fm.end()
4675 fm.end()
4676
4676
4677 @command('^merge',
4677 @command('^merge',
4678 [('f', 'force', None,
4678 [('f', 'force', None,
4679 _('force a merge including outstanding changes (DEPRECATED)')),
4679 _('force a merge including outstanding changes (DEPRECATED)')),
4680 ('r', 'rev', '', _('revision to merge'), _('REV')),
4680 ('r', 'rev', '', _('revision to merge'), _('REV')),
4681 ('P', 'preview', None,
4681 ('P', 'preview', None,
4682 _('review revisions to merge (no merge is performed)'))
4682 _('review revisions to merge (no merge is performed)'))
4683 ] + mergetoolopts,
4683 ] + mergetoolopts,
4684 _('[-P] [-f] [[-r] REV]'))
4684 _('[-P] [-f] [[-r] REV]'))
4685 def merge(ui, repo, node=None, **opts):
4685 def merge(ui, repo, node=None, **opts):
4686 """merge another revision into working directory
4686 """merge another revision into working directory
4687
4687
4688 The current working directory is updated with all changes made in
4688 The current working directory is updated with all changes made in
4689 the requested revision since the last common predecessor revision.
4689 the requested revision since the last common predecessor revision.
4690
4690
4691 Files that changed between either parent are marked as changed for
4691 Files that changed between either parent are marked as changed for
4692 the next commit and a commit must be performed before any further
4692 the next commit and a commit must be performed before any further
4693 updates to the repository are allowed. The next commit will have
4693 updates to the repository are allowed. The next commit will have
4694 two parents.
4694 two parents.
4695
4695
4696 ``--tool`` can be used to specify the merge tool used for file
4696 ``--tool`` can be used to specify the merge tool used for file
4697 merges. It overrides the HGMERGE environment variable and your
4697 merges. It overrides the HGMERGE environment variable and your
4698 configuration files. See :hg:`help merge-tools` for options.
4698 configuration files. See :hg:`help merge-tools` for options.
4699
4699
4700 If no revision is specified, the working directory's parent is a
4700 If no revision is specified, the working directory's parent is a
4701 head revision, and the current branch contains exactly one other
4701 head revision, and the current branch contains exactly one other
4702 head, the other head is merged with by default. Otherwise, an
4702 head, the other head is merged with by default. Otherwise, an
4703 explicit revision with which to merge with must be provided.
4703 explicit revision with which to merge with must be provided.
4704
4704
4705 :hg:`resolve` must be used to resolve unresolved files.
4705 :hg:`resolve` must be used to resolve unresolved files.
4706
4706
4707 To undo an uncommitted merge, use :hg:`update --clean .` which
4707 To undo an uncommitted merge, use :hg:`update --clean .` which
4708 will check out a clean copy of the original merge parent, losing
4708 will check out a clean copy of the original merge parent, losing
4709 all changes.
4709 all changes.
4710
4710
4711 Returns 0 on success, 1 if there are unresolved files.
4711 Returns 0 on success, 1 if there are unresolved files.
4712 """
4712 """
4713
4713
4714 if opts.get('rev') and node:
4714 if opts.get('rev') and node:
4715 raise util.Abort(_("please specify just one revision"))
4715 raise util.Abort(_("please specify just one revision"))
4716 if not node:
4716 if not node:
4717 node = opts.get('rev')
4717 node = opts.get('rev')
4718
4718
4719 if node:
4719 if node:
4720 node = scmutil.revsingle(repo, node).node()
4720 node = scmutil.revsingle(repo, node).node()
4721
4721
4722 if not node and repo._activebookmark:
4722 if not node and repo._activebookmark:
4723 bmheads = repo.bookmarkheads(repo._activebookmark)
4723 bmheads = repo.bookmarkheads(repo._activebookmark)
4724 curhead = repo[repo._activebookmark].node()
4724 curhead = repo[repo._activebookmark].node()
4725 if len(bmheads) == 2:
4725 if len(bmheads) == 2:
4726 if curhead == bmheads[0]:
4726 if curhead == bmheads[0]:
4727 node = bmheads[1]
4727 node = bmheads[1]
4728 else:
4728 else:
4729 node = bmheads[0]
4729 node = bmheads[0]
4730 elif len(bmheads) > 2:
4730 elif len(bmheads) > 2:
4731 raise util.Abort(_("multiple matching bookmarks to merge - "
4731 raise util.Abort(_("multiple matching bookmarks to merge - "
4732 "please merge with an explicit rev or bookmark"),
4732 "please merge with an explicit rev or bookmark"),
4733 hint=_("run 'hg heads' to see all heads"))
4733 hint=_("run 'hg heads' to see all heads"))
4734 elif len(bmheads) <= 1:
4734 elif len(bmheads) <= 1:
4735 raise util.Abort(_("no matching bookmark to merge - "
4735 raise util.Abort(_("no matching bookmark to merge - "
4736 "please merge with an explicit rev or bookmark"),
4736 "please merge with an explicit rev or bookmark"),
4737 hint=_("run 'hg heads' to see all heads"))
4737 hint=_("run 'hg heads' to see all heads"))
4738
4738
4739 if not node and not repo._activebookmark:
4739 if not node and not repo._activebookmark:
4740 branch = repo[None].branch()
4740 branch = repo[None].branch()
4741 bheads = repo.branchheads(branch)
4741 bheads = repo.branchheads(branch)
4742 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4742 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4743
4743
4744 if len(nbhs) > 2:
4744 if len(nbhs) > 2:
4745 raise util.Abort(_("branch '%s' has %d heads - "
4745 raise util.Abort(_("branch '%s' has %d heads - "
4746 "please merge with an explicit rev")
4746 "please merge with an explicit rev")
4747 % (branch, len(bheads)),
4747 % (branch, len(bheads)),
4748 hint=_("run 'hg heads .' to see heads"))
4748 hint=_("run 'hg heads .' to see heads"))
4749
4749
4750 parent = repo.dirstate.p1()
4750 parent = repo.dirstate.p1()
4751 if len(nbhs) <= 1:
4751 if len(nbhs) <= 1:
4752 if len(bheads) > 1:
4752 if len(bheads) > 1:
4753 raise util.Abort(_("heads are bookmarked - "
4753 raise util.Abort(_("heads are bookmarked - "
4754 "please merge with an explicit rev"),
4754 "please merge with an explicit rev"),
4755 hint=_("run 'hg heads' to see all heads"))
4755 hint=_("run 'hg heads' to see all heads"))
4756 if len(repo.heads()) > 1:
4756 if len(repo.heads()) > 1:
4757 raise util.Abort(_("branch '%s' has one head - "
4757 raise util.Abort(_("branch '%s' has one head - "
4758 "please merge with an explicit rev")
4758 "please merge with an explicit rev")
4759 % branch,
4759 % branch,
4760 hint=_("run 'hg heads' to see all heads"))
4760 hint=_("run 'hg heads' to see all heads"))
4761 msg, hint = _('nothing to merge'), None
4761 msg, hint = _('nothing to merge'), None
4762 if parent != repo.lookup(branch):
4762 if parent != repo.lookup(branch):
4763 hint = _("use 'hg update' instead")
4763 hint = _("use 'hg update' instead")
4764 raise util.Abort(msg, hint=hint)
4764 raise util.Abort(msg, hint=hint)
4765
4765
4766 if parent not in bheads:
4766 if parent not in bheads:
4767 raise util.Abort(_('working directory not at a head revision'),
4767 raise util.Abort(_('working directory not at a head revision'),
4768 hint=_("use 'hg update' or merge with an "
4768 hint=_("use 'hg update' or merge with an "
4769 "explicit revision"))
4769 "explicit revision"))
4770 if parent == nbhs[0]:
4770 if parent == nbhs[0]:
4771 node = nbhs[-1]
4771 node = nbhs[-1]
4772 else:
4772 else:
4773 node = nbhs[0]
4773 node = nbhs[0]
4774
4774
4775 if opts.get('preview'):
4775 if opts.get('preview'):
4776 # find nodes that are ancestors of p2 but not of p1
4776 # find nodes that are ancestors of p2 but not of p1
4777 p1 = repo.lookup('.')
4777 p1 = repo.lookup('.')
4778 p2 = repo.lookup(node)
4778 p2 = repo.lookup(node)
4779 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4779 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4780
4780
4781 displayer = cmdutil.show_changeset(ui, repo, opts)
4781 displayer = cmdutil.show_changeset(ui, repo, opts)
4782 for node in nodes:
4782 for node in nodes:
4783 displayer.show(repo[node])
4783 displayer.show(repo[node])
4784 displayer.close()
4784 displayer.close()
4785 return 0
4785 return 0
4786
4786
4787 try:
4787 try:
4788 # ui.forcemerge is an internal variable, do not document
4788 # ui.forcemerge is an internal variable, do not document
4789 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4789 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4790 return hg.merge(repo, node, force=opts.get('force'))
4790 return hg.merge(repo, node, force=opts.get('force'))
4791 finally:
4791 finally:
4792 ui.setconfig('ui', 'forcemerge', '', 'merge')
4792 ui.setconfig('ui', 'forcemerge', '', 'merge')
4793
4793
4794 @command('outgoing|out',
4794 @command('outgoing|out',
4795 [('f', 'force', None, _('run even when the destination is unrelated')),
4795 [('f', 'force', None, _('run even when the destination is unrelated')),
4796 ('r', 'rev', [],
4796 ('r', 'rev', [],
4797 _('a changeset intended to be included in the destination'), _('REV')),
4797 _('a changeset intended to be included in the destination'), _('REV')),
4798 ('n', 'newest-first', None, _('show newest record first')),
4798 ('n', 'newest-first', None, _('show newest record first')),
4799 ('B', 'bookmarks', False, _('compare bookmarks')),
4799 ('B', 'bookmarks', False, _('compare bookmarks')),
4800 ('b', 'branch', [], _('a specific branch you would like to push'),
4800 ('b', 'branch', [], _('a specific branch you would like to push'),
4801 _('BRANCH')),
4801 _('BRANCH')),
4802 ] + logopts + remoteopts + subrepoopts,
4802 ] + logopts + remoteopts + subrepoopts,
4803 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4803 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4804 def outgoing(ui, repo, dest=None, **opts):
4804 def outgoing(ui, repo, dest=None, **opts):
4805 """show changesets not found in the destination
4805 """show changesets not found in the destination
4806
4806
4807 Show changesets not found in the specified destination repository
4807 Show changesets not found in the specified destination repository
4808 or the default push location. These are the changesets that would
4808 or the default push location. These are the changesets that would
4809 be pushed if a push was requested.
4809 be pushed if a push was requested.
4810
4810
4811 See pull for details of valid destination formats.
4811 See pull for details of valid destination formats.
4812
4812
4813 .. container:: verbose
4813 .. container:: verbose
4814
4814
4815 With -B/--bookmarks, the result of bookmark comparison between
4815 With -B/--bookmarks, the result of bookmark comparison between
4816 local and remote repositories is displayed. With -v/--verbose,
4816 local and remote repositories is displayed. With -v/--verbose,
4817 status is also displayed for each bookmark like below::
4817 status is also displayed for each bookmark like below::
4818
4818
4819 BM1 01234567890a added
4819 BM1 01234567890a added
4820 BM2 deleted
4820 BM2 deleted
4821 BM3 234567890abc advanced
4821 BM3 234567890abc advanced
4822 BM4 34567890abcd diverged
4822 BM4 34567890abcd diverged
4823 BM5 4567890abcde changed
4823 BM5 4567890abcde changed
4824
4824
4825 The action taken when pushing depends on the
4825 The action taken when pushing depends on the
4826 status of each bookmark:
4826 status of each bookmark:
4827
4827
4828 :``added``: push with ``-B`` will create it
4828 :``added``: push with ``-B`` will create it
4829 :``deleted``: push with ``-B`` will delete it
4829 :``deleted``: push with ``-B`` will delete it
4830 :``advanced``: push will update it
4830 :``advanced``: push will update it
4831 :``diverged``: push with ``-B`` will update it
4831 :``diverged``: push with ``-B`` will update it
4832 :``changed``: push with ``-B`` will update it
4832 :``changed``: push with ``-B`` will update it
4833
4833
4834 From the point of view of pushing behavior, bookmarks
4834 From the point of view of pushing behavior, bookmarks
4835 existing only in the remote repository are treated as
4835 existing only in the remote repository are treated as
4836 ``deleted``, even if it is in fact added remotely.
4836 ``deleted``, even if it is in fact added remotely.
4837
4837
4838 Returns 0 if there are outgoing changes, 1 otherwise.
4838 Returns 0 if there are outgoing changes, 1 otherwise.
4839 """
4839 """
4840 if opts.get('graph'):
4840 if opts.get('graph'):
4841 cmdutil.checkunsupportedgraphflags([], opts)
4841 cmdutil.checkunsupportedgraphflags([], opts)
4842 o, other = hg._outgoing(ui, repo, dest, opts)
4842 o, other = hg._outgoing(ui, repo, dest, opts)
4843 if not o:
4843 if not o:
4844 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4844 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4845 return
4845 return
4846
4846
4847 revdag = cmdutil.graphrevs(repo, o, opts)
4847 revdag = cmdutil.graphrevs(repo, o, opts)
4848 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4848 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4849 showparents = [ctx.node() for ctx in repo[None].parents()]
4849 showparents = [ctx.node() for ctx in repo[None].parents()]
4850 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4850 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4851 graphmod.asciiedges)
4851 graphmod.asciiedges)
4852 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4852 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4853 return 0
4853 return 0
4854
4854
4855 if opts.get('bookmarks'):
4855 if opts.get('bookmarks'):
4856 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4856 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4857 dest, branches = hg.parseurl(dest, opts.get('branch'))
4857 dest, branches = hg.parseurl(dest, opts.get('branch'))
4858 other = hg.peer(repo, opts, dest)
4858 other = hg.peer(repo, opts, dest)
4859 if 'bookmarks' not in other.listkeys('namespaces'):
4859 if 'bookmarks' not in other.listkeys('namespaces'):
4860 ui.warn(_("remote doesn't support bookmarks\n"))
4860 ui.warn(_("remote doesn't support bookmarks\n"))
4861 return 0
4861 return 0
4862 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4862 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4863 return bookmarks.outgoing(ui, repo, other)
4863 return bookmarks.outgoing(ui, repo, other)
4864
4864
4865 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4865 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4866 try:
4866 try:
4867 return hg.outgoing(ui, repo, dest, opts)
4867 return hg.outgoing(ui, repo, dest, opts)
4868 finally:
4868 finally:
4869 del repo._subtoppath
4869 del repo._subtoppath
4870
4870
4871 @command('parents',
4871 @command('parents',
4872 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4872 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4873 ] + templateopts,
4873 ] + templateopts,
4874 _('[-r REV] [FILE]'),
4874 _('[-r REV] [FILE]'),
4875 inferrepo=True)
4875 inferrepo=True)
4876 def parents(ui, repo, file_=None, **opts):
4876 def parents(ui, repo, file_=None, **opts):
4877 """show the parents of the working directory or revision (DEPRECATED)
4877 """show the parents of the working directory or revision (DEPRECATED)
4878
4878
4879 Print the working directory's parent revisions. If a revision is
4879 Print the working directory's parent revisions. If a revision is
4880 given via -r/--rev, the parent of that revision will be printed.
4880 given via -r/--rev, the parent of that revision will be printed.
4881 If a file argument is given, the revision in which the file was
4881 If a file argument is given, the revision in which the file was
4882 last changed (before the working directory revision or the
4882 last changed (before the working directory revision or the
4883 argument to --rev if given) is printed.
4883 argument to --rev if given) is printed.
4884
4884
4885 See :hg:`summary` and :hg:`help revsets` for related information.
4885 See :hg:`summary` and :hg:`help revsets` for related information.
4886
4886
4887 Returns 0 on success.
4887 Returns 0 on success.
4888 """
4888 """
4889
4889
4890 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4890 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4891
4891
4892 if file_:
4892 if file_:
4893 m = scmutil.match(ctx, (file_,), opts)
4893 m = scmutil.match(ctx, (file_,), opts)
4894 if m.anypats() or len(m.files()) != 1:
4894 if m.anypats() or len(m.files()) != 1:
4895 raise util.Abort(_('can only specify an explicit filename'))
4895 raise util.Abort(_('can only specify an explicit filename'))
4896 file_ = m.files()[0]
4896 file_ = m.files()[0]
4897 filenodes = []
4897 filenodes = []
4898 for cp in ctx.parents():
4898 for cp in ctx.parents():
4899 if not cp:
4899 if not cp:
4900 continue
4900 continue
4901 try:
4901 try:
4902 filenodes.append(cp.filenode(file_))
4902 filenodes.append(cp.filenode(file_))
4903 except error.LookupError:
4903 except error.LookupError:
4904 pass
4904 pass
4905 if not filenodes:
4905 if not filenodes:
4906 raise util.Abort(_("'%s' not found in manifest!") % file_)
4906 raise util.Abort(_("'%s' not found in manifest!") % file_)
4907 p = []
4907 p = []
4908 for fn in filenodes:
4908 for fn in filenodes:
4909 fctx = repo.filectx(file_, fileid=fn)
4909 fctx = repo.filectx(file_, fileid=fn)
4910 p.append(fctx.node())
4910 p.append(fctx.node())
4911 else:
4911 else:
4912 p = [cp.node() for cp in ctx.parents()]
4912 p = [cp.node() for cp in ctx.parents()]
4913
4913
4914 displayer = cmdutil.show_changeset(ui, repo, opts)
4914 displayer = cmdutil.show_changeset(ui, repo, opts)
4915 for n in p:
4915 for n in p:
4916 if n != nullid:
4916 if n != nullid:
4917 displayer.show(repo[n])
4917 displayer.show(repo[n])
4918 displayer.close()
4918 displayer.close()
4919
4919
4920 @command('paths', [], _('[NAME]'), optionalrepo=True)
4920 @command('paths', [], _('[NAME]'), optionalrepo=True)
4921 def paths(ui, repo, search=None):
4921 def paths(ui, repo, search=None):
4922 """show aliases for remote repositories
4922 """show aliases for remote repositories
4923
4923
4924 Show definition of symbolic path name NAME. If no name is given,
4924 Show definition of symbolic path name NAME. If no name is given,
4925 show definition of all available names.
4925 show definition of all available names.
4926
4926
4927 Option -q/--quiet suppresses all output when searching for NAME
4927 Option -q/--quiet suppresses all output when searching for NAME
4928 and shows only the path names when listing all definitions.
4928 and shows only the path names when listing all definitions.
4929
4929
4930 Path names are defined in the [paths] section of your
4930 Path names are defined in the [paths] section of your
4931 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4931 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4932 repository, ``.hg/hgrc`` is used, too.
4932 repository, ``.hg/hgrc`` is used, too.
4933
4933
4934 The path names ``default`` and ``default-push`` have a special
4934 The path names ``default`` and ``default-push`` have a special
4935 meaning. When performing a push or pull operation, they are used
4935 meaning. When performing a push or pull operation, they are used
4936 as fallbacks if no location is specified on the command-line.
4936 as fallbacks if no location is specified on the command-line.
4937 When ``default-push`` is set, it will be used for push and
4937 When ``default-push`` is set, it will be used for push and
4938 ``default`` will be used for pull; otherwise ``default`` is used
4938 ``default`` will be used for pull; otherwise ``default`` is used
4939 as the fallback for both. When cloning a repository, the clone
4939 as the fallback for both. When cloning a repository, the clone
4940 source is written as ``default`` in ``.hg/hgrc``. Note that
4940 source is written as ``default`` in ``.hg/hgrc``. Note that
4941 ``default`` and ``default-push`` apply to all inbound (e.g.
4941 ``default`` and ``default-push`` apply to all inbound (e.g.
4942 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4942 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4943 :hg:`bundle`) operations.
4943 :hg:`bundle`) operations.
4944
4944
4945 See :hg:`help urls` for more information.
4945 See :hg:`help urls` for more information.
4946
4946
4947 Returns 0 on success.
4947 Returns 0 on success.
4948 """
4948 """
4949 if search:
4949 if search:
4950 for name, path in sorted(ui.paths.iteritems()):
4950 for name, path in sorted(ui.paths.iteritems()):
4951 if name == search:
4951 if name == search:
4952 ui.status("%s\n" % util.hidepassword(path.loc))
4952 ui.status("%s\n" % util.hidepassword(path.loc))
4953 return
4953 return
4954 if not ui.quiet:
4954 if not ui.quiet:
4955 ui.warn(_("not found!\n"))
4955 ui.warn(_("not found!\n"))
4956 return 1
4956 return 1
4957 else:
4957 else:
4958 for name, path in sorted(ui.paths.iteritems()):
4958 for name, path in sorted(ui.paths.iteritems()):
4959 if ui.quiet:
4959 if ui.quiet:
4960 ui.write("%s\n" % name)
4960 ui.write("%s\n" % name)
4961 else:
4961 else:
4962 ui.write("%s = %s\n" % (name,
4962 ui.write("%s = %s\n" % (name,
4963 util.hidepassword(path.loc)))
4963 util.hidepassword(path.loc)))
4964
4964
4965 @command('phase',
4965 @command('phase',
4966 [('p', 'public', False, _('set changeset phase to public')),
4966 [('p', 'public', False, _('set changeset phase to public')),
4967 ('d', 'draft', False, _('set changeset phase to draft')),
4967 ('d', 'draft', False, _('set changeset phase to draft')),
4968 ('s', 'secret', False, _('set changeset phase to secret')),
4968 ('s', 'secret', False, _('set changeset phase to secret')),
4969 ('f', 'force', False, _('allow to move boundary backward')),
4969 ('f', 'force', False, _('allow to move boundary backward')),
4970 ('r', 'rev', [], _('target revision'), _('REV')),
4970 ('r', 'rev', [], _('target revision'), _('REV')),
4971 ],
4971 ],
4972 _('[-p|-d|-s] [-f] [-r] [REV...]'))
4972 _('[-p|-d|-s] [-f] [-r] [REV...]'))
4973 def phase(ui, repo, *revs, **opts):
4973 def phase(ui, repo, *revs, **opts):
4974 """set or show the current phase name
4974 """set or show the current phase name
4975
4975
4976 With no argument, show the phase name of the current revision(s).
4976 With no argument, show the phase name of the current revision(s).
4977
4977
4978 With one of -p/--public, -d/--draft or -s/--secret, change the
4978 With one of -p/--public, -d/--draft or -s/--secret, change the
4979 phase value of the specified revisions.
4979 phase value of the specified revisions.
4980
4980
4981 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4981 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4982 lower phase to an higher phase. Phases are ordered as follows::
4982 lower phase to an higher phase. Phases are ordered as follows::
4983
4983
4984 public < draft < secret
4984 public < draft < secret
4985
4985
4986 Returns 0 on success, 1 if no phases were changed or some could not
4986 Returns 0 on success, 1 if no phases were changed or some could not
4987 be changed.
4987 be changed.
4988 """
4988 """
4989 # search for a unique phase argument
4989 # search for a unique phase argument
4990 targetphase = None
4990 targetphase = None
4991 for idx, name in enumerate(phases.phasenames):
4991 for idx, name in enumerate(phases.phasenames):
4992 if opts[name]:
4992 if opts[name]:
4993 if targetphase is not None:
4993 if targetphase is not None:
4994 raise util.Abort(_('only one phase can be specified'))
4994 raise util.Abort(_('only one phase can be specified'))
4995 targetphase = idx
4995 targetphase = idx
4996
4996
4997 # look for specified revision
4997 # look for specified revision
4998 revs = list(revs)
4998 revs = list(revs)
4999 revs.extend(opts['rev'])
4999 revs.extend(opts['rev'])
5000 if not revs:
5000 if not revs:
5001 # display both parents as the second parent phase can influence
5001 # display both parents as the second parent phase can influence
5002 # the phase of a merge commit
5002 # the phase of a merge commit
5003 revs = [c.rev() for c in repo[None].parents()]
5003 revs = [c.rev() for c in repo[None].parents()]
5004
5004
5005 revs = scmutil.revrange(repo, revs)
5005 revs = scmutil.revrange(repo, revs)
5006
5006
5007 lock = None
5007 lock = None
5008 ret = 0
5008 ret = 0
5009 if targetphase is None:
5009 if targetphase is None:
5010 # display
5010 # display
5011 for r in revs:
5011 for r in revs:
5012 ctx = repo[r]
5012 ctx = repo[r]
5013 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5013 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5014 else:
5014 else:
5015 tr = None
5015 tr = None
5016 lock = repo.lock()
5016 lock = repo.lock()
5017 try:
5017 try:
5018 tr = repo.transaction("phase")
5018 tr = repo.transaction("phase")
5019 # set phase
5019 # set phase
5020 if not revs:
5020 if not revs:
5021 raise util.Abort(_('empty revision set'))
5021 raise util.Abort(_('empty revision set'))
5022 nodes = [repo[r].node() for r in revs]
5022 nodes = [repo[r].node() for r in revs]
5023 # moving revision from public to draft may hide them
5023 # moving revision from public to draft may hide them
5024 # We have to check result on an unfiltered repository
5024 # We have to check result on an unfiltered repository
5025 unfi = repo.unfiltered()
5025 unfi = repo.unfiltered()
5026 getphase = unfi._phasecache.phase
5026 getphase = unfi._phasecache.phase
5027 olddata = [getphase(unfi, r) for r in unfi]
5027 olddata = [getphase(unfi, r) for r in unfi]
5028 phases.advanceboundary(repo, tr, targetphase, nodes)
5028 phases.advanceboundary(repo, tr, targetphase, nodes)
5029 if opts['force']:
5029 if opts['force']:
5030 phases.retractboundary(repo, tr, targetphase, nodes)
5030 phases.retractboundary(repo, tr, targetphase, nodes)
5031 tr.close()
5031 tr.close()
5032 finally:
5032 finally:
5033 if tr is not None:
5033 if tr is not None:
5034 tr.release()
5034 tr.release()
5035 lock.release()
5035 lock.release()
5036 getphase = unfi._phasecache.phase
5036 getphase = unfi._phasecache.phase
5037 newdata = [getphase(unfi, r) for r in unfi]
5037 newdata = [getphase(unfi, r) for r in unfi]
5038 changes = sum(newdata[r] != olddata[r] for r in unfi)
5038 changes = sum(newdata[r] != olddata[r] for r in unfi)
5039 cl = unfi.changelog
5039 cl = unfi.changelog
5040 rejected = [n for n in nodes
5040 rejected = [n for n in nodes
5041 if newdata[cl.rev(n)] < targetphase]
5041 if newdata[cl.rev(n)] < targetphase]
5042 if rejected:
5042 if rejected:
5043 ui.warn(_('cannot move %i changesets to a higher '
5043 ui.warn(_('cannot move %i changesets to a higher '
5044 'phase, use --force\n') % len(rejected))
5044 'phase, use --force\n') % len(rejected))
5045 ret = 1
5045 ret = 1
5046 if changes:
5046 if changes:
5047 msg = _('phase changed for %i changesets\n') % changes
5047 msg = _('phase changed for %i changesets\n') % changes
5048 if ret:
5048 if ret:
5049 ui.status(msg)
5049 ui.status(msg)
5050 else:
5050 else:
5051 ui.note(msg)
5051 ui.note(msg)
5052 else:
5052 else:
5053 ui.warn(_('no phases changed\n'))
5053 ui.warn(_('no phases changed\n'))
5054 ret = 1
5054 ret = 1
5055 return ret
5055 return ret
5056
5056
5057 def postincoming(ui, repo, modheads, optupdate, checkout):
5057 def postincoming(ui, repo, modheads, optupdate, checkout):
5058 if modheads == 0:
5058 if modheads == 0:
5059 return
5059 return
5060 if optupdate:
5060 if optupdate:
5061 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5061 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5062 try:
5062 try:
5063 ret = hg.update(repo, checkout)
5063 ret = hg.update(repo, checkout)
5064 except util.Abort, inst:
5064 except util.Abort, inst:
5065 ui.warn(_("not updating: %s\n") % str(inst))
5065 ui.warn(_("not updating: %s\n") % str(inst))
5066 if inst.hint:
5066 if inst.hint:
5067 ui.warn(_("(%s)\n") % inst.hint)
5067 ui.warn(_("(%s)\n") % inst.hint)
5068 return 0
5068 return 0
5069 if not ret and not checkout:
5069 if not ret and not checkout:
5070 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5070 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5071 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5071 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5072 return ret
5072 return ret
5073 if modheads > 1:
5073 if modheads > 1:
5074 currentbranchheads = len(repo.branchheads())
5074 currentbranchheads = len(repo.branchheads())
5075 if currentbranchheads == modheads:
5075 if currentbranchheads == modheads:
5076 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5076 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5077 elif currentbranchheads > 1:
5077 elif currentbranchheads > 1:
5078 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5078 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5079 "merge)\n"))
5079 "merge)\n"))
5080 else:
5080 else:
5081 ui.status(_("(run 'hg heads' to see heads)\n"))
5081 ui.status(_("(run 'hg heads' to see heads)\n"))
5082 else:
5082 else:
5083 ui.status(_("(run 'hg update' to get a working copy)\n"))
5083 ui.status(_("(run 'hg update' to get a working copy)\n"))
5084
5084
5085 @command('^pull',
5085 @command('^pull',
5086 [('u', 'update', None,
5086 [('u', 'update', None,
5087 _('update to new branch head if changesets were pulled')),
5087 _('update to new branch head if changesets were pulled')),
5088 ('f', 'force', None, _('run even when remote repository is unrelated')),
5088 ('f', 'force', None, _('run even when remote repository is unrelated')),
5089 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5089 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5090 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5090 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5091 ('b', 'branch', [], _('a specific branch you would like to pull'),
5091 ('b', 'branch', [], _('a specific branch you would like to pull'),
5092 _('BRANCH')),
5092 _('BRANCH')),
5093 ] + remoteopts,
5093 ] + remoteopts,
5094 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5094 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5095 def pull(ui, repo, source="default", **opts):
5095 def pull(ui, repo, source="default", **opts):
5096 """pull changes from the specified source
5096 """pull changes from the specified source
5097
5097
5098 Pull changes from a remote repository to a local one.
5098 Pull changes from a remote repository to a local one.
5099
5099
5100 This finds all changes from the repository at the specified path
5100 This finds all changes from the repository at the specified path
5101 or URL and adds them to a local repository (the current one unless
5101 or URL and adds them to a local repository (the current one unless
5102 -R is specified). By default, this does not update the copy of the
5102 -R is specified). By default, this does not update the copy of the
5103 project in the working directory.
5103 project in the working directory.
5104
5104
5105 Use :hg:`incoming` if you want to see what would have been added
5105 Use :hg:`incoming` if you want to see what would have been added
5106 by a pull at the time you issued this command. If you then decide
5106 by a pull at the time you issued this command. If you then decide
5107 to add those changes to the repository, you should use :hg:`pull
5107 to add those changes to the repository, you should use :hg:`pull
5108 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5108 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5109
5109
5110 If SOURCE is omitted, the 'default' path will be used.
5110 If SOURCE is omitted, the 'default' path will be used.
5111 See :hg:`help urls` for more information.
5111 See :hg:`help urls` for more information.
5112
5112
5113 Returns 0 on success, 1 if an update had unresolved files.
5113 Returns 0 on success, 1 if an update had unresolved files.
5114 """
5114 """
5115 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5115 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5116 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5116 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5117 other = hg.peer(repo, opts, source)
5117 other = hg.peer(repo, opts, source)
5118 try:
5118 try:
5119 revs, checkout = hg.addbranchrevs(repo, other, branches,
5119 revs, checkout = hg.addbranchrevs(repo, other, branches,
5120 opts.get('rev'))
5120 opts.get('rev'))
5121
5121
5122
5122
5123 pullopargs = {}
5123 pullopargs = {}
5124 if opts.get('bookmark'):
5124 if opts.get('bookmark'):
5125 if not revs:
5125 if not revs:
5126 revs = []
5126 revs = []
5127 # The list of bookmark used here is not the one used to actually
5127 # The list of bookmark used here is not the one used to actually
5128 # update the bookmark name. This can result in the revision pulled
5128 # update the bookmark name. This can result in the revision pulled
5129 # not ending up with the name of the bookmark because of a race
5129 # not ending up with the name of the bookmark because of a race
5130 # condition on the server. (See issue 4689 for details)
5130 # condition on the server. (See issue 4689 for details)
5131 remotebookmarks = other.listkeys('bookmarks')
5131 remotebookmarks = other.listkeys('bookmarks')
5132 pullopargs['remotebookmarks'] = remotebookmarks
5132 pullopargs['remotebookmarks'] = remotebookmarks
5133 for b in opts['bookmark']:
5133 for b in opts['bookmark']:
5134 if b not in remotebookmarks:
5134 if b not in remotebookmarks:
5135 raise util.Abort(_('remote bookmark %s not found!') % b)
5135 raise util.Abort(_('remote bookmark %s not found!') % b)
5136 revs.append(remotebookmarks[b])
5136 revs.append(remotebookmarks[b])
5137
5137
5138 if revs:
5138 if revs:
5139 try:
5139 try:
5140 # When 'rev' is a bookmark name, we cannot guarantee that it
5140 # When 'rev' is a bookmark name, we cannot guarantee that it
5141 # will be updated with that name because of a race condition
5141 # will be updated with that name because of a race condition
5142 # server side. (See issue 4689 for details)
5142 # server side. (See issue 4689 for details)
5143 oldrevs = revs
5143 oldrevs = revs
5144 revs = [] # actually, nodes
5144 revs = [] # actually, nodes
5145 for r in oldrevs:
5145 for r in oldrevs:
5146 node = other.lookup(r)
5146 node = other.lookup(r)
5147 revs.append(node)
5147 revs.append(node)
5148 if r == checkout:
5148 if r == checkout:
5149 checkout = node
5149 checkout = node
5150 except error.CapabilityError:
5150 except error.CapabilityError:
5151 err = _("other repository doesn't support revision lookup, "
5151 err = _("other repository doesn't support revision lookup, "
5152 "so a rev cannot be specified.")
5152 "so a rev cannot be specified.")
5153 raise util.Abort(err)
5153 raise util.Abort(err)
5154
5154
5155 modheads = exchange.pull(repo, other, heads=revs,
5155 modheads = exchange.pull(repo, other, heads=revs,
5156 force=opts.get('force'),
5156 force=opts.get('force'),
5157 bookmarks=opts.get('bookmark', ()),
5157 bookmarks=opts.get('bookmark', ()),
5158 opargs=pullopargs).cgresult
5158 opargs=pullopargs).cgresult
5159 if checkout:
5159 if checkout:
5160 checkout = str(repo.changelog.rev(checkout))
5160 checkout = str(repo.changelog.rev(checkout))
5161 repo._subtoppath = source
5161 repo._subtoppath = source
5162 try:
5162 try:
5163 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5163 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5164
5164
5165 finally:
5165 finally:
5166 del repo._subtoppath
5166 del repo._subtoppath
5167
5167
5168 finally:
5168 finally:
5169 other.close()
5169 other.close()
5170 return ret
5170 return ret
5171
5171
5172 @command('^push',
5172 @command('^push',
5173 [('f', 'force', None, _('force push')),
5173 [('f', 'force', None, _('force push')),
5174 ('r', 'rev', [],
5174 ('r', 'rev', [],
5175 _('a changeset intended to be included in the destination'),
5175 _('a changeset intended to be included in the destination'),
5176 _('REV')),
5176 _('REV')),
5177 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5177 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5178 ('b', 'branch', [],
5178 ('b', 'branch', [],
5179 _('a specific branch you would like to push'), _('BRANCH')),
5179 _('a specific branch you would like to push'), _('BRANCH')),
5180 ('', 'new-branch', False, _('allow pushing a new branch')),
5180 ('', 'new-branch', False, _('allow pushing a new branch')),
5181 ] + remoteopts,
5181 ] + remoteopts,
5182 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5182 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5183 def push(ui, repo, dest=None, **opts):
5183 def push(ui, repo, dest=None, **opts):
5184 """push changes to the specified destination
5184 """push changes to the specified destination
5185
5185
5186 Push changesets from the local repository to the specified
5186 Push changesets from the local repository to the specified
5187 destination.
5187 destination.
5188
5188
5189 This operation is symmetrical to pull: it is identical to a pull
5189 This operation is symmetrical to pull: it is identical to a pull
5190 in the destination repository from the current one.
5190 in the destination repository from the current one.
5191
5191
5192 By default, push will not allow creation of new heads at the
5192 By default, push will not allow creation of new heads at the
5193 destination, since multiple heads would make it unclear which head
5193 destination, since multiple heads would make it unclear which head
5194 to use. In this situation, it is recommended to pull and merge
5194 to use. In this situation, it is recommended to pull and merge
5195 before pushing.
5195 before pushing.
5196
5196
5197 Use --new-branch if you want to allow push to create a new named
5197 Use --new-branch if you want to allow push to create a new named
5198 branch that is not present at the destination. This allows you to
5198 branch that is not present at the destination. This allows you to
5199 only create a new branch without forcing other changes.
5199 only create a new branch without forcing other changes.
5200
5200
5201 .. note::
5201 .. note::
5202
5202
5203 Extra care should be taken with the -f/--force option,
5203 Extra care should be taken with the -f/--force option,
5204 which will push all new heads on all branches, an action which will
5204 which will push all new heads on all branches, an action which will
5205 almost always cause confusion for collaborators.
5205 almost always cause confusion for collaborators.
5206
5206
5207 If -r/--rev is used, the specified revision and all its ancestors
5207 If -r/--rev is used, the specified revision and all its ancestors
5208 will be pushed to the remote repository.
5208 will be pushed to the remote repository.
5209
5209
5210 If -B/--bookmark is used, the specified bookmarked revision, its
5210 If -B/--bookmark is used, the specified bookmarked revision, its
5211 ancestors, and the bookmark will be pushed to the remote
5211 ancestors, and the bookmark will be pushed to the remote
5212 repository.
5212 repository.
5213
5213
5214 Please see :hg:`help urls` for important details about ``ssh://``
5214 Please see :hg:`help urls` for important details about ``ssh://``
5215 URLs. If DESTINATION is omitted, a default path will be used.
5215 URLs. If DESTINATION is omitted, a default path will be used.
5216
5216
5217 Returns 0 if push was successful, 1 if nothing to push.
5217 Returns 0 if push was successful, 1 if nothing to push.
5218 """
5218 """
5219
5219
5220 if opts.get('bookmark'):
5220 if opts.get('bookmark'):
5221 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5221 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5222 for b in opts['bookmark']:
5222 for b in opts['bookmark']:
5223 # translate -B options to -r so changesets get pushed
5223 # translate -B options to -r so changesets get pushed
5224 if b in repo._bookmarks:
5224 if b in repo._bookmarks:
5225 opts.setdefault('rev', []).append(b)
5225 opts.setdefault('rev', []).append(b)
5226 else:
5226 else:
5227 # if we try to push a deleted bookmark, translate it to null
5227 # if we try to push a deleted bookmark, translate it to null
5228 # this lets simultaneous -r, -b options continue working
5228 # this lets simultaneous -r, -b options continue working
5229 opts.setdefault('rev', []).append("null")
5229 opts.setdefault('rev', []).append("null")
5230
5230
5231 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5231 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5232 dest, branches = hg.parseurl(dest, opts.get('branch'))
5232 dest, branches = hg.parseurl(dest, opts.get('branch'))
5233 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5233 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5234 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5234 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5235 try:
5235 try:
5236 other = hg.peer(repo, opts, dest)
5236 other = hg.peer(repo, opts, dest)
5237 except error.RepoError:
5237 except error.RepoError:
5238 if dest == "default-push":
5238 if dest == "default-push":
5239 raise util.Abort(_("default repository not configured!"),
5239 raise util.Abort(_("default repository not configured!"),
5240 hint=_('see the "path" section in "hg help config"'))
5240 hint=_('see the "path" section in "hg help config"'))
5241 else:
5241 else:
5242 raise
5242 raise
5243
5243
5244 if revs:
5244 if revs:
5245 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5245 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5246 if not revs:
5246 if not revs:
5247 raise util.Abort(_("specified revisions evaluate to an empty set"),
5247 raise util.Abort(_("specified revisions evaluate to an empty set"),
5248 hint=_("use different revision arguments"))
5248 hint=_("use different revision arguments"))
5249
5249
5250 repo._subtoppath = dest
5250 repo._subtoppath = dest
5251 try:
5251 try:
5252 # push subrepos depth-first for coherent ordering
5252 # push subrepos depth-first for coherent ordering
5253 c = repo['']
5253 c = repo['']
5254 subs = c.substate # only repos that are committed
5254 subs = c.substate # only repos that are committed
5255 for s in sorted(subs):
5255 for s in sorted(subs):
5256 result = c.sub(s).push(opts)
5256 result = c.sub(s).push(opts)
5257 if result == 0:
5257 if result == 0:
5258 return not result
5258 return not result
5259 finally:
5259 finally:
5260 del repo._subtoppath
5260 del repo._subtoppath
5261 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5261 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5262 newbranch=opts.get('new_branch'),
5262 newbranch=opts.get('new_branch'),
5263 bookmarks=opts.get('bookmark', ()))
5263 bookmarks=opts.get('bookmark', ()))
5264
5264
5265 result = not pushop.cgresult
5265 result = not pushop.cgresult
5266
5266
5267 if pushop.bkresult is not None:
5267 if pushop.bkresult is not None:
5268 if pushop.bkresult == 2:
5268 if pushop.bkresult == 2:
5269 result = 2
5269 result = 2
5270 elif not result and pushop.bkresult:
5270 elif not result and pushop.bkresult:
5271 result = 2
5271 result = 2
5272
5272
5273 return result
5273 return result
5274
5274
5275 @command('recover', [])
5275 @command('recover', [])
5276 def recover(ui, repo):
5276 def recover(ui, repo):
5277 """roll back an interrupted transaction
5277 """roll back an interrupted transaction
5278
5278
5279 Recover from an interrupted commit or pull.
5279 Recover from an interrupted commit or pull.
5280
5280
5281 This command tries to fix the repository status after an
5281 This command tries to fix the repository status after an
5282 interrupted operation. It should only be necessary when Mercurial
5282 interrupted operation. It should only be necessary when Mercurial
5283 suggests it.
5283 suggests it.
5284
5284
5285 Returns 0 if successful, 1 if nothing to recover or verify fails.
5285 Returns 0 if successful, 1 if nothing to recover or verify fails.
5286 """
5286 """
5287 if repo.recover():
5287 if repo.recover():
5288 return hg.verify(repo)
5288 return hg.verify(repo)
5289 return 1
5289 return 1
5290
5290
5291 @command('^remove|rm',
5291 @command('^remove|rm',
5292 [('A', 'after', None, _('record delete for missing files')),
5292 [('A', 'after', None, _('record delete for missing files')),
5293 ('f', 'force', None,
5293 ('f', 'force', None,
5294 _('remove (and delete) file even if added or modified')),
5294 _('remove (and delete) file even if added or modified')),
5295 ] + subrepoopts + walkopts,
5295 ] + subrepoopts + walkopts,
5296 _('[OPTION]... FILE...'),
5296 _('[OPTION]... FILE...'),
5297 inferrepo=True)
5297 inferrepo=True)
5298 def remove(ui, repo, *pats, **opts):
5298 def remove(ui, repo, *pats, **opts):
5299 """remove the specified files on the next commit
5299 """remove the specified files on the next commit
5300
5300
5301 Schedule the indicated files for removal from the current branch.
5301 Schedule the indicated files for removal from the current branch.
5302
5302
5303 This command schedules the files to be removed at the next commit.
5303 This command schedules the files to be removed at the next commit.
5304 To undo a remove before that, see :hg:`revert`. To undo added
5304 To undo a remove before that, see :hg:`revert`. To undo added
5305 files, see :hg:`forget`.
5305 files, see :hg:`forget`.
5306
5306
5307 .. container:: verbose
5307 .. container:: verbose
5308
5308
5309 -A/--after can be used to remove only files that have already
5309 -A/--after can be used to remove only files that have already
5310 been deleted, -f/--force can be used to force deletion, and -Af
5310 been deleted, -f/--force can be used to force deletion, and -Af
5311 can be used to remove files from the next revision without
5311 can be used to remove files from the next revision without
5312 deleting them from the working directory.
5312 deleting them from the working directory.
5313
5313
5314 The following table details the behavior of remove for different
5314 The following table details the behavior of remove for different
5315 file states (columns) and option combinations (rows). The file
5315 file states (columns) and option combinations (rows). The file
5316 states are Added [A], Clean [C], Modified [M] and Missing [!]
5316 states are Added [A], Clean [C], Modified [M] and Missing [!]
5317 (as reported by :hg:`status`). The actions are Warn, Remove
5317 (as reported by :hg:`status`). The actions are Warn, Remove
5318 (from branch) and Delete (from disk):
5318 (from branch) and Delete (from disk):
5319
5319
5320 ========= == == == ==
5320 ========= == == == ==
5321 opt/state A C M !
5321 opt/state A C M !
5322 ========= == == == ==
5322 ========= == == == ==
5323 none W RD W R
5323 none W RD W R
5324 -f R RD RD R
5324 -f R RD RD R
5325 -A W W W R
5325 -A W W W R
5326 -Af R R R R
5326 -Af R R R R
5327 ========= == == == ==
5327 ========= == == == ==
5328
5328
5329 Note that remove never deletes files in Added [A] state from the
5329 Note that remove never deletes files in Added [A] state from the
5330 working directory, not even if option --force is specified.
5330 working directory, not even if option --force is specified.
5331
5331
5332 Returns 0 on success, 1 if any warnings encountered.
5332 Returns 0 on success, 1 if any warnings encountered.
5333 """
5333 """
5334
5334
5335 after, force = opts.get('after'), opts.get('force')
5335 after, force = opts.get('after'), opts.get('force')
5336 if not pats and not after:
5336 if not pats and not after:
5337 raise util.Abort(_('no files specified'))
5337 raise util.Abort(_('no files specified'))
5338
5338
5339 m = scmutil.match(repo[None], pats, opts)
5339 m = scmutil.match(repo[None], pats, opts)
5340 subrepos = opts.get('subrepos')
5340 subrepos = opts.get('subrepos')
5341 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5341 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5342
5342
5343 @command('rename|move|mv',
5343 @command('rename|move|mv',
5344 [('A', 'after', None, _('record a rename that has already occurred')),
5344 [('A', 'after', None, _('record a rename that has already occurred')),
5345 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5345 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5346 ] + walkopts + dryrunopts,
5346 ] + walkopts + dryrunopts,
5347 _('[OPTION]... SOURCE... DEST'))
5347 _('[OPTION]... SOURCE... DEST'))
5348 def rename(ui, repo, *pats, **opts):
5348 def rename(ui, repo, *pats, **opts):
5349 """rename files; equivalent of copy + remove
5349 """rename files; equivalent of copy + remove
5350
5350
5351 Mark dest as copies of sources; mark sources for deletion. If dest
5351 Mark dest as copies of sources; mark sources for deletion. If dest
5352 is a directory, copies are put in that directory. If dest is a
5352 is a directory, copies are put in that directory. If dest is a
5353 file, there can only be one source.
5353 file, there can only be one source.
5354
5354
5355 By default, this command copies the contents of files as they
5355 By default, this command copies the contents of files as they
5356 exist in the working directory. If invoked with -A/--after, the
5356 exist in the working directory. If invoked with -A/--after, the
5357 operation is recorded, but no copying is performed.
5357 operation is recorded, but no copying is performed.
5358
5358
5359 This command takes effect at the next commit. To undo a rename
5359 This command takes effect at the next commit. To undo a rename
5360 before that, see :hg:`revert`.
5360 before that, see :hg:`revert`.
5361
5361
5362 Returns 0 on success, 1 if errors are encountered.
5362 Returns 0 on success, 1 if errors are encountered.
5363 """
5363 """
5364 wlock = repo.wlock(False)
5364 wlock = repo.wlock(False)
5365 try:
5365 try:
5366 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5366 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5367 finally:
5367 finally:
5368 wlock.release()
5368 wlock.release()
5369
5369
5370 @command('resolve',
5370 @command('resolve',
5371 [('a', 'all', None, _('select all unresolved files')),
5371 [('a', 'all', None, _('select all unresolved files')),
5372 ('l', 'list', None, _('list state of files needing merge')),
5372 ('l', 'list', None, _('list state of files needing merge')),
5373 ('m', 'mark', None, _('mark files as resolved')),
5373 ('m', 'mark', None, _('mark files as resolved')),
5374 ('u', 'unmark', None, _('mark files as unresolved')),
5374 ('u', 'unmark', None, _('mark files as unresolved')),
5375 ('n', 'no-status', None, _('hide status prefix'))]
5375 ('n', 'no-status', None, _('hide status prefix'))]
5376 + mergetoolopts + walkopts + formatteropts,
5376 + mergetoolopts + walkopts + formatteropts,
5377 _('[OPTION]... [FILE]...'),
5377 _('[OPTION]... [FILE]...'),
5378 inferrepo=True)
5378 inferrepo=True)
5379 def resolve(ui, repo, *pats, **opts):
5379 def resolve(ui, repo, *pats, **opts):
5380 """redo merges or set/view the merge status of files
5380 """redo merges or set/view the merge status of files
5381
5381
5382 Merges with unresolved conflicts are often the result of
5382 Merges with unresolved conflicts are often the result of
5383 non-interactive merging using the ``internal:merge`` configuration
5383 non-interactive merging using the ``internal:merge`` configuration
5384 setting, or a command-line merge tool like ``diff3``. The resolve
5384 setting, or a command-line merge tool like ``diff3``. The resolve
5385 command is used to manage the files involved in a merge, after
5385 command is used to manage the files involved in a merge, after
5386 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5386 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5387 working directory must have two parents). See :hg:`help
5387 working directory must have two parents). See :hg:`help
5388 merge-tools` for information on configuring merge tools.
5388 merge-tools` for information on configuring merge tools.
5389
5389
5390 The resolve command can be used in the following ways:
5390 The resolve command can be used in the following ways:
5391
5391
5392 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5392 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5393 files, discarding any previous merge attempts. Re-merging is not
5393 files, discarding any previous merge attempts. Re-merging is not
5394 performed for files already marked as resolved. Use ``--all/-a``
5394 performed for files already marked as resolved. Use ``--all/-a``
5395 to select all unresolved files. ``--tool`` can be used to specify
5395 to select all unresolved files. ``--tool`` can be used to specify
5396 the merge tool used for the given files. It overrides the HGMERGE
5396 the merge tool used for the given files. It overrides the HGMERGE
5397 environment variable and your configuration files. Previous file
5397 environment variable and your configuration files. Previous file
5398 contents are saved with a ``.orig`` suffix.
5398 contents are saved with a ``.orig`` suffix.
5399
5399
5400 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5400 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5401 (e.g. after having manually fixed-up the files). The default is
5401 (e.g. after having manually fixed-up the files). The default is
5402 to mark all unresolved files.
5402 to mark all unresolved files.
5403
5403
5404 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5404 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5405 default is to mark all resolved files.
5405 default is to mark all resolved files.
5406
5406
5407 - :hg:`resolve -l`: list files which had or still have conflicts.
5407 - :hg:`resolve -l`: list files which had or still have conflicts.
5408 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5408 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5409
5409
5410 Note that Mercurial will not let you commit files with unresolved
5410 Note that Mercurial will not let you commit files with unresolved
5411 merge conflicts. You must use :hg:`resolve -m ...` before you can
5411 merge conflicts. You must use :hg:`resolve -m ...` before you can
5412 commit after a conflicting merge.
5412 commit after a conflicting merge.
5413
5413
5414 Returns 0 on success, 1 if any files fail a resolve attempt.
5414 Returns 0 on success, 1 if any files fail a resolve attempt.
5415 """
5415 """
5416
5416
5417 all, mark, unmark, show, nostatus = \
5417 all, mark, unmark, show, nostatus = \
5418 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5418 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5419
5419
5420 if (show and (mark or unmark)) or (mark and unmark):
5420 if (show and (mark or unmark)) or (mark and unmark):
5421 raise util.Abort(_("too many options specified"))
5421 raise util.Abort(_("too many options specified"))
5422 if pats and all:
5422 if pats and all:
5423 raise util.Abort(_("can't specify --all and patterns"))
5423 raise util.Abort(_("can't specify --all and patterns"))
5424 if not (all or pats or show or mark or unmark):
5424 if not (all or pats or show or mark or unmark):
5425 raise util.Abort(_('no files or directories specified'),
5425 raise util.Abort(_('no files or directories specified'),
5426 hint=('use --all to remerge all files'))
5426 hint=('use --all to remerge all files'))
5427
5427
5428 if show:
5428 if show:
5429 fm = ui.formatter('resolve', opts)
5429 fm = ui.formatter('resolve', opts)
5430 ms = mergemod.mergestate(repo)
5430 ms = mergemod.mergestate(repo)
5431 m = scmutil.match(repo[None], pats, opts)
5431 m = scmutil.match(repo[None], pats, opts)
5432 for f in ms:
5432 for f in ms:
5433 if not m(f):
5433 if not m(f):
5434 continue
5434 continue
5435 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5435 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5436 fm.startitem()
5436 fm.startitem()
5437 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5437 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5438 fm.write('path', '%s\n', f, label=l)
5438 fm.write('path', '%s\n', f, label=l)
5439 fm.end()
5439 fm.end()
5440 return 0
5440 return 0
5441
5441
5442 wlock = repo.wlock()
5442 wlock = repo.wlock()
5443 try:
5443 try:
5444 ms = mergemod.mergestate(repo)
5444 ms = mergemod.mergestate(repo)
5445
5445
5446 if not (ms.active() or repo.dirstate.p2() != nullid):
5446 if not (ms.active() or repo.dirstate.p2() != nullid):
5447 raise util.Abort(
5447 raise util.Abort(
5448 _('resolve command not applicable when not merging'))
5448 _('resolve command not applicable when not merging'))
5449
5449
5450 m = scmutil.match(repo[None], pats, opts)
5450 m = scmutil.match(repo[None], pats, opts)
5451 ret = 0
5451 ret = 0
5452 didwork = False
5452 didwork = False
5453
5453
5454 for f in ms:
5454 for f in ms:
5455 if not m(f):
5455 if not m(f):
5456 continue
5456 continue
5457
5457
5458 didwork = True
5458 didwork = True
5459
5459
5460 if mark:
5460 if mark:
5461 ms.mark(f, "r")
5461 ms.mark(f, "r")
5462 elif unmark:
5462 elif unmark:
5463 ms.mark(f, "u")
5463 ms.mark(f, "u")
5464 else:
5464 else:
5465 wctx = repo[None]
5465 wctx = repo[None]
5466
5466
5467 # backup pre-resolve (merge uses .orig for its own purposes)
5467 # backup pre-resolve (merge uses .orig for its own purposes)
5468 a = repo.wjoin(f)
5468 a = repo.wjoin(f)
5469 util.copyfile(a, a + ".resolve")
5469 util.copyfile(a, a + ".resolve")
5470
5470
5471 try:
5471 try:
5472 # resolve file
5472 # resolve file
5473 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5473 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5474 'resolve')
5474 'resolve')
5475 if ms.resolve(f, wctx):
5475 if ms.resolve(f, wctx):
5476 ret = 1
5476 ret = 1
5477 finally:
5477 finally:
5478 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5478 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5479 ms.commit()
5479 ms.commit()
5480
5480
5481 # replace filemerge's .orig file with our resolve file
5481 # replace filemerge's .orig file with our resolve file
5482 util.rename(a + ".resolve", a + ".orig")
5482 util.rename(a + ".resolve", a + ".orig")
5483
5483
5484 ms.commit()
5484 ms.commit()
5485
5485
5486 if not didwork and pats:
5486 if not didwork and pats:
5487 ui.warn(_("arguments do not match paths that need resolving\n"))
5487 ui.warn(_("arguments do not match paths that need resolving\n"))
5488
5488
5489 finally:
5489 finally:
5490 wlock.release()
5490 wlock.release()
5491
5491
5492 # Nudge users into finishing an unfinished operation
5492 # Nudge users into finishing an unfinished operation
5493 if not list(ms.unresolved()):
5493 if not list(ms.unresolved()):
5494 ui.status(_('(no more unresolved files)\n'))
5494 ui.status(_('(no more unresolved files)\n'))
5495
5495
5496 return ret
5496 return ret
5497
5497
5498 @command('revert',
5498 @command('revert',
5499 [('a', 'all', None, _('revert all changes when no arguments given')),
5499 [('a', 'all', None, _('revert all changes when no arguments given')),
5500 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5500 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5501 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5501 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5502 ('C', 'no-backup', None, _('do not save backup copies of files')),
5502 ('C', 'no-backup', None, _('do not save backup copies of files')),
5503 ('i', 'interactive', None,
5503 ('i', 'interactive', None,
5504 _('interactively select the changes (EXPERIMENTAL)')),
5504 _('interactively select the changes (EXPERIMENTAL)')),
5505 ] + walkopts + dryrunopts,
5505 ] + walkopts + dryrunopts,
5506 _('[OPTION]... [-r REV] [NAME]...'))
5506 _('[OPTION]... [-r REV] [NAME]...'))
5507 def revert(ui, repo, *pats, **opts):
5507 def revert(ui, repo, *pats, **opts):
5508 """restore files to their checkout state
5508 """restore files to their checkout state
5509
5509
5510 .. note::
5510 .. note::
5511
5511
5512 To check out earlier revisions, you should use :hg:`update REV`.
5512 To check out earlier revisions, you should use :hg:`update REV`.
5513 To cancel an uncommitted merge (and lose your changes),
5513 To cancel an uncommitted merge (and lose your changes),
5514 use :hg:`update --clean .`.
5514 use :hg:`update --clean .`.
5515
5515
5516 With no revision specified, revert the specified files or directories
5516 With no revision specified, revert the specified files or directories
5517 to the contents they had in the parent of the working directory.
5517 to the contents they had in the parent of the working directory.
5518 This restores the contents of files to an unmodified
5518 This restores the contents of files to an unmodified
5519 state and unschedules adds, removes, copies, and renames. If the
5519 state and unschedules adds, removes, copies, and renames. If the
5520 working directory has two parents, you must explicitly specify a
5520 working directory has two parents, you must explicitly specify a
5521 revision.
5521 revision.
5522
5522
5523 Using the -r/--rev or -d/--date options, revert the given files or
5523 Using the -r/--rev or -d/--date options, revert the given files or
5524 directories to their states as of a specific revision. Because
5524 directories to their states as of a specific revision. Because
5525 revert does not change the working directory parents, this will
5525 revert does not change the working directory parents, this will
5526 cause these files to appear modified. This can be helpful to "back
5526 cause these files to appear modified. This can be helpful to "back
5527 out" some or all of an earlier change. See :hg:`backout` for a
5527 out" some or all of an earlier change. See :hg:`backout` for a
5528 related method.
5528 related method.
5529
5529
5530 Modified files are saved with a .orig suffix before reverting.
5530 Modified files are saved with a .orig suffix before reverting.
5531 To disable these backups, use --no-backup.
5531 To disable these backups, use --no-backup.
5532
5532
5533 See :hg:`help dates` for a list of formats valid for -d/--date.
5533 See :hg:`help dates` for a list of formats valid for -d/--date.
5534
5534
5535 Returns 0 on success.
5535 Returns 0 on success.
5536 """
5536 """
5537
5537
5538 if opts.get("date"):
5538 if opts.get("date"):
5539 if opts.get("rev"):
5539 if opts.get("rev"):
5540 raise util.Abort(_("you can't specify a revision and a date"))
5540 raise util.Abort(_("you can't specify a revision and a date"))
5541 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5541 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5542
5542
5543 parent, p2 = repo.dirstate.parents()
5543 parent, p2 = repo.dirstate.parents()
5544 if not opts.get('rev') and p2 != nullid:
5544 if not opts.get('rev') and p2 != nullid:
5545 # revert after merge is a trap for new users (issue2915)
5545 # revert after merge is a trap for new users (issue2915)
5546 raise util.Abort(_('uncommitted merge with no revision specified'),
5546 raise util.Abort(_('uncommitted merge with no revision specified'),
5547 hint=_('use "hg update" or see "hg help revert"'))
5547 hint=_('use "hg update" or see "hg help revert"'))
5548
5548
5549 ctx = scmutil.revsingle(repo, opts.get('rev'))
5549 ctx = scmutil.revsingle(repo, opts.get('rev'))
5550
5550
5551 if (not (pats or opts.get('include') or opts.get('exclude') or
5551 if (not (pats or opts.get('include') or opts.get('exclude') or
5552 opts.get('all') or opts.get('interactive'))):
5552 opts.get('all') or opts.get('interactive'))):
5553 msg = _("no files or directories specified")
5553 msg = _("no files or directories specified")
5554 if p2 != nullid:
5554 if p2 != nullid:
5555 hint = _("uncommitted merge, use --all to discard all changes,"
5555 hint = _("uncommitted merge, use --all to discard all changes,"
5556 " or 'hg update -C .' to abort the merge")
5556 " or 'hg update -C .' to abort the merge")
5557 raise util.Abort(msg, hint=hint)
5557 raise util.Abort(msg, hint=hint)
5558 dirty = any(repo.status())
5558 dirty = any(repo.status())
5559 node = ctx.node()
5559 node = ctx.node()
5560 if node != parent:
5560 if node != parent:
5561 if dirty:
5561 if dirty:
5562 hint = _("uncommitted changes, use --all to discard all"
5562 hint = _("uncommitted changes, use --all to discard all"
5563 " changes, or 'hg update %s' to update") % ctx.rev()
5563 " changes, or 'hg update %s' to update") % ctx.rev()
5564 else:
5564 else:
5565 hint = _("use --all to revert all files,"
5565 hint = _("use --all to revert all files,"
5566 " or 'hg update %s' to update") % ctx.rev()
5566 " or 'hg update %s' to update") % ctx.rev()
5567 elif dirty:
5567 elif dirty:
5568 hint = _("uncommitted changes, use --all to discard all changes")
5568 hint = _("uncommitted changes, use --all to discard all changes")
5569 else:
5569 else:
5570 hint = _("use --all to revert all files")
5570 hint = _("use --all to revert all files")
5571 raise util.Abort(msg, hint=hint)
5571 raise util.Abort(msg, hint=hint)
5572
5572
5573 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5573 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5574
5574
5575 @command('rollback', dryrunopts +
5575 @command('rollback', dryrunopts +
5576 [('f', 'force', False, _('ignore safety measures'))])
5576 [('f', 'force', False, _('ignore safety measures'))])
5577 def rollback(ui, repo, **opts):
5577 def rollback(ui, repo, **opts):
5578 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5578 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5579
5579
5580 Please use :hg:`commit --amend` instead of rollback to correct
5580 Please use :hg:`commit --amend` instead of rollback to correct
5581 mistakes in the last commit.
5581 mistakes in the last commit.
5582
5582
5583 This command should be used with care. There is only one level of
5583 This command should be used with care. There is only one level of
5584 rollback, and there is no way to undo a rollback. It will also
5584 rollback, and there is no way to undo a rollback. It will also
5585 restore the dirstate at the time of the last transaction, losing
5585 restore the dirstate at the time of the last transaction, losing
5586 any dirstate changes since that time. This command does not alter
5586 any dirstate changes since that time. This command does not alter
5587 the working directory.
5587 the working directory.
5588
5588
5589 Transactions are used to encapsulate the effects of all commands
5589 Transactions are used to encapsulate the effects of all commands
5590 that create new changesets or propagate existing changesets into a
5590 that create new changesets or propagate existing changesets into a
5591 repository.
5591 repository.
5592
5592
5593 .. container:: verbose
5593 .. container:: verbose
5594
5594
5595 For example, the following commands are transactional, and their
5595 For example, the following commands are transactional, and their
5596 effects can be rolled back:
5596 effects can be rolled back:
5597
5597
5598 - commit
5598 - commit
5599 - import
5599 - import
5600 - pull
5600 - pull
5601 - push (with this repository as the destination)
5601 - push (with this repository as the destination)
5602 - unbundle
5602 - unbundle
5603
5603
5604 To avoid permanent data loss, rollback will refuse to rollback a
5604 To avoid permanent data loss, rollback will refuse to rollback a
5605 commit transaction if it isn't checked out. Use --force to
5605 commit transaction if it isn't checked out. Use --force to
5606 override this protection.
5606 override this protection.
5607
5607
5608 This command is not intended for use on public repositories. Once
5608 This command is not intended for use on public repositories. Once
5609 changes are visible for pull by other users, rolling a transaction
5609 changes are visible for pull by other users, rolling a transaction
5610 back locally is ineffective (someone else may already have pulled
5610 back locally is ineffective (someone else may already have pulled
5611 the changes). Furthermore, a race is possible with readers of the
5611 the changes). Furthermore, a race is possible with readers of the
5612 repository; for example an in-progress pull from the repository
5612 repository; for example an in-progress pull from the repository
5613 may fail if a rollback is performed.
5613 may fail if a rollback is performed.
5614
5614
5615 Returns 0 on success, 1 if no rollback data is available.
5615 Returns 0 on success, 1 if no rollback data is available.
5616 """
5616 """
5617 return repo.rollback(dryrun=opts.get('dry_run'),
5617 return repo.rollback(dryrun=opts.get('dry_run'),
5618 force=opts.get('force'))
5618 force=opts.get('force'))
5619
5619
5620 @command('root', [])
5620 @command('root', [])
5621 def root(ui, repo):
5621 def root(ui, repo):
5622 """print the root (top) of the current working directory
5622 """print the root (top) of the current working directory
5623
5623
5624 Print the root directory of the current repository.
5624 Print the root directory of the current repository.
5625
5625
5626 Returns 0 on success.
5626 Returns 0 on success.
5627 """
5627 """
5628 ui.write(repo.root + "\n")
5628 ui.write(repo.root + "\n")
5629
5629
5630 @command('^serve',
5630 @command('^serve',
5631 [('A', 'accesslog', '', _('name of access log file to write to'),
5631 [('A', 'accesslog', '', _('name of access log file to write to'),
5632 _('FILE')),
5632 _('FILE')),
5633 ('d', 'daemon', None, _('run server in background')),
5633 ('d', 'daemon', None, _('run server in background')),
5634 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5634 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5635 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5635 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5636 # use string type, then we can check if something was passed
5636 # use string type, then we can check if something was passed
5637 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5637 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5638 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5638 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5639 _('ADDR')),
5639 _('ADDR')),
5640 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5640 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5641 _('PREFIX')),
5641 _('PREFIX')),
5642 ('n', 'name', '',
5642 ('n', 'name', '',
5643 _('name to show in web pages (default: working directory)'), _('NAME')),
5643 _('name to show in web pages (default: working directory)'), _('NAME')),
5644 ('', 'web-conf', '',
5644 ('', 'web-conf', '',
5645 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5645 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5646 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5646 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5647 _('FILE')),
5647 _('FILE')),
5648 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5648 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5649 ('', 'stdio', None, _('for remote clients')),
5649 ('', 'stdio', None, _('for remote clients')),
5650 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5650 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5651 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5651 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5652 ('', 'style', '', _('template style to use'), _('STYLE')),
5652 ('', 'style', '', _('template style to use'), _('STYLE')),
5653 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5653 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5654 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5654 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5655 _('[OPTION]...'),
5655 _('[OPTION]...'),
5656 optionalrepo=True)
5656 optionalrepo=True)
5657 def serve(ui, repo, **opts):
5657 def serve(ui, repo, **opts):
5658 """start stand-alone webserver
5658 """start stand-alone webserver
5659
5659
5660 Start a local HTTP repository browser and pull server. You can use
5660 Start a local HTTP repository browser and pull server. You can use
5661 this for ad-hoc sharing and browsing of repositories. It is
5661 this for ad-hoc sharing and browsing of repositories. It is
5662 recommended to use a real web server to serve a repository for
5662 recommended to use a real web server to serve a repository for
5663 longer periods of time.
5663 longer periods of time.
5664
5664
5665 Please note that the server does not implement access control.
5665 Please note that the server does not implement access control.
5666 This means that, by default, anybody can read from the server and
5666 This means that, by default, anybody can read from the server and
5667 nobody can write to it by default. Set the ``web.allow_push``
5667 nobody can write to it by default. Set the ``web.allow_push``
5668 option to ``*`` to allow everybody to push to the server. You
5668 option to ``*`` to allow everybody to push to the server. You
5669 should use a real web server if you need to authenticate users.
5669 should use a real web server if you need to authenticate users.
5670
5670
5671 By default, the server logs accesses to stdout and errors to
5671 By default, the server logs accesses to stdout and errors to
5672 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5672 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5673 files.
5673 files.
5674
5674
5675 To have the server choose a free port number to listen on, specify
5675 To have the server choose a free port number to listen on, specify
5676 a port number of 0; in this case, the server will print the port
5676 a port number of 0; in this case, the server will print the port
5677 number it uses.
5677 number it uses.
5678
5678
5679 Returns 0 on success.
5679 Returns 0 on success.
5680 """
5680 """
5681
5681
5682 if opts["stdio"] and opts["cmdserver"]:
5682 if opts["stdio"] and opts["cmdserver"]:
5683 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5683 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5684
5684
5685 if opts["stdio"]:
5685 if opts["stdio"]:
5686 if repo is None:
5686 if repo is None:
5687 raise error.RepoError(_("there is no Mercurial repository here"
5687 raise error.RepoError(_("there is no Mercurial repository here"
5688 " (.hg not found)"))
5688 " (.hg not found)"))
5689 s = sshserver.sshserver(ui, repo)
5689 s = sshserver.sshserver(ui, repo)
5690 s.serve_forever()
5690 s.serve_forever()
5691
5691
5692 if opts["cmdserver"]:
5692 if opts["cmdserver"]:
5693 service = commandserver.createservice(ui, repo, opts)
5693 service = commandserver.createservice(ui, repo, opts)
5694 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5694 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5695
5695
5696 # this way we can check if something was given in the command-line
5696 # this way we can check if something was given in the command-line
5697 if opts.get('port'):
5697 if opts.get('port'):
5698 opts['port'] = util.getport(opts.get('port'))
5698 opts['port'] = util.getport(opts.get('port'))
5699
5699
5700 if repo:
5700 if repo:
5701 baseui = repo.baseui
5701 baseui = repo.baseui
5702 else:
5702 else:
5703 baseui = ui
5703 baseui = ui
5704 optlist = ("name templates style address port prefix ipv6"
5704 optlist = ("name templates style address port prefix ipv6"
5705 " accesslog errorlog certificate encoding")
5705 " accesslog errorlog certificate encoding")
5706 for o in optlist.split():
5706 for o in optlist.split():
5707 val = opts.get(o, '')
5707 val = opts.get(o, '')
5708 if val in (None, ''): # should check against default options instead
5708 if val in (None, ''): # should check against default options instead
5709 continue
5709 continue
5710 baseui.setconfig("web", o, val, 'serve')
5710 baseui.setconfig("web", o, val, 'serve')
5711 if repo and repo.ui != baseui:
5711 if repo and repo.ui != baseui:
5712 repo.ui.setconfig("web", o, val, 'serve')
5712 repo.ui.setconfig("web", o, val, 'serve')
5713
5713
5714 o = opts.get('web_conf') or opts.get('webdir_conf')
5714 o = opts.get('web_conf') or opts.get('webdir_conf')
5715 if not o:
5715 if not o:
5716 if not repo:
5716 if not repo:
5717 raise error.RepoError(_("there is no Mercurial repository"
5717 raise error.RepoError(_("there is no Mercurial repository"
5718 " here (.hg not found)"))
5718 " here (.hg not found)"))
5719 o = repo
5719 o = repo
5720
5720
5721 app = hgweb.hgweb(o, baseui=baseui)
5721 app = hgweb.hgweb(o, baseui=baseui)
5722 service = httpservice(ui, app, opts)
5722 service = httpservice(ui, app, opts)
5723 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5723 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5724
5724
5725 class httpservice(object):
5725 class httpservice(object):
5726 def __init__(self, ui, app, opts):
5726 def __init__(self, ui, app, opts):
5727 self.ui = ui
5727 self.ui = ui
5728 self.app = app
5728 self.app = app
5729 self.opts = opts
5729 self.opts = opts
5730
5730
5731 def init(self):
5731 def init(self):
5732 util.setsignalhandler()
5732 util.setsignalhandler()
5733 self.httpd = hgweb_server.create_server(self.ui, self.app)
5733 self.httpd = hgweb_server.create_server(self.ui, self.app)
5734
5734
5735 if self.opts['port'] and not self.ui.verbose:
5735 if self.opts['port'] and not self.ui.verbose:
5736 return
5736 return
5737
5737
5738 if self.httpd.prefix:
5738 if self.httpd.prefix:
5739 prefix = self.httpd.prefix.strip('/') + '/'
5739 prefix = self.httpd.prefix.strip('/') + '/'
5740 else:
5740 else:
5741 prefix = ''
5741 prefix = ''
5742
5742
5743 port = ':%d' % self.httpd.port
5743 port = ':%d' % self.httpd.port
5744 if port == ':80':
5744 if port == ':80':
5745 port = ''
5745 port = ''
5746
5746
5747 bindaddr = self.httpd.addr
5747 bindaddr = self.httpd.addr
5748 if bindaddr == '0.0.0.0':
5748 if bindaddr == '0.0.0.0':
5749 bindaddr = '*'
5749 bindaddr = '*'
5750 elif ':' in bindaddr: # IPv6
5750 elif ':' in bindaddr: # IPv6
5751 bindaddr = '[%s]' % bindaddr
5751 bindaddr = '[%s]' % bindaddr
5752
5752
5753 fqaddr = self.httpd.fqaddr
5753 fqaddr = self.httpd.fqaddr
5754 if ':' in fqaddr:
5754 if ':' in fqaddr:
5755 fqaddr = '[%s]' % fqaddr
5755 fqaddr = '[%s]' % fqaddr
5756 if self.opts['port']:
5756 if self.opts['port']:
5757 write = self.ui.status
5757 write = self.ui.status
5758 else:
5758 else:
5759 write = self.ui.write
5759 write = self.ui.write
5760 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5760 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5761 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5761 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5762 self.ui.flush() # avoid buffering of status message
5762 self.ui.flush() # avoid buffering of status message
5763
5763
5764 def run(self):
5764 def run(self):
5765 self.httpd.serve_forever()
5765 self.httpd.serve_forever()
5766
5766
5767
5767
5768 @command('^status|st',
5768 @command('^status|st',
5769 [('A', 'all', None, _('show status of all files')),
5769 [('A', 'all', None, _('show status of all files')),
5770 ('m', 'modified', None, _('show only modified files')),
5770 ('m', 'modified', None, _('show only modified files')),
5771 ('a', 'added', None, _('show only added files')),
5771 ('a', 'added', None, _('show only added files')),
5772 ('r', 'removed', None, _('show only removed files')),
5772 ('r', 'removed', None, _('show only removed files')),
5773 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5773 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5774 ('c', 'clean', None, _('show only files without changes')),
5774 ('c', 'clean', None, _('show only files without changes')),
5775 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5775 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5776 ('i', 'ignored', None, _('show only ignored files')),
5776 ('i', 'ignored', None, _('show only ignored files')),
5777 ('n', 'no-status', None, _('hide status prefix')),
5777 ('n', 'no-status', None, _('hide status prefix')),
5778 ('C', 'copies', None, _('show source of copied files')),
5778 ('C', 'copies', None, _('show source of copied files')),
5779 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5779 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5780 ('', 'rev', [], _('show difference from revision'), _('REV')),
5780 ('', 'rev', [], _('show difference from revision'), _('REV')),
5781 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5781 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5782 ] + walkopts + subrepoopts + formatteropts,
5782 ] + walkopts + subrepoopts + formatteropts,
5783 _('[OPTION]... [FILE]...'),
5783 _('[OPTION]... [FILE]...'),
5784 inferrepo=True)
5784 inferrepo=True)
5785 def status(ui, repo, *pats, **opts):
5785 def status(ui, repo, *pats, **opts):
5786 """show changed files in the working directory
5786 """show changed files in the working directory
5787
5787
5788 Show status of files in the repository. If names are given, only
5788 Show status of files in the repository. If names are given, only
5789 files that match are shown. Files that are clean or ignored or
5789 files that match are shown. Files that are clean or ignored or
5790 the source of a copy/move operation, are not listed unless
5790 the source of a copy/move operation, are not listed unless
5791 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5791 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5792 Unless options described with "show only ..." are given, the
5792 Unless options described with "show only ..." are given, the
5793 options -mardu are used.
5793 options -mardu are used.
5794
5794
5795 Option -q/--quiet hides untracked (unknown and ignored) files
5795 Option -q/--quiet hides untracked (unknown and ignored) files
5796 unless explicitly requested with -u/--unknown or -i/--ignored.
5796 unless explicitly requested with -u/--unknown or -i/--ignored.
5797
5797
5798 .. note::
5798 .. note::
5799
5799
5800 status may appear to disagree with diff if permissions have
5800 status may appear to disagree with diff if permissions have
5801 changed or a merge has occurred. The standard diff format does
5801 changed or a merge has occurred. The standard diff format does
5802 not report permission changes and diff only reports changes
5802 not report permission changes and diff only reports changes
5803 relative to one merge parent.
5803 relative to one merge parent.
5804
5804
5805 If one revision is given, it is used as the base revision.
5805 If one revision is given, it is used as the base revision.
5806 If two revisions are given, the differences between them are
5806 If two revisions are given, the differences between them are
5807 shown. The --change option can also be used as a shortcut to list
5807 shown. The --change option can also be used as a shortcut to list
5808 the changed files of a revision from its first parent.
5808 the changed files of a revision from its first parent.
5809
5809
5810 The codes used to show the status of files are::
5810 The codes used to show the status of files are::
5811
5811
5812 M = modified
5812 M = modified
5813 A = added
5813 A = added
5814 R = removed
5814 R = removed
5815 C = clean
5815 C = clean
5816 ! = missing (deleted by non-hg command, but still tracked)
5816 ! = missing (deleted by non-hg command, but still tracked)
5817 ? = not tracked
5817 ? = not tracked
5818 I = ignored
5818 I = ignored
5819 = origin of the previous file (with --copies)
5819 = origin of the previous file (with --copies)
5820
5820
5821 .. container:: verbose
5821 .. container:: verbose
5822
5822
5823 Examples:
5823 Examples:
5824
5824
5825 - show changes in the working directory relative to a
5825 - show changes in the working directory relative to a
5826 changeset::
5826 changeset::
5827
5827
5828 hg status --rev 9353
5828 hg status --rev 9353
5829
5829
5830 - show changes in the working directory relative to the
5830 - show changes in the working directory relative to the
5831 current directory (see :hg:`help patterns` for more information)::
5831 current directory (see :hg:`help patterns` for more information)::
5832
5832
5833 hg status re:
5833 hg status re:
5834
5834
5835 - show all changes including copies in an existing changeset::
5835 - show all changes including copies in an existing changeset::
5836
5836
5837 hg status --copies --change 9353
5837 hg status --copies --change 9353
5838
5838
5839 - get a NUL separated list of added files, suitable for xargs::
5839 - get a NUL separated list of added files, suitable for xargs::
5840
5840
5841 hg status -an0
5841 hg status -an0
5842
5842
5843 Returns 0 on success.
5843 Returns 0 on success.
5844 """
5844 """
5845
5845
5846 revs = opts.get('rev')
5846 revs = opts.get('rev')
5847 change = opts.get('change')
5847 change = opts.get('change')
5848
5848
5849 if revs and change:
5849 if revs and change:
5850 msg = _('cannot specify --rev and --change at the same time')
5850 msg = _('cannot specify --rev and --change at the same time')
5851 raise util.Abort(msg)
5851 raise util.Abort(msg)
5852 elif change:
5852 elif change:
5853 node2 = scmutil.revsingle(repo, change, None).node()
5853 node2 = scmutil.revsingle(repo, change, None).node()
5854 node1 = repo[node2].p1().node()
5854 node1 = repo[node2].p1().node()
5855 else:
5855 else:
5856 node1, node2 = scmutil.revpair(repo, revs)
5856 node1, node2 = scmutil.revpair(repo, revs)
5857
5857
5858 if pats:
5858 if pats:
5859 cwd = repo.getcwd()
5859 cwd = repo.getcwd()
5860 else:
5860 else:
5861 cwd = ''
5861 cwd = ''
5862
5862
5863 if opts.get('print0'):
5863 if opts.get('print0'):
5864 end = '\0'
5864 end = '\0'
5865 else:
5865 else:
5866 end = '\n'
5866 end = '\n'
5867 copy = {}
5867 copy = {}
5868 states = 'modified added removed deleted unknown ignored clean'.split()
5868 states = 'modified added removed deleted unknown ignored clean'.split()
5869 show = [k for k in states if opts.get(k)]
5869 show = [k for k in states if opts.get(k)]
5870 if opts.get('all'):
5870 if opts.get('all'):
5871 show += ui.quiet and (states[:4] + ['clean']) or states
5871 show += ui.quiet and (states[:4] + ['clean']) or states
5872 if not show:
5872 if not show:
5873 if ui.quiet:
5873 if ui.quiet:
5874 show = states[:4]
5874 show = states[:4]
5875 else:
5875 else:
5876 show = states[:5]
5876 show = states[:5]
5877
5877
5878 m = scmutil.match(repo[node2], pats, opts)
5878 m = scmutil.match(repo[node2], pats, opts)
5879 stat = repo.status(node1, node2, m,
5879 stat = repo.status(node1, node2, m,
5880 'ignored' in show, 'clean' in show, 'unknown' in show,
5880 'ignored' in show, 'clean' in show, 'unknown' in show,
5881 opts.get('subrepos'))
5881 opts.get('subrepos'))
5882 changestates = zip(states, 'MAR!?IC', stat)
5882 changestates = zip(states, 'MAR!?IC', stat)
5883
5883
5884 if (opts.get('all') or opts.get('copies')
5884 if (opts.get('all') or opts.get('copies')
5885 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5885 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5886 copy = copies.pathcopies(repo[node1], repo[node2], m)
5886 copy = copies.pathcopies(repo[node1], repo[node2], m)
5887
5887
5888 fm = ui.formatter('status', opts)
5888 fm = ui.formatter('status', opts)
5889 fmt = '%s' + end
5889 fmt = '%s' + end
5890 showchar = not opts.get('no_status')
5890 showchar = not opts.get('no_status')
5891
5891
5892 for state, char, files in changestates:
5892 for state, char, files in changestates:
5893 if state in show:
5893 if state in show:
5894 label = 'status.' + state
5894 label = 'status.' + state
5895 for f in files:
5895 for f in files:
5896 fm.startitem()
5896 fm.startitem()
5897 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5897 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5898 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5898 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5899 if f in copy:
5899 if f in copy:
5900 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5900 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5901 label='status.copied')
5901 label='status.copied')
5902 fm.end()
5902 fm.end()
5903
5903
5904 @command('^summary|sum',
5904 @command('^summary|sum',
5905 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5905 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5906 def summary(ui, repo, **opts):
5906 def summary(ui, repo, **opts):
5907 """summarize working directory state
5907 """summarize working directory state
5908
5908
5909 This generates a brief summary of the working directory state,
5909 This generates a brief summary of the working directory state,
5910 including parents, branch, commit status, phase and available updates.
5910 including parents, branch, commit status, phase and available updates.
5911
5911
5912 With the --remote option, this will check the default paths for
5912 With the --remote option, this will check the default paths for
5913 incoming and outgoing changes. This can be time-consuming.
5913 incoming and outgoing changes. This can be time-consuming.
5914
5914
5915 Returns 0 on success.
5915 Returns 0 on success.
5916 """
5916 """
5917
5917
5918 ctx = repo[None]
5918 ctx = repo[None]
5919 parents = ctx.parents()
5919 parents = ctx.parents()
5920 pnode = parents[0].node()
5920 pnode = parents[0].node()
5921 marks = []
5921 marks = []
5922
5922
5923 for p in parents:
5923 for p in parents:
5924 # label with log.changeset (instead of log.parent) since this
5924 # label with log.changeset (instead of log.parent) since this
5925 # shows a working directory parent *changeset*:
5925 # shows a working directory parent *changeset*:
5926 # i18n: column positioning for "hg summary"
5926 # i18n: column positioning for "hg summary"
5927 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5927 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5928 label='log.changeset changeset.%s' % p.phasestr())
5928 label='log.changeset changeset.%s' % p.phasestr())
5929 ui.write(' '.join(p.tags()), label='log.tag')
5929 ui.write(' '.join(p.tags()), label='log.tag')
5930 if p.bookmarks():
5930 if p.bookmarks():
5931 marks.extend(p.bookmarks())
5931 marks.extend(p.bookmarks())
5932 if p.rev() == -1:
5932 if p.rev() == -1:
5933 if not len(repo):
5933 if not len(repo):
5934 ui.write(_(' (empty repository)'))
5934 ui.write(_(' (empty repository)'))
5935 else:
5935 else:
5936 ui.write(_(' (no revision checked out)'))
5936 ui.write(_(' (no revision checked out)'))
5937 ui.write('\n')
5937 ui.write('\n')
5938 if p.description():
5938 if p.description():
5939 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5939 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5940 label='log.summary')
5940 label='log.summary')
5941
5941
5942 branch = ctx.branch()
5942 branch = ctx.branch()
5943 bheads = repo.branchheads(branch)
5943 bheads = repo.branchheads(branch)
5944 # i18n: column positioning for "hg summary"
5944 # i18n: column positioning for "hg summary"
5945 m = _('branch: %s\n') % branch
5945 m = _('branch: %s\n') % branch
5946 if branch != 'default':
5946 if branch != 'default':
5947 ui.write(m, label='log.branch')
5947 ui.write(m, label='log.branch')
5948 else:
5948 else:
5949 ui.status(m, label='log.branch')
5949 ui.status(m, label='log.branch')
5950
5950
5951 if marks:
5951 if marks:
5952 active = repo._activebookmark
5952 active = repo._activebookmark
5953 # i18n: column positioning for "hg summary"
5953 # i18n: column positioning for "hg summary"
5954 ui.write(_('bookmarks:'), label='log.bookmark')
5954 ui.write(_('bookmarks:'), label='log.bookmark')
5955 if active is not None:
5955 if active is not None:
5956 if active in marks:
5956 if active in marks:
5957 ui.write(' *' + active, label=activebookmarklabel)
5957 ui.write(' *' + active, label=activebookmarklabel)
5958 marks.remove(active)
5958 marks.remove(active)
5959 else:
5959 else:
5960 ui.write(' [%s]' % active, label=activebookmarklabel)
5960 ui.write(' [%s]' % active, label=activebookmarklabel)
5961 for m in marks:
5961 for m in marks:
5962 ui.write(' ' + m, label='log.bookmark')
5962 ui.write(' ' + m, label='log.bookmark')
5963 ui.write('\n', label='log.bookmark')
5963 ui.write('\n', label='log.bookmark')
5964
5964
5965 status = repo.status(unknown=True)
5965 status = repo.status(unknown=True)
5966
5966
5967 c = repo.dirstate.copies()
5967 c = repo.dirstate.copies()
5968 copied, renamed = [], []
5968 copied, renamed = [], []
5969 for d, s in c.iteritems():
5969 for d, s in c.iteritems():
5970 if s in status.removed:
5970 if s in status.removed:
5971 status.removed.remove(s)
5971 status.removed.remove(s)
5972 renamed.append(d)
5972 renamed.append(d)
5973 else:
5973 else:
5974 copied.append(d)
5974 copied.append(d)
5975 if d in status.added:
5975 if d in status.added:
5976 status.added.remove(d)
5976 status.added.remove(d)
5977
5977
5978 ms = mergemod.mergestate(repo)
5978 ms = mergemod.mergestate(repo)
5979 unresolved = [f for f in ms if ms[f] == 'u']
5979 unresolved = [f for f in ms if ms[f] == 'u']
5980
5980
5981 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5981 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5982
5982
5983 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5983 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5984 (ui.label(_('%d added'), 'status.added'), status.added),
5984 (ui.label(_('%d added'), 'status.added'), status.added),
5985 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5985 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5986 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5986 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5987 (ui.label(_('%d copied'), 'status.copied'), copied),
5987 (ui.label(_('%d copied'), 'status.copied'), copied),
5988 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5988 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5989 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5989 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5990 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5990 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5991 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5991 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5992 t = []
5992 t = []
5993 for l, s in labels:
5993 for l, s in labels:
5994 if s:
5994 if s:
5995 t.append(l % len(s))
5995 t.append(l % len(s))
5996
5996
5997 t = ', '.join(t)
5997 t = ', '.join(t)
5998 cleanworkdir = False
5998 cleanworkdir = False
5999
5999
6000 if repo.vfs.exists('updatestate'):
6000 if repo.vfs.exists('updatestate'):
6001 t += _(' (interrupted update)')
6001 t += _(' (interrupted update)')
6002 elif len(parents) > 1:
6002 elif len(parents) > 1:
6003 t += _(' (merge)')
6003 t += _(' (merge)')
6004 elif branch != parents[0].branch():
6004 elif branch != parents[0].branch():
6005 t += _(' (new branch)')
6005 t += _(' (new branch)')
6006 elif (parents[0].closesbranch() and
6006 elif (parents[0].closesbranch() and
6007 pnode in repo.branchheads(branch, closed=True)):
6007 pnode in repo.branchheads(branch, closed=True)):
6008 t += _(' (head closed)')
6008 t += _(' (head closed)')
6009 elif not (status.modified or status.added or status.removed or renamed or
6009 elif not (status.modified or status.added or status.removed or renamed or
6010 copied or subs):
6010 copied or subs):
6011 t += _(' (clean)')
6011 t += _(' (clean)')
6012 cleanworkdir = True
6012 cleanworkdir = True
6013 elif pnode not in bheads:
6013 elif pnode not in bheads:
6014 t += _(' (new branch head)')
6014 t += _(' (new branch head)')
6015
6015
6016 if parents:
6016 if parents:
6017 pendingphase = max(p.phase() for p in parents)
6017 pendingphase = max(p.phase() for p in parents)
6018 else:
6018 else:
6019 pendingphase = phases.public
6019 pendingphase = phases.public
6020
6020
6021 if pendingphase > phases.newcommitphase(ui):
6021 if pendingphase > phases.newcommitphase(ui):
6022 t += ' (%s)' % phases.phasenames[pendingphase]
6022 t += ' (%s)' % phases.phasenames[pendingphase]
6023
6023
6024 if cleanworkdir:
6024 if cleanworkdir:
6025 # i18n: column positioning for "hg summary"
6025 # i18n: column positioning for "hg summary"
6026 ui.status(_('commit: %s\n') % t.strip())
6026 ui.status(_('commit: %s\n') % t.strip())
6027 else:
6027 else:
6028 # i18n: column positioning for "hg summary"
6028 # i18n: column positioning for "hg summary"
6029 ui.write(_('commit: %s\n') % t.strip())
6029 ui.write(_('commit: %s\n') % t.strip())
6030
6030
6031 # all ancestors of branch heads - all ancestors of parent = new csets
6031 # all ancestors of branch heads - all ancestors of parent = new csets
6032 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6032 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6033 bheads))
6033 bheads))
6034
6034
6035 if new == 0:
6035 if new == 0:
6036 # i18n: column positioning for "hg summary"
6036 # i18n: column positioning for "hg summary"
6037 ui.status(_('update: (current)\n'))
6037 ui.status(_('update: (current)\n'))
6038 elif pnode not in bheads:
6038 elif pnode not in bheads:
6039 # i18n: column positioning for "hg summary"
6039 # i18n: column positioning for "hg summary"
6040 ui.write(_('update: %d new changesets (update)\n') % new)
6040 ui.write(_('update: %d new changesets (update)\n') % new)
6041 else:
6041 else:
6042 # i18n: column positioning for "hg summary"
6042 # i18n: column positioning for "hg summary"
6043 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6043 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6044 (new, len(bheads)))
6044 (new, len(bheads)))
6045
6045
6046 t = []
6046 t = []
6047 draft = len(repo.revs('draft()'))
6047 draft = len(repo.revs('draft()'))
6048 if draft:
6048 if draft:
6049 t.append(_('%d draft') % draft)
6049 t.append(_('%d draft') % draft)
6050 secret = len(repo.revs('secret()'))
6050 secret = len(repo.revs('secret()'))
6051 if secret:
6051 if secret:
6052 t.append(_('%d secret') % secret)
6052 t.append(_('%d secret') % secret)
6053
6053
6054 if draft or secret:
6054 if draft or secret:
6055 ui.status(_('phases: %s\n') % ', '.join(t))
6055 ui.status(_('phases: %s\n') % ', '.join(t))
6056
6056
6057 cmdutil.summaryhooks(ui, repo)
6057 cmdutil.summaryhooks(ui, repo)
6058
6058
6059 if opts.get('remote'):
6059 if opts.get('remote'):
6060 needsincoming, needsoutgoing = True, True
6060 needsincoming, needsoutgoing = True, True
6061 else:
6061 else:
6062 needsincoming, needsoutgoing = False, False
6062 needsincoming, needsoutgoing = False, False
6063 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6063 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6064 if i:
6064 if i:
6065 needsincoming = True
6065 needsincoming = True
6066 if o:
6066 if o:
6067 needsoutgoing = True
6067 needsoutgoing = True
6068 if not needsincoming and not needsoutgoing:
6068 if not needsincoming and not needsoutgoing:
6069 return
6069 return
6070
6070
6071 def getincoming():
6071 def getincoming():
6072 source, branches = hg.parseurl(ui.expandpath('default'))
6072 source, branches = hg.parseurl(ui.expandpath('default'))
6073 sbranch = branches[0]
6073 sbranch = branches[0]
6074 try:
6074 try:
6075 other = hg.peer(repo, {}, source)
6075 other = hg.peer(repo, {}, source)
6076 except error.RepoError:
6076 except error.RepoError:
6077 if opts.get('remote'):
6077 if opts.get('remote'):
6078 raise
6078 raise
6079 return source, sbranch, None, None, None
6079 return source, sbranch, None, None, None
6080 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6080 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6081 if revs:
6081 if revs:
6082 revs = [other.lookup(rev) for rev in revs]
6082 revs = [other.lookup(rev) for rev in revs]
6083 ui.debug('comparing with %s\n' % util.hidepassword(source))
6083 ui.debug('comparing with %s\n' % util.hidepassword(source))
6084 repo.ui.pushbuffer()
6084 repo.ui.pushbuffer()
6085 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6085 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6086 repo.ui.popbuffer()
6086 repo.ui.popbuffer()
6087 return source, sbranch, other, commoninc, commoninc[1]
6087 return source, sbranch, other, commoninc, commoninc[1]
6088
6088
6089 if needsincoming:
6089 if needsincoming:
6090 source, sbranch, sother, commoninc, incoming = getincoming()
6090 source, sbranch, sother, commoninc, incoming = getincoming()
6091 else:
6091 else:
6092 source = sbranch = sother = commoninc = incoming = None
6092 source = sbranch = sother = commoninc = incoming = None
6093
6093
6094 def getoutgoing():
6094 def getoutgoing():
6095 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6095 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6096 dbranch = branches[0]
6096 dbranch = branches[0]
6097 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6097 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6098 if source != dest:
6098 if source != dest:
6099 try:
6099 try:
6100 dother = hg.peer(repo, {}, dest)
6100 dother = hg.peer(repo, {}, dest)
6101 except error.RepoError:
6101 except error.RepoError:
6102 if opts.get('remote'):
6102 if opts.get('remote'):
6103 raise
6103 raise
6104 return dest, dbranch, None, None
6104 return dest, dbranch, None, None
6105 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6105 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6106 elif sother is None:
6106 elif sother is None:
6107 # there is no explicit destination peer, but source one is invalid
6107 # there is no explicit destination peer, but source one is invalid
6108 return dest, dbranch, None, None
6108 return dest, dbranch, None, None
6109 else:
6109 else:
6110 dother = sother
6110 dother = sother
6111 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6111 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6112 common = None
6112 common = None
6113 else:
6113 else:
6114 common = commoninc
6114 common = commoninc
6115 if revs:
6115 if revs:
6116 revs = [repo.lookup(rev) for rev in revs]
6116 revs = [repo.lookup(rev) for rev in revs]
6117 repo.ui.pushbuffer()
6117 repo.ui.pushbuffer()
6118 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6118 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6119 commoninc=common)
6119 commoninc=common)
6120 repo.ui.popbuffer()
6120 repo.ui.popbuffer()
6121 return dest, dbranch, dother, outgoing
6121 return dest, dbranch, dother, outgoing
6122
6122
6123 if needsoutgoing:
6123 if needsoutgoing:
6124 dest, dbranch, dother, outgoing = getoutgoing()
6124 dest, dbranch, dother, outgoing = getoutgoing()
6125 else:
6125 else:
6126 dest = dbranch = dother = outgoing = None
6126 dest = dbranch = dother = outgoing = None
6127
6127
6128 if opts.get('remote'):
6128 if opts.get('remote'):
6129 t = []
6129 t = []
6130 if incoming:
6130 if incoming:
6131 t.append(_('1 or more incoming'))
6131 t.append(_('1 or more incoming'))
6132 o = outgoing.missing
6132 o = outgoing.missing
6133 if o:
6133 if o:
6134 t.append(_('%d outgoing') % len(o))
6134 t.append(_('%d outgoing') % len(o))
6135 other = dother or sother
6135 other = dother or sother
6136 if 'bookmarks' in other.listkeys('namespaces'):
6136 if 'bookmarks' in other.listkeys('namespaces'):
6137 counts = bookmarks.summary(repo, other)
6137 counts = bookmarks.summary(repo, other)
6138 if counts[0] > 0:
6138 if counts[0] > 0:
6139 t.append(_('%d incoming bookmarks') % counts[0])
6139 t.append(_('%d incoming bookmarks') % counts[0])
6140 if counts[1] > 0:
6140 if counts[1] > 0:
6141 t.append(_('%d outgoing bookmarks') % counts[1])
6141 t.append(_('%d outgoing bookmarks') % counts[1])
6142
6142
6143 if t:
6143 if t:
6144 # i18n: column positioning for "hg summary"
6144 # i18n: column positioning for "hg summary"
6145 ui.write(_('remote: %s\n') % (', '.join(t)))
6145 ui.write(_('remote: %s\n') % (', '.join(t)))
6146 else:
6146 else:
6147 # i18n: column positioning for "hg summary"
6147 # i18n: column positioning for "hg summary"
6148 ui.status(_('remote: (synced)\n'))
6148 ui.status(_('remote: (synced)\n'))
6149
6149
6150 cmdutil.summaryremotehooks(ui, repo, opts,
6150 cmdutil.summaryremotehooks(ui, repo, opts,
6151 ((source, sbranch, sother, commoninc),
6151 ((source, sbranch, sother, commoninc),
6152 (dest, dbranch, dother, outgoing)))
6152 (dest, dbranch, dother, outgoing)))
6153
6153
6154 @command('tag',
6154 @command('tag',
6155 [('f', 'force', None, _('force tag')),
6155 [('f', 'force', None, _('force tag')),
6156 ('l', 'local', None, _('make the tag local')),
6156 ('l', 'local', None, _('make the tag local')),
6157 ('r', 'rev', '', _('revision to tag'), _('REV')),
6157 ('r', 'rev', '', _('revision to tag'), _('REV')),
6158 ('', 'remove', None, _('remove a tag')),
6158 ('', 'remove', None, _('remove a tag')),
6159 # -l/--local is already there, commitopts cannot be used
6159 # -l/--local is already there, commitopts cannot be used
6160 ('e', 'edit', None, _('invoke editor on commit messages')),
6160 ('e', 'edit', None, _('invoke editor on commit messages')),
6161 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6161 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6162 ] + commitopts2,
6162 ] + commitopts2,
6163 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6163 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6164 def tag(ui, repo, name1, *names, **opts):
6164 def tag(ui, repo, name1, *names, **opts):
6165 """add one or more tags for the current or given revision
6165 """add one or more tags for the current or given revision
6166
6166
6167 Name a particular revision using <name>.
6167 Name a particular revision using <name>.
6168
6168
6169 Tags are used to name particular revisions of the repository and are
6169 Tags are used to name particular revisions of the repository and are
6170 very useful to compare different revisions, to go back to significant
6170 very useful to compare different revisions, to go back to significant
6171 earlier versions or to mark branch points as releases, etc. Changing
6171 earlier versions or to mark branch points as releases, etc. Changing
6172 an existing tag is normally disallowed; use -f/--force to override.
6172 an existing tag is normally disallowed; use -f/--force to override.
6173
6173
6174 If no revision is given, the parent of the working directory is
6174 If no revision is given, the parent of the working directory is
6175 used.
6175 used.
6176
6176
6177 To facilitate version control, distribution, and merging of tags,
6177 To facilitate version control, distribution, and merging of tags,
6178 they are stored as a file named ".hgtags" which is managed similarly
6178 they are stored as a file named ".hgtags" which is managed similarly
6179 to other project files and can be hand-edited if necessary. This
6179 to other project files and can be hand-edited if necessary. This
6180 also means that tagging creates a new commit. The file
6180 also means that tagging creates a new commit. The file
6181 ".hg/localtags" is used for local tags (not shared among
6181 ".hg/localtags" is used for local tags (not shared among
6182 repositories).
6182 repositories).
6183
6183
6184 Tag commits are usually made at the head of a branch. If the parent
6184 Tag commits are usually made at the head of a branch. If the parent
6185 of the working directory is not a branch head, :hg:`tag` aborts; use
6185 of the working directory is not a branch head, :hg:`tag` aborts; use
6186 -f/--force to force the tag commit to be based on a non-head
6186 -f/--force to force the tag commit to be based on a non-head
6187 changeset.
6187 changeset.
6188
6188
6189 See :hg:`help dates` for a list of formats valid for -d/--date.
6189 See :hg:`help dates` for a list of formats valid for -d/--date.
6190
6190
6191 Since tag names have priority over branch names during revision
6191 Since tag names have priority over branch names during revision
6192 lookup, using an existing branch name as a tag name is discouraged.
6192 lookup, using an existing branch name as a tag name is discouraged.
6193
6193
6194 Returns 0 on success.
6194 Returns 0 on success.
6195 """
6195 """
6196 wlock = lock = None
6196 wlock = lock = None
6197 try:
6197 try:
6198 wlock = repo.wlock()
6198 wlock = repo.wlock()
6199 lock = repo.lock()
6199 lock = repo.lock()
6200 rev_ = "."
6200 rev_ = "."
6201 names = [t.strip() for t in (name1,) + names]
6201 names = [t.strip() for t in (name1,) + names]
6202 if len(names) != len(set(names)):
6202 if len(names) != len(set(names)):
6203 raise util.Abort(_('tag names must be unique'))
6203 raise util.Abort(_('tag names must be unique'))
6204 for n in names:
6204 for n in names:
6205 scmutil.checknewlabel(repo, n, 'tag')
6205 scmutil.checknewlabel(repo, n, 'tag')
6206 if not n:
6206 if not n:
6207 raise util.Abort(_('tag names cannot consist entirely of '
6207 raise util.Abort(_('tag names cannot consist entirely of '
6208 'whitespace'))
6208 'whitespace'))
6209 if opts.get('rev') and opts.get('remove'):
6209 if opts.get('rev') and opts.get('remove'):
6210 raise util.Abort(_("--rev and --remove are incompatible"))
6210 raise util.Abort(_("--rev and --remove are incompatible"))
6211 if opts.get('rev'):
6211 if opts.get('rev'):
6212 rev_ = opts['rev']
6212 rev_ = opts['rev']
6213 message = opts.get('message')
6213 message = opts.get('message')
6214 if opts.get('remove'):
6214 if opts.get('remove'):
6215 if opts.get('local'):
6215 if opts.get('local'):
6216 expectedtype = 'local'
6216 expectedtype = 'local'
6217 else:
6217 else:
6218 expectedtype = 'global'
6218 expectedtype = 'global'
6219
6219
6220 for n in names:
6220 for n in names:
6221 if not repo.tagtype(n):
6221 if not repo.tagtype(n):
6222 raise util.Abort(_("tag '%s' does not exist") % n)
6222 raise util.Abort(_("tag '%s' does not exist") % n)
6223 if repo.tagtype(n) != expectedtype:
6223 if repo.tagtype(n) != expectedtype:
6224 if expectedtype == 'global':
6224 if expectedtype == 'global':
6225 raise util.Abort(_("tag '%s' is not a global tag") % n)
6225 raise util.Abort(_("tag '%s' is not a global tag") % n)
6226 else:
6226 else:
6227 raise util.Abort(_("tag '%s' is not a local tag") % n)
6227 raise util.Abort(_("tag '%s' is not a local tag") % n)
6228 rev_ = nullid
6228 rev_ = nullid
6229 if not message:
6229 if not message:
6230 # we don't translate commit messages
6230 # we don't translate commit messages
6231 message = 'Removed tag %s' % ', '.join(names)
6231 message = 'Removed tag %s' % ', '.join(names)
6232 elif not opts.get('force'):
6232 elif not opts.get('force'):
6233 for n in names:
6233 for n in names:
6234 if n in repo.tags():
6234 if n in repo.tags():
6235 raise util.Abort(_("tag '%s' already exists "
6235 raise util.Abort(_("tag '%s' already exists "
6236 "(use -f to force)") % n)
6236 "(use -f to force)") % n)
6237 if not opts.get('local'):
6237 if not opts.get('local'):
6238 p1, p2 = repo.dirstate.parents()
6238 p1, p2 = repo.dirstate.parents()
6239 if p2 != nullid:
6239 if p2 != nullid:
6240 raise util.Abort(_('uncommitted merge'))
6240 raise util.Abort(_('uncommitted merge'))
6241 bheads = repo.branchheads()
6241 bheads = repo.branchheads()
6242 if not opts.get('force') and bheads and p1 not in bheads:
6242 if not opts.get('force') and bheads and p1 not in bheads:
6243 raise util.Abort(_('not at a branch head (use -f to force)'))
6243 raise util.Abort(_('not at a branch head (use -f to force)'))
6244 r = scmutil.revsingle(repo, rev_).node()
6244 r = scmutil.revsingle(repo, rev_).node()
6245
6245
6246 if not message:
6246 if not message:
6247 # we don't translate commit messages
6247 # we don't translate commit messages
6248 message = ('Added tag %s for changeset %s' %
6248 message = ('Added tag %s for changeset %s' %
6249 (', '.join(names), short(r)))
6249 (', '.join(names), short(r)))
6250
6250
6251 date = opts.get('date')
6251 date = opts.get('date')
6252 if date:
6252 if date:
6253 date = util.parsedate(date)
6253 date = util.parsedate(date)
6254
6254
6255 if opts.get('remove'):
6255 if opts.get('remove'):
6256 editform = 'tag.remove'
6256 editform = 'tag.remove'
6257 else:
6257 else:
6258 editform = 'tag.add'
6258 editform = 'tag.add'
6259 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6259 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6260
6260
6261 # don't allow tagging the null rev
6261 # don't allow tagging the null rev
6262 if (not opts.get('remove') and
6262 if (not opts.get('remove') and
6263 scmutil.revsingle(repo, rev_).rev() == nullrev):
6263 scmutil.revsingle(repo, rev_).rev() == nullrev):
6264 raise util.Abort(_("cannot tag null revision"))
6264 raise util.Abort(_("cannot tag null revision"))
6265
6265
6266 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6266 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6267 editor=editor)
6267 editor=editor)
6268 finally:
6268 finally:
6269 release(lock, wlock)
6269 release(lock, wlock)
6270
6270
6271 @command('tags', formatteropts, '')
6271 @command('tags', formatteropts, '')
6272 def tags(ui, repo, **opts):
6272 def tags(ui, repo, **opts):
6273 """list repository tags
6273 """list repository tags
6274
6274
6275 This lists both regular and local tags. When the -v/--verbose
6275 This lists both regular and local tags. When the -v/--verbose
6276 switch is used, a third column "local" is printed for local tags.
6276 switch is used, a third column "local" is printed for local tags.
6277
6277
6278 Returns 0 on success.
6278 Returns 0 on success.
6279 """
6279 """
6280
6280
6281 fm = ui.formatter('tags', opts)
6281 fm = ui.formatter('tags', opts)
6282 hexfunc = fm.hexfunc
6282 hexfunc = fm.hexfunc
6283 tagtype = ""
6283 tagtype = ""
6284
6284
6285 for t, n in reversed(repo.tagslist()):
6285 for t, n in reversed(repo.tagslist()):
6286 hn = hexfunc(n)
6286 hn = hexfunc(n)
6287 label = 'tags.normal'
6287 label = 'tags.normal'
6288 tagtype = ''
6288 tagtype = ''
6289 if repo.tagtype(t) == 'local':
6289 if repo.tagtype(t) == 'local':
6290 label = 'tags.local'
6290 label = 'tags.local'
6291 tagtype = 'local'
6291 tagtype = 'local'
6292
6292
6293 fm.startitem()
6293 fm.startitem()
6294 fm.write('tag', '%s', t, label=label)
6294 fm.write('tag', '%s', t, label=label)
6295 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6295 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6296 fm.condwrite(not ui.quiet, 'rev node', fmt,
6296 fm.condwrite(not ui.quiet, 'rev node', fmt,
6297 repo.changelog.rev(n), hn, label=label)
6297 repo.changelog.rev(n), hn, label=label)
6298 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6298 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6299 tagtype, label=label)
6299 tagtype, label=label)
6300 fm.plain('\n')
6300 fm.plain('\n')
6301 fm.end()
6301 fm.end()
6302
6302
6303 @command('tip',
6303 @command('tip',
6304 [('p', 'patch', None, _('show patch')),
6304 [('p', 'patch', None, _('show patch')),
6305 ('g', 'git', None, _('use git extended diff format')),
6305 ('g', 'git', None, _('use git extended diff format')),
6306 ] + templateopts,
6306 ] + templateopts,
6307 _('[-p] [-g]'))
6307 _('[-p] [-g]'))
6308 def tip(ui, repo, **opts):
6308 def tip(ui, repo, **opts):
6309 """show the tip revision (DEPRECATED)
6309 """show the tip revision (DEPRECATED)
6310
6310
6311 The tip revision (usually just called the tip) is the changeset
6311 The tip revision (usually just called the tip) is the changeset
6312 most recently added to the repository (and therefore the most
6312 most recently added to the repository (and therefore the most
6313 recently changed head).
6313 recently changed head).
6314
6314
6315 If you have just made a commit, that commit will be the tip. If
6315 If you have just made a commit, that commit will be the tip. If
6316 you have just pulled changes from another repository, the tip of
6316 you have just pulled changes from another repository, the tip of
6317 that repository becomes the current tip. The "tip" tag is special
6317 that repository becomes the current tip. The "tip" tag is special
6318 and cannot be renamed or assigned to a different changeset.
6318 and cannot be renamed or assigned to a different changeset.
6319
6319
6320 This command is deprecated, please use :hg:`heads` instead.
6320 This command is deprecated, please use :hg:`heads` instead.
6321
6321
6322 Returns 0 on success.
6322 Returns 0 on success.
6323 """
6323 """
6324 displayer = cmdutil.show_changeset(ui, repo, opts)
6324 displayer = cmdutil.show_changeset(ui, repo, opts)
6325 displayer.show(repo['tip'])
6325 displayer.show(repo['tip'])
6326 displayer.close()
6326 displayer.close()
6327
6327
6328 @command('unbundle',
6328 @command('unbundle',
6329 [('u', 'update', None,
6329 [('u', 'update', None,
6330 _('update to new branch head if changesets were unbundled'))],
6330 _('update to new branch head if changesets were unbundled'))],
6331 _('[-u] FILE...'))
6331 _('[-u] FILE...'))
6332 def unbundle(ui, repo, fname1, *fnames, **opts):
6332 def unbundle(ui, repo, fname1, *fnames, **opts):
6333 """apply one or more changegroup files
6333 """apply one or more changegroup files
6334
6334
6335 Apply one or more compressed changegroup files generated by the
6335 Apply one or more compressed changegroup files generated by the
6336 bundle command.
6336 bundle command.
6337
6337
6338 Returns 0 on success, 1 if an update has unresolved files.
6338 Returns 0 on success, 1 if an update has unresolved files.
6339 """
6339 """
6340 fnames = (fname1,) + fnames
6340 fnames = (fname1,) + fnames
6341
6341
6342 lock = repo.lock()
6342 lock = repo.lock()
6343 try:
6343 try:
6344 for fname in fnames:
6344 for fname in fnames:
6345 f = hg.openpath(ui, fname)
6345 f = hg.openpath(ui, fname)
6346 gen = exchange.readbundle(ui, f, fname)
6346 gen = exchange.readbundle(ui, f, fname)
6347 if isinstance(gen, bundle2.unbundle20):
6347 if isinstance(gen, bundle2.unbundle20):
6348 tr = repo.transaction('unbundle')
6348 tr = repo.transaction('unbundle')
6349 try:
6349 try:
6350 op = bundle2.processbundle(repo, gen, lambda: tr)
6350 op = bundle2.processbundle(repo, gen, lambda: tr)
6351 tr.close()
6351 tr.close()
6352 finally:
6352 finally:
6353 if tr:
6353 if tr:
6354 tr.release()
6354 tr.release()
6355 changes = [r.get('result', 0)
6355 changes = [r.get('result', 0)
6356 for r in op.records['changegroup']]
6356 for r in op.records['changegroup']]
6357 modheads = changegroup.combineresults(changes)
6357 modheads = changegroup.combineresults(changes)
6358 else:
6358 else:
6359 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6359 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6360 'bundle:' + fname)
6360 'bundle:' + fname)
6361 finally:
6361 finally:
6362 lock.release()
6362 lock.release()
6363
6363
6364 return postincoming(ui, repo, modheads, opts.get('update'), None)
6364 return postincoming(ui, repo, modheads, opts.get('update'), None)
6365
6365
6366 @command('^update|up|checkout|co',
6366 @command('^update|up|checkout|co',
6367 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6367 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6368 ('c', 'check', None,
6368 ('c', 'check', None,
6369 _('update across branches if no uncommitted changes')),
6369 _('update across branches if no uncommitted changes')),
6370 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6370 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6371 ('r', 'rev', '', _('revision'), _('REV'))
6371 ('r', 'rev', '', _('revision'), _('REV'))
6372 ] + mergetoolopts,
6372 ] + mergetoolopts,
6373 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6373 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6374 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6374 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6375 tool=None):
6375 tool=None):
6376 """update working directory (or switch revisions)
6376 """update working directory (or switch revisions)
6377
6377
6378 Update the repository's working directory to the specified
6378 Update the repository's working directory to the specified
6379 changeset. If no changeset is specified, update to the tip of the
6379 changeset. If no changeset is specified, update to the tip of the
6380 current named branch and move the active bookmark (see :hg:`help
6380 current named branch and move the active bookmark (see :hg:`help
6381 bookmarks`).
6381 bookmarks`).
6382
6382
6383 Update sets the working directory's parent revision to the specified
6383 Update sets the working directory's parent revision to the specified
6384 changeset (see :hg:`help parents`).
6384 changeset (see :hg:`help parents`).
6385
6385
6386 If the changeset is not a descendant or ancestor of the working
6386 If the changeset is not a descendant or ancestor of the working
6387 directory's parent, the update is aborted. With the -c/--check
6387 directory's parent, the update is aborted. With the -c/--check
6388 option, the working directory is checked for uncommitted changes; if
6388 option, the working directory is checked for uncommitted changes; if
6389 none are found, the working directory is updated to the specified
6389 none are found, the working directory is updated to the specified
6390 changeset.
6390 changeset.
6391
6391
6392 .. container:: verbose
6392 .. container:: verbose
6393
6393
6394 The following rules apply when the working directory contains
6394 The following rules apply when the working directory contains
6395 uncommitted changes:
6395 uncommitted changes:
6396
6396
6397 1. If neither -c/--check nor -C/--clean is specified, and if
6397 1. If neither -c/--check nor -C/--clean is specified, and if
6398 the requested changeset is an ancestor or descendant of
6398 the requested changeset is an ancestor or descendant of
6399 the working directory's parent, the uncommitted changes
6399 the working directory's parent, the uncommitted changes
6400 are merged into the requested changeset and the merged
6400 are merged into the requested changeset and the merged
6401 result is left uncommitted. If the requested changeset is
6401 result is left uncommitted. If the requested changeset is
6402 not an ancestor or descendant (that is, it is on another
6402 not an ancestor or descendant (that is, it is on another
6403 branch), the update is aborted and the uncommitted changes
6403 branch), the update is aborted and the uncommitted changes
6404 are preserved.
6404 are preserved.
6405
6405
6406 2. With the -c/--check option, the update is aborted and the
6406 2. With the -c/--check option, the update is aborted and the
6407 uncommitted changes are preserved.
6407 uncommitted changes are preserved.
6408
6408
6409 3. With the -C/--clean option, uncommitted changes are discarded and
6409 3. With the -C/--clean option, uncommitted changes are discarded and
6410 the working directory is updated to the requested changeset.
6410 the working directory is updated to the requested changeset.
6411
6411
6412 To cancel an uncommitted merge (and lose your changes), use
6412 To cancel an uncommitted merge (and lose your changes), use
6413 :hg:`update --clean .`.
6413 :hg:`update --clean .`.
6414
6414
6415 Use null as the changeset to remove the working directory (like
6415 Use null as the changeset to remove the working directory (like
6416 :hg:`clone -U`).
6416 :hg:`clone -U`).
6417
6417
6418 If you want to revert just one file to an older revision, use
6418 If you want to revert just one file to an older revision, use
6419 :hg:`revert [-r REV] NAME`.
6419 :hg:`revert [-r REV] NAME`.
6420
6420
6421 See :hg:`help dates` for a list of formats valid for -d/--date.
6421 See :hg:`help dates` for a list of formats valid for -d/--date.
6422
6422
6423 Returns 0 on success, 1 if there are unresolved files.
6423 Returns 0 on success, 1 if there are unresolved files.
6424 """
6424 """
6425 if rev and node:
6425 if rev and node:
6426 raise util.Abort(_("please specify just one revision"))
6426 raise util.Abort(_("please specify just one revision"))
6427
6427
6428 if rev is None or rev == '':
6428 if rev is None or rev == '':
6429 rev = node
6429 rev = node
6430
6430
6431 cmdutil.clearunfinished(repo)
6431 cmdutil.clearunfinished(repo)
6432
6432
6433 # with no argument, we also move the active bookmark, if any
6433 # with no argument, we also move the active bookmark, if any
6434 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6434 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6435
6435
6436 # if we defined a bookmark, we have to remember the original bookmark name
6436 # if we defined a bookmark, we have to remember the original bookmark name
6437 brev = rev
6437 brev = rev
6438 rev = scmutil.revsingle(repo, rev, rev).rev()
6438 rev = scmutil.revsingle(repo, rev, rev).rev()
6439
6439
6440 if check and clean:
6440 if check and clean:
6441 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6441 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6442
6442
6443 if date:
6443 if date:
6444 if rev is not None:
6444 if rev is not None:
6445 raise util.Abort(_("you can't specify a revision and a date"))
6445 raise util.Abort(_("you can't specify a revision and a date"))
6446 rev = cmdutil.finddate(ui, repo, date)
6446 rev = cmdutil.finddate(ui, repo, date)
6447
6447
6448 if check:
6448 if check:
6449 cmdutil.bailifchanged(repo, merge=False)
6449 cmdutil.bailifchanged(repo, merge=False)
6450 if rev is None:
6450 if rev is None:
6451 rev = repo[repo[None].branch()].rev()
6451 rev = repo[repo[None].branch()].rev()
6452
6452
6453 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6453 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6454
6454
6455 if clean:
6455 if clean:
6456 ret = hg.clean(repo, rev)
6456 ret = hg.clean(repo, rev)
6457 else:
6457 else:
6458 ret = hg.update(repo, rev)
6458 ret = hg.update(repo, rev)
6459
6459
6460 if not ret and movemarkfrom:
6460 if not ret and movemarkfrom:
6461 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6461 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6462 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6462 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6463 elif brev in repo._bookmarks:
6463 elif brev in repo._bookmarks:
6464 bookmarks.activate(repo, brev)
6464 bookmarks.activate(repo, brev)
6465 ui.status(_("(activating bookmark %s)\n") % brev)
6465 ui.status(_("(activating bookmark %s)\n") % brev)
6466 elif brev:
6466 elif brev:
6467 if repo._activebookmark:
6467 if repo._activebookmark:
6468 ui.status(_("(leaving bookmark %s)\n") %
6468 ui.status(_("(leaving bookmark %s)\n") %
6469 repo._activebookmark)
6469 repo._activebookmark)
6470 bookmarks.deactivate(repo)
6470 bookmarks.deactivate(repo)
6471
6471
6472 return ret
6472 return ret
6473
6473
6474 @command('verify', [])
6474 @command('verify', [])
6475 def verify(ui, repo):
6475 def verify(ui, repo):
6476 """verify the integrity of the repository
6476 """verify the integrity of the repository
6477
6477
6478 Verify the integrity of the current repository.
6478 Verify the integrity of the current repository.
6479
6479
6480 This will perform an extensive check of the repository's
6480 This will perform an extensive check of the repository's
6481 integrity, validating the hashes and checksums of each entry in
6481 integrity, validating the hashes and checksums of each entry in
6482 the changelog, manifest, and tracked files, as well as the
6482 the changelog, manifest, and tracked files, as well as the
6483 integrity of their crosslinks and indices.
6483 integrity of their crosslinks and indices.
6484
6484
6485 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6485 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6486 for more information about recovery from corruption of the
6486 for more information about recovery from corruption of the
6487 repository.
6487 repository.
6488
6488
6489 Returns 0 on success, 1 if errors are encountered.
6489 Returns 0 on success, 1 if errors are encountered.
6490 """
6490 """
6491 return hg.verify(repo)
6491 return hg.verify(repo)
6492
6492
6493 @command('version', [], norepo=True)
6493 @command('version', [], norepo=True)
6494 def version_(ui):
6494 def version_(ui):
6495 """output version and copyright information"""
6495 """output version and copyright information"""
6496 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6496 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6497 % util.version())
6497 % util.version())
6498 ui.status(_(
6498 ui.status(_(
6499 "(see http://mercurial.selenic.com for more information)\n"
6499 "(see http://mercurial.selenic.com for more information)\n"
6500 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6500 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6501 "This is free software; see the source for copying conditions. "
6501 "This is free software; see the source for copying conditions. "
6502 "There is NO\nwarranty; "
6502 "There is NO\nwarranty; "
6503 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6503 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6504 ))
6504 ))
6505
6505
6506 ui.note(_("\nEnabled extensions:\n\n"))
6506 ui.note(_("\nEnabled extensions:\n\n"))
6507 if ui.verbose:
6507 if ui.verbose:
6508 # format names and versions into columns
6508 # format names and versions into columns
6509 names = []
6509 names = []
6510 vers = []
6510 vers = []
6511 for name, module in extensions.extensions():
6511 for name, module in extensions.extensions():
6512 names.append(name)
6512 names.append(name)
6513 vers.append(extensions.moduleversion(module))
6513 vers.append(extensions.moduleversion(module))
6514 if names:
6514 if names:
6515 maxnamelen = max(len(n) for n in names)
6515 maxnamelen = max(len(n) for n in names)
6516 for i, name in enumerate(names):
6516 for i, name in enumerate(names):
6517 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6517 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now