##// END OF EJS Templates
commands: add ui.statuscopies config knob...
Mathias De Maré -
r24663:7d01371e default
parent child Browse files
Show More
@@ -1,6461 +1,6462 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 # common command options
43 # common command options
44
44
45 globalopts = [
45 globalopts = [
46 ('R', 'repository', '',
46 ('R', 'repository', '',
47 _('repository root directory or name of overlay bundle file'),
47 _('repository root directory or name of overlay bundle file'),
48 _('REPO')),
48 _('REPO')),
49 ('', 'cwd', '',
49 ('', 'cwd', '',
50 _('change working directory'), _('DIR')),
50 _('change working directory'), _('DIR')),
51 ('y', 'noninteractive', None,
51 ('y', 'noninteractive', None,
52 _('do not prompt, automatically pick the first choice for all prompts')),
52 _('do not prompt, automatically pick the first choice for all prompts')),
53 ('q', 'quiet', None, _('suppress output')),
53 ('q', 'quiet', None, _('suppress output')),
54 ('v', 'verbose', None, _('enable additional output')),
54 ('v', 'verbose', None, _('enable additional output')),
55 ('', 'config', [],
55 ('', 'config', [],
56 _('set/override config option (use \'section.name=value\')'),
56 _('set/override config option (use \'section.name=value\')'),
57 _('CONFIG')),
57 _('CONFIG')),
58 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debug', None, _('enable debugging output')),
59 ('', 'debugger', None, _('start debugger')),
59 ('', 'debugger', None, _('start debugger')),
60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
61 _('ENCODE')),
61 _('ENCODE')),
62 ('', 'encodingmode', encoding.encodingmode,
62 ('', 'encodingmode', encoding.encodingmode,
63 _('set the charset encoding mode'), _('MODE')),
63 _('set the charset encoding mode'), _('MODE')),
64 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'traceback', None, _('always print a traceback on exception')),
65 ('', 'time', None, _('time how long the command takes')),
65 ('', 'time', None, _('time how long the command takes')),
66 ('', 'profile', None, _('print command execution profile')),
66 ('', 'profile', None, _('print command execution profile')),
67 ('', 'version', None, _('output version information and exit')),
67 ('', 'version', None, _('output version information and exit')),
68 ('h', 'help', None, _('display help and exit')),
68 ('h', 'help', None, _('display help and exit')),
69 ('', 'hidden', False, _('consider hidden changesets')),
69 ('', 'hidden', False, _('consider hidden changesets')),
70 ]
70 ]
71
71
72 dryrunopts = [('n', 'dry-run', None,
72 dryrunopts = [('n', 'dry-run', None,
73 _('do not perform actions, just print output'))]
73 _('do not perform actions, just print output'))]
74
74
75 remoteopts = [
75 remoteopts = [
76 ('e', 'ssh', '',
76 ('e', 'ssh', '',
77 _('specify ssh command to use'), _('CMD')),
77 _('specify ssh command to use'), _('CMD')),
78 ('', 'remotecmd', '',
78 ('', 'remotecmd', '',
79 _('specify hg command to run on the remote side'), _('CMD')),
79 _('specify hg command to run on the remote side'), _('CMD')),
80 ('', 'insecure', None,
80 ('', 'insecure', None,
81 _('do not verify server certificate (ignoring web.cacerts config)')),
81 _('do not verify server certificate (ignoring web.cacerts config)')),
82 ]
82 ]
83
83
84 walkopts = [
84 walkopts = [
85 ('I', 'include', [],
85 ('I', 'include', [],
86 _('include names matching the given patterns'), _('PATTERN')),
86 _('include names matching the given patterns'), _('PATTERN')),
87 ('X', 'exclude', [],
87 ('X', 'exclude', [],
88 _('exclude names matching the given patterns'), _('PATTERN')),
88 _('exclude names matching the given patterns'), _('PATTERN')),
89 ]
89 ]
90
90
91 commitopts = [
91 commitopts = [
92 ('m', 'message', '',
92 ('m', 'message', '',
93 _('use text as commit message'), _('TEXT')),
93 _('use text as commit message'), _('TEXT')),
94 ('l', 'logfile', '',
94 ('l', 'logfile', '',
95 _('read commit message from file'), _('FILE')),
95 _('read commit message from file'), _('FILE')),
96 ]
96 ]
97
97
98 commitopts2 = [
98 commitopts2 = [
99 ('d', 'date', '',
99 ('d', 'date', '',
100 _('record the specified date as commit date'), _('DATE')),
100 _('record the specified date as commit date'), _('DATE')),
101 ('u', 'user', '',
101 ('u', 'user', '',
102 _('record the specified user as committer'), _('USER')),
102 _('record the specified user as committer'), _('USER')),
103 ]
103 ]
104
104
105 # hidden for now
105 # hidden for now
106 formatteropts = [
106 formatteropts = [
107 ('T', 'template', '',
107 ('T', 'template', '',
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
109 ]
109 ]
110
110
111 templateopts = [
111 templateopts = [
112 ('', 'style', '',
112 ('', 'style', '',
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template'), _('TEMPLATE')),
115 _('display with template'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 logopts = [
118 logopts = [
119 ('p', 'patch', None, _('show patch')),
119 ('p', 'patch', None, _('show patch')),
120 ('g', 'git', None, _('use git extended diff format')),
120 ('g', 'git', None, _('use git extended diff format')),
121 ('l', 'limit', '',
121 ('l', 'limit', '',
122 _('limit number of changes displayed'), _('NUM')),
122 _('limit number of changes displayed'), _('NUM')),
123 ('M', 'no-merges', None, _('do not show merges')),
123 ('M', 'no-merges', None, _('do not show merges')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('G', 'graph', None, _("show the revision DAG")),
125 ('G', 'graph', None, _("show the revision DAG")),
126 ] + templateopts
126 ] + templateopts
127
127
128 diffopts = [
128 diffopts = [
129 ('a', 'text', None, _('treat all files as text')),
129 ('a', 'text', None, _('treat all files as text')),
130 ('g', 'git', None, _('use git extended diff format')),
130 ('g', 'git', None, _('use git extended diff format')),
131 ('', 'nodates', None, _('omit dates from diff headers'))
131 ('', 'nodates', None, _('omit dates from diff headers'))
132 ]
132 ]
133
133
134 diffwsopts = [
134 diffwsopts = [
135 ('w', 'ignore-all-space', None,
135 ('w', 'ignore-all-space', None,
136 _('ignore white space when comparing lines')),
136 _('ignore white space when comparing lines')),
137 ('b', 'ignore-space-change', None,
137 ('b', 'ignore-space-change', None,
138 _('ignore changes in the amount of white space')),
138 _('ignore changes in the amount of white space')),
139 ('B', 'ignore-blank-lines', None,
139 ('B', 'ignore-blank-lines', None,
140 _('ignore changes whose lines are all blank')),
140 _('ignore changes whose lines are all blank')),
141 ]
141 ]
142
142
143 diffopts2 = [
143 diffopts2 = [
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
145 ('p', 'show-function', None, _('show which function each change is in')),
145 ('p', 'show-function', None, _('show which function each change is in')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
147 ] + diffwsopts + [
147 ] + diffwsopts + [
148 ('U', 'unified', '',
148 ('U', 'unified', '',
149 _('number of lines of context to show'), _('NUM')),
149 _('number of lines of context to show'), _('NUM')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
151 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
151 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
152 ]
152 ]
153
153
154 mergetoolopts = [
154 mergetoolopts = [
155 ('t', 'tool', '', _('specify merge tool')),
155 ('t', 'tool', '', _('specify merge tool')),
156 ]
156 ]
157
157
158 similarityopts = [
158 similarityopts = [
159 ('s', 'similarity', '',
159 ('s', 'similarity', '',
160 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
160 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
161 ]
161 ]
162
162
163 subrepoopts = [
163 subrepoopts = [
164 ('S', 'subrepos', None,
164 ('S', 'subrepos', None,
165 _('recurse into subrepositories'))
165 _('recurse into subrepositories'))
166 ]
166 ]
167
167
168 # Commands start here, listed alphabetically
168 # Commands start here, listed alphabetically
169
169
170 @command('^add',
170 @command('^add',
171 walkopts + subrepoopts + dryrunopts,
171 walkopts + subrepoopts + dryrunopts,
172 _('[OPTION]... [FILE]...'),
172 _('[OPTION]... [FILE]...'),
173 inferrepo=True)
173 inferrepo=True)
174 def add(ui, repo, *pats, **opts):
174 def add(ui, repo, *pats, **opts):
175 """add the specified files on the next commit
175 """add the specified files on the next commit
176
176
177 Schedule files to be version controlled and added to the
177 Schedule files to be version controlled and added to the
178 repository.
178 repository.
179
179
180 The files will be added to the repository at the next commit. To
180 The files will be added to the repository at the next commit. To
181 undo an add before that, see :hg:`forget`.
181 undo an add before that, see :hg:`forget`.
182
182
183 If no names are given, add all files to the repository.
183 If no names are given, add all files to the repository.
184
184
185 .. container:: verbose
185 .. container:: verbose
186
186
187 An example showing how new (unknown) files are added
187 An example showing how new (unknown) files are added
188 automatically by :hg:`add`::
188 automatically by :hg:`add`::
189
189
190 $ ls
190 $ ls
191 foo.c
191 foo.c
192 $ hg status
192 $ hg status
193 ? foo.c
193 ? foo.c
194 $ hg add
194 $ hg add
195 adding foo.c
195 adding foo.c
196 $ hg status
196 $ hg status
197 A foo.c
197 A foo.c
198
198
199 Returns 0 if all files are successfully added.
199 Returns 0 if all files are successfully added.
200 """
200 """
201
201
202 m = scmutil.match(repo[None], pats, opts)
202 m = scmutil.match(repo[None], pats, opts)
203 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
203 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
204 return rejected and 1 or 0
204 return rejected and 1 or 0
205
205
206 @command('addremove',
206 @command('addremove',
207 similarityopts + subrepoopts + walkopts + dryrunopts,
207 similarityopts + subrepoopts + walkopts + dryrunopts,
208 _('[OPTION]... [FILE]...'),
208 _('[OPTION]... [FILE]...'),
209 inferrepo=True)
209 inferrepo=True)
210 def addremove(ui, repo, *pats, **opts):
210 def addremove(ui, repo, *pats, **opts):
211 """add all new files, delete all missing files
211 """add all new files, delete all missing files
212
212
213 Add all new files and remove all missing files from the
213 Add all new files and remove all missing files from the
214 repository.
214 repository.
215
215
216 New files are ignored if they match any of the patterns in
216 New files are ignored if they match any of the patterns in
217 ``.hgignore``. As with add, these changes take effect at the next
217 ``.hgignore``. As with add, these changes take effect at the next
218 commit.
218 commit.
219
219
220 Use the -s/--similarity option to detect renamed files. This
220 Use the -s/--similarity option to detect renamed files. This
221 option takes a percentage between 0 (disabled) and 100 (files must
221 option takes a percentage between 0 (disabled) and 100 (files must
222 be identical) as its parameter. With a parameter greater than 0,
222 be identical) as its parameter. With a parameter greater than 0,
223 this compares every removed file with every added file and records
223 this compares every removed file with every added file and records
224 those similar enough as renames. Detecting renamed files this way
224 those similar enough as renames. Detecting renamed files this way
225 can be expensive. After using this option, :hg:`status -C` can be
225 can be expensive. After using this option, :hg:`status -C` can be
226 used to check which files were identified as moved or renamed. If
226 used to check which files were identified as moved or renamed. If
227 not specified, -s/--similarity defaults to 100 and only renames of
227 not specified, -s/--similarity defaults to 100 and only renames of
228 identical files are detected.
228 identical files are detected.
229
229
230 Returns 0 if all files are successfully added.
230 Returns 0 if all files are successfully added.
231 """
231 """
232 try:
232 try:
233 sim = float(opts.get('similarity') or 100)
233 sim = float(opts.get('similarity') or 100)
234 except ValueError:
234 except ValueError:
235 raise util.Abort(_('similarity must be a number'))
235 raise util.Abort(_('similarity must be a number'))
236 if sim < 0 or sim > 100:
236 if sim < 0 or sim > 100:
237 raise util.Abort(_('similarity must be between 0 and 100'))
237 raise util.Abort(_('similarity must be between 0 and 100'))
238 matcher = scmutil.match(repo[None], pats, opts)
238 matcher = scmutil.match(repo[None], pats, opts)
239 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
239 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
240
240
241 @command('^annotate|blame',
241 @command('^annotate|blame',
242 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
242 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
243 ('', 'follow', None,
243 ('', 'follow', None,
244 _('follow copies/renames and list the filename (DEPRECATED)')),
244 _('follow copies/renames and list the filename (DEPRECATED)')),
245 ('', 'no-follow', None, _("don't follow copies and renames")),
245 ('', 'no-follow', None, _("don't follow copies and renames")),
246 ('a', 'text', None, _('treat all files as text')),
246 ('a', 'text', None, _('treat all files as text')),
247 ('u', 'user', None, _('list the author (long with -v)')),
247 ('u', 'user', None, _('list the author (long with -v)')),
248 ('f', 'file', None, _('list the filename')),
248 ('f', 'file', None, _('list the filename')),
249 ('d', 'date', None, _('list the date (short with -q)')),
249 ('d', 'date', None, _('list the date (short with -q)')),
250 ('n', 'number', None, _('list the revision number (default)')),
250 ('n', 'number', None, _('list the revision number (default)')),
251 ('c', 'changeset', None, _('list the changeset')),
251 ('c', 'changeset', None, _('list the changeset')),
252 ('l', 'line-number', None, _('show line number at the first appearance'))
252 ('l', 'line-number', None, _('show line number at the first appearance'))
253 ] + diffwsopts + walkopts + formatteropts,
253 ] + diffwsopts + walkopts + formatteropts,
254 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
254 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
255 inferrepo=True)
255 inferrepo=True)
256 def annotate(ui, repo, *pats, **opts):
256 def annotate(ui, repo, *pats, **opts):
257 """show changeset information by line for each file
257 """show changeset information by line for each file
258
258
259 List changes in files, showing the revision id responsible for
259 List changes in files, showing the revision id responsible for
260 each line
260 each line
261
261
262 This command is useful for discovering when a change was made and
262 This command is useful for discovering when a change was made and
263 by whom.
263 by whom.
264
264
265 Without the -a/--text option, annotate will avoid processing files
265 Without the -a/--text option, annotate will avoid processing files
266 it detects as binary. With -a, annotate will annotate the file
266 it detects as binary. With -a, annotate will annotate the file
267 anyway, although the results will probably be neither useful
267 anyway, although the results will probably be neither useful
268 nor desirable.
268 nor desirable.
269
269
270 By default, annotate files in the parent of the working directory.
270 By default, annotate files in the parent of the working directory.
271 Use -r "wdir()" to annotate the working directory files.
271 Use -r "wdir()" to annotate the working directory files.
272
272
273 Returns 0 on success.
273 Returns 0 on success.
274 """
274 """
275 if not pats:
275 if not pats:
276 raise util.Abort(_('at least one filename or pattern is required'))
276 raise util.Abort(_('at least one filename or pattern is required'))
277
277
278 if opts.get('follow'):
278 if opts.get('follow'):
279 # --follow is deprecated and now just an alias for -f/--file
279 # --follow is deprecated and now just an alias for -f/--file
280 # to mimic the behavior of Mercurial before version 1.5
280 # to mimic the behavior of Mercurial before version 1.5
281 opts['file'] = True
281 opts['file'] = True
282
282
283 ctx = scmutil.revsingle(repo, opts.get('rev'))
283 ctx = scmutil.revsingle(repo, opts.get('rev'))
284
284
285 fm = ui.formatter('annotate', opts)
285 fm = ui.formatter('annotate', opts)
286 if ui.quiet:
286 if ui.quiet:
287 datefunc = util.shortdate
287 datefunc = util.shortdate
288 else:
288 else:
289 datefunc = util.datestr
289 datefunc = util.datestr
290 if ctx.rev() is None:
290 if ctx.rev() is None:
291 def hexfn(node):
291 def hexfn(node):
292 if node is None:
292 if node is None:
293 return None
293 return None
294 else:
294 else:
295 return fm.hexfunc(node)
295 return fm.hexfunc(node)
296 if opts.get('changeset'):
296 if opts.get('changeset'):
297 # omit "+" suffix which is appended to node hex
297 # omit "+" suffix which is appended to node hex
298 def formatrev(rev):
298 def formatrev(rev):
299 if rev is None:
299 if rev is None:
300 return '%d' % ctx.p1().rev()
300 return '%d' % ctx.p1().rev()
301 else:
301 else:
302 return '%d' % rev
302 return '%d' % rev
303 else:
303 else:
304 def formatrev(rev):
304 def formatrev(rev):
305 if rev is None:
305 if rev is None:
306 return '%d+' % ctx.p1().rev()
306 return '%d+' % ctx.p1().rev()
307 else:
307 else:
308 return '%d ' % rev
308 return '%d ' % rev
309 def formathex(hex):
309 def formathex(hex):
310 if hex is None:
310 if hex is None:
311 return '%s+' % fm.hexfunc(ctx.p1().node())
311 return '%s+' % fm.hexfunc(ctx.p1().node())
312 else:
312 else:
313 return '%s ' % hex
313 return '%s ' % hex
314 else:
314 else:
315 hexfn = fm.hexfunc
315 hexfn = fm.hexfunc
316 formatrev = formathex = str
316 formatrev = formathex = str
317
317
318 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
318 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
319 ('number', ' ', lambda x: x[0].rev(), formatrev),
319 ('number', ' ', lambda x: x[0].rev(), formatrev),
320 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
320 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
321 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
321 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
322 ('file', ' ', lambda x: x[0].path(), str),
322 ('file', ' ', lambda x: x[0].path(), str),
323 ('line_number', ':', lambda x: x[1], str),
323 ('line_number', ':', lambda x: x[1], str),
324 ]
324 ]
325 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
325 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
326
326
327 if (not opts.get('user') and not opts.get('changeset')
327 if (not opts.get('user') and not opts.get('changeset')
328 and not opts.get('date') and not opts.get('file')):
328 and not opts.get('date') and not opts.get('file')):
329 opts['number'] = True
329 opts['number'] = True
330
330
331 linenumber = opts.get('line_number') is not None
331 linenumber = opts.get('line_number') is not None
332 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
332 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
333 raise util.Abort(_('at least one of -n/-c is required for -l'))
333 raise util.Abort(_('at least one of -n/-c is required for -l'))
334
334
335 if fm:
335 if fm:
336 def makefunc(get, fmt):
336 def makefunc(get, fmt):
337 return get
337 return get
338 else:
338 else:
339 def makefunc(get, fmt):
339 def makefunc(get, fmt):
340 return lambda x: fmt(get(x))
340 return lambda x: fmt(get(x))
341 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
341 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
342 if opts.get(op)]
342 if opts.get(op)]
343 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
343 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
344 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
344 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
345 if opts.get(op))
345 if opts.get(op))
346
346
347 def bad(x, y):
347 def bad(x, y):
348 raise util.Abort("%s: %s" % (x, y))
348 raise util.Abort("%s: %s" % (x, y))
349
349
350 m = scmutil.match(ctx, pats, opts)
350 m = scmutil.match(ctx, pats, opts)
351 m.bad = bad
351 m.bad = bad
352 follow = not opts.get('no_follow')
352 follow = not opts.get('no_follow')
353 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
353 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
354 whitespace=True)
354 whitespace=True)
355 for abs in ctx.walk(m):
355 for abs in ctx.walk(m):
356 fctx = ctx[abs]
356 fctx = ctx[abs]
357 if not opts.get('text') and util.binary(fctx.data()):
357 if not opts.get('text') and util.binary(fctx.data()):
358 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
358 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
359 continue
359 continue
360
360
361 lines = fctx.annotate(follow=follow, linenumber=linenumber,
361 lines = fctx.annotate(follow=follow, linenumber=linenumber,
362 diffopts=diffopts)
362 diffopts=diffopts)
363 formats = []
363 formats = []
364 pieces = []
364 pieces = []
365
365
366 for f, sep in funcmap:
366 for f, sep in funcmap:
367 l = [f(n) for n, dummy in lines]
367 l = [f(n) for n, dummy in lines]
368 if l:
368 if l:
369 if fm:
369 if fm:
370 formats.append(['%s' for x in l])
370 formats.append(['%s' for x in l])
371 else:
371 else:
372 sizes = [encoding.colwidth(x) for x in l]
372 sizes = [encoding.colwidth(x) for x in l]
373 ml = max(sizes)
373 ml = max(sizes)
374 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
374 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
375 pieces.append(l)
375 pieces.append(l)
376
376
377 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
377 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
378 fm.startitem()
378 fm.startitem()
379 fm.write(fields, "".join(f), *p)
379 fm.write(fields, "".join(f), *p)
380 fm.write('line', ": %s", l[1])
380 fm.write('line', ": %s", l[1])
381
381
382 if lines and not lines[-1][1].endswith('\n'):
382 if lines and not lines[-1][1].endswith('\n'):
383 fm.plain('\n')
383 fm.plain('\n')
384
384
385 fm.end()
385 fm.end()
386
386
387 @command('archive',
387 @command('archive',
388 [('', 'no-decode', None, _('do not pass files through decoders')),
388 [('', 'no-decode', None, _('do not pass files through decoders')),
389 ('p', 'prefix', '', _('directory prefix for files in archive'),
389 ('p', 'prefix', '', _('directory prefix for files in archive'),
390 _('PREFIX')),
390 _('PREFIX')),
391 ('r', 'rev', '', _('revision to distribute'), _('REV')),
391 ('r', 'rev', '', _('revision to distribute'), _('REV')),
392 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
392 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
393 ] + subrepoopts + walkopts,
393 ] + subrepoopts + walkopts,
394 _('[OPTION]... DEST'))
394 _('[OPTION]... DEST'))
395 def archive(ui, repo, dest, **opts):
395 def archive(ui, repo, dest, **opts):
396 '''create an unversioned archive of a repository revision
396 '''create an unversioned archive of a repository revision
397
397
398 By default, the revision used is the parent of the working
398 By default, the revision used is the parent of the working
399 directory; use -r/--rev to specify a different revision.
399 directory; use -r/--rev to specify a different revision.
400
400
401 The archive type is automatically detected based on file
401 The archive type is automatically detected based on file
402 extension (or override using -t/--type).
402 extension (or override using -t/--type).
403
403
404 .. container:: verbose
404 .. container:: verbose
405
405
406 Examples:
406 Examples:
407
407
408 - create a zip file containing the 1.0 release::
408 - create a zip file containing the 1.0 release::
409
409
410 hg archive -r 1.0 project-1.0.zip
410 hg archive -r 1.0 project-1.0.zip
411
411
412 - create a tarball excluding .hg files::
412 - create a tarball excluding .hg files::
413
413
414 hg archive project.tar.gz -X ".hg*"
414 hg archive project.tar.gz -X ".hg*"
415
415
416 Valid types are:
416 Valid types are:
417
417
418 :``files``: a directory full of files (default)
418 :``files``: a directory full of files (default)
419 :``tar``: tar archive, uncompressed
419 :``tar``: tar archive, uncompressed
420 :``tbz2``: tar archive, compressed using bzip2
420 :``tbz2``: tar archive, compressed using bzip2
421 :``tgz``: tar archive, compressed using gzip
421 :``tgz``: tar archive, compressed using gzip
422 :``uzip``: zip archive, uncompressed
422 :``uzip``: zip archive, uncompressed
423 :``zip``: zip archive, compressed using deflate
423 :``zip``: zip archive, compressed using deflate
424
424
425 The exact name of the destination archive or directory is given
425 The exact name of the destination archive or directory is given
426 using a format string; see :hg:`help export` for details.
426 using a format string; see :hg:`help export` for details.
427
427
428 Each member added to an archive file has a directory prefix
428 Each member added to an archive file has a directory prefix
429 prepended. Use -p/--prefix to specify a format string for the
429 prepended. Use -p/--prefix to specify a format string for the
430 prefix. The default is the basename of the archive, with suffixes
430 prefix. The default is the basename of the archive, with suffixes
431 removed.
431 removed.
432
432
433 Returns 0 on success.
433 Returns 0 on success.
434 '''
434 '''
435
435
436 ctx = scmutil.revsingle(repo, opts.get('rev'))
436 ctx = scmutil.revsingle(repo, opts.get('rev'))
437 if not ctx:
437 if not ctx:
438 raise util.Abort(_('no working directory: please specify a revision'))
438 raise util.Abort(_('no working directory: please specify a revision'))
439 node = ctx.node()
439 node = ctx.node()
440 dest = cmdutil.makefilename(repo, dest, node)
440 dest = cmdutil.makefilename(repo, dest, node)
441 if os.path.realpath(dest) == repo.root:
441 if os.path.realpath(dest) == repo.root:
442 raise util.Abort(_('repository root cannot be destination'))
442 raise util.Abort(_('repository root cannot be destination'))
443
443
444 kind = opts.get('type') or archival.guesskind(dest) or 'files'
444 kind = opts.get('type') or archival.guesskind(dest) or 'files'
445 prefix = opts.get('prefix')
445 prefix = opts.get('prefix')
446
446
447 if dest == '-':
447 if dest == '-':
448 if kind == 'files':
448 if kind == 'files':
449 raise util.Abort(_('cannot archive plain files to stdout'))
449 raise util.Abort(_('cannot archive plain files to stdout'))
450 dest = cmdutil.makefileobj(repo, dest)
450 dest = cmdutil.makefileobj(repo, dest)
451 if not prefix:
451 if not prefix:
452 prefix = os.path.basename(repo.root) + '-%h'
452 prefix = os.path.basename(repo.root) + '-%h'
453
453
454 prefix = cmdutil.makefilename(repo, prefix, node)
454 prefix = cmdutil.makefilename(repo, prefix, node)
455 matchfn = scmutil.match(ctx, [], opts)
455 matchfn = scmutil.match(ctx, [], opts)
456 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
456 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
457 matchfn, prefix, subrepos=opts.get('subrepos'))
457 matchfn, prefix, subrepos=opts.get('subrepos'))
458
458
459 @command('backout',
459 @command('backout',
460 [('', 'merge', None, _('merge with old dirstate parent after backout')),
460 [('', 'merge', None, _('merge with old dirstate parent after backout')),
461 ('', 'commit', None, _('commit if no conflicts were encountered')),
461 ('', 'commit', None, _('commit if no conflicts were encountered')),
462 ('', 'parent', '',
462 ('', 'parent', '',
463 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
463 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
464 ('r', 'rev', '', _('revision to backout'), _('REV')),
464 ('r', 'rev', '', _('revision to backout'), _('REV')),
465 ('e', 'edit', False, _('invoke editor on commit messages')),
465 ('e', 'edit', False, _('invoke editor on commit messages')),
466 ] + mergetoolopts + walkopts + commitopts + commitopts2,
466 ] + mergetoolopts + walkopts + commitopts + commitopts2,
467 _('[OPTION]... [-r] REV'))
467 _('[OPTION]... [-r] REV'))
468 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
468 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
469 '''reverse effect of earlier changeset
469 '''reverse effect of earlier changeset
470
470
471 Prepare a new changeset with the effect of REV undone in the
471 Prepare a new changeset with the effect of REV undone in the
472 current working directory.
472 current working directory.
473
473
474 If REV is the parent of the working directory, then this new changeset
474 If REV is the parent of the working directory, then this new changeset
475 is committed automatically. Otherwise, hg needs to merge the
475 is committed automatically. Otherwise, hg needs to merge the
476 changes and the merged result is left uncommitted.
476 changes and the merged result is left uncommitted.
477
477
478 .. note::
478 .. note::
479
479
480 backout cannot be used to fix either an unwanted or
480 backout cannot be used to fix either an unwanted or
481 incorrect merge.
481 incorrect merge.
482
482
483 .. container:: verbose
483 .. container:: verbose
484
484
485 By default, the pending changeset will have one parent,
485 By default, the pending changeset will have one parent,
486 maintaining a linear history. With --merge, the pending
486 maintaining a linear history. With --merge, the pending
487 changeset will instead have two parents: the old parent of the
487 changeset will instead have two parents: the old parent of the
488 working directory and a new child of REV that simply undoes REV.
488 working directory and a new child of REV that simply undoes REV.
489
489
490 Before version 1.7, the behavior without --merge was equivalent
490 Before version 1.7, the behavior without --merge was equivalent
491 to specifying --merge followed by :hg:`update --clean .` to
491 to specifying --merge followed by :hg:`update --clean .` to
492 cancel the merge and leave the child of REV as a head to be
492 cancel the merge and leave the child of REV as a head to be
493 merged separately.
493 merged separately.
494
494
495 See :hg:`help dates` for a list of formats valid for -d/--date.
495 See :hg:`help dates` for a list of formats valid for -d/--date.
496
496
497 Returns 0 on success, 1 if nothing to backout or there are unresolved
497 Returns 0 on success, 1 if nothing to backout or there are unresolved
498 files.
498 files.
499 '''
499 '''
500 if rev and node:
500 if rev and node:
501 raise util.Abort(_("please specify just one revision"))
501 raise util.Abort(_("please specify just one revision"))
502
502
503 if not rev:
503 if not rev:
504 rev = node
504 rev = node
505
505
506 if not rev:
506 if not rev:
507 raise util.Abort(_("please specify a revision to backout"))
507 raise util.Abort(_("please specify a revision to backout"))
508
508
509 date = opts.get('date')
509 date = opts.get('date')
510 if date:
510 if date:
511 opts['date'] = util.parsedate(date)
511 opts['date'] = util.parsedate(date)
512
512
513 cmdutil.checkunfinished(repo)
513 cmdutil.checkunfinished(repo)
514 cmdutil.bailifchanged(repo)
514 cmdutil.bailifchanged(repo)
515 node = scmutil.revsingle(repo, rev).node()
515 node = scmutil.revsingle(repo, rev).node()
516
516
517 op1, op2 = repo.dirstate.parents()
517 op1, op2 = repo.dirstate.parents()
518 if not repo.changelog.isancestor(node, op1):
518 if not repo.changelog.isancestor(node, op1):
519 raise util.Abort(_('cannot backout change that is not an ancestor'))
519 raise util.Abort(_('cannot backout change that is not an ancestor'))
520
520
521 p1, p2 = repo.changelog.parents(node)
521 p1, p2 = repo.changelog.parents(node)
522 if p1 == nullid:
522 if p1 == nullid:
523 raise util.Abort(_('cannot backout a change with no parents'))
523 raise util.Abort(_('cannot backout a change with no parents'))
524 if p2 != nullid:
524 if p2 != nullid:
525 if not opts.get('parent'):
525 if not opts.get('parent'):
526 raise util.Abort(_('cannot backout a merge changeset'))
526 raise util.Abort(_('cannot backout a merge changeset'))
527 p = repo.lookup(opts['parent'])
527 p = repo.lookup(opts['parent'])
528 if p not in (p1, p2):
528 if p not in (p1, p2):
529 raise util.Abort(_('%s is not a parent of %s') %
529 raise util.Abort(_('%s is not a parent of %s') %
530 (short(p), short(node)))
530 (short(p), short(node)))
531 parent = p
531 parent = p
532 else:
532 else:
533 if opts.get('parent'):
533 if opts.get('parent'):
534 raise util.Abort(_('cannot use --parent on non-merge changeset'))
534 raise util.Abort(_('cannot use --parent on non-merge changeset'))
535 parent = p1
535 parent = p1
536
536
537 # the backout should appear on the same branch
537 # the backout should appear on the same branch
538 wlock = repo.wlock()
538 wlock = repo.wlock()
539 try:
539 try:
540 branch = repo.dirstate.branch()
540 branch = repo.dirstate.branch()
541 bheads = repo.branchheads(branch)
541 bheads = repo.branchheads(branch)
542 rctx = scmutil.revsingle(repo, hex(parent))
542 rctx = scmutil.revsingle(repo, hex(parent))
543 if not opts.get('merge') and op1 != node:
543 if not opts.get('merge') and op1 != node:
544 try:
544 try:
545 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
545 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
546 'backout')
546 'backout')
547 repo.dirstate.beginparentchange()
547 repo.dirstate.beginparentchange()
548 stats = mergemod.update(repo, parent, True, True, False,
548 stats = mergemod.update(repo, parent, True, True, False,
549 node, False)
549 node, False)
550 repo.setparents(op1, op2)
550 repo.setparents(op1, op2)
551 repo.dirstate.endparentchange()
551 repo.dirstate.endparentchange()
552 hg._showstats(repo, stats)
552 hg._showstats(repo, stats)
553 if stats[3]:
553 if stats[3]:
554 repo.ui.status(_("use 'hg resolve' to retry unresolved "
554 repo.ui.status(_("use 'hg resolve' to retry unresolved "
555 "file merges\n"))
555 "file merges\n"))
556 return 1
556 return 1
557 elif not commit:
557 elif not commit:
558 msg = _("changeset %s backed out, "
558 msg = _("changeset %s backed out, "
559 "don't forget to commit.\n")
559 "don't forget to commit.\n")
560 ui.status(msg % short(node))
560 ui.status(msg % short(node))
561 return 0
561 return 0
562 finally:
562 finally:
563 ui.setconfig('ui', 'forcemerge', '', '')
563 ui.setconfig('ui', 'forcemerge', '', '')
564 else:
564 else:
565 hg.clean(repo, node, show_stats=False)
565 hg.clean(repo, node, show_stats=False)
566 repo.dirstate.setbranch(branch)
566 repo.dirstate.setbranch(branch)
567 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
567 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
568
568
569
569
570 def commitfunc(ui, repo, message, match, opts):
570 def commitfunc(ui, repo, message, match, opts):
571 editform = 'backout'
571 editform = 'backout'
572 e = cmdutil.getcommiteditor(editform=editform, **opts)
572 e = cmdutil.getcommiteditor(editform=editform, **opts)
573 if not message:
573 if not message:
574 # we don't translate commit messages
574 # we don't translate commit messages
575 message = "Backed out changeset %s" % short(node)
575 message = "Backed out changeset %s" % short(node)
576 e = cmdutil.getcommiteditor(edit=True, editform=editform)
576 e = cmdutil.getcommiteditor(edit=True, editform=editform)
577 return repo.commit(message, opts.get('user'), opts.get('date'),
577 return repo.commit(message, opts.get('user'), opts.get('date'),
578 match, editor=e)
578 match, editor=e)
579 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
579 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
580 if not newnode:
580 if not newnode:
581 ui.status(_("nothing changed\n"))
581 ui.status(_("nothing changed\n"))
582 return 1
582 return 1
583 cmdutil.commitstatus(repo, newnode, branch, bheads)
583 cmdutil.commitstatus(repo, newnode, branch, bheads)
584
584
585 def nice(node):
585 def nice(node):
586 return '%d:%s' % (repo.changelog.rev(node), short(node))
586 return '%d:%s' % (repo.changelog.rev(node), short(node))
587 ui.status(_('changeset %s backs out changeset %s\n') %
587 ui.status(_('changeset %s backs out changeset %s\n') %
588 (nice(repo.changelog.tip()), nice(node)))
588 (nice(repo.changelog.tip()), nice(node)))
589 if opts.get('merge') and op1 != node:
589 if opts.get('merge') and op1 != node:
590 hg.clean(repo, op1, show_stats=False)
590 hg.clean(repo, op1, show_stats=False)
591 ui.status(_('merging with changeset %s\n')
591 ui.status(_('merging with changeset %s\n')
592 % nice(repo.changelog.tip()))
592 % nice(repo.changelog.tip()))
593 try:
593 try:
594 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
594 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
595 'backout')
595 'backout')
596 return hg.merge(repo, hex(repo.changelog.tip()))
596 return hg.merge(repo, hex(repo.changelog.tip()))
597 finally:
597 finally:
598 ui.setconfig('ui', 'forcemerge', '', '')
598 ui.setconfig('ui', 'forcemerge', '', '')
599 finally:
599 finally:
600 wlock.release()
600 wlock.release()
601 return 0
601 return 0
602
602
603 @command('bisect',
603 @command('bisect',
604 [('r', 'reset', False, _('reset bisect state')),
604 [('r', 'reset', False, _('reset bisect state')),
605 ('g', 'good', False, _('mark changeset good')),
605 ('g', 'good', False, _('mark changeset good')),
606 ('b', 'bad', False, _('mark changeset bad')),
606 ('b', 'bad', False, _('mark changeset bad')),
607 ('s', 'skip', False, _('skip testing changeset')),
607 ('s', 'skip', False, _('skip testing changeset')),
608 ('e', 'extend', False, _('extend the bisect range')),
608 ('e', 'extend', False, _('extend the bisect range')),
609 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
609 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
610 ('U', 'noupdate', False, _('do not update to target'))],
610 ('U', 'noupdate', False, _('do not update to target'))],
611 _("[-gbsr] [-U] [-c CMD] [REV]"))
611 _("[-gbsr] [-U] [-c CMD] [REV]"))
612 def bisect(ui, repo, rev=None, extra=None, command=None,
612 def bisect(ui, repo, rev=None, extra=None, command=None,
613 reset=None, good=None, bad=None, skip=None, extend=None,
613 reset=None, good=None, bad=None, skip=None, extend=None,
614 noupdate=None):
614 noupdate=None):
615 """subdivision search of changesets
615 """subdivision search of changesets
616
616
617 This command helps to find changesets which introduce problems. To
617 This command helps to find changesets which introduce problems. To
618 use, mark the earliest changeset you know exhibits the problem as
618 use, mark the earliest changeset you know exhibits the problem as
619 bad, then mark the latest changeset which is free from the problem
619 bad, then mark the latest changeset which is free from the problem
620 as good. Bisect will update your working directory to a revision
620 as good. Bisect will update your working directory to a revision
621 for testing (unless the -U/--noupdate option is specified). Once
621 for testing (unless the -U/--noupdate option is specified). Once
622 you have performed tests, mark the working directory as good or
622 you have performed tests, mark the working directory as good or
623 bad, and bisect will either update to another candidate changeset
623 bad, and bisect will either update to another candidate changeset
624 or announce that it has found the bad revision.
624 or announce that it has found the bad revision.
625
625
626 As a shortcut, you can also use the revision argument to mark a
626 As a shortcut, you can also use the revision argument to mark a
627 revision as good or bad without checking it out first.
627 revision as good or bad without checking it out first.
628
628
629 If you supply a command, it will be used for automatic bisection.
629 If you supply a command, it will be used for automatic bisection.
630 The environment variable HG_NODE will contain the ID of the
630 The environment variable HG_NODE will contain the ID of the
631 changeset being tested. The exit status of the command will be
631 changeset being tested. The exit status of the command will be
632 used to mark revisions as good or bad: status 0 means good, 125
632 used to mark revisions as good or bad: status 0 means good, 125
633 means to skip the revision, 127 (command not found) will abort the
633 means to skip the revision, 127 (command not found) will abort the
634 bisection, and any other non-zero exit status means the revision
634 bisection, and any other non-zero exit status means the revision
635 is bad.
635 is bad.
636
636
637 .. container:: verbose
637 .. container:: verbose
638
638
639 Some examples:
639 Some examples:
640
640
641 - start a bisection with known bad revision 34, and good revision 12::
641 - start a bisection with known bad revision 34, and good revision 12::
642
642
643 hg bisect --bad 34
643 hg bisect --bad 34
644 hg bisect --good 12
644 hg bisect --good 12
645
645
646 - advance the current bisection by marking current revision as good or
646 - advance the current bisection by marking current revision as good or
647 bad::
647 bad::
648
648
649 hg bisect --good
649 hg bisect --good
650 hg bisect --bad
650 hg bisect --bad
651
651
652 - mark the current revision, or a known revision, to be skipped (e.g. if
652 - mark the current revision, or a known revision, to be skipped (e.g. if
653 that revision is not usable because of another issue)::
653 that revision is not usable because of another issue)::
654
654
655 hg bisect --skip
655 hg bisect --skip
656 hg bisect --skip 23
656 hg bisect --skip 23
657
657
658 - skip all revisions that do not touch directories ``foo`` or ``bar``::
658 - skip all revisions that do not touch directories ``foo`` or ``bar``::
659
659
660 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
660 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
661
661
662 - forget the current bisection::
662 - forget the current bisection::
663
663
664 hg bisect --reset
664 hg bisect --reset
665
665
666 - use 'make && make tests' to automatically find the first broken
666 - use 'make && make tests' to automatically find the first broken
667 revision::
667 revision::
668
668
669 hg bisect --reset
669 hg bisect --reset
670 hg bisect --bad 34
670 hg bisect --bad 34
671 hg bisect --good 12
671 hg bisect --good 12
672 hg bisect --command "make && make tests"
672 hg bisect --command "make && make tests"
673
673
674 - see all changesets whose states are already known in the current
674 - see all changesets whose states are already known in the current
675 bisection::
675 bisection::
676
676
677 hg log -r "bisect(pruned)"
677 hg log -r "bisect(pruned)"
678
678
679 - see the changeset currently being bisected (especially useful
679 - see the changeset currently being bisected (especially useful
680 if running with -U/--noupdate)::
680 if running with -U/--noupdate)::
681
681
682 hg log -r "bisect(current)"
682 hg log -r "bisect(current)"
683
683
684 - see all changesets that took part in the current bisection::
684 - see all changesets that took part in the current bisection::
685
685
686 hg log -r "bisect(range)"
686 hg log -r "bisect(range)"
687
687
688 - you can even get a nice graph::
688 - you can even get a nice graph::
689
689
690 hg log --graph -r "bisect(range)"
690 hg log --graph -r "bisect(range)"
691
691
692 See :hg:`help revsets` for more about the `bisect()` keyword.
692 See :hg:`help revsets` for more about the `bisect()` keyword.
693
693
694 Returns 0 on success.
694 Returns 0 on success.
695 """
695 """
696 def extendbisectrange(nodes, good):
696 def extendbisectrange(nodes, good):
697 # bisect is incomplete when it ends on a merge node and
697 # bisect is incomplete when it ends on a merge node and
698 # one of the parent was not checked.
698 # one of the parent was not checked.
699 parents = repo[nodes[0]].parents()
699 parents = repo[nodes[0]].parents()
700 if len(parents) > 1:
700 if len(parents) > 1:
701 if good:
701 if good:
702 side = state['bad']
702 side = state['bad']
703 else:
703 else:
704 side = state['good']
704 side = state['good']
705 num = len(set(i.node() for i in parents) & set(side))
705 num = len(set(i.node() for i in parents) & set(side))
706 if num == 1:
706 if num == 1:
707 return parents[0].ancestor(parents[1])
707 return parents[0].ancestor(parents[1])
708 return None
708 return None
709
709
710 def print_result(nodes, good):
710 def print_result(nodes, good):
711 displayer = cmdutil.show_changeset(ui, repo, {})
711 displayer = cmdutil.show_changeset(ui, repo, {})
712 if len(nodes) == 1:
712 if len(nodes) == 1:
713 # narrowed it down to a single revision
713 # narrowed it down to a single revision
714 if good:
714 if good:
715 ui.write(_("The first good revision is:\n"))
715 ui.write(_("The first good revision is:\n"))
716 else:
716 else:
717 ui.write(_("The first bad revision is:\n"))
717 ui.write(_("The first bad revision is:\n"))
718 displayer.show(repo[nodes[0]])
718 displayer.show(repo[nodes[0]])
719 extendnode = extendbisectrange(nodes, good)
719 extendnode = extendbisectrange(nodes, good)
720 if extendnode is not None:
720 if extendnode is not None:
721 ui.write(_('Not all ancestors of this changeset have been'
721 ui.write(_('Not all ancestors of this changeset have been'
722 ' checked.\nUse bisect --extend to continue the '
722 ' checked.\nUse bisect --extend to continue the '
723 'bisection from\nthe common ancestor, %s.\n')
723 'bisection from\nthe common ancestor, %s.\n')
724 % extendnode)
724 % extendnode)
725 else:
725 else:
726 # multiple possible revisions
726 # multiple possible revisions
727 if good:
727 if good:
728 ui.write(_("Due to skipped revisions, the first "
728 ui.write(_("Due to skipped revisions, the first "
729 "good revision could be any of:\n"))
729 "good revision could be any of:\n"))
730 else:
730 else:
731 ui.write(_("Due to skipped revisions, the first "
731 ui.write(_("Due to skipped revisions, the first "
732 "bad revision could be any of:\n"))
732 "bad revision could be any of:\n"))
733 for n in nodes:
733 for n in nodes:
734 displayer.show(repo[n])
734 displayer.show(repo[n])
735 displayer.close()
735 displayer.close()
736
736
737 def check_state(state, interactive=True):
737 def check_state(state, interactive=True):
738 if not state['good'] or not state['bad']:
738 if not state['good'] or not state['bad']:
739 if (good or bad or skip or reset) and interactive:
739 if (good or bad or skip or reset) and interactive:
740 return
740 return
741 if not state['good']:
741 if not state['good']:
742 raise util.Abort(_('cannot bisect (no known good revisions)'))
742 raise util.Abort(_('cannot bisect (no known good revisions)'))
743 else:
743 else:
744 raise util.Abort(_('cannot bisect (no known bad revisions)'))
744 raise util.Abort(_('cannot bisect (no known bad revisions)'))
745 return True
745 return True
746
746
747 # backward compatibility
747 # backward compatibility
748 if rev in "good bad reset init".split():
748 if rev in "good bad reset init".split():
749 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
749 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
750 cmd, rev, extra = rev, extra, None
750 cmd, rev, extra = rev, extra, None
751 if cmd == "good":
751 if cmd == "good":
752 good = True
752 good = True
753 elif cmd == "bad":
753 elif cmd == "bad":
754 bad = True
754 bad = True
755 else:
755 else:
756 reset = True
756 reset = True
757 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
757 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
758 raise util.Abort(_('incompatible arguments'))
758 raise util.Abort(_('incompatible arguments'))
759
759
760 cmdutil.checkunfinished(repo)
760 cmdutil.checkunfinished(repo)
761
761
762 if reset:
762 if reset:
763 p = repo.join("bisect.state")
763 p = repo.join("bisect.state")
764 if os.path.exists(p):
764 if os.path.exists(p):
765 os.unlink(p)
765 os.unlink(p)
766 return
766 return
767
767
768 state = hbisect.load_state(repo)
768 state = hbisect.load_state(repo)
769
769
770 if command:
770 if command:
771 changesets = 1
771 changesets = 1
772 if noupdate:
772 if noupdate:
773 try:
773 try:
774 node = state['current'][0]
774 node = state['current'][0]
775 except LookupError:
775 except LookupError:
776 raise util.Abort(_('current bisect revision is unknown - '
776 raise util.Abort(_('current bisect revision is unknown - '
777 'start a new bisect to fix'))
777 'start a new bisect to fix'))
778 else:
778 else:
779 node, p2 = repo.dirstate.parents()
779 node, p2 = repo.dirstate.parents()
780 if p2 != nullid:
780 if p2 != nullid:
781 raise util.Abort(_('current bisect revision is a merge'))
781 raise util.Abort(_('current bisect revision is a merge'))
782 try:
782 try:
783 while changesets:
783 while changesets:
784 # update state
784 # update state
785 state['current'] = [node]
785 state['current'] = [node]
786 hbisect.save_state(repo, state)
786 hbisect.save_state(repo, state)
787 status = ui.system(command, environ={'HG_NODE': hex(node)})
787 status = ui.system(command, environ={'HG_NODE': hex(node)})
788 if status == 125:
788 if status == 125:
789 transition = "skip"
789 transition = "skip"
790 elif status == 0:
790 elif status == 0:
791 transition = "good"
791 transition = "good"
792 # status < 0 means process was killed
792 # status < 0 means process was killed
793 elif status == 127:
793 elif status == 127:
794 raise util.Abort(_("failed to execute %s") % command)
794 raise util.Abort(_("failed to execute %s") % command)
795 elif status < 0:
795 elif status < 0:
796 raise util.Abort(_("%s killed") % command)
796 raise util.Abort(_("%s killed") % command)
797 else:
797 else:
798 transition = "bad"
798 transition = "bad"
799 ctx = scmutil.revsingle(repo, rev, node)
799 ctx = scmutil.revsingle(repo, rev, node)
800 rev = None # clear for future iterations
800 rev = None # clear for future iterations
801 state[transition].append(ctx.node())
801 state[transition].append(ctx.node())
802 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
802 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
803 check_state(state, interactive=False)
803 check_state(state, interactive=False)
804 # bisect
804 # bisect
805 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
805 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
806 # update to next check
806 # update to next check
807 node = nodes[0]
807 node = nodes[0]
808 if not noupdate:
808 if not noupdate:
809 cmdutil.bailifchanged(repo)
809 cmdutil.bailifchanged(repo)
810 hg.clean(repo, node, show_stats=False)
810 hg.clean(repo, node, show_stats=False)
811 finally:
811 finally:
812 state['current'] = [node]
812 state['current'] = [node]
813 hbisect.save_state(repo, state)
813 hbisect.save_state(repo, state)
814 print_result(nodes, bgood)
814 print_result(nodes, bgood)
815 return
815 return
816
816
817 # update state
817 # update state
818
818
819 if rev:
819 if rev:
820 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
820 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
821 else:
821 else:
822 nodes = [repo.lookup('.')]
822 nodes = [repo.lookup('.')]
823
823
824 if good or bad or skip:
824 if good or bad or skip:
825 if good:
825 if good:
826 state['good'] += nodes
826 state['good'] += nodes
827 elif bad:
827 elif bad:
828 state['bad'] += nodes
828 state['bad'] += nodes
829 elif skip:
829 elif skip:
830 state['skip'] += nodes
830 state['skip'] += nodes
831 hbisect.save_state(repo, state)
831 hbisect.save_state(repo, state)
832
832
833 if not check_state(state):
833 if not check_state(state):
834 return
834 return
835
835
836 # actually bisect
836 # actually bisect
837 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
837 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
838 if extend:
838 if extend:
839 if not changesets:
839 if not changesets:
840 extendnode = extendbisectrange(nodes, good)
840 extendnode = extendbisectrange(nodes, good)
841 if extendnode is not None:
841 if extendnode is not None:
842 ui.write(_("Extending search to changeset %d:%s\n")
842 ui.write(_("Extending search to changeset %d:%s\n")
843 % (extendnode.rev(), extendnode))
843 % (extendnode.rev(), extendnode))
844 state['current'] = [extendnode.node()]
844 state['current'] = [extendnode.node()]
845 hbisect.save_state(repo, state)
845 hbisect.save_state(repo, state)
846 if noupdate:
846 if noupdate:
847 return
847 return
848 cmdutil.bailifchanged(repo)
848 cmdutil.bailifchanged(repo)
849 return hg.clean(repo, extendnode.node())
849 return hg.clean(repo, extendnode.node())
850 raise util.Abort(_("nothing to extend"))
850 raise util.Abort(_("nothing to extend"))
851
851
852 if changesets == 0:
852 if changesets == 0:
853 print_result(nodes, good)
853 print_result(nodes, good)
854 else:
854 else:
855 assert len(nodes) == 1 # only a single node can be tested next
855 assert len(nodes) == 1 # only a single node can be tested next
856 node = nodes[0]
856 node = nodes[0]
857 # compute the approximate number of remaining tests
857 # compute the approximate number of remaining tests
858 tests, size = 0, 2
858 tests, size = 0, 2
859 while size <= changesets:
859 while size <= changesets:
860 tests, size = tests + 1, size * 2
860 tests, size = tests + 1, size * 2
861 rev = repo.changelog.rev(node)
861 rev = repo.changelog.rev(node)
862 ui.write(_("Testing changeset %d:%s "
862 ui.write(_("Testing changeset %d:%s "
863 "(%d changesets remaining, ~%d tests)\n")
863 "(%d changesets remaining, ~%d tests)\n")
864 % (rev, short(node), changesets, tests))
864 % (rev, short(node), changesets, tests))
865 state['current'] = [node]
865 state['current'] = [node]
866 hbisect.save_state(repo, state)
866 hbisect.save_state(repo, state)
867 if not noupdate:
867 if not noupdate:
868 cmdutil.bailifchanged(repo)
868 cmdutil.bailifchanged(repo)
869 return hg.clean(repo, node)
869 return hg.clean(repo, node)
870
870
871 @command('bookmarks|bookmark',
871 @command('bookmarks|bookmark',
872 [('f', 'force', False, _('force')),
872 [('f', 'force', False, _('force')),
873 ('r', 'rev', '', _('revision'), _('REV')),
873 ('r', 'rev', '', _('revision'), _('REV')),
874 ('d', 'delete', False, _('delete a given bookmark')),
874 ('d', 'delete', False, _('delete a given bookmark')),
875 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
875 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
876 ('i', 'inactive', False, _('mark a bookmark inactive')),
876 ('i', 'inactive', False, _('mark a bookmark inactive')),
877 ] + formatteropts,
877 ] + formatteropts,
878 _('hg bookmarks [OPTIONS]... [NAME]...'))
878 _('hg bookmarks [OPTIONS]... [NAME]...'))
879 def bookmark(ui, repo, *names, **opts):
879 def bookmark(ui, repo, *names, **opts):
880 '''create a new bookmark or list existing bookmarks
880 '''create a new bookmark or list existing bookmarks
881
881
882 Bookmarks are labels on changesets to help track lines of development.
882 Bookmarks are labels on changesets to help track lines of development.
883 Bookmarks are unversioned and can be moved, renamed and deleted.
883 Bookmarks are unversioned and can be moved, renamed and deleted.
884 Deleting or moving a bookmark has no effect on the associated changesets.
884 Deleting or moving a bookmark has no effect on the associated changesets.
885
885
886 Creating or updating to a bookmark causes it to be marked as 'active'.
886 Creating or updating to a bookmark causes it to be marked as 'active'.
887 The active bookmark is indicated with a '*'.
887 The active bookmark is indicated with a '*'.
888 When a commit is made, the active bookmark will advance to the new commit.
888 When a commit is made, the active bookmark will advance to the new commit.
889 A plain :hg:`update` will also advance an active bookmark, if possible.
889 A plain :hg:`update` will also advance an active bookmark, if possible.
890 Updating away from a bookmark will cause it to be deactivated.
890 Updating away from a bookmark will cause it to be deactivated.
891
891
892 Bookmarks can be pushed and pulled between repositories (see
892 Bookmarks can be pushed and pulled between repositories (see
893 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
893 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
894 diverged, a new 'divergent bookmark' of the form 'name@path' will
894 diverged, a new 'divergent bookmark' of the form 'name@path' will
895 be created. Using :hg:`merge` will resolve the divergence.
895 be created. Using :hg:`merge` will resolve the divergence.
896
896
897 A bookmark named '@' has the special property that :hg:`clone` will
897 A bookmark named '@' has the special property that :hg:`clone` will
898 check it out by default if it exists.
898 check it out by default if it exists.
899
899
900 .. container:: verbose
900 .. container:: verbose
901
901
902 Examples:
902 Examples:
903
903
904 - create an active bookmark for a new line of development::
904 - create an active bookmark for a new line of development::
905
905
906 hg book new-feature
906 hg book new-feature
907
907
908 - create an inactive bookmark as a place marker::
908 - create an inactive bookmark as a place marker::
909
909
910 hg book -i reviewed
910 hg book -i reviewed
911
911
912 - create an inactive bookmark on another changeset::
912 - create an inactive bookmark on another changeset::
913
913
914 hg book -r .^ tested
914 hg book -r .^ tested
915
915
916 - move the '@' bookmark from another branch::
916 - move the '@' bookmark from another branch::
917
917
918 hg book -f @
918 hg book -f @
919 '''
919 '''
920 force = opts.get('force')
920 force = opts.get('force')
921 rev = opts.get('rev')
921 rev = opts.get('rev')
922 delete = opts.get('delete')
922 delete = opts.get('delete')
923 rename = opts.get('rename')
923 rename = opts.get('rename')
924 inactive = opts.get('inactive')
924 inactive = opts.get('inactive')
925
925
926 def checkformat(mark):
926 def checkformat(mark):
927 mark = mark.strip()
927 mark = mark.strip()
928 if not mark:
928 if not mark:
929 raise util.Abort(_("bookmark names cannot consist entirely of "
929 raise util.Abort(_("bookmark names cannot consist entirely of "
930 "whitespace"))
930 "whitespace"))
931 scmutil.checknewlabel(repo, mark, 'bookmark')
931 scmutil.checknewlabel(repo, mark, 'bookmark')
932 return mark
932 return mark
933
933
934 def checkconflict(repo, mark, cur, force=False, target=None):
934 def checkconflict(repo, mark, cur, force=False, target=None):
935 if mark in marks and not force:
935 if mark in marks and not force:
936 if target:
936 if target:
937 if marks[mark] == target and target == cur:
937 if marks[mark] == target and target == cur:
938 # re-activating a bookmark
938 # re-activating a bookmark
939 return
939 return
940 anc = repo.changelog.ancestors([repo[target].rev()])
940 anc = repo.changelog.ancestors([repo[target].rev()])
941 bmctx = repo[marks[mark]]
941 bmctx = repo[marks[mark]]
942 divs = [repo[b].node() for b in marks
942 divs = [repo[b].node() for b in marks
943 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
943 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
944
944
945 # allow resolving a single divergent bookmark even if moving
945 # allow resolving a single divergent bookmark even if moving
946 # the bookmark across branches when a revision is specified
946 # the bookmark across branches when a revision is specified
947 # that contains a divergent bookmark
947 # that contains a divergent bookmark
948 if bmctx.rev() not in anc and target in divs:
948 if bmctx.rev() not in anc and target in divs:
949 bookmarks.deletedivergent(repo, [target], mark)
949 bookmarks.deletedivergent(repo, [target], mark)
950 return
950 return
951
951
952 deletefrom = [b for b in divs
952 deletefrom = [b for b in divs
953 if repo[b].rev() in anc or b == target]
953 if repo[b].rev() in anc or b == target]
954 bookmarks.deletedivergent(repo, deletefrom, mark)
954 bookmarks.deletedivergent(repo, deletefrom, mark)
955 if bookmarks.validdest(repo, bmctx, repo[target]):
955 if bookmarks.validdest(repo, bmctx, repo[target]):
956 ui.status(_("moving bookmark '%s' forward from %s\n") %
956 ui.status(_("moving bookmark '%s' forward from %s\n") %
957 (mark, short(bmctx.node())))
957 (mark, short(bmctx.node())))
958 return
958 return
959 raise util.Abort(_("bookmark '%s' already exists "
959 raise util.Abort(_("bookmark '%s' already exists "
960 "(use -f to force)") % mark)
960 "(use -f to force)") % mark)
961 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
961 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
962 and not force):
962 and not force):
963 raise util.Abort(
963 raise util.Abort(
964 _("a bookmark cannot have the name of an existing branch"))
964 _("a bookmark cannot have the name of an existing branch"))
965
965
966 if delete and rename:
966 if delete and rename:
967 raise util.Abort(_("--delete and --rename are incompatible"))
967 raise util.Abort(_("--delete and --rename are incompatible"))
968 if delete and rev:
968 if delete and rev:
969 raise util.Abort(_("--rev is incompatible with --delete"))
969 raise util.Abort(_("--rev is incompatible with --delete"))
970 if rename and rev:
970 if rename and rev:
971 raise util.Abort(_("--rev is incompatible with --rename"))
971 raise util.Abort(_("--rev is incompatible with --rename"))
972 if not names and (delete or rev):
972 if not names and (delete or rev):
973 raise util.Abort(_("bookmark name required"))
973 raise util.Abort(_("bookmark name required"))
974
974
975 if delete or rename or names or inactive:
975 if delete or rename or names or inactive:
976 wlock = repo.wlock()
976 wlock = repo.wlock()
977 try:
977 try:
978 cur = repo.changectx('.').node()
978 cur = repo.changectx('.').node()
979 marks = repo._bookmarks
979 marks = repo._bookmarks
980 if delete:
980 if delete:
981 for mark in names:
981 for mark in names:
982 if mark not in marks:
982 if mark not in marks:
983 raise util.Abort(_("bookmark '%s' does not exist") %
983 raise util.Abort(_("bookmark '%s' does not exist") %
984 mark)
984 mark)
985 if mark == repo._bookmarkcurrent:
985 if mark == repo._bookmarkcurrent:
986 bookmarks.unsetcurrent(repo)
986 bookmarks.unsetcurrent(repo)
987 del marks[mark]
987 del marks[mark]
988 marks.write()
988 marks.write()
989
989
990 elif rename:
990 elif rename:
991 if not names:
991 if not names:
992 raise util.Abort(_("new bookmark name required"))
992 raise util.Abort(_("new bookmark name required"))
993 elif len(names) > 1:
993 elif len(names) > 1:
994 raise util.Abort(_("only one new bookmark name allowed"))
994 raise util.Abort(_("only one new bookmark name allowed"))
995 mark = checkformat(names[0])
995 mark = checkformat(names[0])
996 if rename not in marks:
996 if rename not in marks:
997 raise util.Abort(_("bookmark '%s' does not exist") % rename)
997 raise util.Abort(_("bookmark '%s' does not exist") % rename)
998 checkconflict(repo, mark, cur, force)
998 checkconflict(repo, mark, cur, force)
999 marks[mark] = marks[rename]
999 marks[mark] = marks[rename]
1000 if repo._bookmarkcurrent == rename and not inactive:
1000 if repo._bookmarkcurrent == rename and not inactive:
1001 bookmarks.setcurrent(repo, mark)
1001 bookmarks.setcurrent(repo, mark)
1002 del marks[rename]
1002 del marks[rename]
1003 marks.write()
1003 marks.write()
1004
1004
1005 elif names:
1005 elif names:
1006 newact = None
1006 newact = None
1007 for mark in names:
1007 for mark in names:
1008 mark = checkformat(mark)
1008 mark = checkformat(mark)
1009 if newact is None:
1009 if newact is None:
1010 newact = mark
1010 newact = mark
1011 if inactive and mark == repo._bookmarkcurrent:
1011 if inactive and mark == repo._bookmarkcurrent:
1012 bookmarks.unsetcurrent(repo)
1012 bookmarks.unsetcurrent(repo)
1013 return
1013 return
1014 tgt = cur
1014 tgt = cur
1015 if rev:
1015 if rev:
1016 tgt = scmutil.revsingle(repo, rev).node()
1016 tgt = scmutil.revsingle(repo, rev).node()
1017 checkconflict(repo, mark, cur, force, tgt)
1017 checkconflict(repo, mark, cur, force, tgt)
1018 marks[mark] = tgt
1018 marks[mark] = tgt
1019 if not inactive and cur == marks[newact] and not rev:
1019 if not inactive and cur == marks[newact] and not rev:
1020 bookmarks.setcurrent(repo, newact)
1020 bookmarks.setcurrent(repo, newact)
1021 elif cur != tgt and newact == repo._bookmarkcurrent:
1021 elif cur != tgt and newact == repo._bookmarkcurrent:
1022 bookmarks.unsetcurrent(repo)
1022 bookmarks.unsetcurrent(repo)
1023 marks.write()
1023 marks.write()
1024
1024
1025 elif inactive:
1025 elif inactive:
1026 if len(marks) == 0:
1026 if len(marks) == 0:
1027 ui.status(_("no bookmarks set\n"))
1027 ui.status(_("no bookmarks set\n"))
1028 elif not repo._bookmarkcurrent:
1028 elif not repo._bookmarkcurrent:
1029 ui.status(_("no active bookmark\n"))
1029 ui.status(_("no active bookmark\n"))
1030 else:
1030 else:
1031 bookmarks.unsetcurrent(repo)
1031 bookmarks.unsetcurrent(repo)
1032 finally:
1032 finally:
1033 wlock.release()
1033 wlock.release()
1034 else: # show bookmarks
1034 else: # show bookmarks
1035 fm = ui.formatter('bookmarks', opts)
1035 fm = ui.formatter('bookmarks', opts)
1036 hexfn = fm.hexfunc
1036 hexfn = fm.hexfunc
1037 marks = repo._bookmarks
1037 marks = repo._bookmarks
1038 if len(marks) == 0 and not fm:
1038 if len(marks) == 0 and not fm:
1039 ui.status(_("no bookmarks set\n"))
1039 ui.status(_("no bookmarks set\n"))
1040 for bmark, n in sorted(marks.iteritems()):
1040 for bmark, n in sorted(marks.iteritems()):
1041 current = repo._bookmarkcurrent
1041 current = repo._bookmarkcurrent
1042 if bmark == current:
1042 if bmark == current:
1043 prefix, label = '*', 'bookmarks.current'
1043 prefix, label = '*', 'bookmarks.current'
1044 else:
1044 else:
1045 prefix, label = ' ', ''
1045 prefix, label = ' ', ''
1046
1046
1047 fm.startitem()
1047 fm.startitem()
1048 if not ui.quiet:
1048 if not ui.quiet:
1049 fm.plain(' %s ' % prefix, label=label)
1049 fm.plain(' %s ' % prefix, label=label)
1050 fm.write('bookmark', '%s', bmark, label=label)
1050 fm.write('bookmark', '%s', bmark, label=label)
1051 pad = " " * (25 - encoding.colwidth(bmark))
1051 pad = " " * (25 - encoding.colwidth(bmark))
1052 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1052 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1053 repo.changelog.rev(n), hexfn(n), label=label)
1053 repo.changelog.rev(n), hexfn(n), label=label)
1054 fm.data(active=(bmark == current))
1054 fm.data(active=(bmark == current))
1055 fm.plain('\n')
1055 fm.plain('\n')
1056 fm.end()
1056 fm.end()
1057
1057
1058 @command('branch',
1058 @command('branch',
1059 [('f', 'force', None,
1059 [('f', 'force', None,
1060 _('set branch name even if it shadows an existing branch')),
1060 _('set branch name even if it shadows an existing branch')),
1061 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1061 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1062 _('[-fC] [NAME]'))
1062 _('[-fC] [NAME]'))
1063 def branch(ui, repo, label=None, **opts):
1063 def branch(ui, repo, label=None, **opts):
1064 """set or show the current branch name
1064 """set or show the current branch name
1065
1065
1066 .. note::
1066 .. note::
1067
1067
1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1069 light-weight bookmark instead. See :hg:`help glossary` for more
1069 light-weight bookmark instead. See :hg:`help glossary` for more
1070 information about named branches and bookmarks.
1070 information about named branches and bookmarks.
1071
1071
1072 With no argument, show the current branch name. With one argument,
1072 With no argument, show the current branch name. With one argument,
1073 set the working directory branch name (the branch will not exist
1073 set the working directory branch name (the branch will not exist
1074 in the repository until the next commit). Standard practice
1074 in the repository until the next commit). Standard practice
1075 recommends that primary development take place on the 'default'
1075 recommends that primary development take place on the 'default'
1076 branch.
1076 branch.
1077
1077
1078 Unless -f/--force is specified, branch will not let you set a
1078 Unless -f/--force is specified, branch will not let you set a
1079 branch name that already exists.
1079 branch name that already exists.
1080
1080
1081 Use -C/--clean to reset the working directory branch to that of
1081 Use -C/--clean to reset the working directory branch to that of
1082 the parent of the working directory, negating a previous branch
1082 the parent of the working directory, negating a previous branch
1083 change.
1083 change.
1084
1084
1085 Use the command :hg:`update` to switch to an existing branch. Use
1085 Use the command :hg:`update` to switch to an existing branch. Use
1086 :hg:`commit --close-branch` to mark this branch as closed.
1086 :hg:`commit --close-branch` to mark this branch as closed.
1087
1087
1088 Returns 0 on success.
1088 Returns 0 on success.
1089 """
1089 """
1090 if label:
1090 if label:
1091 label = label.strip()
1091 label = label.strip()
1092
1092
1093 if not opts.get('clean') and not label:
1093 if not opts.get('clean') and not label:
1094 ui.write("%s\n" % repo.dirstate.branch())
1094 ui.write("%s\n" % repo.dirstate.branch())
1095 return
1095 return
1096
1096
1097 wlock = repo.wlock()
1097 wlock = repo.wlock()
1098 try:
1098 try:
1099 if opts.get('clean'):
1099 if opts.get('clean'):
1100 label = repo[None].p1().branch()
1100 label = repo[None].p1().branch()
1101 repo.dirstate.setbranch(label)
1101 repo.dirstate.setbranch(label)
1102 ui.status(_('reset working directory to branch %s\n') % label)
1102 ui.status(_('reset working directory to branch %s\n') % label)
1103 elif label:
1103 elif label:
1104 if not opts.get('force') and label in repo.branchmap():
1104 if not opts.get('force') and label in repo.branchmap():
1105 if label not in [p.branch() for p in repo.parents()]:
1105 if label not in [p.branch() for p in repo.parents()]:
1106 raise util.Abort(_('a branch of the same name already'
1106 raise util.Abort(_('a branch of the same name already'
1107 ' exists'),
1107 ' exists'),
1108 # i18n: "it" refers to an existing branch
1108 # i18n: "it" refers to an existing branch
1109 hint=_("use 'hg update' to switch to it"))
1109 hint=_("use 'hg update' to switch to it"))
1110 scmutil.checknewlabel(repo, label, 'branch')
1110 scmutil.checknewlabel(repo, label, 'branch')
1111 repo.dirstate.setbranch(label)
1111 repo.dirstate.setbranch(label)
1112 ui.status(_('marked working directory as branch %s\n') % label)
1112 ui.status(_('marked working directory as branch %s\n') % label)
1113 ui.status(_('(branches are permanent and global, '
1113 ui.status(_('(branches are permanent and global, '
1114 'did you want a bookmark?)\n'))
1114 'did you want a bookmark?)\n'))
1115 finally:
1115 finally:
1116 wlock.release()
1116 wlock.release()
1117
1117
1118 @command('branches',
1118 @command('branches',
1119 [('a', 'active', False,
1119 [('a', 'active', False,
1120 _('show only branches that have unmerged heads (DEPRECATED)')),
1120 _('show only branches that have unmerged heads (DEPRECATED)')),
1121 ('c', 'closed', False, _('show normal and closed branches')),
1121 ('c', 'closed', False, _('show normal and closed branches')),
1122 ] + formatteropts,
1122 ] + formatteropts,
1123 _('[-ac]'))
1123 _('[-ac]'))
1124 def branches(ui, repo, active=False, closed=False, **opts):
1124 def branches(ui, repo, active=False, closed=False, **opts):
1125 """list repository named branches
1125 """list repository named branches
1126
1126
1127 List the repository's named branches, indicating which ones are
1127 List the repository's named branches, indicating which ones are
1128 inactive. If -c/--closed is specified, also list branches which have
1128 inactive. If -c/--closed is specified, also list branches which have
1129 been marked closed (see :hg:`commit --close-branch`).
1129 been marked closed (see :hg:`commit --close-branch`).
1130
1130
1131 Use the command :hg:`update` to switch to an existing branch.
1131 Use the command :hg:`update` to switch to an existing branch.
1132
1132
1133 Returns 0.
1133 Returns 0.
1134 """
1134 """
1135
1135
1136 fm = ui.formatter('branches', opts)
1136 fm = ui.formatter('branches', opts)
1137 hexfunc = fm.hexfunc
1137 hexfunc = fm.hexfunc
1138
1138
1139 allheads = set(repo.heads())
1139 allheads = set(repo.heads())
1140 branches = []
1140 branches = []
1141 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1141 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1142 isactive = not isclosed and bool(set(heads) & allheads)
1142 isactive = not isclosed and bool(set(heads) & allheads)
1143 branches.append((tag, repo[tip], isactive, not isclosed))
1143 branches.append((tag, repo[tip], isactive, not isclosed))
1144 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1144 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1145 reverse=True)
1145 reverse=True)
1146
1146
1147 for tag, ctx, isactive, isopen in branches:
1147 for tag, ctx, isactive, isopen in branches:
1148 if active and not isactive:
1148 if active and not isactive:
1149 continue
1149 continue
1150 if isactive:
1150 if isactive:
1151 label = 'branches.active'
1151 label = 'branches.active'
1152 notice = ''
1152 notice = ''
1153 elif not isopen:
1153 elif not isopen:
1154 if not closed:
1154 if not closed:
1155 continue
1155 continue
1156 label = 'branches.closed'
1156 label = 'branches.closed'
1157 notice = _(' (closed)')
1157 notice = _(' (closed)')
1158 else:
1158 else:
1159 label = 'branches.inactive'
1159 label = 'branches.inactive'
1160 notice = _(' (inactive)')
1160 notice = _(' (inactive)')
1161 current = (tag == repo.dirstate.branch())
1161 current = (tag == repo.dirstate.branch())
1162 if current:
1162 if current:
1163 label = 'branches.current'
1163 label = 'branches.current'
1164
1164
1165 fm.startitem()
1165 fm.startitem()
1166 fm.write('branch', '%s', tag, label=label)
1166 fm.write('branch', '%s', tag, label=label)
1167 rev = ctx.rev()
1167 rev = ctx.rev()
1168 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1168 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1169 fmt = ' ' * padsize + ' %d:%s'
1169 fmt = ' ' * padsize + ' %d:%s'
1170 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1170 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1171 label='log.changeset changeset.%s' % ctx.phasestr())
1171 label='log.changeset changeset.%s' % ctx.phasestr())
1172 fm.data(active=isactive, closed=not isopen, current=current)
1172 fm.data(active=isactive, closed=not isopen, current=current)
1173 if not ui.quiet:
1173 if not ui.quiet:
1174 fm.plain(notice)
1174 fm.plain(notice)
1175 fm.plain('\n')
1175 fm.plain('\n')
1176 fm.end()
1176 fm.end()
1177
1177
1178 @command('bundle',
1178 @command('bundle',
1179 [('f', 'force', None, _('run even when the destination is unrelated')),
1179 [('f', 'force', None, _('run even when the destination is unrelated')),
1180 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1180 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1181 _('REV')),
1181 _('REV')),
1182 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1182 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1183 _('BRANCH')),
1183 _('BRANCH')),
1184 ('', 'base', [],
1184 ('', 'base', [],
1185 _('a base changeset assumed to be available at the destination'),
1185 _('a base changeset assumed to be available at the destination'),
1186 _('REV')),
1186 _('REV')),
1187 ('a', 'all', None, _('bundle all changesets in the repository')),
1187 ('a', 'all', None, _('bundle all changesets in the repository')),
1188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1189 ] + remoteopts,
1189 ] + remoteopts,
1190 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1190 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1191 def bundle(ui, repo, fname, dest=None, **opts):
1191 def bundle(ui, repo, fname, dest=None, **opts):
1192 """create a changegroup file
1192 """create a changegroup file
1193
1193
1194 Generate a compressed changegroup file collecting changesets not
1194 Generate a compressed changegroup file collecting changesets not
1195 known to be in another repository.
1195 known to be in another repository.
1196
1196
1197 If you omit the destination repository, then hg assumes the
1197 If you omit the destination repository, then hg assumes the
1198 destination will have all the nodes you specify with --base
1198 destination will have all the nodes you specify with --base
1199 parameters. To create a bundle containing all changesets, use
1199 parameters. To create a bundle containing all changesets, use
1200 -a/--all (or --base null).
1200 -a/--all (or --base null).
1201
1201
1202 You can change compression method with the -t/--type option.
1202 You can change compression method with the -t/--type option.
1203 The available compression methods are: none, bzip2, and
1203 The available compression methods are: none, bzip2, and
1204 gzip (by default, bundles are compressed using bzip2).
1204 gzip (by default, bundles are compressed using bzip2).
1205
1205
1206 The bundle file can then be transferred using conventional means
1206 The bundle file can then be transferred using conventional means
1207 and applied to another repository with the unbundle or pull
1207 and applied to another repository with the unbundle or pull
1208 command. This is useful when direct push and pull are not
1208 command. This is useful when direct push and pull are not
1209 available or when exporting an entire repository is undesirable.
1209 available or when exporting an entire repository is undesirable.
1210
1210
1211 Applying bundles preserves all changeset contents including
1211 Applying bundles preserves all changeset contents including
1212 permissions, copy/rename information, and revision history.
1212 permissions, copy/rename information, and revision history.
1213
1213
1214 Returns 0 on success, 1 if no changes found.
1214 Returns 0 on success, 1 if no changes found.
1215 """
1215 """
1216 revs = None
1216 revs = None
1217 if 'rev' in opts:
1217 if 'rev' in opts:
1218 revs = scmutil.revrange(repo, opts['rev'])
1218 revs = scmutil.revrange(repo, opts['rev'])
1219
1219
1220 bundletype = opts.get('type', 'bzip2').lower()
1220 bundletype = opts.get('type', 'bzip2').lower()
1221 btypes = {'none': 'HG10UN',
1221 btypes = {'none': 'HG10UN',
1222 'bzip2': 'HG10BZ',
1222 'bzip2': 'HG10BZ',
1223 'gzip': 'HG10GZ',
1223 'gzip': 'HG10GZ',
1224 'bundle2': 'HG2Y'}
1224 'bundle2': 'HG2Y'}
1225 bundletype = btypes.get(bundletype)
1225 bundletype = btypes.get(bundletype)
1226 if bundletype not in changegroup.bundletypes:
1226 if bundletype not in changegroup.bundletypes:
1227 raise util.Abort(_('unknown bundle type specified with --type'))
1227 raise util.Abort(_('unknown bundle type specified with --type'))
1228
1228
1229 if opts.get('all'):
1229 if opts.get('all'):
1230 base = ['null']
1230 base = ['null']
1231 else:
1231 else:
1232 base = scmutil.revrange(repo, opts.get('base'))
1232 base = scmutil.revrange(repo, opts.get('base'))
1233 # TODO: get desired bundlecaps from command line.
1233 # TODO: get desired bundlecaps from command line.
1234 bundlecaps = None
1234 bundlecaps = None
1235 if base:
1235 if base:
1236 if dest:
1236 if dest:
1237 raise util.Abort(_("--base is incompatible with specifying "
1237 raise util.Abort(_("--base is incompatible with specifying "
1238 "a destination"))
1238 "a destination"))
1239 common = [repo.lookup(rev) for rev in base]
1239 common = [repo.lookup(rev) for rev in base]
1240 heads = revs and map(repo.lookup, revs) or revs
1240 heads = revs and map(repo.lookup, revs) or revs
1241 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1241 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1242 common=common, bundlecaps=bundlecaps)
1242 common=common, bundlecaps=bundlecaps)
1243 outgoing = None
1243 outgoing = None
1244 else:
1244 else:
1245 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1245 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1246 dest, branches = hg.parseurl(dest, opts.get('branch'))
1246 dest, branches = hg.parseurl(dest, opts.get('branch'))
1247 other = hg.peer(repo, opts, dest)
1247 other = hg.peer(repo, opts, dest)
1248 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1248 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1249 heads = revs and map(repo.lookup, revs) or revs
1249 heads = revs and map(repo.lookup, revs) or revs
1250 outgoing = discovery.findcommonoutgoing(repo, other,
1250 outgoing = discovery.findcommonoutgoing(repo, other,
1251 onlyheads=heads,
1251 onlyheads=heads,
1252 force=opts.get('force'),
1252 force=opts.get('force'),
1253 portable=True)
1253 portable=True)
1254 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1254 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1255 bundlecaps)
1255 bundlecaps)
1256 if not cg:
1256 if not cg:
1257 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1257 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1258 return 1
1258 return 1
1259
1259
1260 changegroup.writebundle(ui, cg, fname, bundletype)
1260 changegroup.writebundle(ui, cg, fname, bundletype)
1261
1261
1262 @command('cat',
1262 @command('cat',
1263 [('o', 'output', '',
1263 [('o', 'output', '',
1264 _('print output to file with formatted name'), _('FORMAT')),
1264 _('print output to file with formatted name'), _('FORMAT')),
1265 ('r', 'rev', '', _('print the given revision'), _('REV')),
1265 ('r', 'rev', '', _('print the given revision'), _('REV')),
1266 ('', 'decode', None, _('apply any matching decode filter')),
1266 ('', 'decode', None, _('apply any matching decode filter')),
1267 ] + walkopts,
1267 ] + walkopts,
1268 _('[OPTION]... FILE...'),
1268 _('[OPTION]... FILE...'),
1269 inferrepo=True)
1269 inferrepo=True)
1270 def cat(ui, repo, file1, *pats, **opts):
1270 def cat(ui, repo, file1, *pats, **opts):
1271 """output the current or given revision of files
1271 """output the current or given revision of files
1272
1272
1273 Print the specified files as they were at the given revision. If
1273 Print the specified files as they were at the given revision. If
1274 no revision is given, the parent of the working directory is used.
1274 no revision is given, the parent of the working directory is used.
1275
1275
1276 Output may be to a file, in which case the name of the file is
1276 Output may be to a file, in which case the name of the file is
1277 given using a format string. The formatting rules as follows:
1277 given using a format string. The formatting rules as follows:
1278
1278
1279 :``%%``: literal "%" character
1279 :``%%``: literal "%" character
1280 :``%s``: basename of file being printed
1280 :``%s``: basename of file being printed
1281 :``%d``: dirname of file being printed, or '.' if in repository root
1281 :``%d``: dirname of file being printed, or '.' if in repository root
1282 :``%p``: root-relative path name of file being printed
1282 :``%p``: root-relative path name of file being printed
1283 :``%H``: changeset hash (40 hexadecimal digits)
1283 :``%H``: changeset hash (40 hexadecimal digits)
1284 :``%R``: changeset revision number
1284 :``%R``: changeset revision number
1285 :``%h``: short-form changeset hash (12 hexadecimal digits)
1285 :``%h``: short-form changeset hash (12 hexadecimal digits)
1286 :``%r``: zero-padded changeset revision number
1286 :``%r``: zero-padded changeset revision number
1287 :``%b``: basename of the exporting repository
1287 :``%b``: basename of the exporting repository
1288
1288
1289 Returns 0 on success.
1289 Returns 0 on success.
1290 """
1290 """
1291 ctx = scmutil.revsingle(repo, opts.get('rev'))
1291 ctx = scmutil.revsingle(repo, opts.get('rev'))
1292 m = scmutil.match(ctx, (file1,) + pats, opts)
1292 m = scmutil.match(ctx, (file1,) + pats, opts)
1293
1293
1294 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1294 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1295
1295
1296 @command('^clone',
1296 @command('^clone',
1297 [('U', 'noupdate', None, _('the clone will include an empty working '
1297 [('U', 'noupdate', None, _('the clone will include an empty working '
1298 'directory (only a repository)')),
1298 'directory (only a repository)')),
1299 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1299 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1300 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1300 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1301 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1301 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1302 ('', 'pull', None, _('use pull protocol to copy metadata')),
1302 ('', 'pull', None, _('use pull protocol to copy metadata')),
1303 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1303 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1304 ] + remoteopts,
1304 ] + remoteopts,
1305 _('[OPTION]... SOURCE [DEST]'),
1305 _('[OPTION]... SOURCE [DEST]'),
1306 norepo=True)
1306 norepo=True)
1307 def clone(ui, source, dest=None, **opts):
1307 def clone(ui, source, dest=None, **opts):
1308 """make a copy of an existing repository
1308 """make a copy of an existing repository
1309
1309
1310 Create a copy of an existing repository in a new directory.
1310 Create a copy of an existing repository in a new directory.
1311
1311
1312 If no destination directory name is specified, it defaults to the
1312 If no destination directory name is specified, it defaults to the
1313 basename of the source.
1313 basename of the source.
1314
1314
1315 The location of the source is added to the new repository's
1315 The location of the source is added to the new repository's
1316 ``.hg/hgrc`` file, as the default to be used for future pulls.
1316 ``.hg/hgrc`` file, as the default to be used for future pulls.
1317
1317
1318 Only local paths and ``ssh://`` URLs are supported as
1318 Only local paths and ``ssh://`` URLs are supported as
1319 destinations. For ``ssh://`` destinations, no working directory or
1319 destinations. For ``ssh://`` destinations, no working directory or
1320 ``.hg/hgrc`` will be created on the remote side.
1320 ``.hg/hgrc`` will be created on the remote side.
1321
1321
1322 To pull only a subset of changesets, specify one or more revisions
1322 To pull only a subset of changesets, specify one or more revisions
1323 identifiers with -r/--rev or branches with -b/--branch. The
1323 identifiers with -r/--rev or branches with -b/--branch. The
1324 resulting clone will contain only the specified changesets and
1324 resulting clone will contain only the specified changesets and
1325 their ancestors. These options (or 'clone src#rev dest') imply
1325 their ancestors. These options (or 'clone src#rev dest') imply
1326 --pull, even for local source repositories. Note that specifying a
1326 --pull, even for local source repositories. Note that specifying a
1327 tag will include the tagged changeset but not the changeset
1327 tag will include the tagged changeset but not the changeset
1328 containing the tag.
1328 containing the tag.
1329
1329
1330 If the source repository has a bookmark called '@' set, that
1330 If the source repository has a bookmark called '@' set, that
1331 revision will be checked out in the new repository by default.
1331 revision will be checked out in the new repository by default.
1332
1332
1333 To check out a particular version, use -u/--update, or
1333 To check out a particular version, use -u/--update, or
1334 -U/--noupdate to create a clone with no working directory.
1334 -U/--noupdate to create a clone with no working directory.
1335
1335
1336 .. container:: verbose
1336 .. container:: verbose
1337
1337
1338 For efficiency, hardlinks are used for cloning whenever the
1338 For efficiency, hardlinks are used for cloning whenever the
1339 source and destination are on the same filesystem (note this
1339 source and destination are on the same filesystem (note this
1340 applies only to the repository data, not to the working
1340 applies only to the repository data, not to the working
1341 directory). Some filesystems, such as AFS, implement hardlinking
1341 directory). Some filesystems, such as AFS, implement hardlinking
1342 incorrectly, but do not report errors. In these cases, use the
1342 incorrectly, but do not report errors. In these cases, use the
1343 --pull option to avoid hardlinking.
1343 --pull option to avoid hardlinking.
1344
1344
1345 In some cases, you can clone repositories and the working
1345 In some cases, you can clone repositories and the working
1346 directory using full hardlinks with ::
1346 directory using full hardlinks with ::
1347
1347
1348 $ cp -al REPO REPOCLONE
1348 $ cp -al REPO REPOCLONE
1349
1349
1350 This is the fastest way to clone, but it is not always safe. The
1350 This is the fastest way to clone, but it is not always safe. The
1351 operation is not atomic (making sure REPO is not modified during
1351 operation is not atomic (making sure REPO is not modified during
1352 the operation is up to you) and you have to make sure your
1352 the operation is up to you) and you have to make sure your
1353 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1353 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1354 so). Also, this is not compatible with certain extensions that
1354 so). Also, this is not compatible with certain extensions that
1355 place their metadata under the .hg directory, such as mq.
1355 place their metadata under the .hg directory, such as mq.
1356
1356
1357 Mercurial will update the working directory to the first applicable
1357 Mercurial will update the working directory to the first applicable
1358 revision from this list:
1358 revision from this list:
1359
1359
1360 a) null if -U or the source repository has no changesets
1360 a) null if -U or the source repository has no changesets
1361 b) if -u . and the source repository is local, the first parent of
1361 b) if -u . and the source repository is local, the first parent of
1362 the source repository's working directory
1362 the source repository's working directory
1363 c) the changeset specified with -u (if a branch name, this means the
1363 c) the changeset specified with -u (if a branch name, this means the
1364 latest head of that branch)
1364 latest head of that branch)
1365 d) the changeset specified with -r
1365 d) the changeset specified with -r
1366 e) the tipmost head specified with -b
1366 e) the tipmost head specified with -b
1367 f) the tipmost head specified with the url#branch source syntax
1367 f) the tipmost head specified with the url#branch source syntax
1368 g) the revision marked with the '@' bookmark, if present
1368 g) the revision marked with the '@' bookmark, if present
1369 h) the tipmost head of the default branch
1369 h) the tipmost head of the default branch
1370 i) tip
1370 i) tip
1371
1371
1372 Examples:
1372 Examples:
1373
1373
1374 - clone a remote repository to a new directory named hg/::
1374 - clone a remote repository to a new directory named hg/::
1375
1375
1376 hg clone http://selenic.com/hg
1376 hg clone http://selenic.com/hg
1377
1377
1378 - create a lightweight local clone::
1378 - create a lightweight local clone::
1379
1379
1380 hg clone project/ project-feature/
1380 hg clone project/ project-feature/
1381
1381
1382 - clone from an absolute path on an ssh server (note double-slash)::
1382 - clone from an absolute path on an ssh server (note double-slash)::
1383
1383
1384 hg clone ssh://user@server//home/projects/alpha/
1384 hg clone ssh://user@server//home/projects/alpha/
1385
1385
1386 - do a high-speed clone over a LAN while checking out a
1386 - do a high-speed clone over a LAN while checking out a
1387 specified version::
1387 specified version::
1388
1388
1389 hg clone --uncompressed http://server/repo -u 1.5
1389 hg clone --uncompressed http://server/repo -u 1.5
1390
1390
1391 - create a repository without changesets after a particular revision::
1391 - create a repository without changesets after a particular revision::
1392
1392
1393 hg clone -r 04e544 experimental/ good/
1393 hg clone -r 04e544 experimental/ good/
1394
1394
1395 - clone (and track) a particular named branch::
1395 - clone (and track) a particular named branch::
1396
1396
1397 hg clone http://selenic.com/hg#stable
1397 hg clone http://selenic.com/hg#stable
1398
1398
1399 See :hg:`help urls` for details on specifying URLs.
1399 See :hg:`help urls` for details on specifying URLs.
1400
1400
1401 Returns 0 on success.
1401 Returns 0 on success.
1402 """
1402 """
1403 if opts.get('noupdate') and opts.get('updaterev'):
1403 if opts.get('noupdate') and opts.get('updaterev'):
1404 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1404 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1405
1405
1406 r = hg.clone(ui, opts, source, dest,
1406 r = hg.clone(ui, opts, source, dest,
1407 pull=opts.get('pull'),
1407 pull=opts.get('pull'),
1408 stream=opts.get('uncompressed'),
1408 stream=opts.get('uncompressed'),
1409 rev=opts.get('rev'),
1409 rev=opts.get('rev'),
1410 update=opts.get('updaterev') or not opts.get('noupdate'),
1410 update=opts.get('updaterev') or not opts.get('noupdate'),
1411 branch=opts.get('branch'))
1411 branch=opts.get('branch'))
1412
1412
1413 return r is None
1413 return r is None
1414
1414
1415 @command('^commit|ci',
1415 @command('^commit|ci',
1416 [('A', 'addremove', None,
1416 [('A', 'addremove', None,
1417 _('mark new/missing files as added/removed before committing')),
1417 _('mark new/missing files as added/removed before committing')),
1418 ('', 'close-branch', None,
1418 ('', 'close-branch', None,
1419 _('mark a branch as closed, hiding it from the branch list')),
1419 _('mark a branch as closed, hiding it from the branch list')),
1420 ('', 'amend', None, _('amend the parent of the working directory')),
1420 ('', 'amend', None, _('amend the parent of the working directory')),
1421 ('s', 'secret', None, _('use the secret phase for committing')),
1421 ('s', 'secret', None, _('use the secret phase for committing')),
1422 ('e', 'edit', None, _('invoke editor on commit messages')),
1422 ('e', 'edit', None, _('invoke editor on commit messages')),
1423 ('i', 'interactive', None, _('use interactive mode')),
1423 ('i', 'interactive', None, _('use interactive mode')),
1424 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1424 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1425 _('[OPTION]... [FILE]...'),
1425 _('[OPTION]... [FILE]...'),
1426 inferrepo=True)
1426 inferrepo=True)
1427 def commit(ui, repo, *pats, **opts):
1427 def commit(ui, repo, *pats, **opts):
1428 """commit the specified files or all outstanding changes
1428 """commit the specified files or all outstanding changes
1429
1429
1430 Commit changes to the given files into the repository. Unlike a
1430 Commit changes to the given files into the repository. Unlike a
1431 centralized SCM, this operation is a local operation. See
1431 centralized SCM, this operation is a local operation. See
1432 :hg:`push` for a way to actively distribute your changes.
1432 :hg:`push` for a way to actively distribute your changes.
1433
1433
1434 If a list of files is omitted, all changes reported by :hg:`status`
1434 If a list of files is omitted, all changes reported by :hg:`status`
1435 will be committed.
1435 will be committed.
1436
1436
1437 If you are committing the result of a merge, do not provide any
1437 If you are committing the result of a merge, do not provide any
1438 filenames or -I/-X filters.
1438 filenames or -I/-X filters.
1439
1439
1440 If no commit message is specified, Mercurial starts your
1440 If no commit message is specified, Mercurial starts your
1441 configured editor where you can enter a message. In case your
1441 configured editor where you can enter a message. In case your
1442 commit fails, you will find a backup of your message in
1442 commit fails, you will find a backup of your message in
1443 ``.hg/last-message.txt``.
1443 ``.hg/last-message.txt``.
1444
1444
1445 The --amend flag can be used to amend the parent of the
1445 The --amend flag can be used to amend the parent of the
1446 working directory with a new commit that contains the changes
1446 working directory with a new commit that contains the changes
1447 in the parent in addition to those currently reported by :hg:`status`,
1447 in the parent in addition to those currently reported by :hg:`status`,
1448 if there are any. The old commit is stored in a backup bundle in
1448 if there are any. The old commit is stored in a backup bundle in
1449 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1449 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1450 on how to restore it).
1450 on how to restore it).
1451
1451
1452 Message, user and date are taken from the amended commit unless
1452 Message, user and date are taken from the amended commit unless
1453 specified. When a message isn't specified on the command line,
1453 specified. When a message isn't specified on the command line,
1454 the editor will open with the message of the amended commit.
1454 the editor will open with the message of the amended commit.
1455
1455
1456 It is not possible to amend public changesets (see :hg:`help phases`)
1456 It is not possible to amend public changesets (see :hg:`help phases`)
1457 or changesets that have children.
1457 or changesets that have children.
1458
1458
1459 See :hg:`help dates` for a list of formats valid for -d/--date.
1459 See :hg:`help dates` for a list of formats valid for -d/--date.
1460
1460
1461 Returns 0 on success, 1 if nothing changed.
1461 Returns 0 on success, 1 if nothing changed.
1462 """
1462 """
1463 if opts.get('interactive'):
1463 if opts.get('interactive'):
1464 opts.pop('interactive')
1464 opts.pop('interactive')
1465 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1465 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1466 cmdutil.recordfilter, *pats, **opts)
1466 cmdutil.recordfilter, *pats, **opts)
1467 return
1467 return
1468
1468
1469 if opts.get('subrepos'):
1469 if opts.get('subrepos'):
1470 if opts.get('amend'):
1470 if opts.get('amend'):
1471 raise util.Abort(_('cannot amend with --subrepos'))
1471 raise util.Abort(_('cannot amend with --subrepos'))
1472 # Let --subrepos on the command line override config setting.
1472 # Let --subrepos on the command line override config setting.
1473 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1473 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1474
1474
1475 cmdutil.checkunfinished(repo, commit=True)
1475 cmdutil.checkunfinished(repo, commit=True)
1476
1476
1477 branch = repo[None].branch()
1477 branch = repo[None].branch()
1478 bheads = repo.branchheads(branch)
1478 bheads = repo.branchheads(branch)
1479
1479
1480 extra = {}
1480 extra = {}
1481 if opts.get('close_branch'):
1481 if opts.get('close_branch'):
1482 extra['close'] = 1
1482 extra['close'] = 1
1483
1483
1484 if not bheads:
1484 if not bheads:
1485 raise util.Abort(_('can only close branch heads'))
1485 raise util.Abort(_('can only close branch heads'))
1486 elif opts.get('amend'):
1486 elif opts.get('amend'):
1487 if repo.parents()[0].p1().branch() != branch and \
1487 if repo.parents()[0].p1().branch() != branch and \
1488 repo.parents()[0].p2().branch() != branch:
1488 repo.parents()[0].p2().branch() != branch:
1489 raise util.Abort(_('can only close branch heads'))
1489 raise util.Abort(_('can only close branch heads'))
1490
1490
1491 if opts.get('amend'):
1491 if opts.get('amend'):
1492 if ui.configbool('ui', 'commitsubrepos'):
1492 if ui.configbool('ui', 'commitsubrepos'):
1493 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1493 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1494
1494
1495 old = repo['.']
1495 old = repo['.']
1496 if not old.mutable():
1496 if not old.mutable():
1497 raise util.Abort(_('cannot amend public changesets'))
1497 raise util.Abort(_('cannot amend public changesets'))
1498 if len(repo[None].parents()) > 1:
1498 if len(repo[None].parents()) > 1:
1499 raise util.Abort(_('cannot amend while merging'))
1499 raise util.Abort(_('cannot amend while merging'))
1500 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1500 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1501 if not allowunstable and old.children():
1501 if not allowunstable and old.children():
1502 raise util.Abort(_('cannot amend changeset with children'))
1502 raise util.Abort(_('cannot amend changeset with children'))
1503
1503
1504 # commitfunc is used only for temporary amend commit by cmdutil.amend
1504 # commitfunc is used only for temporary amend commit by cmdutil.amend
1505 def commitfunc(ui, repo, message, match, opts):
1505 def commitfunc(ui, repo, message, match, opts):
1506 return repo.commit(message,
1506 return repo.commit(message,
1507 opts.get('user') or old.user(),
1507 opts.get('user') or old.user(),
1508 opts.get('date') or old.date(),
1508 opts.get('date') or old.date(),
1509 match,
1509 match,
1510 extra=extra)
1510 extra=extra)
1511
1511
1512 current = repo._bookmarkcurrent
1512 current = repo._bookmarkcurrent
1513 marks = old.bookmarks()
1513 marks = old.bookmarks()
1514 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1514 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1515 if node == old.node():
1515 if node == old.node():
1516 ui.status(_("nothing changed\n"))
1516 ui.status(_("nothing changed\n"))
1517 return 1
1517 return 1
1518 elif marks:
1518 elif marks:
1519 ui.debug('moving bookmarks %r from %s to %s\n' %
1519 ui.debug('moving bookmarks %r from %s to %s\n' %
1520 (marks, old.hex(), hex(node)))
1520 (marks, old.hex(), hex(node)))
1521 newmarks = repo._bookmarks
1521 newmarks = repo._bookmarks
1522 for bm in marks:
1522 for bm in marks:
1523 newmarks[bm] = node
1523 newmarks[bm] = node
1524 if bm == current:
1524 if bm == current:
1525 bookmarks.setcurrent(repo, bm)
1525 bookmarks.setcurrent(repo, bm)
1526 newmarks.write()
1526 newmarks.write()
1527 else:
1527 else:
1528 def commitfunc(ui, repo, message, match, opts):
1528 def commitfunc(ui, repo, message, match, opts):
1529 backup = ui.backupconfig('phases', 'new-commit')
1529 backup = ui.backupconfig('phases', 'new-commit')
1530 baseui = repo.baseui
1530 baseui = repo.baseui
1531 basebackup = baseui.backupconfig('phases', 'new-commit')
1531 basebackup = baseui.backupconfig('phases', 'new-commit')
1532 try:
1532 try:
1533 if opts.get('secret'):
1533 if opts.get('secret'):
1534 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1534 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1535 # Propagate to subrepos
1535 # Propagate to subrepos
1536 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1536 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1537
1537
1538 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1538 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1539 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1539 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1540 return repo.commit(message, opts.get('user'), opts.get('date'),
1540 return repo.commit(message, opts.get('user'), opts.get('date'),
1541 match,
1541 match,
1542 editor=editor,
1542 editor=editor,
1543 extra=extra)
1543 extra=extra)
1544 finally:
1544 finally:
1545 ui.restoreconfig(backup)
1545 ui.restoreconfig(backup)
1546 repo.baseui.restoreconfig(basebackup)
1546 repo.baseui.restoreconfig(basebackup)
1547
1547
1548
1548
1549 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1549 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1550
1550
1551 if not node:
1551 if not node:
1552 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1552 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1553 if stat[3]:
1553 if stat[3]:
1554 ui.status(_("nothing changed (%d missing files, see "
1554 ui.status(_("nothing changed (%d missing files, see "
1555 "'hg status')\n") % len(stat[3]))
1555 "'hg status')\n") % len(stat[3]))
1556 else:
1556 else:
1557 ui.status(_("nothing changed\n"))
1557 ui.status(_("nothing changed\n"))
1558 return 1
1558 return 1
1559
1559
1560 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1560 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1561
1561
1562 @command('config|showconfig|debugconfig',
1562 @command('config|showconfig|debugconfig',
1563 [('u', 'untrusted', None, _('show untrusted configuration options')),
1563 [('u', 'untrusted', None, _('show untrusted configuration options')),
1564 ('e', 'edit', None, _('edit user config')),
1564 ('e', 'edit', None, _('edit user config')),
1565 ('l', 'local', None, _('edit repository config')),
1565 ('l', 'local', None, _('edit repository config')),
1566 ('g', 'global', None, _('edit global config'))],
1566 ('g', 'global', None, _('edit global config'))],
1567 _('[-u] [NAME]...'),
1567 _('[-u] [NAME]...'),
1568 optionalrepo=True)
1568 optionalrepo=True)
1569 def config(ui, repo, *values, **opts):
1569 def config(ui, repo, *values, **opts):
1570 """show combined config settings from all hgrc files
1570 """show combined config settings from all hgrc files
1571
1571
1572 With no arguments, print names and values of all config items.
1572 With no arguments, print names and values of all config items.
1573
1573
1574 With one argument of the form section.name, print just the value
1574 With one argument of the form section.name, print just the value
1575 of that config item.
1575 of that config item.
1576
1576
1577 With multiple arguments, print names and values of all config
1577 With multiple arguments, print names and values of all config
1578 items with matching section names.
1578 items with matching section names.
1579
1579
1580 With --edit, start an editor on the user-level config file. With
1580 With --edit, start an editor on the user-level config file. With
1581 --global, edit the system-wide config file. With --local, edit the
1581 --global, edit the system-wide config file. With --local, edit the
1582 repository-level config file.
1582 repository-level config file.
1583
1583
1584 With --debug, the source (filename and line number) is printed
1584 With --debug, the source (filename and line number) is printed
1585 for each config item.
1585 for each config item.
1586
1586
1587 See :hg:`help config` for more information about config files.
1587 See :hg:`help config` for more information about config files.
1588
1588
1589 Returns 0 on success, 1 if NAME does not exist.
1589 Returns 0 on success, 1 if NAME does not exist.
1590
1590
1591 """
1591 """
1592
1592
1593 if opts.get('edit') or opts.get('local') or opts.get('global'):
1593 if opts.get('edit') or opts.get('local') or opts.get('global'):
1594 if opts.get('local') and opts.get('global'):
1594 if opts.get('local') and opts.get('global'):
1595 raise util.Abort(_("can't use --local and --global together"))
1595 raise util.Abort(_("can't use --local and --global together"))
1596
1596
1597 if opts.get('local'):
1597 if opts.get('local'):
1598 if not repo:
1598 if not repo:
1599 raise util.Abort(_("can't use --local outside a repository"))
1599 raise util.Abort(_("can't use --local outside a repository"))
1600 paths = [repo.join('hgrc')]
1600 paths = [repo.join('hgrc')]
1601 elif opts.get('global'):
1601 elif opts.get('global'):
1602 paths = scmutil.systemrcpath()
1602 paths = scmutil.systemrcpath()
1603 else:
1603 else:
1604 paths = scmutil.userrcpath()
1604 paths = scmutil.userrcpath()
1605
1605
1606 for f in paths:
1606 for f in paths:
1607 if os.path.exists(f):
1607 if os.path.exists(f):
1608 break
1608 break
1609 else:
1609 else:
1610 if opts.get('global'):
1610 if opts.get('global'):
1611 samplehgrc = uimod.samplehgrcs['global']
1611 samplehgrc = uimod.samplehgrcs['global']
1612 elif opts.get('local'):
1612 elif opts.get('local'):
1613 samplehgrc = uimod.samplehgrcs['local']
1613 samplehgrc = uimod.samplehgrcs['local']
1614 else:
1614 else:
1615 samplehgrc = uimod.samplehgrcs['user']
1615 samplehgrc = uimod.samplehgrcs['user']
1616
1616
1617 f = paths[0]
1617 f = paths[0]
1618 fp = open(f, "w")
1618 fp = open(f, "w")
1619 fp.write(samplehgrc)
1619 fp.write(samplehgrc)
1620 fp.close()
1620 fp.close()
1621
1621
1622 editor = ui.geteditor()
1622 editor = ui.geteditor()
1623 ui.system("%s \"%s\"" % (editor, f),
1623 ui.system("%s \"%s\"" % (editor, f),
1624 onerr=util.Abort, errprefix=_("edit failed"))
1624 onerr=util.Abort, errprefix=_("edit failed"))
1625 return
1625 return
1626
1626
1627 for f in scmutil.rcpath():
1627 for f in scmutil.rcpath():
1628 ui.debug('read config from: %s\n' % f)
1628 ui.debug('read config from: %s\n' % f)
1629 untrusted = bool(opts.get('untrusted'))
1629 untrusted = bool(opts.get('untrusted'))
1630 if values:
1630 if values:
1631 sections = [v for v in values if '.' not in v]
1631 sections = [v for v in values if '.' not in v]
1632 items = [v for v in values if '.' in v]
1632 items = [v for v in values if '.' in v]
1633 if len(items) > 1 or items and sections:
1633 if len(items) > 1 or items and sections:
1634 raise util.Abort(_('only one config item permitted'))
1634 raise util.Abort(_('only one config item permitted'))
1635 matched = False
1635 matched = False
1636 for section, name, value in ui.walkconfig(untrusted=untrusted):
1636 for section, name, value in ui.walkconfig(untrusted=untrusted):
1637 value = str(value).replace('\n', '\\n')
1637 value = str(value).replace('\n', '\\n')
1638 sectname = section + '.' + name
1638 sectname = section + '.' + name
1639 if values:
1639 if values:
1640 for v in values:
1640 for v in values:
1641 if v == section:
1641 if v == section:
1642 ui.debug('%s: ' %
1642 ui.debug('%s: ' %
1643 ui.configsource(section, name, untrusted))
1643 ui.configsource(section, name, untrusted))
1644 ui.write('%s=%s\n' % (sectname, value))
1644 ui.write('%s=%s\n' % (sectname, value))
1645 matched = True
1645 matched = True
1646 elif v == sectname:
1646 elif v == sectname:
1647 ui.debug('%s: ' %
1647 ui.debug('%s: ' %
1648 ui.configsource(section, name, untrusted))
1648 ui.configsource(section, name, untrusted))
1649 ui.write(value, '\n')
1649 ui.write(value, '\n')
1650 matched = True
1650 matched = True
1651 else:
1651 else:
1652 ui.debug('%s: ' %
1652 ui.debug('%s: ' %
1653 ui.configsource(section, name, untrusted))
1653 ui.configsource(section, name, untrusted))
1654 ui.write('%s=%s\n' % (sectname, value))
1654 ui.write('%s=%s\n' % (sectname, value))
1655 matched = True
1655 matched = True
1656 if matched:
1656 if matched:
1657 return 0
1657 return 0
1658 return 1
1658 return 1
1659
1659
1660 @command('copy|cp',
1660 @command('copy|cp',
1661 [('A', 'after', None, _('record a copy that has already occurred')),
1661 [('A', 'after', None, _('record a copy that has already occurred')),
1662 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1662 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1663 ] + walkopts + dryrunopts,
1663 ] + walkopts + dryrunopts,
1664 _('[OPTION]... [SOURCE]... DEST'))
1664 _('[OPTION]... [SOURCE]... DEST'))
1665 def copy(ui, repo, *pats, **opts):
1665 def copy(ui, repo, *pats, **opts):
1666 """mark files as copied for the next commit
1666 """mark files as copied for the next commit
1667
1667
1668 Mark dest as having copies of source files. If dest is a
1668 Mark dest as having copies of source files. If dest is a
1669 directory, copies are put in that directory. If dest is a file,
1669 directory, copies are put in that directory. If dest is a file,
1670 the source must be a single file.
1670 the source must be a single file.
1671
1671
1672 By default, this command copies the contents of files as they
1672 By default, this command copies the contents of files as they
1673 exist in the working directory. If invoked with -A/--after, the
1673 exist in the working directory. If invoked with -A/--after, the
1674 operation is recorded, but no copying is performed.
1674 operation is recorded, but no copying is performed.
1675
1675
1676 This command takes effect with the next commit. To undo a copy
1676 This command takes effect with the next commit. To undo a copy
1677 before that, see :hg:`revert`.
1677 before that, see :hg:`revert`.
1678
1678
1679 Returns 0 on success, 1 if errors are encountered.
1679 Returns 0 on success, 1 if errors are encountered.
1680 """
1680 """
1681 wlock = repo.wlock(False)
1681 wlock = repo.wlock(False)
1682 try:
1682 try:
1683 return cmdutil.copy(ui, repo, pats, opts)
1683 return cmdutil.copy(ui, repo, pats, opts)
1684 finally:
1684 finally:
1685 wlock.release()
1685 wlock.release()
1686
1686
1687 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1687 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1688 def debugancestor(ui, repo, *args):
1688 def debugancestor(ui, repo, *args):
1689 """find the ancestor revision of two revisions in a given index"""
1689 """find the ancestor revision of two revisions in a given index"""
1690 if len(args) == 3:
1690 if len(args) == 3:
1691 index, rev1, rev2 = args
1691 index, rev1, rev2 = args
1692 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1692 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1693 lookup = r.lookup
1693 lookup = r.lookup
1694 elif len(args) == 2:
1694 elif len(args) == 2:
1695 if not repo:
1695 if not repo:
1696 raise util.Abort(_("there is no Mercurial repository here "
1696 raise util.Abort(_("there is no Mercurial repository here "
1697 "(.hg not found)"))
1697 "(.hg not found)"))
1698 rev1, rev2 = args
1698 rev1, rev2 = args
1699 r = repo.changelog
1699 r = repo.changelog
1700 lookup = repo.lookup
1700 lookup = repo.lookup
1701 else:
1701 else:
1702 raise util.Abort(_('either two or three arguments required'))
1702 raise util.Abort(_('either two or three arguments required'))
1703 a = r.ancestor(lookup(rev1), lookup(rev2))
1703 a = r.ancestor(lookup(rev1), lookup(rev2))
1704 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1704 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1705
1705
1706 @command('debugbuilddag',
1706 @command('debugbuilddag',
1707 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1707 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1708 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1708 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1709 ('n', 'new-file', None, _('add new file at each rev'))],
1709 ('n', 'new-file', None, _('add new file at each rev'))],
1710 _('[OPTION]... [TEXT]'))
1710 _('[OPTION]... [TEXT]'))
1711 def debugbuilddag(ui, repo, text=None,
1711 def debugbuilddag(ui, repo, text=None,
1712 mergeable_file=False,
1712 mergeable_file=False,
1713 overwritten_file=False,
1713 overwritten_file=False,
1714 new_file=False):
1714 new_file=False):
1715 """builds a repo with a given DAG from scratch in the current empty repo
1715 """builds a repo with a given DAG from scratch in the current empty repo
1716
1716
1717 The description of the DAG is read from stdin if not given on the
1717 The description of the DAG is read from stdin if not given on the
1718 command line.
1718 command line.
1719
1719
1720 Elements:
1720 Elements:
1721
1721
1722 - "+n" is a linear run of n nodes based on the current default parent
1722 - "+n" is a linear run of n nodes based on the current default parent
1723 - "." is a single node based on the current default parent
1723 - "." is a single node based on the current default parent
1724 - "$" resets the default parent to null (implied at the start);
1724 - "$" resets the default parent to null (implied at the start);
1725 otherwise the default parent is always the last node created
1725 otherwise the default parent is always the last node created
1726 - "<p" sets the default parent to the backref p
1726 - "<p" sets the default parent to the backref p
1727 - "*p" is a fork at parent p, which is a backref
1727 - "*p" is a fork at parent p, which is a backref
1728 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1728 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1729 - "/p2" is a merge of the preceding node and p2
1729 - "/p2" is a merge of the preceding node and p2
1730 - ":tag" defines a local tag for the preceding node
1730 - ":tag" defines a local tag for the preceding node
1731 - "@branch" sets the named branch for subsequent nodes
1731 - "@branch" sets the named branch for subsequent nodes
1732 - "#...\\n" is a comment up to the end of the line
1732 - "#...\\n" is a comment up to the end of the line
1733
1733
1734 Whitespace between the above elements is ignored.
1734 Whitespace between the above elements is ignored.
1735
1735
1736 A backref is either
1736 A backref is either
1737
1737
1738 - a number n, which references the node curr-n, where curr is the current
1738 - a number n, which references the node curr-n, where curr is the current
1739 node, or
1739 node, or
1740 - the name of a local tag you placed earlier using ":tag", or
1740 - the name of a local tag you placed earlier using ":tag", or
1741 - empty to denote the default parent.
1741 - empty to denote the default parent.
1742
1742
1743 All string valued-elements are either strictly alphanumeric, or must
1743 All string valued-elements are either strictly alphanumeric, or must
1744 be enclosed in double quotes ("..."), with "\\" as escape character.
1744 be enclosed in double quotes ("..."), with "\\" as escape character.
1745 """
1745 """
1746
1746
1747 if text is None:
1747 if text is None:
1748 ui.status(_("reading DAG from stdin\n"))
1748 ui.status(_("reading DAG from stdin\n"))
1749 text = ui.fin.read()
1749 text = ui.fin.read()
1750
1750
1751 cl = repo.changelog
1751 cl = repo.changelog
1752 if len(cl) > 0:
1752 if len(cl) > 0:
1753 raise util.Abort(_('repository is not empty'))
1753 raise util.Abort(_('repository is not empty'))
1754
1754
1755 # determine number of revs in DAG
1755 # determine number of revs in DAG
1756 total = 0
1756 total = 0
1757 for type, data in dagparser.parsedag(text):
1757 for type, data in dagparser.parsedag(text):
1758 if type == 'n':
1758 if type == 'n':
1759 total += 1
1759 total += 1
1760
1760
1761 if mergeable_file:
1761 if mergeable_file:
1762 linesperrev = 2
1762 linesperrev = 2
1763 # make a file with k lines per rev
1763 # make a file with k lines per rev
1764 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1764 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1765 initialmergedlines.append("")
1765 initialmergedlines.append("")
1766
1766
1767 tags = []
1767 tags = []
1768
1768
1769 lock = tr = None
1769 lock = tr = None
1770 try:
1770 try:
1771 lock = repo.lock()
1771 lock = repo.lock()
1772 tr = repo.transaction("builddag")
1772 tr = repo.transaction("builddag")
1773
1773
1774 at = -1
1774 at = -1
1775 atbranch = 'default'
1775 atbranch = 'default'
1776 nodeids = []
1776 nodeids = []
1777 id = 0
1777 id = 0
1778 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1778 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1779 for type, data in dagparser.parsedag(text):
1779 for type, data in dagparser.parsedag(text):
1780 if type == 'n':
1780 if type == 'n':
1781 ui.note(('node %s\n' % str(data)))
1781 ui.note(('node %s\n' % str(data)))
1782 id, ps = data
1782 id, ps = data
1783
1783
1784 files = []
1784 files = []
1785 fctxs = {}
1785 fctxs = {}
1786
1786
1787 p2 = None
1787 p2 = None
1788 if mergeable_file:
1788 if mergeable_file:
1789 fn = "mf"
1789 fn = "mf"
1790 p1 = repo[ps[0]]
1790 p1 = repo[ps[0]]
1791 if len(ps) > 1:
1791 if len(ps) > 1:
1792 p2 = repo[ps[1]]
1792 p2 = repo[ps[1]]
1793 pa = p1.ancestor(p2)
1793 pa = p1.ancestor(p2)
1794 base, local, other = [x[fn].data() for x in (pa, p1,
1794 base, local, other = [x[fn].data() for x in (pa, p1,
1795 p2)]
1795 p2)]
1796 m3 = simplemerge.Merge3Text(base, local, other)
1796 m3 = simplemerge.Merge3Text(base, local, other)
1797 ml = [l.strip() for l in m3.merge_lines()]
1797 ml = [l.strip() for l in m3.merge_lines()]
1798 ml.append("")
1798 ml.append("")
1799 elif at > 0:
1799 elif at > 0:
1800 ml = p1[fn].data().split("\n")
1800 ml = p1[fn].data().split("\n")
1801 else:
1801 else:
1802 ml = initialmergedlines
1802 ml = initialmergedlines
1803 ml[id * linesperrev] += " r%i" % id
1803 ml[id * linesperrev] += " r%i" % id
1804 mergedtext = "\n".join(ml)
1804 mergedtext = "\n".join(ml)
1805 files.append(fn)
1805 files.append(fn)
1806 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1806 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1807
1807
1808 if overwritten_file:
1808 if overwritten_file:
1809 fn = "of"
1809 fn = "of"
1810 files.append(fn)
1810 files.append(fn)
1811 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1811 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1812
1812
1813 if new_file:
1813 if new_file:
1814 fn = "nf%i" % id
1814 fn = "nf%i" % id
1815 files.append(fn)
1815 files.append(fn)
1816 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1816 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1817 if len(ps) > 1:
1817 if len(ps) > 1:
1818 if not p2:
1818 if not p2:
1819 p2 = repo[ps[1]]
1819 p2 = repo[ps[1]]
1820 for fn in p2:
1820 for fn in p2:
1821 if fn.startswith("nf"):
1821 if fn.startswith("nf"):
1822 files.append(fn)
1822 files.append(fn)
1823 fctxs[fn] = p2[fn]
1823 fctxs[fn] = p2[fn]
1824
1824
1825 def fctxfn(repo, cx, path):
1825 def fctxfn(repo, cx, path):
1826 return fctxs.get(path)
1826 return fctxs.get(path)
1827
1827
1828 if len(ps) == 0 or ps[0] < 0:
1828 if len(ps) == 0 or ps[0] < 0:
1829 pars = [None, None]
1829 pars = [None, None]
1830 elif len(ps) == 1:
1830 elif len(ps) == 1:
1831 pars = [nodeids[ps[0]], None]
1831 pars = [nodeids[ps[0]], None]
1832 else:
1832 else:
1833 pars = [nodeids[p] for p in ps]
1833 pars = [nodeids[p] for p in ps]
1834 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1834 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1835 date=(id, 0),
1835 date=(id, 0),
1836 user="debugbuilddag",
1836 user="debugbuilddag",
1837 extra={'branch': atbranch})
1837 extra={'branch': atbranch})
1838 nodeid = repo.commitctx(cx)
1838 nodeid = repo.commitctx(cx)
1839 nodeids.append(nodeid)
1839 nodeids.append(nodeid)
1840 at = id
1840 at = id
1841 elif type == 'l':
1841 elif type == 'l':
1842 id, name = data
1842 id, name = data
1843 ui.note(('tag %s\n' % name))
1843 ui.note(('tag %s\n' % name))
1844 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1844 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1845 elif type == 'a':
1845 elif type == 'a':
1846 ui.note(('branch %s\n' % data))
1846 ui.note(('branch %s\n' % data))
1847 atbranch = data
1847 atbranch = data
1848 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1848 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1849 tr.close()
1849 tr.close()
1850
1850
1851 if tags:
1851 if tags:
1852 repo.vfs.write("localtags", "".join(tags))
1852 repo.vfs.write("localtags", "".join(tags))
1853 finally:
1853 finally:
1854 ui.progress(_('building'), None)
1854 ui.progress(_('building'), None)
1855 release(tr, lock)
1855 release(tr, lock)
1856
1856
1857 @command('debugbundle',
1857 @command('debugbundle',
1858 [('a', 'all', None, _('show all details'))],
1858 [('a', 'all', None, _('show all details'))],
1859 _('FILE'),
1859 _('FILE'),
1860 norepo=True)
1860 norepo=True)
1861 def debugbundle(ui, bundlepath, all=None, **opts):
1861 def debugbundle(ui, bundlepath, all=None, **opts):
1862 """lists the contents of a bundle"""
1862 """lists the contents of a bundle"""
1863 f = hg.openpath(ui, bundlepath)
1863 f = hg.openpath(ui, bundlepath)
1864 try:
1864 try:
1865 gen = exchange.readbundle(ui, f, bundlepath)
1865 gen = exchange.readbundle(ui, f, bundlepath)
1866 if isinstance(gen, bundle2.unbundle20):
1866 if isinstance(gen, bundle2.unbundle20):
1867 return _debugbundle2(ui, gen, all=all, **opts)
1867 return _debugbundle2(ui, gen, all=all, **opts)
1868 if all:
1868 if all:
1869 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1869 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1870
1870
1871 def showchunks(named):
1871 def showchunks(named):
1872 ui.write("\n%s\n" % named)
1872 ui.write("\n%s\n" % named)
1873 chain = None
1873 chain = None
1874 while True:
1874 while True:
1875 chunkdata = gen.deltachunk(chain)
1875 chunkdata = gen.deltachunk(chain)
1876 if not chunkdata:
1876 if not chunkdata:
1877 break
1877 break
1878 node = chunkdata['node']
1878 node = chunkdata['node']
1879 p1 = chunkdata['p1']
1879 p1 = chunkdata['p1']
1880 p2 = chunkdata['p2']
1880 p2 = chunkdata['p2']
1881 cs = chunkdata['cs']
1881 cs = chunkdata['cs']
1882 deltabase = chunkdata['deltabase']
1882 deltabase = chunkdata['deltabase']
1883 delta = chunkdata['delta']
1883 delta = chunkdata['delta']
1884 ui.write("%s %s %s %s %s %s\n" %
1884 ui.write("%s %s %s %s %s %s\n" %
1885 (hex(node), hex(p1), hex(p2),
1885 (hex(node), hex(p1), hex(p2),
1886 hex(cs), hex(deltabase), len(delta)))
1886 hex(cs), hex(deltabase), len(delta)))
1887 chain = node
1887 chain = node
1888
1888
1889 chunkdata = gen.changelogheader()
1889 chunkdata = gen.changelogheader()
1890 showchunks("changelog")
1890 showchunks("changelog")
1891 chunkdata = gen.manifestheader()
1891 chunkdata = gen.manifestheader()
1892 showchunks("manifest")
1892 showchunks("manifest")
1893 while True:
1893 while True:
1894 chunkdata = gen.filelogheader()
1894 chunkdata = gen.filelogheader()
1895 if not chunkdata:
1895 if not chunkdata:
1896 break
1896 break
1897 fname = chunkdata['filename']
1897 fname = chunkdata['filename']
1898 showchunks(fname)
1898 showchunks(fname)
1899 else:
1899 else:
1900 if isinstance(gen, bundle2.unbundle20):
1900 if isinstance(gen, bundle2.unbundle20):
1901 raise util.Abort(_('use debugbundle2 for this file'))
1901 raise util.Abort(_('use debugbundle2 for this file'))
1902 chunkdata = gen.changelogheader()
1902 chunkdata = gen.changelogheader()
1903 chain = None
1903 chain = None
1904 while True:
1904 while True:
1905 chunkdata = gen.deltachunk(chain)
1905 chunkdata = gen.deltachunk(chain)
1906 if not chunkdata:
1906 if not chunkdata:
1907 break
1907 break
1908 node = chunkdata['node']
1908 node = chunkdata['node']
1909 ui.write("%s\n" % hex(node))
1909 ui.write("%s\n" % hex(node))
1910 chain = node
1910 chain = node
1911 finally:
1911 finally:
1912 f.close()
1912 f.close()
1913
1913
1914 def _debugbundle2(ui, gen, **opts):
1914 def _debugbundle2(ui, gen, **opts):
1915 """lists the contents of a bundle2"""
1915 """lists the contents of a bundle2"""
1916 if not isinstance(gen, bundle2.unbundle20):
1916 if not isinstance(gen, bundle2.unbundle20):
1917 raise util.Abort(_('not a bundle2 file'))
1917 raise util.Abort(_('not a bundle2 file'))
1918 ui.write(('Stream params: %s\n' % repr(gen.params)))
1918 ui.write(('Stream params: %s\n' % repr(gen.params)))
1919 for part in gen.iterparts():
1919 for part in gen.iterparts():
1920 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1920 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1921 if part.type == 'b2x:changegroup':
1921 if part.type == 'b2x:changegroup':
1922 version = part.params.get('version', '01')
1922 version = part.params.get('version', '01')
1923 cg = changegroup.packermap[version][1](part, 'UN')
1923 cg = changegroup.packermap[version][1](part, 'UN')
1924 chunkdata = cg.changelogheader()
1924 chunkdata = cg.changelogheader()
1925 chain = None
1925 chain = None
1926 while True:
1926 while True:
1927 chunkdata = cg.deltachunk(chain)
1927 chunkdata = cg.deltachunk(chain)
1928 if not chunkdata:
1928 if not chunkdata:
1929 break
1929 break
1930 node = chunkdata['node']
1930 node = chunkdata['node']
1931 ui.write(" %s\n" % hex(node))
1931 ui.write(" %s\n" % hex(node))
1932 chain = node
1932 chain = node
1933
1933
1934 @command('debugcheckstate', [], '')
1934 @command('debugcheckstate', [], '')
1935 def debugcheckstate(ui, repo):
1935 def debugcheckstate(ui, repo):
1936 """validate the correctness of the current dirstate"""
1936 """validate the correctness of the current dirstate"""
1937 parent1, parent2 = repo.dirstate.parents()
1937 parent1, parent2 = repo.dirstate.parents()
1938 m1 = repo[parent1].manifest()
1938 m1 = repo[parent1].manifest()
1939 m2 = repo[parent2].manifest()
1939 m2 = repo[parent2].manifest()
1940 errors = 0
1940 errors = 0
1941 for f in repo.dirstate:
1941 for f in repo.dirstate:
1942 state = repo.dirstate[f]
1942 state = repo.dirstate[f]
1943 if state in "nr" and f not in m1:
1943 if state in "nr" and f not in m1:
1944 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1944 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1945 errors += 1
1945 errors += 1
1946 if state in "a" and f in m1:
1946 if state in "a" and f in m1:
1947 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1947 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1948 errors += 1
1948 errors += 1
1949 if state in "m" and f not in m1 and f not in m2:
1949 if state in "m" and f not in m1 and f not in m2:
1950 ui.warn(_("%s in state %s, but not in either manifest\n") %
1950 ui.warn(_("%s in state %s, but not in either manifest\n") %
1951 (f, state))
1951 (f, state))
1952 errors += 1
1952 errors += 1
1953 for f in m1:
1953 for f in m1:
1954 state = repo.dirstate[f]
1954 state = repo.dirstate[f]
1955 if state not in "nrm":
1955 if state not in "nrm":
1956 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1956 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1957 errors += 1
1957 errors += 1
1958 if errors:
1958 if errors:
1959 error = _(".hg/dirstate inconsistent with current parent's manifest")
1959 error = _(".hg/dirstate inconsistent with current parent's manifest")
1960 raise util.Abort(error)
1960 raise util.Abort(error)
1961
1961
1962 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1962 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1963 def debugcommands(ui, cmd='', *args):
1963 def debugcommands(ui, cmd='', *args):
1964 """list all available commands and options"""
1964 """list all available commands and options"""
1965 for cmd, vals in sorted(table.iteritems()):
1965 for cmd, vals in sorted(table.iteritems()):
1966 cmd = cmd.split('|')[0].strip('^')
1966 cmd = cmd.split('|')[0].strip('^')
1967 opts = ', '.join([i[1] for i in vals[1]])
1967 opts = ', '.join([i[1] for i in vals[1]])
1968 ui.write('%s: %s\n' % (cmd, opts))
1968 ui.write('%s: %s\n' % (cmd, opts))
1969
1969
1970 @command('debugcomplete',
1970 @command('debugcomplete',
1971 [('o', 'options', None, _('show the command options'))],
1971 [('o', 'options', None, _('show the command options'))],
1972 _('[-o] CMD'),
1972 _('[-o] CMD'),
1973 norepo=True)
1973 norepo=True)
1974 def debugcomplete(ui, cmd='', **opts):
1974 def debugcomplete(ui, cmd='', **opts):
1975 """returns the completion list associated with the given command"""
1975 """returns the completion list associated with the given command"""
1976
1976
1977 if opts.get('options'):
1977 if opts.get('options'):
1978 options = []
1978 options = []
1979 otables = [globalopts]
1979 otables = [globalopts]
1980 if cmd:
1980 if cmd:
1981 aliases, entry = cmdutil.findcmd(cmd, table, False)
1981 aliases, entry = cmdutil.findcmd(cmd, table, False)
1982 otables.append(entry[1])
1982 otables.append(entry[1])
1983 for t in otables:
1983 for t in otables:
1984 for o in t:
1984 for o in t:
1985 if "(DEPRECATED)" in o[3]:
1985 if "(DEPRECATED)" in o[3]:
1986 continue
1986 continue
1987 if o[0]:
1987 if o[0]:
1988 options.append('-%s' % o[0])
1988 options.append('-%s' % o[0])
1989 options.append('--%s' % o[1])
1989 options.append('--%s' % o[1])
1990 ui.write("%s\n" % "\n".join(options))
1990 ui.write("%s\n" % "\n".join(options))
1991 return
1991 return
1992
1992
1993 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1993 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1994 if ui.verbose:
1994 if ui.verbose:
1995 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1995 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1996 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1996 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1997
1997
1998 @command('debugdag',
1998 @command('debugdag',
1999 [('t', 'tags', None, _('use tags as labels')),
1999 [('t', 'tags', None, _('use tags as labels')),
2000 ('b', 'branches', None, _('annotate with branch names')),
2000 ('b', 'branches', None, _('annotate with branch names')),
2001 ('', 'dots', None, _('use dots for runs')),
2001 ('', 'dots', None, _('use dots for runs')),
2002 ('s', 'spaces', None, _('separate elements by spaces'))],
2002 ('s', 'spaces', None, _('separate elements by spaces'))],
2003 _('[OPTION]... [FILE [REV]...]'),
2003 _('[OPTION]... [FILE [REV]...]'),
2004 optionalrepo=True)
2004 optionalrepo=True)
2005 def debugdag(ui, repo, file_=None, *revs, **opts):
2005 def debugdag(ui, repo, file_=None, *revs, **opts):
2006 """format the changelog or an index DAG as a concise textual description
2006 """format the changelog or an index DAG as a concise textual description
2007
2007
2008 If you pass a revlog index, the revlog's DAG is emitted. If you list
2008 If you pass a revlog index, the revlog's DAG is emitted. If you list
2009 revision numbers, they get labeled in the output as rN.
2009 revision numbers, they get labeled in the output as rN.
2010
2010
2011 Otherwise, the changelog DAG of the current repo is emitted.
2011 Otherwise, the changelog DAG of the current repo is emitted.
2012 """
2012 """
2013 spaces = opts.get('spaces')
2013 spaces = opts.get('spaces')
2014 dots = opts.get('dots')
2014 dots = opts.get('dots')
2015 if file_:
2015 if file_:
2016 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2016 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2017 revs = set((int(r) for r in revs))
2017 revs = set((int(r) for r in revs))
2018 def events():
2018 def events():
2019 for r in rlog:
2019 for r in rlog:
2020 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2020 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2021 if p != -1))
2021 if p != -1))
2022 if r in revs:
2022 if r in revs:
2023 yield 'l', (r, "r%i" % r)
2023 yield 'l', (r, "r%i" % r)
2024 elif repo:
2024 elif repo:
2025 cl = repo.changelog
2025 cl = repo.changelog
2026 tags = opts.get('tags')
2026 tags = opts.get('tags')
2027 branches = opts.get('branches')
2027 branches = opts.get('branches')
2028 if tags:
2028 if tags:
2029 labels = {}
2029 labels = {}
2030 for l, n in repo.tags().items():
2030 for l, n in repo.tags().items():
2031 labels.setdefault(cl.rev(n), []).append(l)
2031 labels.setdefault(cl.rev(n), []).append(l)
2032 def events():
2032 def events():
2033 b = "default"
2033 b = "default"
2034 for r in cl:
2034 for r in cl:
2035 if branches:
2035 if branches:
2036 newb = cl.read(cl.node(r))[5]['branch']
2036 newb = cl.read(cl.node(r))[5]['branch']
2037 if newb != b:
2037 if newb != b:
2038 yield 'a', newb
2038 yield 'a', newb
2039 b = newb
2039 b = newb
2040 yield 'n', (r, list(p for p in cl.parentrevs(r)
2040 yield 'n', (r, list(p for p in cl.parentrevs(r)
2041 if p != -1))
2041 if p != -1))
2042 if tags:
2042 if tags:
2043 ls = labels.get(r)
2043 ls = labels.get(r)
2044 if ls:
2044 if ls:
2045 for l in ls:
2045 for l in ls:
2046 yield 'l', (r, l)
2046 yield 'l', (r, l)
2047 else:
2047 else:
2048 raise util.Abort(_('need repo for changelog dag'))
2048 raise util.Abort(_('need repo for changelog dag'))
2049
2049
2050 for line in dagparser.dagtextlines(events(),
2050 for line in dagparser.dagtextlines(events(),
2051 addspaces=spaces,
2051 addspaces=spaces,
2052 wraplabels=True,
2052 wraplabels=True,
2053 wrapannotations=True,
2053 wrapannotations=True,
2054 wrapnonlinear=dots,
2054 wrapnonlinear=dots,
2055 usedots=dots,
2055 usedots=dots,
2056 maxlinewidth=70):
2056 maxlinewidth=70):
2057 ui.write(line)
2057 ui.write(line)
2058 ui.write("\n")
2058 ui.write("\n")
2059
2059
2060 @command('debugdata',
2060 @command('debugdata',
2061 [('c', 'changelog', False, _('open changelog')),
2061 [('c', 'changelog', False, _('open changelog')),
2062 ('m', 'manifest', False, _('open manifest'))],
2062 ('m', 'manifest', False, _('open manifest'))],
2063 _('-c|-m|FILE REV'))
2063 _('-c|-m|FILE REV'))
2064 def debugdata(ui, repo, file_, rev=None, **opts):
2064 def debugdata(ui, repo, file_, rev=None, **opts):
2065 """dump the contents of a data file revision"""
2065 """dump the contents of a data file revision"""
2066 if opts.get('changelog') or opts.get('manifest'):
2066 if opts.get('changelog') or opts.get('manifest'):
2067 file_, rev = None, file_
2067 file_, rev = None, file_
2068 elif rev is None:
2068 elif rev is None:
2069 raise error.CommandError('debugdata', _('invalid arguments'))
2069 raise error.CommandError('debugdata', _('invalid arguments'))
2070 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2070 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2071 try:
2071 try:
2072 ui.write(r.revision(r.lookup(rev)))
2072 ui.write(r.revision(r.lookup(rev)))
2073 except KeyError:
2073 except KeyError:
2074 raise util.Abort(_('invalid revision identifier %s') % rev)
2074 raise util.Abort(_('invalid revision identifier %s') % rev)
2075
2075
2076 @command('debugdate',
2076 @command('debugdate',
2077 [('e', 'extended', None, _('try extended date formats'))],
2077 [('e', 'extended', None, _('try extended date formats'))],
2078 _('[-e] DATE [RANGE]'),
2078 _('[-e] DATE [RANGE]'),
2079 norepo=True, optionalrepo=True)
2079 norepo=True, optionalrepo=True)
2080 def debugdate(ui, date, range=None, **opts):
2080 def debugdate(ui, date, range=None, **opts):
2081 """parse and display a date"""
2081 """parse and display a date"""
2082 if opts["extended"]:
2082 if opts["extended"]:
2083 d = util.parsedate(date, util.extendeddateformats)
2083 d = util.parsedate(date, util.extendeddateformats)
2084 else:
2084 else:
2085 d = util.parsedate(date)
2085 d = util.parsedate(date)
2086 ui.write(("internal: %s %s\n") % d)
2086 ui.write(("internal: %s %s\n") % d)
2087 ui.write(("standard: %s\n") % util.datestr(d))
2087 ui.write(("standard: %s\n") % util.datestr(d))
2088 if range:
2088 if range:
2089 m = util.matchdate(range)
2089 m = util.matchdate(range)
2090 ui.write(("match: %s\n") % m(d[0]))
2090 ui.write(("match: %s\n") % m(d[0]))
2091
2091
2092 @command('debugdiscovery',
2092 @command('debugdiscovery',
2093 [('', 'old', None, _('use old-style discovery')),
2093 [('', 'old', None, _('use old-style discovery')),
2094 ('', 'nonheads', None,
2094 ('', 'nonheads', None,
2095 _('use old-style discovery with non-heads included')),
2095 _('use old-style discovery with non-heads included')),
2096 ] + remoteopts,
2096 ] + remoteopts,
2097 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2097 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2098 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2098 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2099 """runs the changeset discovery protocol in isolation"""
2099 """runs the changeset discovery protocol in isolation"""
2100 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2100 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2101 opts.get('branch'))
2101 opts.get('branch'))
2102 remote = hg.peer(repo, opts, remoteurl)
2102 remote = hg.peer(repo, opts, remoteurl)
2103 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2103 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2104
2104
2105 # make sure tests are repeatable
2105 # make sure tests are repeatable
2106 random.seed(12323)
2106 random.seed(12323)
2107
2107
2108 def doit(localheads, remoteheads, remote=remote):
2108 def doit(localheads, remoteheads, remote=remote):
2109 if opts.get('old'):
2109 if opts.get('old'):
2110 if localheads:
2110 if localheads:
2111 raise util.Abort('cannot use localheads with old style '
2111 raise util.Abort('cannot use localheads with old style '
2112 'discovery')
2112 'discovery')
2113 if not util.safehasattr(remote, 'branches'):
2113 if not util.safehasattr(remote, 'branches'):
2114 # enable in-client legacy support
2114 # enable in-client legacy support
2115 remote = localrepo.locallegacypeer(remote.local())
2115 remote = localrepo.locallegacypeer(remote.local())
2116 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2116 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2117 force=True)
2117 force=True)
2118 common = set(common)
2118 common = set(common)
2119 if not opts.get('nonheads'):
2119 if not opts.get('nonheads'):
2120 ui.write(("unpruned common: %s\n") %
2120 ui.write(("unpruned common: %s\n") %
2121 " ".join(sorted(short(n) for n in common)))
2121 " ".join(sorted(short(n) for n in common)))
2122 dag = dagutil.revlogdag(repo.changelog)
2122 dag = dagutil.revlogdag(repo.changelog)
2123 all = dag.ancestorset(dag.internalizeall(common))
2123 all = dag.ancestorset(dag.internalizeall(common))
2124 common = dag.externalizeall(dag.headsetofconnecteds(all))
2124 common = dag.externalizeall(dag.headsetofconnecteds(all))
2125 else:
2125 else:
2126 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2126 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2127 common = set(common)
2127 common = set(common)
2128 rheads = set(hds)
2128 rheads = set(hds)
2129 lheads = set(repo.heads())
2129 lheads = set(repo.heads())
2130 ui.write(("common heads: %s\n") %
2130 ui.write(("common heads: %s\n") %
2131 " ".join(sorted(short(n) for n in common)))
2131 " ".join(sorted(short(n) for n in common)))
2132 if lheads <= common:
2132 if lheads <= common:
2133 ui.write(("local is subset\n"))
2133 ui.write(("local is subset\n"))
2134 elif rheads <= common:
2134 elif rheads <= common:
2135 ui.write(("remote is subset\n"))
2135 ui.write(("remote is subset\n"))
2136
2136
2137 serverlogs = opts.get('serverlog')
2137 serverlogs = opts.get('serverlog')
2138 if serverlogs:
2138 if serverlogs:
2139 for filename in serverlogs:
2139 for filename in serverlogs:
2140 logfile = open(filename, 'r')
2140 logfile = open(filename, 'r')
2141 try:
2141 try:
2142 line = logfile.readline()
2142 line = logfile.readline()
2143 while line:
2143 while line:
2144 parts = line.strip().split(';')
2144 parts = line.strip().split(';')
2145 op = parts[1]
2145 op = parts[1]
2146 if op == 'cg':
2146 if op == 'cg':
2147 pass
2147 pass
2148 elif op == 'cgss':
2148 elif op == 'cgss':
2149 doit(parts[2].split(' '), parts[3].split(' '))
2149 doit(parts[2].split(' '), parts[3].split(' '))
2150 elif op == 'unb':
2150 elif op == 'unb':
2151 doit(parts[3].split(' '), parts[2].split(' '))
2151 doit(parts[3].split(' '), parts[2].split(' '))
2152 line = logfile.readline()
2152 line = logfile.readline()
2153 finally:
2153 finally:
2154 logfile.close()
2154 logfile.close()
2155
2155
2156 else:
2156 else:
2157 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2157 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2158 opts.get('remote_head'))
2158 opts.get('remote_head'))
2159 localrevs = opts.get('local_head')
2159 localrevs = opts.get('local_head')
2160 doit(localrevs, remoterevs)
2160 doit(localrevs, remoterevs)
2161
2161
2162 @command('debugfileset',
2162 @command('debugfileset',
2163 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2163 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2164 _('[-r REV] FILESPEC'))
2164 _('[-r REV] FILESPEC'))
2165 def debugfileset(ui, repo, expr, **opts):
2165 def debugfileset(ui, repo, expr, **opts):
2166 '''parse and apply a fileset specification'''
2166 '''parse and apply a fileset specification'''
2167 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2167 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2168 if ui.verbose:
2168 if ui.verbose:
2169 tree = fileset.parse(expr)[0]
2169 tree = fileset.parse(expr)[0]
2170 ui.note(tree, "\n")
2170 ui.note(tree, "\n")
2171
2171
2172 for f in ctx.getfileset(expr):
2172 for f in ctx.getfileset(expr):
2173 ui.write("%s\n" % f)
2173 ui.write("%s\n" % f)
2174
2174
2175 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2175 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2176 def debugfsinfo(ui, path="."):
2176 def debugfsinfo(ui, path="."):
2177 """show information detected about current filesystem"""
2177 """show information detected about current filesystem"""
2178 util.writefile('.debugfsinfo', '')
2178 util.writefile('.debugfsinfo', '')
2179 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2179 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2180 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2180 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2181 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2181 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2182 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2182 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2183 and 'yes' or 'no'))
2183 and 'yes' or 'no'))
2184 os.unlink('.debugfsinfo')
2184 os.unlink('.debugfsinfo')
2185
2185
2186 @command('debuggetbundle',
2186 @command('debuggetbundle',
2187 [('H', 'head', [], _('id of head node'), _('ID')),
2187 [('H', 'head', [], _('id of head node'), _('ID')),
2188 ('C', 'common', [], _('id of common node'), _('ID')),
2188 ('C', 'common', [], _('id of common node'), _('ID')),
2189 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2189 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2190 _('REPO FILE [-H|-C ID]...'),
2190 _('REPO FILE [-H|-C ID]...'),
2191 norepo=True)
2191 norepo=True)
2192 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2192 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2193 """retrieves a bundle from a repo
2193 """retrieves a bundle from a repo
2194
2194
2195 Every ID must be a full-length hex node id string. Saves the bundle to the
2195 Every ID must be a full-length hex node id string. Saves the bundle to the
2196 given file.
2196 given file.
2197 """
2197 """
2198 repo = hg.peer(ui, opts, repopath)
2198 repo = hg.peer(ui, opts, repopath)
2199 if not repo.capable('getbundle'):
2199 if not repo.capable('getbundle'):
2200 raise util.Abort("getbundle() not supported by target repository")
2200 raise util.Abort("getbundle() not supported by target repository")
2201 args = {}
2201 args = {}
2202 if common:
2202 if common:
2203 args['common'] = [bin(s) for s in common]
2203 args['common'] = [bin(s) for s in common]
2204 if head:
2204 if head:
2205 args['heads'] = [bin(s) for s in head]
2205 args['heads'] = [bin(s) for s in head]
2206 # TODO: get desired bundlecaps from command line.
2206 # TODO: get desired bundlecaps from command line.
2207 args['bundlecaps'] = None
2207 args['bundlecaps'] = None
2208 bundle = repo.getbundle('debug', **args)
2208 bundle = repo.getbundle('debug', **args)
2209
2209
2210 bundletype = opts.get('type', 'bzip2').lower()
2210 bundletype = opts.get('type', 'bzip2').lower()
2211 btypes = {'none': 'HG10UN',
2211 btypes = {'none': 'HG10UN',
2212 'bzip2': 'HG10BZ',
2212 'bzip2': 'HG10BZ',
2213 'gzip': 'HG10GZ',
2213 'gzip': 'HG10GZ',
2214 'bundle2': 'HG2Y'}
2214 'bundle2': 'HG2Y'}
2215 bundletype = btypes.get(bundletype)
2215 bundletype = btypes.get(bundletype)
2216 if bundletype not in changegroup.bundletypes:
2216 if bundletype not in changegroup.bundletypes:
2217 raise util.Abort(_('unknown bundle type specified with --type'))
2217 raise util.Abort(_('unknown bundle type specified with --type'))
2218 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2218 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2219
2219
2220 @command('debugignore', [], '')
2220 @command('debugignore', [], '')
2221 def debugignore(ui, repo, *values, **opts):
2221 def debugignore(ui, repo, *values, **opts):
2222 """display the combined ignore pattern"""
2222 """display the combined ignore pattern"""
2223 ignore = repo.dirstate._ignore
2223 ignore = repo.dirstate._ignore
2224 includepat = getattr(ignore, 'includepat', None)
2224 includepat = getattr(ignore, 'includepat', None)
2225 if includepat is not None:
2225 if includepat is not None:
2226 ui.write("%s\n" % includepat)
2226 ui.write("%s\n" % includepat)
2227 else:
2227 else:
2228 raise util.Abort(_("no ignore patterns found"))
2228 raise util.Abort(_("no ignore patterns found"))
2229
2229
2230 @command('debugindex',
2230 @command('debugindex',
2231 [('c', 'changelog', False, _('open changelog')),
2231 [('c', 'changelog', False, _('open changelog')),
2232 ('m', 'manifest', False, _('open manifest')),
2232 ('m', 'manifest', False, _('open manifest')),
2233 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2233 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2234 _('[-f FORMAT] -c|-m|FILE'),
2234 _('[-f FORMAT] -c|-m|FILE'),
2235 optionalrepo=True)
2235 optionalrepo=True)
2236 def debugindex(ui, repo, file_=None, **opts):
2236 def debugindex(ui, repo, file_=None, **opts):
2237 """dump the contents of an index file"""
2237 """dump the contents of an index file"""
2238 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2238 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2239 format = opts.get('format', 0)
2239 format = opts.get('format', 0)
2240 if format not in (0, 1):
2240 if format not in (0, 1):
2241 raise util.Abort(_("unknown format %d") % format)
2241 raise util.Abort(_("unknown format %d") % format)
2242
2242
2243 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2243 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2244 if generaldelta:
2244 if generaldelta:
2245 basehdr = ' delta'
2245 basehdr = ' delta'
2246 else:
2246 else:
2247 basehdr = ' base'
2247 basehdr = ' base'
2248
2248
2249 if ui.debugflag:
2249 if ui.debugflag:
2250 shortfn = hex
2250 shortfn = hex
2251 else:
2251 else:
2252 shortfn = short
2252 shortfn = short
2253
2253
2254 # There might not be anything in r, so have a sane default
2254 # There might not be anything in r, so have a sane default
2255 idlen = 12
2255 idlen = 12
2256 for i in r:
2256 for i in r:
2257 idlen = len(shortfn(r.node(i)))
2257 idlen = len(shortfn(r.node(i)))
2258 break
2258 break
2259
2259
2260 if format == 0:
2260 if format == 0:
2261 ui.write(" rev offset length " + basehdr + " linkrev"
2261 ui.write(" rev offset length " + basehdr + " linkrev"
2262 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2262 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2263 elif format == 1:
2263 elif format == 1:
2264 ui.write(" rev flag offset length"
2264 ui.write(" rev flag offset length"
2265 " size " + basehdr + " link p1 p2"
2265 " size " + basehdr + " link p1 p2"
2266 " %s\n" % "nodeid".rjust(idlen))
2266 " %s\n" % "nodeid".rjust(idlen))
2267
2267
2268 for i in r:
2268 for i in r:
2269 node = r.node(i)
2269 node = r.node(i)
2270 if generaldelta:
2270 if generaldelta:
2271 base = r.deltaparent(i)
2271 base = r.deltaparent(i)
2272 else:
2272 else:
2273 base = r.chainbase(i)
2273 base = r.chainbase(i)
2274 if format == 0:
2274 if format == 0:
2275 try:
2275 try:
2276 pp = r.parents(node)
2276 pp = r.parents(node)
2277 except Exception:
2277 except Exception:
2278 pp = [nullid, nullid]
2278 pp = [nullid, nullid]
2279 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2279 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2280 i, r.start(i), r.length(i), base, r.linkrev(i),
2280 i, r.start(i), r.length(i), base, r.linkrev(i),
2281 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2281 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2282 elif format == 1:
2282 elif format == 1:
2283 pr = r.parentrevs(i)
2283 pr = r.parentrevs(i)
2284 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2284 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2285 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2285 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2286 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2286 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2287
2287
2288 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2288 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2289 def debugindexdot(ui, repo, file_):
2289 def debugindexdot(ui, repo, file_):
2290 """dump an index DAG as a graphviz dot file"""
2290 """dump an index DAG as a graphviz dot file"""
2291 r = None
2291 r = None
2292 if repo:
2292 if repo:
2293 filelog = repo.file(file_)
2293 filelog = repo.file(file_)
2294 if len(filelog):
2294 if len(filelog):
2295 r = filelog
2295 r = filelog
2296 if not r:
2296 if not r:
2297 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2297 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2298 ui.write(("digraph G {\n"))
2298 ui.write(("digraph G {\n"))
2299 for i in r:
2299 for i in r:
2300 node = r.node(i)
2300 node = r.node(i)
2301 pp = r.parents(node)
2301 pp = r.parents(node)
2302 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2302 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2303 if pp[1] != nullid:
2303 if pp[1] != nullid:
2304 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2304 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2305 ui.write("}\n")
2305 ui.write("}\n")
2306
2306
2307 @command('debuginstall', [], '', norepo=True)
2307 @command('debuginstall', [], '', norepo=True)
2308 def debuginstall(ui):
2308 def debuginstall(ui):
2309 '''test Mercurial installation
2309 '''test Mercurial installation
2310
2310
2311 Returns 0 on success.
2311 Returns 0 on success.
2312 '''
2312 '''
2313
2313
2314 def writetemp(contents):
2314 def writetemp(contents):
2315 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2315 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2316 f = os.fdopen(fd, "wb")
2316 f = os.fdopen(fd, "wb")
2317 f.write(contents)
2317 f.write(contents)
2318 f.close()
2318 f.close()
2319 return name
2319 return name
2320
2320
2321 problems = 0
2321 problems = 0
2322
2322
2323 # encoding
2323 # encoding
2324 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2324 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2325 try:
2325 try:
2326 encoding.fromlocal("test")
2326 encoding.fromlocal("test")
2327 except util.Abort, inst:
2327 except util.Abort, inst:
2328 ui.write(" %s\n" % inst)
2328 ui.write(" %s\n" % inst)
2329 ui.write(_(" (check that your locale is properly set)\n"))
2329 ui.write(_(" (check that your locale is properly set)\n"))
2330 problems += 1
2330 problems += 1
2331
2331
2332 # Python
2332 # Python
2333 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2333 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2334 ui.status(_("checking Python version (%s)\n")
2334 ui.status(_("checking Python version (%s)\n")
2335 % ("%s.%s.%s" % sys.version_info[:3]))
2335 % ("%s.%s.%s" % sys.version_info[:3]))
2336 ui.status(_("checking Python lib (%s)...\n")
2336 ui.status(_("checking Python lib (%s)...\n")
2337 % os.path.dirname(os.__file__))
2337 % os.path.dirname(os.__file__))
2338
2338
2339 # compiled modules
2339 # compiled modules
2340 ui.status(_("checking installed modules (%s)...\n")
2340 ui.status(_("checking installed modules (%s)...\n")
2341 % os.path.dirname(__file__))
2341 % os.path.dirname(__file__))
2342 try:
2342 try:
2343 import bdiff, mpatch, base85, osutil
2343 import bdiff, mpatch, base85, osutil
2344 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2344 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2345 except Exception, inst:
2345 except Exception, inst:
2346 ui.write(" %s\n" % inst)
2346 ui.write(" %s\n" % inst)
2347 ui.write(_(" One or more extensions could not be found"))
2347 ui.write(_(" One or more extensions could not be found"))
2348 ui.write(_(" (check that you compiled the extensions)\n"))
2348 ui.write(_(" (check that you compiled the extensions)\n"))
2349 problems += 1
2349 problems += 1
2350
2350
2351 # templates
2351 # templates
2352 import templater
2352 import templater
2353 p = templater.templatepaths()
2353 p = templater.templatepaths()
2354 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2354 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2355 if p:
2355 if p:
2356 m = templater.templatepath("map-cmdline.default")
2356 m = templater.templatepath("map-cmdline.default")
2357 if m:
2357 if m:
2358 # template found, check if it is working
2358 # template found, check if it is working
2359 try:
2359 try:
2360 templater.templater(m)
2360 templater.templater(m)
2361 except Exception, inst:
2361 except Exception, inst:
2362 ui.write(" %s\n" % inst)
2362 ui.write(" %s\n" % inst)
2363 p = None
2363 p = None
2364 else:
2364 else:
2365 ui.write(_(" template 'default' not found\n"))
2365 ui.write(_(" template 'default' not found\n"))
2366 p = None
2366 p = None
2367 else:
2367 else:
2368 ui.write(_(" no template directories found\n"))
2368 ui.write(_(" no template directories found\n"))
2369 if not p:
2369 if not p:
2370 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2370 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2371 problems += 1
2371 problems += 1
2372
2372
2373 # editor
2373 # editor
2374 ui.status(_("checking commit editor...\n"))
2374 ui.status(_("checking commit editor...\n"))
2375 editor = ui.geteditor()
2375 editor = ui.geteditor()
2376 cmdpath = util.findexe(shlex.split(editor)[0])
2376 cmdpath = util.findexe(shlex.split(editor)[0])
2377 if not cmdpath:
2377 if not cmdpath:
2378 if editor == 'vi':
2378 if editor == 'vi':
2379 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2379 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2380 ui.write(_(" (specify a commit editor in your configuration"
2380 ui.write(_(" (specify a commit editor in your configuration"
2381 " file)\n"))
2381 " file)\n"))
2382 else:
2382 else:
2383 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2383 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2384 ui.write(_(" (specify a commit editor in your configuration"
2384 ui.write(_(" (specify a commit editor in your configuration"
2385 " file)\n"))
2385 " file)\n"))
2386 problems += 1
2386 problems += 1
2387
2387
2388 # check username
2388 # check username
2389 ui.status(_("checking username...\n"))
2389 ui.status(_("checking username...\n"))
2390 try:
2390 try:
2391 ui.username()
2391 ui.username()
2392 except util.Abort, e:
2392 except util.Abort, e:
2393 ui.write(" %s\n" % e)
2393 ui.write(" %s\n" % e)
2394 ui.write(_(" (specify a username in your configuration file)\n"))
2394 ui.write(_(" (specify a username in your configuration file)\n"))
2395 problems += 1
2395 problems += 1
2396
2396
2397 if not problems:
2397 if not problems:
2398 ui.status(_("no problems detected\n"))
2398 ui.status(_("no problems detected\n"))
2399 else:
2399 else:
2400 ui.write(_("%s problems detected,"
2400 ui.write(_("%s problems detected,"
2401 " please check your install!\n") % problems)
2401 " please check your install!\n") % problems)
2402
2402
2403 return problems
2403 return problems
2404
2404
2405 @command('debugknown', [], _('REPO ID...'), norepo=True)
2405 @command('debugknown', [], _('REPO ID...'), norepo=True)
2406 def debugknown(ui, repopath, *ids, **opts):
2406 def debugknown(ui, repopath, *ids, **opts):
2407 """test whether node ids are known to a repo
2407 """test whether node ids are known to a repo
2408
2408
2409 Every ID must be a full-length hex node id string. Returns a list of 0s
2409 Every ID must be a full-length hex node id string. Returns a list of 0s
2410 and 1s indicating unknown/known.
2410 and 1s indicating unknown/known.
2411 """
2411 """
2412 repo = hg.peer(ui, opts, repopath)
2412 repo = hg.peer(ui, opts, repopath)
2413 if not repo.capable('known'):
2413 if not repo.capable('known'):
2414 raise util.Abort("known() not supported by target repository")
2414 raise util.Abort("known() not supported by target repository")
2415 flags = repo.known([bin(s) for s in ids])
2415 flags = repo.known([bin(s) for s in ids])
2416 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2416 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2417
2417
2418 @command('debuglabelcomplete', [], _('LABEL...'))
2418 @command('debuglabelcomplete', [], _('LABEL...'))
2419 def debuglabelcomplete(ui, repo, *args):
2419 def debuglabelcomplete(ui, repo, *args):
2420 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2420 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2421 debugnamecomplete(ui, repo, *args)
2421 debugnamecomplete(ui, repo, *args)
2422
2422
2423 @command('debugnamecomplete', [], _('NAME...'))
2423 @command('debugnamecomplete', [], _('NAME...'))
2424 def debugnamecomplete(ui, repo, *args):
2424 def debugnamecomplete(ui, repo, *args):
2425 '''complete "names" - tags, open branch names, bookmark names'''
2425 '''complete "names" - tags, open branch names, bookmark names'''
2426
2426
2427 names = set()
2427 names = set()
2428 # since we previously only listed open branches, we will handle that
2428 # since we previously only listed open branches, we will handle that
2429 # specially (after this for loop)
2429 # specially (after this for loop)
2430 for name, ns in repo.names.iteritems():
2430 for name, ns in repo.names.iteritems():
2431 if name != 'branches':
2431 if name != 'branches':
2432 names.update(ns.listnames(repo))
2432 names.update(ns.listnames(repo))
2433 names.update(tag for (tag, heads, tip, closed)
2433 names.update(tag for (tag, heads, tip, closed)
2434 in repo.branchmap().iterbranches() if not closed)
2434 in repo.branchmap().iterbranches() if not closed)
2435 completions = set()
2435 completions = set()
2436 if not args:
2436 if not args:
2437 args = ['']
2437 args = ['']
2438 for a in args:
2438 for a in args:
2439 completions.update(n for n in names if n.startswith(a))
2439 completions.update(n for n in names if n.startswith(a))
2440 ui.write('\n'.join(sorted(completions)))
2440 ui.write('\n'.join(sorted(completions)))
2441 ui.write('\n')
2441 ui.write('\n')
2442
2442
2443 @command('debuglocks',
2443 @command('debuglocks',
2444 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2444 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2445 ('W', 'force-wlock', None,
2445 ('W', 'force-wlock', None,
2446 _('free the working state lock (DANGEROUS)'))],
2446 _('free the working state lock (DANGEROUS)'))],
2447 _('[OPTION]...'))
2447 _('[OPTION]...'))
2448 def debuglocks(ui, repo, **opts):
2448 def debuglocks(ui, repo, **opts):
2449 """show or modify state of locks
2449 """show or modify state of locks
2450
2450
2451 By default, this command will show which locks are held. This
2451 By default, this command will show which locks are held. This
2452 includes the user and process holding the lock, the amount of time
2452 includes the user and process holding the lock, the amount of time
2453 the lock has been held, and the machine name where the process is
2453 the lock has been held, and the machine name where the process is
2454 running if it's not local.
2454 running if it's not local.
2455
2455
2456 Locks protect the integrity of Mercurial's data, so should be
2456 Locks protect the integrity of Mercurial's data, so should be
2457 treated with care. System crashes or other interruptions may cause
2457 treated with care. System crashes or other interruptions may cause
2458 locks to not be properly released, though Mercurial will usually
2458 locks to not be properly released, though Mercurial will usually
2459 detect and remove such stale locks automatically.
2459 detect and remove such stale locks automatically.
2460
2460
2461 However, detecting stale locks may not always be possible (for
2461 However, detecting stale locks may not always be possible (for
2462 instance, on a shared filesystem). Removing locks may also be
2462 instance, on a shared filesystem). Removing locks may also be
2463 blocked by filesystem permissions.
2463 blocked by filesystem permissions.
2464
2464
2465 Returns 0 if no locks are held.
2465 Returns 0 if no locks are held.
2466
2466
2467 """
2467 """
2468
2468
2469 if opts.get('force_lock'):
2469 if opts.get('force_lock'):
2470 repo.svfs.unlink('lock')
2470 repo.svfs.unlink('lock')
2471 if opts.get('force_wlock'):
2471 if opts.get('force_wlock'):
2472 repo.vfs.unlink('wlock')
2472 repo.vfs.unlink('wlock')
2473 if opts.get('force_lock') or opts.get('force_lock'):
2473 if opts.get('force_lock') or opts.get('force_lock'):
2474 return 0
2474 return 0
2475
2475
2476 now = time.time()
2476 now = time.time()
2477 held = 0
2477 held = 0
2478
2478
2479 def report(vfs, name, method):
2479 def report(vfs, name, method):
2480 # this causes stale locks to get reaped for more accurate reporting
2480 # this causes stale locks to get reaped for more accurate reporting
2481 try:
2481 try:
2482 l = method(False)
2482 l = method(False)
2483 except error.LockHeld:
2483 except error.LockHeld:
2484 l = None
2484 l = None
2485
2485
2486 if l:
2486 if l:
2487 l.release()
2487 l.release()
2488 else:
2488 else:
2489 try:
2489 try:
2490 stat = repo.svfs.lstat(name)
2490 stat = repo.svfs.lstat(name)
2491 age = now - stat.st_mtime
2491 age = now - stat.st_mtime
2492 user = util.username(stat.st_uid)
2492 user = util.username(stat.st_uid)
2493 locker = vfs.readlock(name)
2493 locker = vfs.readlock(name)
2494 if ":" in locker:
2494 if ":" in locker:
2495 host, pid = locker.split(':')
2495 host, pid = locker.split(':')
2496 if host == socket.gethostname():
2496 if host == socket.gethostname():
2497 locker = 'user %s, process %s' % (user, pid)
2497 locker = 'user %s, process %s' % (user, pid)
2498 else:
2498 else:
2499 locker = 'user %s, process %s, host %s' \
2499 locker = 'user %s, process %s, host %s' \
2500 % (user, pid, host)
2500 % (user, pid, host)
2501 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2501 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2502 return 1
2502 return 1
2503 except OSError, e:
2503 except OSError, e:
2504 if e.errno != errno.ENOENT:
2504 if e.errno != errno.ENOENT:
2505 raise
2505 raise
2506
2506
2507 ui.write("%-6s free\n" % (name + ":"))
2507 ui.write("%-6s free\n" % (name + ":"))
2508 return 0
2508 return 0
2509
2509
2510 held += report(repo.svfs, "lock", repo.lock)
2510 held += report(repo.svfs, "lock", repo.lock)
2511 held += report(repo.vfs, "wlock", repo.wlock)
2511 held += report(repo.vfs, "wlock", repo.wlock)
2512
2512
2513 return held
2513 return held
2514
2514
2515 @command('debugobsolete',
2515 @command('debugobsolete',
2516 [('', 'flags', 0, _('markers flag')),
2516 [('', 'flags', 0, _('markers flag')),
2517 ('', 'record-parents', False,
2517 ('', 'record-parents', False,
2518 _('record parent information for the precursor')),
2518 _('record parent information for the precursor')),
2519 ('r', 'rev', [], _('display markers relevant to REV')),
2519 ('r', 'rev', [], _('display markers relevant to REV')),
2520 ] + commitopts2,
2520 ] + commitopts2,
2521 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2521 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2522 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2522 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2523 """create arbitrary obsolete marker
2523 """create arbitrary obsolete marker
2524
2524
2525 With no arguments, displays the list of obsolescence markers."""
2525 With no arguments, displays the list of obsolescence markers."""
2526
2526
2527 def parsenodeid(s):
2527 def parsenodeid(s):
2528 try:
2528 try:
2529 # We do not use revsingle/revrange functions here to accept
2529 # We do not use revsingle/revrange functions here to accept
2530 # arbitrary node identifiers, possibly not present in the
2530 # arbitrary node identifiers, possibly not present in the
2531 # local repository.
2531 # local repository.
2532 n = bin(s)
2532 n = bin(s)
2533 if len(n) != len(nullid):
2533 if len(n) != len(nullid):
2534 raise TypeError()
2534 raise TypeError()
2535 return n
2535 return n
2536 except TypeError:
2536 except TypeError:
2537 raise util.Abort('changeset references must be full hexadecimal '
2537 raise util.Abort('changeset references must be full hexadecimal '
2538 'node identifiers')
2538 'node identifiers')
2539
2539
2540 if precursor is not None:
2540 if precursor is not None:
2541 if opts['rev']:
2541 if opts['rev']:
2542 raise util.Abort('cannot select revision when creating marker')
2542 raise util.Abort('cannot select revision when creating marker')
2543 metadata = {}
2543 metadata = {}
2544 metadata['user'] = opts['user'] or ui.username()
2544 metadata['user'] = opts['user'] or ui.username()
2545 succs = tuple(parsenodeid(succ) for succ in successors)
2545 succs = tuple(parsenodeid(succ) for succ in successors)
2546 l = repo.lock()
2546 l = repo.lock()
2547 try:
2547 try:
2548 tr = repo.transaction('debugobsolete')
2548 tr = repo.transaction('debugobsolete')
2549 try:
2549 try:
2550 try:
2550 try:
2551 date = opts.get('date')
2551 date = opts.get('date')
2552 if date:
2552 if date:
2553 date = util.parsedate(date)
2553 date = util.parsedate(date)
2554 else:
2554 else:
2555 date = None
2555 date = None
2556 prec = parsenodeid(precursor)
2556 prec = parsenodeid(precursor)
2557 parents = None
2557 parents = None
2558 if opts['record_parents']:
2558 if opts['record_parents']:
2559 if prec not in repo.unfiltered():
2559 if prec not in repo.unfiltered():
2560 raise util.Abort('cannot used --record-parents on '
2560 raise util.Abort('cannot used --record-parents on '
2561 'unknown changesets')
2561 'unknown changesets')
2562 parents = repo.unfiltered()[prec].parents()
2562 parents = repo.unfiltered()[prec].parents()
2563 parents = tuple(p.node() for p in parents)
2563 parents = tuple(p.node() for p in parents)
2564 repo.obsstore.create(tr, prec, succs, opts['flags'],
2564 repo.obsstore.create(tr, prec, succs, opts['flags'],
2565 parents=parents, date=date,
2565 parents=parents, date=date,
2566 metadata=metadata)
2566 metadata=metadata)
2567 tr.close()
2567 tr.close()
2568 except ValueError, exc:
2568 except ValueError, exc:
2569 raise util.Abort(_('bad obsmarker input: %s') % exc)
2569 raise util.Abort(_('bad obsmarker input: %s') % exc)
2570 finally:
2570 finally:
2571 tr.release()
2571 tr.release()
2572 finally:
2572 finally:
2573 l.release()
2573 l.release()
2574 else:
2574 else:
2575 if opts['rev']:
2575 if opts['rev']:
2576 revs = scmutil.revrange(repo, opts['rev'])
2576 revs = scmutil.revrange(repo, opts['rev'])
2577 nodes = [repo[r].node() for r in revs]
2577 nodes = [repo[r].node() for r in revs]
2578 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2578 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2579 markers.sort(key=lambda x: x._data)
2579 markers.sort(key=lambda x: x._data)
2580 else:
2580 else:
2581 markers = obsolete.getmarkers(repo)
2581 markers = obsolete.getmarkers(repo)
2582
2582
2583 for m in markers:
2583 for m in markers:
2584 cmdutil.showmarker(ui, m)
2584 cmdutil.showmarker(ui, m)
2585
2585
2586 @command('debugpathcomplete',
2586 @command('debugpathcomplete',
2587 [('f', 'full', None, _('complete an entire path')),
2587 [('f', 'full', None, _('complete an entire path')),
2588 ('n', 'normal', None, _('show only normal files')),
2588 ('n', 'normal', None, _('show only normal files')),
2589 ('a', 'added', None, _('show only added files')),
2589 ('a', 'added', None, _('show only added files')),
2590 ('r', 'removed', None, _('show only removed files'))],
2590 ('r', 'removed', None, _('show only removed files'))],
2591 _('FILESPEC...'))
2591 _('FILESPEC...'))
2592 def debugpathcomplete(ui, repo, *specs, **opts):
2592 def debugpathcomplete(ui, repo, *specs, **opts):
2593 '''complete part or all of a tracked path
2593 '''complete part or all of a tracked path
2594
2594
2595 This command supports shells that offer path name completion. It
2595 This command supports shells that offer path name completion. It
2596 currently completes only files already known to the dirstate.
2596 currently completes only files already known to the dirstate.
2597
2597
2598 Completion extends only to the next path segment unless
2598 Completion extends only to the next path segment unless
2599 --full is specified, in which case entire paths are used.'''
2599 --full is specified, in which case entire paths are used.'''
2600
2600
2601 def complete(path, acceptable):
2601 def complete(path, acceptable):
2602 dirstate = repo.dirstate
2602 dirstate = repo.dirstate
2603 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2603 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2604 rootdir = repo.root + os.sep
2604 rootdir = repo.root + os.sep
2605 if spec != repo.root and not spec.startswith(rootdir):
2605 if spec != repo.root and not spec.startswith(rootdir):
2606 return [], []
2606 return [], []
2607 if os.path.isdir(spec):
2607 if os.path.isdir(spec):
2608 spec += '/'
2608 spec += '/'
2609 spec = spec[len(rootdir):]
2609 spec = spec[len(rootdir):]
2610 fixpaths = os.sep != '/'
2610 fixpaths = os.sep != '/'
2611 if fixpaths:
2611 if fixpaths:
2612 spec = spec.replace(os.sep, '/')
2612 spec = spec.replace(os.sep, '/')
2613 speclen = len(spec)
2613 speclen = len(spec)
2614 fullpaths = opts['full']
2614 fullpaths = opts['full']
2615 files, dirs = set(), set()
2615 files, dirs = set(), set()
2616 adddir, addfile = dirs.add, files.add
2616 adddir, addfile = dirs.add, files.add
2617 for f, st in dirstate.iteritems():
2617 for f, st in dirstate.iteritems():
2618 if f.startswith(spec) and st[0] in acceptable:
2618 if f.startswith(spec) and st[0] in acceptable:
2619 if fixpaths:
2619 if fixpaths:
2620 f = f.replace('/', os.sep)
2620 f = f.replace('/', os.sep)
2621 if fullpaths:
2621 if fullpaths:
2622 addfile(f)
2622 addfile(f)
2623 continue
2623 continue
2624 s = f.find(os.sep, speclen)
2624 s = f.find(os.sep, speclen)
2625 if s >= 0:
2625 if s >= 0:
2626 adddir(f[:s])
2626 adddir(f[:s])
2627 else:
2627 else:
2628 addfile(f)
2628 addfile(f)
2629 return files, dirs
2629 return files, dirs
2630
2630
2631 acceptable = ''
2631 acceptable = ''
2632 if opts['normal']:
2632 if opts['normal']:
2633 acceptable += 'nm'
2633 acceptable += 'nm'
2634 if opts['added']:
2634 if opts['added']:
2635 acceptable += 'a'
2635 acceptable += 'a'
2636 if opts['removed']:
2636 if opts['removed']:
2637 acceptable += 'r'
2637 acceptable += 'r'
2638 cwd = repo.getcwd()
2638 cwd = repo.getcwd()
2639 if not specs:
2639 if not specs:
2640 specs = ['.']
2640 specs = ['.']
2641
2641
2642 files, dirs = set(), set()
2642 files, dirs = set(), set()
2643 for spec in specs:
2643 for spec in specs:
2644 f, d = complete(spec, acceptable or 'nmar')
2644 f, d = complete(spec, acceptable or 'nmar')
2645 files.update(f)
2645 files.update(f)
2646 dirs.update(d)
2646 dirs.update(d)
2647 files.update(dirs)
2647 files.update(dirs)
2648 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2648 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2649 ui.write('\n')
2649 ui.write('\n')
2650
2650
2651 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2651 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2652 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2652 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2653 '''access the pushkey key/value protocol
2653 '''access the pushkey key/value protocol
2654
2654
2655 With two args, list the keys in the given namespace.
2655 With two args, list the keys in the given namespace.
2656
2656
2657 With five args, set a key to new if it currently is set to old.
2657 With five args, set a key to new if it currently is set to old.
2658 Reports success or failure.
2658 Reports success or failure.
2659 '''
2659 '''
2660
2660
2661 target = hg.peer(ui, {}, repopath)
2661 target = hg.peer(ui, {}, repopath)
2662 if keyinfo:
2662 if keyinfo:
2663 key, old, new = keyinfo
2663 key, old, new = keyinfo
2664 r = target.pushkey(namespace, key, old, new)
2664 r = target.pushkey(namespace, key, old, new)
2665 ui.status(str(r) + '\n')
2665 ui.status(str(r) + '\n')
2666 return not r
2666 return not r
2667 else:
2667 else:
2668 for k, v in sorted(target.listkeys(namespace).iteritems()):
2668 for k, v in sorted(target.listkeys(namespace).iteritems()):
2669 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2669 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2670 v.encode('string-escape')))
2670 v.encode('string-escape')))
2671
2671
2672 @command('debugpvec', [], _('A B'))
2672 @command('debugpvec', [], _('A B'))
2673 def debugpvec(ui, repo, a, b=None):
2673 def debugpvec(ui, repo, a, b=None):
2674 ca = scmutil.revsingle(repo, a)
2674 ca = scmutil.revsingle(repo, a)
2675 cb = scmutil.revsingle(repo, b)
2675 cb = scmutil.revsingle(repo, b)
2676 pa = pvec.ctxpvec(ca)
2676 pa = pvec.ctxpvec(ca)
2677 pb = pvec.ctxpvec(cb)
2677 pb = pvec.ctxpvec(cb)
2678 if pa == pb:
2678 if pa == pb:
2679 rel = "="
2679 rel = "="
2680 elif pa > pb:
2680 elif pa > pb:
2681 rel = ">"
2681 rel = ">"
2682 elif pa < pb:
2682 elif pa < pb:
2683 rel = "<"
2683 rel = "<"
2684 elif pa | pb:
2684 elif pa | pb:
2685 rel = "|"
2685 rel = "|"
2686 ui.write(_("a: %s\n") % pa)
2686 ui.write(_("a: %s\n") % pa)
2687 ui.write(_("b: %s\n") % pb)
2687 ui.write(_("b: %s\n") % pb)
2688 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2688 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2689 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2689 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2690 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2690 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2691 pa.distance(pb), rel))
2691 pa.distance(pb), rel))
2692
2692
2693 @command('debugrebuilddirstate|debugrebuildstate',
2693 @command('debugrebuilddirstate|debugrebuildstate',
2694 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2694 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2695 _('[-r REV]'))
2695 _('[-r REV]'))
2696 def debugrebuilddirstate(ui, repo, rev):
2696 def debugrebuilddirstate(ui, repo, rev):
2697 """rebuild the dirstate as it would look like for the given revision
2697 """rebuild the dirstate as it would look like for the given revision
2698
2698
2699 If no revision is specified the first current parent will be used.
2699 If no revision is specified the first current parent will be used.
2700
2700
2701 The dirstate will be set to the files of the given revision.
2701 The dirstate will be set to the files of the given revision.
2702 The actual working directory content or existing dirstate
2702 The actual working directory content or existing dirstate
2703 information such as adds or removes is not considered.
2703 information such as adds or removes is not considered.
2704
2704
2705 One use of this command is to make the next :hg:`status` invocation
2705 One use of this command is to make the next :hg:`status` invocation
2706 check the actual file content.
2706 check the actual file content.
2707 """
2707 """
2708 ctx = scmutil.revsingle(repo, rev)
2708 ctx = scmutil.revsingle(repo, rev)
2709 wlock = repo.wlock()
2709 wlock = repo.wlock()
2710 try:
2710 try:
2711 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2711 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2712 finally:
2712 finally:
2713 wlock.release()
2713 wlock.release()
2714
2714
2715 @command('debugrename',
2715 @command('debugrename',
2716 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2716 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2717 _('[-r REV] FILE'))
2717 _('[-r REV] FILE'))
2718 def debugrename(ui, repo, file1, *pats, **opts):
2718 def debugrename(ui, repo, file1, *pats, **opts):
2719 """dump rename information"""
2719 """dump rename information"""
2720
2720
2721 ctx = scmutil.revsingle(repo, opts.get('rev'))
2721 ctx = scmutil.revsingle(repo, opts.get('rev'))
2722 m = scmutil.match(ctx, (file1,) + pats, opts)
2722 m = scmutil.match(ctx, (file1,) + pats, opts)
2723 for abs in ctx.walk(m):
2723 for abs in ctx.walk(m):
2724 fctx = ctx[abs]
2724 fctx = ctx[abs]
2725 o = fctx.filelog().renamed(fctx.filenode())
2725 o = fctx.filelog().renamed(fctx.filenode())
2726 rel = m.rel(abs)
2726 rel = m.rel(abs)
2727 if o:
2727 if o:
2728 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2728 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2729 else:
2729 else:
2730 ui.write(_("%s not renamed\n") % rel)
2730 ui.write(_("%s not renamed\n") % rel)
2731
2731
2732 @command('debugrevlog',
2732 @command('debugrevlog',
2733 [('c', 'changelog', False, _('open changelog')),
2733 [('c', 'changelog', False, _('open changelog')),
2734 ('m', 'manifest', False, _('open manifest')),
2734 ('m', 'manifest', False, _('open manifest')),
2735 ('d', 'dump', False, _('dump index data'))],
2735 ('d', 'dump', False, _('dump index data'))],
2736 _('-c|-m|FILE'),
2736 _('-c|-m|FILE'),
2737 optionalrepo=True)
2737 optionalrepo=True)
2738 def debugrevlog(ui, repo, file_=None, **opts):
2738 def debugrevlog(ui, repo, file_=None, **opts):
2739 """show data and statistics about a revlog"""
2739 """show data and statistics about a revlog"""
2740 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2740 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2741
2741
2742 if opts.get("dump"):
2742 if opts.get("dump"):
2743 numrevs = len(r)
2743 numrevs = len(r)
2744 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2744 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2745 " rawsize totalsize compression heads chainlen\n")
2745 " rawsize totalsize compression heads chainlen\n")
2746 ts = 0
2746 ts = 0
2747 heads = set()
2747 heads = set()
2748
2748
2749 for rev in xrange(numrevs):
2749 for rev in xrange(numrevs):
2750 dbase = r.deltaparent(rev)
2750 dbase = r.deltaparent(rev)
2751 if dbase == -1:
2751 if dbase == -1:
2752 dbase = rev
2752 dbase = rev
2753 cbase = r.chainbase(rev)
2753 cbase = r.chainbase(rev)
2754 clen = r.chainlen(rev)
2754 clen = r.chainlen(rev)
2755 p1, p2 = r.parentrevs(rev)
2755 p1, p2 = r.parentrevs(rev)
2756 rs = r.rawsize(rev)
2756 rs = r.rawsize(rev)
2757 ts = ts + rs
2757 ts = ts + rs
2758 heads -= set(r.parentrevs(rev))
2758 heads -= set(r.parentrevs(rev))
2759 heads.add(rev)
2759 heads.add(rev)
2760 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2760 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2761 "%11d %5d %8d\n" %
2761 "%11d %5d %8d\n" %
2762 (rev, p1, p2, r.start(rev), r.end(rev),
2762 (rev, p1, p2, r.start(rev), r.end(rev),
2763 r.start(dbase), r.start(cbase),
2763 r.start(dbase), r.start(cbase),
2764 r.start(p1), r.start(p2),
2764 r.start(p1), r.start(p2),
2765 rs, ts, ts / r.end(rev), len(heads), clen))
2765 rs, ts, ts / r.end(rev), len(heads), clen))
2766 return 0
2766 return 0
2767
2767
2768 v = r.version
2768 v = r.version
2769 format = v & 0xFFFF
2769 format = v & 0xFFFF
2770 flags = []
2770 flags = []
2771 gdelta = False
2771 gdelta = False
2772 if v & revlog.REVLOGNGINLINEDATA:
2772 if v & revlog.REVLOGNGINLINEDATA:
2773 flags.append('inline')
2773 flags.append('inline')
2774 if v & revlog.REVLOGGENERALDELTA:
2774 if v & revlog.REVLOGGENERALDELTA:
2775 gdelta = True
2775 gdelta = True
2776 flags.append('generaldelta')
2776 flags.append('generaldelta')
2777 if not flags:
2777 if not flags:
2778 flags = ['(none)']
2778 flags = ['(none)']
2779
2779
2780 nummerges = 0
2780 nummerges = 0
2781 numfull = 0
2781 numfull = 0
2782 numprev = 0
2782 numprev = 0
2783 nump1 = 0
2783 nump1 = 0
2784 nump2 = 0
2784 nump2 = 0
2785 numother = 0
2785 numother = 0
2786 nump1prev = 0
2786 nump1prev = 0
2787 nump2prev = 0
2787 nump2prev = 0
2788 chainlengths = []
2788 chainlengths = []
2789
2789
2790 datasize = [None, 0, 0L]
2790 datasize = [None, 0, 0L]
2791 fullsize = [None, 0, 0L]
2791 fullsize = [None, 0, 0L]
2792 deltasize = [None, 0, 0L]
2792 deltasize = [None, 0, 0L]
2793
2793
2794 def addsize(size, l):
2794 def addsize(size, l):
2795 if l[0] is None or size < l[0]:
2795 if l[0] is None or size < l[0]:
2796 l[0] = size
2796 l[0] = size
2797 if size > l[1]:
2797 if size > l[1]:
2798 l[1] = size
2798 l[1] = size
2799 l[2] += size
2799 l[2] += size
2800
2800
2801 numrevs = len(r)
2801 numrevs = len(r)
2802 for rev in xrange(numrevs):
2802 for rev in xrange(numrevs):
2803 p1, p2 = r.parentrevs(rev)
2803 p1, p2 = r.parentrevs(rev)
2804 delta = r.deltaparent(rev)
2804 delta = r.deltaparent(rev)
2805 if format > 0:
2805 if format > 0:
2806 addsize(r.rawsize(rev), datasize)
2806 addsize(r.rawsize(rev), datasize)
2807 if p2 != nullrev:
2807 if p2 != nullrev:
2808 nummerges += 1
2808 nummerges += 1
2809 size = r.length(rev)
2809 size = r.length(rev)
2810 if delta == nullrev:
2810 if delta == nullrev:
2811 chainlengths.append(0)
2811 chainlengths.append(0)
2812 numfull += 1
2812 numfull += 1
2813 addsize(size, fullsize)
2813 addsize(size, fullsize)
2814 else:
2814 else:
2815 chainlengths.append(chainlengths[delta] + 1)
2815 chainlengths.append(chainlengths[delta] + 1)
2816 addsize(size, deltasize)
2816 addsize(size, deltasize)
2817 if delta == rev - 1:
2817 if delta == rev - 1:
2818 numprev += 1
2818 numprev += 1
2819 if delta == p1:
2819 if delta == p1:
2820 nump1prev += 1
2820 nump1prev += 1
2821 elif delta == p2:
2821 elif delta == p2:
2822 nump2prev += 1
2822 nump2prev += 1
2823 elif delta == p1:
2823 elif delta == p1:
2824 nump1 += 1
2824 nump1 += 1
2825 elif delta == p2:
2825 elif delta == p2:
2826 nump2 += 1
2826 nump2 += 1
2827 elif delta != nullrev:
2827 elif delta != nullrev:
2828 numother += 1
2828 numother += 1
2829
2829
2830 # Adjust size min value for empty cases
2830 # Adjust size min value for empty cases
2831 for size in (datasize, fullsize, deltasize):
2831 for size in (datasize, fullsize, deltasize):
2832 if size[0] is None:
2832 if size[0] is None:
2833 size[0] = 0
2833 size[0] = 0
2834
2834
2835 numdeltas = numrevs - numfull
2835 numdeltas = numrevs - numfull
2836 numoprev = numprev - nump1prev - nump2prev
2836 numoprev = numprev - nump1prev - nump2prev
2837 totalrawsize = datasize[2]
2837 totalrawsize = datasize[2]
2838 datasize[2] /= numrevs
2838 datasize[2] /= numrevs
2839 fulltotal = fullsize[2]
2839 fulltotal = fullsize[2]
2840 fullsize[2] /= numfull
2840 fullsize[2] /= numfull
2841 deltatotal = deltasize[2]
2841 deltatotal = deltasize[2]
2842 if numrevs - numfull > 0:
2842 if numrevs - numfull > 0:
2843 deltasize[2] /= numrevs - numfull
2843 deltasize[2] /= numrevs - numfull
2844 totalsize = fulltotal + deltatotal
2844 totalsize = fulltotal + deltatotal
2845 avgchainlen = sum(chainlengths) / numrevs
2845 avgchainlen = sum(chainlengths) / numrevs
2846 maxchainlen = max(chainlengths)
2846 maxchainlen = max(chainlengths)
2847 compratio = totalrawsize / totalsize
2847 compratio = totalrawsize / totalsize
2848
2848
2849 basedfmtstr = '%%%dd\n'
2849 basedfmtstr = '%%%dd\n'
2850 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2850 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2851
2851
2852 def dfmtstr(max):
2852 def dfmtstr(max):
2853 return basedfmtstr % len(str(max))
2853 return basedfmtstr % len(str(max))
2854 def pcfmtstr(max, padding=0):
2854 def pcfmtstr(max, padding=0):
2855 return basepcfmtstr % (len(str(max)), ' ' * padding)
2855 return basepcfmtstr % (len(str(max)), ' ' * padding)
2856
2856
2857 def pcfmt(value, total):
2857 def pcfmt(value, total):
2858 return (value, 100 * float(value) / total)
2858 return (value, 100 * float(value) / total)
2859
2859
2860 ui.write(('format : %d\n') % format)
2860 ui.write(('format : %d\n') % format)
2861 ui.write(('flags : %s\n') % ', '.join(flags))
2861 ui.write(('flags : %s\n') % ', '.join(flags))
2862
2862
2863 ui.write('\n')
2863 ui.write('\n')
2864 fmt = pcfmtstr(totalsize)
2864 fmt = pcfmtstr(totalsize)
2865 fmt2 = dfmtstr(totalsize)
2865 fmt2 = dfmtstr(totalsize)
2866 ui.write(('revisions : ') + fmt2 % numrevs)
2866 ui.write(('revisions : ') + fmt2 % numrevs)
2867 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2867 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2868 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2868 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2869 ui.write(('revisions : ') + fmt2 % numrevs)
2869 ui.write(('revisions : ') + fmt2 % numrevs)
2870 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2870 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2871 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2871 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2872 ui.write(('revision size : ') + fmt2 % totalsize)
2872 ui.write(('revision size : ') + fmt2 % totalsize)
2873 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2873 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2874 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2874 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2875
2875
2876 ui.write('\n')
2876 ui.write('\n')
2877 fmt = dfmtstr(max(avgchainlen, compratio))
2877 fmt = dfmtstr(max(avgchainlen, compratio))
2878 ui.write(('avg chain length : ') + fmt % avgchainlen)
2878 ui.write(('avg chain length : ') + fmt % avgchainlen)
2879 ui.write(('max chain length : ') + fmt % maxchainlen)
2879 ui.write(('max chain length : ') + fmt % maxchainlen)
2880 ui.write(('compression ratio : ') + fmt % compratio)
2880 ui.write(('compression ratio : ') + fmt % compratio)
2881
2881
2882 if format > 0:
2882 if format > 0:
2883 ui.write('\n')
2883 ui.write('\n')
2884 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2884 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2885 % tuple(datasize))
2885 % tuple(datasize))
2886 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2886 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2887 % tuple(fullsize))
2887 % tuple(fullsize))
2888 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2888 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2889 % tuple(deltasize))
2889 % tuple(deltasize))
2890
2890
2891 if numdeltas > 0:
2891 if numdeltas > 0:
2892 ui.write('\n')
2892 ui.write('\n')
2893 fmt = pcfmtstr(numdeltas)
2893 fmt = pcfmtstr(numdeltas)
2894 fmt2 = pcfmtstr(numdeltas, 4)
2894 fmt2 = pcfmtstr(numdeltas, 4)
2895 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2895 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2896 if numprev > 0:
2896 if numprev > 0:
2897 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2897 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2898 numprev))
2898 numprev))
2899 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2899 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2900 numprev))
2900 numprev))
2901 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2901 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2902 numprev))
2902 numprev))
2903 if gdelta:
2903 if gdelta:
2904 ui.write(('deltas against p1 : ')
2904 ui.write(('deltas against p1 : ')
2905 + fmt % pcfmt(nump1, numdeltas))
2905 + fmt % pcfmt(nump1, numdeltas))
2906 ui.write(('deltas against p2 : ')
2906 ui.write(('deltas against p2 : ')
2907 + fmt % pcfmt(nump2, numdeltas))
2907 + fmt % pcfmt(nump2, numdeltas))
2908 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2908 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2909 numdeltas))
2909 numdeltas))
2910
2910
2911 @command('debugrevspec',
2911 @command('debugrevspec',
2912 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2912 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2913 ('REVSPEC'))
2913 ('REVSPEC'))
2914 def debugrevspec(ui, repo, expr, **opts):
2914 def debugrevspec(ui, repo, expr, **opts):
2915 """parse and apply a revision specification
2915 """parse and apply a revision specification
2916
2916
2917 Use --verbose to print the parsed tree before and after aliases
2917 Use --verbose to print the parsed tree before and after aliases
2918 expansion.
2918 expansion.
2919 """
2919 """
2920 if ui.verbose:
2920 if ui.verbose:
2921 tree = revset.parse(expr)[0]
2921 tree = revset.parse(expr)[0]
2922 ui.note(revset.prettyformat(tree), "\n")
2922 ui.note(revset.prettyformat(tree), "\n")
2923 newtree = revset.findaliases(ui, tree)
2923 newtree = revset.findaliases(ui, tree)
2924 if newtree != tree:
2924 if newtree != tree:
2925 ui.note(revset.prettyformat(newtree), "\n")
2925 ui.note(revset.prettyformat(newtree), "\n")
2926 tree = newtree
2926 tree = newtree
2927 newtree = revset.foldconcat(tree)
2927 newtree = revset.foldconcat(tree)
2928 if newtree != tree:
2928 if newtree != tree:
2929 ui.note(revset.prettyformat(newtree), "\n")
2929 ui.note(revset.prettyformat(newtree), "\n")
2930 if opts["optimize"]:
2930 if opts["optimize"]:
2931 weight, optimizedtree = revset.optimize(newtree, True)
2931 weight, optimizedtree = revset.optimize(newtree, True)
2932 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2932 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2933 func = revset.match(ui, expr)
2933 func = revset.match(ui, expr)
2934 revs = func(repo)
2934 revs = func(repo)
2935 if ui.verbose:
2935 if ui.verbose:
2936 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2936 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2937 for c in revs:
2937 for c in revs:
2938 ui.write("%s\n" % c)
2938 ui.write("%s\n" % c)
2939
2939
2940 @command('debugsetparents', [], _('REV1 [REV2]'))
2940 @command('debugsetparents', [], _('REV1 [REV2]'))
2941 def debugsetparents(ui, repo, rev1, rev2=None):
2941 def debugsetparents(ui, repo, rev1, rev2=None):
2942 """manually set the parents of the current working directory
2942 """manually set the parents of the current working directory
2943
2943
2944 This is useful for writing repository conversion tools, but should
2944 This is useful for writing repository conversion tools, but should
2945 be used with care. For example, neither the working directory nor the
2945 be used with care. For example, neither the working directory nor the
2946 dirstate is updated, so file status may be incorrect after running this
2946 dirstate is updated, so file status may be incorrect after running this
2947 command.
2947 command.
2948
2948
2949 Returns 0 on success.
2949 Returns 0 on success.
2950 """
2950 """
2951
2951
2952 r1 = scmutil.revsingle(repo, rev1).node()
2952 r1 = scmutil.revsingle(repo, rev1).node()
2953 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2953 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2954
2954
2955 wlock = repo.wlock()
2955 wlock = repo.wlock()
2956 try:
2956 try:
2957 repo.dirstate.beginparentchange()
2957 repo.dirstate.beginparentchange()
2958 repo.setparents(r1, r2)
2958 repo.setparents(r1, r2)
2959 repo.dirstate.endparentchange()
2959 repo.dirstate.endparentchange()
2960 finally:
2960 finally:
2961 wlock.release()
2961 wlock.release()
2962
2962
2963 @command('debugdirstate|debugstate',
2963 @command('debugdirstate|debugstate',
2964 [('', 'nodates', None, _('do not display the saved mtime')),
2964 [('', 'nodates', None, _('do not display the saved mtime')),
2965 ('', 'datesort', None, _('sort by saved mtime'))],
2965 ('', 'datesort', None, _('sort by saved mtime'))],
2966 _('[OPTION]...'))
2966 _('[OPTION]...'))
2967 def debugstate(ui, repo, nodates=None, datesort=None):
2967 def debugstate(ui, repo, nodates=None, datesort=None):
2968 """show the contents of the current dirstate"""
2968 """show the contents of the current dirstate"""
2969 timestr = ""
2969 timestr = ""
2970 if datesort:
2970 if datesort:
2971 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2971 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2972 else:
2972 else:
2973 keyfunc = None # sort by filename
2973 keyfunc = None # sort by filename
2974 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2974 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2975 if ent[3] == -1:
2975 if ent[3] == -1:
2976 timestr = 'unset '
2976 timestr = 'unset '
2977 elif nodates:
2977 elif nodates:
2978 timestr = 'set '
2978 timestr = 'set '
2979 else:
2979 else:
2980 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2980 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2981 time.localtime(ent[3]))
2981 time.localtime(ent[3]))
2982 if ent[1] & 020000:
2982 if ent[1] & 020000:
2983 mode = 'lnk'
2983 mode = 'lnk'
2984 else:
2984 else:
2985 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2985 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2986 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2986 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2987 for f in repo.dirstate.copies():
2987 for f in repo.dirstate.copies():
2988 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2988 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2989
2989
2990 @command('debugsub',
2990 @command('debugsub',
2991 [('r', 'rev', '',
2991 [('r', 'rev', '',
2992 _('revision to check'), _('REV'))],
2992 _('revision to check'), _('REV'))],
2993 _('[-r REV] [REV]'))
2993 _('[-r REV] [REV]'))
2994 def debugsub(ui, repo, rev=None):
2994 def debugsub(ui, repo, rev=None):
2995 ctx = scmutil.revsingle(repo, rev, None)
2995 ctx = scmutil.revsingle(repo, rev, None)
2996 for k, v in sorted(ctx.substate.items()):
2996 for k, v in sorted(ctx.substate.items()):
2997 ui.write(('path %s\n') % k)
2997 ui.write(('path %s\n') % k)
2998 ui.write((' source %s\n') % v[0])
2998 ui.write((' source %s\n') % v[0])
2999 ui.write((' revision %s\n') % v[1])
2999 ui.write((' revision %s\n') % v[1])
3000
3000
3001 @command('debugsuccessorssets',
3001 @command('debugsuccessorssets',
3002 [],
3002 [],
3003 _('[REV]'))
3003 _('[REV]'))
3004 def debugsuccessorssets(ui, repo, *revs):
3004 def debugsuccessorssets(ui, repo, *revs):
3005 """show set of successors for revision
3005 """show set of successors for revision
3006
3006
3007 A successors set of changeset A is a consistent group of revisions that
3007 A successors set of changeset A is a consistent group of revisions that
3008 succeed A. It contains non-obsolete changesets only.
3008 succeed A. It contains non-obsolete changesets only.
3009
3009
3010 In most cases a changeset A has a single successors set containing a single
3010 In most cases a changeset A has a single successors set containing a single
3011 successor (changeset A replaced by A').
3011 successor (changeset A replaced by A').
3012
3012
3013 A changeset that is made obsolete with no successors are called "pruned".
3013 A changeset that is made obsolete with no successors are called "pruned".
3014 Such changesets have no successors sets at all.
3014 Such changesets have no successors sets at all.
3015
3015
3016 A changeset that has been "split" will have a successors set containing
3016 A changeset that has been "split" will have a successors set containing
3017 more than one successor.
3017 more than one successor.
3018
3018
3019 A changeset that has been rewritten in multiple different ways is called
3019 A changeset that has been rewritten in multiple different ways is called
3020 "divergent". Such changesets have multiple successor sets (each of which
3020 "divergent". Such changesets have multiple successor sets (each of which
3021 may also be split, i.e. have multiple successors).
3021 may also be split, i.e. have multiple successors).
3022
3022
3023 Results are displayed as follows::
3023 Results are displayed as follows::
3024
3024
3025 <rev1>
3025 <rev1>
3026 <successors-1A>
3026 <successors-1A>
3027 <rev2>
3027 <rev2>
3028 <successors-2A>
3028 <successors-2A>
3029 <successors-2B1> <successors-2B2> <successors-2B3>
3029 <successors-2B1> <successors-2B2> <successors-2B3>
3030
3030
3031 Here rev2 has two possible (i.e. divergent) successors sets. The first
3031 Here rev2 has two possible (i.e. divergent) successors sets. The first
3032 holds one element, whereas the second holds three (i.e. the changeset has
3032 holds one element, whereas the second holds three (i.e. the changeset has
3033 been split).
3033 been split).
3034 """
3034 """
3035 # passed to successorssets caching computation from one call to another
3035 # passed to successorssets caching computation from one call to another
3036 cache = {}
3036 cache = {}
3037 ctx2str = str
3037 ctx2str = str
3038 node2str = short
3038 node2str = short
3039 if ui.debug():
3039 if ui.debug():
3040 def ctx2str(ctx):
3040 def ctx2str(ctx):
3041 return ctx.hex()
3041 return ctx.hex()
3042 node2str = hex
3042 node2str = hex
3043 for rev in scmutil.revrange(repo, revs):
3043 for rev in scmutil.revrange(repo, revs):
3044 ctx = repo[rev]
3044 ctx = repo[rev]
3045 ui.write('%s\n'% ctx2str(ctx))
3045 ui.write('%s\n'% ctx2str(ctx))
3046 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3046 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3047 if succsset:
3047 if succsset:
3048 ui.write(' ')
3048 ui.write(' ')
3049 ui.write(node2str(succsset[0]))
3049 ui.write(node2str(succsset[0]))
3050 for node in succsset[1:]:
3050 for node in succsset[1:]:
3051 ui.write(' ')
3051 ui.write(' ')
3052 ui.write(node2str(node))
3052 ui.write(node2str(node))
3053 ui.write('\n')
3053 ui.write('\n')
3054
3054
3055 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3055 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3056 def debugwalk(ui, repo, *pats, **opts):
3056 def debugwalk(ui, repo, *pats, **opts):
3057 """show how files match on given patterns"""
3057 """show how files match on given patterns"""
3058 m = scmutil.match(repo[None], pats, opts)
3058 m = scmutil.match(repo[None], pats, opts)
3059 items = list(repo.walk(m))
3059 items = list(repo.walk(m))
3060 if not items:
3060 if not items:
3061 return
3061 return
3062 f = lambda fn: fn
3062 f = lambda fn: fn
3063 if ui.configbool('ui', 'slash') and os.sep != '/':
3063 if ui.configbool('ui', 'slash') and os.sep != '/':
3064 f = lambda fn: util.normpath(fn)
3064 f = lambda fn: util.normpath(fn)
3065 fmt = 'f %%-%ds %%-%ds %%s' % (
3065 fmt = 'f %%-%ds %%-%ds %%s' % (
3066 max([len(abs) for abs in items]),
3066 max([len(abs) for abs in items]),
3067 max([len(m.rel(abs)) for abs in items]))
3067 max([len(m.rel(abs)) for abs in items]))
3068 for abs in items:
3068 for abs in items:
3069 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3069 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3070 ui.write("%s\n" % line.rstrip())
3070 ui.write("%s\n" % line.rstrip())
3071
3071
3072 @command('debugwireargs',
3072 @command('debugwireargs',
3073 [('', 'three', '', 'three'),
3073 [('', 'three', '', 'three'),
3074 ('', 'four', '', 'four'),
3074 ('', 'four', '', 'four'),
3075 ('', 'five', '', 'five'),
3075 ('', 'five', '', 'five'),
3076 ] + remoteopts,
3076 ] + remoteopts,
3077 _('REPO [OPTIONS]... [ONE [TWO]]'),
3077 _('REPO [OPTIONS]... [ONE [TWO]]'),
3078 norepo=True)
3078 norepo=True)
3079 def debugwireargs(ui, repopath, *vals, **opts):
3079 def debugwireargs(ui, repopath, *vals, **opts):
3080 repo = hg.peer(ui, opts, repopath)
3080 repo = hg.peer(ui, opts, repopath)
3081 for opt in remoteopts:
3081 for opt in remoteopts:
3082 del opts[opt[1]]
3082 del opts[opt[1]]
3083 args = {}
3083 args = {}
3084 for k, v in opts.iteritems():
3084 for k, v in opts.iteritems():
3085 if v:
3085 if v:
3086 args[k] = v
3086 args[k] = v
3087 # run twice to check that we don't mess up the stream for the next command
3087 # run twice to check that we don't mess up the stream for the next command
3088 res1 = repo.debugwireargs(*vals, **args)
3088 res1 = repo.debugwireargs(*vals, **args)
3089 res2 = repo.debugwireargs(*vals, **args)
3089 res2 = repo.debugwireargs(*vals, **args)
3090 ui.write("%s\n" % res1)
3090 ui.write("%s\n" % res1)
3091 if res1 != res2:
3091 if res1 != res2:
3092 ui.warn("%s\n" % res2)
3092 ui.warn("%s\n" % res2)
3093
3093
3094 @command('^diff',
3094 @command('^diff',
3095 [('r', 'rev', [], _('revision'), _('REV')),
3095 [('r', 'rev', [], _('revision'), _('REV')),
3096 ('c', 'change', '', _('change made by revision'), _('REV'))
3096 ('c', 'change', '', _('change made by revision'), _('REV'))
3097 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3097 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3098 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3098 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3099 inferrepo=True)
3099 inferrepo=True)
3100 def diff(ui, repo, *pats, **opts):
3100 def diff(ui, repo, *pats, **opts):
3101 """diff repository (or selected files)
3101 """diff repository (or selected files)
3102
3102
3103 Show differences between revisions for the specified files.
3103 Show differences between revisions for the specified files.
3104
3104
3105 Differences between files are shown using the unified diff format.
3105 Differences between files are shown using the unified diff format.
3106
3106
3107 .. note::
3107 .. note::
3108
3108
3109 diff may generate unexpected results for merges, as it will
3109 diff may generate unexpected results for merges, as it will
3110 default to comparing against the working directory's first
3110 default to comparing against the working directory's first
3111 parent changeset if no revisions are specified.
3111 parent changeset if no revisions are specified.
3112
3112
3113 When two revision arguments are given, then changes are shown
3113 When two revision arguments are given, then changes are shown
3114 between those revisions. If only one revision is specified then
3114 between those revisions. If only one revision is specified then
3115 that revision is compared to the working directory, and, when no
3115 that revision is compared to the working directory, and, when no
3116 revisions are specified, the working directory files are compared
3116 revisions are specified, the working directory files are compared
3117 to its parent.
3117 to its parent.
3118
3118
3119 Alternatively you can specify -c/--change with a revision to see
3119 Alternatively you can specify -c/--change with a revision to see
3120 the changes in that changeset relative to its first parent.
3120 the changes in that changeset relative to its first parent.
3121
3121
3122 Without the -a/--text option, diff will avoid generating diffs of
3122 Without the -a/--text option, diff will avoid generating diffs of
3123 files it detects as binary. With -a, diff will generate a diff
3123 files it detects as binary. With -a, diff will generate a diff
3124 anyway, probably with undesirable results.
3124 anyway, probably with undesirable results.
3125
3125
3126 Use the -g/--git option to generate diffs in the git extended diff
3126 Use the -g/--git option to generate diffs in the git extended diff
3127 format. For more information, read :hg:`help diffs`.
3127 format. For more information, read :hg:`help diffs`.
3128
3128
3129 .. container:: verbose
3129 .. container:: verbose
3130
3130
3131 Examples:
3131 Examples:
3132
3132
3133 - compare a file in the current working directory to its parent::
3133 - compare a file in the current working directory to its parent::
3134
3134
3135 hg diff foo.c
3135 hg diff foo.c
3136
3136
3137 - compare two historical versions of a directory, with rename info::
3137 - compare two historical versions of a directory, with rename info::
3138
3138
3139 hg diff --git -r 1.0:1.2 lib/
3139 hg diff --git -r 1.0:1.2 lib/
3140
3140
3141 - get change stats relative to the last change on some date::
3141 - get change stats relative to the last change on some date::
3142
3142
3143 hg diff --stat -r "date('may 2')"
3143 hg diff --stat -r "date('may 2')"
3144
3144
3145 - diff all newly-added files that contain a keyword::
3145 - diff all newly-added files that contain a keyword::
3146
3146
3147 hg diff "set:added() and grep(GNU)"
3147 hg diff "set:added() and grep(GNU)"
3148
3148
3149 - compare a revision and its parents::
3149 - compare a revision and its parents::
3150
3150
3151 hg diff -c 9353 # compare against first parent
3151 hg diff -c 9353 # compare against first parent
3152 hg diff -r 9353^:9353 # same using revset syntax
3152 hg diff -r 9353^:9353 # same using revset syntax
3153 hg diff -r 9353^2:9353 # compare against the second parent
3153 hg diff -r 9353^2:9353 # compare against the second parent
3154
3154
3155 Returns 0 on success.
3155 Returns 0 on success.
3156 """
3156 """
3157
3157
3158 revs = opts.get('rev')
3158 revs = opts.get('rev')
3159 change = opts.get('change')
3159 change = opts.get('change')
3160 stat = opts.get('stat')
3160 stat = opts.get('stat')
3161 reverse = opts.get('reverse')
3161 reverse = opts.get('reverse')
3162
3162
3163 if revs and change:
3163 if revs and change:
3164 msg = _('cannot specify --rev and --change at the same time')
3164 msg = _('cannot specify --rev and --change at the same time')
3165 raise util.Abort(msg)
3165 raise util.Abort(msg)
3166 elif change:
3166 elif change:
3167 node2 = scmutil.revsingle(repo, change, None).node()
3167 node2 = scmutil.revsingle(repo, change, None).node()
3168 node1 = repo[node2].p1().node()
3168 node1 = repo[node2].p1().node()
3169 else:
3169 else:
3170 node1, node2 = scmutil.revpair(repo, revs)
3170 node1, node2 = scmutil.revpair(repo, revs)
3171
3171
3172 if reverse:
3172 if reverse:
3173 node1, node2 = node2, node1
3173 node1, node2 = node2, node1
3174
3174
3175 diffopts = patch.diffallopts(ui, opts)
3175 diffopts = patch.diffallopts(ui, opts)
3176 m = scmutil.match(repo[node2], pats, opts)
3176 m = scmutil.match(repo[node2], pats, opts)
3177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3178 listsubrepos=opts.get('subrepos'),
3178 listsubrepos=opts.get('subrepos'),
3179 root=opts.get('root'))
3179 root=opts.get('root'))
3180
3180
3181 @command('^export',
3181 @command('^export',
3182 [('o', 'output', '',
3182 [('o', 'output', '',
3183 _('print output to file with formatted name'), _('FORMAT')),
3183 _('print output to file with formatted name'), _('FORMAT')),
3184 ('', 'switch-parent', None, _('diff against the second parent')),
3184 ('', 'switch-parent', None, _('diff against the second parent')),
3185 ('r', 'rev', [], _('revisions to export'), _('REV')),
3185 ('r', 'rev', [], _('revisions to export'), _('REV')),
3186 ] + diffopts,
3186 ] + diffopts,
3187 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3187 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3188 def export(ui, repo, *changesets, **opts):
3188 def export(ui, repo, *changesets, **opts):
3189 """dump the header and diffs for one or more changesets
3189 """dump the header and diffs for one or more changesets
3190
3190
3191 Print the changeset header and diffs for one or more revisions.
3191 Print the changeset header and diffs for one or more revisions.
3192 If no revision is given, the parent of the working directory is used.
3192 If no revision is given, the parent of the working directory is used.
3193
3193
3194 The information shown in the changeset header is: author, date,
3194 The information shown in the changeset header is: author, date,
3195 branch name (if non-default), changeset hash, parent(s) and commit
3195 branch name (if non-default), changeset hash, parent(s) and commit
3196 comment.
3196 comment.
3197
3197
3198 .. note::
3198 .. note::
3199
3199
3200 export may generate unexpected diff output for merge
3200 export may generate unexpected diff output for merge
3201 changesets, as it will compare the merge changeset against its
3201 changesets, as it will compare the merge changeset against its
3202 first parent only.
3202 first parent only.
3203
3203
3204 Output may be to a file, in which case the name of the file is
3204 Output may be to a file, in which case the name of the file is
3205 given using a format string. The formatting rules are as follows:
3205 given using a format string. The formatting rules are as follows:
3206
3206
3207 :``%%``: literal "%" character
3207 :``%%``: literal "%" character
3208 :``%H``: changeset hash (40 hexadecimal digits)
3208 :``%H``: changeset hash (40 hexadecimal digits)
3209 :``%N``: number of patches being generated
3209 :``%N``: number of patches being generated
3210 :``%R``: changeset revision number
3210 :``%R``: changeset revision number
3211 :``%b``: basename of the exporting repository
3211 :``%b``: basename of the exporting repository
3212 :``%h``: short-form changeset hash (12 hexadecimal digits)
3212 :``%h``: short-form changeset hash (12 hexadecimal digits)
3213 :``%m``: first line of the commit message (only alphanumeric characters)
3213 :``%m``: first line of the commit message (only alphanumeric characters)
3214 :``%n``: zero-padded sequence number, starting at 1
3214 :``%n``: zero-padded sequence number, starting at 1
3215 :``%r``: zero-padded changeset revision number
3215 :``%r``: zero-padded changeset revision number
3216
3216
3217 Without the -a/--text option, export will avoid generating diffs
3217 Without the -a/--text option, export will avoid generating diffs
3218 of files it detects as binary. With -a, export will generate a
3218 of files it detects as binary. With -a, export will generate a
3219 diff anyway, probably with undesirable results.
3219 diff anyway, probably with undesirable results.
3220
3220
3221 Use the -g/--git option to generate diffs in the git extended diff
3221 Use the -g/--git option to generate diffs in the git extended diff
3222 format. See :hg:`help diffs` for more information.
3222 format. See :hg:`help diffs` for more information.
3223
3223
3224 With the --switch-parent option, the diff will be against the
3224 With the --switch-parent option, the diff will be against the
3225 second parent. It can be useful to review a merge.
3225 second parent. It can be useful to review a merge.
3226
3226
3227 .. container:: verbose
3227 .. container:: verbose
3228
3228
3229 Examples:
3229 Examples:
3230
3230
3231 - use export and import to transplant a bugfix to the current
3231 - use export and import to transplant a bugfix to the current
3232 branch::
3232 branch::
3233
3233
3234 hg export -r 9353 | hg import -
3234 hg export -r 9353 | hg import -
3235
3235
3236 - export all the changesets between two revisions to a file with
3236 - export all the changesets between two revisions to a file with
3237 rename information::
3237 rename information::
3238
3238
3239 hg export --git -r 123:150 > changes.txt
3239 hg export --git -r 123:150 > changes.txt
3240
3240
3241 - split outgoing changes into a series of patches with
3241 - split outgoing changes into a series of patches with
3242 descriptive names::
3242 descriptive names::
3243
3243
3244 hg export -r "outgoing()" -o "%n-%m.patch"
3244 hg export -r "outgoing()" -o "%n-%m.patch"
3245
3245
3246 Returns 0 on success.
3246 Returns 0 on success.
3247 """
3247 """
3248 changesets += tuple(opts.get('rev', []))
3248 changesets += tuple(opts.get('rev', []))
3249 if not changesets:
3249 if not changesets:
3250 changesets = ['.']
3250 changesets = ['.']
3251 revs = scmutil.revrange(repo, changesets)
3251 revs = scmutil.revrange(repo, changesets)
3252 if not revs:
3252 if not revs:
3253 raise util.Abort(_("export requires at least one changeset"))
3253 raise util.Abort(_("export requires at least one changeset"))
3254 if len(revs) > 1:
3254 if len(revs) > 1:
3255 ui.note(_('exporting patches:\n'))
3255 ui.note(_('exporting patches:\n'))
3256 else:
3256 else:
3257 ui.note(_('exporting patch:\n'))
3257 ui.note(_('exporting patch:\n'))
3258 cmdutil.export(repo, revs, template=opts.get('output'),
3258 cmdutil.export(repo, revs, template=opts.get('output'),
3259 switch_parent=opts.get('switch_parent'),
3259 switch_parent=opts.get('switch_parent'),
3260 opts=patch.diffallopts(ui, opts))
3260 opts=patch.diffallopts(ui, opts))
3261
3261
3262 @command('files',
3262 @command('files',
3263 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3263 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3264 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3264 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3265 ] + walkopts + formatteropts + subrepoopts,
3265 ] + walkopts + formatteropts + subrepoopts,
3266 _('[OPTION]... [PATTERN]...'))
3266 _('[OPTION]... [PATTERN]...'))
3267 def files(ui, repo, *pats, **opts):
3267 def files(ui, repo, *pats, **opts):
3268 """list tracked files
3268 """list tracked files
3269
3269
3270 Print files under Mercurial control in the working directory or
3270 Print files under Mercurial control in the working directory or
3271 specified revision whose names match the given patterns (excluding
3271 specified revision whose names match the given patterns (excluding
3272 removed files).
3272 removed files).
3273
3273
3274 If no patterns are given to match, this command prints the names
3274 If no patterns are given to match, this command prints the names
3275 of all files under Mercurial control in the working directory.
3275 of all files under Mercurial control in the working directory.
3276
3276
3277 .. container:: verbose
3277 .. container:: verbose
3278
3278
3279 Examples:
3279 Examples:
3280
3280
3281 - list all files under the current directory::
3281 - list all files under the current directory::
3282
3282
3283 hg files .
3283 hg files .
3284
3284
3285 - shows sizes and flags for current revision::
3285 - shows sizes and flags for current revision::
3286
3286
3287 hg files -vr .
3287 hg files -vr .
3288
3288
3289 - list all files named README::
3289 - list all files named README::
3290
3290
3291 hg files -I "**/README"
3291 hg files -I "**/README"
3292
3292
3293 - list all binary files::
3293 - list all binary files::
3294
3294
3295 hg files "set:binary()"
3295 hg files "set:binary()"
3296
3296
3297 - find files containing a regular expression::
3297 - find files containing a regular expression::
3298
3298
3299 hg files "set:grep('bob')"
3299 hg files "set:grep('bob')"
3300
3300
3301 - search tracked file contents with xargs and grep::
3301 - search tracked file contents with xargs and grep::
3302
3302
3303 hg files -0 | xargs -0 grep foo
3303 hg files -0 | xargs -0 grep foo
3304
3304
3305 See :hg:`help patterns` and :hg:`help filesets` for more information
3305 See :hg:`help patterns` and :hg:`help filesets` for more information
3306 on specifying file patterns.
3306 on specifying file patterns.
3307
3307
3308 Returns 0 if a match is found, 1 otherwise.
3308 Returns 0 if a match is found, 1 otherwise.
3309
3309
3310 """
3310 """
3311 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3311 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3312
3312
3313 end = '\n'
3313 end = '\n'
3314 if opts.get('print0'):
3314 if opts.get('print0'):
3315 end = '\0'
3315 end = '\0'
3316 fm = ui.formatter('files', opts)
3316 fm = ui.formatter('files', opts)
3317 fmt = '%s' + end
3317 fmt = '%s' + end
3318
3318
3319 m = scmutil.match(ctx, pats, opts)
3319 m = scmutil.match(ctx, pats, opts)
3320 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3320 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3321
3321
3322 fm.end()
3322 fm.end()
3323
3323
3324 return ret
3324 return ret
3325
3325
3326 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3326 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3327 def forget(ui, repo, *pats, **opts):
3327 def forget(ui, repo, *pats, **opts):
3328 """forget the specified files on the next commit
3328 """forget the specified files on the next commit
3329
3329
3330 Mark the specified files so they will no longer be tracked
3330 Mark the specified files so they will no longer be tracked
3331 after the next commit.
3331 after the next commit.
3332
3332
3333 This only removes files from the current branch, not from the
3333 This only removes files from the current branch, not from the
3334 entire project history, and it does not delete them from the
3334 entire project history, and it does not delete them from the
3335 working directory.
3335 working directory.
3336
3336
3337 To undo a forget before the next commit, see :hg:`add`.
3337 To undo a forget before the next commit, see :hg:`add`.
3338
3338
3339 .. container:: verbose
3339 .. container:: verbose
3340
3340
3341 Examples:
3341 Examples:
3342
3342
3343 - forget newly-added binary files::
3343 - forget newly-added binary files::
3344
3344
3345 hg forget "set:added() and binary()"
3345 hg forget "set:added() and binary()"
3346
3346
3347 - forget files that would be excluded by .hgignore::
3347 - forget files that would be excluded by .hgignore::
3348
3348
3349 hg forget "set:hgignore()"
3349 hg forget "set:hgignore()"
3350
3350
3351 Returns 0 on success.
3351 Returns 0 on success.
3352 """
3352 """
3353
3353
3354 if not pats:
3354 if not pats:
3355 raise util.Abort(_('no files specified'))
3355 raise util.Abort(_('no files specified'))
3356
3356
3357 m = scmutil.match(repo[None], pats, opts)
3357 m = scmutil.match(repo[None], pats, opts)
3358 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3358 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3359 return rejected and 1 or 0
3359 return rejected and 1 or 0
3360
3360
3361 @command(
3361 @command(
3362 'graft',
3362 'graft',
3363 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3363 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3364 ('c', 'continue', False, _('resume interrupted graft')),
3364 ('c', 'continue', False, _('resume interrupted graft')),
3365 ('e', 'edit', False, _('invoke editor on commit messages')),
3365 ('e', 'edit', False, _('invoke editor on commit messages')),
3366 ('', 'log', None, _('append graft info to log message')),
3366 ('', 'log', None, _('append graft info to log message')),
3367 ('f', 'force', False, _('force graft')),
3367 ('f', 'force', False, _('force graft')),
3368 ('D', 'currentdate', False,
3368 ('D', 'currentdate', False,
3369 _('record the current date as commit date')),
3369 _('record the current date as commit date')),
3370 ('U', 'currentuser', False,
3370 ('U', 'currentuser', False,
3371 _('record the current user as committer'), _('DATE'))]
3371 _('record the current user as committer'), _('DATE'))]
3372 + commitopts2 + mergetoolopts + dryrunopts,
3372 + commitopts2 + mergetoolopts + dryrunopts,
3373 _('[OPTION]... [-r] REV...'))
3373 _('[OPTION]... [-r] REV...'))
3374 def graft(ui, repo, *revs, **opts):
3374 def graft(ui, repo, *revs, **opts):
3375 '''copy changes from other branches onto the current branch
3375 '''copy changes from other branches onto the current branch
3376
3376
3377 This command uses Mercurial's merge logic to copy individual
3377 This command uses Mercurial's merge logic to copy individual
3378 changes from other branches without merging branches in the
3378 changes from other branches without merging branches in the
3379 history graph. This is sometimes known as 'backporting' or
3379 history graph. This is sometimes known as 'backporting' or
3380 'cherry-picking'. By default, graft will copy user, date, and
3380 'cherry-picking'. By default, graft will copy user, date, and
3381 description from the source changesets.
3381 description from the source changesets.
3382
3382
3383 Changesets that are ancestors of the current revision, that have
3383 Changesets that are ancestors of the current revision, that have
3384 already been grafted, or that are merges will be skipped.
3384 already been grafted, or that are merges will be skipped.
3385
3385
3386 If --log is specified, log messages will have a comment appended
3386 If --log is specified, log messages will have a comment appended
3387 of the form::
3387 of the form::
3388
3388
3389 (grafted from CHANGESETHASH)
3389 (grafted from CHANGESETHASH)
3390
3390
3391 If --force is specified, revisions will be grafted even if they
3391 If --force is specified, revisions will be grafted even if they
3392 are already ancestors of or have been grafted to the destination.
3392 are already ancestors of or have been grafted to the destination.
3393 This is useful when the revisions have since been backed out.
3393 This is useful when the revisions have since been backed out.
3394
3394
3395 If a graft merge results in conflicts, the graft process is
3395 If a graft merge results in conflicts, the graft process is
3396 interrupted so that the current merge can be manually resolved.
3396 interrupted so that the current merge can be manually resolved.
3397 Once all conflicts are addressed, the graft process can be
3397 Once all conflicts are addressed, the graft process can be
3398 continued with the -c/--continue option.
3398 continued with the -c/--continue option.
3399
3399
3400 .. note::
3400 .. note::
3401
3401
3402 The -c/--continue option does not reapply earlier options, except
3402 The -c/--continue option does not reapply earlier options, except
3403 for --force.
3403 for --force.
3404
3404
3405 .. container:: verbose
3405 .. container:: verbose
3406
3406
3407 Examples:
3407 Examples:
3408
3408
3409 - copy a single change to the stable branch and edit its description::
3409 - copy a single change to the stable branch and edit its description::
3410
3410
3411 hg update stable
3411 hg update stable
3412 hg graft --edit 9393
3412 hg graft --edit 9393
3413
3413
3414 - graft a range of changesets with one exception, updating dates::
3414 - graft a range of changesets with one exception, updating dates::
3415
3415
3416 hg graft -D "2085::2093 and not 2091"
3416 hg graft -D "2085::2093 and not 2091"
3417
3417
3418 - continue a graft after resolving conflicts::
3418 - continue a graft after resolving conflicts::
3419
3419
3420 hg graft -c
3420 hg graft -c
3421
3421
3422 - show the source of a grafted changeset::
3422 - show the source of a grafted changeset::
3423
3423
3424 hg log --debug -r .
3424 hg log --debug -r .
3425
3425
3426 See :hg:`help revisions` and :hg:`help revsets` for more about
3426 See :hg:`help revisions` and :hg:`help revsets` for more about
3427 specifying revisions.
3427 specifying revisions.
3428
3428
3429 Returns 0 on successful completion.
3429 Returns 0 on successful completion.
3430 '''
3430 '''
3431
3431
3432 revs = list(revs)
3432 revs = list(revs)
3433 revs.extend(opts['rev'])
3433 revs.extend(opts['rev'])
3434
3434
3435 if not opts.get('user') and opts.get('currentuser'):
3435 if not opts.get('user') and opts.get('currentuser'):
3436 opts['user'] = ui.username()
3436 opts['user'] = ui.username()
3437 if not opts.get('date') and opts.get('currentdate'):
3437 if not opts.get('date') and opts.get('currentdate'):
3438 opts['date'] = "%d %d" % util.makedate()
3438 opts['date'] = "%d %d" % util.makedate()
3439
3439
3440 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3440 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3441
3441
3442 cont = False
3442 cont = False
3443 if opts['continue']:
3443 if opts['continue']:
3444 cont = True
3444 cont = True
3445 if revs:
3445 if revs:
3446 raise util.Abort(_("can't specify --continue and revisions"))
3446 raise util.Abort(_("can't specify --continue and revisions"))
3447 # read in unfinished revisions
3447 # read in unfinished revisions
3448 try:
3448 try:
3449 nodes = repo.vfs.read('graftstate').splitlines()
3449 nodes = repo.vfs.read('graftstate').splitlines()
3450 revs = [repo[node].rev() for node in nodes]
3450 revs = [repo[node].rev() for node in nodes]
3451 except IOError, inst:
3451 except IOError, inst:
3452 if inst.errno != errno.ENOENT:
3452 if inst.errno != errno.ENOENT:
3453 raise
3453 raise
3454 raise util.Abort(_("no graft state found, can't continue"))
3454 raise util.Abort(_("no graft state found, can't continue"))
3455 else:
3455 else:
3456 cmdutil.checkunfinished(repo)
3456 cmdutil.checkunfinished(repo)
3457 cmdutil.bailifchanged(repo)
3457 cmdutil.bailifchanged(repo)
3458 if not revs:
3458 if not revs:
3459 raise util.Abort(_('no revisions specified'))
3459 raise util.Abort(_('no revisions specified'))
3460 revs = scmutil.revrange(repo, revs)
3460 revs = scmutil.revrange(repo, revs)
3461
3461
3462 skipped = set()
3462 skipped = set()
3463 # check for merges
3463 # check for merges
3464 for rev in repo.revs('%ld and merge()', revs):
3464 for rev in repo.revs('%ld and merge()', revs):
3465 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3465 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3466 skipped.add(rev)
3466 skipped.add(rev)
3467 revs = [r for r in revs if r not in skipped]
3467 revs = [r for r in revs if r not in skipped]
3468 if not revs:
3468 if not revs:
3469 return -1
3469 return -1
3470
3470
3471 # Don't check in the --continue case, in effect retaining --force across
3471 # Don't check in the --continue case, in effect retaining --force across
3472 # --continues. That's because without --force, any revisions we decided to
3472 # --continues. That's because without --force, any revisions we decided to
3473 # skip would have been filtered out here, so they wouldn't have made their
3473 # skip would have been filtered out here, so they wouldn't have made their
3474 # way to the graftstate. With --force, any revisions we would have otherwise
3474 # way to the graftstate. With --force, any revisions we would have otherwise
3475 # skipped would not have been filtered out, and if they hadn't been applied
3475 # skipped would not have been filtered out, and if they hadn't been applied
3476 # already, they'd have been in the graftstate.
3476 # already, they'd have been in the graftstate.
3477 if not (cont or opts.get('force')):
3477 if not (cont or opts.get('force')):
3478 # check for ancestors of dest branch
3478 # check for ancestors of dest branch
3479 crev = repo['.'].rev()
3479 crev = repo['.'].rev()
3480 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3480 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3481 # Cannot use x.remove(y) on smart set, this has to be a list.
3481 # Cannot use x.remove(y) on smart set, this has to be a list.
3482 # XXX make this lazy in the future
3482 # XXX make this lazy in the future
3483 revs = list(revs)
3483 revs = list(revs)
3484 # don't mutate while iterating, create a copy
3484 # don't mutate while iterating, create a copy
3485 for rev in list(revs):
3485 for rev in list(revs):
3486 if rev in ancestors:
3486 if rev in ancestors:
3487 ui.warn(_('skipping ancestor revision %d:%s\n') %
3487 ui.warn(_('skipping ancestor revision %d:%s\n') %
3488 (rev, repo[rev]))
3488 (rev, repo[rev]))
3489 # XXX remove on list is slow
3489 # XXX remove on list is slow
3490 revs.remove(rev)
3490 revs.remove(rev)
3491 if not revs:
3491 if not revs:
3492 return -1
3492 return -1
3493
3493
3494 # analyze revs for earlier grafts
3494 # analyze revs for earlier grafts
3495 ids = {}
3495 ids = {}
3496 for ctx in repo.set("%ld", revs):
3496 for ctx in repo.set("%ld", revs):
3497 ids[ctx.hex()] = ctx.rev()
3497 ids[ctx.hex()] = ctx.rev()
3498 n = ctx.extra().get('source')
3498 n = ctx.extra().get('source')
3499 if n:
3499 if n:
3500 ids[n] = ctx.rev()
3500 ids[n] = ctx.rev()
3501
3501
3502 # check ancestors for earlier grafts
3502 # check ancestors for earlier grafts
3503 ui.debug('scanning for duplicate grafts\n')
3503 ui.debug('scanning for duplicate grafts\n')
3504
3504
3505 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3505 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3506 ctx = repo[rev]
3506 ctx = repo[rev]
3507 n = ctx.extra().get('source')
3507 n = ctx.extra().get('source')
3508 if n in ids:
3508 if n in ids:
3509 try:
3509 try:
3510 r = repo[n].rev()
3510 r = repo[n].rev()
3511 except error.RepoLookupError:
3511 except error.RepoLookupError:
3512 r = None
3512 r = None
3513 if r in revs:
3513 if r in revs:
3514 ui.warn(_('skipping revision %d:%s '
3514 ui.warn(_('skipping revision %d:%s '
3515 '(already grafted to %d:%s)\n')
3515 '(already grafted to %d:%s)\n')
3516 % (r, repo[r], rev, ctx))
3516 % (r, repo[r], rev, ctx))
3517 revs.remove(r)
3517 revs.remove(r)
3518 elif ids[n] in revs:
3518 elif ids[n] in revs:
3519 if r is None:
3519 if r is None:
3520 ui.warn(_('skipping already grafted revision %d:%s '
3520 ui.warn(_('skipping already grafted revision %d:%s '
3521 '(%d:%s also has unknown origin %s)\n')
3521 '(%d:%s also has unknown origin %s)\n')
3522 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3522 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3523 else:
3523 else:
3524 ui.warn(_('skipping already grafted revision %d:%s '
3524 ui.warn(_('skipping already grafted revision %d:%s '
3525 '(%d:%s also has origin %d:%s)\n')
3525 '(%d:%s also has origin %d:%s)\n')
3526 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3526 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3527 revs.remove(ids[n])
3527 revs.remove(ids[n])
3528 elif ctx.hex() in ids:
3528 elif ctx.hex() in ids:
3529 r = ids[ctx.hex()]
3529 r = ids[ctx.hex()]
3530 ui.warn(_('skipping already grafted revision %d:%s '
3530 ui.warn(_('skipping already grafted revision %d:%s '
3531 '(was grafted from %d:%s)\n') %
3531 '(was grafted from %d:%s)\n') %
3532 (r, repo[r], rev, ctx))
3532 (r, repo[r], rev, ctx))
3533 revs.remove(r)
3533 revs.remove(r)
3534 if not revs:
3534 if not revs:
3535 return -1
3535 return -1
3536
3536
3537 wlock = repo.wlock()
3537 wlock = repo.wlock()
3538 try:
3538 try:
3539 for pos, ctx in enumerate(repo.set("%ld", revs)):
3539 for pos, ctx in enumerate(repo.set("%ld", revs)):
3540 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3540 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3541 ctx.description().split('\n', 1)[0])
3541 ctx.description().split('\n', 1)[0])
3542 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3542 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3543 if names:
3543 if names:
3544 desc += ' (%s)' % ' '.join(names)
3544 desc += ' (%s)' % ' '.join(names)
3545 ui.status(_('grafting %s\n') % desc)
3545 ui.status(_('grafting %s\n') % desc)
3546 if opts.get('dry_run'):
3546 if opts.get('dry_run'):
3547 continue
3547 continue
3548
3548
3549 source = ctx.extra().get('source')
3549 source = ctx.extra().get('source')
3550 extra = {}
3550 extra = {}
3551 if source:
3551 if source:
3552 extra['source'] = source
3552 extra['source'] = source
3553 extra['intermediate-source'] = ctx.hex()
3553 extra['intermediate-source'] = ctx.hex()
3554 else:
3554 else:
3555 extra['source'] = ctx.hex()
3555 extra['source'] = ctx.hex()
3556 user = ctx.user()
3556 user = ctx.user()
3557 if opts.get('user'):
3557 if opts.get('user'):
3558 user = opts['user']
3558 user = opts['user']
3559 date = ctx.date()
3559 date = ctx.date()
3560 if opts.get('date'):
3560 if opts.get('date'):
3561 date = opts['date']
3561 date = opts['date']
3562 message = ctx.description()
3562 message = ctx.description()
3563 if opts.get('log'):
3563 if opts.get('log'):
3564 message += '\n(grafted from %s)' % ctx.hex()
3564 message += '\n(grafted from %s)' % ctx.hex()
3565
3565
3566 # we don't merge the first commit when continuing
3566 # we don't merge the first commit when continuing
3567 if not cont:
3567 if not cont:
3568 # perform the graft merge with p1(rev) as 'ancestor'
3568 # perform the graft merge with p1(rev) as 'ancestor'
3569 try:
3569 try:
3570 # ui.forcemerge is an internal variable, do not document
3570 # ui.forcemerge is an internal variable, do not document
3571 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3571 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3572 'graft')
3572 'graft')
3573 stats = mergemod.graft(repo, ctx, ctx.p1(),
3573 stats = mergemod.graft(repo, ctx, ctx.p1(),
3574 ['local', 'graft'])
3574 ['local', 'graft'])
3575 finally:
3575 finally:
3576 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3576 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3577 # report any conflicts
3577 # report any conflicts
3578 if stats and stats[3] > 0:
3578 if stats and stats[3] > 0:
3579 # write out state for --continue
3579 # write out state for --continue
3580 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3580 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3581 repo.vfs.write('graftstate', ''.join(nodelines))
3581 repo.vfs.write('graftstate', ''.join(nodelines))
3582 raise util.Abort(
3582 raise util.Abort(
3583 _("unresolved conflicts, can't continue"),
3583 _("unresolved conflicts, can't continue"),
3584 hint=_('use hg resolve and hg graft --continue'))
3584 hint=_('use hg resolve and hg graft --continue'))
3585 else:
3585 else:
3586 cont = False
3586 cont = False
3587
3587
3588 # commit
3588 # commit
3589 node = repo.commit(text=message, user=user,
3589 node = repo.commit(text=message, user=user,
3590 date=date, extra=extra, editor=editor)
3590 date=date, extra=extra, editor=editor)
3591 if node is None:
3591 if node is None:
3592 ui.warn(
3592 ui.warn(
3593 _('note: graft of %d:%s created no changes to commit\n') %
3593 _('note: graft of %d:%s created no changes to commit\n') %
3594 (ctx.rev(), ctx))
3594 (ctx.rev(), ctx))
3595 finally:
3595 finally:
3596 wlock.release()
3596 wlock.release()
3597
3597
3598 # remove state when we complete successfully
3598 # remove state when we complete successfully
3599 if not opts.get('dry_run'):
3599 if not opts.get('dry_run'):
3600 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3600 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3601
3601
3602 return 0
3602 return 0
3603
3603
3604 @command('grep',
3604 @command('grep',
3605 [('0', 'print0', None, _('end fields with NUL')),
3605 [('0', 'print0', None, _('end fields with NUL')),
3606 ('', 'all', None, _('print all revisions that match')),
3606 ('', 'all', None, _('print all revisions that match')),
3607 ('a', 'text', None, _('treat all files as text')),
3607 ('a', 'text', None, _('treat all files as text')),
3608 ('f', 'follow', None,
3608 ('f', 'follow', None,
3609 _('follow changeset history,'
3609 _('follow changeset history,'
3610 ' or file history across copies and renames')),
3610 ' or file history across copies and renames')),
3611 ('i', 'ignore-case', None, _('ignore case when matching')),
3611 ('i', 'ignore-case', None, _('ignore case when matching')),
3612 ('l', 'files-with-matches', None,
3612 ('l', 'files-with-matches', None,
3613 _('print only filenames and revisions that match')),
3613 _('print only filenames and revisions that match')),
3614 ('n', 'line-number', None, _('print matching line numbers')),
3614 ('n', 'line-number', None, _('print matching line numbers')),
3615 ('r', 'rev', [],
3615 ('r', 'rev', [],
3616 _('only search files changed within revision range'), _('REV')),
3616 _('only search files changed within revision range'), _('REV')),
3617 ('u', 'user', None, _('list the author (long with -v)')),
3617 ('u', 'user', None, _('list the author (long with -v)')),
3618 ('d', 'date', None, _('list the date (short with -q)')),
3618 ('d', 'date', None, _('list the date (short with -q)')),
3619 ] + walkopts,
3619 ] + walkopts,
3620 _('[OPTION]... PATTERN [FILE]...'),
3620 _('[OPTION]... PATTERN [FILE]...'),
3621 inferrepo=True)
3621 inferrepo=True)
3622 def grep(ui, repo, pattern, *pats, **opts):
3622 def grep(ui, repo, pattern, *pats, **opts):
3623 """search for a pattern in specified files and revisions
3623 """search for a pattern in specified files and revisions
3624
3624
3625 Search revisions of files for a regular expression.
3625 Search revisions of files for a regular expression.
3626
3626
3627 This command behaves differently than Unix grep. It only accepts
3627 This command behaves differently than Unix grep. It only accepts
3628 Python/Perl regexps. It searches repository history, not the
3628 Python/Perl regexps. It searches repository history, not the
3629 working directory. It always prints the revision number in which a
3629 working directory. It always prints the revision number in which a
3630 match appears.
3630 match appears.
3631
3631
3632 By default, grep only prints output for the first revision of a
3632 By default, grep only prints output for the first revision of a
3633 file in which it finds a match. To get it to print every revision
3633 file in which it finds a match. To get it to print every revision
3634 that contains a change in match status ("-" for a match that
3634 that contains a change in match status ("-" for a match that
3635 becomes a non-match, or "+" for a non-match that becomes a match),
3635 becomes a non-match, or "+" for a non-match that becomes a match),
3636 use the --all flag.
3636 use the --all flag.
3637
3637
3638 Returns 0 if a match is found, 1 otherwise.
3638 Returns 0 if a match is found, 1 otherwise.
3639 """
3639 """
3640 reflags = re.M
3640 reflags = re.M
3641 if opts.get('ignore_case'):
3641 if opts.get('ignore_case'):
3642 reflags |= re.I
3642 reflags |= re.I
3643 try:
3643 try:
3644 regexp = util.re.compile(pattern, reflags)
3644 regexp = util.re.compile(pattern, reflags)
3645 except re.error, inst:
3645 except re.error, inst:
3646 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3646 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3647 return 1
3647 return 1
3648 sep, eol = ':', '\n'
3648 sep, eol = ':', '\n'
3649 if opts.get('print0'):
3649 if opts.get('print0'):
3650 sep = eol = '\0'
3650 sep = eol = '\0'
3651
3651
3652 getfile = util.lrucachefunc(repo.file)
3652 getfile = util.lrucachefunc(repo.file)
3653
3653
3654 def matchlines(body):
3654 def matchlines(body):
3655 begin = 0
3655 begin = 0
3656 linenum = 0
3656 linenum = 0
3657 while begin < len(body):
3657 while begin < len(body):
3658 match = regexp.search(body, begin)
3658 match = regexp.search(body, begin)
3659 if not match:
3659 if not match:
3660 break
3660 break
3661 mstart, mend = match.span()
3661 mstart, mend = match.span()
3662 linenum += body.count('\n', begin, mstart) + 1
3662 linenum += body.count('\n', begin, mstart) + 1
3663 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3663 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3664 begin = body.find('\n', mend) + 1 or len(body) + 1
3664 begin = body.find('\n', mend) + 1 or len(body) + 1
3665 lend = begin - 1
3665 lend = begin - 1
3666 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3666 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3667
3667
3668 class linestate(object):
3668 class linestate(object):
3669 def __init__(self, line, linenum, colstart, colend):
3669 def __init__(self, line, linenum, colstart, colend):
3670 self.line = line
3670 self.line = line
3671 self.linenum = linenum
3671 self.linenum = linenum
3672 self.colstart = colstart
3672 self.colstart = colstart
3673 self.colend = colend
3673 self.colend = colend
3674
3674
3675 def __hash__(self):
3675 def __hash__(self):
3676 return hash((self.linenum, self.line))
3676 return hash((self.linenum, self.line))
3677
3677
3678 def __eq__(self, other):
3678 def __eq__(self, other):
3679 return self.line == other.line
3679 return self.line == other.line
3680
3680
3681 def __iter__(self):
3681 def __iter__(self):
3682 yield (self.line[:self.colstart], '')
3682 yield (self.line[:self.colstart], '')
3683 yield (self.line[self.colstart:self.colend], 'grep.match')
3683 yield (self.line[self.colstart:self.colend], 'grep.match')
3684 rest = self.line[self.colend:]
3684 rest = self.line[self.colend:]
3685 while rest != '':
3685 while rest != '':
3686 match = regexp.search(rest)
3686 match = regexp.search(rest)
3687 if not match:
3687 if not match:
3688 yield (rest, '')
3688 yield (rest, '')
3689 break
3689 break
3690 mstart, mend = match.span()
3690 mstart, mend = match.span()
3691 yield (rest[:mstart], '')
3691 yield (rest[:mstart], '')
3692 yield (rest[mstart:mend], 'grep.match')
3692 yield (rest[mstart:mend], 'grep.match')
3693 rest = rest[mend:]
3693 rest = rest[mend:]
3694
3694
3695 matches = {}
3695 matches = {}
3696 copies = {}
3696 copies = {}
3697 def grepbody(fn, rev, body):
3697 def grepbody(fn, rev, body):
3698 matches[rev].setdefault(fn, [])
3698 matches[rev].setdefault(fn, [])
3699 m = matches[rev][fn]
3699 m = matches[rev][fn]
3700 for lnum, cstart, cend, line in matchlines(body):
3700 for lnum, cstart, cend, line in matchlines(body):
3701 s = linestate(line, lnum, cstart, cend)
3701 s = linestate(line, lnum, cstart, cend)
3702 m.append(s)
3702 m.append(s)
3703
3703
3704 def difflinestates(a, b):
3704 def difflinestates(a, b):
3705 sm = difflib.SequenceMatcher(None, a, b)
3705 sm = difflib.SequenceMatcher(None, a, b)
3706 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3706 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3707 if tag == 'insert':
3707 if tag == 'insert':
3708 for i in xrange(blo, bhi):
3708 for i in xrange(blo, bhi):
3709 yield ('+', b[i])
3709 yield ('+', b[i])
3710 elif tag == 'delete':
3710 elif tag == 'delete':
3711 for i in xrange(alo, ahi):
3711 for i in xrange(alo, ahi):
3712 yield ('-', a[i])
3712 yield ('-', a[i])
3713 elif tag == 'replace':
3713 elif tag == 'replace':
3714 for i in xrange(alo, ahi):
3714 for i in xrange(alo, ahi):
3715 yield ('-', a[i])
3715 yield ('-', a[i])
3716 for i in xrange(blo, bhi):
3716 for i in xrange(blo, bhi):
3717 yield ('+', b[i])
3717 yield ('+', b[i])
3718
3718
3719 def display(fn, ctx, pstates, states):
3719 def display(fn, ctx, pstates, states):
3720 rev = ctx.rev()
3720 rev = ctx.rev()
3721 if ui.quiet:
3721 if ui.quiet:
3722 datefunc = util.shortdate
3722 datefunc = util.shortdate
3723 else:
3723 else:
3724 datefunc = util.datestr
3724 datefunc = util.datestr
3725 found = False
3725 found = False
3726 @util.cachefunc
3726 @util.cachefunc
3727 def binary():
3727 def binary():
3728 flog = getfile(fn)
3728 flog = getfile(fn)
3729 return util.binary(flog.read(ctx.filenode(fn)))
3729 return util.binary(flog.read(ctx.filenode(fn)))
3730
3730
3731 if opts.get('all'):
3731 if opts.get('all'):
3732 iter = difflinestates(pstates, states)
3732 iter = difflinestates(pstates, states)
3733 else:
3733 else:
3734 iter = [('', l) for l in states]
3734 iter = [('', l) for l in states]
3735 for change, l in iter:
3735 for change, l in iter:
3736 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3736 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3737
3737
3738 if opts.get('line_number'):
3738 if opts.get('line_number'):
3739 cols.append((str(l.linenum), 'grep.linenumber'))
3739 cols.append((str(l.linenum), 'grep.linenumber'))
3740 if opts.get('all'):
3740 if opts.get('all'):
3741 cols.append((change, 'grep.change'))
3741 cols.append((change, 'grep.change'))
3742 if opts.get('user'):
3742 if opts.get('user'):
3743 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3743 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3744 if opts.get('date'):
3744 if opts.get('date'):
3745 cols.append((datefunc(ctx.date()), 'grep.date'))
3745 cols.append((datefunc(ctx.date()), 'grep.date'))
3746 for col, label in cols[:-1]:
3746 for col, label in cols[:-1]:
3747 ui.write(col, label=label)
3747 ui.write(col, label=label)
3748 ui.write(sep, label='grep.sep')
3748 ui.write(sep, label='grep.sep')
3749 ui.write(cols[-1][0], label=cols[-1][1])
3749 ui.write(cols[-1][0], label=cols[-1][1])
3750 if not opts.get('files_with_matches'):
3750 if not opts.get('files_with_matches'):
3751 ui.write(sep, label='grep.sep')
3751 ui.write(sep, label='grep.sep')
3752 if not opts.get('text') and binary():
3752 if not opts.get('text') and binary():
3753 ui.write(" Binary file matches")
3753 ui.write(" Binary file matches")
3754 else:
3754 else:
3755 for s, label in l:
3755 for s, label in l:
3756 ui.write(s, label=label)
3756 ui.write(s, label=label)
3757 ui.write(eol)
3757 ui.write(eol)
3758 found = True
3758 found = True
3759 if opts.get('files_with_matches'):
3759 if opts.get('files_with_matches'):
3760 break
3760 break
3761 return found
3761 return found
3762
3762
3763 skip = {}
3763 skip = {}
3764 revfiles = {}
3764 revfiles = {}
3765 matchfn = scmutil.match(repo[None], pats, opts)
3765 matchfn = scmutil.match(repo[None], pats, opts)
3766 found = False
3766 found = False
3767 follow = opts.get('follow')
3767 follow = opts.get('follow')
3768
3768
3769 def prep(ctx, fns):
3769 def prep(ctx, fns):
3770 rev = ctx.rev()
3770 rev = ctx.rev()
3771 pctx = ctx.p1()
3771 pctx = ctx.p1()
3772 parent = pctx.rev()
3772 parent = pctx.rev()
3773 matches.setdefault(rev, {})
3773 matches.setdefault(rev, {})
3774 matches.setdefault(parent, {})
3774 matches.setdefault(parent, {})
3775 files = revfiles.setdefault(rev, [])
3775 files = revfiles.setdefault(rev, [])
3776 for fn in fns:
3776 for fn in fns:
3777 flog = getfile(fn)
3777 flog = getfile(fn)
3778 try:
3778 try:
3779 fnode = ctx.filenode(fn)
3779 fnode = ctx.filenode(fn)
3780 except error.LookupError:
3780 except error.LookupError:
3781 continue
3781 continue
3782
3782
3783 copied = flog.renamed(fnode)
3783 copied = flog.renamed(fnode)
3784 copy = follow and copied and copied[0]
3784 copy = follow and copied and copied[0]
3785 if copy:
3785 if copy:
3786 copies.setdefault(rev, {})[fn] = copy
3786 copies.setdefault(rev, {})[fn] = copy
3787 if fn in skip:
3787 if fn in skip:
3788 if copy:
3788 if copy:
3789 skip[copy] = True
3789 skip[copy] = True
3790 continue
3790 continue
3791 files.append(fn)
3791 files.append(fn)
3792
3792
3793 if fn not in matches[rev]:
3793 if fn not in matches[rev]:
3794 grepbody(fn, rev, flog.read(fnode))
3794 grepbody(fn, rev, flog.read(fnode))
3795
3795
3796 pfn = copy or fn
3796 pfn = copy or fn
3797 if pfn not in matches[parent]:
3797 if pfn not in matches[parent]:
3798 try:
3798 try:
3799 fnode = pctx.filenode(pfn)
3799 fnode = pctx.filenode(pfn)
3800 grepbody(pfn, parent, flog.read(fnode))
3800 grepbody(pfn, parent, flog.read(fnode))
3801 except error.LookupError:
3801 except error.LookupError:
3802 pass
3802 pass
3803
3803
3804 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3804 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3805 rev = ctx.rev()
3805 rev = ctx.rev()
3806 parent = ctx.p1().rev()
3806 parent = ctx.p1().rev()
3807 for fn in sorted(revfiles.get(rev, [])):
3807 for fn in sorted(revfiles.get(rev, [])):
3808 states = matches[rev][fn]
3808 states = matches[rev][fn]
3809 copy = copies.get(rev, {}).get(fn)
3809 copy = copies.get(rev, {}).get(fn)
3810 if fn in skip:
3810 if fn in skip:
3811 if copy:
3811 if copy:
3812 skip[copy] = True
3812 skip[copy] = True
3813 continue
3813 continue
3814 pstates = matches.get(parent, {}).get(copy or fn, [])
3814 pstates = matches.get(parent, {}).get(copy or fn, [])
3815 if pstates or states:
3815 if pstates or states:
3816 r = display(fn, ctx, pstates, states)
3816 r = display(fn, ctx, pstates, states)
3817 found = found or r
3817 found = found or r
3818 if r and not opts.get('all'):
3818 if r and not opts.get('all'):
3819 skip[fn] = True
3819 skip[fn] = True
3820 if copy:
3820 if copy:
3821 skip[copy] = True
3821 skip[copy] = True
3822 del matches[rev]
3822 del matches[rev]
3823 del revfiles[rev]
3823 del revfiles[rev]
3824
3824
3825 return not found
3825 return not found
3826
3826
3827 @command('heads',
3827 @command('heads',
3828 [('r', 'rev', '',
3828 [('r', 'rev', '',
3829 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3829 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3830 ('t', 'topo', False, _('show topological heads only')),
3830 ('t', 'topo', False, _('show topological heads only')),
3831 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3831 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3832 ('c', 'closed', False, _('show normal and closed branch heads')),
3832 ('c', 'closed', False, _('show normal and closed branch heads')),
3833 ] + templateopts,
3833 ] + templateopts,
3834 _('[-ct] [-r STARTREV] [REV]...'))
3834 _('[-ct] [-r STARTREV] [REV]...'))
3835 def heads(ui, repo, *branchrevs, **opts):
3835 def heads(ui, repo, *branchrevs, **opts):
3836 """show branch heads
3836 """show branch heads
3837
3837
3838 With no arguments, show all open branch heads in the repository.
3838 With no arguments, show all open branch heads in the repository.
3839 Branch heads are changesets that have no descendants on the
3839 Branch heads are changesets that have no descendants on the
3840 same branch. They are where development generally takes place and
3840 same branch. They are where development generally takes place and
3841 are the usual targets for update and merge operations.
3841 are the usual targets for update and merge operations.
3842
3842
3843 If one or more REVs are given, only open branch heads on the
3843 If one or more REVs are given, only open branch heads on the
3844 branches associated with the specified changesets are shown. This
3844 branches associated with the specified changesets are shown. This
3845 means that you can use :hg:`heads .` to see the heads on the
3845 means that you can use :hg:`heads .` to see the heads on the
3846 currently checked-out branch.
3846 currently checked-out branch.
3847
3847
3848 If -c/--closed is specified, also show branch heads marked closed
3848 If -c/--closed is specified, also show branch heads marked closed
3849 (see :hg:`commit --close-branch`).
3849 (see :hg:`commit --close-branch`).
3850
3850
3851 If STARTREV is specified, only those heads that are descendants of
3851 If STARTREV is specified, only those heads that are descendants of
3852 STARTREV will be displayed.
3852 STARTREV will be displayed.
3853
3853
3854 If -t/--topo is specified, named branch mechanics will be ignored and only
3854 If -t/--topo is specified, named branch mechanics will be ignored and only
3855 topological heads (changesets with no children) will be shown.
3855 topological heads (changesets with no children) will be shown.
3856
3856
3857 Returns 0 if matching heads are found, 1 if not.
3857 Returns 0 if matching heads are found, 1 if not.
3858 """
3858 """
3859
3859
3860 start = None
3860 start = None
3861 if 'rev' in opts:
3861 if 'rev' in opts:
3862 start = scmutil.revsingle(repo, opts['rev'], None).node()
3862 start = scmutil.revsingle(repo, opts['rev'], None).node()
3863
3863
3864 if opts.get('topo'):
3864 if opts.get('topo'):
3865 heads = [repo[h] for h in repo.heads(start)]
3865 heads = [repo[h] for h in repo.heads(start)]
3866 else:
3866 else:
3867 heads = []
3867 heads = []
3868 for branch in repo.branchmap():
3868 for branch in repo.branchmap():
3869 heads += repo.branchheads(branch, start, opts.get('closed'))
3869 heads += repo.branchheads(branch, start, opts.get('closed'))
3870 heads = [repo[h] for h in heads]
3870 heads = [repo[h] for h in heads]
3871
3871
3872 if branchrevs:
3872 if branchrevs:
3873 branches = set(repo[br].branch() for br in branchrevs)
3873 branches = set(repo[br].branch() for br in branchrevs)
3874 heads = [h for h in heads if h.branch() in branches]
3874 heads = [h for h in heads if h.branch() in branches]
3875
3875
3876 if opts.get('active') and branchrevs:
3876 if opts.get('active') and branchrevs:
3877 dagheads = repo.heads(start)
3877 dagheads = repo.heads(start)
3878 heads = [h for h in heads if h.node() in dagheads]
3878 heads = [h for h in heads if h.node() in dagheads]
3879
3879
3880 if branchrevs:
3880 if branchrevs:
3881 haveheads = set(h.branch() for h in heads)
3881 haveheads = set(h.branch() for h in heads)
3882 if branches - haveheads:
3882 if branches - haveheads:
3883 headless = ', '.join(b for b in branches - haveheads)
3883 headless = ', '.join(b for b in branches - haveheads)
3884 msg = _('no open branch heads found on branches %s')
3884 msg = _('no open branch heads found on branches %s')
3885 if opts.get('rev'):
3885 if opts.get('rev'):
3886 msg += _(' (started at %s)') % opts['rev']
3886 msg += _(' (started at %s)') % opts['rev']
3887 ui.warn((msg + '\n') % headless)
3887 ui.warn((msg + '\n') % headless)
3888
3888
3889 if not heads:
3889 if not heads:
3890 return 1
3890 return 1
3891
3891
3892 heads = sorted(heads, key=lambda x: -x.rev())
3892 heads = sorted(heads, key=lambda x: -x.rev())
3893 displayer = cmdutil.show_changeset(ui, repo, opts)
3893 displayer = cmdutil.show_changeset(ui, repo, opts)
3894 for ctx in heads:
3894 for ctx in heads:
3895 displayer.show(ctx)
3895 displayer.show(ctx)
3896 displayer.close()
3896 displayer.close()
3897
3897
3898 @command('help',
3898 @command('help',
3899 [('e', 'extension', None, _('show only help for extensions')),
3899 [('e', 'extension', None, _('show only help for extensions')),
3900 ('c', 'command', None, _('show only help for commands')),
3900 ('c', 'command', None, _('show only help for commands')),
3901 ('k', 'keyword', '', _('show topics matching keyword')),
3901 ('k', 'keyword', '', _('show topics matching keyword')),
3902 ],
3902 ],
3903 _('[-ec] [TOPIC]'),
3903 _('[-ec] [TOPIC]'),
3904 norepo=True)
3904 norepo=True)
3905 def help_(ui, name=None, **opts):
3905 def help_(ui, name=None, **opts):
3906 """show help for a given topic or a help overview
3906 """show help for a given topic or a help overview
3907
3907
3908 With no arguments, print a list of commands with short help messages.
3908 With no arguments, print a list of commands with short help messages.
3909
3909
3910 Given a topic, extension, or command name, print help for that
3910 Given a topic, extension, or command name, print help for that
3911 topic.
3911 topic.
3912
3912
3913 Returns 0 if successful.
3913 Returns 0 if successful.
3914 """
3914 """
3915
3915
3916 textwidth = min(ui.termwidth(), 80) - 2
3916 textwidth = min(ui.termwidth(), 80) - 2
3917
3917
3918 keep = []
3918 keep = []
3919 if ui.verbose:
3919 if ui.verbose:
3920 keep.append('verbose')
3920 keep.append('verbose')
3921 if sys.platform.startswith('win'):
3921 if sys.platform.startswith('win'):
3922 keep.append('windows')
3922 keep.append('windows')
3923 elif sys.platform == 'OpenVMS':
3923 elif sys.platform == 'OpenVMS':
3924 keep.append('vms')
3924 keep.append('vms')
3925 elif sys.platform == 'plan9':
3925 elif sys.platform == 'plan9':
3926 keep.append('plan9')
3926 keep.append('plan9')
3927 else:
3927 else:
3928 keep.append('unix')
3928 keep.append('unix')
3929 keep.append(sys.platform.lower())
3929 keep.append(sys.platform.lower())
3930
3930
3931 section = None
3931 section = None
3932 if name and '.' in name:
3932 if name and '.' in name:
3933 name, section = name.split('.', 1)
3933 name, section = name.split('.', 1)
3934
3934
3935 text = help.help_(ui, name, **opts)
3935 text = help.help_(ui, name, **opts)
3936
3936
3937 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3937 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3938 section=section)
3938 section=section)
3939 if section and not formatted:
3939 if section and not formatted:
3940 raise util.Abort(_("help section not found"))
3940 raise util.Abort(_("help section not found"))
3941
3941
3942 if 'verbose' in pruned:
3942 if 'verbose' in pruned:
3943 keep.append('omitted')
3943 keep.append('omitted')
3944 else:
3944 else:
3945 keep.append('notomitted')
3945 keep.append('notomitted')
3946 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3946 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3947 section=section)
3947 section=section)
3948 ui.write(formatted)
3948 ui.write(formatted)
3949
3949
3950
3950
3951 @command('identify|id',
3951 @command('identify|id',
3952 [('r', 'rev', '',
3952 [('r', 'rev', '',
3953 _('identify the specified revision'), _('REV')),
3953 _('identify the specified revision'), _('REV')),
3954 ('n', 'num', None, _('show local revision number')),
3954 ('n', 'num', None, _('show local revision number')),
3955 ('i', 'id', None, _('show global revision id')),
3955 ('i', 'id', None, _('show global revision id')),
3956 ('b', 'branch', None, _('show branch')),
3956 ('b', 'branch', None, _('show branch')),
3957 ('t', 'tags', None, _('show tags')),
3957 ('t', 'tags', None, _('show tags')),
3958 ('B', 'bookmarks', None, _('show bookmarks')),
3958 ('B', 'bookmarks', None, _('show bookmarks')),
3959 ] + remoteopts,
3959 ] + remoteopts,
3960 _('[-nibtB] [-r REV] [SOURCE]'),
3960 _('[-nibtB] [-r REV] [SOURCE]'),
3961 optionalrepo=True)
3961 optionalrepo=True)
3962 def identify(ui, repo, source=None, rev=None,
3962 def identify(ui, repo, source=None, rev=None,
3963 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3963 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3964 """identify the working directory or specified revision
3964 """identify the working directory or specified revision
3965
3965
3966 Print a summary identifying the repository state at REV using one or
3966 Print a summary identifying the repository state at REV using one or
3967 two parent hash identifiers, followed by a "+" if the working
3967 two parent hash identifiers, followed by a "+" if the working
3968 directory has uncommitted changes, the branch name (if not default),
3968 directory has uncommitted changes, the branch name (if not default),
3969 a list of tags, and a list of bookmarks.
3969 a list of tags, and a list of bookmarks.
3970
3970
3971 When REV is not given, print a summary of the current state of the
3971 When REV is not given, print a summary of the current state of the
3972 repository.
3972 repository.
3973
3973
3974 Specifying a path to a repository root or Mercurial bundle will
3974 Specifying a path to a repository root or Mercurial bundle will
3975 cause lookup to operate on that repository/bundle.
3975 cause lookup to operate on that repository/bundle.
3976
3976
3977 .. container:: verbose
3977 .. container:: verbose
3978
3978
3979 Examples:
3979 Examples:
3980
3980
3981 - generate a build identifier for the working directory::
3981 - generate a build identifier for the working directory::
3982
3982
3983 hg id --id > build-id.dat
3983 hg id --id > build-id.dat
3984
3984
3985 - find the revision corresponding to a tag::
3985 - find the revision corresponding to a tag::
3986
3986
3987 hg id -n -r 1.3
3987 hg id -n -r 1.3
3988
3988
3989 - check the most recent revision of a remote repository::
3989 - check the most recent revision of a remote repository::
3990
3990
3991 hg id -r tip http://selenic.com/hg/
3991 hg id -r tip http://selenic.com/hg/
3992
3992
3993 Returns 0 if successful.
3993 Returns 0 if successful.
3994 """
3994 """
3995
3995
3996 if not repo and not source:
3996 if not repo and not source:
3997 raise util.Abort(_("there is no Mercurial repository here "
3997 raise util.Abort(_("there is no Mercurial repository here "
3998 "(.hg not found)"))
3998 "(.hg not found)"))
3999
3999
4000 if ui.debugflag:
4000 if ui.debugflag:
4001 hexfunc = hex
4001 hexfunc = hex
4002 else:
4002 else:
4003 hexfunc = short
4003 hexfunc = short
4004 default = not (num or id or branch or tags or bookmarks)
4004 default = not (num or id or branch or tags or bookmarks)
4005 output = []
4005 output = []
4006 revs = []
4006 revs = []
4007
4007
4008 if source:
4008 if source:
4009 source, branches = hg.parseurl(ui.expandpath(source))
4009 source, branches = hg.parseurl(ui.expandpath(source))
4010 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4010 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4011 repo = peer.local()
4011 repo = peer.local()
4012 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4012 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4013
4013
4014 if not repo:
4014 if not repo:
4015 if num or branch or tags:
4015 if num or branch or tags:
4016 raise util.Abort(
4016 raise util.Abort(
4017 _("can't query remote revision number, branch, or tags"))
4017 _("can't query remote revision number, branch, or tags"))
4018 if not rev and revs:
4018 if not rev and revs:
4019 rev = revs[0]
4019 rev = revs[0]
4020 if not rev:
4020 if not rev:
4021 rev = "tip"
4021 rev = "tip"
4022
4022
4023 remoterev = peer.lookup(rev)
4023 remoterev = peer.lookup(rev)
4024 if default or id:
4024 if default or id:
4025 output = [hexfunc(remoterev)]
4025 output = [hexfunc(remoterev)]
4026
4026
4027 def getbms():
4027 def getbms():
4028 bms = []
4028 bms = []
4029
4029
4030 if 'bookmarks' in peer.listkeys('namespaces'):
4030 if 'bookmarks' in peer.listkeys('namespaces'):
4031 hexremoterev = hex(remoterev)
4031 hexremoterev = hex(remoterev)
4032 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4032 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4033 if bmr == hexremoterev]
4033 if bmr == hexremoterev]
4034
4034
4035 return sorted(bms)
4035 return sorted(bms)
4036
4036
4037 if bookmarks:
4037 if bookmarks:
4038 output.extend(getbms())
4038 output.extend(getbms())
4039 elif default and not ui.quiet:
4039 elif default and not ui.quiet:
4040 # multiple bookmarks for a single parent separated by '/'
4040 # multiple bookmarks for a single parent separated by '/'
4041 bm = '/'.join(getbms())
4041 bm = '/'.join(getbms())
4042 if bm:
4042 if bm:
4043 output.append(bm)
4043 output.append(bm)
4044 else:
4044 else:
4045 if not rev:
4045 if not rev:
4046 ctx = repo[None]
4046 ctx = repo[None]
4047 parents = ctx.parents()
4047 parents = ctx.parents()
4048 changed = ""
4048 changed = ""
4049 if default or id or num:
4049 if default or id or num:
4050 if (util.any(repo.status())
4050 if (util.any(repo.status())
4051 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4051 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4052 changed = '+'
4052 changed = '+'
4053 if default or id:
4053 if default or id:
4054 output = ["%s%s" %
4054 output = ["%s%s" %
4055 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4055 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4056 if num:
4056 if num:
4057 output.append("%s%s" %
4057 output.append("%s%s" %
4058 ('+'.join([str(p.rev()) for p in parents]), changed))
4058 ('+'.join([str(p.rev()) for p in parents]), changed))
4059 else:
4059 else:
4060 ctx = scmutil.revsingle(repo, rev)
4060 ctx = scmutil.revsingle(repo, rev)
4061 if default or id:
4061 if default or id:
4062 output = [hexfunc(ctx.node())]
4062 output = [hexfunc(ctx.node())]
4063 if num:
4063 if num:
4064 output.append(str(ctx.rev()))
4064 output.append(str(ctx.rev()))
4065
4065
4066 if default and not ui.quiet:
4066 if default and not ui.quiet:
4067 b = ctx.branch()
4067 b = ctx.branch()
4068 if b != 'default':
4068 if b != 'default':
4069 output.append("(%s)" % b)
4069 output.append("(%s)" % b)
4070
4070
4071 # multiple tags for a single parent separated by '/'
4071 # multiple tags for a single parent separated by '/'
4072 t = '/'.join(ctx.tags())
4072 t = '/'.join(ctx.tags())
4073 if t:
4073 if t:
4074 output.append(t)
4074 output.append(t)
4075
4075
4076 # multiple bookmarks for a single parent separated by '/'
4076 # multiple bookmarks for a single parent separated by '/'
4077 bm = '/'.join(ctx.bookmarks())
4077 bm = '/'.join(ctx.bookmarks())
4078 if bm:
4078 if bm:
4079 output.append(bm)
4079 output.append(bm)
4080 else:
4080 else:
4081 if branch:
4081 if branch:
4082 output.append(ctx.branch())
4082 output.append(ctx.branch())
4083
4083
4084 if tags:
4084 if tags:
4085 output.extend(ctx.tags())
4085 output.extend(ctx.tags())
4086
4086
4087 if bookmarks:
4087 if bookmarks:
4088 output.extend(ctx.bookmarks())
4088 output.extend(ctx.bookmarks())
4089
4089
4090 ui.write("%s\n" % ' '.join(output))
4090 ui.write("%s\n" % ' '.join(output))
4091
4091
4092 @command('import|patch',
4092 @command('import|patch',
4093 [('p', 'strip', 1,
4093 [('p', 'strip', 1,
4094 _('directory strip option for patch. This has the same '
4094 _('directory strip option for patch. This has the same '
4095 'meaning as the corresponding patch option'), _('NUM')),
4095 'meaning as the corresponding patch option'), _('NUM')),
4096 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4096 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4097 ('e', 'edit', False, _('invoke editor on commit messages')),
4097 ('e', 'edit', False, _('invoke editor on commit messages')),
4098 ('f', 'force', None,
4098 ('f', 'force', None,
4099 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4099 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4100 ('', 'no-commit', None,
4100 ('', 'no-commit', None,
4101 _("don't commit, just update the working directory")),
4101 _("don't commit, just update the working directory")),
4102 ('', 'bypass', None,
4102 ('', 'bypass', None,
4103 _("apply patch without touching the working directory")),
4103 _("apply patch without touching the working directory")),
4104 ('', 'partial', None,
4104 ('', 'partial', None,
4105 _('commit even if some hunks fail')),
4105 _('commit even if some hunks fail')),
4106 ('', 'exact', None,
4106 ('', 'exact', None,
4107 _('apply patch to the nodes from which it was generated')),
4107 _('apply patch to the nodes from which it was generated')),
4108 ('', 'prefix', '',
4108 ('', 'prefix', '',
4109 _('apply patch to subdirectory'), _('DIR')),
4109 _('apply patch to subdirectory'), _('DIR')),
4110 ('', 'import-branch', None,
4110 ('', 'import-branch', None,
4111 _('use any branch information in patch (implied by --exact)'))] +
4111 _('use any branch information in patch (implied by --exact)'))] +
4112 commitopts + commitopts2 + similarityopts,
4112 commitopts + commitopts2 + similarityopts,
4113 _('[OPTION]... PATCH...'))
4113 _('[OPTION]... PATCH...'))
4114 def import_(ui, repo, patch1=None, *patches, **opts):
4114 def import_(ui, repo, patch1=None, *patches, **opts):
4115 """import an ordered set of patches
4115 """import an ordered set of patches
4116
4116
4117 Import a list of patches and commit them individually (unless
4117 Import a list of patches and commit them individually (unless
4118 --no-commit is specified).
4118 --no-commit is specified).
4119
4119
4120 Because import first applies changes to the working directory,
4120 Because import first applies changes to the working directory,
4121 import will abort if there are outstanding changes.
4121 import will abort if there are outstanding changes.
4122
4122
4123 You can import a patch straight from a mail message. Even patches
4123 You can import a patch straight from a mail message. Even patches
4124 as attachments work (to use the body part, it must have type
4124 as attachments work (to use the body part, it must have type
4125 text/plain or text/x-patch). From and Subject headers of email
4125 text/plain or text/x-patch). From and Subject headers of email
4126 message are used as default committer and commit message. All
4126 message are used as default committer and commit message. All
4127 text/plain body parts before first diff are added to commit
4127 text/plain body parts before first diff are added to commit
4128 message.
4128 message.
4129
4129
4130 If the imported patch was generated by :hg:`export`, user and
4130 If the imported patch was generated by :hg:`export`, user and
4131 description from patch override values from message headers and
4131 description from patch override values from message headers and
4132 body. Values given on command line with -m/--message and -u/--user
4132 body. Values given on command line with -m/--message and -u/--user
4133 override these.
4133 override these.
4134
4134
4135 If --exact is specified, import will set the working directory to
4135 If --exact is specified, import will set the working directory to
4136 the parent of each patch before applying it, and will abort if the
4136 the parent of each patch before applying it, and will abort if the
4137 resulting changeset has a different ID than the one recorded in
4137 resulting changeset has a different ID than the one recorded in
4138 the patch. This may happen due to character set problems or other
4138 the patch. This may happen due to character set problems or other
4139 deficiencies in the text patch format.
4139 deficiencies in the text patch format.
4140
4140
4141 Use --bypass to apply and commit patches directly to the
4141 Use --bypass to apply and commit patches directly to the
4142 repository, not touching the working directory. Without --exact,
4142 repository, not touching the working directory. Without --exact,
4143 patches will be applied on top of the working directory parent
4143 patches will be applied on top of the working directory parent
4144 revision.
4144 revision.
4145
4145
4146 With -s/--similarity, hg will attempt to discover renames and
4146 With -s/--similarity, hg will attempt to discover renames and
4147 copies in the patch in the same way as :hg:`addremove`.
4147 copies in the patch in the same way as :hg:`addremove`.
4148
4148
4149 Use --partial to ensure a changeset will be created from the patch
4149 Use --partial to ensure a changeset will be created from the patch
4150 even if some hunks fail to apply. Hunks that fail to apply will be
4150 even if some hunks fail to apply. Hunks that fail to apply will be
4151 written to a <target-file>.rej file. Conflicts can then be resolved
4151 written to a <target-file>.rej file. Conflicts can then be resolved
4152 by hand before :hg:`commit --amend` is run to update the created
4152 by hand before :hg:`commit --amend` is run to update the created
4153 changeset. This flag exists to let people import patches that
4153 changeset. This flag exists to let people import patches that
4154 partially apply without losing the associated metadata (author,
4154 partially apply without losing the associated metadata (author,
4155 date, description, ...). Note that when none of the hunk applies
4155 date, description, ...). Note that when none of the hunk applies
4156 cleanly, :hg:`import --partial` will create an empty changeset,
4156 cleanly, :hg:`import --partial` will create an empty changeset,
4157 importing only the patch metadata.
4157 importing only the patch metadata.
4158
4158
4159 To read a patch from standard input, use "-" as the patch name. If
4159 To read a patch from standard input, use "-" as the patch name. If
4160 a URL is specified, the patch will be downloaded from it.
4160 a URL is specified, the patch will be downloaded from it.
4161 See :hg:`help dates` for a list of formats valid for -d/--date.
4161 See :hg:`help dates` for a list of formats valid for -d/--date.
4162
4162
4163 .. container:: verbose
4163 .. container:: verbose
4164
4164
4165 Examples:
4165 Examples:
4166
4166
4167 - import a traditional patch from a website and detect renames::
4167 - import a traditional patch from a website and detect renames::
4168
4168
4169 hg import -s 80 http://example.com/bugfix.patch
4169 hg import -s 80 http://example.com/bugfix.patch
4170
4170
4171 - import a changeset from an hgweb server::
4171 - import a changeset from an hgweb server::
4172
4172
4173 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4173 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4174
4174
4175 - import all the patches in an Unix-style mbox::
4175 - import all the patches in an Unix-style mbox::
4176
4176
4177 hg import incoming-patches.mbox
4177 hg import incoming-patches.mbox
4178
4178
4179 - attempt to exactly restore an exported changeset (not always
4179 - attempt to exactly restore an exported changeset (not always
4180 possible)::
4180 possible)::
4181
4181
4182 hg import --exact proposed-fix.patch
4182 hg import --exact proposed-fix.patch
4183
4183
4184 Returns 0 on success, 1 on partial success (see --partial).
4184 Returns 0 on success, 1 on partial success (see --partial).
4185 """
4185 """
4186
4186
4187 if not patch1:
4187 if not patch1:
4188 raise util.Abort(_('need at least one patch to import'))
4188 raise util.Abort(_('need at least one patch to import'))
4189
4189
4190 patches = (patch1,) + patches
4190 patches = (patch1,) + patches
4191
4191
4192 date = opts.get('date')
4192 date = opts.get('date')
4193 if date:
4193 if date:
4194 opts['date'] = util.parsedate(date)
4194 opts['date'] = util.parsedate(date)
4195
4195
4196 update = not opts.get('bypass')
4196 update = not opts.get('bypass')
4197 if not update and opts.get('no_commit'):
4197 if not update and opts.get('no_commit'):
4198 raise util.Abort(_('cannot use --no-commit with --bypass'))
4198 raise util.Abort(_('cannot use --no-commit with --bypass'))
4199 try:
4199 try:
4200 sim = float(opts.get('similarity') or 0)
4200 sim = float(opts.get('similarity') or 0)
4201 except ValueError:
4201 except ValueError:
4202 raise util.Abort(_('similarity must be a number'))
4202 raise util.Abort(_('similarity must be a number'))
4203 if sim < 0 or sim > 100:
4203 if sim < 0 or sim > 100:
4204 raise util.Abort(_('similarity must be between 0 and 100'))
4204 raise util.Abort(_('similarity must be between 0 and 100'))
4205 if sim and not update:
4205 if sim and not update:
4206 raise util.Abort(_('cannot use --similarity with --bypass'))
4206 raise util.Abort(_('cannot use --similarity with --bypass'))
4207 if opts.get('exact') and opts.get('edit'):
4207 if opts.get('exact') and opts.get('edit'):
4208 raise util.Abort(_('cannot use --exact with --edit'))
4208 raise util.Abort(_('cannot use --exact with --edit'))
4209 if opts.get('exact') and opts.get('prefix'):
4209 if opts.get('exact') and opts.get('prefix'):
4210 raise util.Abort(_('cannot use --exact with --prefix'))
4210 raise util.Abort(_('cannot use --exact with --prefix'))
4211
4211
4212 if update:
4212 if update:
4213 cmdutil.checkunfinished(repo)
4213 cmdutil.checkunfinished(repo)
4214 if (opts.get('exact') or not opts.get('force')) and update:
4214 if (opts.get('exact') or not opts.get('force')) and update:
4215 cmdutil.bailifchanged(repo)
4215 cmdutil.bailifchanged(repo)
4216
4216
4217 base = opts["base"]
4217 base = opts["base"]
4218 wlock = lock = tr = None
4218 wlock = lock = tr = None
4219 msgs = []
4219 msgs = []
4220 ret = 0
4220 ret = 0
4221
4221
4222
4222
4223 try:
4223 try:
4224 try:
4224 try:
4225 wlock = repo.wlock()
4225 wlock = repo.wlock()
4226 repo.dirstate.beginparentchange()
4226 repo.dirstate.beginparentchange()
4227 if not opts.get('no_commit'):
4227 if not opts.get('no_commit'):
4228 lock = repo.lock()
4228 lock = repo.lock()
4229 tr = repo.transaction('import')
4229 tr = repo.transaction('import')
4230 parents = repo.parents()
4230 parents = repo.parents()
4231 for patchurl in patches:
4231 for patchurl in patches:
4232 if patchurl == '-':
4232 if patchurl == '-':
4233 ui.status(_('applying patch from stdin\n'))
4233 ui.status(_('applying patch from stdin\n'))
4234 patchfile = ui.fin
4234 patchfile = ui.fin
4235 patchurl = 'stdin' # for error message
4235 patchurl = 'stdin' # for error message
4236 else:
4236 else:
4237 patchurl = os.path.join(base, patchurl)
4237 patchurl = os.path.join(base, patchurl)
4238 ui.status(_('applying %s\n') % patchurl)
4238 ui.status(_('applying %s\n') % patchurl)
4239 patchfile = hg.openpath(ui, patchurl)
4239 patchfile = hg.openpath(ui, patchurl)
4240
4240
4241 haspatch = False
4241 haspatch = False
4242 for hunk in patch.split(patchfile):
4242 for hunk in patch.split(patchfile):
4243 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4243 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4244 parents, opts,
4244 parents, opts,
4245 msgs, hg.clean)
4245 msgs, hg.clean)
4246 if msg:
4246 if msg:
4247 haspatch = True
4247 haspatch = True
4248 ui.note(msg + '\n')
4248 ui.note(msg + '\n')
4249 if update or opts.get('exact'):
4249 if update or opts.get('exact'):
4250 parents = repo.parents()
4250 parents = repo.parents()
4251 else:
4251 else:
4252 parents = [repo[node]]
4252 parents = [repo[node]]
4253 if rej:
4253 if rej:
4254 ui.write_err(_("patch applied partially\n"))
4254 ui.write_err(_("patch applied partially\n"))
4255 ui.write_err(_("(fix the .rej files and run "
4255 ui.write_err(_("(fix the .rej files and run "
4256 "`hg commit --amend`)\n"))
4256 "`hg commit --amend`)\n"))
4257 ret = 1
4257 ret = 1
4258 break
4258 break
4259
4259
4260 if not haspatch:
4260 if not haspatch:
4261 raise util.Abort(_('%s: no diffs found') % patchurl)
4261 raise util.Abort(_('%s: no diffs found') % patchurl)
4262
4262
4263 if tr:
4263 if tr:
4264 tr.close()
4264 tr.close()
4265 if msgs:
4265 if msgs:
4266 repo.savecommitmessage('\n* * *\n'.join(msgs))
4266 repo.savecommitmessage('\n* * *\n'.join(msgs))
4267 repo.dirstate.endparentchange()
4267 repo.dirstate.endparentchange()
4268 return ret
4268 return ret
4269 except: # re-raises
4269 except: # re-raises
4270 # wlock.release() indirectly calls dirstate.write(): since
4270 # wlock.release() indirectly calls dirstate.write(): since
4271 # we're crashing, we do not want to change the working dir
4271 # we're crashing, we do not want to change the working dir
4272 # parent after all, so make sure it writes nothing
4272 # parent after all, so make sure it writes nothing
4273 repo.dirstate.invalidate()
4273 repo.dirstate.invalidate()
4274 raise
4274 raise
4275 finally:
4275 finally:
4276 if tr:
4276 if tr:
4277 tr.release()
4277 tr.release()
4278 release(lock, wlock)
4278 release(lock, wlock)
4279
4279
4280 @command('incoming|in',
4280 @command('incoming|in',
4281 [('f', 'force', None,
4281 [('f', 'force', None,
4282 _('run even if remote repository is unrelated')),
4282 _('run even if remote repository is unrelated')),
4283 ('n', 'newest-first', None, _('show newest record first')),
4283 ('n', 'newest-first', None, _('show newest record first')),
4284 ('', 'bundle', '',
4284 ('', 'bundle', '',
4285 _('file to store the bundles into'), _('FILE')),
4285 _('file to store the bundles into'), _('FILE')),
4286 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4286 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4287 ('B', 'bookmarks', False, _("compare bookmarks")),
4287 ('B', 'bookmarks', False, _("compare bookmarks")),
4288 ('b', 'branch', [],
4288 ('b', 'branch', [],
4289 _('a specific branch you would like to pull'), _('BRANCH')),
4289 _('a specific branch you would like to pull'), _('BRANCH')),
4290 ] + logopts + remoteopts + subrepoopts,
4290 ] + logopts + remoteopts + subrepoopts,
4291 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4291 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4292 def incoming(ui, repo, source="default", **opts):
4292 def incoming(ui, repo, source="default", **opts):
4293 """show new changesets found in source
4293 """show new changesets found in source
4294
4294
4295 Show new changesets found in the specified path/URL or the default
4295 Show new changesets found in the specified path/URL or the default
4296 pull location. These are the changesets that would have been pulled
4296 pull location. These are the changesets that would have been pulled
4297 if a pull at the time you issued this command.
4297 if a pull at the time you issued this command.
4298
4298
4299 See pull for valid source format details.
4299 See pull for valid source format details.
4300
4300
4301 .. container:: verbose
4301 .. container:: verbose
4302
4302
4303 With -B/--bookmarks, the result of bookmark comparison between
4303 With -B/--bookmarks, the result of bookmark comparison between
4304 local and remote repositories is displayed. With -v/--verbose,
4304 local and remote repositories is displayed. With -v/--verbose,
4305 status is also displayed for each bookmark like below::
4305 status is also displayed for each bookmark like below::
4306
4306
4307 BM1 01234567890a added
4307 BM1 01234567890a added
4308 BM2 1234567890ab advanced
4308 BM2 1234567890ab advanced
4309 BM3 234567890abc diverged
4309 BM3 234567890abc diverged
4310 BM4 34567890abcd changed
4310 BM4 34567890abcd changed
4311
4311
4312 The action taken locally when pulling depends on the
4312 The action taken locally when pulling depends on the
4313 status of each bookmark:
4313 status of each bookmark:
4314
4314
4315 :``added``: pull will create it
4315 :``added``: pull will create it
4316 :``advanced``: pull will update it
4316 :``advanced``: pull will update it
4317 :``diverged``: pull will create a divergent bookmark
4317 :``diverged``: pull will create a divergent bookmark
4318 :``changed``: result depends on remote changesets
4318 :``changed``: result depends on remote changesets
4319
4319
4320 From the point of view of pulling behavior, bookmark
4320 From the point of view of pulling behavior, bookmark
4321 existing only in the remote repository are treated as ``added``,
4321 existing only in the remote repository are treated as ``added``,
4322 even if it is in fact locally deleted.
4322 even if it is in fact locally deleted.
4323
4323
4324 .. container:: verbose
4324 .. container:: verbose
4325
4325
4326 For remote repository, using --bundle avoids downloading the
4326 For remote repository, using --bundle avoids downloading the
4327 changesets twice if the incoming is followed by a pull.
4327 changesets twice if the incoming is followed by a pull.
4328
4328
4329 Examples:
4329 Examples:
4330
4330
4331 - show incoming changes with patches and full description::
4331 - show incoming changes with patches and full description::
4332
4332
4333 hg incoming -vp
4333 hg incoming -vp
4334
4334
4335 - show incoming changes excluding merges, store a bundle::
4335 - show incoming changes excluding merges, store a bundle::
4336
4336
4337 hg in -vpM --bundle incoming.hg
4337 hg in -vpM --bundle incoming.hg
4338 hg pull incoming.hg
4338 hg pull incoming.hg
4339
4339
4340 - briefly list changes inside a bundle::
4340 - briefly list changes inside a bundle::
4341
4341
4342 hg in changes.hg -T "{desc|firstline}\\n"
4342 hg in changes.hg -T "{desc|firstline}\\n"
4343
4343
4344 Returns 0 if there are incoming changes, 1 otherwise.
4344 Returns 0 if there are incoming changes, 1 otherwise.
4345 """
4345 """
4346 if opts.get('graph'):
4346 if opts.get('graph'):
4347 cmdutil.checkunsupportedgraphflags([], opts)
4347 cmdutil.checkunsupportedgraphflags([], opts)
4348 def display(other, chlist, displayer):
4348 def display(other, chlist, displayer):
4349 revdag = cmdutil.graphrevs(other, chlist, opts)
4349 revdag = cmdutil.graphrevs(other, chlist, opts)
4350 showparents = [ctx.node() for ctx in repo[None].parents()]
4350 showparents = [ctx.node() for ctx in repo[None].parents()]
4351 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4351 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4352 graphmod.asciiedges)
4352 graphmod.asciiedges)
4353
4353
4354 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4354 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4355 return 0
4355 return 0
4356
4356
4357 if opts.get('bundle') and opts.get('subrepos'):
4357 if opts.get('bundle') and opts.get('subrepos'):
4358 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4358 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4359
4359
4360 if opts.get('bookmarks'):
4360 if opts.get('bookmarks'):
4361 source, branches = hg.parseurl(ui.expandpath(source),
4361 source, branches = hg.parseurl(ui.expandpath(source),
4362 opts.get('branch'))
4362 opts.get('branch'))
4363 other = hg.peer(repo, opts, source)
4363 other = hg.peer(repo, opts, source)
4364 if 'bookmarks' not in other.listkeys('namespaces'):
4364 if 'bookmarks' not in other.listkeys('namespaces'):
4365 ui.warn(_("remote doesn't support bookmarks\n"))
4365 ui.warn(_("remote doesn't support bookmarks\n"))
4366 return 0
4366 return 0
4367 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4367 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4368 return bookmarks.incoming(ui, repo, other)
4368 return bookmarks.incoming(ui, repo, other)
4369
4369
4370 repo._subtoppath = ui.expandpath(source)
4370 repo._subtoppath = ui.expandpath(source)
4371 try:
4371 try:
4372 return hg.incoming(ui, repo, source, opts)
4372 return hg.incoming(ui, repo, source, opts)
4373 finally:
4373 finally:
4374 del repo._subtoppath
4374 del repo._subtoppath
4375
4375
4376
4376
4377 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4377 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4378 norepo=True)
4378 norepo=True)
4379 def init(ui, dest=".", **opts):
4379 def init(ui, dest=".", **opts):
4380 """create a new repository in the given directory
4380 """create a new repository in the given directory
4381
4381
4382 Initialize a new repository in the given directory. If the given
4382 Initialize a new repository in the given directory. If the given
4383 directory does not exist, it will be created.
4383 directory does not exist, it will be created.
4384
4384
4385 If no directory is given, the current directory is used.
4385 If no directory is given, the current directory is used.
4386
4386
4387 It is possible to specify an ``ssh://`` URL as the destination.
4387 It is possible to specify an ``ssh://`` URL as the destination.
4388 See :hg:`help urls` for more information.
4388 See :hg:`help urls` for more information.
4389
4389
4390 Returns 0 on success.
4390 Returns 0 on success.
4391 """
4391 """
4392 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4392 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4393
4393
4394 @command('locate',
4394 @command('locate',
4395 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4395 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4396 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4396 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4397 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4397 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4398 ] + walkopts,
4398 ] + walkopts,
4399 _('[OPTION]... [PATTERN]...'))
4399 _('[OPTION]... [PATTERN]...'))
4400 def locate(ui, repo, *pats, **opts):
4400 def locate(ui, repo, *pats, **opts):
4401 """locate files matching specific patterns (DEPRECATED)
4401 """locate files matching specific patterns (DEPRECATED)
4402
4402
4403 Print files under Mercurial control in the working directory whose
4403 Print files under Mercurial control in the working directory whose
4404 names match the given patterns.
4404 names match the given patterns.
4405
4405
4406 By default, this command searches all directories in the working
4406 By default, this command searches all directories in the working
4407 directory. To search just the current directory and its
4407 directory. To search just the current directory and its
4408 subdirectories, use "--include .".
4408 subdirectories, use "--include .".
4409
4409
4410 If no patterns are given to match, this command prints the names
4410 If no patterns are given to match, this command prints the names
4411 of all files under Mercurial control in the working directory.
4411 of all files under Mercurial control in the working directory.
4412
4412
4413 If you want to feed the output of this command into the "xargs"
4413 If you want to feed the output of this command into the "xargs"
4414 command, use the -0 option to both this command and "xargs". This
4414 command, use the -0 option to both this command and "xargs". This
4415 will avoid the problem of "xargs" treating single filenames that
4415 will avoid the problem of "xargs" treating single filenames that
4416 contain whitespace as multiple filenames.
4416 contain whitespace as multiple filenames.
4417
4417
4418 See :hg:`help files` for a more versatile command.
4418 See :hg:`help files` for a more versatile command.
4419
4419
4420 Returns 0 if a match is found, 1 otherwise.
4420 Returns 0 if a match is found, 1 otherwise.
4421 """
4421 """
4422 if opts.get('print0'):
4422 if opts.get('print0'):
4423 end = '\0'
4423 end = '\0'
4424 else:
4424 else:
4425 end = '\n'
4425 end = '\n'
4426 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4426 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4427
4427
4428 ret = 1
4428 ret = 1
4429 ctx = repo[rev]
4429 ctx = repo[rev]
4430 m = scmutil.match(ctx, pats, opts, default='relglob')
4430 m = scmutil.match(ctx, pats, opts, default='relglob')
4431 m.bad = lambda x, y: False
4431 m.bad = lambda x, y: False
4432
4432
4433 for abs in ctx.matches(m):
4433 for abs in ctx.matches(m):
4434 if opts.get('fullpath'):
4434 if opts.get('fullpath'):
4435 ui.write(repo.wjoin(abs), end)
4435 ui.write(repo.wjoin(abs), end)
4436 else:
4436 else:
4437 ui.write(((pats and m.rel(abs)) or abs), end)
4437 ui.write(((pats and m.rel(abs)) or abs), end)
4438 ret = 0
4438 ret = 0
4439
4439
4440 return ret
4440 return ret
4441
4441
4442 @command('^log|history',
4442 @command('^log|history',
4443 [('f', 'follow', None,
4443 [('f', 'follow', None,
4444 _('follow changeset history, or file history across copies and renames')),
4444 _('follow changeset history, or file history across copies and renames')),
4445 ('', 'follow-first', None,
4445 ('', 'follow-first', None,
4446 _('only follow the first parent of merge changesets (DEPRECATED)')),
4446 _('only follow the first parent of merge changesets (DEPRECATED)')),
4447 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4447 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4448 ('C', 'copies', None, _('show copied files')),
4448 ('C', 'copies', None, _('show copied files')),
4449 ('k', 'keyword', [],
4449 ('k', 'keyword', [],
4450 _('do case-insensitive search for a given text'), _('TEXT')),
4450 _('do case-insensitive search for a given text'), _('TEXT')),
4451 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4451 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4452 ('', 'removed', None, _('include revisions where files were removed')),
4452 ('', 'removed', None, _('include revisions where files were removed')),
4453 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4453 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4454 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4454 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4455 ('', 'only-branch', [],
4455 ('', 'only-branch', [],
4456 _('show only changesets within the given named branch (DEPRECATED)'),
4456 _('show only changesets within the given named branch (DEPRECATED)'),
4457 _('BRANCH')),
4457 _('BRANCH')),
4458 ('b', 'branch', [],
4458 ('b', 'branch', [],
4459 _('show changesets within the given named branch'), _('BRANCH')),
4459 _('show changesets within the given named branch'), _('BRANCH')),
4460 ('P', 'prune', [],
4460 ('P', 'prune', [],
4461 _('do not display revision or any of its ancestors'), _('REV')),
4461 _('do not display revision or any of its ancestors'), _('REV')),
4462 ] + logopts + walkopts,
4462 ] + logopts + walkopts,
4463 _('[OPTION]... [FILE]'),
4463 _('[OPTION]... [FILE]'),
4464 inferrepo=True)
4464 inferrepo=True)
4465 def log(ui, repo, *pats, **opts):
4465 def log(ui, repo, *pats, **opts):
4466 """show revision history of entire repository or files
4466 """show revision history of entire repository or files
4467
4467
4468 Print the revision history of the specified files or the entire
4468 Print the revision history of the specified files or the entire
4469 project.
4469 project.
4470
4470
4471 If no revision range is specified, the default is ``tip:0`` unless
4471 If no revision range is specified, the default is ``tip:0`` unless
4472 --follow is set, in which case the working directory parent is
4472 --follow is set, in which case the working directory parent is
4473 used as the starting revision.
4473 used as the starting revision.
4474
4474
4475 File history is shown without following rename or copy history of
4475 File history is shown without following rename or copy history of
4476 files. Use -f/--follow with a filename to follow history across
4476 files. Use -f/--follow with a filename to follow history across
4477 renames and copies. --follow without a filename will only show
4477 renames and copies. --follow without a filename will only show
4478 ancestors or descendants of the starting revision.
4478 ancestors or descendants of the starting revision.
4479
4479
4480 By default this command prints revision number and changeset id,
4480 By default this command prints revision number and changeset id,
4481 tags, non-trivial parents, user, date and time, and a summary for
4481 tags, non-trivial parents, user, date and time, and a summary for
4482 each commit. When the -v/--verbose switch is used, the list of
4482 each commit. When the -v/--verbose switch is used, the list of
4483 changed files and full commit message are shown.
4483 changed files and full commit message are shown.
4484
4484
4485 With --graph the revisions are shown as an ASCII art DAG with the most
4485 With --graph the revisions are shown as an ASCII art DAG with the most
4486 recent changeset at the top.
4486 recent changeset at the top.
4487 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4487 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4488 and '+' represents a fork where the changeset from the lines below is a
4488 and '+' represents a fork where the changeset from the lines below is a
4489 parent of the 'o' merge on the same line.
4489 parent of the 'o' merge on the same line.
4490
4490
4491 .. note::
4491 .. note::
4492
4492
4493 log -p/--patch may generate unexpected diff output for merge
4493 log -p/--patch may generate unexpected diff output for merge
4494 changesets, as it will only compare the merge changeset against
4494 changesets, as it will only compare the merge changeset against
4495 its first parent. Also, only files different from BOTH parents
4495 its first parent. Also, only files different from BOTH parents
4496 will appear in files:.
4496 will appear in files:.
4497
4497
4498 .. note::
4498 .. note::
4499
4499
4500 for performance reasons, log FILE may omit duplicate changes
4500 for performance reasons, log FILE may omit duplicate changes
4501 made on branches and will not show removals or mode changes. To
4501 made on branches and will not show removals or mode changes. To
4502 see all such changes, use the --removed switch.
4502 see all such changes, use the --removed switch.
4503
4503
4504 .. container:: verbose
4504 .. container:: verbose
4505
4505
4506 Some examples:
4506 Some examples:
4507
4507
4508 - changesets with full descriptions and file lists::
4508 - changesets with full descriptions and file lists::
4509
4509
4510 hg log -v
4510 hg log -v
4511
4511
4512 - changesets ancestral to the working directory::
4512 - changesets ancestral to the working directory::
4513
4513
4514 hg log -f
4514 hg log -f
4515
4515
4516 - last 10 commits on the current branch::
4516 - last 10 commits on the current branch::
4517
4517
4518 hg log -l 10 -b .
4518 hg log -l 10 -b .
4519
4519
4520 - changesets showing all modifications of a file, including removals::
4520 - changesets showing all modifications of a file, including removals::
4521
4521
4522 hg log --removed file.c
4522 hg log --removed file.c
4523
4523
4524 - all changesets that touch a directory, with diffs, excluding merges::
4524 - all changesets that touch a directory, with diffs, excluding merges::
4525
4525
4526 hg log -Mp lib/
4526 hg log -Mp lib/
4527
4527
4528 - all revision numbers that match a keyword::
4528 - all revision numbers that match a keyword::
4529
4529
4530 hg log -k bug --template "{rev}\\n"
4530 hg log -k bug --template "{rev}\\n"
4531
4531
4532 - list available log templates::
4532 - list available log templates::
4533
4533
4534 hg log -T list
4534 hg log -T list
4535
4535
4536 - check if a given changeset is included in a tagged release::
4536 - check if a given changeset is included in a tagged release::
4537
4537
4538 hg log -r "a21ccf and ancestor(1.9)"
4538 hg log -r "a21ccf and ancestor(1.9)"
4539
4539
4540 - find all changesets by some user in a date range::
4540 - find all changesets by some user in a date range::
4541
4541
4542 hg log -k alice -d "may 2008 to jul 2008"
4542 hg log -k alice -d "may 2008 to jul 2008"
4543
4543
4544 - summary of all changesets after the last tag::
4544 - summary of all changesets after the last tag::
4545
4545
4546 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4546 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4547
4547
4548 See :hg:`help dates` for a list of formats valid for -d/--date.
4548 See :hg:`help dates` for a list of formats valid for -d/--date.
4549
4549
4550 See :hg:`help revisions` and :hg:`help revsets` for more about
4550 See :hg:`help revisions` and :hg:`help revsets` for more about
4551 specifying revisions.
4551 specifying revisions.
4552
4552
4553 See :hg:`help templates` for more about pre-packaged styles and
4553 See :hg:`help templates` for more about pre-packaged styles and
4554 specifying custom templates.
4554 specifying custom templates.
4555
4555
4556 Returns 0 on success.
4556 Returns 0 on success.
4557
4557
4558 """
4558 """
4559 if opts.get('follow') and opts.get('rev'):
4559 if opts.get('follow') and opts.get('rev'):
4560 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4560 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4561 del opts['follow']
4561 del opts['follow']
4562
4562
4563 if opts.get('graph'):
4563 if opts.get('graph'):
4564 return cmdutil.graphlog(ui, repo, *pats, **opts)
4564 return cmdutil.graphlog(ui, repo, *pats, **opts)
4565
4565
4566 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4566 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4567 limit = cmdutil.loglimit(opts)
4567 limit = cmdutil.loglimit(opts)
4568 count = 0
4568 count = 0
4569
4569
4570 getrenamed = None
4570 getrenamed = None
4571 if opts.get('copies'):
4571 if opts.get('copies'):
4572 endrev = None
4572 endrev = None
4573 if opts.get('rev'):
4573 if opts.get('rev'):
4574 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4574 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4575 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4575 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4576
4576
4577 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4577 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4578 for rev in revs:
4578 for rev in revs:
4579 if count == limit:
4579 if count == limit:
4580 break
4580 break
4581 ctx = repo[rev]
4581 ctx = repo[rev]
4582 copies = None
4582 copies = None
4583 if getrenamed is not None and rev:
4583 if getrenamed is not None and rev:
4584 copies = []
4584 copies = []
4585 for fn in ctx.files():
4585 for fn in ctx.files():
4586 rename = getrenamed(fn, rev)
4586 rename = getrenamed(fn, rev)
4587 if rename:
4587 if rename:
4588 copies.append((fn, rename[0]))
4588 copies.append((fn, rename[0]))
4589 if filematcher:
4589 if filematcher:
4590 revmatchfn = filematcher(ctx.rev())
4590 revmatchfn = filematcher(ctx.rev())
4591 else:
4591 else:
4592 revmatchfn = None
4592 revmatchfn = None
4593 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4593 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4594 if displayer.flush(rev):
4594 if displayer.flush(rev):
4595 count += 1
4595 count += 1
4596
4596
4597 displayer.close()
4597 displayer.close()
4598
4598
4599 @command('manifest',
4599 @command('manifest',
4600 [('r', 'rev', '', _('revision to display'), _('REV')),
4600 [('r', 'rev', '', _('revision to display'), _('REV')),
4601 ('', 'all', False, _("list files from all revisions"))]
4601 ('', 'all', False, _("list files from all revisions"))]
4602 + formatteropts,
4602 + formatteropts,
4603 _('[-r REV]'))
4603 _('[-r REV]'))
4604 def manifest(ui, repo, node=None, rev=None, **opts):
4604 def manifest(ui, repo, node=None, rev=None, **opts):
4605 """output the current or given revision of the project manifest
4605 """output the current or given revision of the project manifest
4606
4606
4607 Print a list of version controlled files for the given revision.
4607 Print a list of version controlled files for the given revision.
4608 If no revision is given, the first parent of the working directory
4608 If no revision is given, the first parent of the working directory
4609 is used, or the null revision if no revision is checked out.
4609 is used, or the null revision if no revision is checked out.
4610
4610
4611 With -v, print file permissions, symlink and executable bits.
4611 With -v, print file permissions, symlink and executable bits.
4612 With --debug, print file revision hashes.
4612 With --debug, print file revision hashes.
4613
4613
4614 If option --all is specified, the list of all files from all revisions
4614 If option --all is specified, the list of all files from all revisions
4615 is printed. This includes deleted and renamed files.
4615 is printed. This includes deleted and renamed files.
4616
4616
4617 Returns 0 on success.
4617 Returns 0 on success.
4618 """
4618 """
4619
4619
4620 fm = ui.formatter('manifest', opts)
4620 fm = ui.formatter('manifest', opts)
4621
4621
4622 if opts.get('all'):
4622 if opts.get('all'):
4623 if rev or node:
4623 if rev or node:
4624 raise util.Abort(_("can't specify a revision with --all"))
4624 raise util.Abort(_("can't specify a revision with --all"))
4625
4625
4626 res = []
4626 res = []
4627 prefix = "data/"
4627 prefix = "data/"
4628 suffix = ".i"
4628 suffix = ".i"
4629 plen = len(prefix)
4629 plen = len(prefix)
4630 slen = len(suffix)
4630 slen = len(suffix)
4631 lock = repo.lock()
4631 lock = repo.lock()
4632 try:
4632 try:
4633 for fn, b, size in repo.store.datafiles():
4633 for fn, b, size in repo.store.datafiles():
4634 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4634 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4635 res.append(fn[plen:-slen])
4635 res.append(fn[plen:-slen])
4636 finally:
4636 finally:
4637 lock.release()
4637 lock.release()
4638 for f in res:
4638 for f in res:
4639 fm.startitem()
4639 fm.startitem()
4640 fm.write("path", '%s\n', f)
4640 fm.write("path", '%s\n', f)
4641 fm.end()
4641 fm.end()
4642 return
4642 return
4643
4643
4644 if rev and node:
4644 if rev and node:
4645 raise util.Abort(_("please specify just one revision"))
4645 raise util.Abort(_("please specify just one revision"))
4646
4646
4647 if not node:
4647 if not node:
4648 node = rev
4648 node = rev
4649
4649
4650 char = {'l': '@', 'x': '*', '': ''}
4650 char = {'l': '@', 'x': '*', '': ''}
4651 mode = {'l': '644', 'x': '755', '': '644'}
4651 mode = {'l': '644', 'x': '755', '': '644'}
4652 ctx = scmutil.revsingle(repo, node)
4652 ctx = scmutil.revsingle(repo, node)
4653 mf = ctx.manifest()
4653 mf = ctx.manifest()
4654 for f in ctx:
4654 for f in ctx:
4655 fm.startitem()
4655 fm.startitem()
4656 fl = ctx[f].flags()
4656 fl = ctx[f].flags()
4657 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4657 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4658 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4658 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4659 fm.write('path', '%s\n', f)
4659 fm.write('path', '%s\n', f)
4660 fm.end()
4660 fm.end()
4661
4661
4662 @command('^merge',
4662 @command('^merge',
4663 [('f', 'force', None,
4663 [('f', 'force', None,
4664 _('force a merge including outstanding changes (DEPRECATED)')),
4664 _('force a merge including outstanding changes (DEPRECATED)')),
4665 ('r', 'rev', '', _('revision to merge'), _('REV')),
4665 ('r', 'rev', '', _('revision to merge'), _('REV')),
4666 ('P', 'preview', None,
4666 ('P', 'preview', None,
4667 _('review revisions to merge (no merge is performed)'))
4667 _('review revisions to merge (no merge is performed)'))
4668 ] + mergetoolopts,
4668 ] + mergetoolopts,
4669 _('[-P] [-f] [[-r] REV]'))
4669 _('[-P] [-f] [[-r] REV]'))
4670 def merge(ui, repo, node=None, **opts):
4670 def merge(ui, repo, node=None, **opts):
4671 """merge another revision into working directory
4671 """merge another revision into working directory
4672
4672
4673 The current working directory is updated with all changes made in
4673 The current working directory is updated with all changes made in
4674 the requested revision since the last common predecessor revision.
4674 the requested revision since the last common predecessor revision.
4675
4675
4676 Files that changed between either parent are marked as changed for
4676 Files that changed between either parent are marked as changed for
4677 the next commit and a commit must be performed before any further
4677 the next commit and a commit must be performed before any further
4678 updates to the repository are allowed. The next commit will have
4678 updates to the repository are allowed. The next commit will have
4679 two parents.
4679 two parents.
4680
4680
4681 ``--tool`` can be used to specify the merge tool used for file
4681 ``--tool`` can be used to specify the merge tool used for file
4682 merges. It overrides the HGMERGE environment variable and your
4682 merges. It overrides the HGMERGE environment variable and your
4683 configuration files. See :hg:`help merge-tools` for options.
4683 configuration files. See :hg:`help merge-tools` for options.
4684
4684
4685 If no revision is specified, the working directory's parent is a
4685 If no revision is specified, the working directory's parent is a
4686 head revision, and the current branch contains exactly one other
4686 head revision, and the current branch contains exactly one other
4687 head, the other head is merged with by default. Otherwise, an
4687 head, the other head is merged with by default. Otherwise, an
4688 explicit revision with which to merge with must be provided.
4688 explicit revision with which to merge with must be provided.
4689
4689
4690 :hg:`resolve` must be used to resolve unresolved files.
4690 :hg:`resolve` must be used to resolve unresolved files.
4691
4691
4692 To undo an uncommitted merge, use :hg:`update --clean .` which
4692 To undo an uncommitted merge, use :hg:`update --clean .` which
4693 will check out a clean copy of the original merge parent, losing
4693 will check out a clean copy of the original merge parent, losing
4694 all changes.
4694 all changes.
4695
4695
4696 Returns 0 on success, 1 if there are unresolved files.
4696 Returns 0 on success, 1 if there are unresolved files.
4697 """
4697 """
4698
4698
4699 if opts.get('rev') and node:
4699 if opts.get('rev') and node:
4700 raise util.Abort(_("please specify just one revision"))
4700 raise util.Abort(_("please specify just one revision"))
4701 if not node:
4701 if not node:
4702 node = opts.get('rev')
4702 node = opts.get('rev')
4703
4703
4704 if node:
4704 if node:
4705 node = scmutil.revsingle(repo, node).node()
4705 node = scmutil.revsingle(repo, node).node()
4706
4706
4707 if not node and repo._bookmarkcurrent:
4707 if not node and repo._bookmarkcurrent:
4708 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4708 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4709 curhead = repo[repo._bookmarkcurrent].node()
4709 curhead = repo[repo._bookmarkcurrent].node()
4710 if len(bmheads) == 2:
4710 if len(bmheads) == 2:
4711 if curhead == bmheads[0]:
4711 if curhead == bmheads[0]:
4712 node = bmheads[1]
4712 node = bmheads[1]
4713 else:
4713 else:
4714 node = bmheads[0]
4714 node = bmheads[0]
4715 elif len(bmheads) > 2:
4715 elif len(bmheads) > 2:
4716 raise util.Abort(_("multiple matching bookmarks to merge - "
4716 raise util.Abort(_("multiple matching bookmarks to merge - "
4717 "please merge with an explicit rev or bookmark"),
4717 "please merge with an explicit rev or bookmark"),
4718 hint=_("run 'hg heads' to see all heads"))
4718 hint=_("run 'hg heads' to see all heads"))
4719 elif len(bmheads) <= 1:
4719 elif len(bmheads) <= 1:
4720 raise util.Abort(_("no matching bookmark to merge - "
4720 raise util.Abort(_("no matching bookmark to merge - "
4721 "please merge with an explicit rev or bookmark"),
4721 "please merge with an explicit rev or bookmark"),
4722 hint=_("run 'hg heads' to see all heads"))
4722 hint=_("run 'hg heads' to see all heads"))
4723
4723
4724 if not node and not repo._bookmarkcurrent:
4724 if not node and not repo._bookmarkcurrent:
4725 branch = repo[None].branch()
4725 branch = repo[None].branch()
4726 bheads = repo.branchheads(branch)
4726 bheads = repo.branchheads(branch)
4727 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4727 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4728
4728
4729 if len(nbhs) > 2:
4729 if len(nbhs) > 2:
4730 raise util.Abort(_("branch '%s' has %d heads - "
4730 raise util.Abort(_("branch '%s' has %d heads - "
4731 "please merge with an explicit rev")
4731 "please merge with an explicit rev")
4732 % (branch, len(bheads)),
4732 % (branch, len(bheads)),
4733 hint=_("run 'hg heads .' to see heads"))
4733 hint=_("run 'hg heads .' to see heads"))
4734
4734
4735 parent = repo.dirstate.p1()
4735 parent = repo.dirstate.p1()
4736 if len(nbhs) <= 1:
4736 if len(nbhs) <= 1:
4737 if len(bheads) > 1:
4737 if len(bheads) > 1:
4738 raise util.Abort(_("heads are bookmarked - "
4738 raise util.Abort(_("heads are bookmarked - "
4739 "please merge with an explicit rev"),
4739 "please merge with an explicit rev"),
4740 hint=_("run 'hg heads' to see all heads"))
4740 hint=_("run 'hg heads' to see all heads"))
4741 if len(repo.heads()) > 1:
4741 if len(repo.heads()) > 1:
4742 raise util.Abort(_("branch '%s' has one head - "
4742 raise util.Abort(_("branch '%s' has one head - "
4743 "please merge with an explicit rev")
4743 "please merge with an explicit rev")
4744 % branch,
4744 % branch,
4745 hint=_("run 'hg heads' to see all heads"))
4745 hint=_("run 'hg heads' to see all heads"))
4746 msg, hint = _('nothing to merge'), None
4746 msg, hint = _('nothing to merge'), None
4747 if parent != repo.lookup(branch):
4747 if parent != repo.lookup(branch):
4748 hint = _("use 'hg update' instead")
4748 hint = _("use 'hg update' instead")
4749 raise util.Abort(msg, hint=hint)
4749 raise util.Abort(msg, hint=hint)
4750
4750
4751 if parent not in bheads:
4751 if parent not in bheads:
4752 raise util.Abort(_('working directory not at a head revision'),
4752 raise util.Abort(_('working directory not at a head revision'),
4753 hint=_("use 'hg update' or merge with an "
4753 hint=_("use 'hg update' or merge with an "
4754 "explicit revision"))
4754 "explicit revision"))
4755 if parent == nbhs[0]:
4755 if parent == nbhs[0]:
4756 node = nbhs[-1]
4756 node = nbhs[-1]
4757 else:
4757 else:
4758 node = nbhs[0]
4758 node = nbhs[0]
4759
4759
4760 if opts.get('preview'):
4760 if opts.get('preview'):
4761 # find nodes that are ancestors of p2 but not of p1
4761 # find nodes that are ancestors of p2 but not of p1
4762 p1 = repo.lookup('.')
4762 p1 = repo.lookup('.')
4763 p2 = repo.lookup(node)
4763 p2 = repo.lookup(node)
4764 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4764 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4765
4765
4766 displayer = cmdutil.show_changeset(ui, repo, opts)
4766 displayer = cmdutil.show_changeset(ui, repo, opts)
4767 for node in nodes:
4767 for node in nodes:
4768 displayer.show(repo[node])
4768 displayer.show(repo[node])
4769 displayer.close()
4769 displayer.close()
4770 return 0
4770 return 0
4771
4771
4772 try:
4772 try:
4773 # ui.forcemerge is an internal variable, do not document
4773 # ui.forcemerge is an internal variable, do not document
4774 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4774 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4775 return hg.merge(repo, node, force=opts.get('force'))
4775 return hg.merge(repo, node, force=opts.get('force'))
4776 finally:
4776 finally:
4777 ui.setconfig('ui', 'forcemerge', '', 'merge')
4777 ui.setconfig('ui', 'forcemerge', '', 'merge')
4778
4778
4779 @command('outgoing|out',
4779 @command('outgoing|out',
4780 [('f', 'force', None, _('run even when the destination is unrelated')),
4780 [('f', 'force', None, _('run even when the destination is unrelated')),
4781 ('r', 'rev', [],
4781 ('r', 'rev', [],
4782 _('a changeset intended to be included in the destination'), _('REV')),
4782 _('a changeset intended to be included in the destination'), _('REV')),
4783 ('n', 'newest-first', None, _('show newest record first')),
4783 ('n', 'newest-first', None, _('show newest record first')),
4784 ('B', 'bookmarks', False, _('compare bookmarks')),
4784 ('B', 'bookmarks', False, _('compare bookmarks')),
4785 ('b', 'branch', [], _('a specific branch you would like to push'),
4785 ('b', 'branch', [], _('a specific branch you would like to push'),
4786 _('BRANCH')),
4786 _('BRANCH')),
4787 ] + logopts + remoteopts + subrepoopts,
4787 ] + logopts + remoteopts + subrepoopts,
4788 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4788 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4789 def outgoing(ui, repo, dest=None, **opts):
4789 def outgoing(ui, repo, dest=None, **opts):
4790 """show changesets not found in the destination
4790 """show changesets not found in the destination
4791
4791
4792 Show changesets not found in the specified destination repository
4792 Show changesets not found in the specified destination repository
4793 or the default push location. These are the changesets that would
4793 or the default push location. These are the changesets that would
4794 be pushed if a push was requested.
4794 be pushed if a push was requested.
4795
4795
4796 See pull for details of valid destination formats.
4796 See pull for details of valid destination formats.
4797
4797
4798 .. container:: verbose
4798 .. container:: verbose
4799
4799
4800 With -B/--bookmarks, the result of bookmark comparison between
4800 With -B/--bookmarks, the result of bookmark comparison between
4801 local and remote repositories is displayed. With -v/--verbose,
4801 local and remote repositories is displayed. With -v/--verbose,
4802 status is also displayed for each bookmark like below::
4802 status is also displayed for each bookmark like below::
4803
4803
4804 BM1 01234567890a added
4804 BM1 01234567890a added
4805 BM2 deleted
4805 BM2 deleted
4806 BM3 234567890abc advanced
4806 BM3 234567890abc advanced
4807 BM4 34567890abcd diverged
4807 BM4 34567890abcd diverged
4808 BM5 4567890abcde changed
4808 BM5 4567890abcde changed
4809
4809
4810 The action taken when pushing depends on the
4810 The action taken when pushing depends on the
4811 status of each bookmark:
4811 status of each bookmark:
4812
4812
4813 :``added``: push with ``-B`` will create it
4813 :``added``: push with ``-B`` will create it
4814 :``deleted``: push with ``-B`` will delete it
4814 :``deleted``: push with ``-B`` will delete it
4815 :``advanced``: push will update it
4815 :``advanced``: push will update it
4816 :``diverged``: push with ``-B`` will update it
4816 :``diverged``: push with ``-B`` will update it
4817 :``changed``: push with ``-B`` will update it
4817 :``changed``: push with ``-B`` will update it
4818
4818
4819 From the point of view of pushing behavior, bookmarks
4819 From the point of view of pushing behavior, bookmarks
4820 existing only in the remote repository are treated as
4820 existing only in the remote repository are treated as
4821 ``deleted``, even if it is in fact added remotely.
4821 ``deleted``, even if it is in fact added remotely.
4822
4822
4823 Returns 0 if there are outgoing changes, 1 otherwise.
4823 Returns 0 if there are outgoing changes, 1 otherwise.
4824 """
4824 """
4825 if opts.get('graph'):
4825 if opts.get('graph'):
4826 cmdutil.checkunsupportedgraphflags([], opts)
4826 cmdutil.checkunsupportedgraphflags([], opts)
4827 o, other = hg._outgoing(ui, repo, dest, opts)
4827 o, other = hg._outgoing(ui, repo, dest, opts)
4828 if not o:
4828 if not o:
4829 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4829 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4830 return
4830 return
4831
4831
4832 revdag = cmdutil.graphrevs(repo, o, opts)
4832 revdag = cmdutil.graphrevs(repo, o, opts)
4833 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4833 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4834 showparents = [ctx.node() for ctx in repo[None].parents()]
4834 showparents = [ctx.node() for ctx in repo[None].parents()]
4835 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4835 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4836 graphmod.asciiedges)
4836 graphmod.asciiedges)
4837 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4837 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4838 return 0
4838 return 0
4839
4839
4840 if opts.get('bookmarks'):
4840 if opts.get('bookmarks'):
4841 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4841 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4842 dest, branches = hg.parseurl(dest, opts.get('branch'))
4842 dest, branches = hg.parseurl(dest, opts.get('branch'))
4843 other = hg.peer(repo, opts, dest)
4843 other = hg.peer(repo, opts, dest)
4844 if 'bookmarks' not in other.listkeys('namespaces'):
4844 if 'bookmarks' not in other.listkeys('namespaces'):
4845 ui.warn(_("remote doesn't support bookmarks\n"))
4845 ui.warn(_("remote doesn't support bookmarks\n"))
4846 return 0
4846 return 0
4847 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4847 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4848 return bookmarks.outgoing(ui, repo, other)
4848 return bookmarks.outgoing(ui, repo, other)
4849
4849
4850 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4850 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4851 try:
4851 try:
4852 return hg.outgoing(ui, repo, dest, opts)
4852 return hg.outgoing(ui, repo, dest, opts)
4853 finally:
4853 finally:
4854 del repo._subtoppath
4854 del repo._subtoppath
4855
4855
4856 @command('parents',
4856 @command('parents',
4857 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4857 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4858 ] + templateopts,
4858 ] + templateopts,
4859 _('[-r REV] [FILE]'),
4859 _('[-r REV] [FILE]'),
4860 inferrepo=True)
4860 inferrepo=True)
4861 def parents(ui, repo, file_=None, **opts):
4861 def parents(ui, repo, file_=None, **opts):
4862 """show the parents of the working directory or revision (DEPRECATED)
4862 """show the parents of the working directory or revision (DEPRECATED)
4863
4863
4864 Print the working directory's parent revisions. If a revision is
4864 Print the working directory's parent revisions. If a revision is
4865 given via -r/--rev, the parent of that revision will be printed.
4865 given via -r/--rev, the parent of that revision will be printed.
4866 If a file argument is given, the revision in which the file was
4866 If a file argument is given, the revision in which the file was
4867 last changed (before the working directory revision or the
4867 last changed (before the working directory revision or the
4868 argument to --rev if given) is printed.
4868 argument to --rev if given) is printed.
4869
4869
4870 See :hg:`summary` and :hg:`help revsets` for related information.
4870 See :hg:`summary` and :hg:`help revsets` for related information.
4871
4871
4872 Returns 0 on success.
4872 Returns 0 on success.
4873 """
4873 """
4874
4874
4875 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4875 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4876
4876
4877 if file_:
4877 if file_:
4878 m = scmutil.match(ctx, (file_,), opts)
4878 m = scmutil.match(ctx, (file_,), opts)
4879 if m.anypats() or len(m.files()) != 1:
4879 if m.anypats() or len(m.files()) != 1:
4880 raise util.Abort(_('can only specify an explicit filename'))
4880 raise util.Abort(_('can only specify an explicit filename'))
4881 file_ = m.files()[0]
4881 file_ = m.files()[0]
4882 filenodes = []
4882 filenodes = []
4883 for cp in ctx.parents():
4883 for cp in ctx.parents():
4884 if not cp:
4884 if not cp:
4885 continue
4885 continue
4886 try:
4886 try:
4887 filenodes.append(cp.filenode(file_))
4887 filenodes.append(cp.filenode(file_))
4888 except error.LookupError:
4888 except error.LookupError:
4889 pass
4889 pass
4890 if not filenodes:
4890 if not filenodes:
4891 raise util.Abort(_("'%s' not found in manifest!") % file_)
4891 raise util.Abort(_("'%s' not found in manifest!") % file_)
4892 p = []
4892 p = []
4893 for fn in filenodes:
4893 for fn in filenodes:
4894 fctx = repo.filectx(file_, fileid=fn)
4894 fctx = repo.filectx(file_, fileid=fn)
4895 p.append(fctx.node())
4895 p.append(fctx.node())
4896 else:
4896 else:
4897 p = [cp.node() for cp in ctx.parents()]
4897 p = [cp.node() for cp in ctx.parents()]
4898
4898
4899 displayer = cmdutil.show_changeset(ui, repo, opts)
4899 displayer = cmdutil.show_changeset(ui, repo, opts)
4900 for n in p:
4900 for n in p:
4901 if n != nullid:
4901 if n != nullid:
4902 displayer.show(repo[n])
4902 displayer.show(repo[n])
4903 displayer.close()
4903 displayer.close()
4904
4904
4905 @command('paths', [], _('[NAME]'), optionalrepo=True)
4905 @command('paths', [], _('[NAME]'), optionalrepo=True)
4906 def paths(ui, repo, search=None):
4906 def paths(ui, repo, search=None):
4907 """show aliases for remote repositories
4907 """show aliases for remote repositories
4908
4908
4909 Show definition of symbolic path name NAME. If no name is given,
4909 Show definition of symbolic path name NAME. If no name is given,
4910 show definition of all available names.
4910 show definition of all available names.
4911
4911
4912 Option -q/--quiet suppresses all output when searching for NAME
4912 Option -q/--quiet suppresses all output when searching for NAME
4913 and shows only the path names when listing all definitions.
4913 and shows only the path names when listing all definitions.
4914
4914
4915 Path names are defined in the [paths] section of your
4915 Path names are defined in the [paths] section of your
4916 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4916 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4917 repository, ``.hg/hgrc`` is used, too.
4917 repository, ``.hg/hgrc`` is used, too.
4918
4918
4919 The path names ``default`` and ``default-push`` have a special
4919 The path names ``default`` and ``default-push`` have a special
4920 meaning. When performing a push or pull operation, they are used
4920 meaning. When performing a push or pull operation, they are used
4921 as fallbacks if no location is specified on the command-line.
4921 as fallbacks if no location is specified on the command-line.
4922 When ``default-push`` is set, it will be used for push and
4922 When ``default-push`` is set, it will be used for push and
4923 ``default`` will be used for pull; otherwise ``default`` is used
4923 ``default`` will be used for pull; otherwise ``default`` is used
4924 as the fallback for both. When cloning a repository, the clone
4924 as the fallback for both. When cloning a repository, the clone
4925 source is written as ``default`` in ``.hg/hgrc``. Note that
4925 source is written as ``default`` in ``.hg/hgrc``. Note that
4926 ``default`` and ``default-push`` apply to all inbound (e.g.
4926 ``default`` and ``default-push`` apply to all inbound (e.g.
4927 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4927 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4928 :hg:`bundle`) operations.
4928 :hg:`bundle`) operations.
4929
4929
4930 See :hg:`help urls` for more information.
4930 See :hg:`help urls` for more information.
4931
4931
4932 Returns 0 on success.
4932 Returns 0 on success.
4933 """
4933 """
4934 if search:
4934 if search:
4935 for name, path in sorted(ui.paths.iteritems()):
4935 for name, path in sorted(ui.paths.iteritems()):
4936 if name == search:
4936 if name == search:
4937 ui.status("%s\n" % util.hidepassword(path.loc))
4937 ui.status("%s\n" % util.hidepassword(path.loc))
4938 return
4938 return
4939 if not ui.quiet:
4939 if not ui.quiet:
4940 ui.warn(_("not found!\n"))
4940 ui.warn(_("not found!\n"))
4941 return 1
4941 return 1
4942 else:
4942 else:
4943 for name, path in sorted(ui.paths.iteritems()):
4943 for name, path in sorted(ui.paths.iteritems()):
4944 if ui.quiet:
4944 if ui.quiet:
4945 ui.write("%s\n" % name)
4945 ui.write("%s\n" % name)
4946 else:
4946 else:
4947 ui.write("%s = %s\n" % (name,
4947 ui.write("%s = %s\n" % (name,
4948 util.hidepassword(path.loc)))
4948 util.hidepassword(path.loc)))
4949
4949
4950 @command('phase',
4950 @command('phase',
4951 [('p', 'public', False, _('set changeset phase to public')),
4951 [('p', 'public', False, _('set changeset phase to public')),
4952 ('d', 'draft', False, _('set changeset phase to draft')),
4952 ('d', 'draft', False, _('set changeset phase to draft')),
4953 ('s', 'secret', False, _('set changeset phase to secret')),
4953 ('s', 'secret', False, _('set changeset phase to secret')),
4954 ('f', 'force', False, _('allow to move boundary backward')),
4954 ('f', 'force', False, _('allow to move boundary backward')),
4955 ('r', 'rev', [], _('target revision'), _('REV')),
4955 ('r', 'rev', [], _('target revision'), _('REV')),
4956 ],
4956 ],
4957 _('[-p|-d|-s] [-f] [-r] REV...'))
4957 _('[-p|-d|-s] [-f] [-r] REV...'))
4958 def phase(ui, repo, *revs, **opts):
4958 def phase(ui, repo, *revs, **opts):
4959 """set or show the current phase name
4959 """set or show the current phase name
4960
4960
4961 With no argument, show the phase name of specified revisions.
4961 With no argument, show the phase name of specified revisions.
4962
4962
4963 With one of -p/--public, -d/--draft or -s/--secret, change the
4963 With one of -p/--public, -d/--draft or -s/--secret, change the
4964 phase value of the specified revisions.
4964 phase value of the specified revisions.
4965
4965
4966 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4966 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4967 lower phase to an higher phase. Phases are ordered as follows::
4967 lower phase to an higher phase. Phases are ordered as follows::
4968
4968
4969 public < draft < secret
4969 public < draft < secret
4970
4970
4971 Returns 0 on success, 1 if no phases were changed or some could not
4971 Returns 0 on success, 1 if no phases were changed or some could not
4972 be changed.
4972 be changed.
4973 """
4973 """
4974 # search for a unique phase argument
4974 # search for a unique phase argument
4975 targetphase = None
4975 targetphase = None
4976 for idx, name in enumerate(phases.phasenames):
4976 for idx, name in enumerate(phases.phasenames):
4977 if opts[name]:
4977 if opts[name]:
4978 if targetphase is not None:
4978 if targetphase is not None:
4979 raise util.Abort(_('only one phase can be specified'))
4979 raise util.Abort(_('only one phase can be specified'))
4980 targetphase = idx
4980 targetphase = idx
4981
4981
4982 # look for specified revision
4982 # look for specified revision
4983 revs = list(revs)
4983 revs = list(revs)
4984 revs.extend(opts['rev'])
4984 revs.extend(opts['rev'])
4985 if not revs:
4985 if not revs:
4986 raise util.Abort(_('no revisions specified'))
4986 raise util.Abort(_('no revisions specified'))
4987
4987
4988 revs = scmutil.revrange(repo, revs)
4988 revs = scmutil.revrange(repo, revs)
4989
4989
4990 lock = None
4990 lock = None
4991 ret = 0
4991 ret = 0
4992 if targetphase is None:
4992 if targetphase is None:
4993 # display
4993 # display
4994 for r in revs:
4994 for r in revs:
4995 ctx = repo[r]
4995 ctx = repo[r]
4996 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4996 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4997 else:
4997 else:
4998 tr = None
4998 tr = None
4999 lock = repo.lock()
4999 lock = repo.lock()
5000 try:
5000 try:
5001 tr = repo.transaction("phase")
5001 tr = repo.transaction("phase")
5002 # set phase
5002 # set phase
5003 if not revs:
5003 if not revs:
5004 raise util.Abort(_('empty revision set'))
5004 raise util.Abort(_('empty revision set'))
5005 nodes = [repo[r].node() for r in revs]
5005 nodes = [repo[r].node() for r in revs]
5006 # moving revision from public to draft may hide them
5006 # moving revision from public to draft may hide them
5007 # We have to check result on an unfiltered repository
5007 # We have to check result on an unfiltered repository
5008 unfi = repo.unfiltered()
5008 unfi = repo.unfiltered()
5009 getphase = unfi._phasecache.phase
5009 getphase = unfi._phasecache.phase
5010 olddata = [getphase(unfi, r) for r in unfi]
5010 olddata = [getphase(unfi, r) for r in unfi]
5011 phases.advanceboundary(repo, tr, targetphase, nodes)
5011 phases.advanceboundary(repo, tr, targetphase, nodes)
5012 if opts['force']:
5012 if opts['force']:
5013 phases.retractboundary(repo, tr, targetphase, nodes)
5013 phases.retractboundary(repo, tr, targetphase, nodes)
5014 tr.close()
5014 tr.close()
5015 finally:
5015 finally:
5016 if tr is not None:
5016 if tr is not None:
5017 tr.release()
5017 tr.release()
5018 lock.release()
5018 lock.release()
5019 getphase = unfi._phasecache.phase
5019 getphase = unfi._phasecache.phase
5020 newdata = [getphase(unfi, r) for r in unfi]
5020 newdata = [getphase(unfi, r) for r in unfi]
5021 changes = sum(newdata[r] != olddata[r] for r in unfi)
5021 changes = sum(newdata[r] != olddata[r] for r in unfi)
5022 cl = unfi.changelog
5022 cl = unfi.changelog
5023 rejected = [n for n in nodes
5023 rejected = [n for n in nodes
5024 if newdata[cl.rev(n)] < targetphase]
5024 if newdata[cl.rev(n)] < targetphase]
5025 if rejected:
5025 if rejected:
5026 ui.warn(_('cannot move %i changesets to a higher '
5026 ui.warn(_('cannot move %i changesets to a higher '
5027 'phase, use --force\n') % len(rejected))
5027 'phase, use --force\n') % len(rejected))
5028 ret = 1
5028 ret = 1
5029 if changes:
5029 if changes:
5030 msg = _('phase changed for %i changesets\n') % changes
5030 msg = _('phase changed for %i changesets\n') % changes
5031 if ret:
5031 if ret:
5032 ui.status(msg)
5032 ui.status(msg)
5033 else:
5033 else:
5034 ui.note(msg)
5034 ui.note(msg)
5035 else:
5035 else:
5036 ui.warn(_('no phases changed\n'))
5036 ui.warn(_('no phases changed\n'))
5037 ret = 1
5037 ret = 1
5038 return ret
5038 return ret
5039
5039
5040 def postincoming(ui, repo, modheads, optupdate, checkout):
5040 def postincoming(ui, repo, modheads, optupdate, checkout):
5041 if modheads == 0:
5041 if modheads == 0:
5042 return
5042 return
5043 if optupdate:
5043 if optupdate:
5044 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5044 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5045 try:
5045 try:
5046 ret = hg.update(repo, checkout)
5046 ret = hg.update(repo, checkout)
5047 except util.Abort, inst:
5047 except util.Abort, inst:
5048 ui.warn(_("not updating: %s\n") % str(inst))
5048 ui.warn(_("not updating: %s\n") % str(inst))
5049 if inst.hint:
5049 if inst.hint:
5050 ui.warn(_("(%s)\n") % inst.hint)
5050 ui.warn(_("(%s)\n") % inst.hint)
5051 return 0
5051 return 0
5052 if not ret and not checkout:
5052 if not ret and not checkout:
5053 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5053 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5054 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5054 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5055 return ret
5055 return ret
5056 if modheads > 1:
5056 if modheads > 1:
5057 currentbranchheads = len(repo.branchheads())
5057 currentbranchheads = len(repo.branchheads())
5058 if currentbranchheads == modheads:
5058 if currentbranchheads == modheads:
5059 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5059 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5060 elif currentbranchheads > 1:
5060 elif currentbranchheads > 1:
5061 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5061 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5062 "merge)\n"))
5062 "merge)\n"))
5063 else:
5063 else:
5064 ui.status(_("(run 'hg heads' to see heads)\n"))
5064 ui.status(_("(run 'hg heads' to see heads)\n"))
5065 else:
5065 else:
5066 ui.status(_("(run 'hg update' to get a working copy)\n"))
5066 ui.status(_("(run 'hg update' to get a working copy)\n"))
5067
5067
5068 @command('^pull',
5068 @command('^pull',
5069 [('u', 'update', None,
5069 [('u', 'update', None,
5070 _('update to new branch head if changesets were pulled')),
5070 _('update to new branch head if changesets were pulled')),
5071 ('f', 'force', None, _('run even when remote repository is unrelated')),
5071 ('f', 'force', None, _('run even when remote repository is unrelated')),
5072 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5072 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5073 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5073 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5074 ('b', 'branch', [], _('a specific branch you would like to pull'),
5074 ('b', 'branch', [], _('a specific branch you would like to pull'),
5075 _('BRANCH')),
5075 _('BRANCH')),
5076 ] + remoteopts,
5076 ] + remoteopts,
5077 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5077 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5078 def pull(ui, repo, source="default", **opts):
5078 def pull(ui, repo, source="default", **opts):
5079 """pull changes from the specified source
5079 """pull changes from the specified source
5080
5080
5081 Pull changes from a remote repository to a local one.
5081 Pull changes from a remote repository to a local one.
5082
5082
5083 This finds all changes from the repository at the specified path
5083 This finds all changes from the repository at the specified path
5084 or URL and adds them to a local repository (the current one unless
5084 or URL and adds them to a local repository (the current one unless
5085 -R is specified). By default, this does not update the copy of the
5085 -R is specified). By default, this does not update the copy of the
5086 project in the working directory.
5086 project in the working directory.
5087
5087
5088 Use :hg:`incoming` if you want to see what would have been added
5088 Use :hg:`incoming` if you want to see what would have been added
5089 by a pull at the time you issued this command. If you then decide
5089 by a pull at the time you issued this command. If you then decide
5090 to add those changes to the repository, you should use :hg:`pull
5090 to add those changes to the repository, you should use :hg:`pull
5091 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5091 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5092
5092
5093 If SOURCE is omitted, the 'default' path will be used.
5093 If SOURCE is omitted, the 'default' path will be used.
5094 See :hg:`help urls` for more information.
5094 See :hg:`help urls` for more information.
5095
5095
5096 Returns 0 on success, 1 if an update had unresolved files.
5096 Returns 0 on success, 1 if an update had unresolved files.
5097 """
5097 """
5098 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5098 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5099 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5099 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5100 other = hg.peer(repo, opts, source)
5100 other = hg.peer(repo, opts, source)
5101 try:
5101 try:
5102 revs, checkout = hg.addbranchrevs(repo, other, branches,
5102 revs, checkout = hg.addbranchrevs(repo, other, branches,
5103 opts.get('rev'))
5103 opts.get('rev'))
5104
5104
5105 remotebookmarks = other.listkeys('bookmarks')
5105 remotebookmarks = other.listkeys('bookmarks')
5106
5106
5107 if opts.get('bookmark'):
5107 if opts.get('bookmark'):
5108 if not revs:
5108 if not revs:
5109 revs = []
5109 revs = []
5110 for b in opts['bookmark']:
5110 for b in opts['bookmark']:
5111 if b not in remotebookmarks:
5111 if b not in remotebookmarks:
5112 raise util.Abort(_('remote bookmark %s not found!') % b)
5112 raise util.Abort(_('remote bookmark %s not found!') % b)
5113 revs.append(remotebookmarks[b])
5113 revs.append(remotebookmarks[b])
5114
5114
5115 if revs:
5115 if revs:
5116 try:
5116 try:
5117 revs = [other.lookup(rev) for rev in revs]
5117 revs = [other.lookup(rev) for rev in revs]
5118 except error.CapabilityError:
5118 except error.CapabilityError:
5119 err = _("other repository doesn't support revision lookup, "
5119 err = _("other repository doesn't support revision lookup, "
5120 "so a rev cannot be specified.")
5120 "so a rev cannot be specified.")
5121 raise util.Abort(err)
5121 raise util.Abort(err)
5122
5122
5123 modheads = exchange.pull(repo, other, heads=revs,
5123 modheads = exchange.pull(repo, other, heads=revs,
5124 force=opts.get('force'),
5124 force=opts.get('force'),
5125 bookmarks=opts.get('bookmark', ())).cgresult
5125 bookmarks=opts.get('bookmark', ())).cgresult
5126 if checkout:
5126 if checkout:
5127 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5127 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5128 repo._subtoppath = source
5128 repo._subtoppath = source
5129 try:
5129 try:
5130 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5130 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5131
5131
5132 finally:
5132 finally:
5133 del repo._subtoppath
5133 del repo._subtoppath
5134
5134
5135 finally:
5135 finally:
5136 other.close()
5136 other.close()
5137 return ret
5137 return ret
5138
5138
5139 @command('^push',
5139 @command('^push',
5140 [('f', 'force', None, _('force push')),
5140 [('f', 'force', None, _('force push')),
5141 ('r', 'rev', [],
5141 ('r', 'rev', [],
5142 _('a changeset intended to be included in the destination'),
5142 _('a changeset intended to be included in the destination'),
5143 _('REV')),
5143 _('REV')),
5144 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5144 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5145 ('b', 'branch', [],
5145 ('b', 'branch', [],
5146 _('a specific branch you would like to push'), _('BRANCH')),
5146 _('a specific branch you would like to push'), _('BRANCH')),
5147 ('', 'new-branch', False, _('allow pushing a new branch')),
5147 ('', 'new-branch', False, _('allow pushing a new branch')),
5148 ] + remoteopts,
5148 ] + remoteopts,
5149 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5149 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5150 def push(ui, repo, dest=None, **opts):
5150 def push(ui, repo, dest=None, **opts):
5151 """push changes to the specified destination
5151 """push changes to the specified destination
5152
5152
5153 Push changesets from the local repository to the specified
5153 Push changesets from the local repository to the specified
5154 destination.
5154 destination.
5155
5155
5156 This operation is symmetrical to pull: it is identical to a pull
5156 This operation is symmetrical to pull: it is identical to a pull
5157 in the destination repository from the current one.
5157 in the destination repository from the current one.
5158
5158
5159 By default, push will not allow creation of new heads at the
5159 By default, push will not allow creation of new heads at the
5160 destination, since multiple heads would make it unclear which head
5160 destination, since multiple heads would make it unclear which head
5161 to use. In this situation, it is recommended to pull and merge
5161 to use. In this situation, it is recommended to pull and merge
5162 before pushing.
5162 before pushing.
5163
5163
5164 Use --new-branch if you want to allow push to create a new named
5164 Use --new-branch if you want to allow push to create a new named
5165 branch that is not present at the destination. This allows you to
5165 branch that is not present at the destination. This allows you to
5166 only create a new branch without forcing other changes.
5166 only create a new branch without forcing other changes.
5167
5167
5168 .. note::
5168 .. note::
5169
5169
5170 Extra care should be taken with the -f/--force option,
5170 Extra care should be taken with the -f/--force option,
5171 which will push all new heads on all branches, an action which will
5171 which will push all new heads on all branches, an action which will
5172 almost always cause confusion for collaborators.
5172 almost always cause confusion for collaborators.
5173
5173
5174 If -r/--rev is used, the specified revision and all its ancestors
5174 If -r/--rev is used, the specified revision and all its ancestors
5175 will be pushed to the remote repository.
5175 will be pushed to the remote repository.
5176
5176
5177 If -B/--bookmark is used, the specified bookmarked revision, its
5177 If -B/--bookmark is used, the specified bookmarked revision, its
5178 ancestors, and the bookmark will be pushed to the remote
5178 ancestors, and the bookmark will be pushed to the remote
5179 repository.
5179 repository.
5180
5180
5181 Please see :hg:`help urls` for important details about ``ssh://``
5181 Please see :hg:`help urls` for important details about ``ssh://``
5182 URLs. If DESTINATION is omitted, a default path will be used.
5182 URLs. If DESTINATION is omitted, a default path will be used.
5183
5183
5184 Returns 0 if push was successful, 1 if nothing to push.
5184 Returns 0 if push was successful, 1 if nothing to push.
5185 """
5185 """
5186
5186
5187 if opts.get('bookmark'):
5187 if opts.get('bookmark'):
5188 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5188 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5189 for b in opts['bookmark']:
5189 for b in opts['bookmark']:
5190 # translate -B options to -r so changesets get pushed
5190 # translate -B options to -r so changesets get pushed
5191 if b in repo._bookmarks:
5191 if b in repo._bookmarks:
5192 opts.setdefault('rev', []).append(b)
5192 opts.setdefault('rev', []).append(b)
5193 else:
5193 else:
5194 # if we try to push a deleted bookmark, translate it to null
5194 # if we try to push a deleted bookmark, translate it to null
5195 # this lets simultaneous -r, -b options continue working
5195 # this lets simultaneous -r, -b options continue working
5196 opts.setdefault('rev', []).append("null")
5196 opts.setdefault('rev', []).append("null")
5197
5197
5198 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5198 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5199 dest, branches = hg.parseurl(dest, opts.get('branch'))
5199 dest, branches = hg.parseurl(dest, opts.get('branch'))
5200 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5200 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5201 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5201 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5202 try:
5202 try:
5203 other = hg.peer(repo, opts, dest)
5203 other = hg.peer(repo, opts, dest)
5204 except error.RepoError:
5204 except error.RepoError:
5205 if dest == "default-push":
5205 if dest == "default-push":
5206 raise util.Abort(_("default repository not configured!"),
5206 raise util.Abort(_("default repository not configured!"),
5207 hint=_('see the "path" section in "hg help config"'))
5207 hint=_('see the "path" section in "hg help config"'))
5208 else:
5208 else:
5209 raise
5209 raise
5210
5210
5211 if revs:
5211 if revs:
5212 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5212 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5213 if not revs:
5213 if not revs:
5214 raise util.Abort(_("specified revisions evaluate to an empty set"),
5214 raise util.Abort(_("specified revisions evaluate to an empty set"),
5215 hint=_("use different revision arguments"))
5215 hint=_("use different revision arguments"))
5216
5216
5217 repo._subtoppath = dest
5217 repo._subtoppath = dest
5218 try:
5218 try:
5219 # push subrepos depth-first for coherent ordering
5219 # push subrepos depth-first for coherent ordering
5220 c = repo['']
5220 c = repo['']
5221 subs = c.substate # only repos that are committed
5221 subs = c.substate # only repos that are committed
5222 for s in sorted(subs):
5222 for s in sorted(subs):
5223 result = c.sub(s).push(opts)
5223 result = c.sub(s).push(opts)
5224 if result == 0:
5224 if result == 0:
5225 return not result
5225 return not result
5226 finally:
5226 finally:
5227 del repo._subtoppath
5227 del repo._subtoppath
5228 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5228 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5229 newbranch=opts.get('new_branch'),
5229 newbranch=opts.get('new_branch'),
5230 bookmarks=opts.get('bookmark', ()))
5230 bookmarks=opts.get('bookmark', ()))
5231
5231
5232 result = not pushop.cgresult
5232 result = not pushop.cgresult
5233
5233
5234 if pushop.bkresult is not None:
5234 if pushop.bkresult is not None:
5235 if pushop.bkresult == 2:
5235 if pushop.bkresult == 2:
5236 result = 2
5236 result = 2
5237 elif not result and pushop.bkresult:
5237 elif not result and pushop.bkresult:
5238 result = 2
5238 result = 2
5239
5239
5240 return result
5240 return result
5241
5241
5242 @command('recover', [])
5242 @command('recover', [])
5243 def recover(ui, repo):
5243 def recover(ui, repo):
5244 """roll back an interrupted transaction
5244 """roll back an interrupted transaction
5245
5245
5246 Recover from an interrupted commit or pull.
5246 Recover from an interrupted commit or pull.
5247
5247
5248 This command tries to fix the repository status after an
5248 This command tries to fix the repository status after an
5249 interrupted operation. It should only be necessary when Mercurial
5249 interrupted operation. It should only be necessary when Mercurial
5250 suggests it.
5250 suggests it.
5251
5251
5252 Returns 0 if successful, 1 if nothing to recover or verify fails.
5252 Returns 0 if successful, 1 if nothing to recover or verify fails.
5253 """
5253 """
5254 if repo.recover():
5254 if repo.recover():
5255 return hg.verify(repo)
5255 return hg.verify(repo)
5256 return 1
5256 return 1
5257
5257
5258 @command('^remove|rm',
5258 @command('^remove|rm',
5259 [('A', 'after', None, _('record delete for missing files')),
5259 [('A', 'after', None, _('record delete for missing files')),
5260 ('f', 'force', None,
5260 ('f', 'force', None,
5261 _('remove (and delete) file even if added or modified')),
5261 _('remove (and delete) file even if added or modified')),
5262 ] + subrepoopts + walkopts,
5262 ] + subrepoopts + walkopts,
5263 _('[OPTION]... FILE...'),
5263 _('[OPTION]... FILE...'),
5264 inferrepo=True)
5264 inferrepo=True)
5265 def remove(ui, repo, *pats, **opts):
5265 def remove(ui, repo, *pats, **opts):
5266 """remove the specified files on the next commit
5266 """remove the specified files on the next commit
5267
5267
5268 Schedule the indicated files for removal from the current branch.
5268 Schedule the indicated files for removal from the current branch.
5269
5269
5270 This command schedules the files to be removed at the next commit.
5270 This command schedules the files to be removed at the next commit.
5271 To undo a remove before that, see :hg:`revert`. To undo added
5271 To undo a remove before that, see :hg:`revert`. To undo added
5272 files, see :hg:`forget`.
5272 files, see :hg:`forget`.
5273
5273
5274 .. container:: verbose
5274 .. container:: verbose
5275
5275
5276 -A/--after can be used to remove only files that have already
5276 -A/--after can be used to remove only files that have already
5277 been deleted, -f/--force can be used to force deletion, and -Af
5277 been deleted, -f/--force can be used to force deletion, and -Af
5278 can be used to remove files from the next revision without
5278 can be used to remove files from the next revision without
5279 deleting them from the working directory.
5279 deleting them from the working directory.
5280
5280
5281 The following table details the behavior of remove for different
5281 The following table details the behavior of remove for different
5282 file states (columns) and option combinations (rows). The file
5282 file states (columns) and option combinations (rows). The file
5283 states are Added [A], Clean [C], Modified [M] and Missing [!]
5283 states are Added [A], Clean [C], Modified [M] and Missing [!]
5284 (as reported by :hg:`status`). The actions are Warn, Remove
5284 (as reported by :hg:`status`). The actions are Warn, Remove
5285 (from branch) and Delete (from disk):
5285 (from branch) and Delete (from disk):
5286
5286
5287 ========= == == == ==
5287 ========= == == == ==
5288 opt/state A C M !
5288 opt/state A C M !
5289 ========= == == == ==
5289 ========= == == == ==
5290 none W RD W R
5290 none W RD W R
5291 -f R RD RD R
5291 -f R RD RD R
5292 -A W W W R
5292 -A W W W R
5293 -Af R R R R
5293 -Af R R R R
5294 ========= == == == ==
5294 ========= == == == ==
5295
5295
5296 Note that remove never deletes files in Added [A] state from the
5296 Note that remove never deletes files in Added [A] state from the
5297 working directory, not even if option --force is specified.
5297 working directory, not even if option --force is specified.
5298
5298
5299 Returns 0 on success, 1 if any warnings encountered.
5299 Returns 0 on success, 1 if any warnings encountered.
5300 """
5300 """
5301
5301
5302 after, force = opts.get('after'), opts.get('force')
5302 after, force = opts.get('after'), opts.get('force')
5303 if not pats and not after:
5303 if not pats and not after:
5304 raise util.Abort(_('no files specified'))
5304 raise util.Abort(_('no files specified'))
5305
5305
5306 m = scmutil.match(repo[None], pats, opts)
5306 m = scmutil.match(repo[None], pats, opts)
5307 subrepos = opts.get('subrepos')
5307 subrepos = opts.get('subrepos')
5308 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5308 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5309
5309
5310 @command('rename|move|mv',
5310 @command('rename|move|mv',
5311 [('A', 'after', None, _('record a rename that has already occurred')),
5311 [('A', 'after', None, _('record a rename that has already occurred')),
5312 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5312 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5313 ] + walkopts + dryrunopts,
5313 ] + walkopts + dryrunopts,
5314 _('[OPTION]... SOURCE... DEST'))
5314 _('[OPTION]... SOURCE... DEST'))
5315 def rename(ui, repo, *pats, **opts):
5315 def rename(ui, repo, *pats, **opts):
5316 """rename files; equivalent of copy + remove
5316 """rename files; equivalent of copy + remove
5317
5317
5318 Mark dest as copies of sources; mark sources for deletion. If dest
5318 Mark dest as copies of sources; mark sources for deletion. If dest
5319 is a directory, copies are put in that directory. If dest is a
5319 is a directory, copies are put in that directory. If dest is a
5320 file, there can only be one source.
5320 file, there can only be one source.
5321
5321
5322 By default, this command copies the contents of files as they
5322 By default, this command copies the contents of files as they
5323 exist in the working directory. If invoked with -A/--after, the
5323 exist in the working directory. If invoked with -A/--after, the
5324 operation is recorded, but no copying is performed.
5324 operation is recorded, but no copying is performed.
5325
5325
5326 This command takes effect at the next commit. To undo a rename
5326 This command takes effect at the next commit. To undo a rename
5327 before that, see :hg:`revert`.
5327 before that, see :hg:`revert`.
5328
5328
5329 Returns 0 on success, 1 if errors are encountered.
5329 Returns 0 on success, 1 if errors are encountered.
5330 """
5330 """
5331 wlock = repo.wlock(False)
5331 wlock = repo.wlock(False)
5332 try:
5332 try:
5333 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5333 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5334 finally:
5334 finally:
5335 wlock.release()
5335 wlock.release()
5336
5336
5337 @command('resolve',
5337 @command('resolve',
5338 [('a', 'all', None, _('select all unresolved files')),
5338 [('a', 'all', None, _('select all unresolved files')),
5339 ('l', 'list', None, _('list state of files needing merge')),
5339 ('l', 'list', None, _('list state of files needing merge')),
5340 ('m', 'mark', None, _('mark files as resolved')),
5340 ('m', 'mark', None, _('mark files as resolved')),
5341 ('u', 'unmark', None, _('mark files as unresolved')),
5341 ('u', 'unmark', None, _('mark files as unresolved')),
5342 ('n', 'no-status', None, _('hide status prefix'))]
5342 ('n', 'no-status', None, _('hide status prefix'))]
5343 + mergetoolopts + walkopts + formatteropts,
5343 + mergetoolopts + walkopts + formatteropts,
5344 _('[OPTION]... [FILE]...'),
5344 _('[OPTION]... [FILE]...'),
5345 inferrepo=True)
5345 inferrepo=True)
5346 def resolve(ui, repo, *pats, **opts):
5346 def resolve(ui, repo, *pats, **opts):
5347 """redo merges or set/view the merge status of files
5347 """redo merges or set/view the merge status of files
5348
5348
5349 Merges with unresolved conflicts are often the result of
5349 Merges with unresolved conflicts are often the result of
5350 non-interactive merging using the ``internal:merge`` configuration
5350 non-interactive merging using the ``internal:merge`` configuration
5351 setting, or a command-line merge tool like ``diff3``. The resolve
5351 setting, or a command-line merge tool like ``diff3``. The resolve
5352 command is used to manage the files involved in a merge, after
5352 command is used to manage the files involved in a merge, after
5353 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5353 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5354 working directory must have two parents). See :hg:`help
5354 working directory must have two parents). See :hg:`help
5355 merge-tools` for information on configuring merge tools.
5355 merge-tools` for information on configuring merge tools.
5356
5356
5357 The resolve command can be used in the following ways:
5357 The resolve command can be used in the following ways:
5358
5358
5359 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5359 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5360 files, discarding any previous merge attempts. Re-merging is not
5360 files, discarding any previous merge attempts. Re-merging is not
5361 performed for files already marked as resolved. Use ``--all/-a``
5361 performed for files already marked as resolved. Use ``--all/-a``
5362 to select all unresolved files. ``--tool`` can be used to specify
5362 to select all unresolved files. ``--tool`` can be used to specify
5363 the merge tool used for the given files. It overrides the HGMERGE
5363 the merge tool used for the given files. It overrides the HGMERGE
5364 environment variable and your configuration files. Previous file
5364 environment variable and your configuration files. Previous file
5365 contents are saved with a ``.orig`` suffix.
5365 contents are saved with a ``.orig`` suffix.
5366
5366
5367 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5367 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5368 (e.g. after having manually fixed-up the files). The default is
5368 (e.g. after having manually fixed-up the files). The default is
5369 to mark all unresolved files.
5369 to mark all unresolved files.
5370
5370
5371 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5371 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5372 default is to mark all resolved files.
5372 default is to mark all resolved files.
5373
5373
5374 - :hg:`resolve -l`: list files which had or still have conflicts.
5374 - :hg:`resolve -l`: list files which had or still have conflicts.
5375 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5375 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5376
5376
5377 Note that Mercurial will not let you commit files with unresolved
5377 Note that Mercurial will not let you commit files with unresolved
5378 merge conflicts. You must use :hg:`resolve -m ...` before you can
5378 merge conflicts. You must use :hg:`resolve -m ...` before you can
5379 commit after a conflicting merge.
5379 commit after a conflicting merge.
5380
5380
5381 Returns 0 on success, 1 if any files fail a resolve attempt.
5381 Returns 0 on success, 1 if any files fail a resolve attempt.
5382 """
5382 """
5383
5383
5384 all, mark, unmark, show, nostatus = \
5384 all, mark, unmark, show, nostatus = \
5385 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5385 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5386
5386
5387 if (show and (mark or unmark)) or (mark and unmark):
5387 if (show and (mark or unmark)) or (mark and unmark):
5388 raise util.Abort(_("too many options specified"))
5388 raise util.Abort(_("too many options specified"))
5389 if pats and all:
5389 if pats and all:
5390 raise util.Abort(_("can't specify --all and patterns"))
5390 raise util.Abort(_("can't specify --all and patterns"))
5391 if not (all or pats or show or mark or unmark):
5391 if not (all or pats or show or mark or unmark):
5392 raise util.Abort(_('no files or directories specified'),
5392 raise util.Abort(_('no files or directories specified'),
5393 hint=('use --all to remerge all files'))
5393 hint=('use --all to remerge all files'))
5394
5394
5395 if show:
5395 if show:
5396 fm = ui.formatter('resolve', opts)
5396 fm = ui.formatter('resolve', opts)
5397 ms = mergemod.mergestate(repo)
5397 ms = mergemod.mergestate(repo)
5398 m = scmutil.match(repo[None], pats, opts)
5398 m = scmutil.match(repo[None], pats, opts)
5399 for f in ms:
5399 for f in ms:
5400 if not m(f):
5400 if not m(f):
5401 continue
5401 continue
5402 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5402 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5403 fm.startitem()
5403 fm.startitem()
5404 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5404 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5405 fm.write('path', '%s\n', f, label=l)
5405 fm.write('path', '%s\n', f, label=l)
5406 fm.end()
5406 fm.end()
5407 return 0
5407 return 0
5408
5408
5409 wlock = repo.wlock()
5409 wlock = repo.wlock()
5410 try:
5410 try:
5411 ms = mergemod.mergestate(repo)
5411 ms = mergemod.mergestate(repo)
5412
5412
5413 if not (ms.active() or repo.dirstate.p2() != nullid):
5413 if not (ms.active() or repo.dirstate.p2() != nullid):
5414 raise util.Abort(
5414 raise util.Abort(
5415 _('resolve command not applicable when not merging'))
5415 _('resolve command not applicable when not merging'))
5416
5416
5417 m = scmutil.match(repo[None], pats, opts)
5417 m = scmutil.match(repo[None], pats, opts)
5418 ret = 0
5418 ret = 0
5419 didwork = False
5419 didwork = False
5420
5420
5421 for f in ms:
5421 for f in ms:
5422 if not m(f):
5422 if not m(f):
5423 continue
5423 continue
5424
5424
5425 didwork = True
5425 didwork = True
5426
5426
5427 if mark:
5427 if mark:
5428 ms.mark(f, "r")
5428 ms.mark(f, "r")
5429 elif unmark:
5429 elif unmark:
5430 ms.mark(f, "u")
5430 ms.mark(f, "u")
5431 else:
5431 else:
5432 wctx = repo[None]
5432 wctx = repo[None]
5433
5433
5434 # backup pre-resolve (merge uses .orig for its own purposes)
5434 # backup pre-resolve (merge uses .orig for its own purposes)
5435 a = repo.wjoin(f)
5435 a = repo.wjoin(f)
5436 util.copyfile(a, a + ".resolve")
5436 util.copyfile(a, a + ".resolve")
5437
5437
5438 try:
5438 try:
5439 # resolve file
5439 # resolve file
5440 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5440 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5441 'resolve')
5441 'resolve')
5442 if ms.resolve(f, wctx):
5442 if ms.resolve(f, wctx):
5443 ret = 1
5443 ret = 1
5444 finally:
5444 finally:
5445 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5445 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5446 ms.commit()
5446 ms.commit()
5447
5447
5448 # replace filemerge's .orig file with our resolve file
5448 # replace filemerge's .orig file with our resolve file
5449 util.rename(a + ".resolve", a + ".orig")
5449 util.rename(a + ".resolve", a + ".orig")
5450
5450
5451 ms.commit()
5451 ms.commit()
5452
5452
5453 if not didwork and pats:
5453 if not didwork and pats:
5454 ui.warn(_("arguments do not match paths that need resolving\n"))
5454 ui.warn(_("arguments do not match paths that need resolving\n"))
5455
5455
5456 finally:
5456 finally:
5457 wlock.release()
5457 wlock.release()
5458
5458
5459 # Nudge users into finishing an unfinished operation
5459 # Nudge users into finishing an unfinished operation
5460 if not list(ms.unresolved()):
5460 if not list(ms.unresolved()):
5461 ui.status(_('(no more unresolved files)\n'))
5461 ui.status(_('(no more unresolved files)\n'))
5462
5462
5463 return ret
5463 return ret
5464
5464
5465 @command('revert',
5465 @command('revert',
5466 [('a', 'all', None, _('revert all changes when no arguments given')),
5466 [('a', 'all', None, _('revert all changes when no arguments given')),
5467 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5467 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5468 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5468 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5469 ('C', 'no-backup', None, _('do not save backup copies of files')),
5469 ('C', 'no-backup', None, _('do not save backup copies of files')),
5470 ('i', 'interactive', None, _('interactively select the changes')),
5470 ('i', 'interactive', None, _('interactively select the changes')),
5471 ] + walkopts + dryrunopts,
5471 ] + walkopts + dryrunopts,
5472 _('[OPTION]... [-r REV] [NAME]...'))
5472 _('[OPTION]... [-r REV] [NAME]...'))
5473 def revert(ui, repo, *pats, **opts):
5473 def revert(ui, repo, *pats, **opts):
5474 """restore files to their checkout state
5474 """restore files to their checkout state
5475
5475
5476 .. note::
5476 .. note::
5477
5477
5478 To check out earlier revisions, you should use :hg:`update REV`.
5478 To check out earlier revisions, you should use :hg:`update REV`.
5479 To cancel an uncommitted merge (and lose your changes),
5479 To cancel an uncommitted merge (and lose your changes),
5480 use :hg:`update --clean .`.
5480 use :hg:`update --clean .`.
5481
5481
5482 With no revision specified, revert the specified files or directories
5482 With no revision specified, revert the specified files or directories
5483 to the contents they had in the parent of the working directory.
5483 to the contents they had in the parent of the working directory.
5484 This restores the contents of files to an unmodified
5484 This restores the contents of files to an unmodified
5485 state and unschedules adds, removes, copies, and renames. If the
5485 state and unschedules adds, removes, copies, and renames. If the
5486 working directory has two parents, you must explicitly specify a
5486 working directory has two parents, you must explicitly specify a
5487 revision.
5487 revision.
5488
5488
5489 Using the -r/--rev or -d/--date options, revert the given files or
5489 Using the -r/--rev or -d/--date options, revert the given files or
5490 directories to their states as of a specific revision. Because
5490 directories to their states as of a specific revision. Because
5491 revert does not change the working directory parents, this will
5491 revert does not change the working directory parents, this will
5492 cause these files to appear modified. This can be helpful to "back
5492 cause these files to appear modified. This can be helpful to "back
5493 out" some or all of an earlier change. See :hg:`backout` for a
5493 out" some or all of an earlier change. See :hg:`backout` for a
5494 related method.
5494 related method.
5495
5495
5496 Modified files are saved with a .orig suffix before reverting.
5496 Modified files are saved with a .orig suffix before reverting.
5497 To disable these backups, use --no-backup.
5497 To disable these backups, use --no-backup.
5498
5498
5499 See :hg:`help dates` for a list of formats valid for -d/--date.
5499 See :hg:`help dates` for a list of formats valid for -d/--date.
5500
5500
5501 Returns 0 on success.
5501 Returns 0 on success.
5502 """
5502 """
5503
5503
5504 if opts.get("date"):
5504 if opts.get("date"):
5505 if opts.get("rev"):
5505 if opts.get("rev"):
5506 raise util.Abort(_("you can't specify a revision and a date"))
5506 raise util.Abort(_("you can't specify a revision and a date"))
5507 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5507 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5508
5508
5509 parent, p2 = repo.dirstate.parents()
5509 parent, p2 = repo.dirstate.parents()
5510 if not opts.get('rev') and p2 != nullid:
5510 if not opts.get('rev') and p2 != nullid:
5511 # revert after merge is a trap for new users (issue2915)
5511 # revert after merge is a trap for new users (issue2915)
5512 raise util.Abort(_('uncommitted merge with no revision specified'),
5512 raise util.Abort(_('uncommitted merge with no revision specified'),
5513 hint=_('use "hg update" or see "hg help revert"'))
5513 hint=_('use "hg update" or see "hg help revert"'))
5514
5514
5515 ctx = scmutil.revsingle(repo, opts.get('rev'))
5515 ctx = scmutil.revsingle(repo, opts.get('rev'))
5516
5516
5517 if not pats and not opts.get('all'):
5517 if not pats and not opts.get('all'):
5518 msg = _("no files or directories specified")
5518 msg = _("no files or directories specified")
5519 if p2 != nullid:
5519 if p2 != nullid:
5520 hint = _("uncommitted merge, use --all to discard all changes,"
5520 hint = _("uncommitted merge, use --all to discard all changes,"
5521 " or 'hg update -C .' to abort the merge")
5521 " or 'hg update -C .' to abort the merge")
5522 raise util.Abort(msg, hint=hint)
5522 raise util.Abort(msg, hint=hint)
5523 dirty = util.any(repo.status())
5523 dirty = util.any(repo.status())
5524 node = ctx.node()
5524 node = ctx.node()
5525 if node != parent:
5525 if node != parent:
5526 if dirty:
5526 if dirty:
5527 hint = _("uncommitted changes, use --all to discard all"
5527 hint = _("uncommitted changes, use --all to discard all"
5528 " changes, or 'hg update %s' to update") % ctx.rev()
5528 " changes, or 'hg update %s' to update") % ctx.rev()
5529 else:
5529 else:
5530 hint = _("use --all to revert all files,"
5530 hint = _("use --all to revert all files,"
5531 " or 'hg update %s' to update") % ctx.rev()
5531 " or 'hg update %s' to update") % ctx.rev()
5532 elif dirty:
5532 elif dirty:
5533 hint = _("uncommitted changes, use --all to discard all changes")
5533 hint = _("uncommitted changes, use --all to discard all changes")
5534 else:
5534 else:
5535 hint = _("use --all to revert all files")
5535 hint = _("use --all to revert all files")
5536 raise util.Abort(msg, hint=hint)
5536 raise util.Abort(msg, hint=hint)
5537
5537
5538 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5538 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5539
5539
5540 @command('rollback', dryrunopts +
5540 @command('rollback', dryrunopts +
5541 [('f', 'force', False, _('ignore safety measures'))])
5541 [('f', 'force', False, _('ignore safety measures'))])
5542 def rollback(ui, repo, **opts):
5542 def rollback(ui, repo, **opts):
5543 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5543 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5544
5544
5545 Please use :hg:`commit --amend` instead of rollback to correct
5545 Please use :hg:`commit --amend` instead of rollback to correct
5546 mistakes in the last commit.
5546 mistakes in the last commit.
5547
5547
5548 This command should be used with care. There is only one level of
5548 This command should be used with care. There is only one level of
5549 rollback, and there is no way to undo a rollback. It will also
5549 rollback, and there is no way to undo a rollback. It will also
5550 restore the dirstate at the time of the last transaction, losing
5550 restore the dirstate at the time of the last transaction, losing
5551 any dirstate changes since that time. This command does not alter
5551 any dirstate changes since that time. This command does not alter
5552 the working directory.
5552 the working directory.
5553
5553
5554 Transactions are used to encapsulate the effects of all commands
5554 Transactions are used to encapsulate the effects of all commands
5555 that create new changesets or propagate existing changesets into a
5555 that create new changesets or propagate existing changesets into a
5556 repository.
5556 repository.
5557
5557
5558 .. container:: verbose
5558 .. container:: verbose
5559
5559
5560 For example, the following commands are transactional, and their
5560 For example, the following commands are transactional, and their
5561 effects can be rolled back:
5561 effects can be rolled back:
5562
5562
5563 - commit
5563 - commit
5564 - import
5564 - import
5565 - pull
5565 - pull
5566 - push (with this repository as the destination)
5566 - push (with this repository as the destination)
5567 - unbundle
5567 - unbundle
5568
5568
5569 To avoid permanent data loss, rollback will refuse to rollback a
5569 To avoid permanent data loss, rollback will refuse to rollback a
5570 commit transaction if it isn't checked out. Use --force to
5570 commit transaction if it isn't checked out. Use --force to
5571 override this protection.
5571 override this protection.
5572
5572
5573 This command is not intended for use on public repositories. Once
5573 This command is not intended for use on public repositories. Once
5574 changes are visible for pull by other users, rolling a transaction
5574 changes are visible for pull by other users, rolling a transaction
5575 back locally is ineffective (someone else may already have pulled
5575 back locally is ineffective (someone else may already have pulled
5576 the changes). Furthermore, a race is possible with readers of the
5576 the changes). Furthermore, a race is possible with readers of the
5577 repository; for example an in-progress pull from the repository
5577 repository; for example an in-progress pull from the repository
5578 may fail if a rollback is performed.
5578 may fail if a rollback is performed.
5579
5579
5580 Returns 0 on success, 1 if no rollback data is available.
5580 Returns 0 on success, 1 if no rollback data is available.
5581 """
5581 """
5582 return repo.rollback(dryrun=opts.get('dry_run'),
5582 return repo.rollback(dryrun=opts.get('dry_run'),
5583 force=opts.get('force'))
5583 force=opts.get('force'))
5584
5584
5585 @command('root', [])
5585 @command('root', [])
5586 def root(ui, repo):
5586 def root(ui, repo):
5587 """print the root (top) of the current working directory
5587 """print the root (top) of the current working directory
5588
5588
5589 Print the root directory of the current repository.
5589 Print the root directory of the current repository.
5590
5590
5591 Returns 0 on success.
5591 Returns 0 on success.
5592 """
5592 """
5593 ui.write(repo.root + "\n")
5593 ui.write(repo.root + "\n")
5594
5594
5595 @command('^serve',
5595 @command('^serve',
5596 [('A', 'accesslog', '', _('name of access log file to write to'),
5596 [('A', 'accesslog', '', _('name of access log file to write to'),
5597 _('FILE')),
5597 _('FILE')),
5598 ('d', 'daemon', None, _('run server in background')),
5598 ('d', 'daemon', None, _('run server in background')),
5599 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5599 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5600 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5600 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5601 # use string type, then we can check if something was passed
5601 # use string type, then we can check if something was passed
5602 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5602 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5603 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5603 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5604 _('ADDR')),
5604 _('ADDR')),
5605 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5605 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5606 _('PREFIX')),
5606 _('PREFIX')),
5607 ('n', 'name', '',
5607 ('n', 'name', '',
5608 _('name to show in web pages (default: working directory)'), _('NAME')),
5608 _('name to show in web pages (default: working directory)'), _('NAME')),
5609 ('', 'web-conf', '',
5609 ('', 'web-conf', '',
5610 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5610 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5611 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5611 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5612 _('FILE')),
5612 _('FILE')),
5613 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5613 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5614 ('', 'stdio', None, _('for remote clients')),
5614 ('', 'stdio', None, _('for remote clients')),
5615 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5615 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5616 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5616 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5617 ('', 'style', '', _('template style to use'), _('STYLE')),
5617 ('', 'style', '', _('template style to use'), _('STYLE')),
5618 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5618 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5619 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5619 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5620 _('[OPTION]...'),
5620 _('[OPTION]...'),
5621 optionalrepo=True)
5621 optionalrepo=True)
5622 def serve(ui, repo, **opts):
5622 def serve(ui, repo, **opts):
5623 """start stand-alone webserver
5623 """start stand-alone webserver
5624
5624
5625 Start a local HTTP repository browser and pull server. You can use
5625 Start a local HTTP repository browser and pull server. You can use
5626 this for ad-hoc sharing and browsing of repositories. It is
5626 this for ad-hoc sharing and browsing of repositories. It is
5627 recommended to use a real web server to serve a repository for
5627 recommended to use a real web server to serve a repository for
5628 longer periods of time.
5628 longer periods of time.
5629
5629
5630 Please note that the server does not implement access control.
5630 Please note that the server does not implement access control.
5631 This means that, by default, anybody can read from the server and
5631 This means that, by default, anybody can read from the server and
5632 nobody can write to it by default. Set the ``web.allow_push``
5632 nobody can write to it by default. Set the ``web.allow_push``
5633 option to ``*`` to allow everybody to push to the server. You
5633 option to ``*`` to allow everybody to push to the server. You
5634 should use a real web server if you need to authenticate users.
5634 should use a real web server if you need to authenticate users.
5635
5635
5636 By default, the server logs accesses to stdout and errors to
5636 By default, the server logs accesses to stdout and errors to
5637 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5637 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5638 files.
5638 files.
5639
5639
5640 To have the server choose a free port number to listen on, specify
5640 To have the server choose a free port number to listen on, specify
5641 a port number of 0; in this case, the server will print the port
5641 a port number of 0; in this case, the server will print the port
5642 number it uses.
5642 number it uses.
5643
5643
5644 Returns 0 on success.
5644 Returns 0 on success.
5645 """
5645 """
5646
5646
5647 if opts["stdio"] and opts["cmdserver"]:
5647 if opts["stdio"] and opts["cmdserver"]:
5648 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5648 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5649
5649
5650 if opts["stdio"]:
5650 if opts["stdio"]:
5651 if repo is None:
5651 if repo is None:
5652 raise error.RepoError(_("there is no Mercurial repository here"
5652 raise error.RepoError(_("there is no Mercurial repository here"
5653 " (.hg not found)"))
5653 " (.hg not found)"))
5654 s = sshserver.sshserver(ui, repo)
5654 s = sshserver.sshserver(ui, repo)
5655 s.serve_forever()
5655 s.serve_forever()
5656
5656
5657 if opts["cmdserver"]:
5657 if opts["cmdserver"]:
5658 service = commandserver.createservice(ui, repo, opts)
5658 service = commandserver.createservice(ui, repo, opts)
5659 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5659 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5660
5660
5661 # this way we can check if something was given in the command-line
5661 # this way we can check if something was given in the command-line
5662 if opts.get('port'):
5662 if opts.get('port'):
5663 opts['port'] = util.getport(opts.get('port'))
5663 opts['port'] = util.getport(opts.get('port'))
5664
5664
5665 if repo:
5665 if repo:
5666 baseui = repo.baseui
5666 baseui = repo.baseui
5667 else:
5667 else:
5668 baseui = ui
5668 baseui = ui
5669 optlist = ("name templates style address port prefix ipv6"
5669 optlist = ("name templates style address port prefix ipv6"
5670 " accesslog errorlog certificate encoding")
5670 " accesslog errorlog certificate encoding")
5671 for o in optlist.split():
5671 for o in optlist.split():
5672 val = opts.get(o, '')
5672 val = opts.get(o, '')
5673 if val in (None, ''): # should check against default options instead
5673 if val in (None, ''): # should check against default options instead
5674 continue
5674 continue
5675 baseui.setconfig("web", o, val, 'serve')
5675 baseui.setconfig("web", o, val, 'serve')
5676 if repo and repo.ui != baseui:
5676 if repo and repo.ui != baseui:
5677 repo.ui.setconfig("web", o, val, 'serve')
5677 repo.ui.setconfig("web", o, val, 'serve')
5678
5678
5679 o = opts.get('web_conf') or opts.get('webdir_conf')
5679 o = opts.get('web_conf') or opts.get('webdir_conf')
5680 if not o:
5680 if not o:
5681 if not repo:
5681 if not repo:
5682 raise error.RepoError(_("there is no Mercurial repository"
5682 raise error.RepoError(_("there is no Mercurial repository"
5683 " here (.hg not found)"))
5683 " here (.hg not found)"))
5684 o = repo
5684 o = repo
5685
5685
5686 app = hgweb.hgweb(o, baseui=baseui)
5686 app = hgweb.hgweb(o, baseui=baseui)
5687 service = httpservice(ui, app, opts)
5687 service = httpservice(ui, app, opts)
5688 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5688 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5689
5689
5690 class httpservice(object):
5690 class httpservice(object):
5691 def __init__(self, ui, app, opts):
5691 def __init__(self, ui, app, opts):
5692 self.ui = ui
5692 self.ui = ui
5693 self.app = app
5693 self.app = app
5694 self.opts = opts
5694 self.opts = opts
5695
5695
5696 def init(self):
5696 def init(self):
5697 util.setsignalhandler()
5697 util.setsignalhandler()
5698 self.httpd = hgweb_server.create_server(self.ui, self.app)
5698 self.httpd = hgweb_server.create_server(self.ui, self.app)
5699
5699
5700 if self.opts['port'] and not self.ui.verbose:
5700 if self.opts['port'] and not self.ui.verbose:
5701 return
5701 return
5702
5702
5703 if self.httpd.prefix:
5703 if self.httpd.prefix:
5704 prefix = self.httpd.prefix.strip('/') + '/'
5704 prefix = self.httpd.prefix.strip('/') + '/'
5705 else:
5705 else:
5706 prefix = ''
5706 prefix = ''
5707
5707
5708 port = ':%d' % self.httpd.port
5708 port = ':%d' % self.httpd.port
5709 if port == ':80':
5709 if port == ':80':
5710 port = ''
5710 port = ''
5711
5711
5712 bindaddr = self.httpd.addr
5712 bindaddr = self.httpd.addr
5713 if bindaddr == '0.0.0.0':
5713 if bindaddr == '0.0.0.0':
5714 bindaddr = '*'
5714 bindaddr = '*'
5715 elif ':' in bindaddr: # IPv6
5715 elif ':' in bindaddr: # IPv6
5716 bindaddr = '[%s]' % bindaddr
5716 bindaddr = '[%s]' % bindaddr
5717
5717
5718 fqaddr = self.httpd.fqaddr
5718 fqaddr = self.httpd.fqaddr
5719 if ':' in fqaddr:
5719 if ':' in fqaddr:
5720 fqaddr = '[%s]' % fqaddr
5720 fqaddr = '[%s]' % fqaddr
5721 if self.opts['port']:
5721 if self.opts['port']:
5722 write = self.ui.status
5722 write = self.ui.status
5723 else:
5723 else:
5724 write = self.ui.write
5724 write = self.ui.write
5725 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5725 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5726 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5726 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5727 self.ui.flush() # avoid buffering of status message
5727 self.ui.flush() # avoid buffering of status message
5728
5728
5729 def run(self):
5729 def run(self):
5730 self.httpd.serve_forever()
5730 self.httpd.serve_forever()
5731
5731
5732
5732
5733 @command('^status|st',
5733 @command('^status|st',
5734 [('A', 'all', None, _('show status of all files')),
5734 [('A', 'all', None, _('show status of all files')),
5735 ('m', 'modified', None, _('show only modified files')),
5735 ('m', 'modified', None, _('show only modified files')),
5736 ('a', 'added', None, _('show only added files')),
5736 ('a', 'added', None, _('show only added files')),
5737 ('r', 'removed', None, _('show only removed files')),
5737 ('r', 'removed', None, _('show only removed files')),
5738 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5738 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5739 ('c', 'clean', None, _('show only files without changes')),
5739 ('c', 'clean', None, _('show only files without changes')),
5740 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5740 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5741 ('i', 'ignored', None, _('show only ignored files')),
5741 ('i', 'ignored', None, _('show only ignored files')),
5742 ('n', 'no-status', None, _('hide status prefix')),
5742 ('n', 'no-status', None, _('hide status prefix')),
5743 ('C', 'copies', None, _('show source of copied files')),
5743 ('C', 'copies', None, _('show source of copied files')),
5744 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5744 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5745 ('', 'rev', [], _('show difference from revision'), _('REV')),
5745 ('', 'rev', [], _('show difference from revision'), _('REV')),
5746 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5746 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5747 ] + walkopts + subrepoopts + formatteropts,
5747 ] + walkopts + subrepoopts + formatteropts,
5748 _('[OPTION]... [FILE]...'),
5748 _('[OPTION]... [FILE]...'),
5749 inferrepo=True)
5749 inferrepo=True)
5750 def status(ui, repo, *pats, **opts):
5750 def status(ui, repo, *pats, **opts):
5751 """show changed files in the working directory
5751 """show changed files in the working directory
5752
5752
5753 Show status of files in the repository. If names are given, only
5753 Show status of files in the repository. If names are given, only
5754 files that match are shown. Files that are clean or ignored or
5754 files that match are shown. Files that are clean or ignored or
5755 the source of a copy/move operation, are not listed unless
5755 the source of a copy/move operation, are not listed unless
5756 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5756 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5757 Unless options described with "show only ..." are given, the
5757 Unless options described with "show only ..." are given, the
5758 options -mardu are used.
5758 options -mardu are used.
5759
5759
5760 Option -q/--quiet hides untracked (unknown and ignored) files
5760 Option -q/--quiet hides untracked (unknown and ignored) files
5761 unless explicitly requested with -u/--unknown or -i/--ignored.
5761 unless explicitly requested with -u/--unknown or -i/--ignored.
5762
5762
5763 .. note::
5763 .. note::
5764
5764
5765 status may appear to disagree with diff if permissions have
5765 status may appear to disagree with diff if permissions have
5766 changed or a merge has occurred. The standard diff format does
5766 changed or a merge has occurred. The standard diff format does
5767 not report permission changes and diff only reports changes
5767 not report permission changes and diff only reports changes
5768 relative to one merge parent.
5768 relative to one merge parent.
5769
5769
5770 If one revision is given, it is used as the base revision.
5770 If one revision is given, it is used as the base revision.
5771 If two revisions are given, the differences between them are
5771 If two revisions are given, the differences between them are
5772 shown. The --change option can also be used as a shortcut to list
5772 shown. The --change option can also be used as a shortcut to list
5773 the changed files of a revision from its first parent.
5773 the changed files of a revision from its first parent.
5774
5774
5775 The codes used to show the status of files are::
5775 The codes used to show the status of files are::
5776
5776
5777 M = modified
5777 M = modified
5778 A = added
5778 A = added
5779 R = removed
5779 R = removed
5780 C = clean
5780 C = clean
5781 ! = missing (deleted by non-hg command, but still tracked)
5781 ! = missing (deleted by non-hg command, but still tracked)
5782 ? = not tracked
5782 ? = not tracked
5783 I = ignored
5783 I = ignored
5784 = origin of the previous file (with --copies)
5784 = origin of the previous file (with --copies)
5785
5785
5786 .. container:: verbose
5786 .. container:: verbose
5787
5787
5788 Examples:
5788 Examples:
5789
5789
5790 - show changes in the working directory relative to a
5790 - show changes in the working directory relative to a
5791 changeset::
5791 changeset::
5792
5792
5793 hg status --rev 9353
5793 hg status --rev 9353
5794
5794
5795 - show changes in the working directory relative to the
5795 - show changes in the working directory relative to the
5796 current directory (see :hg:`help patterns` for more information)::
5796 current directory (see :hg:`help patterns` for more information)::
5797
5797
5798 hg status re:
5798 hg status re:
5799
5799
5800 - show all changes including copies in an existing changeset::
5800 - show all changes including copies in an existing changeset::
5801
5801
5802 hg status --copies --change 9353
5802 hg status --copies --change 9353
5803
5803
5804 - get a NUL separated list of added files, suitable for xargs::
5804 - get a NUL separated list of added files, suitable for xargs::
5805
5805
5806 hg status -an0
5806 hg status -an0
5807
5807
5808 Returns 0 on success.
5808 Returns 0 on success.
5809 """
5809 """
5810
5810
5811 revs = opts.get('rev')
5811 revs = opts.get('rev')
5812 change = opts.get('change')
5812 change = opts.get('change')
5813
5813
5814 if revs and change:
5814 if revs and change:
5815 msg = _('cannot specify --rev and --change at the same time')
5815 msg = _('cannot specify --rev and --change at the same time')
5816 raise util.Abort(msg)
5816 raise util.Abort(msg)
5817 elif change:
5817 elif change:
5818 node2 = scmutil.revsingle(repo, change, None).node()
5818 node2 = scmutil.revsingle(repo, change, None).node()
5819 node1 = repo[node2].p1().node()
5819 node1 = repo[node2].p1().node()
5820 else:
5820 else:
5821 node1, node2 = scmutil.revpair(repo, revs)
5821 node1, node2 = scmutil.revpair(repo, revs)
5822
5822
5823 if pats:
5823 if pats:
5824 cwd = repo.getcwd()
5824 cwd = repo.getcwd()
5825 else:
5825 else:
5826 cwd = ''
5826 cwd = ''
5827
5827
5828 if opts.get('print0'):
5828 if opts.get('print0'):
5829 end = '\0'
5829 end = '\0'
5830 else:
5830 else:
5831 end = '\n'
5831 end = '\n'
5832 copy = {}
5832 copy = {}
5833 states = 'modified added removed deleted unknown ignored clean'.split()
5833 states = 'modified added removed deleted unknown ignored clean'.split()
5834 show = [k for k in states if opts.get(k)]
5834 show = [k for k in states if opts.get(k)]
5835 if opts.get('all'):
5835 if opts.get('all'):
5836 show += ui.quiet and (states[:4] + ['clean']) or states
5836 show += ui.quiet and (states[:4] + ['clean']) or states
5837 if not show:
5837 if not show:
5838 if ui.quiet:
5838 if ui.quiet:
5839 show = states[:4]
5839 show = states[:4]
5840 else:
5840 else:
5841 show = states[:5]
5841 show = states[:5]
5842
5842
5843 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5843 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5844 'ignored' in show, 'clean' in show, 'unknown' in show,
5844 'ignored' in show, 'clean' in show, 'unknown' in show,
5845 opts.get('subrepos'))
5845 opts.get('subrepos'))
5846 changestates = zip(states, 'MAR!?IC', stat)
5846 changestates = zip(states, 'MAR!?IC', stat)
5847
5847
5848 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5848 if (opts.get('all') or opts.get('copies')
5849 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5849 copy = copies.pathcopies(repo[node1], repo[node2])
5850 copy = copies.pathcopies(repo[node1], repo[node2])
5850
5851
5851 fm = ui.formatter('status', opts)
5852 fm = ui.formatter('status', opts)
5852 fmt = '%s' + end
5853 fmt = '%s' + end
5853 showchar = not opts.get('no_status')
5854 showchar = not opts.get('no_status')
5854
5855
5855 for state, char, files in changestates:
5856 for state, char, files in changestates:
5856 if state in show:
5857 if state in show:
5857 label = 'status.' + state
5858 label = 'status.' + state
5858 for f in files:
5859 for f in files:
5859 fm.startitem()
5860 fm.startitem()
5860 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5861 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5861 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5862 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5862 if f in copy:
5863 if f in copy:
5863 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5864 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5864 label='status.copied')
5865 label='status.copied')
5865 fm.end()
5866 fm.end()
5866
5867
5867 @command('^summary|sum',
5868 @command('^summary|sum',
5868 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5869 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5869 def summary(ui, repo, **opts):
5870 def summary(ui, repo, **opts):
5870 """summarize working directory state
5871 """summarize working directory state
5871
5872
5872 This generates a brief summary of the working directory state,
5873 This generates a brief summary of the working directory state,
5873 including parents, branch, commit status, and available updates.
5874 including parents, branch, commit status, and available updates.
5874
5875
5875 With the --remote option, this will check the default paths for
5876 With the --remote option, this will check the default paths for
5876 incoming and outgoing changes. This can be time-consuming.
5877 incoming and outgoing changes. This can be time-consuming.
5877
5878
5878 Returns 0 on success.
5879 Returns 0 on success.
5879 """
5880 """
5880
5881
5881 ctx = repo[None]
5882 ctx = repo[None]
5882 parents = ctx.parents()
5883 parents = ctx.parents()
5883 pnode = parents[0].node()
5884 pnode = parents[0].node()
5884 marks = []
5885 marks = []
5885
5886
5886 for p in parents:
5887 for p in parents:
5887 # label with log.changeset (instead of log.parent) since this
5888 # label with log.changeset (instead of log.parent) since this
5888 # shows a working directory parent *changeset*:
5889 # shows a working directory parent *changeset*:
5889 # i18n: column positioning for "hg summary"
5890 # i18n: column positioning for "hg summary"
5890 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5891 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5891 label='log.changeset changeset.%s' % p.phasestr())
5892 label='log.changeset changeset.%s' % p.phasestr())
5892 ui.write(' '.join(p.tags()), label='log.tag')
5893 ui.write(' '.join(p.tags()), label='log.tag')
5893 if p.bookmarks():
5894 if p.bookmarks():
5894 marks.extend(p.bookmarks())
5895 marks.extend(p.bookmarks())
5895 if p.rev() == -1:
5896 if p.rev() == -1:
5896 if not len(repo):
5897 if not len(repo):
5897 ui.write(_(' (empty repository)'))
5898 ui.write(_(' (empty repository)'))
5898 else:
5899 else:
5899 ui.write(_(' (no revision checked out)'))
5900 ui.write(_(' (no revision checked out)'))
5900 ui.write('\n')
5901 ui.write('\n')
5901 if p.description():
5902 if p.description():
5902 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5903 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5903 label='log.summary')
5904 label='log.summary')
5904
5905
5905 branch = ctx.branch()
5906 branch = ctx.branch()
5906 bheads = repo.branchheads(branch)
5907 bheads = repo.branchheads(branch)
5907 # i18n: column positioning for "hg summary"
5908 # i18n: column positioning for "hg summary"
5908 m = _('branch: %s\n') % branch
5909 m = _('branch: %s\n') % branch
5909 if branch != 'default':
5910 if branch != 'default':
5910 ui.write(m, label='log.branch')
5911 ui.write(m, label='log.branch')
5911 else:
5912 else:
5912 ui.status(m, label='log.branch')
5913 ui.status(m, label='log.branch')
5913
5914
5914 if marks:
5915 if marks:
5915 current = repo._bookmarkcurrent
5916 current = repo._bookmarkcurrent
5916 # i18n: column positioning for "hg summary"
5917 # i18n: column positioning for "hg summary"
5917 ui.write(_('bookmarks:'), label='log.bookmark')
5918 ui.write(_('bookmarks:'), label='log.bookmark')
5918 if current is not None:
5919 if current is not None:
5919 if current in marks:
5920 if current in marks:
5920 ui.write(' *' + current, label='bookmarks.current')
5921 ui.write(' *' + current, label='bookmarks.current')
5921 marks.remove(current)
5922 marks.remove(current)
5922 else:
5923 else:
5923 ui.write(' [%s]' % current, label='bookmarks.current')
5924 ui.write(' [%s]' % current, label='bookmarks.current')
5924 for m in marks:
5925 for m in marks:
5925 ui.write(' ' + m, label='log.bookmark')
5926 ui.write(' ' + m, label='log.bookmark')
5926 ui.write('\n', label='log.bookmark')
5927 ui.write('\n', label='log.bookmark')
5927
5928
5928 status = repo.status(unknown=True)
5929 status = repo.status(unknown=True)
5929
5930
5930 c = repo.dirstate.copies()
5931 c = repo.dirstate.copies()
5931 copied, renamed = [], []
5932 copied, renamed = [], []
5932 for d, s in c.iteritems():
5933 for d, s in c.iteritems():
5933 if s in status.removed:
5934 if s in status.removed:
5934 status.removed.remove(s)
5935 status.removed.remove(s)
5935 renamed.append(d)
5936 renamed.append(d)
5936 else:
5937 else:
5937 copied.append(d)
5938 copied.append(d)
5938 if d in status.added:
5939 if d in status.added:
5939 status.added.remove(d)
5940 status.added.remove(d)
5940
5941
5941 ms = mergemod.mergestate(repo)
5942 ms = mergemod.mergestate(repo)
5942 unresolved = [f for f in ms if ms[f] == 'u']
5943 unresolved = [f for f in ms if ms[f] == 'u']
5943
5944
5944 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5945 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5945
5946
5946 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5947 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5947 (ui.label(_('%d added'), 'status.added'), status.added),
5948 (ui.label(_('%d added'), 'status.added'), status.added),
5948 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5949 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5949 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5950 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5950 (ui.label(_('%d copied'), 'status.copied'), copied),
5951 (ui.label(_('%d copied'), 'status.copied'), copied),
5951 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5952 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5952 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5953 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5953 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5954 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5954 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5955 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5955 t = []
5956 t = []
5956 for l, s in labels:
5957 for l, s in labels:
5957 if s:
5958 if s:
5958 t.append(l % len(s))
5959 t.append(l % len(s))
5959
5960
5960 t = ', '.join(t)
5961 t = ', '.join(t)
5961 cleanworkdir = False
5962 cleanworkdir = False
5962
5963
5963 if repo.vfs.exists('updatestate'):
5964 if repo.vfs.exists('updatestate'):
5964 t += _(' (interrupted update)')
5965 t += _(' (interrupted update)')
5965 elif len(parents) > 1:
5966 elif len(parents) > 1:
5966 t += _(' (merge)')
5967 t += _(' (merge)')
5967 elif branch != parents[0].branch():
5968 elif branch != parents[0].branch():
5968 t += _(' (new branch)')
5969 t += _(' (new branch)')
5969 elif (parents[0].closesbranch() and
5970 elif (parents[0].closesbranch() and
5970 pnode in repo.branchheads(branch, closed=True)):
5971 pnode in repo.branchheads(branch, closed=True)):
5971 t += _(' (head closed)')
5972 t += _(' (head closed)')
5972 elif not (status.modified or status.added or status.removed or renamed or
5973 elif not (status.modified or status.added or status.removed or renamed or
5973 copied or subs):
5974 copied or subs):
5974 t += _(' (clean)')
5975 t += _(' (clean)')
5975 cleanworkdir = True
5976 cleanworkdir = True
5976 elif pnode not in bheads:
5977 elif pnode not in bheads:
5977 t += _(' (new branch head)')
5978 t += _(' (new branch head)')
5978
5979
5979 if cleanworkdir:
5980 if cleanworkdir:
5980 # i18n: column positioning for "hg summary"
5981 # i18n: column positioning for "hg summary"
5981 ui.status(_('commit: %s\n') % t.strip())
5982 ui.status(_('commit: %s\n') % t.strip())
5982 else:
5983 else:
5983 # i18n: column positioning for "hg summary"
5984 # i18n: column positioning for "hg summary"
5984 ui.write(_('commit: %s\n') % t.strip())
5985 ui.write(_('commit: %s\n') % t.strip())
5985
5986
5986 # all ancestors of branch heads - all ancestors of parent = new csets
5987 # all ancestors of branch heads - all ancestors of parent = new csets
5987 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5988 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5988 bheads))
5989 bheads))
5989
5990
5990 if new == 0:
5991 if new == 0:
5991 # i18n: column positioning for "hg summary"
5992 # i18n: column positioning for "hg summary"
5992 ui.status(_('update: (current)\n'))
5993 ui.status(_('update: (current)\n'))
5993 elif pnode not in bheads:
5994 elif pnode not in bheads:
5994 # i18n: column positioning for "hg summary"
5995 # i18n: column positioning for "hg summary"
5995 ui.write(_('update: %d new changesets (update)\n') % new)
5996 ui.write(_('update: %d new changesets (update)\n') % new)
5996 else:
5997 else:
5997 # i18n: column positioning for "hg summary"
5998 # i18n: column positioning for "hg summary"
5998 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5999 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5999 (new, len(bheads)))
6000 (new, len(bheads)))
6000
6001
6001 cmdutil.summaryhooks(ui, repo)
6002 cmdutil.summaryhooks(ui, repo)
6002
6003
6003 if opts.get('remote'):
6004 if opts.get('remote'):
6004 needsincoming, needsoutgoing = True, True
6005 needsincoming, needsoutgoing = True, True
6005 else:
6006 else:
6006 needsincoming, needsoutgoing = False, False
6007 needsincoming, needsoutgoing = False, False
6007 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6008 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6008 if i:
6009 if i:
6009 needsincoming = True
6010 needsincoming = True
6010 if o:
6011 if o:
6011 needsoutgoing = True
6012 needsoutgoing = True
6012 if not needsincoming and not needsoutgoing:
6013 if not needsincoming and not needsoutgoing:
6013 return
6014 return
6014
6015
6015 def getincoming():
6016 def getincoming():
6016 source, branches = hg.parseurl(ui.expandpath('default'))
6017 source, branches = hg.parseurl(ui.expandpath('default'))
6017 sbranch = branches[0]
6018 sbranch = branches[0]
6018 try:
6019 try:
6019 other = hg.peer(repo, {}, source)
6020 other = hg.peer(repo, {}, source)
6020 except error.RepoError:
6021 except error.RepoError:
6021 if opts.get('remote'):
6022 if opts.get('remote'):
6022 raise
6023 raise
6023 return source, sbranch, None, None, None
6024 return source, sbranch, None, None, None
6024 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6025 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6025 if revs:
6026 if revs:
6026 revs = [other.lookup(rev) for rev in revs]
6027 revs = [other.lookup(rev) for rev in revs]
6027 ui.debug('comparing with %s\n' % util.hidepassword(source))
6028 ui.debug('comparing with %s\n' % util.hidepassword(source))
6028 repo.ui.pushbuffer()
6029 repo.ui.pushbuffer()
6029 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6030 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6030 repo.ui.popbuffer()
6031 repo.ui.popbuffer()
6031 return source, sbranch, other, commoninc, commoninc[1]
6032 return source, sbranch, other, commoninc, commoninc[1]
6032
6033
6033 if needsincoming:
6034 if needsincoming:
6034 source, sbranch, sother, commoninc, incoming = getincoming()
6035 source, sbranch, sother, commoninc, incoming = getincoming()
6035 else:
6036 else:
6036 source = sbranch = sother = commoninc = incoming = None
6037 source = sbranch = sother = commoninc = incoming = None
6037
6038
6038 def getoutgoing():
6039 def getoutgoing():
6039 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6040 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6040 dbranch = branches[0]
6041 dbranch = branches[0]
6041 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6042 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6042 if source != dest:
6043 if source != dest:
6043 try:
6044 try:
6044 dother = hg.peer(repo, {}, dest)
6045 dother = hg.peer(repo, {}, dest)
6045 except error.RepoError:
6046 except error.RepoError:
6046 if opts.get('remote'):
6047 if opts.get('remote'):
6047 raise
6048 raise
6048 return dest, dbranch, None, None
6049 return dest, dbranch, None, None
6049 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6050 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6050 elif sother is None:
6051 elif sother is None:
6051 # there is no explicit destination peer, but source one is invalid
6052 # there is no explicit destination peer, but source one is invalid
6052 return dest, dbranch, None, None
6053 return dest, dbranch, None, None
6053 else:
6054 else:
6054 dother = sother
6055 dother = sother
6055 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6056 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6056 common = None
6057 common = None
6057 else:
6058 else:
6058 common = commoninc
6059 common = commoninc
6059 if revs:
6060 if revs:
6060 revs = [repo.lookup(rev) for rev in revs]
6061 revs = [repo.lookup(rev) for rev in revs]
6061 repo.ui.pushbuffer()
6062 repo.ui.pushbuffer()
6062 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6063 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6063 commoninc=common)
6064 commoninc=common)
6064 repo.ui.popbuffer()
6065 repo.ui.popbuffer()
6065 return dest, dbranch, dother, outgoing
6066 return dest, dbranch, dother, outgoing
6066
6067
6067 if needsoutgoing:
6068 if needsoutgoing:
6068 dest, dbranch, dother, outgoing = getoutgoing()
6069 dest, dbranch, dother, outgoing = getoutgoing()
6069 else:
6070 else:
6070 dest = dbranch = dother = outgoing = None
6071 dest = dbranch = dother = outgoing = None
6071
6072
6072 if opts.get('remote'):
6073 if opts.get('remote'):
6073 t = []
6074 t = []
6074 if incoming:
6075 if incoming:
6075 t.append(_('1 or more incoming'))
6076 t.append(_('1 or more incoming'))
6076 o = outgoing.missing
6077 o = outgoing.missing
6077 if o:
6078 if o:
6078 t.append(_('%d outgoing') % len(o))
6079 t.append(_('%d outgoing') % len(o))
6079 other = dother or sother
6080 other = dother or sother
6080 if 'bookmarks' in other.listkeys('namespaces'):
6081 if 'bookmarks' in other.listkeys('namespaces'):
6081 counts = bookmarks.summary(repo, other)
6082 counts = bookmarks.summary(repo, other)
6082 if counts[0] > 0:
6083 if counts[0] > 0:
6083 t.append(_('%d incoming bookmarks') % counts[0])
6084 t.append(_('%d incoming bookmarks') % counts[0])
6084 if counts[1] > 0:
6085 if counts[1] > 0:
6085 t.append(_('%d outgoing bookmarks') % counts[1])
6086 t.append(_('%d outgoing bookmarks') % counts[1])
6086
6087
6087 if t:
6088 if t:
6088 # i18n: column positioning for "hg summary"
6089 # i18n: column positioning for "hg summary"
6089 ui.write(_('remote: %s\n') % (', '.join(t)))
6090 ui.write(_('remote: %s\n') % (', '.join(t)))
6090 else:
6091 else:
6091 # i18n: column positioning for "hg summary"
6092 # i18n: column positioning for "hg summary"
6092 ui.status(_('remote: (synced)\n'))
6093 ui.status(_('remote: (synced)\n'))
6093
6094
6094 cmdutil.summaryremotehooks(ui, repo, opts,
6095 cmdutil.summaryremotehooks(ui, repo, opts,
6095 ((source, sbranch, sother, commoninc),
6096 ((source, sbranch, sother, commoninc),
6096 (dest, dbranch, dother, outgoing)))
6097 (dest, dbranch, dother, outgoing)))
6097
6098
6098 @command('tag',
6099 @command('tag',
6099 [('f', 'force', None, _('force tag')),
6100 [('f', 'force', None, _('force tag')),
6100 ('l', 'local', None, _('make the tag local')),
6101 ('l', 'local', None, _('make the tag local')),
6101 ('r', 'rev', '', _('revision to tag'), _('REV')),
6102 ('r', 'rev', '', _('revision to tag'), _('REV')),
6102 ('', 'remove', None, _('remove a tag')),
6103 ('', 'remove', None, _('remove a tag')),
6103 # -l/--local is already there, commitopts cannot be used
6104 # -l/--local is already there, commitopts cannot be used
6104 ('e', 'edit', None, _('invoke editor on commit messages')),
6105 ('e', 'edit', None, _('invoke editor on commit messages')),
6105 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6106 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6106 ] + commitopts2,
6107 ] + commitopts2,
6107 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6108 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6108 def tag(ui, repo, name1, *names, **opts):
6109 def tag(ui, repo, name1, *names, **opts):
6109 """add one or more tags for the current or given revision
6110 """add one or more tags for the current or given revision
6110
6111
6111 Name a particular revision using <name>.
6112 Name a particular revision using <name>.
6112
6113
6113 Tags are used to name particular revisions of the repository and are
6114 Tags are used to name particular revisions of the repository and are
6114 very useful to compare different revisions, to go back to significant
6115 very useful to compare different revisions, to go back to significant
6115 earlier versions or to mark branch points as releases, etc. Changing
6116 earlier versions or to mark branch points as releases, etc. Changing
6116 an existing tag is normally disallowed; use -f/--force to override.
6117 an existing tag is normally disallowed; use -f/--force to override.
6117
6118
6118 If no revision is given, the parent of the working directory is
6119 If no revision is given, the parent of the working directory is
6119 used.
6120 used.
6120
6121
6121 To facilitate version control, distribution, and merging of tags,
6122 To facilitate version control, distribution, and merging of tags,
6122 they are stored as a file named ".hgtags" which is managed similarly
6123 they are stored as a file named ".hgtags" which is managed similarly
6123 to other project files and can be hand-edited if necessary. This
6124 to other project files and can be hand-edited if necessary. This
6124 also means that tagging creates a new commit. The file
6125 also means that tagging creates a new commit. The file
6125 ".hg/localtags" is used for local tags (not shared among
6126 ".hg/localtags" is used for local tags (not shared among
6126 repositories).
6127 repositories).
6127
6128
6128 Tag commits are usually made at the head of a branch. If the parent
6129 Tag commits are usually made at the head of a branch. If the parent
6129 of the working directory is not a branch head, :hg:`tag` aborts; use
6130 of the working directory is not a branch head, :hg:`tag` aborts; use
6130 -f/--force to force the tag commit to be based on a non-head
6131 -f/--force to force the tag commit to be based on a non-head
6131 changeset.
6132 changeset.
6132
6133
6133 See :hg:`help dates` for a list of formats valid for -d/--date.
6134 See :hg:`help dates` for a list of formats valid for -d/--date.
6134
6135
6135 Since tag names have priority over branch names during revision
6136 Since tag names have priority over branch names during revision
6136 lookup, using an existing branch name as a tag name is discouraged.
6137 lookup, using an existing branch name as a tag name is discouraged.
6137
6138
6138 Returns 0 on success.
6139 Returns 0 on success.
6139 """
6140 """
6140 wlock = lock = None
6141 wlock = lock = None
6141 try:
6142 try:
6142 wlock = repo.wlock()
6143 wlock = repo.wlock()
6143 lock = repo.lock()
6144 lock = repo.lock()
6144 rev_ = "."
6145 rev_ = "."
6145 names = [t.strip() for t in (name1,) + names]
6146 names = [t.strip() for t in (name1,) + names]
6146 if len(names) != len(set(names)):
6147 if len(names) != len(set(names)):
6147 raise util.Abort(_('tag names must be unique'))
6148 raise util.Abort(_('tag names must be unique'))
6148 for n in names:
6149 for n in names:
6149 scmutil.checknewlabel(repo, n, 'tag')
6150 scmutil.checknewlabel(repo, n, 'tag')
6150 if not n:
6151 if not n:
6151 raise util.Abort(_('tag names cannot consist entirely of '
6152 raise util.Abort(_('tag names cannot consist entirely of '
6152 'whitespace'))
6153 'whitespace'))
6153 if opts.get('rev') and opts.get('remove'):
6154 if opts.get('rev') and opts.get('remove'):
6154 raise util.Abort(_("--rev and --remove are incompatible"))
6155 raise util.Abort(_("--rev and --remove are incompatible"))
6155 if opts.get('rev'):
6156 if opts.get('rev'):
6156 rev_ = opts['rev']
6157 rev_ = opts['rev']
6157 message = opts.get('message')
6158 message = opts.get('message')
6158 if opts.get('remove'):
6159 if opts.get('remove'):
6159 if opts.get('local'):
6160 if opts.get('local'):
6160 expectedtype = 'local'
6161 expectedtype = 'local'
6161 else:
6162 else:
6162 expectedtype = 'global'
6163 expectedtype = 'global'
6163
6164
6164 for n in names:
6165 for n in names:
6165 if not repo.tagtype(n):
6166 if not repo.tagtype(n):
6166 raise util.Abort(_("tag '%s' does not exist") % n)
6167 raise util.Abort(_("tag '%s' does not exist") % n)
6167 if repo.tagtype(n) != expectedtype:
6168 if repo.tagtype(n) != expectedtype:
6168 if expectedtype == 'global':
6169 if expectedtype == 'global':
6169 raise util.Abort(_("tag '%s' is not a global tag") % n)
6170 raise util.Abort(_("tag '%s' is not a global tag") % n)
6170 else:
6171 else:
6171 raise util.Abort(_("tag '%s' is not a local tag") % n)
6172 raise util.Abort(_("tag '%s' is not a local tag") % n)
6172 rev_ = nullid
6173 rev_ = nullid
6173 if not message:
6174 if not message:
6174 # we don't translate commit messages
6175 # we don't translate commit messages
6175 message = 'Removed tag %s' % ', '.join(names)
6176 message = 'Removed tag %s' % ', '.join(names)
6176 elif not opts.get('force'):
6177 elif not opts.get('force'):
6177 for n in names:
6178 for n in names:
6178 if n in repo.tags():
6179 if n in repo.tags():
6179 raise util.Abort(_("tag '%s' already exists "
6180 raise util.Abort(_("tag '%s' already exists "
6180 "(use -f to force)") % n)
6181 "(use -f to force)") % n)
6181 if not opts.get('local'):
6182 if not opts.get('local'):
6182 p1, p2 = repo.dirstate.parents()
6183 p1, p2 = repo.dirstate.parents()
6183 if p2 != nullid:
6184 if p2 != nullid:
6184 raise util.Abort(_('uncommitted merge'))
6185 raise util.Abort(_('uncommitted merge'))
6185 bheads = repo.branchheads()
6186 bheads = repo.branchheads()
6186 if not opts.get('force') and bheads and p1 not in bheads:
6187 if not opts.get('force') and bheads and p1 not in bheads:
6187 raise util.Abort(_('not at a branch head (use -f to force)'))
6188 raise util.Abort(_('not at a branch head (use -f to force)'))
6188 r = scmutil.revsingle(repo, rev_).node()
6189 r = scmutil.revsingle(repo, rev_).node()
6189
6190
6190 if not message:
6191 if not message:
6191 # we don't translate commit messages
6192 # we don't translate commit messages
6192 message = ('Added tag %s for changeset %s' %
6193 message = ('Added tag %s for changeset %s' %
6193 (', '.join(names), short(r)))
6194 (', '.join(names), short(r)))
6194
6195
6195 date = opts.get('date')
6196 date = opts.get('date')
6196 if date:
6197 if date:
6197 date = util.parsedate(date)
6198 date = util.parsedate(date)
6198
6199
6199 if opts.get('remove'):
6200 if opts.get('remove'):
6200 editform = 'tag.remove'
6201 editform = 'tag.remove'
6201 else:
6202 else:
6202 editform = 'tag.add'
6203 editform = 'tag.add'
6203 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6204 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6204
6205
6205 # don't allow tagging the null rev
6206 # don't allow tagging the null rev
6206 if (not opts.get('remove') and
6207 if (not opts.get('remove') and
6207 scmutil.revsingle(repo, rev_).rev() == nullrev):
6208 scmutil.revsingle(repo, rev_).rev() == nullrev):
6208 raise util.Abort(_("cannot tag null revision"))
6209 raise util.Abort(_("cannot tag null revision"))
6209
6210
6210 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6211 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6211 editor=editor)
6212 editor=editor)
6212 finally:
6213 finally:
6213 release(lock, wlock)
6214 release(lock, wlock)
6214
6215
6215 @command('tags', formatteropts, '')
6216 @command('tags', formatteropts, '')
6216 def tags(ui, repo, **opts):
6217 def tags(ui, repo, **opts):
6217 """list repository tags
6218 """list repository tags
6218
6219
6219 This lists both regular and local tags. When the -v/--verbose
6220 This lists both regular and local tags. When the -v/--verbose
6220 switch is used, a third column "local" is printed for local tags.
6221 switch is used, a third column "local" is printed for local tags.
6221
6222
6222 Returns 0 on success.
6223 Returns 0 on success.
6223 """
6224 """
6224
6225
6225 fm = ui.formatter('tags', opts)
6226 fm = ui.formatter('tags', opts)
6226 hexfunc = fm.hexfunc
6227 hexfunc = fm.hexfunc
6227 tagtype = ""
6228 tagtype = ""
6228
6229
6229 for t, n in reversed(repo.tagslist()):
6230 for t, n in reversed(repo.tagslist()):
6230 hn = hexfunc(n)
6231 hn = hexfunc(n)
6231 label = 'tags.normal'
6232 label = 'tags.normal'
6232 tagtype = ''
6233 tagtype = ''
6233 if repo.tagtype(t) == 'local':
6234 if repo.tagtype(t) == 'local':
6234 label = 'tags.local'
6235 label = 'tags.local'
6235 tagtype = 'local'
6236 tagtype = 'local'
6236
6237
6237 fm.startitem()
6238 fm.startitem()
6238 fm.write('tag', '%s', t, label=label)
6239 fm.write('tag', '%s', t, label=label)
6239 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6240 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6240 fm.condwrite(not ui.quiet, 'rev node', fmt,
6241 fm.condwrite(not ui.quiet, 'rev node', fmt,
6241 repo.changelog.rev(n), hn, label=label)
6242 repo.changelog.rev(n), hn, label=label)
6242 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6243 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6243 tagtype, label=label)
6244 tagtype, label=label)
6244 fm.plain('\n')
6245 fm.plain('\n')
6245 fm.end()
6246 fm.end()
6246
6247
6247 @command('tip',
6248 @command('tip',
6248 [('p', 'patch', None, _('show patch')),
6249 [('p', 'patch', None, _('show patch')),
6249 ('g', 'git', None, _('use git extended diff format')),
6250 ('g', 'git', None, _('use git extended diff format')),
6250 ] + templateopts,
6251 ] + templateopts,
6251 _('[-p] [-g]'))
6252 _('[-p] [-g]'))
6252 def tip(ui, repo, **opts):
6253 def tip(ui, repo, **opts):
6253 """show the tip revision (DEPRECATED)
6254 """show the tip revision (DEPRECATED)
6254
6255
6255 The tip revision (usually just called the tip) is the changeset
6256 The tip revision (usually just called the tip) is the changeset
6256 most recently added to the repository (and therefore the most
6257 most recently added to the repository (and therefore the most
6257 recently changed head).
6258 recently changed head).
6258
6259
6259 If you have just made a commit, that commit will be the tip. If
6260 If you have just made a commit, that commit will be the tip. If
6260 you have just pulled changes from another repository, the tip of
6261 you have just pulled changes from another repository, the tip of
6261 that repository becomes the current tip. The "tip" tag is special
6262 that repository becomes the current tip. The "tip" tag is special
6262 and cannot be renamed or assigned to a different changeset.
6263 and cannot be renamed or assigned to a different changeset.
6263
6264
6264 This command is deprecated, please use :hg:`heads` instead.
6265 This command is deprecated, please use :hg:`heads` instead.
6265
6266
6266 Returns 0 on success.
6267 Returns 0 on success.
6267 """
6268 """
6268 displayer = cmdutil.show_changeset(ui, repo, opts)
6269 displayer = cmdutil.show_changeset(ui, repo, opts)
6269 displayer.show(repo['tip'])
6270 displayer.show(repo['tip'])
6270 displayer.close()
6271 displayer.close()
6271
6272
6272 @command('unbundle',
6273 @command('unbundle',
6273 [('u', 'update', None,
6274 [('u', 'update', None,
6274 _('update to new branch head if changesets were unbundled'))],
6275 _('update to new branch head if changesets were unbundled'))],
6275 _('[-u] FILE...'))
6276 _('[-u] FILE...'))
6276 def unbundle(ui, repo, fname1, *fnames, **opts):
6277 def unbundle(ui, repo, fname1, *fnames, **opts):
6277 """apply one or more changegroup files
6278 """apply one or more changegroup files
6278
6279
6279 Apply one or more compressed changegroup files generated by the
6280 Apply one or more compressed changegroup files generated by the
6280 bundle command.
6281 bundle command.
6281
6282
6282 Returns 0 on success, 1 if an update has unresolved files.
6283 Returns 0 on success, 1 if an update has unresolved files.
6283 """
6284 """
6284 fnames = (fname1,) + fnames
6285 fnames = (fname1,) + fnames
6285
6286
6286 lock = repo.lock()
6287 lock = repo.lock()
6287 try:
6288 try:
6288 for fname in fnames:
6289 for fname in fnames:
6289 f = hg.openpath(ui, fname)
6290 f = hg.openpath(ui, fname)
6290 gen = exchange.readbundle(ui, f, fname)
6291 gen = exchange.readbundle(ui, f, fname)
6291 if isinstance(gen, bundle2.unbundle20):
6292 if isinstance(gen, bundle2.unbundle20):
6292 tr = repo.transaction('unbundle')
6293 tr = repo.transaction('unbundle')
6293 try:
6294 try:
6294 op = bundle2.processbundle(repo, gen, lambda: tr)
6295 op = bundle2.processbundle(repo, gen, lambda: tr)
6295 tr.close()
6296 tr.close()
6296 finally:
6297 finally:
6297 if tr:
6298 if tr:
6298 tr.release()
6299 tr.release()
6299 changes = [r.get('result', 0)
6300 changes = [r.get('result', 0)
6300 for r in op.records['changegroup']]
6301 for r in op.records['changegroup']]
6301 modheads = changegroup.combineresults(changes)
6302 modheads = changegroup.combineresults(changes)
6302 else:
6303 else:
6303 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6304 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6304 'bundle:' + fname)
6305 'bundle:' + fname)
6305 finally:
6306 finally:
6306 lock.release()
6307 lock.release()
6307
6308
6308 return postincoming(ui, repo, modheads, opts.get('update'), None)
6309 return postincoming(ui, repo, modheads, opts.get('update'), None)
6309
6310
6310 @command('^update|up|checkout|co',
6311 @command('^update|up|checkout|co',
6311 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6312 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6312 ('c', 'check', None,
6313 ('c', 'check', None,
6313 _('update across branches if no uncommitted changes')),
6314 _('update across branches if no uncommitted changes')),
6314 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6315 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6315 ('r', 'rev', '', _('revision'), _('REV'))
6316 ('r', 'rev', '', _('revision'), _('REV'))
6316 ] + mergetoolopts,
6317 ] + mergetoolopts,
6317 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6318 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6318 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6319 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6319 tool=None):
6320 tool=None):
6320 """update working directory (or switch revisions)
6321 """update working directory (or switch revisions)
6321
6322
6322 Update the repository's working directory to the specified
6323 Update the repository's working directory to the specified
6323 changeset. If no changeset is specified, update to the tip of the
6324 changeset. If no changeset is specified, update to the tip of the
6324 current named branch and move the current bookmark (see :hg:`help
6325 current named branch and move the current bookmark (see :hg:`help
6325 bookmarks`).
6326 bookmarks`).
6326
6327
6327 Update sets the working directory's parent revision to the specified
6328 Update sets the working directory's parent revision to the specified
6328 changeset (see :hg:`help parents`).
6329 changeset (see :hg:`help parents`).
6329
6330
6330 If the changeset is not a descendant or ancestor of the working
6331 If the changeset is not a descendant or ancestor of the working
6331 directory's parent, the update is aborted. With the -c/--check
6332 directory's parent, the update is aborted. With the -c/--check
6332 option, the working directory is checked for uncommitted changes; if
6333 option, the working directory is checked for uncommitted changes; if
6333 none are found, the working directory is updated to the specified
6334 none are found, the working directory is updated to the specified
6334 changeset.
6335 changeset.
6335
6336
6336 .. container:: verbose
6337 .. container:: verbose
6337
6338
6338 The following rules apply when the working directory contains
6339 The following rules apply when the working directory contains
6339 uncommitted changes:
6340 uncommitted changes:
6340
6341
6341 1. If neither -c/--check nor -C/--clean is specified, and if
6342 1. If neither -c/--check nor -C/--clean is specified, and if
6342 the requested changeset is an ancestor or descendant of
6343 the requested changeset is an ancestor or descendant of
6343 the working directory's parent, the uncommitted changes
6344 the working directory's parent, the uncommitted changes
6344 are merged into the requested changeset and the merged
6345 are merged into the requested changeset and the merged
6345 result is left uncommitted. If the requested changeset is
6346 result is left uncommitted. If the requested changeset is
6346 not an ancestor or descendant (that is, it is on another
6347 not an ancestor or descendant (that is, it is on another
6347 branch), the update is aborted and the uncommitted changes
6348 branch), the update is aborted and the uncommitted changes
6348 are preserved.
6349 are preserved.
6349
6350
6350 2. With the -c/--check option, the update is aborted and the
6351 2. With the -c/--check option, the update is aborted and the
6351 uncommitted changes are preserved.
6352 uncommitted changes are preserved.
6352
6353
6353 3. With the -C/--clean option, uncommitted changes are discarded and
6354 3. With the -C/--clean option, uncommitted changes are discarded and
6354 the working directory is updated to the requested changeset.
6355 the working directory is updated to the requested changeset.
6355
6356
6356 To cancel an uncommitted merge (and lose your changes), use
6357 To cancel an uncommitted merge (and lose your changes), use
6357 :hg:`update --clean .`.
6358 :hg:`update --clean .`.
6358
6359
6359 Use null as the changeset to remove the working directory (like
6360 Use null as the changeset to remove the working directory (like
6360 :hg:`clone -U`).
6361 :hg:`clone -U`).
6361
6362
6362 If you want to revert just one file to an older revision, use
6363 If you want to revert just one file to an older revision, use
6363 :hg:`revert [-r REV] NAME`.
6364 :hg:`revert [-r REV] NAME`.
6364
6365
6365 See :hg:`help dates` for a list of formats valid for -d/--date.
6366 See :hg:`help dates` for a list of formats valid for -d/--date.
6366
6367
6367 Returns 0 on success, 1 if there are unresolved files.
6368 Returns 0 on success, 1 if there are unresolved files.
6368 """
6369 """
6369 if rev and node:
6370 if rev and node:
6370 raise util.Abort(_("please specify just one revision"))
6371 raise util.Abort(_("please specify just one revision"))
6371
6372
6372 if rev is None or rev == '':
6373 if rev is None or rev == '':
6373 rev = node
6374 rev = node
6374
6375
6375 cmdutil.clearunfinished(repo)
6376 cmdutil.clearunfinished(repo)
6376
6377
6377 # with no argument, we also move the current bookmark, if any
6378 # with no argument, we also move the current bookmark, if any
6378 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6379 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6379
6380
6380 # if we defined a bookmark, we have to remember the original bookmark name
6381 # if we defined a bookmark, we have to remember the original bookmark name
6381 brev = rev
6382 brev = rev
6382 rev = scmutil.revsingle(repo, rev, rev).rev()
6383 rev = scmutil.revsingle(repo, rev, rev).rev()
6383
6384
6384 if check and clean:
6385 if check and clean:
6385 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6386 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6386
6387
6387 if date:
6388 if date:
6388 if rev is not None:
6389 if rev is not None:
6389 raise util.Abort(_("you can't specify a revision and a date"))
6390 raise util.Abort(_("you can't specify a revision and a date"))
6390 rev = cmdutil.finddate(ui, repo, date)
6391 rev = cmdutil.finddate(ui, repo, date)
6391
6392
6392 if check:
6393 if check:
6393 cmdutil.bailifchanged(repo, merge=False)
6394 cmdutil.bailifchanged(repo, merge=False)
6394 if rev is None:
6395 if rev is None:
6395 rev = repo[repo[None].branch()].rev()
6396 rev = repo[repo[None].branch()].rev()
6396
6397
6397 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6398 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6398
6399
6399 if clean:
6400 if clean:
6400 ret = hg.clean(repo, rev)
6401 ret = hg.clean(repo, rev)
6401 else:
6402 else:
6402 ret = hg.update(repo, rev)
6403 ret = hg.update(repo, rev)
6403
6404
6404 if not ret and movemarkfrom:
6405 if not ret and movemarkfrom:
6405 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6406 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6406 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6407 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6407 elif brev in repo._bookmarks:
6408 elif brev in repo._bookmarks:
6408 bookmarks.setcurrent(repo, brev)
6409 bookmarks.setcurrent(repo, brev)
6409 ui.status(_("(activating bookmark %s)\n") % brev)
6410 ui.status(_("(activating bookmark %s)\n") % brev)
6410 elif brev:
6411 elif brev:
6411 if repo._bookmarkcurrent:
6412 if repo._bookmarkcurrent:
6412 ui.status(_("(leaving bookmark %s)\n") %
6413 ui.status(_("(leaving bookmark %s)\n") %
6413 repo._bookmarkcurrent)
6414 repo._bookmarkcurrent)
6414 bookmarks.unsetcurrent(repo)
6415 bookmarks.unsetcurrent(repo)
6415
6416
6416 return ret
6417 return ret
6417
6418
6418 @command('verify', [])
6419 @command('verify', [])
6419 def verify(ui, repo):
6420 def verify(ui, repo):
6420 """verify the integrity of the repository
6421 """verify the integrity of the repository
6421
6422
6422 Verify the integrity of the current repository.
6423 Verify the integrity of the current repository.
6423
6424
6424 This will perform an extensive check of the repository's
6425 This will perform an extensive check of the repository's
6425 integrity, validating the hashes and checksums of each entry in
6426 integrity, validating the hashes and checksums of each entry in
6426 the changelog, manifest, and tracked files, as well as the
6427 the changelog, manifest, and tracked files, as well as the
6427 integrity of their crosslinks and indices.
6428 integrity of their crosslinks and indices.
6428
6429
6429 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6430 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6430 for more information about recovery from corruption of the
6431 for more information about recovery from corruption of the
6431 repository.
6432 repository.
6432
6433
6433 Returns 0 on success, 1 if errors are encountered.
6434 Returns 0 on success, 1 if errors are encountered.
6434 """
6435 """
6435 return hg.verify(repo)
6436 return hg.verify(repo)
6436
6437
6437 @command('version', [], norepo=True)
6438 @command('version', [], norepo=True)
6438 def version_(ui):
6439 def version_(ui):
6439 """output version and copyright information"""
6440 """output version and copyright information"""
6440 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6441 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6441 % util.version())
6442 % util.version())
6442 ui.status(_(
6443 ui.status(_(
6443 "(see http://mercurial.selenic.com for more information)\n"
6444 "(see http://mercurial.selenic.com for more information)\n"
6444 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6445 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6445 "This is free software; see the source for copying conditions. "
6446 "This is free software; see the source for copying conditions. "
6446 "There is NO\nwarranty; "
6447 "There is NO\nwarranty; "
6447 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6448 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6448 ))
6449 ))
6449
6450
6450 ui.note(_("\nEnabled extensions:\n\n"))
6451 ui.note(_("\nEnabled extensions:\n\n"))
6451 if ui.verbose:
6452 if ui.verbose:
6452 # format names and versions into columns
6453 # format names and versions into columns
6453 names = []
6454 names = []
6454 vers = []
6455 vers = []
6455 for name, module in extensions.extensions():
6456 for name, module in extensions.extensions():
6456 names.append(name)
6457 names.append(name)
6457 vers.append(extensions.moduleversion(module))
6458 vers.append(extensions.moduleversion(module))
6458 if names:
6459 if names:
6459 maxnamelen = max(len(n) for n in names)
6460 maxnamelen = max(len(n) for n in names)
6460 for i, name in enumerate(names):
6461 for i, name in enumerate(names):
6461 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6462 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,1746 +1,1749 b''
1 The Mercurial system uses a set of configuration files to control
1 The Mercurial system uses a set of configuration files to control
2 aspects of its behavior.
2 aspects of its behavior.
3
3
4 The configuration files use a simple ini-file format. A configuration
4 The configuration files use a simple ini-file format. A configuration
5 file consists of sections, led by a ``[section]`` header and followed
5 file consists of sections, led by a ``[section]`` header and followed
6 by ``name = value`` entries::
6 by ``name = value`` entries::
7
7
8 [ui]
8 [ui]
9 username = Firstname Lastname <firstname.lastname@example.net>
9 username = Firstname Lastname <firstname.lastname@example.net>
10 verbose = True
10 verbose = True
11
11
12 The above entries will be referred to as ``ui.username`` and
12 The above entries will be referred to as ``ui.username`` and
13 ``ui.verbose``, respectively. See the Syntax section below.
13 ``ui.verbose``, respectively. See the Syntax section below.
14
14
15 Files
15 Files
16 =====
16 =====
17
17
18 Mercurial reads configuration data from several files, if they exist.
18 Mercurial reads configuration data from several files, if they exist.
19 These files do not exist by default and you will have to create the
19 These files do not exist by default and you will have to create the
20 appropriate configuration files yourself: global configuration like
20 appropriate configuration files yourself: global configuration like
21 the username setting is typically put into
21 the username setting is typically put into
22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
24
24
25 The names of these files depend on the system on which Mercurial is
25 The names of these files depend on the system on which Mercurial is
26 installed. ``*.rc`` files from a single directory are read in
26 installed. ``*.rc`` files from a single directory are read in
27 alphabetical order, later ones overriding earlier ones. Where multiple
27 alphabetical order, later ones overriding earlier ones. Where multiple
28 paths are given below, settings from earlier paths override later
28 paths are given below, settings from earlier paths override later
29 ones.
29 ones.
30
30
31 .. container:: verbose.unix
31 .. container:: verbose.unix
32
32
33 On Unix, the following files are consulted:
33 On Unix, the following files are consulted:
34
34
35 - ``<repo>/.hg/hgrc`` (per-repository)
35 - ``<repo>/.hg/hgrc`` (per-repository)
36 - ``$HOME/.hgrc`` (per-user)
36 - ``$HOME/.hgrc`` (per-user)
37 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
37 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
38 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
38 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
39 - ``/etc/mercurial/hgrc`` (per-system)
39 - ``/etc/mercurial/hgrc`` (per-system)
40 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
40 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
41 - ``<internal>/default.d/*.rc`` (defaults)
41 - ``<internal>/default.d/*.rc`` (defaults)
42
42
43 .. container:: verbose.windows
43 .. container:: verbose.windows
44
44
45 On Windows, the following files are consulted:
45 On Windows, the following files are consulted:
46
46
47 - ``<repo>/.hg/hgrc`` (per-repository)
47 - ``<repo>/.hg/hgrc`` (per-repository)
48 - ``%USERPROFILE%\.hgrc`` (per-user)
48 - ``%USERPROFILE%\.hgrc`` (per-user)
49 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
49 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
50 - ``%HOME%\.hgrc`` (per-user)
50 - ``%HOME%\.hgrc`` (per-user)
51 - ``%HOME%\Mercurial.ini`` (per-user)
51 - ``%HOME%\Mercurial.ini`` (per-user)
52 - ``<install-dir>\Mercurial.ini`` (per-installation)
52 - ``<install-dir>\Mercurial.ini`` (per-installation)
53 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
53 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
54 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
54 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
55 - ``<internal>/default.d/*.rc`` (defaults)
55 - ``<internal>/default.d/*.rc`` (defaults)
56
56
57 .. note::
57 .. note::
58
58
59 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
59 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
60 is used when running 32-bit Python on 64-bit Windows.
60 is used when running 32-bit Python on 64-bit Windows.
61
61
62 .. container:: verbose.plan9
62 .. container:: verbose.plan9
63
63
64 On Plan9, the following files are consulted:
64 On Plan9, the following files are consulted:
65
65
66 - ``<repo>/.hg/hgrc`` (per-repository)
66 - ``<repo>/.hg/hgrc`` (per-repository)
67 - ``$home/lib/hgrc`` (per-user)
67 - ``$home/lib/hgrc`` (per-user)
68 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
68 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
69 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
69 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
70 - ``/lib/mercurial/hgrc`` (per-system)
70 - ``/lib/mercurial/hgrc`` (per-system)
71 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
71 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
72 - ``<internal>/default.d/*.rc`` (defaults)
72 - ``<internal>/default.d/*.rc`` (defaults)
73
73
74 Per-repository configuration options only apply in a
74 Per-repository configuration options only apply in a
75 particular repository. This file is not version-controlled, and
75 particular repository. This file is not version-controlled, and
76 will not get transferred during a "clone" operation. Options in
76 will not get transferred during a "clone" operation. Options in
77 this file override options in all other configuration files. On
77 this file override options in all other configuration files. On
78 Plan 9 and Unix, most of this file will be ignored if it doesn't
78 Plan 9 and Unix, most of this file will be ignored if it doesn't
79 belong to a trusted user or to a trusted group. See the documentation
79 belong to a trusted user or to a trusted group. See the documentation
80 for the ``[trusted]`` section below for more details.
80 for the ``[trusted]`` section below for more details.
81
81
82 Per-user configuration file(s) are for the user running Mercurial. On
82 Per-user configuration file(s) are for the user running Mercurial. On
83 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
83 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
84 files apply to all Mercurial commands executed by this user in any
84 files apply to all Mercurial commands executed by this user in any
85 directory. Options in these files override per-system and per-installation
85 directory. Options in these files override per-system and per-installation
86 options.
86 options.
87
87
88 Per-installation configuration files are searched for in the
88 Per-installation configuration files are searched for in the
89 directory where Mercurial is installed. ``<install-root>`` is the
89 directory where Mercurial is installed. ``<install-root>`` is the
90 parent directory of the **hg** executable (or symlink) being run. For
90 parent directory of the **hg** executable (or symlink) being run. For
91 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
91 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
92 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
92 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
93 to all Mercurial commands executed by any user in any directory.
93 to all Mercurial commands executed by any user in any directory.
94
94
95 Per-installation configuration files are for the system on
95 Per-installation configuration files are for the system on
96 which Mercurial is running. Options in these files apply to all
96 which Mercurial is running. Options in these files apply to all
97 Mercurial commands executed by any user in any directory. Registry
97 Mercurial commands executed by any user in any directory. Registry
98 keys contain PATH-like strings, every part of which must reference
98 keys contain PATH-like strings, every part of which must reference
99 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
99 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
100 be read. Mercurial checks each of these locations in the specified
100 be read. Mercurial checks each of these locations in the specified
101 order until one or more configuration files are detected.
101 order until one or more configuration files are detected.
102
102
103 Per-system configuration files are for the system on which Mercurial
103 Per-system configuration files are for the system on which Mercurial
104 is running. Options in these files apply to all Mercurial commands
104 is running. Options in these files apply to all Mercurial commands
105 executed by any user in any directory. Options in these files
105 executed by any user in any directory. Options in these files
106 override per-installation options.
106 override per-installation options.
107
107
108 Mercurial comes with some default configuration. The default configuration
108 Mercurial comes with some default configuration. The default configuration
109 files are installed with Mercurial and will be overwritten on upgrades. Default
109 files are installed with Mercurial and will be overwritten on upgrades. Default
110 configuration files should never be edited by users or administrators but can
110 configuration files should never be edited by users or administrators but can
111 be overridden in other configuration files. So far the directory only contains
111 be overridden in other configuration files. So far the directory only contains
112 merge tool configuration but packagers can also put other default configuration
112 merge tool configuration but packagers can also put other default configuration
113 there.
113 there.
114
114
115 Syntax
115 Syntax
116 ======
116 ======
117
117
118 A configuration file consists of sections, led by a ``[section]`` header
118 A configuration file consists of sections, led by a ``[section]`` header
119 and followed by ``name = value`` entries (sometimes called
119 and followed by ``name = value`` entries (sometimes called
120 ``configuration keys``)::
120 ``configuration keys``)::
121
121
122 [spam]
122 [spam]
123 eggs=ham
123 eggs=ham
124 green=
124 green=
125 eggs
125 eggs
126
126
127 Each line contains one entry. If the lines that follow are indented,
127 Each line contains one entry. If the lines that follow are indented,
128 they are treated as continuations of that entry. Leading whitespace is
128 they are treated as continuations of that entry. Leading whitespace is
129 removed from values. Empty lines are skipped. Lines beginning with
129 removed from values. Empty lines are skipped. Lines beginning with
130 ``#`` or ``;`` are ignored and may be used to provide comments.
130 ``#`` or ``;`` are ignored and may be used to provide comments.
131
131
132 Configuration keys can be set multiple times, in which case Mercurial
132 Configuration keys can be set multiple times, in which case Mercurial
133 will use the value that was configured last. As an example::
133 will use the value that was configured last. As an example::
134
134
135 [spam]
135 [spam]
136 eggs=large
136 eggs=large
137 ham=serrano
137 ham=serrano
138 eggs=small
138 eggs=small
139
139
140 This would set the configuration key named ``eggs`` to ``small``.
140 This would set the configuration key named ``eggs`` to ``small``.
141
141
142 It is also possible to define a section multiple times. A section can
142 It is also possible to define a section multiple times. A section can
143 be redefined on the same and/or on different configuration files. For
143 be redefined on the same and/or on different configuration files. For
144 example::
144 example::
145
145
146 [foo]
146 [foo]
147 eggs=large
147 eggs=large
148 ham=serrano
148 ham=serrano
149 eggs=small
149 eggs=small
150
150
151 [bar]
151 [bar]
152 eggs=ham
152 eggs=ham
153 green=
153 green=
154 eggs
154 eggs
155
155
156 [foo]
156 [foo]
157 ham=prosciutto
157 ham=prosciutto
158 eggs=medium
158 eggs=medium
159 bread=toasted
159 bread=toasted
160
160
161 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
161 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
162 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
162 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
163 respectively. As you can see there only thing that matters is the last
163 respectively. As you can see there only thing that matters is the last
164 value that was set for each of the configuration keys.
164 value that was set for each of the configuration keys.
165
165
166 If a configuration key is set multiple times in different
166 If a configuration key is set multiple times in different
167 configuration files the final value will depend on the order in which
167 configuration files the final value will depend on the order in which
168 the different configuration files are read, with settings from earlier
168 the different configuration files are read, with settings from earlier
169 paths overriding later ones as described on the ``Files`` section
169 paths overriding later ones as described on the ``Files`` section
170 above.
170 above.
171
171
172 A line of the form ``%include file`` will include ``file`` into the
172 A line of the form ``%include file`` will include ``file`` into the
173 current configuration file. The inclusion is recursive, which means
173 current configuration file. The inclusion is recursive, which means
174 that included files can include other files. Filenames are relative to
174 that included files can include other files. Filenames are relative to
175 the configuration file in which the ``%include`` directive is found.
175 the configuration file in which the ``%include`` directive is found.
176 Environment variables and ``~user`` constructs are expanded in
176 Environment variables and ``~user`` constructs are expanded in
177 ``file``. This lets you do something like::
177 ``file``. This lets you do something like::
178
178
179 %include ~/.hgrc.d/$HOST.rc
179 %include ~/.hgrc.d/$HOST.rc
180
180
181 to include a different configuration file on each computer you use.
181 to include a different configuration file on each computer you use.
182
182
183 A line with ``%unset name`` will remove ``name`` from the current
183 A line with ``%unset name`` will remove ``name`` from the current
184 section, if it has been set previously.
184 section, if it has been set previously.
185
185
186 The values are either free-form text strings, lists of text strings,
186 The values are either free-form text strings, lists of text strings,
187 or Boolean values. Boolean values can be set to true using any of "1",
187 or Boolean values. Boolean values can be set to true using any of "1",
188 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
188 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
189 (all case insensitive).
189 (all case insensitive).
190
190
191 List values are separated by whitespace or comma, except when values are
191 List values are separated by whitespace or comma, except when values are
192 placed in double quotation marks::
192 placed in double quotation marks::
193
193
194 allow_read = "John Doe, PhD", brian, betty
194 allow_read = "John Doe, PhD", brian, betty
195
195
196 Quotation marks can be escaped by prefixing them with a backslash. Only
196 Quotation marks can be escaped by prefixing them with a backslash. Only
197 quotation marks at the beginning of a word is counted as a quotation
197 quotation marks at the beginning of a word is counted as a quotation
198 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
198 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
199
199
200 Sections
200 Sections
201 ========
201 ========
202
202
203 This section describes the different sections that may appear in a
203 This section describes the different sections that may appear in a
204 Mercurial configuration file, the purpose of each section, its possible
204 Mercurial configuration file, the purpose of each section, its possible
205 keys, and their possible values.
205 keys, and their possible values.
206
206
207 ``alias``
207 ``alias``
208 ---------
208 ---------
209
209
210 Defines command aliases.
210 Defines command aliases.
211 Aliases allow you to define your own commands in terms of other
211 Aliases allow you to define your own commands in terms of other
212 commands (or aliases), optionally including arguments. Positional
212 commands (or aliases), optionally including arguments. Positional
213 arguments in the form of ``$1``, ``$2``, etc in the alias definition
213 arguments in the form of ``$1``, ``$2``, etc in the alias definition
214 are expanded by Mercurial before execution. Positional arguments not
214 are expanded by Mercurial before execution. Positional arguments not
215 already used by ``$N`` in the definition are put at the end of the
215 already used by ``$N`` in the definition are put at the end of the
216 command to be executed.
216 command to be executed.
217
217
218 Alias definitions consist of lines of the form::
218 Alias definitions consist of lines of the form::
219
219
220 <alias> = <command> [<argument>]...
220 <alias> = <command> [<argument>]...
221
221
222 For example, this definition::
222 For example, this definition::
223
223
224 latest = log --limit 5
224 latest = log --limit 5
225
225
226 creates a new command ``latest`` that shows only the five most recent
226 creates a new command ``latest`` that shows only the five most recent
227 changesets. You can define subsequent aliases using earlier ones::
227 changesets. You can define subsequent aliases using earlier ones::
228
228
229 stable5 = latest -b stable
229 stable5 = latest -b stable
230
230
231 .. note::
231 .. note::
232
232
233 It is possible to create aliases with the same names as
233 It is possible to create aliases with the same names as
234 existing commands, which will then override the original
234 existing commands, which will then override the original
235 definitions. This is almost always a bad idea!
235 definitions. This is almost always a bad idea!
236
236
237 An alias can start with an exclamation point (``!``) to make it a
237 An alias can start with an exclamation point (``!``) to make it a
238 shell alias. A shell alias is executed with the shell and will let you
238 shell alias. A shell alias is executed with the shell and will let you
239 run arbitrary commands. As an example, ::
239 run arbitrary commands. As an example, ::
240
240
241 echo = !echo $@
241 echo = !echo $@
242
242
243 will let you do ``hg echo foo`` to have ``foo`` printed in your
243 will let you do ``hg echo foo`` to have ``foo`` printed in your
244 terminal. A better example might be::
244 terminal. A better example might be::
245
245
246 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
246 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
247
247
248 which will make ``hg purge`` delete all unknown files in the
248 which will make ``hg purge`` delete all unknown files in the
249 repository in the same manner as the purge extension.
249 repository in the same manner as the purge extension.
250
250
251 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
251 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
252 expand to the command arguments. Unmatched arguments are
252 expand to the command arguments. Unmatched arguments are
253 removed. ``$0`` expands to the alias name and ``$@`` expands to all
253 removed. ``$0`` expands to the alias name and ``$@`` expands to all
254 arguments separated by a space. ``"$@"`` (with quotes) expands to all
254 arguments separated by a space. ``"$@"`` (with quotes) expands to all
255 arguments quoted individually and separated by a space. These expansions
255 arguments quoted individually and separated by a space. These expansions
256 happen before the command is passed to the shell.
256 happen before the command is passed to the shell.
257
257
258 Shell aliases are executed in an environment where ``$HG`` expands to
258 Shell aliases are executed in an environment where ``$HG`` expands to
259 the path of the Mercurial that was used to execute the alias. This is
259 the path of the Mercurial that was used to execute the alias. This is
260 useful when you want to call further Mercurial commands in a shell
260 useful when you want to call further Mercurial commands in a shell
261 alias, as was done above for the purge alias. In addition,
261 alias, as was done above for the purge alias. In addition,
262 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
262 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
263 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
263 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
264
264
265 .. note::
265 .. note::
266
266
267 Some global configuration options such as ``-R`` are
267 Some global configuration options such as ``-R`` are
268 processed before shell aliases and will thus not be passed to
268 processed before shell aliases and will thus not be passed to
269 aliases.
269 aliases.
270
270
271
271
272 ``annotate``
272 ``annotate``
273 ------------
273 ------------
274
274
275 Settings used when displaying file annotations. All values are
275 Settings used when displaying file annotations. All values are
276 Booleans and default to False. See ``diff`` section for related
276 Booleans and default to False. See ``diff`` section for related
277 options for the diff command.
277 options for the diff command.
278
278
279 ``ignorews``
279 ``ignorews``
280 Ignore white space when comparing lines.
280 Ignore white space when comparing lines.
281
281
282 ``ignorewsamount``
282 ``ignorewsamount``
283 Ignore changes in the amount of white space.
283 Ignore changes in the amount of white space.
284
284
285 ``ignoreblanklines``
285 ``ignoreblanklines``
286 Ignore changes whose lines are all blank.
286 Ignore changes whose lines are all blank.
287
287
288
288
289 ``auth``
289 ``auth``
290 --------
290 --------
291
291
292 Authentication credentials for HTTP authentication. This section
292 Authentication credentials for HTTP authentication. This section
293 allows you to store usernames and passwords for use when logging
293 allows you to store usernames and passwords for use when logging
294 *into* HTTP servers. See the ``[web]`` configuration section if
294 *into* HTTP servers. See the ``[web]`` configuration section if
295 you want to configure *who* can login to your HTTP server.
295 you want to configure *who* can login to your HTTP server.
296
296
297 Each line has the following format::
297 Each line has the following format::
298
298
299 <name>.<argument> = <value>
299 <name>.<argument> = <value>
300
300
301 where ``<name>`` is used to group arguments into authentication
301 where ``<name>`` is used to group arguments into authentication
302 entries. Example::
302 entries. Example::
303
303
304 foo.prefix = hg.intevation.org/mercurial
304 foo.prefix = hg.intevation.org/mercurial
305 foo.username = foo
305 foo.username = foo
306 foo.password = bar
306 foo.password = bar
307 foo.schemes = http https
307 foo.schemes = http https
308
308
309 bar.prefix = secure.example.org
309 bar.prefix = secure.example.org
310 bar.key = path/to/file.key
310 bar.key = path/to/file.key
311 bar.cert = path/to/file.cert
311 bar.cert = path/to/file.cert
312 bar.schemes = https
312 bar.schemes = https
313
313
314 Supported arguments:
314 Supported arguments:
315
315
316 ``prefix``
316 ``prefix``
317 Either ``*`` or a URI prefix with or without the scheme part.
317 Either ``*`` or a URI prefix with or without the scheme part.
318 The authentication entry with the longest matching prefix is used
318 The authentication entry with the longest matching prefix is used
319 (where ``*`` matches everything and counts as a match of length
319 (where ``*`` matches everything and counts as a match of length
320 1). If the prefix doesn't include a scheme, the match is performed
320 1). If the prefix doesn't include a scheme, the match is performed
321 against the URI with its scheme stripped as well, and the schemes
321 against the URI with its scheme stripped as well, and the schemes
322 argument, q.v., is then subsequently consulted.
322 argument, q.v., is then subsequently consulted.
323
323
324 ``username``
324 ``username``
325 Optional. Username to authenticate with. If not given, and the
325 Optional. Username to authenticate with. If not given, and the
326 remote site requires basic or digest authentication, the user will
326 remote site requires basic or digest authentication, the user will
327 be prompted for it. Environment variables are expanded in the
327 be prompted for it. Environment variables are expanded in the
328 username letting you do ``foo.username = $USER``. If the URI
328 username letting you do ``foo.username = $USER``. If the URI
329 includes a username, only ``[auth]`` entries with a matching
329 includes a username, only ``[auth]`` entries with a matching
330 username or without a username will be considered.
330 username or without a username will be considered.
331
331
332 ``password``
332 ``password``
333 Optional. Password to authenticate with. If not given, and the
333 Optional. Password to authenticate with. If not given, and the
334 remote site requires basic or digest authentication, the user
334 remote site requires basic or digest authentication, the user
335 will be prompted for it.
335 will be prompted for it.
336
336
337 ``key``
337 ``key``
338 Optional. PEM encoded client certificate key file. Environment
338 Optional. PEM encoded client certificate key file. Environment
339 variables are expanded in the filename.
339 variables are expanded in the filename.
340
340
341 ``cert``
341 ``cert``
342 Optional. PEM encoded client certificate chain file. Environment
342 Optional. PEM encoded client certificate chain file. Environment
343 variables are expanded in the filename.
343 variables are expanded in the filename.
344
344
345 ``schemes``
345 ``schemes``
346 Optional. Space separated list of URI schemes to use this
346 Optional. Space separated list of URI schemes to use this
347 authentication entry with. Only used if the prefix doesn't include
347 authentication entry with. Only used if the prefix doesn't include
348 a scheme. Supported schemes are http and https. They will match
348 a scheme. Supported schemes are http and https. They will match
349 static-http and static-https respectively, as well.
349 static-http and static-https respectively, as well.
350 Default: https.
350 Default: https.
351
351
352 If no suitable authentication entry is found, the user is prompted
352 If no suitable authentication entry is found, the user is prompted
353 for credentials as usual if required by the remote.
353 for credentials as usual if required by the remote.
354
354
355
355
356 ``committemplate``
356 ``committemplate``
357 ------------------
357 ------------------
358
358
359 ``changeset`` configuration in this section is used as the template to
359 ``changeset`` configuration in this section is used as the template to
360 customize the text shown in the editor when committing.
360 customize the text shown in the editor when committing.
361
361
362 In addition to pre-defined template keywords, commit log specific one
362 In addition to pre-defined template keywords, commit log specific one
363 below can be used for customization:
363 below can be used for customization:
364
364
365 ``extramsg``
365 ``extramsg``
366 String: Extra message (typically 'Leave message empty to abort
366 String: Extra message (typically 'Leave message empty to abort
367 commit.'). This may be changed by some commands or extensions.
367 commit.'). This may be changed by some commands or extensions.
368
368
369 For example, the template configuration below shows as same text as
369 For example, the template configuration below shows as same text as
370 one shown by default::
370 one shown by default::
371
371
372 [committemplate]
372 [committemplate]
373 changeset = {desc}\n\n
373 changeset = {desc}\n\n
374 HG: Enter commit message. Lines beginning with 'HG:' are removed.
374 HG: Enter commit message. Lines beginning with 'HG:' are removed.
375 HG: {extramsg}
375 HG: {extramsg}
376 HG: --
376 HG: --
377 HG: user: {author}\n{ifeq(p2rev, "-1", "",
377 HG: user: {author}\n{ifeq(p2rev, "-1", "",
378 "HG: branch merge\n")
378 "HG: branch merge\n")
379 }HG: branch '{branch}'\n{if(currentbookmark,
379 }HG: branch '{branch}'\n{if(currentbookmark,
380 "HG: bookmark '{currentbookmark}'\n") }{subrepos %
380 "HG: bookmark '{currentbookmark}'\n") }{subrepos %
381 "HG: subrepo {subrepo}\n" }{file_adds %
381 "HG: subrepo {subrepo}\n" }{file_adds %
382 "HG: added {file}\n" }{file_mods %
382 "HG: added {file}\n" }{file_mods %
383 "HG: changed {file}\n" }{file_dels %
383 "HG: changed {file}\n" }{file_dels %
384 "HG: removed {file}\n" }{if(files, "",
384 "HG: removed {file}\n" }{if(files, "",
385 "HG: no files changed\n")}
385 "HG: no files changed\n")}
386
386
387 .. note::
387 .. note::
388
388
389 For some problematic encodings (see :hg:`help win32mbcs` for
389 For some problematic encodings (see :hg:`help win32mbcs` for
390 detail), this customization should be configured carefully, to
390 detail), this customization should be configured carefully, to
391 avoid showing broken characters.
391 avoid showing broken characters.
392
392
393 For example, if multibyte character ending with backslash (0x5c) is
393 For example, if multibyte character ending with backslash (0x5c) is
394 followed by ASCII character 'n' in the customized template,
394 followed by ASCII character 'n' in the customized template,
395 sequence of backslash and 'n' is treated as line-feed unexpectedly
395 sequence of backslash and 'n' is treated as line-feed unexpectedly
396 (and multibyte character is broken, too).
396 (and multibyte character is broken, too).
397
397
398 Customized template is used for commands below (``--edit`` may be
398 Customized template is used for commands below (``--edit`` may be
399 required):
399 required):
400
400
401 - :hg:`backout`
401 - :hg:`backout`
402 - :hg:`commit`
402 - :hg:`commit`
403 - :hg:`fetch` (for merge commit only)
403 - :hg:`fetch` (for merge commit only)
404 - :hg:`graft`
404 - :hg:`graft`
405 - :hg:`histedit`
405 - :hg:`histedit`
406 - :hg:`import`
406 - :hg:`import`
407 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
407 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
408 - :hg:`rebase`
408 - :hg:`rebase`
409 - :hg:`shelve`
409 - :hg:`shelve`
410 - :hg:`sign`
410 - :hg:`sign`
411 - :hg:`tag`
411 - :hg:`tag`
412 - :hg:`transplant`
412 - :hg:`transplant`
413
413
414 Configuring items below instead of ``changeset`` allows showing
414 Configuring items below instead of ``changeset`` allows showing
415 customized message only for specific actions, or showing different
415 customized message only for specific actions, or showing different
416 messages for each action.
416 messages for each action.
417
417
418 - ``changeset.backout`` for :hg:`backout`
418 - ``changeset.backout`` for :hg:`backout`
419 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
419 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
420 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
420 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
421 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
421 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
422 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
422 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
423 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
423 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
424 - ``changeset.gpg.sign`` for :hg:`sign`
424 - ``changeset.gpg.sign`` for :hg:`sign`
425 - ``changeset.graft`` for :hg:`graft`
425 - ``changeset.graft`` for :hg:`graft`
426 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
426 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
427 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
427 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
428 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
428 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
429 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
429 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
430 - ``changeset.import.bypass`` for :hg:`import --bypass`
430 - ``changeset.import.bypass`` for :hg:`import --bypass`
431 - ``changeset.import.normal.merge`` for :hg:`import` on merges
431 - ``changeset.import.normal.merge`` for :hg:`import` on merges
432 - ``changeset.import.normal.normal`` for :hg:`import` on other
432 - ``changeset.import.normal.normal`` for :hg:`import` on other
433 - ``changeset.mq.qnew`` for :hg:`qnew`
433 - ``changeset.mq.qnew`` for :hg:`qnew`
434 - ``changeset.mq.qfold`` for :hg:`qfold`
434 - ``changeset.mq.qfold`` for :hg:`qfold`
435 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
435 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
436 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
436 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
437 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
437 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
438 - ``changeset.rebase.normal`` for :hg:`rebase` on other
438 - ``changeset.rebase.normal`` for :hg:`rebase` on other
439 - ``changeset.shelve.shelve`` for :hg:`shelve`
439 - ``changeset.shelve.shelve`` for :hg:`shelve`
440 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
440 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
441 - ``changeset.tag.remove`` for :hg:`tag --remove`
441 - ``changeset.tag.remove`` for :hg:`tag --remove`
442 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
442 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
443 - ``changeset.transplant.normal`` for :hg:`transplant` on other
443 - ``changeset.transplant.normal`` for :hg:`transplant` on other
444
444
445 These dot-separated lists of names are treated as hierarchical ones.
445 These dot-separated lists of names are treated as hierarchical ones.
446 For example, ``changeset.tag.remove`` customizes the commit message
446 For example, ``changeset.tag.remove`` customizes the commit message
447 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
447 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
448 commit message for :hg:`tag` regardless of ``--remove`` option.
448 commit message for :hg:`tag` regardless of ``--remove`` option.
449
449
450 At the external editor invocation for committing, corresponding
450 At the external editor invocation for committing, corresponding
451 dot-separated list of names without ``changeset.`` prefix
451 dot-separated list of names without ``changeset.`` prefix
452 (e.g. ``commit.normal.normal``) is in ``HGEDITFORM`` environment variable.
452 (e.g. ``commit.normal.normal``) is in ``HGEDITFORM`` environment variable.
453
453
454 In this section, items other than ``changeset`` can be referred from
454 In this section, items other than ``changeset`` can be referred from
455 others. For example, the configuration to list committed files up
455 others. For example, the configuration to list committed files up
456 below can be referred as ``{listupfiles}``::
456 below can be referred as ``{listupfiles}``::
457
457
458 [committemplate]
458 [committemplate]
459 listupfiles = {file_adds %
459 listupfiles = {file_adds %
460 "HG: added {file}\n" }{file_mods %
460 "HG: added {file}\n" }{file_mods %
461 "HG: changed {file}\n" }{file_dels %
461 "HG: changed {file}\n" }{file_dels %
462 "HG: removed {file}\n" }{if(files, "",
462 "HG: removed {file}\n" }{if(files, "",
463 "HG: no files changed\n")}
463 "HG: no files changed\n")}
464
464
465 ``decode/encode``
465 ``decode/encode``
466 -----------------
466 -----------------
467
467
468 Filters for transforming files on checkout/checkin. This would
468 Filters for transforming files on checkout/checkin. This would
469 typically be used for newline processing or other
469 typically be used for newline processing or other
470 localization/canonicalization of files.
470 localization/canonicalization of files.
471
471
472 Filters consist of a filter pattern followed by a filter command.
472 Filters consist of a filter pattern followed by a filter command.
473 Filter patterns are globs by default, rooted at the repository root.
473 Filter patterns are globs by default, rooted at the repository root.
474 For example, to match any file ending in ``.txt`` in the root
474 For example, to match any file ending in ``.txt`` in the root
475 directory only, use the pattern ``*.txt``. To match any file ending
475 directory only, use the pattern ``*.txt``. To match any file ending
476 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
476 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
477 For each file only the first matching filter applies.
477 For each file only the first matching filter applies.
478
478
479 The filter command can start with a specifier, either ``pipe:`` or
479 The filter command can start with a specifier, either ``pipe:`` or
480 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
480 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
481
481
482 A ``pipe:`` command must accept data on stdin and return the transformed
482 A ``pipe:`` command must accept data on stdin and return the transformed
483 data on stdout.
483 data on stdout.
484
484
485 Pipe example::
485 Pipe example::
486
486
487 [encode]
487 [encode]
488 # uncompress gzip files on checkin to improve delta compression
488 # uncompress gzip files on checkin to improve delta compression
489 # note: not necessarily a good idea, just an example
489 # note: not necessarily a good idea, just an example
490 *.gz = pipe: gunzip
490 *.gz = pipe: gunzip
491
491
492 [decode]
492 [decode]
493 # recompress gzip files when writing them to the working dir (we
493 # recompress gzip files when writing them to the working dir (we
494 # can safely omit "pipe:", because it's the default)
494 # can safely omit "pipe:", because it's the default)
495 *.gz = gzip
495 *.gz = gzip
496
496
497 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
497 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
498 with the name of a temporary file that contains the data to be
498 with the name of a temporary file that contains the data to be
499 filtered by the command. The string ``OUTFILE`` is replaced with the name
499 filtered by the command. The string ``OUTFILE`` is replaced with the name
500 of an empty temporary file, where the filtered data must be written by
500 of an empty temporary file, where the filtered data must be written by
501 the command.
501 the command.
502
502
503 .. note::
503 .. note::
504
504
505 The tempfile mechanism is recommended for Windows systems,
505 The tempfile mechanism is recommended for Windows systems,
506 where the standard shell I/O redirection operators often have
506 where the standard shell I/O redirection operators often have
507 strange effects and may corrupt the contents of your files.
507 strange effects and may corrupt the contents of your files.
508
508
509 This filter mechanism is used internally by the ``eol`` extension to
509 This filter mechanism is used internally by the ``eol`` extension to
510 translate line ending characters between Windows (CRLF) and Unix (LF)
510 translate line ending characters between Windows (CRLF) and Unix (LF)
511 format. We suggest you use the ``eol`` extension for convenience.
511 format. We suggest you use the ``eol`` extension for convenience.
512
512
513
513
514 ``defaults``
514 ``defaults``
515 ------------
515 ------------
516
516
517 (defaults are deprecated. Don't use them. Use aliases instead)
517 (defaults are deprecated. Don't use them. Use aliases instead)
518
518
519 Use the ``[defaults]`` section to define command defaults, i.e. the
519 Use the ``[defaults]`` section to define command defaults, i.e. the
520 default options/arguments to pass to the specified commands.
520 default options/arguments to pass to the specified commands.
521
521
522 The following example makes :hg:`log` run in verbose mode, and
522 The following example makes :hg:`log` run in verbose mode, and
523 :hg:`status` show only the modified files, by default::
523 :hg:`status` show only the modified files, by default::
524
524
525 [defaults]
525 [defaults]
526 log = -v
526 log = -v
527 status = -m
527 status = -m
528
528
529 The actual commands, instead of their aliases, must be used when
529 The actual commands, instead of their aliases, must be used when
530 defining command defaults. The command defaults will also be applied
530 defining command defaults. The command defaults will also be applied
531 to the aliases of the commands defined.
531 to the aliases of the commands defined.
532
532
533
533
534 ``diff``
534 ``diff``
535 --------
535 --------
536
536
537 Settings used when displaying diffs. Everything except for ``unified``
537 Settings used when displaying diffs. Everything except for ``unified``
538 is a Boolean and defaults to False. See ``annotate`` section for
538 is a Boolean and defaults to False. See ``annotate`` section for
539 related options for the annotate command.
539 related options for the annotate command.
540
540
541 ``git``
541 ``git``
542 Use git extended diff format.
542 Use git extended diff format.
543
543
544 ``nobinary``
544 ``nobinary``
545 Omit git binary patches.
545 Omit git binary patches.
546
546
547 ``nodates``
547 ``nodates``
548 Don't include dates in diff headers.
548 Don't include dates in diff headers.
549
549
550 ``noprefix``
550 ``noprefix``
551 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
551 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
552
552
553 ``showfunc``
553 ``showfunc``
554 Show which function each change is in.
554 Show which function each change is in.
555
555
556 ``ignorews``
556 ``ignorews``
557 Ignore white space when comparing lines.
557 Ignore white space when comparing lines.
558
558
559 ``ignorewsamount``
559 ``ignorewsamount``
560 Ignore changes in the amount of white space.
560 Ignore changes in the amount of white space.
561
561
562 ``ignoreblanklines``
562 ``ignoreblanklines``
563 Ignore changes whose lines are all blank.
563 Ignore changes whose lines are all blank.
564
564
565 ``unified``
565 ``unified``
566 Number of lines of context to show.
566 Number of lines of context to show.
567
567
568 ``email``
568 ``email``
569 ---------
569 ---------
570
570
571 Settings for extensions that send email messages.
571 Settings for extensions that send email messages.
572
572
573 ``from``
573 ``from``
574 Optional. Email address to use in "From" header and SMTP envelope
574 Optional. Email address to use in "From" header and SMTP envelope
575 of outgoing messages.
575 of outgoing messages.
576
576
577 ``to``
577 ``to``
578 Optional. Comma-separated list of recipients' email addresses.
578 Optional. Comma-separated list of recipients' email addresses.
579
579
580 ``cc``
580 ``cc``
581 Optional. Comma-separated list of carbon copy recipients'
581 Optional. Comma-separated list of carbon copy recipients'
582 email addresses.
582 email addresses.
583
583
584 ``bcc``
584 ``bcc``
585 Optional. Comma-separated list of blind carbon copy recipients'
585 Optional. Comma-separated list of blind carbon copy recipients'
586 email addresses.
586 email addresses.
587
587
588 ``method``
588 ``method``
589 Optional. Method to use to send email messages. If value is ``smtp``
589 Optional. Method to use to send email messages. If value is ``smtp``
590 (default), use SMTP (see the ``[smtp]`` section for configuration).
590 (default), use SMTP (see the ``[smtp]`` section for configuration).
591 Otherwise, use as name of program to run that acts like sendmail
591 Otherwise, use as name of program to run that acts like sendmail
592 (takes ``-f`` option for sender, list of recipients on command line,
592 (takes ``-f`` option for sender, list of recipients on command line,
593 message on stdin). Normally, setting this to ``sendmail`` or
593 message on stdin). Normally, setting this to ``sendmail`` or
594 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
594 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
595
595
596 ``charsets``
596 ``charsets``
597 Optional. Comma-separated list of character sets considered
597 Optional. Comma-separated list of character sets considered
598 convenient for recipients. Addresses, headers, and parts not
598 convenient for recipients. Addresses, headers, and parts not
599 containing patches of outgoing messages will be encoded in the
599 containing patches of outgoing messages will be encoded in the
600 first character set to which conversion from local encoding
600 first character set to which conversion from local encoding
601 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
601 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
602 conversion fails, the text in question is sent as is. Defaults to
602 conversion fails, the text in question is sent as is. Defaults to
603 empty (explicit) list.
603 empty (explicit) list.
604
604
605 Order of outgoing email character sets:
605 Order of outgoing email character sets:
606
606
607 1. ``us-ascii``: always first, regardless of settings
607 1. ``us-ascii``: always first, regardless of settings
608 2. ``email.charsets``: in order given by user
608 2. ``email.charsets``: in order given by user
609 3. ``ui.fallbackencoding``: if not in email.charsets
609 3. ``ui.fallbackencoding``: if not in email.charsets
610 4. ``$HGENCODING``: if not in email.charsets
610 4. ``$HGENCODING``: if not in email.charsets
611 5. ``utf-8``: always last, regardless of settings
611 5. ``utf-8``: always last, regardless of settings
612
612
613 Email example::
613 Email example::
614
614
615 [email]
615 [email]
616 from = Joseph User <joe.user@example.com>
616 from = Joseph User <joe.user@example.com>
617 method = /usr/sbin/sendmail
617 method = /usr/sbin/sendmail
618 # charsets for western Europeans
618 # charsets for western Europeans
619 # us-ascii, utf-8 omitted, as they are tried first and last
619 # us-ascii, utf-8 omitted, as they are tried first and last
620 charsets = iso-8859-1, iso-8859-15, windows-1252
620 charsets = iso-8859-1, iso-8859-15, windows-1252
621
621
622
622
623 ``extensions``
623 ``extensions``
624 --------------
624 --------------
625
625
626 Mercurial has an extension mechanism for adding new features. To
626 Mercurial has an extension mechanism for adding new features. To
627 enable an extension, create an entry for it in this section.
627 enable an extension, create an entry for it in this section.
628
628
629 If you know that the extension is already in Python's search path,
629 If you know that the extension is already in Python's search path,
630 you can give the name of the module, followed by ``=``, with nothing
630 you can give the name of the module, followed by ``=``, with nothing
631 after the ``=``.
631 after the ``=``.
632
632
633 Otherwise, give a name that you choose, followed by ``=``, followed by
633 Otherwise, give a name that you choose, followed by ``=``, followed by
634 the path to the ``.py`` file (including the file name extension) that
634 the path to the ``.py`` file (including the file name extension) that
635 defines the extension.
635 defines the extension.
636
636
637 To explicitly disable an extension that is enabled in an hgrc of
637 To explicitly disable an extension that is enabled in an hgrc of
638 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
638 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
639 or ``foo = !`` when path is not supplied.
639 or ``foo = !`` when path is not supplied.
640
640
641 Example for ``~/.hgrc``::
641 Example for ``~/.hgrc``::
642
642
643 [extensions]
643 [extensions]
644 # (the progress extension will get loaded from Mercurial's path)
644 # (the progress extension will get loaded from Mercurial's path)
645 progress =
645 progress =
646 # (this extension will get loaded from the file specified)
646 # (this extension will get loaded from the file specified)
647 myfeature = ~/.hgext/myfeature.py
647 myfeature = ~/.hgext/myfeature.py
648
648
649
649
650 ``format``
650 ``format``
651 ----------
651 ----------
652
652
653 ``usestore``
653 ``usestore``
654 Enable or disable the "store" repository format which improves
654 Enable or disable the "store" repository format which improves
655 compatibility with systems that fold case or otherwise mangle
655 compatibility with systems that fold case or otherwise mangle
656 filenames. Enabled by default. Disabling this option will allow
656 filenames. Enabled by default. Disabling this option will allow
657 you to store longer filenames in some situations at the expense of
657 you to store longer filenames in some situations at the expense of
658 compatibility and ensures that the on-disk format of newly created
658 compatibility and ensures that the on-disk format of newly created
659 repositories will be compatible with Mercurial before version 0.9.4.
659 repositories will be compatible with Mercurial before version 0.9.4.
660
660
661 ``usefncache``
661 ``usefncache``
662 Enable or disable the "fncache" repository format which enhances
662 Enable or disable the "fncache" repository format which enhances
663 the "store" repository format (which has to be enabled to use
663 the "store" repository format (which has to be enabled to use
664 fncache) to allow longer filenames and avoids using Windows
664 fncache) to allow longer filenames and avoids using Windows
665 reserved names, e.g. "nul". Enabled by default. Disabling this
665 reserved names, e.g. "nul". Enabled by default. Disabling this
666 option ensures that the on-disk format of newly created
666 option ensures that the on-disk format of newly created
667 repositories will be compatible with Mercurial before version 1.1.
667 repositories will be compatible with Mercurial before version 1.1.
668
668
669 ``dotencode``
669 ``dotencode``
670 Enable or disable the "dotencode" repository format which enhances
670 Enable or disable the "dotencode" repository format which enhances
671 the "fncache" repository format (which has to be enabled to use
671 the "fncache" repository format (which has to be enabled to use
672 dotencode) to avoid issues with filenames starting with ._ on
672 dotencode) to avoid issues with filenames starting with ._ on
673 Mac OS X and spaces on Windows. Enabled by default. Disabling this
673 Mac OS X and spaces on Windows. Enabled by default. Disabling this
674 option ensures that the on-disk format of newly created
674 option ensures that the on-disk format of newly created
675 repositories will be compatible with Mercurial before version 1.7.
675 repositories will be compatible with Mercurial before version 1.7.
676
676
677 ``graph``
677 ``graph``
678 ---------
678 ---------
679
679
680 Web graph view configuration. This section let you change graph
680 Web graph view configuration. This section let you change graph
681 elements display properties by branches, for instance to make the
681 elements display properties by branches, for instance to make the
682 ``default`` branch stand out.
682 ``default`` branch stand out.
683
683
684 Each line has the following format::
684 Each line has the following format::
685
685
686 <branch>.<argument> = <value>
686 <branch>.<argument> = <value>
687
687
688 where ``<branch>`` is the name of the branch being
688 where ``<branch>`` is the name of the branch being
689 customized. Example::
689 customized. Example::
690
690
691 [graph]
691 [graph]
692 # 2px width
692 # 2px width
693 default.width = 2
693 default.width = 2
694 # red color
694 # red color
695 default.color = FF0000
695 default.color = FF0000
696
696
697 Supported arguments:
697 Supported arguments:
698
698
699 ``width``
699 ``width``
700 Set branch edges width in pixels.
700 Set branch edges width in pixels.
701
701
702 ``color``
702 ``color``
703 Set branch edges color in hexadecimal RGB notation.
703 Set branch edges color in hexadecimal RGB notation.
704
704
705 ``hooks``
705 ``hooks``
706 ---------
706 ---------
707
707
708 Commands or Python functions that get automatically executed by
708 Commands or Python functions that get automatically executed by
709 various actions such as starting or finishing a commit. Multiple
709 various actions such as starting or finishing a commit. Multiple
710 hooks can be run for the same action by appending a suffix to the
710 hooks can be run for the same action by appending a suffix to the
711 action. Overriding a site-wide hook can be done by changing its
711 action. Overriding a site-wide hook can be done by changing its
712 value or setting it to an empty string. Hooks can be prioritized
712 value or setting it to an empty string. Hooks can be prioritized
713 by adding a prefix of ``priority`` to the hook name on a new line
713 by adding a prefix of ``priority`` to the hook name on a new line
714 and setting the priority. The default priority is 0 if
714 and setting the priority. The default priority is 0 if
715 not specified.
715 not specified.
716
716
717 Example ``.hg/hgrc``::
717 Example ``.hg/hgrc``::
718
718
719 [hooks]
719 [hooks]
720 # update working directory after adding changesets
720 # update working directory after adding changesets
721 changegroup.update = hg update
721 changegroup.update = hg update
722 # do not use the site-wide hook
722 # do not use the site-wide hook
723 incoming =
723 incoming =
724 incoming.email = /my/email/hook
724 incoming.email = /my/email/hook
725 incoming.autobuild = /my/build/hook
725 incoming.autobuild = /my/build/hook
726 # force autobuild hook to run before other incoming hooks
726 # force autobuild hook to run before other incoming hooks
727 priority.incoming.autobuild = 1
727 priority.incoming.autobuild = 1
728
728
729 Most hooks are run with environment variables set that give useful
729 Most hooks are run with environment variables set that give useful
730 additional information. For each hook below, the environment
730 additional information. For each hook below, the environment
731 variables it is passed are listed with names of the form ``$HG_foo``.
731 variables it is passed are listed with names of the form ``$HG_foo``.
732
732
733 ``changegroup``
733 ``changegroup``
734 Run after a changegroup has been added via push, pull or unbundle.
734 Run after a changegroup has been added via push, pull or unbundle.
735 ID of the first new changeset is in ``$HG_NODE``. URL from which
735 ID of the first new changeset is in ``$HG_NODE``. URL from which
736 changes came is in ``$HG_URL``.
736 changes came is in ``$HG_URL``.
737
737
738 ``commit``
738 ``commit``
739 Run after a changeset has been created in the local repository. ID
739 Run after a changeset has been created in the local repository. ID
740 of the newly created changeset is in ``$HG_NODE``. Parent changeset
740 of the newly created changeset is in ``$HG_NODE``. Parent changeset
741 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
741 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
742
742
743 ``incoming``
743 ``incoming``
744 Run after a changeset has been pulled, pushed, or unbundled into
744 Run after a changeset has been pulled, pushed, or unbundled into
745 the local repository. The ID of the newly arrived changeset is in
745 the local repository. The ID of the newly arrived changeset is in
746 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
746 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
747
747
748 ``outgoing``
748 ``outgoing``
749 Run after sending changes from local repository to another. ID of
749 Run after sending changes from local repository to another. ID of
750 first changeset sent is in ``$HG_NODE``. Source of operation is in
750 first changeset sent is in ``$HG_NODE``. Source of operation is in
751 ``$HG_SOURCE``; see "preoutgoing" hook for description.
751 ``$HG_SOURCE``; see "preoutgoing" hook for description.
752
752
753 ``post-<command>``
753 ``post-<command>``
754 Run after successful invocations of the associated command. The
754 Run after successful invocations of the associated command. The
755 contents of the command line are passed as ``$HG_ARGS`` and the result
755 contents of the command line are passed as ``$HG_ARGS`` and the result
756 code in ``$HG_RESULT``. Parsed command line arguments are passed as
756 code in ``$HG_RESULT``. Parsed command line arguments are passed as
757 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
757 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
758 the python data internally passed to <command>. ``$HG_OPTS`` is a
758 the python data internally passed to <command>. ``$HG_OPTS`` is a
759 dictionary of options (with unspecified options set to their defaults).
759 dictionary of options (with unspecified options set to their defaults).
760 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
760 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
761
761
762 ``pre-<command>``
762 ``pre-<command>``
763 Run before executing the associated command. The contents of the
763 Run before executing the associated command. The contents of the
764 command line are passed as ``$HG_ARGS``. Parsed command line arguments
764 command line are passed as ``$HG_ARGS``. Parsed command line arguments
765 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
765 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
766 representations of the data internally passed to <command>. ``$HG_OPTS``
766 representations of the data internally passed to <command>. ``$HG_OPTS``
767 is a dictionary of options (with unspecified options set to their
767 is a dictionary of options (with unspecified options set to their
768 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
768 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
769 failure, the command doesn't execute and Mercurial returns the failure
769 failure, the command doesn't execute and Mercurial returns the failure
770 code.
770 code.
771
771
772 ``prechangegroup``
772 ``prechangegroup``
773 Run before a changegroup is added via push, pull or unbundle. Exit
773 Run before a changegroup is added via push, pull or unbundle. Exit
774 status 0 allows the changegroup to proceed. Non-zero status will
774 status 0 allows the changegroup to proceed. Non-zero status will
775 cause the push, pull or unbundle to fail. URL from which changes
775 cause the push, pull or unbundle to fail. URL from which changes
776 will come is in ``$HG_URL``.
776 will come is in ``$HG_URL``.
777
777
778 ``precommit``
778 ``precommit``
779 Run before starting a local commit. Exit status 0 allows the
779 Run before starting a local commit. Exit status 0 allows the
780 commit to proceed. Non-zero status will cause the commit to fail.
780 commit to proceed. Non-zero status will cause the commit to fail.
781 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
781 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
782
782
783 ``prelistkeys``
783 ``prelistkeys``
784 Run before listing pushkeys (like bookmarks) in the
784 Run before listing pushkeys (like bookmarks) in the
785 repository. Non-zero status will cause failure. The key namespace is
785 repository. Non-zero status will cause failure. The key namespace is
786 in ``$HG_NAMESPACE``.
786 in ``$HG_NAMESPACE``.
787
787
788 ``preoutgoing``
788 ``preoutgoing``
789 Run before collecting changes to send from the local repository to
789 Run before collecting changes to send from the local repository to
790 another. Non-zero status will cause failure. This lets you prevent
790 another. Non-zero status will cause failure. This lets you prevent
791 pull over HTTP or SSH. Also prevents against local pull, push
791 pull over HTTP or SSH. Also prevents against local pull, push
792 (outbound) or bundle commands, but not effective, since you can
792 (outbound) or bundle commands, but not effective, since you can
793 just copy files instead then. Source of operation is in
793 just copy files instead then. Source of operation is in
794 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
794 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
795 SSH or HTTP repository. If "push", "pull" or "bundle", operation
795 SSH or HTTP repository. If "push", "pull" or "bundle", operation
796 is happening on behalf of repository on same system.
796 is happening on behalf of repository on same system.
797
797
798 ``prepushkey``
798 ``prepushkey``
799 Run before a pushkey (like a bookmark) is added to the
799 Run before a pushkey (like a bookmark) is added to the
800 repository. Non-zero status will cause the key to be rejected. The
800 repository. Non-zero status will cause the key to be rejected. The
801 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
801 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
802 the old value (if any) is in ``$HG_OLD``, and the new value is in
802 the old value (if any) is in ``$HG_OLD``, and the new value is in
803 ``$HG_NEW``.
803 ``$HG_NEW``.
804
804
805 ``pretag``
805 ``pretag``
806 Run before creating a tag. Exit status 0 allows the tag to be
806 Run before creating a tag. Exit status 0 allows the tag to be
807 created. Non-zero status will cause the tag to fail. ID of
807 created. Non-zero status will cause the tag to fail. ID of
808 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
808 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
809 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
809 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
810
810
811 ``pretxnopen``
811 ``pretxnopen``
812 Run before any new repository transaction is open. The reason for the
812 Run before any new repository transaction is open. The reason for the
813 transaction will be in ``$HG_TXNNAME``. A non-zero status will
813 transaction will be in ``$HG_TXNNAME``. A non-zero status will
814 prevent the transaction from being opened.
814 prevent the transaction from being opened.
815
815
816 ``pretxnclose``
816 ``pretxnclose``
817 Run right before the transaction is actually finalized. Any
817 Run right before the transaction is actually finalized. Any
818 repository change will be visible to the hook program. This lets you
818 repository change will be visible to the hook program. This lets you
819 validate the transaction content or change it. Exit status 0 allows
819 validate the transaction content or change it. Exit status 0 allows
820 the commit to proceed. Non-zero status will cause the transaction to
820 the commit to proceed. Non-zero status will cause the transaction to
821 be rolled back. The reason for the transaction opening will be in
821 be rolled back. The reason for the transaction opening will be in
822 ``$HG_TXNNAME``. The rest of the available data will vary according
822 ``$HG_TXNNAME``. The rest of the available data will vary according
823 the transaction type. New changesets will add
823 the transaction type. New changesets will add
824 ``$HG_NODE`` (id of the first added changeset), ``$HG_URL`` and
824 ``$HG_NODE`` (id of the first added changeset), ``$HG_URL`` and
825 ``$HG_SOURCE`` variables, bookmarks and phases changes will set
825 ``$HG_SOURCE`` variables, bookmarks and phases changes will set
826 ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``, etc.
826 ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``, etc.
827
827
828 ``txnclose``
828 ``txnclose``
829 Run after any repository transaction has been commited. At this
829 Run after any repository transaction has been commited. At this
830 point, the transaction can no longer be rolled back. The hook will run
830 point, the transaction can no longer be rolled back. The hook will run
831 after the lock is released. see ``pretxnclose`` docs for details about
831 after the lock is released. see ``pretxnclose`` docs for details about
832 available variables.
832 available variables.
833
833
834 ``pretxnchangegroup``
834 ``pretxnchangegroup``
835 Run after a changegroup has been added via push, pull or unbundle,
835 Run after a changegroup has been added via push, pull or unbundle,
836 but before the transaction has been committed. Changegroup is
836 but before the transaction has been committed. Changegroup is
837 visible to hook program. This lets you validate incoming changes
837 visible to hook program. This lets you validate incoming changes
838 before accepting them. Passed the ID of the first new changeset in
838 before accepting them. Passed the ID of the first new changeset in
839 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
839 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
840 status will cause the transaction to be rolled back and the push,
840 status will cause the transaction to be rolled back and the push,
841 pull or unbundle will fail. URL that was source of changes is in
841 pull or unbundle will fail. URL that was source of changes is in
842 ``$HG_URL``.
842 ``$HG_URL``.
843
843
844 ``pretxncommit``
844 ``pretxncommit``
845 Run after a changeset has been created but the transaction not yet
845 Run after a changeset has been created but the transaction not yet
846 committed. Changeset is visible to hook program. This lets you
846 committed. Changeset is visible to hook program. This lets you
847 validate commit message and changes. Exit status 0 allows the
847 validate commit message and changes. Exit status 0 allows the
848 commit to proceed. Non-zero status will cause the transaction to
848 commit to proceed. Non-zero status will cause the transaction to
849 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
849 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
850 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
850 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
851
851
852 ``preupdate``
852 ``preupdate``
853 Run before updating the working directory. Exit status 0 allows
853 Run before updating the working directory. Exit status 0 allows
854 the update to proceed. Non-zero status will prevent the update.
854 the update to proceed. Non-zero status will prevent the update.
855 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
855 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
856 of second new parent is in ``$HG_PARENT2``.
856 of second new parent is in ``$HG_PARENT2``.
857
857
858 ``listkeys``
858 ``listkeys``
859 Run after listing pushkeys (like bookmarks) in the repository. The
859 Run after listing pushkeys (like bookmarks) in the repository. The
860 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
860 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
861 dictionary containing the keys and values.
861 dictionary containing the keys and values.
862
862
863 ``pushkey``
863 ``pushkey``
864 Run after a pushkey (like a bookmark) is added to the
864 Run after a pushkey (like a bookmark) is added to the
865 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
865 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
866 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
866 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
867 value is in ``$HG_NEW``.
867 value is in ``$HG_NEW``.
868
868
869 ``tag``
869 ``tag``
870 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
870 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
871 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
871 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
872 repository if ``$HG_LOCAL=0``.
872 repository if ``$HG_LOCAL=0``.
873
873
874 ``update``
874 ``update``
875 Run after updating the working directory. Changeset ID of first
875 Run after updating the working directory. Changeset ID of first
876 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
876 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
877 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
877 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
878 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
878 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
879
879
880 .. note::
880 .. note::
881
881
882 It is generally better to use standard hooks rather than the
882 It is generally better to use standard hooks rather than the
883 generic pre- and post- command hooks as they are guaranteed to be
883 generic pre- and post- command hooks as they are guaranteed to be
884 called in the appropriate contexts for influencing transactions.
884 called in the appropriate contexts for influencing transactions.
885 Also, hooks like "commit" will be called in all contexts that
885 Also, hooks like "commit" will be called in all contexts that
886 generate a commit (e.g. tag) and not just the commit command.
886 generate a commit (e.g. tag) and not just the commit command.
887
887
888 .. note::
888 .. note::
889
889
890 Environment variables with empty values may not be passed to
890 Environment variables with empty values may not be passed to
891 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
891 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
892 will have an empty value under Unix-like platforms for non-merge
892 will have an empty value under Unix-like platforms for non-merge
893 changesets, while it will not be available at all under Windows.
893 changesets, while it will not be available at all under Windows.
894
894
895 The syntax for Python hooks is as follows::
895 The syntax for Python hooks is as follows::
896
896
897 hookname = python:modulename.submodule.callable
897 hookname = python:modulename.submodule.callable
898 hookname = python:/path/to/python/module.py:callable
898 hookname = python:/path/to/python/module.py:callable
899
899
900 Python hooks are run within the Mercurial process. Each hook is
900 Python hooks are run within the Mercurial process. Each hook is
901 called with at least three keyword arguments: a ui object (keyword
901 called with at least three keyword arguments: a ui object (keyword
902 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
902 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
903 keyword that tells what kind of hook is used. Arguments listed as
903 keyword that tells what kind of hook is used. Arguments listed as
904 environment variables above are passed as keyword arguments, with no
904 environment variables above are passed as keyword arguments, with no
905 ``HG_`` prefix, and names in lower case.
905 ``HG_`` prefix, and names in lower case.
906
906
907 If a Python hook returns a "true" value or raises an exception, this
907 If a Python hook returns a "true" value or raises an exception, this
908 is treated as a failure.
908 is treated as a failure.
909
909
910
910
911 ``hostfingerprints``
911 ``hostfingerprints``
912 --------------------
912 --------------------
913
913
914 Fingerprints of the certificates of known HTTPS servers.
914 Fingerprints of the certificates of known HTTPS servers.
915 A HTTPS connection to a server with a fingerprint configured here will
915 A HTTPS connection to a server with a fingerprint configured here will
916 only succeed if the servers certificate matches the fingerprint.
916 only succeed if the servers certificate matches the fingerprint.
917 This is very similar to how ssh known hosts works.
917 This is very similar to how ssh known hosts works.
918 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
918 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
919 The CA chain and web.cacerts is not used for servers with a fingerprint.
919 The CA chain and web.cacerts is not used for servers with a fingerprint.
920
920
921 For example::
921 For example::
922
922
923 [hostfingerprints]
923 [hostfingerprints]
924 hg.intevation.org = fa:1f:d9:48:f1:e7:74:30:38:8d:d8:58:b6:94:b8:58:28:7d:8b:d0
924 hg.intevation.org = fa:1f:d9:48:f1:e7:74:30:38:8d:d8:58:b6:94:b8:58:28:7d:8b:d0
925
925
926 This feature is only supported when using Python 2.6 or later.
926 This feature is only supported when using Python 2.6 or later.
927
927
928
928
929 ``http_proxy``
929 ``http_proxy``
930 --------------
930 --------------
931
931
932 Used to access web-based Mercurial repositories through a HTTP
932 Used to access web-based Mercurial repositories through a HTTP
933 proxy.
933 proxy.
934
934
935 ``host``
935 ``host``
936 Host name and (optional) port of the proxy server, for example
936 Host name and (optional) port of the proxy server, for example
937 "myproxy:8000".
937 "myproxy:8000".
938
938
939 ``no``
939 ``no``
940 Optional. Comma-separated list of host names that should bypass
940 Optional. Comma-separated list of host names that should bypass
941 the proxy.
941 the proxy.
942
942
943 ``passwd``
943 ``passwd``
944 Optional. Password to authenticate with at the proxy server.
944 Optional. Password to authenticate with at the proxy server.
945
945
946 ``user``
946 ``user``
947 Optional. User name to authenticate with at the proxy server.
947 Optional. User name to authenticate with at the proxy server.
948
948
949 ``always``
949 ``always``
950 Optional. Always use the proxy, even for localhost and any entries
950 Optional. Always use the proxy, even for localhost and any entries
951 in ``http_proxy.no``. True or False. Default: False.
951 in ``http_proxy.no``. True or False. Default: False.
952
952
953 ``merge-patterns``
953 ``merge-patterns``
954 ------------------
954 ------------------
955
955
956 This section specifies merge tools to associate with particular file
956 This section specifies merge tools to associate with particular file
957 patterns. Tools matched here will take precedence over the default
957 patterns. Tools matched here will take precedence over the default
958 merge tool. Patterns are globs by default, rooted at the repository
958 merge tool. Patterns are globs by default, rooted at the repository
959 root.
959 root.
960
960
961 Example::
961 Example::
962
962
963 [merge-patterns]
963 [merge-patterns]
964 **.c = kdiff3
964 **.c = kdiff3
965 **.jpg = myimgmerge
965 **.jpg = myimgmerge
966
966
967 ``merge-tools``
967 ``merge-tools``
968 ---------------
968 ---------------
969
969
970 This section configures external merge tools to use for file-level
970 This section configures external merge tools to use for file-level
971 merges. This section has likely been preconfigured at install time.
971 merges. This section has likely been preconfigured at install time.
972 Use :hg:`config merge-tools` to check the existing configuration.
972 Use :hg:`config merge-tools` to check the existing configuration.
973 Also see :hg:`help merge-tools` for more details.
973 Also see :hg:`help merge-tools` for more details.
974
974
975 Example ``~/.hgrc``::
975 Example ``~/.hgrc``::
976
976
977 [merge-tools]
977 [merge-tools]
978 # Override stock tool location
978 # Override stock tool location
979 kdiff3.executable = ~/bin/kdiff3
979 kdiff3.executable = ~/bin/kdiff3
980 # Specify command line
980 # Specify command line
981 kdiff3.args = $base $local $other -o $output
981 kdiff3.args = $base $local $other -o $output
982 # Give higher priority
982 # Give higher priority
983 kdiff3.priority = 1
983 kdiff3.priority = 1
984
984
985 # Changing the priority of preconfigured tool
985 # Changing the priority of preconfigured tool
986 vimdiff.priority = 0
986 vimdiff.priority = 0
987
987
988 # Define new tool
988 # Define new tool
989 myHtmlTool.args = -m $local $other $base $output
989 myHtmlTool.args = -m $local $other $base $output
990 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
990 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
991 myHtmlTool.priority = 1
991 myHtmlTool.priority = 1
992
992
993 Supported arguments:
993 Supported arguments:
994
994
995 ``priority``
995 ``priority``
996 The priority in which to evaluate this tool.
996 The priority in which to evaluate this tool.
997 Default: 0.
997 Default: 0.
998
998
999 ``executable``
999 ``executable``
1000 Either just the name of the executable or its pathname. On Windows,
1000 Either just the name of the executable or its pathname. On Windows,
1001 the path can use environment variables with ${ProgramFiles} syntax.
1001 the path can use environment variables with ${ProgramFiles} syntax.
1002 Default: the tool name.
1002 Default: the tool name.
1003
1003
1004 ``args``
1004 ``args``
1005 The arguments to pass to the tool executable. You can refer to the
1005 The arguments to pass to the tool executable. You can refer to the
1006 files being merged as well as the output file through these
1006 files being merged as well as the output file through these
1007 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
1007 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
1008 of ``$local`` and ``$other`` can vary depending on which action is being
1008 of ``$local`` and ``$other`` can vary depending on which action is being
1009 performed. During and update or merge, ``$local`` represents the original
1009 performed. During and update or merge, ``$local`` represents the original
1010 state of the file, while ``$other`` represents the commit you are updating
1010 state of the file, while ``$other`` represents the commit you are updating
1011 to or the commit you are merging with. During a rebase ``$local``
1011 to or the commit you are merging with. During a rebase ``$local``
1012 represents the destination of the rebase, and ``$other`` represents the
1012 represents the destination of the rebase, and ``$other`` represents the
1013 commit being rebased.
1013 commit being rebased.
1014 Default: ``$local $base $other``
1014 Default: ``$local $base $other``
1015
1015
1016 ``premerge``
1016 ``premerge``
1017 Attempt to run internal non-interactive 3-way merge tool before
1017 Attempt to run internal non-interactive 3-way merge tool before
1018 launching external tool. Options are ``true``, ``false``, ``keep`` or
1018 launching external tool. Options are ``true``, ``false``, ``keep`` or
1019 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1019 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1020 premerge fails. The ``keep-merge3`` will do the same but include information
1020 premerge fails. The ``keep-merge3`` will do the same but include information
1021 about the base of the merge in the marker (see internal :merge3 in
1021 about the base of the merge in the marker (see internal :merge3 in
1022 :hg:`help merge-tools`).
1022 :hg:`help merge-tools`).
1023 Default: True
1023 Default: True
1024
1024
1025 ``binary``
1025 ``binary``
1026 This tool can merge binary files. Defaults to False, unless tool
1026 This tool can merge binary files. Defaults to False, unless tool
1027 was selected by file pattern match.
1027 was selected by file pattern match.
1028
1028
1029 ``symlink``
1029 ``symlink``
1030 This tool can merge symlinks. Defaults to False, even if tool was
1030 This tool can merge symlinks. Defaults to False, even if tool was
1031 selected by file pattern match.
1031 selected by file pattern match.
1032
1032
1033 ``check``
1033 ``check``
1034 A list of merge success-checking options:
1034 A list of merge success-checking options:
1035
1035
1036 ``changed``
1036 ``changed``
1037 Ask whether merge was successful when the merged file shows no changes.
1037 Ask whether merge was successful when the merged file shows no changes.
1038 ``conflicts``
1038 ``conflicts``
1039 Check whether there are conflicts even though the tool reported success.
1039 Check whether there are conflicts even though the tool reported success.
1040 ``prompt``
1040 ``prompt``
1041 Always prompt for merge success, regardless of success reported by tool.
1041 Always prompt for merge success, regardless of success reported by tool.
1042
1042
1043 ``fixeol``
1043 ``fixeol``
1044 Attempt to fix up EOL changes caused by the merge tool.
1044 Attempt to fix up EOL changes caused by the merge tool.
1045 Default: False
1045 Default: False
1046
1046
1047 ``gui``
1047 ``gui``
1048 This tool requires a graphical interface to run. Default: False
1048 This tool requires a graphical interface to run. Default: False
1049
1049
1050 ``regkey``
1050 ``regkey``
1051 Windows registry key which describes install location of this
1051 Windows registry key which describes install location of this
1052 tool. Mercurial will search for this key first under
1052 tool. Mercurial will search for this key first under
1053 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1053 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1054 Default: None
1054 Default: None
1055
1055
1056 ``regkeyalt``
1056 ``regkeyalt``
1057 An alternate Windows registry key to try if the first key is not
1057 An alternate Windows registry key to try if the first key is not
1058 found. The alternate key uses the same ``regname`` and ``regappend``
1058 found. The alternate key uses the same ``regname`` and ``regappend``
1059 semantics of the primary key. The most common use for this key
1059 semantics of the primary key. The most common use for this key
1060 is to search for 32bit applications on 64bit operating systems.
1060 is to search for 32bit applications on 64bit operating systems.
1061 Default: None
1061 Default: None
1062
1062
1063 ``regname``
1063 ``regname``
1064 Name of value to read from specified registry key. Defaults to the
1064 Name of value to read from specified registry key. Defaults to the
1065 unnamed (default) value.
1065 unnamed (default) value.
1066
1066
1067 ``regappend``
1067 ``regappend``
1068 String to append to the value read from the registry, typically
1068 String to append to the value read from the registry, typically
1069 the executable name of the tool.
1069 the executable name of the tool.
1070 Default: None
1070 Default: None
1071
1071
1072
1072
1073 ``patch``
1073 ``patch``
1074 ---------
1074 ---------
1075
1075
1076 Settings used when applying patches, for instance through the 'import'
1076 Settings used when applying patches, for instance through the 'import'
1077 command or with Mercurial Queues extension.
1077 command or with Mercurial Queues extension.
1078
1078
1079 ``eol``
1079 ``eol``
1080 When set to 'strict' patch content and patched files end of lines
1080 When set to 'strict' patch content and patched files end of lines
1081 are preserved. When set to ``lf`` or ``crlf``, both files end of
1081 are preserved. When set to ``lf`` or ``crlf``, both files end of
1082 lines are ignored when patching and the result line endings are
1082 lines are ignored when patching and the result line endings are
1083 normalized to either LF (Unix) or CRLF (Windows). When set to
1083 normalized to either LF (Unix) or CRLF (Windows). When set to
1084 ``auto``, end of lines are again ignored while patching but line
1084 ``auto``, end of lines are again ignored while patching but line
1085 endings in patched files are normalized to their original setting
1085 endings in patched files are normalized to their original setting
1086 on a per-file basis. If target file does not exist or has no end
1086 on a per-file basis. If target file does not exist or has no end
1087 of line, patch line endings are preserved.
1087 of line, patch line endings are preserved.
1088 Default: strict.
1088 Default: strict.
1089
1089
1090
1090
1091 ``paths``
1091 ``paths``
1092 ---------
1092 ---------
1093
1093
1094 Assigns symbolic names to repositories. The left side is the
1094 Assigns symbolic names to repositories. The left side is the
1095 symbolic name, and the right gives the directory or URL that is the
1095 symbolic name, and the right gives the directory or URL that is the
1096 location of the repository. Default paths can be declared by setting
1096 location of the repository. Default paths can be declared by setting
1097 the following entries.
1097 the following entries.
1098
1098
1099 ``default``
1099 ``default``
1100 Directory or URL to use when pulling if no source is specified.
1100 Directory or URL to use when pulling if no source is specified.
1101 Default is set to repository from which the current repository was
1101 Default is set to repository from which the current repository was
1102 cloned.
1102 cloned.
1103
1103
1104 ``default-push``
1104 ``default-push``
1105 Optional. Directory or URL to use when pushing if no destination
1105 Optional. Directory or URL to use when pushing if no destination
1106 is specified.
1106 is specified.
1107
1107
1108 Custom paths can be defined by assigning the path to a name that later can be
1108 Custom paths can be defined by assigning the path to a name that later can be
1109 used from the command line. Example::
1109 used from the command line. Example::
1110
1110
1111 [paths]
1111 [paths]
1112 my_path = http://example.com/path
1112 my_path = http://example.com/path
1113
1113
1114 To push to the path defined in ``my_path`` run the command::
1114 To push to the path defined in ``my_path`` run the command::
1115
1115
1116 hg push my_path
1116 hg push my_path
1117
1117
1118
1118
1119 ``phases``
1119 ``phases``
1120 ----------
1120 ----------
1121
1121
1122 Specifies default handling of phases. See :hg:`help phases` for more
1122 Specifies default handling of phases. See :hg:`help phases` for more
1123 information about working with phases.
1123 information about working with phases.
1124
1124
1125 ``publish``
1125 ``publish``
1126 Controls draft phase behavior when working as a server. When true,
1126 Controls draft phase behavior when working as a server. When true,
1127 pushed changesets are set to public in both client and server and
1127 pushed changesets are set to public in both client and server and
1128 pulled or cloned changesets are set to public in the client.
1128 pulled or cloned changesets are set to public in the client.
1129 Default: True
1129 Default: True
1130
1130
1131 ``new-commit``
1131 ``new-commit``
1132 Phase of newly-created commits.
1132 Phase of newly-created commits.
1133 Default: draft
1133 Default: draft
1134
1134
1135 ``checksubrepos``
1135 ``checksubrepos``
1136 Check the phase of the current revision of each subrepository. Allowed
1136 Check the phase of the current revision of each subrepository. Allowed
1137 values are "ignore", "follow" and "abort". For settings other than
1137 values are "ignore", "follow" and "abort". For settings other than
1138 "ignore", the phase of the current revision of each subrepository is
1138 "ignore", the phase of the current revision of each subrepository is
1139 checked before committing the parent repository. If any of those phases is
1139 checked before committing the parent repository. If any of those phases is
1140 greater than the phase of the parent repository (e.g. if a subrepo is in a
1140 greater than the phase of the parent repository (e.g. if a subrepo is in a
1141 "secret" phase while the parent repo is in "draft" phase), the commit is
1141 "secret" phase while the parent repo is in "draft" phase), the commit is
1142 either aborted (if checksubrepos is set to "abort") or the higher phase is
1142 either aborted (if checksubrepos is set to "abort") or the higher phase is
1143 used for the parent repository commit (if set to "follow").
1143 used for the parent repository commit (if set to "follow").
1144 Default: "follow"
1144 Default: "follow"
1145
1145
1146
1146
1147 ``profiling``
1147 ``profiling``
1148 -------------
1148 -------------
1149
1149
1150 Specifies profiling type, format, and file output. Two profilers are
1150 Specifies profiling type, format, and file output. Two profilers are
1151 supported: an instrumenting profiler (named ``ls``), and a sampling
1151 supported: an instrumenting profiler (named ``ls``), and a sampling
1152 profiler (named ``stat``).
1152 profiler (named ``stat``).
1153
1153
1154 In this section description, 'profiling data' stands for the raw data
1154 In this section description, 'profiling data' stands for the raw data
1155 collected during profiling, while 'profiling report' stands for a
1155 collected during profiling, while 'profiling report' stands for a
1156 statistical text report generated from the profiling data. The
1156 statistical text report generated from the profiling data. The
1157 profiling is done using lsprof.
1157 profiling is done using lsprof.
1158
1158
1159 ``type``
1159 ``type``
1160 The type of profiler to use.
1160 The type of profiler to use.
1161 Default: ls.
1161 Default: ls.
1162
1162
1163 ``ls``
1163 ``ls``
1164 Use Python's built-in instrumenting profiler. This profiler
1164 Use Python's built-in instrumenting profiler. This profiler
1165 works on all platforms, but each line number it reports is the
1165 works on all platforms, but each line number it reports is the
1166 first line of a function. This restriction makes it difficult to
1166 first line of a function. This restriction makes it difficult to
1167 identify the expensive parts of a non-trivial function.
1167 identify the expensive parts of a non-trivial function.
1168 ``stat``
1168 ``stat``
1169 Use a third-party statistical profiler, statprof. This profiler
1169 Use a third-party statistical profiler, statprof. This profiler
1170 currently runs only on Unix systems, and is most useful for
1170 currently runs only on Unix systems, and is most useful for
1171 profiling commands that run for longer than about 0.1 seconds.
1171 profiling commands that run for longer than about 0.1 seconds.
1172
1172
1173 ``format``
1173 ``format``
1174 Profiling format. Specific to the ``ls`` instrumenting profiler.
1174 Profiling format. Specific to the ``ls`` instrumenting profiler.
1175 Default: text.
1175 Default: text.
1176
1176
1177 ``text``
1177 ``text``
1178 Generate a profiling report. When saving to a file, it should be
1178 Generate a profiling report. When saving to a file, it should be
1179 noted that only the report is saved, and the profiling data is
1179 noted that only the report is saved, and the profiling data is
1180 not kept.
1180 not kept.
1181 ``kcachegrind``
1181 ``kcachegrind``
1182 Format profiling data for kcachegrind use: when saving to a
1182 Format profiling data for kcachegrind use: when saving to a
1183 file, the generated file can directly be loaded into
1183 file, the generated file can directly be loaded into
1184 kcachegrind.
1184 kcachegrind.
1185
1185
1186 ``frequency``
1186 ``frequency``
1187 Sampling frequency. Specific to the ``stat`` sampling profiler.
1187 Sampling frequency. Specific to the ``stat`` sampling profiler.
1188 Default: 1000.
1188 Default: 1000.
1189
1189
1190 ``output``
1190 ``output``
1191 File path where profiling data or report should be saved. If the
1191 File path where profiling data or report should be saved. If the
1192 file exists, it is replaced. Default: None, data is printed on
1192 file exists, it is replaced. Default: None, data is printed on
1193 stderr
1193 stderr
1194
1194
1195 ``sort``
1195 ``sort``
1196 Sort field. Specific to the ``ls`` instrumenting profiler.
1196 Sort field. Specific to the ``ls`` instrumenting profiler.
1197 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1197 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1198 ``inlinetime``.
1198 ``inlinetime``.
1199 Default: inlinetime.
1199 Default: inlinetime.
1200
1200
1201 ``limit``
1201 ``limit``
1202 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1202 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1203 Default: 30.
1203 Default: 30.
1204
1204
1205 ``nested``
1205 ``nested``
1206 Show at most this number of lines of drill-down info after each main entry.
1206 Show at most this number of lines of drill-down info after each main entry.
1207 This can help explain the difference between Total and Inline.
1207 This can help explain the difference between Total and Inline.
1208 Specific to the ``ls`` instrumenting profiler.
1208 Specific to the ``ls`` instrumenting profiler.
1209 Default: 5.
1209 Default: 5.
1210
1210
1211 ``revsetalias``
1211 ``revsetalias``
1212 ---------------
1212 ---------------
1213
1213
1214 Alias definitions for revsets. See :hg:`help revsets` for details.
1214 Alias definitions for revsets. See :hg:`help revsets` for details.
1215
1215
1216 ``server``
1216 ``server``
1217 ----------
1217 ----------
1218
1218
1219 Controls generic server settings.
1219 Controls generic server settings.
1220
1220
1221 ``uncompressed``
1221 ``uncompressed``
1222 Whether to allow clients to clone a repository using the
1222 Whether to allow clients to clone a repository using the
1223 uncompressed streaming protocol. This transfers about 40% more
1223 uncompressed streaming protocol. This transfers about 40% more
1224 data than a regular clone, but uses less memory and CPU on both
1224 data than a regular clone, but uses less memory and CPU on both
1225 server and client. Over a LAN (100 Mbps or better) or a very fast
1225 server and client. Over a LAN (100 Mbps or better) or a very fast
1226 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1226 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1227 regular clone. Over most WAN connections (anything slower than
1227 regular clone. Over most WAN connections (anything slower than
1228 about 6 Mbps), uncompressed streaming is slower, because of the
1228 about 6 Mbps), uncompressed streaming is slower, because of the
1229 extra data transfer overhead. This mode will also temporarily hold
1229 extra data transfer overhead. This mode will also temporarily hold
1230 the write lock while determining what data to transfer.
1230 the write lock while determining what data to transfer.
1231 Default is True.
1231 Default is True.
1232
1232
1233 ``preferuncompressed``
1233 ``preferuncompressed``
1234 When set, clients will try to use the uncompressed streaming
1234 When set, clients will try to use the uncompressed streaming
1235 protocol. Default is False.
1235 protocol. Default is False.
1236
1236
1237 ``validate``
1237 ``validate``
1238 Whether to validate the completeness of pushed changesets by
1238 Whether to validate the completeness of pushed changesets by
1239 checking that all new file revisions specified in manifests are
1239 checking that all new file revisions specified in manifests are
1240 present. Default is False.
1240 present. Default is False.
1241
1241
1242 ``smtp``
1242 ``smtp``
1243 --------
1243 --------
1244
1244
1245 Configuration for extensions that need to send email messages.
1245 Configuration for extensions that need to send email messages.
1246
1246
1247 ``host``
1247 ``host``
1248 Host name of mail server, e.g. "mail.example.com".
1248 Host name of mail server, e.g. "mail.example.com".
1249
1249
1250 ``port``
1250 ``port``
1251 Optional. Port to connect to on mail server. Default: 465 (if
1251 Optional. Port to connect to on mail server. Default: 465 (if
1252 ``tls`` is smtps) or 25 (otherwise).
1252 ``tls`` is smtps) or 25 (otherwise).
1253
1253
1254 ``tls``
1254 ``tls``
1255 Optional. Method to enable TLS when connecting to mail server: starttls,
1255 Optional. Method to enable TLS when connecting to mail server: starttls,
1256 smtps or none. Default: none.
1256 smtps or none. Default: none.
1257
1257
1258 ``verifycert``
1258 ``verifycert``
1259 Optional. Verification for the certificate of mail server, when
1259 Optional. Verification for the certificate of mail server, when
1260 ``tls`` is starttls or smtps. "strict", "loose" or False. For
1260 ``tls`` is starttls or smtps. "strict", "loose" or False. For
1261 "strict" or "loose", the certificate is verified as same as the
1261 "strict" or "loose", the certificate is verified as same as the
1262 verification for HTTPS connections (see ``[hostfingerprints]`` and
1262 verification for HTTPS connections (see ``[hostfingerprints]`` and
1263 ``[web] cacerts`` also). For "strict", sending email is also
1263 ``[web] cacerts`` also). For "strict", sending email is also
1264 aborted, if there is no configuration for mail server in
1264 aborted, if there is no configuration for mail server in
1265 ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for
1265 ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for
1266 :hg:`email` overwrites this as "loose". Default: "strict".
1266 :hg:`email` overwrites this as "loose". Default: "strict".
1267
1267
1268 ``username``
1268 ``username``
1269 Optional. User name for authenticating with the SMTP server.
1269 Optional. User name for authenticating with the SMTP server.
1270 Default: none.
1270 Default: none.
1271
1271
1272 ``password``
1272 ``password``
1273 Optional. Password for authenticating with the SMTP server. If not
1273 Optional. Password for authenticating with the SMTP server. If not
1274 specified, interactive sessions will prompt the user for a
1274 specified, interactive sessions will prompt the user for a
1275 password; non-interactive sessions will fail. Default: none.
1275 password; non-interactive sessions will fail. Default: none.
1276
1276
1277 ``local_hostname``
1277 ``local_hostname``
1278 Optional. It's the hostname that the sender can use to identify
1278 Optional. It's the hostname that the sender can use to identify
1279 itself to the MTA.
1279 itself to the MTA.
1280
1280
1281
1281
1282 ``subpaths``
1282 ``subpaths``
1283 ------------
1283 ------------
1284
1284
1285 Subrepository source URLs can go stale if a remote server changes name
1285 Subrepository source URLs can go stale if a remote server changes name
1286 or becomes temporarily unavailable. This section lets you define
1286 or becomes temporarily unavailable. This section lets you define
1287 rewrite rules of the form::
1287 rewrite rules of the form::
1288
1288
1289 <pattern> = <replacement>
1289 <pattern> = <replacement>
1290
1290
1291 where ``pattern`` is a regular expression matching a subrepository
1291 where ``pattern`` is a regular expression matching a subrepository
1292 source URL and ``replacement`` is the replacement string used to
1292 source URL and ``replacement`` is the replacement string used to
1293 rewrite it. Groups can be matched in ``pattern`` and referenced in
1293 rewrite it. Groups can be matched in ``pattern`` and referenced in
1294 ``replacements``. For instance::
1294 ``replacements``. For instance::
1295
1295
1296 http://server/(.*)-hg/ = http://hg.server/\1/
1296 http://server/(.*)-hg/ = http://hg.server/\1/
1297
1297
1298 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1298 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1299
1299
1300 Relative subrepository paths are first made absolute, and the
1300 Relative subrepository paths are first made absolute, and the
1301 rewrite rules are then applied on the full (absolute) path. The rules
1301 rewrite rules are then applied on the full (absolute) path. The rules
1302 are applied in definition order.
1302 are applied in definition order.
1303
1303
1304 ``trusted``
1304 ``trusted``
1305 -----------
1305 -----------
1306
1306
1307 Mercurial will not use the settings in the
1307 Mercurial will not use the settings in the
1308 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1308 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1309 user or to a trusted group, as various hgrc features allow arbitrary
1309 user or to a trusted group, as various hgrc features allow arbitrary
1310 commands to be run. This issue is often encountered when configuring
1310 commands to be run. This issue is often encountered when configuring
1311 hooks or extensions for shared repositories or servers. However,
1311 hooks or extensions for shared repositories or servers. However,
1312 the web interface will use some safe settings from the ``[web]``
1312 the web interface will use some safe settings from the ``[web]``
1313 section.
1313 section.
1314
1314
1315 This section specifies what users and groups are trusted. The
1315 This section specifies what users and groups are trusted. The
1316 current user is always trusted. To trust everybody, list a user or a
1316 current user is always trusted. To trust everybody, list a user or a
1317 group with name ``*``. These settings must be placed in an
1317 group with name ``*``. These settings must be placed in an
1318 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1318 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1319 user or service running Mercurial.
1319 user or service running Mercurial.
1320
1320
1321 ``users``
1321 ``users``
1322 Comma-separated list of trusted users.
1322 Comma-separated list of trusted users.
1323
1323
1324 ``groups``
1324 ``groups``
1325 Comma-separated list of trusted groups.
1325 Comma-separated list of trusted groups.
1326
1326
1327
1327
1328 ``ui``
1328 ``ui``
1329 ------
1329 ------
1330
1330
1331 User interface controls.
1331 User interface controls.
1332
1332
1333 ``archivemeta``
1333 ``archivemeta``
1334 Whether to include the .hg_archival.txt file containing meta data
1334 Whether to include the .hg_archival.txt file containing meta data
1335 (hashes for the repository base and for tip) in archives created
1335 (hashes for the repository base and for tip) in archives created
1336 by the :hg:`archive` command or downloaded via hgweb.
1336 by the :hg:`archive` command or downloaded via hgweb.
1337 Default is True.
1337 Default is True.
1338
1338
1339 ``askusername``
1339 ``askusername``
1340 Whether to prompt for a username when committing. If True, and
1340 Whether to prompt for a username when committing. If True, and
1341 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1341 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1342 be prompted to enter a username. If no username is entered, the
1342 be prompted to enter a username. If no username is entered, the
1343 default ``USER@HOST`` is used instead.
1343 default ``USER@HOST`` is used instead.
1344 Default is False.
1344 Default is False.
1345
1345
1346 ``commitsubrepos``
1346 ``commitsubrepos``
1347 Whether to commit modified subrepositories when committing the
1347 Whether to commit modified subrepositories when committing the
1348 parent repository. If False and one subrepository has uncommitted
1348 parent repository. If False and one subrepository has uncommitted
1349 changes, abort the commit.
1349 changes, abort the commit.
1350 Default is False.
1350 Default is False.
1351
1351
1352 ``debug``
1352 ``debug``
1353 Print debugging information. True or False. Default is False.
1353 Print debugging information. True or False. Default is False.
1354
1354
1355 ``editor``
1355 ``editor``
1356 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1356 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1357
1357
1358 ``fallbackencoding``
1358 ``fallbackencoding``
1359 Encoding to try if it's not possible to decode the changelog using
1359 Encoding to try if it's not possible to decode the changelog using
1360 UTF-8. Default is ISO-8859-1.
1360 UTF-8. Default is ISO-8859-1.
1361
1361
1362 ``ignore``
1362 ``ignore``
1363 A file to read per-user ignore patterns from. This file should be
1363 A file to read per-user ignore patterns from. This file should be
1364 in the same format as a repository-wide .hgignore file. Filenames
1364 in the same format as a repository-wide .hgignore file. Filenames
1365 are relative to the repository root. This option supports hook syntax,
1365 are relative to the repository root. This option supports hook syntax,
1366 so if you want to specify multiple ignore files, you can do so by
1366 so if you want to specify multiple ignore files, you can do so by
1367 setting something like ``ignore.other = ~/.hgignore2``. For details
1367 setting something like ``ignore.other = ~/.hgignore2``. For details
1368 of the ignore file format, see the ``hgignore(5)`` man page.
1368 of the ignore file format, see the ``hgignore(5)`` man page.
1369
1369
1370 ``interactive``
1370 ``interactive``
1371 Allow to prompt the user. True or False. Default is True.
1371 Allow to prompt the user. True or False. Default is True.
1372
1372
1373 ``logtemplate``
1373 ``logtemplate``
1374 Template string for commands that print changesets.
1374 Template string for commands that print changesets.
1375
1375
1376 ``merge``
1376 ``merge``
1377 The conflict resolution program to use during a manual merge.
1377 The conflict resolution program to use during a manual merge.
1378 For more information on merge tools see :hg:`help merge-tools`.
1378 For more information on merge tools see :hg:`help merge-tools`.
1379 For configuring merge tools see the ``[merge-tools]`` section.
1379 For configuring merge tools see the ``[merge-tools]`` section.
1380
1380
1381 ``mergemarkers``
1381 ``mergemarkers``
1382 Sets the merge conflict marker label styling. The ``detailed``
1382 Sets the merge conflict marker label styling. The ``detailed``
1383 style uses the ``mergemarkertemplate`` setting to style the labels.
1383 style uses the ``mergemarkertemplate`` setting to style the labels.
1384 The ``basic`` style just uses 'local' and 'other' as the marker label.
1384 The ``basic`` style just uses 'local' and 'other' as the marker label.
1385 One of ``basic`` or ``detailed``.
1385 One of ``basic`` or ``detailed``.
1386 Default is ``basic``.
1386 Default is ``basic``.
1387
1387
1388 ``mergemarkertemplate``
1388 ``mergemarkertemplate``
1389 The template used to print the commit description next to each conflict
1389 The template used to print the commit description next to each conflict
1390 marker during merge conflicts. See :hg:`help templates` for the template
1390 marker during merge conflicts. See :hg:`help templates` for the template
1391 format.
1391 format.
1392 Defaults to showing the hash, tags, branches, bookmarks, author, and
1392 Defaults to showing the hash, tags, branches, bookmarks, author, and
1393 the first line of the commit description.
1393 the first line of the commit description.
1394 If you use non-ASCII characters in names for tags, branches, bookmarks,
1394 If you use non-ASCII characters in names for tags, branches, bookmarks,
1395 authors, and/or commit descriptions, you must pay attention to encodings of
1395 authors, and/or commit descriptions, you must pay attention to encodings of
1396 managed files. At template expansion, non-ASCII characters use the encoding
1396 managed files. At template expansion, non-ASCII characters use the encoding
1397 specified by the ``--encoding`` global option, ``HGENCODING`` or other
1397 specified by the ``--encoding`` global option, ``HGENCODING`` or other
1398 environment variables that govern your locale. If the encoding of the merge
1398 environment variables that govern your locale. If the encoding of the merge
1399 markers is different from the encoding of the merged files,
1399 markers is different from the encoding of the merged files,
1400 serious problems may occur.
1400 serious problems may occur.
1401
1401
1402 ``portablefilenames``
1402 ``portablefilenames``
1403 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1403 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1404 Default is ``warn``.
1404 Default is ``warn``.
1405 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1405 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1406 platforms, if a file with a non-portable filename is added (e.g. a file
1406 platforms, if a file with a non-portable filename is added (e.g. a file
1407 with a name that can't be created on Windows because it contains reserved
1407 with a name that can't be created on Windows because it contains reserved
1408 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1408 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1409 collision with an existing file).
1409 collision with an existing file).
1410 If set to ``ignore`` (or ``false``), no warning is printed.
1410 If set to ``ignore`` (or ``false``), no warning is printed.
1411 If set to ``abort``, the command is aborted.
1411 If set to ``abort``, the command is aborted.
1412 On Windows, this configuration option is ignored and the command aborted.
1412 On Windows, this configuration option is ignored and the command aborted.
1413
1413
1414 ``quiet``
1414 ``quiet``
1415 Reduce the amount of output printed. True or False. Default is False.
1415 Reduce the amount of output printed. True or False. Default is False.
1416
1416
1417 ``remotecmd``
1417 ``remotecmd``
1418 remote command to use for clone/push/pull operations. Default is ``hg``.
1418 remote command to use for clone/push/pull operations. Default is ``hg``.
1419
1419
1420 ``reportoldssl``
1420 ``reportoldssl``
1421 Warn if an SSL certificate is unable to be used due to using Python
1421 Warn if an SSL certificate is unable to be used due to using Python
1422 2.5 or earlier. True or False. Default is True.
1422 2.5 or earlier. True or False. Default is True.
1423
1423
1424 ``report_untrusted``
1424 ``report_untrusted``
1425 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1425 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1426 trusted user or group. True or False. Default is True.
1426 trusted user or group. True or False. Default is True.
1427
1427
1428 ``slash``
1428 ``slash``
1429 Display paths using a slash (``/``) as the path separator. This
1429 Display paths using a slash (``/``) as the path separator. This
1430 only makes a difference on systems where the default path
1430 only makes a difference on systems where the default path
1431 separator is not the slash character (e.g. Windows uses the
1431 separator is not the slash character (e.g. Windows uses the
1432 backslash character (``\``)).
1432 backslash character (``\``)).
1433 Default is False.
1433 Default is False.
1434
1434
1435 ``statuscopies``
1436 Display copies in the status command.
1437
1435 ``ssh``
1438 ``ssh``
1436 command to use for SSH connections. Default is ``ssh``.
1439 command to use for SSH connections. Default is ``ssh``.
1437
1440
1438 ``strict``
1441 ``strict``
1439 Require exact command names, instead of allowing unambiguous
1442 Require exact command names, instead of allowing unambiguous
1440 abbreviations. True or False. Default is False.
1443 abbreviations. True or False. Default is False.
1441
1444
1442 ``style``
1445 ``style``
1443 Name of style to use for command output.
1446 Name of style to use for command output.
1444
1447
1445 ``timeout``
1448 ``timeout``
1446 The timeout used when a lock is held (in seconds), a negative value
1449 The timeout used when a lock is held (in seconds), a negative value
1447 means no timeout. Default is 600.
1450 means no timeout. Default is 600.
1448
1451
1449 ``traceback``
1452 ``traceback``
1450 Mercurial always prints a traceback when an unknown exception
1453 Mercurial always prints a traceback when an unknown exception
1451 occurs. Setting this to True will make Mercurial print a traceback
1454 occurs. Setting this to True will make Mercurial print a traceback
1452 on all exceptions, even those recognized by Mercurial (such as
1455 on all exceptions, even those recognized by Mercurial (such as
1453 IOError or MemoryError). Default is False.
1456 IOError or MemoryError). Default is False.
1454
1457
1455 ``username``
1458 ``username``
1456 The committer of a changeset created when running "commit".
1459 The committer of a changeset created when running "commit".
1457 Typically a person's name and email address, e.g. ``Fred Widget
1460 Typically a person's name and email address, e.g. ``Fred Widget
1458 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1461 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1459 the username in hgrc is empty, it has to be specified manually or
1462 the username in hgrc is empty, it has to be specified manually or
1460 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1463 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1461 ``username =`` in the system hgrc). Environment variables in the
1464 ``username =`` in the system hgrc). Environment variables in the
1462 username are expanded.
1465 username are expanded.
1463
1466
1464 ``verbose``
1467 ``verbose``
1465 Increase the amount of output printed. True or False. Default is False.
1468 Increase the amount of output printed. True or False. Default is False.
1466
1469
1467
1470
1468 ``web``
1471 ``web``
1469 -------
1472 -------
1470
1473
1471 Web interface configuration. The settings in this section apply to
1474 Web interface configuration. The settings in this section apply to
1472 both the builtin webserver (started by :hg:`serve`) and the script you
1475 both the builtin webserver (started by :hg:`serve`) and the script you
1473 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1476 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1474 and WSGI).
1477 and WSGI).
1475
1478
1476 The Mercurial webserver does no authentication (it does not prompt for
1479 The Mercurial webserver does no authentication (it does not prompt for
1477 usernames and passwords to validate *who* users are), but it does do
1480 usernames and passwords to validate *who* users are), but it does do
1478 authorization (it grants or denies access for *authenticated users*
1481 authorization (it grants or denies access for *authenticated users*
1479 based on settings in this section). You must either configure your
1482 based on settings in this section). You must either configure your
1480 webserver to do authentication for you, or disable the authorization
1483 webserver to do authentication for you, or disable the authorization
1481 checks.
1484 checks.
1482
1485
1483 For a quick setup in a trusted environment, e.g., a private LAN, where
1486 For a quick setup in a trusted environment, e.g., a private LAN, where
1484 you want it to accept pushes from anybody, you can use the following
1487 you want it to accept pushes from anybody, you can use the following
1485 command line::
1488 command line::
1486
1489
1487 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1490 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1488
1491
1489 Note that this will allow anybody to push anything to the server and
1492 Note that this will allow anybody to push anything to the server and
1490 that this should not be used for public servers.
1493 that this should not be used for public servers.
1491
1494
1492 The full set of options is:
1495 The full set of options is:
1493
1496
1494 ``accesslog``
1497 ``accesslog``
1495 Where to output the access log. Default is stdout.
1498 Where to output the access log. Default is stdout.
1496
1499
1497 ``address``
1500 ``address``
1498 Interface address to bind to. Default is all.
1501 Interface address to bind to. Default is all.
1499
1502
1500 ``allow_archive``
1503 ``allow_archive``
1501 List of archive format (bz2, gz, zip) allowed for downloading.
1504 List of archive format (bz2, gz, zip) allowed for downloading.
1502 Default is empty.
1505 Default is empty.
1503
1506
1504 ``allowbz2``
1507 ``allowbz2``
1505 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1508 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1506 revisions.
1509 revisions.
1507 Default is False.
1510 Default is False.
1508
1511
1509 ``allowgz``
1512 ``allowgz``
1510 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1513 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1511 revisions.
1514 revisions.
1512 Default is False.
1515 Default is False.
1513
1516
1514 ``allowpull``
1517 ``allowpull``
1515 Whether to allow pulling from the repository. Default is True.
1518 Whether to allow pulling from the repository. Default is True.
1516
1519
1517 ``allow_push``
1520 ``allow_push``
1518 Whether to allow pushing to the repository. If empty or not set,
1521 Whether to allow pushing to the repository. If empty or not set,
1519 push is not allowed. If the special value ``*``, any remote user can
1522 push is not allowed. If the special value ``*``, any remote user can
1520 push, including unauthenticated users. Otherwise, the remote user
1523 push, including unauthenticated users. Otherwise, the remote user
1521 must have been authenticated, and the authenticated user name must
1524 must have been authenticated, and the authenticated user name must
1522 be present in this list. The contents of the allow_push list are
1525 be present in this list. The contents of the allow_push list are
1523 examined after the deny_push list.
1526 examined after the deny_push list.
1524
1527
1525 ``allow_read``
1528 ``allow_read``
1526 If the user has not already been denied repository access due to
1529 If the user has not already been denied repository access due to
1527 the contents of deny_read, this list determines whether to grant
1530 the contents of deny_read, this list determines whether to grant
1528 repository access to the user. If this list is not empty, and the
1531 repository access to the user. If this list is not empty, and the
1529 user is unauthenticated or not present in the list, then access is
1532 user is unauthenticated or not present in the list, then access is
1530 denied for the user. If the list is empty or not set, then access
1533 denied for the user. If the list is empty or not set, then access
1531 is permitted to all users by default. Setting allow_read to the
1534 is permitted to all users by default. Setting allow_read to the
1532 special value ``*`` is equivalent to it not being set (i.e. access
1535 special value ``*`` is equivalent to it not being set (i.e. access
1533 is permitted to all users). The contents of the allow_read list are
1536 is permitted to all users). The contents of the allow_read list are
1534 examined after the deny_read list.
1537 examined after the deny_read list.
1535
1538
1536 ``allowzip``
1539 ``allowzip``
1537 (DEPRECATED) Whether to allow .zip downloading of repository
1540 (DEPRECATED) Whether to allow .zip downloading of repository
1538 revisions. Default is False. This feature creates temporary files.
1541 revisions. Default is False. This feature creates temporary files.
1539
1542
1540 ``archivesubrepos``
1543 ``archivesubrepos``
1541 Whether to recurse into subrepositories when archiving. Default is
1544 Whether to recurse into subrepositories when archiving. Default is
1542 False.
1545 False.
1543
1546
1544 ``baseurl``
1547 ``baseurl``
1545 Base URL to use when publishing URLs in other locations, so
1548 Base URL to use when publishing URLs in other locations, so
1546 third-party tools like email notification hooks can construct
1549 third-party tools like email notification hooks can construct
1547 URLs. Example: ``http://hgserver/repos/``.
1550 URLs. Example: ``http://hgserver/repos/``.
1548
1551
1549 ``cacerts``
1552 ``cacerts``
1550 Path to file containing a list of PEM encoded certificate
1553 Path to file containing a list of PEM encoded certificate
1551 authority certificates. Environment variables and ``~user``
1554 authority certificates. Environment variables and ``~user``
1552 constructs are expanded in the filename. If specified on the
1555 constructs are expanded in the filename. If specified on the
1553 client, then it will verify the identity of remote HTTPS servers
1556 client, then it will verify the identity of remote HTTPS servers
1554 with these certificates.
1557 with these certificates.
1555
1558
1556 This feature is only supported when using Python 2.6 or later. If you wish
1559 This feature is only supported when using Python 2.6 or later. If you wish
1557 to use it with earlier versions of Python, install the backported
1560 to use it with earlier versions of Python, install the backported
1558 version of the ssl library that is available from
1561 version of the ssl library that is available from
1559 ``http://pypi.python.org``.
1562 ``http://pypi.python.org``.
1560
1563
1561 To disable SSL verification temporarily, specify ``--insecure`` from
1564 To disable SSL verification temporarily, specify ``--insecure`` from
1562 command line.
1565 command line.
1563
1566
1564 You can use OpenSSL's CA certificate file if your platform has
1567 You can use OpenSSL's CA certificate file if your platform has
1565 one. On most Linux systems this will be
1568 one. On most Linux systems this will be
1566 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1569 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1567 generate this file manually. The form must be as follows::
1570 generate this file manually. The form must be as follows::
1568
1571
1569 -----BEGIN CERTIFICATE-----
1572 -----BEGIN CERTIFICATE-----
1570 ... (certificate in base64 PEM encoding) ...
1573 ... (certificate in base64 PEM encoding) ...
1571 -----END CERTIFICATE-----
1574 -----END CERTIFICATE-----
1572 -----BEGIN CERTIFICATE-----
1575 -----BEGIN CERTIFICATE-----
1573 ... (certificate in base64 PEM encoding) ...
1576 ... (certificate in base64 PEM encoding) ...
1574 -----END CERTIFICATE-----
1577 -----END CERTIFICATE-----
1575
1578
1576 ``cache``
1579 ``cache``
1577 Whether to support caching in hgweb. Defaults to True.
1580 Whether to support caching in hgweb. Defaults to True.
1578
1581
1579 ``collapse``
1582 ``collapse``
1580 With ``descend`` enabled, repositories in subdirectories are shown at
1583 With ``descend`` enabled, repositories in subdirectories are shown at
1581 a single level alongside repositories in the current path. With
1584 a single level alongside repositories in the current path. With
1582 ``collapse`` also enabled, repositories residing at a deeper level than
1585 ``collapse`` also enabled, repositories residing at a deeper level than
1583 the current path are grouped behind navigable directory entries that
1586 the current path are grouped behind navigable directory entries that
1584 lead to the locations of these repositories. In effect, this setting
1587 lead to the locations of these repositories. In effect, this setting
1585 collapses each collection of repositories found within a subdirectory
1588 collapses each collection of repositories found within a subdirectory
1586 into a single entry for that subdirectory. Default is False.
1589 into a single entry for that subdirectory. Default is False.
1587
1590
1588 ``comparisoncontext``
1591 ``comparisoncontext``
1589 Number of lines of context to show in side-by-side file comparison. If
1592 Number of lines of context to show in side-by-side file comparison. If
1590 negative or the value ``full``, whole files are shown. Default is 5.
1593 negative or the value ``full``, whole files are shown. Default is 5.
1591 This setting can be overridden by a ``context`` request parameter to the
1594 This setting can be overridden by a ``context`` request parameter to the
1592 ``comparison`` command, taking the same values.
1595 ``comparison`` command, taking the same values.
1593
1596
1594 ``contact``
1597 ``contact``
1595 Name or email address of the person in charge of the repository.
1598 Name or email address of the person in charge of the repository.
1596 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1599 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1597
1600
1598 ``deny_push``
1601 ``deny_push``
1599 Whether to deny pushing to the repository. If empty or not set,
1602 Whether to deny pushing to the repository. If empty or not set,
1600 push is not denied. If the special value ``*``, all remote users are
1603 push is not denied. If the special value ``*``, all remote users are
1601 denied push. Otherwise, unauthenticated users are all denied, and
1604 denied push. Otherwise, unauthenticated users are all denied, and
1602 any authenticated user name present in this list is also denied. The
1605 any authenticated user name present in this list is also denied. The
1603 contents of the deny_push list are examined before the allow_push list.
1606 contents of the deny_push list are examined before the allow_push list.
1604
1607
1605 ``deny_read``
1608 ``deny_read``
1606 Whether to deny reading/viewing of the repository. If this list is
1609 Whether to deny reading/viewing of the repository. If this list is
1607 not empty, unauthenticated users are all denied, and any
1610 not empty, unauthenticated users are all denied, and any
1608 authenticated user name present in this list is also denied access to
1611 authenticated user name present in this list is also denied access to
1609 the repository. If set to the special value ``*``, all remote users
1612 the repository. If set to the special value ``*``, all remote users
1610 are denied access (rarely needed ;). If deny_read is empty or not set,
1613 are denied access (rarely needed ;). If deny_read is empty or not set,
1611 the determination of repository access depends on the presence and
1614 the determination of repository access depends on the presence and
1612 content of the allow_read list (see description). If both
1615 content of the allow_read list (see description). If both
1613 deny_read and allow_read are empty or not set, then access is
1616 deny_read and allow_read are empty or not set, then access is
1614 permitted to all users by default. If the repository is being
1617 permitted to all users by default. If the repository is being
1615 served via hgwebdir, denied users will not be able to see it in
1618 served via hgwebdir, denied users will not be able to see it in
1616 the list of repositories. The contents of the deny_read list have
1619 the list of repositories. The contents of the deny_read list have
1617 priority over (are examined before) the contents of the allow_read
1620 priority over (are examined before) the contents of the allow_read
1618 list.
1621 list.
1619
1622
1620 ``descend``
1623 ``descend``
1621 hgwebdir indexes will not descend into subdirectories. Only repositories
1624 hgwebdir indexes will not descend into subdirectories. Only repositories
1622 directly in the current path will be shown (other repositories are still
1625 directly in the current path will be shown (other repositories are still
1623 available from the index corresponding to their containing path).
1626 available from the index corresponding to their containing path).
1624
1627
1625 ``description``
1628 ``description``
1626 Textual description of the repository's purpose or contents.
1629 Textual description of the repository's purpose or contents.
1627 Default is "unknown".
1630 Default is "unknown".
1628
1631
1629 ``encoding``
1632 ``encoding``
1630 Character encoding name. Default is the current locale charset.
1633 Character encoding name. Default is the current locale charset.
1631 Example: "UTF-8"
1634 Example: "UTF-8"
1632
1635
1633 ``errorlog``
1636 ``errorlog``
1634 Where to output the error log. Default is stderr.
1637 Where to output the error log. Default is stderr.
1635
1638
1636 ``guessmime``
1639 ``guessmime``
1637 Control MIME types for raw download of file content.
1640 Control MIME types for raw download of file content.
1638 Set to True to let hgweb guess the content type from the file
1641 Set to True to let hgweb guess the content type from the file
1639 extension. This will serve HTML files as ``text/html`` and might
1642 extension. This will serve HTML files as ``text/html`` and might
1640 allow cross-site scripting attacks when serving untrusted
1643 allow cross-site scripting attacks when serving untrusted
1641 repositories. Default is False.
1644 repositories. Default is False.
1642
1645
1643 ``hidden``
1646 ``hidden``
1644 Whether to hide the repository in the hgwebdir index.
1647 Whether to hide the repository in the hgwebdir index.
1645 Default is False.
1648 Default is False.
1646
1649
1647 ``ipv6``
1650 ``ipv6``
1648 Whether to use IPv6. Default is False.
1651 Whether to use IPv6. Default is False.
1649
1652
1650 ``logoimg``
1653 ``logoimg``
1651 File name of the logo image that some templates display on each page.
1654 File name of the logo image that some templates display on each page.
1652 The file name is relative to ``staticurl``. That is, the full path to
1655 The file name is relative to ``staticurl``. That is, the full path to
1653 the logo image is "staticurl/logoimg".
1656 the logo image is "staticurl/logoimg".
1654 If unset, ``hglogo.png`` will be used.
1657 If unset, ``hglogo.png`` will be used.
1655
1658
1656 ``logourl``
1659 ``logourl``
1657 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1660 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1658 will be used.
1661 will be used.
1659
1662
1660 ``maxchanges``
1663 ``maxchanges``
1661 Maximum number of changes to list on the changelog. Default is 10.
1664 Maximum number of changes to list on the changelog. Default is 10.
1662
1665
1663 ``maxfiles``
1666 ``maxfiles``
1664 Maximum number of files to list per changeset. Default is 10.
1667 Maximum number of files to list per changeset. Default is 10.
1665
1668
1666 ``maxshortchanges``
1669 ``maxshortchanges``
1667 Maximum number of changes to list on the shortlog, graph or filelog
1670 Maximum number of changes to list on the shortlog, graph or filelog
1668 pages. Default is 60.
1671 pages. Default is 60.
1669
1672
1670 ``name``
1673 ``name``
1671 Repository name to use in the web interface. Default is current
1674 Repository name to use in the web interface. Default is current
1672 working directory.
1675 working directory.
1673
1676
1674 ``port``
1677 ``port``
1675 Port to listen on. Default is 8000.
1678 Port to listen on. Default is 8000.
1676
1679
1677 ``prefix``
1680 ``prefix``
1678 Prefix path to serve from. Default is '' (server root).
1681 Prefix path to serve from. Default is '' (server root).
1679
1682
1680 ``push_ssl``
1683 ``push_ssl``
1681 Whether to require that inbound pushes be transported over SSL to
1684 Whether to require that inbound pushes be transported over SSL to
1682 prevent password sniffing. Default is True.
1685 prevent password sniffing. Default is True.
1683
1686
1684 ``staticurl``
1687 ``staticurl``
1685 Base URL to use for static files. If unset, static files (e.g. the
1688 Base URL to use for static files. If unset, static files (e.g. the
1686 hgicon.png favicon) will be served by the CGI script itself. Use
1689 hgicon.png favicon) will be served by the CGI script itself. Use
1687 this setting to serve them directly with the HTTP server.
1690 this setting to serve them directly with the HTTP server.
1688 Example: ``http://hgserver/static/``.
1691 Example: ``http://hgserver/static/``.
1689
1692
1690 ``stripes``
1693 ``stripes``
1691 How many lines a "zebra stripe" should span in multi-line output.
1694 How many lines a "zebra stripe" should span in multi-line output.
1692 Default is 1; set to 0 to disable.
1695 Default is 1; set to 0 to disable.
1693
1696
1694 ``style``
1697 ``style``
1695 Which template map style to use. The available options are the names of
1698 Which template map style to use. The available options are the names of
1696 subdirectories in the HTML templates path. Default is ``paper``.
1699 subdirectories in the HTML templates path. Default is ``paper``.
1697 Example: ``monoblue``
1700 Example: ``monoblue``
1698
1701
1699 ``templates``
1702 ``templates``
1700 Where to find the HTML templates. The default path to the HTML templates
1703 Where to find the HTML templates. The default path to the HTML templates
1701 can be obtained from ``hg debuginstall``.
1704 can be obtained from ``hg debuginstall``.
1702
1705
1703 ``websub``
1706 ``websub``
1704 ----------
1707 ----------
1705
1708
1706 Web substitution filter definition. You can use this section to
1709 Web substitution filter definition. You can use this section to
1707 define a set of regular expression substitution patterns which
1710 define a set of regular expression substitution patterns which
1708 let you automatically modify the hgweb server output.
1711 let you automatically modify the hgweb server output.
1709
1712
1710 The default hgweb templates only apply these substitution patterns
1713 The default hgweb templates only apply these substitution patterns
1711 on the revision description fields. You can apply them anywhere
1714 on the revision description fields. You can apply them anywhere
1712 you want when you create your own templates by adding calls to the
1715 you want when you create your own templates by adding calls to the
1713 "websub" filter (usually after calling the "escape" filter).
1716 "websub" filter (usually after calling the "escape" filter).
1714
1717
1715 This can be used, for example, to convert issue references to links
1718 This can be used, for example, to convert issue references to links
1716 to your issue tracker, or to convert "markdown-like" syntax into
1719 to your issue tracker, or to convert "markdown-like" syntax into
1717 HTML (see the examples below).
1720 HTML (see the examples below).
1718
1721
1719 Each entry in this section names a substitution filter.
1722 Each entry in this section names a substitution filter.
1720 The value of each entry defines the substitution expression itself.
1723 The value of each entry defines the substitution expression itself.
1721 The websub expressions follow the old interhg extension syntax,
1724 The websub expressions follow the old interhg extension syntax,
1722 which in turn imitates the Unix sed replacement syntax::
1725 which in turn imitates the Unix sed replacement syntax::
1723
1726
1724 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
1727 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
1725
1728
1726 You can use any separator other than "/". The final "i" is optional
1729 You can use any separator other than "/". The final "i" is optional
1727 and indicates that the search must be case insensitive.
1730 and indicates that the search must be case insensitive.
1728
1731
1729 Examples::
1732 Examples::
1730
1733
1731 [websub]
1734 [websub]
1732 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
1735 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
1733 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
1736 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
1734 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
1737 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
1735
1738
1736 ``worker``
1739 ``worker``
1737 ----------
1740 ----------
1738
1741
1739 Parallel master/worker configuration. We currently perform working
1742 Parallel master/worker configuration. We currently perform working
1740 directory updates in parallel on Unix-like systems, which greatly
1743 directory updates in parallel on Unix-like systems, which greatly
1741 helps performance.
1744 helps performance.
1742
1745
1743 ``numcpus``
1746 ``numcpus``
1744 Number of CPUs to use for parallel operations. Default is 4 or the
1747 Number of CPUs to use for parallel operations. Default is 4 or the
1745 number of CPUs on the system, whichever is larger. A zero or
1748 number of CPUs on the system, whichever is larger. A zero or
1746 negative value is treated as ``use the default``.
1749 negative value is treated as ``use the default``.
@@ -1,974 +1,974 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits 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 i18n import _
8 from i18n import _
9 import errno, getpass, os, socket, sys, tempfile, traceback
9 import errno, getpass, os, socket, sys, tempfile, traceback
10 import config, scmutil, util, error, formatter
10 import config, scmutil, util, error, formatter
11 from node import hex
11 from node import hex
12
12
13 samplehgrcs = {
13 samplehgrcs = {
14 'user':
14 'user':
15 """# example user config (see "hg help config" for more info)
15 """# example user config (see "hg help config" for more info)
16 [ui]
16 [ui]
17 # name and email, e.g.
17 # name and email, e.g.
18 # username = Jane Doe <jdoe@example.com>
18 # username = Jane Doe <jdoe@example.com>
19 username =
19 username =
20
20
21 [extensions]
21 [extensions]
22 # uncomment these lines to enable some popular extensions
22 # uncomment these lines to enable some popular extensions
23 # (see "hg help extensions" for more info)
23 # (see "hg help extensions" for more info)
24 #
24 #
25 # pager =
25 # pager =
26 # progress =
26 # progress =
27 # color =""",
27 # color =""",
28
28
29 'cloned':
29 'cloned':
30 """# example repository config (see "hg help config" for more info)
30 """# example repository config (see "hg help config" for more info)
31 [paths]
31 [paths]
32 default = %s
32 default = %s
33
33
34 # path aliases to other clones of this repo in URLs or filesystem paths
34 # path aliases to other clones of this repo in URLs or filesystem paths
35 # (see "hg help config.paths" for more info)
35 # (see "hg help config.paths" for more info)
36 #
36 #
37 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
37 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
38 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
38 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
39 # my-clone = /home/jdoe/jdoes-clone
39 # my-clone = /home/jdoe/jdoes-clone
40
40
41 [ui]
41 [ui]
42 # name and email (local to this repository, optional), e.g.
42 # name and email (local to this repository, optional), e.g.
43 # username = Jane Doe <jdoe@example.com>
43 # username = Jane Doe <jdoe@example.com>
44 """,
44 """,
45
45
46 'local':
46 'local':
47 """# example repository config (see "hg help config" for more info)
47 """# example repository config (see "hg help config" for more info)
48 [paths]
48 [paths]
49 # path aliases to other clones of this repo in URLs or filesystem paths
49 # path aliases to other clones of this repo in URLs or filesystem paths
50 # (see "hg help config.paths" for more info)
50 # (see "hg help config.paths" for more info)
51 #
51 #
52 # default = http://example.com/hg/example-repo
52 # default = http://example.com/hg/example-repo
53 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
53 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
54 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
54 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
55 # my-clone = /home/jdoe/jdoes-clone
55 # my-clone = /home/jdoe/jdoes-clone
56
56
57 [ui]
57 [ui]
58 # name and email (local to this repository, optional), e.g.
58 # name and email (local to this repository, optional), e.g.
59 # username = Jane Doe <jdoe@example.com>
59 # username = Jane Doe <jdoe@example.com>
60 """,
60 """,
61
61
62 'global':
62 'global':
63 """# example system-wide hg config (see "hg help config" for more info)
63 """# example system-wide hg config (see "hg help config" for more info)
64
64
65 [extensions]
65 [extensions]
66 # uncomment these lines to enable some popular extensions
66 # uncomment these lines to enable some popular extensions
67 # (see "hg help extensions" for more info)
67 # (see "hg help extensions" for more info)
68 #
68 #
69 # blackbox =
69 # blackbox =
70 # progress =
70 # progress =
71 # color =
71 # color =
72 # pager =""",
72 # pager =""",
73 }
73 }
74
74
75 class ui(object):
75 class ui(object):
76 def __init__(self, src=None):
76 def __init__(self, src=None):
77 # _buffers: used for temporary capture of output
77 # _buffers: used for temporary capture of output
78 self._buffers = []
78 self._buffers = []
79 # _bufferstates: Should the temporary capture includes stderr
79 # _bufferstates: Should the temporary capture includes stderr
80 self._bufferstates = []
80 self._bufferstates = []
81 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
81 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
82 self._reportuntrusted = True
82 self._reportuntrusted = True
83 self._ocfg = config.config() # overlay
83 self._ocfg = config.config() # overlay
84 self._tcfg = config.config() # trusted
84 self._tcfg = config.config() # trusted
85 self._ucfg = config.config() # untrusted
85 self._ucfg = config.config() # untrusted
86 self._trustusers = set()
86 self._trustusers = set()
87 self._trustgroups = set()
87 self._trustgroups = set()
88 self.callhooks = True
88 self.callhooks = True
89
89
90 if src:
90 if src:
91 self.fout = src.fout
91 self.fout = src.fout
92 self.ferr = src.ferr
92 self.ferr = src.ferr
93 self.fin = src.fin
93 self.fin = src.fin
94
94
95 self._tcfg = src._tcfg.copy()
95 self._tcfg = src._tcfg.copy()
96 self._ucfg = src._ucfg.copy()
96 self._ucfg = src._ucfg.copy()
97 self._ocfg = src._ocfg.copy()
97 self._ocfg = src._ocfg.copy()
98 self._trustusers = src._trustusers.copy()
98 self._trustusers = src._trustusers.copy()
99 self._trustgroups = src._trustgroups.copy()
99 self._trustgroups = src._trustgroups.copy()
100 self.environ = src.environ
100 self.environ = src.environ
101 self.callhooks = src.callhooks
101 self.callhooks = src.callhooks
102 self.fixconfig()
102 self.fixconfig()
103 else:
103 else:
104 self.fout = sys.stdout
104 self.fout = sys.stdout
105 self.ferr = sys.stderr
105 self.ferr = sys.stderr
106 self.fin = sys.stdin
106 self.fin = sys.stdin
107
107
108 # shared read-only environment
108 # shared read-only environment
109 self.environ = os.environ
109 self.environ = os.environ
110 # we always trust global config files
110 # we always trust global config files
111 for f in scmutil.rcpath():
111 for f in scmutil.rcpath():
112 self.readconfig(f, trust=True)
112 self.readconfig(f, trust=True)
113
113
114 def copy(self):
114 def copy(self):
115 return self.__class__(self)
115 return self.__class__(self)
116
116
117 def formatter(self, topic, opts):
117 def formatter(self, topic, opts):
118 return formatter.formatter(self, topic, opts)
118 return formatter.formatter(self, topic, opts)
119
119
120 def _trusted(self, fp, f):
120 def _trusted(self, fp, f):
121 st = util.fstat(fp)
121 st = util.fstat(fp)
122 if util.isowner(st):
122 if util.isowner(st):
123 return True
123 return True
124
124
125 tusers, tgroups = self._trustusers, self._trustgroups
125 tusers, tgroups = self._trustusers, self._trustgroups
126 if '*' in tusers or '*' in tgroups:
126 if '*' in tusers or '*' in tgroups:
127 return True
127 return True
128
128
129 user = util.username(st.st_uid)
129 user = util.username(st.st_uid)
130 group = util.groupname(st.st_gid)
130 group = util.groupname(st.st_gid)
131 if user in tusers or group in tgroups or user == util.username():
131 if user in tusers or group in tgroups or user == util.username():
132 return True
132 return True
133
133
134 if self._reportuntrusted:
134 if self._reportuntrusted:
135 self.warn(_('not trusting file %s from untrusted '
135 self.warn(_('not trusting file %s from untrusted '
136 'user %s, group %s\n') % (f, user, group))
136 'user %s, group %s\n') % (f, user, group))
137 return False
137 return False
138
138
139 def readconfig(self, filename, root=None, trust=False,
139 def readconfig(self, filename, root=None, trust=False,
140 sections=None, remap=None):
140 sections=None, remap=None):
141 try:
141 try:
142 fp = open(filename)
142 fp = open(filename)
143 except IOError:
143 except IOError:
144 if not sections: # ignore unless we were looking for something
144 if not sections: # ignore unless we were looking for something
145 return
145 return
146 raise
146 raise
147
147
148 cfg = config.config()
148 cfg = config.config()
149 trusted = sections or trust or self._trusted(fp, filename)
149 trusted = sections or trust or self._trusted(fp, filename)
150
150
151 try:
151 try:
152 cfg.read(filename, fp, sections=sections, remap=remap)
152 cfg.read(filename, fp, sections=sections, remap=remap)
153 fp.close()
153 fp.close()
154 except error.ConfigError, inst:
154 except error.ConfigError, inst:
155 if trusted:
155 if trusted:
156 raise
156 raise
157 self.warn(_("ignored: %s\n") % str(inst))
157 self.warn(_("ignored: %s\n") % str(inst))
158
158
159 if self.plain():
159 if self.plain():
160 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
160 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
161 'logtemplate', 'style',
161 'logtemplate', 'statuscopies', 'style',
162 'traceback', 'verbose'):
162 'traceback', 'verbose'):
163 if k in cfg['ui']:
163 if k in cfg['ui']:
164 del cfg['ui'][k]
164 del cfg['ui'][k]
165 for k, v in cfg.items('defaults'):
165 for k, v in cfg.items('defaults'):
166 del cfg['defaults'][k]
166 del cfg['defaults'][k]
167 # Don't remove aliases from the configuration if in the exceptionlist
167 # Don't remove aliases from the configuration if in the exceptionlist
168 if self.plain('alias'):
168 if self.plain('alias'):
169 for k, v in cfg.items('alias'):
169 for k, v in cfg.items('alias'):
170 del cfg['alias'][k]
170 del cfg['alias'][k]
171
171
172 if trusted:
172 if trusted:
173 self._tcfg.update(cfg)
173 self._tcfg.update(cfg)
174 self._tcfg.update(self._ocfg)
174 self._tcfg.update(self._ocfg)
175 self._ucfg.update(cfg)
175 self._ucfg.update(cfg)
176 self._ucfg.update(self._ocfg)
176 self._ucfg.update(self._ocfg)
177
177
178 if root is None:
178 if root is None:
179 root = os.path.expanduser('~')
179 root = os.path.expanduser('~')
180 self.fixconfig(root=root)
180 self.fixconfig(root=root)
181
181
182 def fixconfig(self, root=None, section=None):
182 def fixconfig(self, root=None, section=None):
183 if section in (None, 'paths'):
183 if section in (None, 'paths'):
184 # expand vars and ~
184 # expand vars and ~
185 # translate paths relative to root (or home) into absolute paths
185 # translate paths relative to root (or home) into absolute paths
186 root = root or os.getcwd()
186 root = root or os.getcwd()
187 for c in self._tcfg, self._ucfg, self._ocfg:
187 for c in self._tcfg, self._ucfg, self._ocfg:
188 for n, p in c.items('paths'):
188 for n, p in c.items('paths'):
189 if not p:
189 if not p:
190 continue
190 continue
191 if '%%' in p:
191 if '%%' in p:
192 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
192 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
193 % (n, p, self.configsource('paths', n)))
193 % (n, p, self.configsource('paths', n)))
194 p = p.replace('%%', '%')
194 p = p.replace('%%', '%')
195 p = util.expandpath(p)
195 p = util.expandpath(p)
196 if not util.hasscheme(p) and not os.path.isabs(p):
196 if not util.hasscheme(p) and not os.path.isabs(p):
197 p = os.path.normpath(os.path.join(root, p))
197 p = os.path.normpath(os.path.join(root, p))
198 c.set("paths", n, p)
198 c.set("paths", n, p)
199
199
200 if section in (None, 'ui'):
200 if section in (None, 'ui'):
201 # update ui options
201 # update ui options
202 self.debugflag = self.configbool('ui', 'debug')
202 self.debugflag = self.configbool('ui', 'debug')
203 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
203 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
204 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
204 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
205 if self.verbose and self.quiet:
205 if self.verbose and self.quiet:
206 self.quiet = self.verbose = False
206 self.quiet = self.verbose = False
207 self._reportuntrusted = self.debugflag or self.configbool("ui",
207 self._reportuntrusted = self.debugflag or self.configbool("ui",
208 "report_untrusted", True)
208 "report_untrusted", True)
209 self.tracebackflag = self.configbool('ui', 'traceback', False)
209 self.tracebackflag = self.configbool('ui', 'traceback', False)
210
210
211 if section in (None, 'trusted'):
211 if section in (None, 'trusted'):
212 # update trust information
212 # update trust information
213 self._trustusers.update(self.configlist('trusted', 'users'))
213 self._trustusers.update(self.configlist('trusted', 'users'))
214 self._trustgroups.update(self.configlist('trusted', 'groups'))
214 self._trustgroups.update(self.configlist('trusted', 'groups'))
215
215
216 def backupconfig(self, section, item):
216 def backupconfig(self, section, item):
217 return (self._ocfg.backup(section, item),
217 return (self._ocfg.backup(section, item),
218 self._tcfg.backup(section, item),
218 self._tcfg.backup(section, item),
219 self._ucfg.backup(section, item),)
219 self._ucfg.backup(section, item),)
220 def restoreconfig(self, data):
220 def restoreconfig(self, data):
221 self._ocfg.restore(data[0])
221 self._ocfg.restore(data[0])
222 self._tcfg.restore(data[1])
222 self._tcfg.restore(data[1])
223 self._ucfg.restore(data[2])
223 self._ucfg.restore(data[2])
224
224
225 def setconfig(self, section, name, value, source=''):
225 def setconfig(self, section, name, value, source=''):
226 for cfg in (self._ocfg, self._tcfg, self._ucfg):
226 for cfg in (self._ocfg, self._tcfg, self._ucfg):
227 cfg.set(section, name, value, source)
227 cfg.set(section, name, value, source)
228 self.fixconfig(section=section)
228 self.fixconfig(section=section)
229
229
230 def _data(self, untrusted):
230 def _data(self, untrusted):
231 return untrusted and self._ucfg or self._tcfg
231 return untrusted and self._ucfg or self._tcfg
232
232
233 def configsource(self, section, name, untrusted=False):
233 def configsource(self, section, name, untrusted=False):
234 return self._data(untrusted).source(section, name) or 'none'
234 return self._data(untrusted).source(section, name) or 'none'
235
235
236 def config(self, section, name, default=None, untrusted=False):
236 def config(self, section, name, default=None, untrusted=False):
237 if isinstance(name, list):
237 if isinstance(name, list):
238 alternates = name
238 alternates = name
239 else:
239 else:
240 alternates = [name]
240 alternates = [name]
241
241
242 for n in alternates:
242 for n in alternates:
243 value = self._data(untrusted).get(section, n, None)
243 value = self._data(untrusted).get(section, n, None)
244 if value is not None:
244 if value is not None:
245 name = n
245 name = n
246 break
246 break
247 else:
247 else:
248 value = default
248 value = default
249
249
250 if self.debugflag and not untrusted and self._reportuntrusted:
250 if self.debugflag and not untrusted and self._reportuntrusted:
251 for n in alternates:
251 for n in alternates:
252 uvalue = self._ucfg.get(section, n)
252 uvalue = self._ucfg.get(section, n)
253 if uvalue is not None and uvalue != value:
253 if uvalue is not None and uvalue != value:
254 self.debug("ignoring untrusted configuration option "
254 self.debug("ignoring untrusted configuration option "
255 "%s.%s = %s\n" % (section, n, uvalue))
255 "%s.%s = %s\n" % (section, n, uvalue))
256 return value
256 return value
257
257
258 def configpath(self, section, name, default=None, untrusted=False):
258 def configpath(self, section, name, default=None, untrusted=False):
259 'get a path config item, expanded relative to repo root or config file'
259 'get a path config item, expanded relative to repo root or config file'
260 v = self.config(section, name, default, untrusted)
260 v = self.config(section, name, default, untrusted)
261 if v is None:
261 if v is None:
262 return None
262 return None
263 if not os.path.isabs(v) or "://" not in v:
263 if not os.path.isabs(v) or "://" not in v:
264 src = self.configsource(section, name, untrusted)
264 src = self.configsource(section, name, untrusted)
265 if ':' in src:
265 if ':' in src:
266 base = os.path.dirname(src.rsplit(':')[0])
266 base = os.path.dirname(src.rsplit(':')[0])
267 v = os.path.join(base, os.path.expanduser(v))
267 v = os.path.join(base, os.path.expanduser(v))
268 return v
268 return v
269
269
270 def configbool(self, section, name, default=False, untrusted=False):
270 def configbool(self, section, name, default=False, untrusted=False):
271 """parse a configuration element as a boolean
271 """parse a configuration element as a boolean
272
272
273 >>> u = ui(); s = 'foo'
273 >>> u = ui(); s = 'foo'
274 >>> u.setconfig(s, 'true', 'yes')
274 >>> u.setconfig(s, 'true', 'yes')
275 >>> u.configbool(s, 'true')
275 >>> u.configbool(s, 'true')
276 True
276 True
277 >>> u.setconfig(s, 'false', 'no')
277 >>> u.setconfig(s, 'false', 'no')
278 >>> u.configbool(s, 'false')
278 >>> u.configbool(s, 'false')
279 False
279 False
280 >>> u.configbool(s, 'unknown')
280 >>> u.configbool(s, 'unknown')
281 False
281 False
282 >>> u.configbool(s, 'unknown', True)
282 >>> u.configbool(s, 'unknown', True)
283 True
283 True
284 >>> u.setconfig(s, 'invalid', 'somevalue')
284 >>> u.setconfig(s, 'invalid', 'somevalue')
285 >>> u.configbool(s, 'invalid')
285 >>> u.configbool(s, 'invalid')
286 Traceback (most recent call last):
286 Traceback (most recent call last):
287 ...
287 ...
288 ConfigError: foo.invalid is not a boolean ('somevalue')
288 ConfigError: foo.invalid is not a boolean ('somevalue')
289 """
289 """
290
290
291 v = self.config(section, name, None, untrusted)
291 v = self.config(section, name, None, untrusted)
292 if v is None:
292 if v is None:
293 return default
293 return default
294 if isinstance(v, bool):
294 if isinstance(v, bool):
295 return v
295 return v
296 b = util.parsebool(v)
296 b = util.parsebool(v)
297 if b is None:
297 if b is None:
298 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
298 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
299 % (section, name, v))
299 % (section, name, v))
300 return b
300 return b
301
301
302 def configint(self, section, name, default=None, untrusted=False):
302 def configint(self, section, name, default=None, untrusted=False):
303 """parse a configuration element as an integer
303 """parse a configuration element as an integer
304
304
305 >>> u = ui(); s = 'foo'
305 >>> u = ui(); s = 'foo'
306 >>> u.setconfig(s, 'int1', '42')
306 >>> u.setconfig(s, 'int1', '42')
307 >>> u.configint(s, 'int1')
307 >>> u.configint(s, 'int1')
308 42
308 42
309 >>> u.setconfig(s, 'int2', '-42')
309 >>> u.setconfig(s, 'int2', '-42')
310 >>> u.configint(s, 'int2')
310 >>> u.configint(s, 'int2')
311 -42
311 -42
312 >>> u.configint(s, 'unknown', 7)
312 >>> u.configint(s, 'unknown', 7)
313 7
313 7
314 >>> u.setconfig(s, 'invalid', 'somevalue')
314 >>> u.setconfig(s, 'invalid', 'somevalue')
315 >>> u.configint(s, 'invalid')
315 >>> u.configint(s, 'invalid')
316 Traceback (most recent call last):
316 Traceback (most recent call last):
317 ...
317 ...
318 ConfigError: foo.invalid is not an integer ('somevalue')
318 ConfigError: foo.invalid is not an integer ('somevalue')
319 """
319 """
320
320
321 v = self.config(section, name, None, untrusted)
321 v = self.config(section, name, None, untrusted)
322 if v is None:
322 if v is None:
323 return default
323 return default
324 try:
324 try:
325 return int(v)
325 return int(v)
326 except ValueError:
326 except ValueError:
327 raise error.ConfigError(_("%s.%s is not an integer ('%s')")
327 raise error.ConfigError(_("%s.%s is not an integer ('%s')")
328 % (section, name, v))
328 % (section, name, v))
329
329
330 def configbytes(self, section, name, default=0, untrusted=False):
330 def configbytes(self, section, name, default=0, untrusted=False):
331 """parse a configuration element as a quantity in bytes
331 """parse a configuration element as a quantity in bytes
332
332
333 Units can be specified as b (bytes), k or kb (kilobytes), m or
333 Units can be specified as b (bytes), k or kb (kilobytes), m or
334 mb (megabytes), g or gb (gigabytes).
334 mb (megabytes), g or gb (gigabytes).
335
335
336 >>> u = ui(); s = 'foo'
336 >>> u = ui(); s = 'foo'
337 >>> u.setconfig(s, 'val1', '42')
337 >>> u.setconfig(s, 'val1', '42')
338 >>> u.configbytes(s, 'val1')
338 >>> u.configbytes(s, 'val1')
339 42
339 42
340 >>> u.setconfig(s, 'val2', '42.5 kb')
340 >>> u.setconfig(s, 'val2', '42.5 kb')
341 >>> u.configbytes(s, 'val2')
341 >>> u.configbytes(s, 'val2')
342 43520
342 43520
343 >>> u.configbytes(s, 'unknown', '7 MB')
343 >>> u.configbytes(s, 'unknown', '7 MB')
344 7340032
344 7340032
345 >>> u.setconfig(s, 'invalid', 'somevalue')
345 >>> u.setconfig(s, 'invalid', 'somevalue')
346 >>> u.configbytes(s, 'invalid')
346 >>> u.configbytes(s, 'invalid')
347 Traceback (most recent call last):
347 Traceback (most recent call last):
348 ...
348 ...
349 ConfigError: foo.invalid is not a byte quantity ('somevalue')
349 ConfigError: foo.invalid is not a byte quantity ('somevalue')
350 """
350 """
351
351
352 value = self.config(section, name)
352 value = self.config(section, name)
353 if value is None:
353 if value is None:
354 if not isinstance(default, str):
354 if not isinstance(default, str):
355 return default
355 return default
356 value = default
356 value = default
357 try:
357 try:
358 return util.sizetoint(value)
358 return util.sizetoint(value)
359 except error.ParseError:
359 except error.ParseError:
360 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
360 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
361 % (section, name, value))
361 % (section, name, value))
362
362
363 def configlist(self, section, name, default=None, untrusted=False):
363 def configlist(self, section, name, default=None, untrusted=False):
364 """parse a configuration element as a list of comma/space separated
364 """parse a configuration element as a list of comma/space separated
365 strings
365 strings
366
366
367 >>> u = ui(); s = 'foo'
367 >>> u = ui(); s = 'foo'
368 >>> u.setconfig(s, 'list1', 'this,is "a small" ,test')
368 >>> u.setconfig(s, 'list1', 'this,is "a small" ,test')
369 >>> u.configlist(s, 'list1')
369 >>> u.configlist(s, 'list1')
370 ['this', 'is', 'a small', 'test']
370 ['this', 'is', 'a small', 'test']
371 """
371 """
372
372
373 def _parse_plain(parts, s, offset):
373 def _parse_plain(parts, s, offset):
374 whitespace = False
374 whitespace = False
375 while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
375 while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
376 whitespace = True
376 whitespace = True
377 offset += 1
377 offset += 1
378 if offset >= len(s):
378 if offset >= len(s):
379 return None, parts, offset
379 return None, parts, offset
380 if whitespace:
380 if whitespace:
381 parts.append('')
381 parts.append('')
382 if s[offset] == '"' and not parts[-1]:
382 if s[offset] == '"' and not parts[-1]:
383 return _parse_quote, parts, offset + 1
383 return _parse_quote, parts, offset + 1
384 elif s[offset] == '"' and parts[-1][-1] == '\\':
384 elif s[offset] == '"' and parts[-1][-1] == '\\':
385 parts[-1] = parts[-1][:-1] + s[offset]
385 parts[-1] = parts[-1][:-1] + s[offset]
386 return _parse_plain, parts, offset + 1
386 return _parse_plain, parts, offset + 1
387 parts[-1] += s[offset]
387 parts[-1] += s[offset]
388 return _parse_plain, parts, offset + 1
388 return _parse_plain, parts, offset + 1
389
389
390 def _parse_quote(parts, s, offset):
390 def _parse_quote(parts, s, offset):
391 if offset < len(s) and s[offset] == '"': # ""
391 if offset < len(s) and s[offset] == '"': # ""
392 parts.append('')
392 parts.append('')
393 offset += 1
393 offset += 1
394 while offset < len(s) and (s[offset].isspace() or
394 while offset < len(s) and (s[offset].isspace() or
395 s[offset] == ','):
395 s[offset] == ','):
396 offset += 1
396 offset += 1
397 return _parse_plain, parts, offset
397 return _parse_plain, parts, offset
398
398
399 while offset < len(s) and s[offset] != '"':
399 while offset < len(s) and s[offset] != '"':
400 if (s[offset] == '\\' and offset + 1 < len(s)
400 if (s[offset] == '\\' and offset + 1 < len(s)
401 and s[offset + 1] == '"'):
401 and s[offset + 1] == '"'):
402 offset += 1
402 offset += 1
403 parts[-1] += '"'
403 parts[-1] += '"'
404 else:
404 else:
405 parts[-1] += s[offset]
405 parts[-1] += s[offset]
406 offset += 1
406 offset += 1
407
407
408 if offset >= len(s):
408 if offset >= len(s):
409 real_parts = _configlist(parts[-1])
409 real_parts = _configlist(parts[-1])
410 if not real_parts:
410 if not real_parts:
411 parts[-1] = '"'
411 parts[-1] = '"'
412 else:
412 else:
413 real_parts[0] = '"' + real_parts[0]
413 real_parts[0] = '"' + real_parts[0]
414 parts = parts[:-1]
414 parts = parts[:-1]
415 parts.extend(real_parts)
415 parts.extend(real_parts)
416 return None, parts, offset
416 return None, parts, offset
417
417
418 offset += 1
418 offset += 1
419 while offset < len(s) and s[offset] in [' ', ',']:
419 while offset < len(s) and s[offset] in [' ', ',']:
420 offset += 1
420 offset += 1
421
421
422 if offset < len(s):
422 if offset < len(s):
423 if offset + 1 == len(s) and s[offset] == '"':
423 if offset + 1 == len(s) and s[offset] == '"':
424 parts[-1] += '"'
424 parts[-1] += '"'
425 offset += 1
425 offset += 1
426 else:
426 else:
427 parts.append('')
427 parts.append('')
428 else:
428 else:
429 return None, parts, offset
429 return None, parts, offset
430
430
431 return _parse_plain, parts, offset
431 return _parse_plain, parts, offset
432
432
433 def _configlist(s):
433 def _configlist(s):
434 s = s.rstrip(' ,')
434 s = s.rstrip(' ,')
435 if not s:
435 if not s:
436 return []
436 return []
437 parser, parts, offset = _parse_plain, [''], 0
437 parser, parts, offset = _parse_plain, [''], 0
438 while parser:
438 while parser:
439 parser, parts, offset = parser(parts, s, offset)
439 parser, parts, offset = parser(parts, s, offset)
440 return parts
440 return parts
441
441
442 result = self.config(section, name, untrusted=untrusted)
442 result = self.config(section, name, untrusted=untrusted)
443 if result is None:
443 if result is None:
444 result = default or []
444 result = default or []
445 if isinstance(result, basestring):
445 if isinstance(result, basestring):
446 result = _configlist(result.lstrip(' ,\n'))
446 result = _configlist(result.lstrip(' ,\n'))
447 if result is None:
447 if result is None:
448 result = default or []
448 result = default or []
449 return result
449 return result
450
450
451 def has_section(self, section, untrusted=False):
451 def has_section(self, section, untrusted=False):
452 '''tell whether section exists in config.'''
452 '''tell whether section exists in config.'''
453 return section in self._data(untrusted)
453 return section in self._data(untrusted)
454
454
455 def configitems(self, section, untrusted=False):
455 def configitems(self, section, untrusted=False):
456 items = self._data(untrusted).items(section)
456 items = self._data(untrusted).items(section)
457 if self.debugflag and not untrusted and self._reportuntrusted:
457 if self.debugflag and not untrusted and self._reportuntrusted:
458 for k, v in self._ucfg.items(section):
458 for k, v in self._ucfg.items(section):
459 if self._tcfg.get(section, k) != v:
459 if self._tcfg.get(section, k) != v:
460 self.debug("ignoring untrusted configuration option "
460 self.debug("ignoring untrusted configuration option "
461 "%s.%s = %s\n" % (section, k, v))
461 "%s.%s = %s\n" % (section, k, v))
462 return items
462 return items
463
463
464 def walkconfig(self, untrusted=False):
464 def walkconfig(self, untrusted=False):
465 cfg = self._data(untrusted)
465 cfg = self._data(untrusted)
466 for section in cfg.sections():
466 for section in cfg.sections():
467 for name, value in self.configitems(section, untrusted):
467 for name, value in self.configitems(section, untrusted):
468 yield section, name, value
468 yield section, name, value
469
469
470 def plain(self, feature=None):
470 def plain(self, feature=None):
471 '''is plain mode active?
471 '''is plain mode active?
472
472
473 Plain mode means that all configuration variables which affect
473 Plain mode means that all configuration variables which affect
474 the behavior and output of Mercurial should be
474 the behavior and output of Mercurial should be
475 ignored. Additionally, the output should be stable,
475 ignored. Additionally, the output should be stable,
476 reproducible and suitable for use in scripts or applications.
476 reproducible and suitable for use in scripts or applications.
477
477
478 The only way to trigger plain mode is by setting either the
478 The only way to trigger plain mode is by setting either the
479 `HGPLAIN' or `HGPLAINEXCEPT' environment variables.
479 `HGPLAIN' or `HGPLAINEXCEPT' environment variables.
480
480
481 The return value can either be
481 The return value can either be
482 - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
482 - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
483 - True otherwise
483 - True otherwise
484 '''
484 '''
485 if 'HGPLAIN' not in os.environ and 'HGPLAINEXCEPT' not in os.environ:
485 if 'HGPLAIN' not in os.environ and 'HGPLAINEXCEPT' not in os.environ:
486 return False
486 return False
487 exceptions = os.environ.get('HGPLAINEXCEPT', '').strip().split(',')
487 exceptions = os.environ.get('HGPLAINEXCEPT', '').strip().split(',')
488 if feature and exceptions:
488 if feature and exceptions:
489 return feature not in exceptions
489 return feature not in exceptions
490 return True
490 return True
491
491
492 def username(self):
492 def username(self):
493 """Return default username to be used in commits.
493 """Return default username to be used in commits.
494
494
495 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
495 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
496 and stop searching if one of these is set.
496 and stop searching if one of these is set.
497 If not found and ui.askusername is True, ask the user, else use
497 If not found and ui.askusername is True, ask the user, else use
498 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
498 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
499 """
499 """
500 user = os.environ.get("HGUSER")
500 user = os.environ.get("HGUSER")
501 if user is None:
501 if user is None:
502 user = self.config("ui", ["username", "user"])
502 user = self.config("ui", ["username", "user"])
503 if user is not None:
503 if user is not None:
504 user = os.path.expandvars(user)
504 user = os.path.expandvars(user)
505 if user is None:
505 if user is None:
506 user = os.environ.get("EMAIL")
506 user = os.environ.get("EMAIL")
507 if user is None and self.configbool("ui", "askusername"):
507 if user is None and self.configbool("ui", "askusername"):
508 user = self.prompt(_("enter a commit username:"), default=None)
508 user = self.prompt(_("enter a commit username:"), default=None)
509 if user is None and not self.interactive():
509 if user is None and not self.interactive():
510 try:
510 try:
511 user = '%s@%s' % (util.getuser(), socket.getfqdn())
511 user = '%s@%s' % (util.getuser(), socket.getfqdn())
512 self.warn(_("no username found, using '%s' instead\n") % user)
512 self.warn(_("no username found, using '%s' instead\n") % user)
513 except KeyError:
513 except KeyError:
514 pass
514 pass
515 if not user:
515 if not user:
516 raise util.Abort(_('no username supplied'),
516 raise util.Abort(_('no username supplied'),
517 hint=_('use "hg config --edit" '
517 hint=_('use "hg config --edit" '
518 'to set your username'))
518 'to set your username'))
519 if "\n" in user:
519 if "\n" in user:
520 raise util.Abort(_("username %s contains a newline\n") % repr(user))
520 raise util.Abort(_("username %s contains a newline\n") % repr(user))
521 return user
521 return user
522
522
523 def shortuser(self, user):
523 def shortuser(self, user):
524 """Return a short representation of a user name or email address."""
524 """Return a short representation of a user name or email address."""
525 if not self.verbose:
525 if not self.verbose:
526 user = util.shortuser(user)
526 user = util.shortuser(user)
527 return user
527 return user
528
528
529 def expandpath(self, loc, default=None):
529 def expandpath(self, loc, default=None):
530 """Return repository location relative to cwd or from [paths]"""
530 """Return repository location relative to cwd or from [paths]"""
531 if util.hasscheme(loc) or os.path.isdir(os.path.join(loc, '.hg')):
531 if util.hasscheme(loc) or os.path.isdir(os.path.join(loc, '.hg')):
532 return loc
532 return loc
533
533
534 p = self.paths.getpath(loc, default=default)
534 p = self.paths.getpath(loc, default=default)
535 if p:
535 if p:
536 return p.loc
536 return p.loc
537 return loc
537 return loc
538
538
539 @util.propertycache
539 @util.propertycache
540 def paths(self):
540 def paths(self):
541 return paths(self)
541 return paths(self)
542
542
543 def pushbuffer(self, error=False):
543 def pushbuffer(self, error=False):
544 """install a buffer to capture standard output of the ui object
544 """install a buffer to capture standard output of the ui object
545
545
546 If error is True, the error output will be captured too."""
546 If error is True, the error output will be captured too."""
547 self._buffers.append([])
547 self._buffers.append([])
548 self._bufferstates.append(error)
548 self._bufferstates.append(error)
549
549
550 def popbuffer(self, labeled=False):
550 def popbuffer(self, labeled=False):
551 '''pop the last buffer and return the buffered output
551 '''pop the last buffer and return the buffered output
552
552
553 If labeled is True, any labels associated with buffered
553 If labeled is True, any labels associated with buffered
554 output will be handled. By default, this has no effect
554 output will be handled. By default, this has no effect
555 on the output returned, but extensions and GUI tools may
555 on the output returned, but extensions and GUI tools may
556 handle this argument and returned styled output. If output
556 handle this argument and returned styled output. If output
557 is being buffered so it can be captured and parsed or
557 is being buffered so it can be captured and parsed or
558 processed, labeled should not be set to True.
558 processed, labeled should not be set to True.
559 '''
559 '''
560 self._bufferstates.pop()
560 self._bufferstates.pop()
561 return "".join(self._buffers.pop())
561 return "".join(self._buffers.pop())
562
562
563 def write(self, *args, **opts):
563 def write(self, *args, **opts):
564 '''write args to output
564 '''write args to output
565
565
566 By default, this method simply writes to the buffer or stdout,
566 By default, this method simply writes to the buffer or stdout,
567 but extensions or GUI tools may override this method,
567 but extensions or GUI tools may override this method,
568 write_err(), popbuffer(), and label() to style output from
568 write_err(), popbuffer(), and label() to style output from
569 various parts of hg.
569 various parts of hg.
570
570
571 An optional keyword argument, "label", can be passed in.
571 An optional keyword argument, "label", can be passed in.
572 This should be a string containing label names separated by
572 This should be a string containing label names separated by
573 space. Label names take the form of "topic.type". For example,
573 space. Label names take the form of "topic.type". For example,
574 ui.debug() issues a label of "ui.debug".
574 ui.debug() issues a label of "ui.debug".
575
575
576 When labeling output for a specific command, a label of
576 When labeling output for a specific command, a label of
577 "cmdname.type" is recommended. For example, status issues
577 "cmdname.type" is recommended. For example, status issues
578 a label of "status.modified" for modified files.
578 a label of "status.modified" for modified files.
579 '''
579 '''
580 if self._buffers:
580 if self._buffers:
581 self._buffers[-1].extend([str(a) for a in args])
581 self._buffers[-1].extend([str(a) for a in args])
582 else:
582 else:
583 for a in args:
583 for a in args:
584 self.fout.write(str(a))
584 self.fout.write(str(a))
585
585
586 def write_err(self, *args, **opts):
586 def write_err(self, *args, **opts):
587 try:
587 try:
588 if self._bufferstates and self._bufferstates[-1]:
588 if self._bufferstates and self._bufferstates[-1]:
589 return self.write(*args, **opts)
589 return self.write(*args, **opts)
590 if not getattr(self.fout, 'closed', False):
590 if not getattr(self.fout, 'closed', False):
591 self.fout.flush()
591 self.fout.flush()
592 for a in args:
592 for a in args:
593 self.ferr.write(str(a))
593 self.ferr.write(str(a))
594 # stderr may be buffered under win32 when redirected to files,
594 # stderr may be buffered under win32 when redirected to files,
595 # including stdout.
595 # including stdout.
596 if not getattr(self.ferr, 'closed', False):
596 if not getattr(self.ferr, 'closed', False):
597 self.ferr.flush()
597 self.ferr.flush()
598 except IOError, inst:
598 except IOError, inst:
599 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
599 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
600 raise
600 raise
601
601
602 def flush(self):
602 def flush(self):
603 try: self.fout.flush()
603 try: self.fout.flush()
604 except (IOError, ValueError): pass
604 except (IOError, ValueError): pass
605 try: self.ferr.flush()
605 try: self.ferr.flush()
606 except (IOError, ValueError): pass
606 except (IOError, ValueError): pass
607
607
608 def _isatty(self, fh):
608 def _isatty(self, fh):
609 if self.configbool('ui', 'nontty', False):
609 if self.configbool('ui', 'nontty', False):
610 return False
610 return False
611 return util.isatty(fh)
611 return util.isatty(fh)
612
612
613 def interactive(self):
613 def interactive(self):
614 '''is interactive input allowed?
614 '''is interactive input allowed?
615
615
616 An interactive session is a session where input can be reasonably read
616 An interactive session is a session where input can be reasonably read
617 from `sys.stdin'. If this function returns false, any attempt to read
617 from `sys.stdin'. If this function returns false, any attempt to read
618 from stdin should fail with an error, unless a sensible default has been
618 from stdin should fail with an error, unless a sensible default has been
619 specified.
619 specified.
620
620
621 Interactiveness is triggered by the value of the `ui.interactive'
621 Interactiveness is triggered by the value of the `ui.interactive'
622 configuration variable or - if it is unset - when `sys.stdin' points
622 configuration variable or - if it is unset - when `sys.stdin' points
623 to a terminal device.
623 to a terminal device.
624
624
625 This function refers to input only; for output, see `ui.formatted()'.
625 This function refers to input only; for output, see `ui.formatted()'.
626 '''
626 '''
627 i = self.configbool("ui", "interactive", None)
627 i = self.configbool("ui", "interactive", None)
628 if i is None:
628 if i is None:
629 # some environments replace stdin without implementing isatty
629 # some environments replace stdin without implementing isatty
630 # usually those are non-interactive
630 # usually those are non-interactive
631 return self._isatty(self.fin)
631 return self._isatty(self.fin)
632
632
633 return i
633 return i
634
634
635 def termwidth(self):
635 def termwidth(self):
636 '''how wide is the terminal in columns?
636 '''how wide is the terminal in columns?
637 '''
637 '''
638 if 'COLUMNS' in os.environ:
638 if 'COLUMNS' in os.environ:
639 try:
639 try:
640 return int(os.environ['COLUMNS'])
640 return int(os.environ['COLUMNS'])
641 except ValueError:
641 except ValueError:
642 pass
642 pass
643 return util.termwidth()
643 return util.termwidth()
644
644
645 def formatted(self):
645 def formatted(self):
646 '''should formatted output be used?
646 '''should formatted output be used?
647
647
648 It is often desirable to format the output to suite the output medium.
648 It is often desirable to format the output to suite the output medium.
649 Examples of this are truncating long lines or colorizing messages.
649 Examples of this are truncating long lines or colorizing messages.
650 However, this is not often not desirable when piping output into other
650 However, this is not often not desirable when piping output into other
651 utilities, e.g. `grep'.
651 utilities, e.g. `grep'.
652
652
653 Formatted output is triggered by the value of the `ui.formatted'
653 Formatted output is triggered by the value of the `ui.formatted'
654 configuration variable or - if it is unset - when `sys.stdout' points
654 configuration variable or - if it is unset - when `sys.stdout' points
655 to a terminal device. Please note that `ui.formatted' should be
655 to a terminal device. Please note that `ui.formatted' should be
656 considered an implementation detail; it is not intended for use outside
656 considered an implementation detail; it is not intended for use outside
657 Mercurial or its extensions.
657 Mercurial or its extensions.
658
658
659 This function refers to output only; for input, see `ui.interactive()'.
659 This function refers to output only; for input, see `ui.interactive()'.
660 This function always returns false when in plain mode, see `ui.plain()'.
660 This function always returns false when in plain mode, see `ui.plain()'.
661 '''
661 '''
662 if self.plain():
662 if self.plain():
663 return False
663 return False
664
664
665 i = self.configbool("ui", "formatted", None)
665 i = self.configbool("ui", "formatted", None)
666 if i is None:
666 if i is None:
667 # some environments replace stdout without implementing isatty
667 # some environments replace stdout without implementing isatty
668 # usually those are non-interactive
668 # usually those are non-interactive
669 return self._isatty(self.fout)
669 return self._isatty(self.fout)
670
670
671 return i
671 return i
672
672
673 def _readline(self, prompt=''):
673 def _readline(self, prompt=''):
674 if self._isatty(self.fin):
674 if self._isatty(self.fin):
675 try:
675 try:
676 # magically add command line editing support, where
676 # magically add command line editing support, where
677 # available
677 # available
678 import readline
678 import readline
679 # force demandimport to really load the module
679 # force demandimport to really load the module
680 readline.read_history_file
680 readline.read_history_file
681 # windows sometimes raises something other than ImportError
681 # windows sometimes raises something other than ImportError
682 except Exception:
682 except Exception:
683 pass
683 pass
684
684
685 # call write() so output goes through subclassed implementation
685 # call write() so output goes through subclassed implementation
686 # e.g. color extension on Windows
686 # e.g. color extension on Windows
687 self.write(prompt)
687 self.write(prompt)
688
688
689 # instead of trying to emulate raw_input, swap (self.fin,
689 # instead of trying to emulate raw_input, swap (self.fin,
690 # self.fout) with (sys.stdin, sys.stdout)
690 # self.fout) with (sys.stdin, sys.stdout)
691 oldin = sys.stdin
691 oldin = sys.stdin
692 oldout = sys.stdout
692 oldout = sys.stdout
693 sys.stdin = self.fin
693 sys.stdin = self.fin
694 sys.stdout = self.fout
694 sys.stdout = self.fout
695 # prompt ' ' must exist; otherwise readline may delete entire line
695 # prompt ' ' must exist; otherwise readline may delete entire line
696 # - http://bugs.python.org/issue12833
696 # - http://bugs.python.org/issue12833
697 line = raw_input(' ')
697 line = raw_input(' ')
698 sys.stdin = oldin
698 sys.stdin = oldin
699 sys.stdout = oldout
699 sys.stdout = oldout
700
700
701 # When stdin is in binary mode on Windows, it can cause
701 # When stdin is in binary mode on Windows, it can cause
702 # raw_input() to emit an extra trailing carriage return
702 # raw_input() to emit an extra trailing carriage return
703 if os.linesep == '\r\n' and line and line[-1] == '\r':
703 if os.linesep == '\r\n' and line and line[-1] == '\r':
704 line = line[:-1]
704 line = line[:-1]
705 return line
705 return line
706
706
707 def prompt(self, msg, default="y"):
707 def prompt(self, msg, default="y"):
708 """Prompt user with msg, read response.
708 """Prompt user with msg, read response.
709 If ui is not interactive, the default is returned.
709 If ui is not interactive, the default is returned.
710 """
710 """
711 if not self.interactive():
711 if not self.interactive():
712 self.write(msg, ' ', default, "\n")
712 self.write(msg, ' ', default, "\n")
713 return default
713 return default
714 try:
714 try:
715 r = self._readline(self.label(msg, 'ui.prompt'))
715 r = self._readline(self.label(msg, 'ui.prompt'))
716 if not r:
716 if not r:
717 r = default
717 r = default
718 if self.configbool('ui', 'promptecho'):
718 if self.configbool('ui', 'promptecho'):
719 self.write(r, "\n")
719 self.write(r, "\n")
720 return r
720 return r
721 except EOFError:
721 except EOFError:
722 raise util.Abort(_('response expected'))
722 raise util.Abort(_('response expected'))
723
723
724 @staticmethod
724 @staticmethod
725 def extractchoices(prompt):
725 def extractchoices(prompt):
726 """Extract prompt message and list of choices from specified prompt.
726 """Extract prompt message and list of choices from specified prompt.
727
727
728 This returns tuple "(message, choices)", and "choices" is the
728 This returns tuple "(message, choices)", and "choices" is the
729 list of tuple "(response character, text without &)".
729 list of tuple "(response character, text without &)".
730 """
730 """
731 parts = prompt.split('$$')
731 parts = prompt.split('$$')
732 msg = parts[0].rstrip(' ')
732 msg = parts[0].rstrip(' ')
733 choices = [p.strip(' ') for p in parts[1:]]
733 choices = [p.strip(' ') for p in parts[1:]]
734 return (msg,
734 return (msg,
735 [(s[s.index('&') + 1].lower(), s.replace('&', '', 1))
735 [(s[s.index('&') + 1].lower(), s.replace('&', '', 1))
736 for s in choices])
736 for s in choices])
737
737
738 def promptchoice(self, prompt, default=0):
738 def promptchoice(self, prompt, default=0):
739 """Prompt user with a message, read response, and ensure it matches
739 """Prompt user with a message, read response, and ensure it matches
740 one of the provided choices. The prompt is formatted as follows:
740 one of the provided choices. The prompt is formatted as follows:
741
741
742 "would you like fries with that (Yn)? $$ &Yes $$ &No"
742 "would you like fries with that (Yn)? $$ &Yes $$ &No"
743
743
744 The index of the choice is returned. Responses are case
744 The index of the choice is returned. Responses are case
745 insensitive. If ui is not interactive, the default is
745 insensitive. If ui is not interactive, the default is
746 returned.
746 returned.
747 """
747 """
748
748
749 msg, choices = self.extractchoices(prompt)
749 msg, choices = self.extractchoices(prompt)
750 resps = [r for r, t in choices]
750 resps = [r for r, t in choices]
751 while True:
751 while True:
752 r = self.prompt(msg, resps[default])
752 r = self.prompt(msg, resps[default])
753 if r.lower() in resps:
753 if r.lower() in resps:
754 return resps.index(r.lower())
754 return resps.index(r.lower())
755 self.write(_("unrecognized response\n"))
755 self.write(_("unrecognized response\n"))
756
756
757 def getpass(self, prompt=None, default=None):
757 def getpass(self, prompt=None, default=None):
758 if not self.interactive():
758 if not self.interactive():
759 return default
759 return default
760 try:
760 try:
761 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
761 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
762 # disable getpass() only if explicitly specified. it's still valid
762 # disable getpass() only if explicitly specified. it's still valid
763 # to interact with tty even if fin is not a tty.
763 # to interact with tty even if fin is not a tty.
764 if self.configbool('ui', 'nontty'):
764 if self.configbool('ui', 'nontty'):
765 return self.fin.readline().rstrip('\n')
765 return self.fin.readline().rstrip('\n')
766 else:
766 else:
767 return getpass.getpass('')
767 return getpass.getpass('')
768 except EOFError:
768 except EOFError:
769 raise util.Abort(_('response expected'))
769 raise util.Abort(_('response expected'))
770 def status(self, *msg, **opts):
770 def status(self, *msg, **opts):
771 '''write status message to output (if ui.quiet is False)
771 '''write status message to output (if ui.quiet is False)
772
772
773 This adds an output label of "ui.status".
773 This adds an output label of "ui.status".
774 '''
774 '''
775 if not self.quiet:
775 if not self.quiet:
776 opts['label'] = opts.get('label', '') + ' ui.status'
776 opts['label'] = opts.get('label', '') + ' ui.status'
777 self.write(*msg, **opts)
777 self.write(*msg, **opts)
778 def warn(self, *msg, **opts):
778 def warn(self, *msg, **opts):
779 '''write warning message to output (stderr)
779 '''write warning message to output (stderr)
780
780
781 This adds an output label of "ui.warning".
781 This adds an output label of "ui.warning".
782 '''
782 '''
783 opts['label'] = opts.get('label', '') + ' ui.warning'
783 opts['label'] = opts.get('label', '') + ' ui.warning'
784 self.write_err(*msg, **opts)
784 self.write_err(*msg, **opts)
785 def note(self, *msg, **opts):
785 def note(self, *msg, **opts):
786 '''write note to output (if ui.verbose is True)
786 '''write note to output (if ui.verbose is True)
787
787
788 This adds an output label of "ui.note".
788 This adds an output label of "ui.note".
789 '''
789 '''
790 if self.verbose:
790 if self.verbose:
791 opts['label'] = opts.get('label', '') + ' ui.note'
791 opts['label'] = opts.get('label', '') + ' ui.note'
792 self.write(*msg, **opts)
792 self.write(*msg, **opts)
793 def debug(self, *msg, **opts):
793 def debug(self, *msg, **opts):
794 '''write debug message to output (if ui.debugflag is True)
794 '''write debug message to output (if ui.debugflag is True)
795
795
796 This adds an output label of "ui.debug".
796 This adds an output label of "ui.debug".
797 '''
797 '''
798 if self.debugflag:
798 if self.debugflag:
799 opts['label'] = opts.get('label', '') + ' ui.debug'
799 opts['label'] = opts.get('label', '') + ' ui.debug'
800 self.write(*msg, **opts)
800 self.write(*msg, **opts)
801 def edit(self, text, user, extra={}, editform=None):
801 def edit(self, text, user, extra={}, editform=None):
802 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
802 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
803 text=True)
803 text=True)
804 try:
804 try:
805 f = os.fdopen(fd, "w")
805 f = os.fdopen(fd, "w")
806 f.write(text)
806 f.write(text)
807 f.close()
807 f.close()
808
808
809 environ = {'HGUSER': user}
809 environ = {'HGUSER': user}
810 if 'transplant_source' in extra:
810 if 'transplant_source' in extra:
811 environ.update({'HGREVISION': hex(extra['transplant_source'])})
811 environ.update({'HGREVISION': hex(extra['transplant_source'])})
812 for label in ('source', 'rebase_source'):
812 for label in ('source', 'rebase_source'):
813 if label in extra:
813 if label in extra:
814 environ.update({'HGREVISION': extra[label]})
814 environ.update({'HGREVISION': extra[label]})
815 break
815 break
816 if editform:
816 if editform:
817 environ.update({'HGEDITFORM': editform})
817 environ.update({'HGEDITFORM': editform})
818
818
819 editor = self.geteditor()
819 editor = self.geteditor()
820
820
821 self.system("%s \"%s\"" % (editor, name),
821 self.system("%s \"%s\"" % (editor, name),
822 environ=environ,
822 environ=environ,
823 onerr=util.Abort, errprefix=_("edit failed"))
823 onerr=util.Abort, errprefix=_("edit failed"))
824
824
825 f = open(name)
825 f = open(name)
826 t = f.read()
826 t = f.read()
827 f.close()
827 f.close()
828 finally:
828 finally:
829 os.unlink(name)
829 os.unlink(name)
830
830
831 return t
831 return t
832
832
833 def system(self, cmd, environ={}, cwd=None, onerr=None, errprefix=None):
833 def system(self, cmd, environ={}, cwd=None, onerr=None, errprefix=None):
834 '''execute shell command with appropriate output stream. command
834 '''execute shell command with appropriate output stream. command
835 output will be redirected if fout is not stdout.
835 output will be redirected if fout is not stdout.
836 '''
836 '''
837 return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
837 return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
838 errprefix=errprefix, out=self.fout)
838 errprefix=errprefix, out=self.fout)
839
839
840 def traceback(self, exc=None, force=False):
840 def traceback(self, exc=None, force=False):
841 '''print exception traceback if traceback printing enabled or forced.
841 '''print exception traceback if traceback printing enabled or forced.
842 only to call in exception handler. returns true if traceback
842 only to call in exception handler. returns true if traceback
843 printed.'''
843 printed.'''
844 if self.tracebackflag or force:
844 if self.tracebackflag or force:
845 if exc is None:
845 if exc is None:
846 exc = sys.exc_info()
846 exc = sys.exc_info()
847 cause = getattr(exc[1], 'cause', None)
847 cause = getattr(exc[1], 'cause', None)
848
848
849 if cause is not None:
849 if cause is not None:
850 causetb = traceback.format_tb(cause[2])
850 causetb = traceback.format_tb(cause[2])
851 exctb = traceback.format_tb(exc[2])
851 exctb = traceback.format_tb(exc[2])
852 exconly = traceback.format_exception_only(cause[0], cause[1])
852 exconly = traceback.format_exception_only(cause[0], cause[1])
853
853
854 # exclude frame where 'exc' was chained and rethrown from exctb
854 # exclude frame where 'exc' was chained and rethrown from exctb
855 self.write_err('Traceback (most recent call last):\n',
855 self.write_err('Traceback (most recent call last):\n',
856 ''.join(exctb[:-1]),
856 ''.join(exctb[:-1]),
857 ''.join(causetb),
857 ''.join(causetb),
858 ''.join(exconly))
858 ''.join(exconly))
859 else:
859 else:
860 traceback.print_exception(exc[0], exc[1], exc[2],
860 traceback.print_exception(exc[0], exc[1], exc[2],
861 file=self.ferr)
861 file=self.ferr)
862 return self.tracebackflag or force
862 return self.tracebackflag or force
863
863
864 def geteditor(self):
864 def geteditor(self):
865 '''return editor to use'''
865 '''return editor to use'''
866 if sys.platform == 'plan9':
866 if sys.platform == 'plan9':
867 # vi is the MIPS instruction simulator on Plan 9. We
867 # vi is the MIPS instruction simulator on Plan 9. We
868 # instead default to E to plumb commit messages to
868 # instead default to E to plumb commit messages to
869 # avoid confusion.
869 # avoid confusion.
870 editor = 'E'
870 editor = 'E'
871 else:
871 else:
872 editor = 'vi'
872 editor = 'vi'
873 return (os.environ.get("HGEDITOR") or
873 return (os.environ.get("HGEDITOR") or
874 self.config("ui", "editor") or
874 self.config("ui", "editor") or
875 os.environ.get("VISUAL") or
875 os.environ.get("VISUAL") or
876 os.environ.get("EDITOR", editor))
876 os.environ.get("EDITOR", editor))
877
877
878 def progress(self, topic, pos, item="", unit="", total=None):
878 def progress(self, topic, pos, item="", unit="", total=None):
879 '''show a progress message
879 '''show a progress message
880
880
881 With stock hg, this is simply a debug message that is hidden
881 With stock hg, this is simply a debug message that is hidden
882 by default, but with extensions or GUI tools it may be
882 by default, but with extensions or GUI tools it may be
883 visible. 'topic' is the current operation, 'item' is a
883 visible. 'topic' is the current operation, 'item' is a
884 non-numeric marker of the current position (i.e. the currently
884 non-numeric marker of the current position (i.e. the currently
885 in-process file), 'pos' is the current numeric position (i.e.
885 in-process file), 'pos' is the current numeric position (i.e.
886 revision, bytes, etc.), unit is a corresponding unit label,
886 revision, bytes, etc.), unit is a corresponding unit label,
887 and total is the highest expected pos.
887 and total is the highest expected pos.
888
888
889 Multiple nested topics may be active at a time.
889 Multiple nested topics may be active at a time.
890
890
891 All topics should be marked closed by setting pos to None at
891 All topics should be marked closed by setting pos to None at
892 termination.
892 termination.
893 '''
893 '''
894
894
895 if pos is None or not self.debugflag:
895 if pos is None or not self.debugflag:
896 return
896 return
897
897
898 if unit:
898 if unit:
899 unit = ' ' + unit
899 unit = ' ' + unit
900 if item:
900 if item:
901 item = ' ' + item
901 item = ' ' + item
902
902
903 if total:
903 if total:
904 pct = 100.0 * pos / total
904 pct = 100.0 * pos / total
905 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
905 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
906 % (topic, item, pos, total, unit, pct))
906 % (topic, item, pos, total, unit, pct))
907 else:
907 else:
908 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
908 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
909
909
910 def log(self, service, *msg, **opts):
910 def log(self, service, *msg, **opts):
911 '''hook for logging facility extensions
911 '''hook for logging facility extensions
912
912
913 service should be a readily-identifiable subsystem, which will
913 service should be a readily-identifiable subsystem, which will
914 allow filtering.
914 allow filtering.
915 message should be a newline-terminated string to log.
915 message should be a newline-terminated string to log.
916 '''
916 '''
917 pass
917 pass
918
918
919 def label(self, msg, label):
919 def label(self, msg, label):
920 '''style msg based on supplied label
920 '''style msg based on supplied label
921
921
922 Like ui.write(), this just returns msg unchanged, but extensions
922 Like ui.write(), this just returns msg unchanged, but extensions
923 and GUI tools can override it to allow styling output without
923 and GUI tools can override it to allow styling output without
924 writing it.
924 writing it.
925
925
926 ui.write(s, 'label') is equivalent to
926 ui.write(s, 'label') is equivalent to
927 ui.write(ui.label(s, 'label')).
927 ui.write(ui.label(s, 'label')).
928 '''
928 '''
929 return msg
929 return msg
930
930
931 class paths(dict):
931 class paths(dict):
932 """Represents a collection of paths and their configs.
932 """Represents a collection of paths and their configs.
933
933
934 Data is initially derived from ui instances and the config files they have
934 Data is initially derived from ui instances and the config files they have
935 loaded.
935 loaded.
936 """
936 """
937 def __init__(self, ui):
937 def __init__(self, ui):
938 dict.__init__(self)
938 dict.__init__(self)
939
939
940 for name, loc in ui.configitems('paths'):
940 for name, loc in ui.configitems('paths'):
941 # No location is the same as not existing.
941 # No location is the same as not existing.
942 if not loc:
942 if not loc:
943 continue
943 continue
944 self[name] = path(name, rawloc=loc)
944 self[name] = path(name, rawloc=loc)
945
945
946 def getpath(self, name, default=None):
946 def getpath(self, name, default=None):
947 """Return a ``path`` for the specified name, falling back to a default.
947 """Return a ``path`` for the specified name, falling back to a default.
948
948
949 Returns the first of ``name`` or ``default`` that is present, or None
949 Returns the first of ``name`` or ``default`` that is present, or None
950 if neither is present.
950 if neither is present.
951 """
951 """
952 try:
952 try:
953 return self[name]
953 return self[name]
954 except KeyError:
954 except KeyError:
955 if default is not None:
955 if default is not None:
956 try:
956 try:
957 return self[default]
957 return self[default]
958 except KeyError:
958 except KeyError:
959 pass
959 pass
960
960
961 return None
961 return None
962
962
963 class path(object):
963 class path(object):
964 """Represents an individual path and its configuration."""
964 """Represents an individual path and its configuration."""
965
965
966 def __init__(self, name, rawloc=None):
966 def __init__(self, name, rawloc=None):
967 """Construct a path from its config options.
967 """Construct a path from its config options.
968
968
969 ``name`` is the symbolic name of the path.
969 ``name`` is the symbolic name of the path.
970 ``rawloc`` is the raw location, as defined in the config.
970 ``rawloc`` is the raw location, as defined in the config.
971 """
971 """
972 self.name = name
972 self.name = name
973 # We'll do more intelligent things with rawloc in the future.
973 # We'll do more intelligent things with rawloc in the future.
974 self.loc = rawloc
974 self.loc = rawloc
@@ -1,449 +1,458 b''
1 $ hg init repo1
1 $ hg init repo1
2 $ cd repo1
2 $ cd repo1
3 $ mkdir a b a/1 b/1 b/2
3 $ mkdir a b a/1 b/1 b/2
4 $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
4 $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
5
5
6 hg status in repo root:
6 hg status in repo root:
7
7
8 $ hg status
8 $ hg status
9 ? a/1/in_a_1
9 ? a/1/in_a_1
10 ? a/in_a
10 ? a/in_a
11 ? b/1/in_b_1
11 ? b/1/in_b_1
12 ? b/2/in_b_2
12 ? b/2/in_b_2
13 ? b/in_b
13 ? b/in_b
14 ? in_root
14 ? in_root
15
15
16 hg status . in repo root:
16 hg status . in repo root:
17
17
18 $ hg status .
18 $ hg status .
19 ? a/1/in_a_1
19 ? a/1/in_a_1
20 ? a/in_a
20 ? a/in_a
21 ? b/1/in_b_1
21 ? b/1/in_b_1
22 ? b/2/in_b_2
22 ? b/2/in_b_2
23 ? b/in_b
23 ? b/in_b
24 ? in_root
24 ? in_root
25
25
26 $ hg status --cwd a
26 $ hg status --cwd a
27 ? a/1/in_a_1
27 ? a/1/in_a_1
28 ? a/in_a
28 ? a/in_a
29 ? b/1/in_b_1
29 ? b/1/in_b_1
30 ? b/2/in_b_2
30 ? b/2/in_b_2
31 ? b/in_b
31 ? b/in_b
32 ? in_root
32 ? in_root
33 $ hg status --cwd a .
33 $ hg status --cwd a .
34 ? 1/in_a_1
34 ? 1/in_a_1
35 ? in_a
35 ? in_a
36 $ hg status --cwd a ..
36 $ hg status --cwd a ..
37 ? 1/in_a_1
37 ? 1/in_a_1
38 ? in_a
38 ? in_a
39 ? ../b/1/in_b_1
39 ? ../b/1/in_b_1
40 ? ../b/2/in_b_2
40 ? ../b/2/in_b_2
41 ? ../b/in_b
41 ? ../b/in_b
42 ? ../in_root
42 ? ../in_root
43
43
44 $ hg status --cwd b
44 $ hg status --cwd b
45 ? a/1/in_a_1
45 ? a/1/in_a_1
46 ? a/in_a
46 ? a/in_a
47 ? b/1/in_b_1
47 ? b/1/in_b_1
48 ? b/2/in_b_2
48 ? b/2/in_b_2
49 ? b/in_b
49 ? b/in_b
50 ? in_root
50 ? in_root
51 $ hg status --cwd b .
51 $ hg status --cwd b .
52 ? 1/in_b_1
52 ? 1/in_b_1
53 ? 2/in_b_2
53 ? 2/in_b_2
54 ? in_b
54 ? in_b
55 $ hg status --cwd b ..
55 $ hg status --cwd b ..
56 ? ../a/1/in_a_1
56 ? ../a/1/in_a_1
57 ? ../a/in_a
57 ? ../a/in_a
58 ? 1/in_b_1
58 ? 1/in_b_1
59 ? 2/in_b_2
59 ? 2/in_b_2
60 ? in_b
60 ? in_b
61 ? ../in_root
61 ? ../in_root
62
62
63 $ hg status --cwd a/1
63 $ hg status --cwd a/1
64 ? a/1/in_a_1
64 ? a/1/in_a_1
65 ? a/in_a
65 ? a/in_a
66 ? b/1/in_b_1
66 ? b/1/in_b_1
67 ? b/2/in_b_2
67 ? b/2/in_b_2
68 ? b/in_b
68 ? b/in_b
69 ? in_root
69 ? in_root
70 $ hg status --cwd a/1 .
70 $ hg status --cwd a/1 .
71 ? in_a_1
71 ? in_a_1
72 $ hg status --cwd a/1 ..
72 $ hg status --cwd a/1 ..
73 ? in_a_1
73 ? in_a_1
74 ? ../in_a
74 ? ../in_a
75
75
76 $ hg status --cwd b/1
76 $ hg status --cwd b/1
77 ? a/1/in_a_1
77 ? a/1/in_a_1
78 ? a/in_a
78 ? a/in_a
79 ? b/1/in_b_1
79 ? b/1/in_b_1
80 ? b/2/in_b_2
80 ? b/2/in_b_2
81 ? b/in_b
81 ? b/in_b
82 ? in_root
82 ? in_root
83 $ hg status --cwd b/1 .
83 $ hg status --cwd b/1 .
84 ? in_b_1
84 ? in_b_1
85 $ hg status --cwd b/1 ..
85 $ hg status --cwd b/1 ..
86 ? in_b_1
86 ? in_b_1
87 ? ../2/in_b_2
87 ? ../2/in_b_2
88 ? ../in_b
88 ? ../in_b
89
89
90 $ hg status --cwd b/2
90 $ hg status --cwd b/2
91 ? a/1/in_a_1
91 ? a/1/in_a_1
92 ? a/in_a
92 ? a/in_a
93 ? b/1/in_b_1
93 ? b/1/in_b_1
94 ? b/2/in_b_2
94 ? b/2/in_b_2
95 ? b/in_b
95 ? b/in_b
96 ? in_root
96 ? in_root
97 $ hg status --cwd b/2 .
97 $ hg status --cwd b/2 .
98 ? in_b_2
98 ? in_b_2
99 $ hg status --cwd b/2 ..
99 $ hg status --cwd b/2 ..
100 ? ../1/in_b_1
100 ? ../1/in_b_1
101 ? in_b_2
101 ? in_b_2
102 ? ../in_b
102 ? ../in_b
103
103
104 combining patterns with root and patterns without a root works
104 combining patterns with root and patterns without a root works
105
105
106 $ hg st a/in_a re:.*b$
106 $ hg st a/in_a re:.*b$
107 ? a/in_a
107 ? a/in_a
108 ? b/in_b
108 ? b/in_b
109
109
110 $ cd ..
110 $ cd ..
111
111
112 $ hg init repo2
112 $ hg init repo2
113 $ cd repo2
113 $ cd repo2
114 $ touch modified removed deleted ignored
114 $ touch modified removed deleted ignored
115 $ echo "^ignored$" > .hgignore
115 $ echo "^ignored$" > .hgignore
116 $ hg ci -A -m 'initial checkin'
116 $ hg ci -A -m 'initial checkin'
117 adding .hgignore
117 adding .hgignore
118 adding deleted
118 adding deleted
119 adding modified
119 adding modified
120 adding removed
120 adding removed
121 $ touch modified added unknown ignored
121 $ touch modified added unknown ignored
122 $ hg add added
122 $ hg add added
123 $ hg remove removed
123 $ hg remove removed
124 $ rm deleted
124 $ rm deleted
125
125
126 hg status:
126 hg status:
127
127
128 $ hg status
128 $ hg status
129 A added
129 A added
130 R removed
130 R removed
131 ! deleted
131 ! deleted
132 ? unknown
132 ? unknown
133
133
134 hg status modified added removed deleted unknown never-existed ignored:
134 hg status modified added removed deleted unknown never-existed ignored:
135
135
136 $ hg status modified added removed deleted unknown never-existed ignored
136 $ hg status modified added removed deleted unknown never-existed ignored
137 never-existed: * (glob)
137 never-existed: * (glob)
138 A added
138 A added
139 R removed
139 R removed
140 ! deleted
140 ! deleted
141 ? unknown
141 ? unknown
142
142
143 $ hg copy modified copied
143 $ hg copy modified copied
144
144
145 hg status -C:
145 hg status -C:
146
146
147 $ hg status -C
147 $ hg status -C
148 A added
148 A added
149 A copied
149 A copied
150 modified
150 modified
151 R removed
151 R removed
152 ! deleted
152 ! deleted
153 ? unknown
153 ? unknown
154
154
155 hg status -A:
155 hg status -A:
156
156
157 $ hg status -A
157 $ hg status -A
158 A added
158 A added
159 A copied
159 A copied
160 modified
160 modified
161 R removed
161 R removed
162 ! deleted
162 ! deleted
163 ? unknown
163 ? unknown
164 I ignored
164 I ignored
165 C .hgignore
165 C .hgignore
166 C modified
166 C modified
167
167
168 $ hg status -A -Tjson
168 $ hg status -A -Tjson
169 [
169 [
170 {
170 {
171 "path": "added",
171 "path": "added",
172 "status": "A"
172 "status": "A"
173 },
173 },
174 {
174 {
175 "copy": "modified",
175 "copy": "modified",
176 "path": "copied",
176 "path": "copied",
177 "status": "A"
177 "status": "A"
178 },
178 },
179 {
179 {
180 "path": "removed",
180 "path": "removed",
181 "status": "R"
181 "status": "R"
182 },
182 },
183 {
183 {
184 "path": "deleted",
184 "path": "deleted",
185 "status": "!"
185 "status": "!"
186 },
186 },
187 {
187 {
188 "path": "unknown",
188 "path": "unknown",
189 "status": "?"
189 "status": "?"
190 },
190 },
191 {
191 {
192 "path": "ignored",
192 "path": "ignored",
193 "status": "I"
193 "status": "I"
194 },
194 },
195 {
195 {
196 "path": ".hgignore",
196 "path": ".hgignore",
197 "status": "C"
197 "status": "C"
198 },
198 },
199 {
199 {
200 "path": "modified",
200 "path": "modified",
201 "status": "C"
201 "status": "C"
202 }
202 }
203 ]
203 ]
204
204
205 $ hg status -A -Tpickle > pickle
205 $ hg status -A -Tpickle > pickle
206 >>> import pickle
206 >>> import pickle
207 >>> print sorted((x['status'], x['path']) for x in pickle.load(open("pickle")))
207 >>> print sorted((x['status'], x['path']) for x in pickle.load(open("pickle")))
208 [('!', 'deleted'), ('?', 'pickle'), ('?', 'unknown'), ('A', 'added'), ('A', 'copied'), ('C', '.hgignore'), ('C', 'modified'), ('I', 'ignored'), ('R', 'removed')]
208 [('!', 'deleted'), ('?', 'pickle'), ('?', 'unknown'), ('A', 'added'), ('A', 'copied'), ('C', '.hgignore'), ('C', 'modified'), ('I', 'ignored'), ('R', 'removed')]
209 $ rm pickle
209 $ rm pickle
210
210
211 $ echo "^ignoreddir$" > .hgignore
211 $ echo "^ignoreddir$" > .hgignore
212 $ mkdir ignoreddir
212 $ mkdir ignoreddir
213 $ touch ignoreddir/file
213 $ touch ignoreddir/file
214
214
215 hg status ignoreddir/file:
215 hg status ignoreddir/file:
216
216
217 $ hg status ignoreddir/file
217 $ hg status ignoreddir/file
218
218
219 hg status -i ignoreddir/file:
219 hg status -i ignoreddir/file:
220
220
221 $ hg status -i ignoreddir/file
221 $ hg status -i ignoreddir/file
222 I ignoreddir/file
222 I ignoreddir/file
223 $ cd ..
223 $ cd ..
224
224
225 Check 'status -q' and some combinations
225 Check 'status -q' and some combinations
226
226
227 $ hg init repo3
227 $ hg init repo3
228 $ cd repo3
228 $ cd repo3
229 $ touch modified removed deleted ignored
229 $ touch modified removed deleted ignored
230 $ echo "^ignored$" > .hgignore
230 $ echo "^ignored$" > .hgignore
231 $ hg commit -A -m 'initial checkin'
231 $ hg commit -A -m 'initial checkin'
232 adding .hgignore
232 adding .hgignore
233 adding deleted
233 adding deleted
234 adding modified
234 adding modified
235 adding removed
235 adding removed
236 $ touch added unknown ignored
236 $ touch added unknown ignored
237 $ hg add added
237 $ hg add added
238 $ echo "test" >> modified
238 $ echo "test" >> modified
239 $ hg remove removed
239 $ hg remove removed
240 $ rm deleted
240 $ rm deleted
241 $ hg copy modified copied
241 $ hg copy modified copied
242
242
243 Specify working directory revision explicitly, that should be the same as
243 Specify working directory revision explicitly, that should be the same as
244 "hg status"
244 "hg status"
245
245
246 $ hg status --change "wdir()"
246 $ hg status --change "wdir()"
247 M modified
247 M modified
248 A added
248 A added
249 A copied
249 A copied
250 R removed
250 R removed
251 ! deleted
251 ! deleted
252 ? unknown
252 ? unknown
253
253
254 Run status with 2 different flags.
254 Run status with 2 different flags.
255 Check if result is the same or different.
255 Check if result is the same or different.
256 If result is not as expected, raise error
256 If result is not as expected, raise error
257
257
258 $ assert() {
258 $ assert() {
259 > hg status $1 > ../a
259 > hg status $1 > ../a
260 > hg status $2 > ../b
260 > hg status $2 > ../b
261 > if diff ../a ../b > /dev/null; then
261 > if diff ../a ../b > /dev/null; then
262 > out=0
262 > out=0
263 > else
263 > else
264 > out=1
264 > out=1
265 > fi
265 > fi
266 > if [ $3 -eq 0 ]; then
266 > if [ $3 -eq 0 ]; then
267 > df="same"
267 > df="same"
268 > else
268 > else
269 > df="different"
269 > df="different"
270 > fi
270 > fi
271 > if [ $out -ne $3 ]; then
271 > if [ $out -ne $3 ]; then
272 > echo "Error on $1 and $2, should be $df."
272 > echo "Error on $1 and $2, should be $df."
273 > fi
273 > fi
274 > }
274 > }
275
275
276 Assert flag1 flag2 [0-same | 1-different]
276 Assert flag1 flag2 [0-same | 1-different]
277
277
278 $ assert "-q" "-mard" 0
278 $ assert "-q" "-mard" 0
279 $ assert "-A" "-marduicC" 0
279 $ assert "-A" "-marduicC" 0
280 $ assert "-qA" "-mardcC" 0
280 $ assert "-qA" "-mardcC" 0
281 $ assert "-qAui" "-A" 0
281 $ assert "-qAui" "-A" 0
282 $ assert "-qAu" "-marducC" 0
282 $ assert "-qAu" "-marducC" 0
283 $ assert "-qAi" "-mardicC" 0
283 $ assert "-qAi" "-mardicC" 0
284 $ assert "-qu" "-u" 0
284 $ assert "-qu" "-u" 0
285 $ assert "-q" "-u" 1
285 $ assert "-q" "-u" 1
286 $ assert "-m" "-a" 1
286 $ assert "-m" "-a" 1
287 $ assert "-r" "-d" 1
287 $ assert "-r" "-d" 1
288 $ cd ..
288 $ cd ..
289
289
290 $ hg init repo4
290 $ hg init repo4
291 $ cd repo4
291 $ cd repo4
292 $ touch modified removed deleted
292 $ touch modified removed deleted
293 $ hg ci -q -A -m 'initial checkin'
293 $ hg ci -q -A -m 'initial checkin'
294 $ touch added unknown
294 $ touch added unknown
295 $ hg add added
295 $ hg add added
296 $ hg remove removed
296 $ hg remove removed
297 $ rm deleted
297 $ rm deleted
298 $ echo x > modified
298 $ echo x > modified
299 $ hg copy modified copied
299 $ hg copy modified copied
300 $ hg ci -m 'test checkin' -d "1000001 0"
300 $ hg ci -m 'test checkin' -d "1000001 0"
301 $ rm *
301 $ rm *
302 $ touch unrelated
302 $ touch unrelated
303 $ hg ci -q -A -m 'unrelated checkin' -d "1000002 0"
303 $ hg ci -q -A -m 'unrelated checkin' -d "1000002 0"
304
304
305 hg status --change 1:
305 hg status --change 1:
306
306
307 $ hg status --change 1
307 $ hg status --change 1
308 M modified
308 M modified
309 A added
309 A added
310 A copied
310 A copied
311 R removed
311 R removed
312
312
313 hg status --change 1 unrelated:
313 hg status --change 1 unrelated:
314
314
315 $ hg status --change 1 unrelated
315 $ hg status --change 1 unrelated
316
316
317 hg status -C --change 1 added modified copied removed deleted:
317 hg status -C --change 1 added modified copied removed deleted:
318
318
319 $ hg status -C --change 1 added modified copied removed deleted
319 $ hg status -C --change 1 added modified copied removed deleted
320 M modified
320 M modified
321 A added
321 A added
322 A copied
322 A copied
323 modified
323 modified
324 R removed
324 R removed
325
325
326 hg status -A --change 1 and revset:
326 hg status -A --change 1 and revset:
327
327
328 $ hg status -A --change '1|1'
328 $ hg status -A --change '1|1'
329 M modified
329 M modified
330 A added
330 A added
331 A copied
331 A copied
332 modified
332 modified
333 R removed
333 R removed
334 C deleted
334 C deleted
335
335
336 $ cd ..
336 $ cd ..
337
337
338 hg status of binary file starting with '\1\n', a separator for metadata:
338 hg status of binary file starting with '\1\n', a separator for metadata:
339
339
340 $ hg init repo5
340 $ hg init repo5
341 $ cd repo5
341 $ cd repo5
342 >>> open("010a", "wb").write("\1\nfoo")
342 >>> open("010a", "wb").write("\1\nfoo")
343 $ hg ci -q -A -m 'initial checkin'
343 $ hg ci -q -A -m 'initial checkin'
344 $ hg status -A
344 $ hg status -A
345 C 010a
345 C 010a
346
346
347 >>> open("010a", "wb").write("\1\nbar")
347 >>> open("010a", "wb").write("\1\nbar")
348 $ hg status -A
348 $ hg status -A
349 M 010a
349 M 010a
350 $ hg ci -q -m 'modify 010a'
350 $ hg ci -q -m 'modify 010a'
351 $ hg status -A --rev 0:1
351 $ hg status -A --rev 0:1
352 M 010a
352 M 010a
353
353
354 $ touch empty
354 $ touch empty
355 $ hg ci -q -A -m 'add another file'
355 $ hg ci -q -A -m 'add another file'
356 $ hg status -A --rev 1:2 010a
356 $ hg status -A --rev 1:2 010a
357 C 010a
357 C 010a
358
358
359 $ cd ..
359 $ cd ..
360
360
361 test "hg status" with "directory pattern" which matches against files
361 test "hg status" with "directory pattern" which matches against files
362 only known on target revision.
362 only known on target revision.
363
363
364 $ hg init repo6
364 $ hg init repo6
365 $ cd repo6
365 $ cd repo6
366
366
367 $ echo a > a.txt
367 $ echo a > a.txt
368 $ hg add a.txt
368 $ hg add a.txt
369 $ hg commit -m '#0'
369 $ hg commit -m '#0'
370 $ mkdir -p 1/2/3/4/5
370 $ mkdir -p 1/2/3/4/5
371 $ echo b > 1/2/3/4/5/b.txt
371 $ echo b > 1/2/3/4/5/b.txt
372 $ hg add 1/2/3/4/5/b.txt
372 $ hg add 1/2/3/4/5/b.txt
373 $ hg commit -m '#1'
373 $ hg commit -m '#1'
374
374
375 $ hg update -C 0 > /dev/null
375 $ hg update -C 0 > /dev/null
376 $ hg status -A
376 $ hg status -A
377 C a.txt
377 C a.txt
378
378
379 the directory matching against specified pattern should be removed,
379 the directory matching against specified pattern should be removed,
380 because directory existence prevents 'dirstate.walk()' from showing
380 because directory existence prevents 'dirstate.walk()' from showing
381 warning message about such pattern.
381 warning message about such pattern.
382
382
383 $ test ! -d 1
383 $ test ! -d 1
384 $ hg status -A --rev 1 1/2/3/4/5/b.txt
384 $ hg status -A --rev 1 1/2/3/4/5/b.txt
385 R 1/2/3/4/5/b.txt
385 R 1/2/3/4/5/b.txt
386 $ hg status -A --rev 1 1/2/3/4/5
386 $ hg status -A --rev 1 1/2/3/4/5
387 R 1/2/3/4/5/b.txt
387 R 1/2/3/4/5/b.txt
388 $ hg status -A --rev 1 1/2/3
388 $ hg status -A --rev 1 1/2/3
389 R 1/2/3/4/5/b.txt
389 R 1/2/3/4/5/b.txt
390 $ hg status -A --rev 1 1
390 $ hg status -A --rev 1 1
391 R 1/2/3/4/5/b.txt
391 R 1/2/3/4/5/b.txt
392
392
393 $ hg status --config ui.formatdebug=True --rev 1 1
393 $ hg status --config ui.formatdebug=True --rev 1 1
394 status = [
394 status = [
395 {*'path': '1/2/3/4/5/b.txt'*}, (glob)
395 {*'path': '1/2/3/4/5/b.txt'*}, (glob)
396 ]
396 ]
397
397
398 #if windows
398 #if windows
399 $ hg --config ui.slash=false status -A --rev 1 1
399 $ hg --config ui.slash=false status -A --rev 1 1
400 R 1\2\3\4\5\b.txt
400 R 1\2\3\4\5\b.txt
401 #endif
401 #endif
402
402
403 $ cd ..
403 $ cd ..
404
404
405 Status after move overwriting a file (issue4458)
405 Status after move overwriting a file (issue4458)
406 =================================================
406 =================================================
407
407
408
408
409 $ hg init issue4458
409 $ hg init issue4458
410 $ cd issue4458
410 $ cd issue4458
411 $ echo a > a
411 $ echo a > a
412 $ echo b > b
412 $ echo b > b
413 $ hg commit -Am base
413 $ hg commit -Am base
414 adding a
414 adding a
415 adding b
415 adding b
416
416
417
417
418 with --force
418 with --force
419
419
420 $ hg mv b --force a
420 $ hg mv b --force a
421 $ hg st --copies
421 $ hg st --copies
422 M a
422 M a
423 b
423 b
424 R b
424 R b
425 $ hg revert --all
425 $ hg revert --all
426 reverting a
426 reverting a
427 undeleting b
427 undeleting b
428 $ rm *.orig
428 $ rm *.orig
429
429
430 without force
430 without force
431
431
432 $ hg rm a
432 $ hg rm a
433 $ hg st --copies
433 $ hg st --copies
434 R a
434 R a
435 $ hg mv b a
435 $ hg mv b a
436 $ hg st --copies
436 $ hg st --copies
437 M a
437 M a
438 b
438 b
439 R b
439 R b
440
440
441 using ui.statuscopies setting
442 $ hg st --config ui.statuscopies=true
443 M a
444 b
445 R b
446 $ hg st --config ui.statuscopies=false
447 M a
448 R b
449
441 Other "bug" highlight, the revision status does not report the copy information.
450 Other "bug" highlight, the revision status does not report the copy information.
442 This is buggy behavior.
451 This is buggy behavior.
443
452
444 $ hg commit -m 'blah'
453 $ hg commit -m 'blah'
445 $ hg st --copies --change .
454 $ hg st --copies --change .
446 M a
455 M a
447 R b
456 R b
448
457
449 $ cd ..
458 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now