##// END OF EJS Templates
branches: port to generic templater
Yuya Nishihara -
r22703:bd6e95cb default
parent child Browse files
Show More
@@ -1,6314 +1,6320
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
21 import dagparser, context, simplemerge, graphmod
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
24 import phases, obsolete, exchange
25
25
26 table = {}
26 table = {}
27
27
28 command = cmdutil.command(table)
28 command = cmdutil.command(table)
29
29
30 # Space delimited list of commands that don't require local repositories.
30 # Space delimited list of commands that don't require local repositories.
31 # This should be populated by passing norepo=True into the @command decorator.
31 # This should be populated by passing norepo=True into the @command decorator.
32 norepo = ''
32 norepo = ''
33 # Space delimited list of commands that optionally require local repositories.
33 # Space delimited list of commands that optionally require local repositories.
34 # This should be populated by passing optionalrepo=True into the @command
34 # This should be populated by passing optionalrepo=True into the @command
35 # decorator.
35 # decorator.
36 optionalrepo = ''
36 optionalrepo = ''
37 # Space delimited list of commands that will examine arguments looking for
37 # Space delimited list of commands that will examine arguments looking for
38 # a repository. This should be populated by passing inferrepo=True into the
38 # a repository. This should be populated by passing inferrepo=True into the
39 # @command decorator.
39 # @command decorator.
40 inferrepo = ''
40 inferrepo = ''
41
41
42 # common command options
42 # common command options
43
43
44 globalopts = [
44 globalopts = [
45 ('R', 'repository', '',
45 ('R', 'repository', '',
46 _('repository root directory or name of overlay bundle file'),
46 _('repository root directory or name of overlay bundle file'),
47 _('REPO')),
47 _('REPO')),
48 ('', 'cwd', '',
48 ('', 'cwd', '',
49 _('change working directory'), _('DIR')),
49 _('change working directory'), _('DIR')),
50 ('y', 'noninteractive', None,
50 ('y', 'noninteractive', None,
51 _('do not prompt, automatically pick the first choice for all prompts')),
51 _('do not prompt, automatically pick the first choice for all prompts')),
52 ('q', 'quiet', None, _('suppress output')),
52 ('q', 'quiet', None, _('suppress output')),
53 ('v', 'verbose', None, _('enable additional output')),
53 ('v', 'verbose', None, _('enable additional output')),
54 ('', 'config', [],
54 ('', 'config', [],
55 _('set/override config option (use \'section.name=value\')'),
55 _('set/override config option (use \'section.name=value\')'),
56 _('CONFIG')),
56 _('CONFIG')),
57 ('', 'debug', None, _('enable debugging output')),
57 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debugger', None, _('start debugger')),
58 ('', 'debugger', None, _('start debugger')),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 _('ENCODE')),
60 _('ENCODE')),
61 ('', 'encodingmode', encoding.encodingmode,
61 ('', 'encodingmode', encoding.encodingmode,
62 _('set the charset encoding mode'), _('MODE')),
62 _('set the charset encoding mode'), _('MODE')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'time', None, _('time how long the command takes')),
64 ('', 'time', None, _('time how long the command takes')),
65 ('', 'profile', None, _('print command execution profile')),
65 ('', 'profile', None, _('print command execution profile')),
66 ('', 'version', None, _('output version information and exit')),
66 ('', 'version', None, _('output version information and exit')),
67 ('h', 'help', None, _('display help and exit')),
67 ('h', 'help', None, _('display help and exit')),
68 ('', 'hidden', False, _('consider hidden changesets')),
68 ('', 'hidden', False, _('consider hidden changesets')),
69 ]
69 ]
70
70
71 dryrunopts = [('n', 'dry-run', None,
71 dryrunopts = [('n', 'dry-run', None,
72 _('do not perform actions, just print output'))]
72 _('do not perform actions, just print output'))]
73
73
74 remoteopts = [
74 remoteopts = [
75 ('e', 'ssh', '',
75 ('e', 'ssh', '',
76 _('specify ssh command to use'), _('CMD')),
76 _('specify ssh command to use'), _('CMD')),
77 ('', 'remotecmd', '',
77 ('', 'remotecmd', '',
78 _('specify hg command to run on the remote side'), _('CMD')),
78 _('specify hg command to run on the remote side'), _('CMD')),
79 ('', 'insecure', None,
79 ('', 'insecure', None,
80 _('do not verify server certificate (ignoring web.cacerts config)')),
80 _('do not verify server certificate (ignoring web.cacerts config)')),
81 ]
81 ]
82
82
83 walkopts = [
83 walkopts = [
84 ('I', 'include', [],
84 ('I', 'include', [],
85 _('include names matching the given patterns'), _('PATTERN')),
85 _('include names matching the given patterns'), _('PATTERN')),
86 ('X', 'exclude', [],
86 ('X', 'exclude', [],
87 _('exclude names matching the given patterns'), _('PATTERN')),
87 _('exclude names matching the given patterns'), _('PATTERN')),
88 ]
88 ]
89
89
90 commitopts = [
90 commitopts = [
91 ('m', 'message', '',
91 ('m', 'message', '',
92 _('use text as commit message'), _('TEXT')),
92 _('use text as commit message'), _('TEXT')),
93 ('l', 'logfile', '',
93 ('l', 'logfile', '',
94 _('read commit message from file'), _('FILE')),
94 _('read commit message from file'), _('FILE')),
95 ]
95 ]
96
96
97 commitopts2 = [
97 commitopts2 = [
98 ('d', 'date', '',
98 ('d', 'date', '',
99 _('record the specified date as commit date'), _('DATE')),
99 _('record the specified date as commit date'), _('DATE')),
100 ('u', 'user', '',
100 ('u', 'user', '',
101 _('record the specified user as committer'), _('USER')),
101 _('record the specified user as committer'), _('USER')),
102 ]
102 ]
103
103
104 # hidden for now
104 # hidden for now
105 formatteropts = [
105 formatteropts = [
106 ('T', 'template', '',
106 ('T', 'template', '',
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 ]
108 ]
109
109
110 templateopts = [
110 templateopts = [
111 ('', 'style', '',
111 ('', 'style', '',
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 ('T', 'template', '',
113 ('T', 'template', '',
114 _('display with template'), _('TEMPLATE')),
114 _('display with template'), _('TEMPLATE')),
115 ]
115 ]
116
116
117 logopts = [
117 logopts = [
118 ('p', 'patch', None, _('show patch')),
118 ('p', 'patch', None, _('show patch')),
119 ('g', 'git', None, _('use git extended diff format')),
119 ('g', 'git', None, _('use git extended diff format')),
120 ('l', 'limit', '',
120 ('l', 'limit', '',
121 _('limit number of changes displayed'), _('NUM')),
121 _('limit number of changes displayed'), _('NUM')),
122 ('M', 'no-merges', None, _('do not show merges')),
122 ('M', 'no-merges', None, _('do not show merges')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('G', 'graph', None, _("show the revision DAG")),
124 ('G', 'graph', None, _("show the revision DAG")),
125 ] + templateopts
125 ] + templateopts
126
126
127 diffopts = [
127 diffopts = [
128 ('a', 'text', None, _('treat all files as text')),
128 ('a', 'text', None, _('treat all files as text')),
129 ('g', 'git', None, _('use git extended diff format')),
129 ('g', 'git', None, _('use git extended diff format')),
130 ('', 'nodates', None, _('omit dates from diff headers'))
130 ('', 'nodates', None, _('omit dates from diff headers'))
131 ]
131 ]
132
132
133 diffwsopts = [
133 diffwsopts = [
134 ('w', 'ignore-all-space', None,
134 ('w', 'ignore-all-space', None,
135 _('ignore white space when comparing lines')),
135 _('ignore white space when comparing lines')),
136 ('b', 'ignore-space-change', None,
136 ('b', 'ignore-space-change', None,
137 _('ignore changes in the amount of white space')),
137 _('ignore changes in the amount of white space')),
138 ('B', 'ignore-blank-lines', None,
138 ('B', 'ignore-blank-lines', None,
139 _('ignore changes whose lines are all blank')),
139 _('ignore changes whose lines are all blank')),
140 ]
140 ]
141
141
142 diffopts2 = [
142 diffopts2 = [
143 ('p', 'show-function', None, _('show which function each change is in')),
143 ('p', 'show-function', None, _('show which function each change is in')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
145 ] + diffwsopts + [
145 ] + diffwsopts + [
146 ('U', 'unified', '',
146 ('U', 'unified', '',
147 _('number of lines of context to show'), _('NUM')),
147 _('number of lines of context to show'), _('NUM')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
149 ]
149 ]
150
150
151 mergetoolopts = [
151 mergetoolopts = [
152 ('t', 'tool', '', _('specify merge tool')),
152 ('t', 'tool', '', _('specify merge tool')),
153 ]
153 ]
154
154
155 similarityopts = [
155 similarityopts = [
156 ('s', 'similarity', '',
156 ('s', 'similarity', '',
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
158 ]
158 ]
159
159
160 subrepoopts = [
160 subrepoopts = [
161 ('S', 'subrepos', None,
161 ('S', 'subrepos', None,
162 _('recurse into subrepositories'))
162 _('recurse into subrepositories'))
163 ]
163 ]
164
164
165 # Commands start here, listed alphabetically
165 # Commands start here, listed alphabetically
166
166
167 @command('^add',
167 @command('^add',
168 walkopts + subrepoopts + dryrunopts,
168 walkopts + subrepoopts + dryrunopts,
169 _('[OPTION]... [FILE]...'),
169 _('[OPTION]... [FILE]...'),
170 inferrepo=True)
170 inferrepo=True)
171 def add(ui, repo, *pats, **opts):
171 def add(ui, repo, *pats, **opts):
172 """add the specified files on the next commit
172 """add the specified files on the next commit
173
173
174 Schedule files to be version controlled and added to the
174 Schedule files to be version controlled and added to the
175 repository.
175 repository.
176
176
177 The files will be added to the repository at the next commit. To
177 The files will be added to the repository at the next commit. To
178 undo an add before that, see :hg:`forget`.
178 undo an add before that, see :hg:`forget`.
179
179
180 If no names are given, add all files to the repository.
180 If no names are given, add all files to the repository.
181
181
182 .. container:: verbose
182 .. container:: verbose
183
183
184 An example showing how new (unknown) files are added
184 An example showing how new (unknown) files are added
185 automatically by :hg:`add`::
185 automatically by :hg:`add`::
186
186
187 $ ls
187 $ ls
188 foo.c
188 foo.c
189 $ hg status
189 $ hg status
190 ? foo.c
190 ? foo.c
191 $ hg add
191 $ hg add
192 adding foo.c
192 adding foo.c
193 $ hg status
193 $ hg status
194 A foo.c
194 A foo.c
195
195
196 Returns 0 if all files are successfully added.
196 Returns 0 if all files are successfully added.
197 """
197 """
198
198
199 m = scmutil.match(repo[None], pats, opts)
199 m = scmutil.match(repo[None], pats, opts)
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
201 opts.get('subrepos'), prefix="", explicitonly=False)
201 opts.get('subrepos'), prefix="", explicitonly=False)
202 return rejected and 1 or 0
202 return rejected and 1 or 0
203
203
204 @command('addremove',
204 @command('addremove',
205 similarityopts + walkopts + dryrunopts,
205 similarityopts + walkopts + dryrunopts,
206 _('[OPTION]... [FILE]...'),
206 _('[OPTION]... [FILE]...'),
207 inferrepo=True)
207 inferrepo=True)
208 def addremove(ui, repo, *pats, **opts):
208 def addremove(ui, repo, *pats, **opts):
209 """add all new files, delete all missing files
209 """add all new files, delete all missing files
210
210
211 Add all new files and remove all missing files from the
211 Add all new files and remove all missing files from the
212 repository.
212 repository.
213
213
214 New files are ignored if they match any of the patterns in
214 New files are ignored if they match any of the patterns in
215 ``.hgignore``. As with add, these changes take effect at the next
215 ``.hgignore``. As with add, these changes take effect at the next
216 commit.
216 commit.
217
217
218 Use the -s/--similarity option to detect renamed files. This
218 Use the -s/--similarity option to detect renamed files. This
219 option takes a percentage between 0 (disabled) and 100 (files must
219 option takes a percentage between 0 (disabled) and 100 (files must
220 be identical) as its parameter. With a parameter greater than 0,
220 be identical) as its parameter. With a parameter greater than 0,
221 this compares every removed file with every added file and records
221 this compares every removed file with every added file and records
222 those similar enough as renames. Detecting renamed files this way
222 those similar enough as renames. Detecting renamed files this way
223 can be expensive. After using this option, :hg:`status -C` can be
223 can be expensive. After using this option, :hg:`status -C` can be
224 used to check which files were identified as moved or renamed. If
224 used to check which files were identified as moved or renamed. If
225 not specified, -s/--similarity defaults to 100 and only renames of
225 not specified, -s/--similarity defaults to 100 and only renames of
226 identical files are detected.
226 identical files are detected.
227
227
228 Returns 0 if all files are successfully added.
228 Returns 0 if all files are successfully added.
229 """
229 """
230 try:
230 try:
231 sim = float(opts.get('similarity') or 100)
231 sim = float(opts.get('similarity') or 100)
232 except ValueError:
232 except ValueError:
233 raise util.Abort(_('similarity must be a number'))
233 raise util.Abort(_('similarity must be a number'))
234 if sim < 0 or sim > 100:
234 if sim < 0 or sim > 100:
235 raise util.Abort(_('similarity must be between 0 and 100'))
235 raise util.Abort(_('similarity must be between 0 and 100'))
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
237
237
238 @command('^annotate|blame',
238 @command('^annotate|blame',
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
240 ('', 'follow', None,
240 ('', 'follow', None,
241 _('follow copies/renames and list the filename (DEPRECATED)')),
241 _('follow copies/renames and list the filename (DEPRECATED)')),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
243 ('a', 'text', None, _('treat all files as text')),
243 ('a', 'text', None, _('treat all files as text')),
244 ('u', 'user', None, _('list the author (long with -v)')),
244 ('u', 'user', None, _('list the author (long with -v)')),
245 ('f', 'file', None, _('list the filename')),
245 ('f', 'file', None, _('list the filename')),
246 ('d', 'date', None, _('list the date (short with -q)')),
246 ('d', 'date', None, _('list the date (short with -q)')),
247 ('n', 'number', None, _('list the revision number (default)')),
247 ('n', 'number', None, _('list the revision number (default)')),
248 ('c', 'changeset', None, _('list the changeset')),
248 ('c', 'changeset', None, _('list the changeset')),
249 ('l', 'line-number', None, _('show line number at the first appearance'))
249 ('l', 'line-number', None, _('show line number at the first appearance'))
250 ] + diffwsopts + walkopts + formatteropts,
250 ] + diffwsopts + walkopts + formatteropts,
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
252 inferrepo=True)
252 inferrepo=True)
253 def annotate(ui, repo, *pats, **opts):
253 def annotate(ui, repo, *pats, **opts):
254 """show changeset information by line for each file
254 """show changeset information by line for each file
255
255
256 List changes in files, showing the revision id responsible for
256 List changes in files, showing the revision id responsible for
257 each line
257 each line
258
258
259 This command is useful for discovering when a change was made and
259 This command is useful for discovering when a change was made and
260 by whom.
260 by whom.
261
261
262 Without the -a/--text option, annotate will avoid processing files
262 Without the -a/--text option, annotate will avoid processing files
263 it detects as binary. With -a, annotate will annotate the file
263 it detects as binary. With -a, annotate will annotate the file
264 anyway, although the results will probably be neither useful
264 anyway, although the results will probably be neither useful
265 nor desirable.
265 nor desirable.
266
266
267 Returns 0 on success.
267 Returns 0 on success.
268 """
268 """
269 if not pats:
269 if not pats:
270 raise util.Abort(_('at least one filename or pattern is required'))
270 raise util.Abort(_('at least one filename or pattern is required'))
271
271
272 if opts.get('follow'):
272 if opts.get('follow'):
273 # --follow is deprecated and now just an alias for -f/--file
273 # --follow is deprecated and now just an alias for -f/--file
274 # to mimic the behavior of Mercurial before version 1.5
274 # to mimic the behavior of Mercurial before version 1.5
275 opts['file'] = True
275 opts['file'] = True
276
276
277 fm = ui.formatter('annotate', opts)
277 fm = ui.formatter('annotate', opts)
278 datefunc = ui.quiet and util.shortdate or util.datestr
278 datefunc = ui.quiet and util.shortdate or util.datestr
279 hexfn = fm.hexfunc
279 hexfn = fm.hexfunc
280
280
281 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
281 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
282 ('number', ' ', lambda x: x[0].rev(), str),
282 ('number', ' ', lambda x: x[0].rev(), str),
283 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
283 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
284 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
284 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
285 ('file', ' ', lambda x: x[0].path(), str),
285 ('file', ' ', lambda x: x[0].path(), str),
286 ('line_number', ':', lambda x: x[1], str),
286 ('line_number', ':', lambda x: x[1], str),
287 ]
287 ]
288 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
288 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
289
289
290 if (not opts.get('user') and not opts.get('changeset')
290 if (not opts.get('user') and not opts.get('changeset')
291 and not opts.get('date') and not opts.get('file')):
291 and not opts.get('date') and not opts.get('file')):
292 opts['number'] = True
292 opts['number'] = True
293
293
294 linenumber = opts.get('line_number') is not None
294 linenumber = opts.get('line_number') is not None
295 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
295 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
296 raise util.Abort(_('at least one of -n/-c is required for -l'))
296 raise util.Abort(_('at least one of -n/-c is required for -l'))
297
297
298 if fm:
298 if fm:
299 def makefunc(get, fmt):
299 def makefunc(get, fmt):
300 return get
300 return get
301 else:
301 else:
302 def makefunc(get, fmt):
302 def makefunc(get, fmt):
303 return lambda x: fmt(get(x))
303 return lambda x: fmt(get(x))
304 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
304 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
305 if opts.get(op)]
305 if opts.get(op)]
306 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
306 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
307 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
307 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
308 if opts.get(op))
308 if opts.get(op))
309
309
310 def bad(x, y):
310 def bad(x, y):
311 raise util.Abort("%s: %s" % (x, y))
311 raise util.Abort("%s: %s" % (x, y))
312
312
313 ctx = scmutil.revsingle(repo, opts.get('rev'))
313 ctx = scmutil.revsingle(repo, opts.get('rev'))
314 m = scmutil.match(ctx, pats, opts)
314 m = scmutil.match(ctx, pats, opts)
315 m.bad = bad
315 m.bad = bad
316 follow = not opts.get('no_follow')
316 follow = not opts.get('no_follow')
317 diffopts = patch.diffopts(ui, opts, section='annotate')
317 diffopts = patch.diffopts(ui, opts, section='annotate')
318 for abs in ctx.walk(m):
318 for abs in ctx.walk(m):
319 fctx = ctx[abs]
319 fctx = ctx[abs]
320 if not opts.get('text') and util.binary(fctx.data()):
320 if not opts.get('text') and util.binary(fctx.data()):
321 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
321 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
322 continue
322 continue
323
323
324 lines = fctx.annotate(follow=follow, linenumber=linenumber,
324 lines = fctx.annotate(follow=follow, linenumber=linenumber,
325 diffopts=diffopts)
325 diffopts=diffopts)
326 formats = []
326 formats = []
327 pieces = []
327 pieces = []
328
328
329 for f, sep in funcmap:
329 for f, sep in funcmap:
330 l = [f(n) for n, dummy in lines]
330 l = [f(n) for n, dummy in lines]
331 if l:
331 if l:
332 if fm:
332 if fm:
333 formats.append(['%s' for x in l])
333 formats.append(['%s' for x in l])
334 else:
334 else:
335 sizes = [encoding.colwidth(x) for x in l]
335 sizes = [encoding.colwidth(x) for x in l]
336 ml = max(sizes)
336 ml = max(sizes)
337 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
337 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
338 pieces.append(l)
338 pieces.append(l)
339
339
340 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
340 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
341 fm.startitem()
341 fm.startitem()
342 fm.write(fields, "".join(f), *p)
342 fm.write(fields, "".join(f), *p)
343 fm.write('line', ": %s", l[1])
343 fm.write('line', ": %s", l[1])
344
344
345 if lines and not lines[-1][1].endswith('\n'):
345 if lines and not lines[-1][1].endswith('\n'):
346 fm.plain('\n')
346 fm.plain('\n')
347
347
348 fm.end()
348 fm.end()
349
349
350 @command('archive',
350 @command('archive',
351 [('', 'no-decode', None, _('do not pass files through decoders')),
351 [('', 'no-decode', None, _('do not pass files through decoders')),
352 ('p', 'prefix', '', _('directory prefix for files in archive'),
352 ('p', 'prefix', '', _('directory prefix for files in archive'),
353 _('PREFIX')),
353 _('PREFIX')),
354 ('r', 'rev', '', _('revision to distribute'), _('REV')),
354 ('r', 'rev', '', _('revision to distribute'), _('REV')),
355 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
355 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
356 ] + subrepoopts + walkopts,
356 ] + subrepoopts + walkopts,
357 _('[OPTION]... DEST'))
357 _('[OPTION]... DEST'))
358 def archive(ui, repo, dest, **opts):
358 def archive(ui, repo, dest, **opts):
359 '''create an unversioned archive of a repository revision
359 '''create an unversioned archive of a repository revision
360
360
361 By default, the revision used is the parent of the working
361 By default, the revision used is the parent of the working
362 directory; use -r/--rev to specify a different revision.
362 directory; use -r/--rev to specify a different revision.
363
363
364 The archive type is automatically detected based on file
364 The archive type is automatically detected based on file
365 extension (or override using -t/--type).
365 extension (or override using -t/--type).
366
366
367 .. container:: verbose
367 .. container:: verbose
368
368
369 Examples:
369 Examples:
370
370
371 - create a zip file containing the 1.0 release::
371 - create a zip file containing the 1.0 release::
372
372
373 hg archive -r 1.0 project-1.0.zip
373 hg archive -r 1.0 project-1.0.zip
374
374
375 - create a tarball excluding .hg files::
375 - create a tarball excluding .hg files::
376
376
377 hg archive project.tar.gz -X ".hg*"
377 hg archive project.tar.gz -X ".hg*"
378
378
379 Valid types are:
379 Valid types are:
380
380
381 :``files``: a directory full of files (default)
381 :``files``: a directory full of files (default)
382 :``tar``: tar archive, uncompressed
382 :``tar``: tar archive, uncompressed
383 :``tbz2``: tar archive, compressed using bzip2
383 :``tbz2``: tar archive, compressed using bzip2
384 :``tgz``: tar archive, compressed using gzip
384 :``tgz``: tar archive, compressed using gzip
385 :``uzip``: zip archive, uncompressed
385 :``uzip``: zip archive, uncompressed
386 :``zip``: zip archive, compressed using deflate
386 :``zip``: zip archive, compressed using deflate
387
387
388 The exact name of the destination archive or directory is given
388 The exact name of the destination archive or directory is given
389 using a format string; see :hg:`help export` for details.
389 using a format string; see :hg:`help export` for details.
390
390
391 Each member added to an archive file has a directory prefix
391 Each member added to an archive file has a directory prefix
392 prepended. Use -p/--prefix to specify a format string for the
392 prepended. Use -p/--prefix to specify a format string for the
393 prefix. The default is the basename of the archive, with suffixes
393 prefix. The default is the basename of the archive, with suffixes
394 removed.
394 removed.
395
395
396 Returns 0 on success.
396 Returns 0 on success.
397 '''
397 '''
398
398
399 ctx = scmutil.revsingle(repo, opts.get('rev'))
399 ctx = scmutil.revsingle(repo, opts.get('rev'))
400 if not ctx:
400 if not ctx:
401 raise util.Abort(_('no working directory: please specify a revision'))
401 raise util.Abort(_('no working directory: please specify a revision'))
402 node = ctx.node()
402 node = ctx.node()
403 dest = cmdutil.makefilename(repo, dest, node)
403 dest = cmdutil.makefilename(repo, dest, node)
404 if os.path.realpath(dest) == repo.root:
404 if os.path.realpath(dest) == repo.root:
405 raise util.Abort(_('repository root cannot be destination'))
405 raise util.Abort(_('repository root cannot be destination'))
406
406
407 kind = opts.get('type') or archival.guesskind(dest) or 'files'
407 kind = opts.get('type') or archival.guesskind(dest) or 'files'
408 prefix = opts.get('prefix')
408 prefix = opts.get('prefix')
409
409
410 if dest == '-':
410 if dest == '-':
411 if kind == 'files':
411 if kind == 'files':
412 raise util.Abort(_('cannot archive plain files to stdout'))
412 raise util.Abort(_('cannot archive plain files to stdout'))
413 dest = cmdutil.makefileobj(repo, dest)
413 dest = cmdutil.makefileobj(repo, dest)
414 if not prefix:
414 if not prefix:
415 prefix = os.path.basename(repo.root) + '-%h'
415 prefix = os.path.basename(repo.root) + '-%h'
416
416
417 prefix = cmdutil.makefilename(repo, prefix, node)
417 prefix = cmdutil.makefilename(repo, prefix, node)
418 matchfn = scmutil.match(ctx, [], opts)
418 matchfn = scmutil.match(ctx, [], opts)
419 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
419 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
420 matchfn, prefix, subrepos=opts.get('subrepos'))
420 matchfn, prefix, subrepos=opts.get('subrepos'))
421
421
422 @command('backout',
422 @command('backout',
423 [('', 'merge', None, _('merge with old dirstate parent after backout')),
423 [('', 'merge', None, _('merge with old dirstate parent after backout')),
424 ('', 'parent', '',
424 ('', 'parent', '',
425 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
425 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
426 ('r', 'rev', '', _('revision to backout'), _('REV')),
426 ('r', 'rev', '', _('revision to backout'), _('REV')),
427 ('e', 'edit', False, _('invoke editor on commit messages')),
427 ('e', 'edit', False, _('invoke editor on commit messages')),
428 ] + mergetoolopts + walkopts + commitopts + commitopts2,
428 ] + mergetoolopts + walkopts + commitopts + commitopts2,
429 _('[OPTION]... [-r] REV'))
429 _('[OPTION]... [-r] REV'))
430 def backout(ui, repo, node=None, rev=None, **opts):
430 def backout(ui, repo, node=None, rev=None, **opts):
431 '''reverse effect of earlier changeset
431 '''reverse effect of earlier changeset
432
432
433 Prepare a new changeset with the effect of REV undone in the
433 Prepare a new changeset with the effect of REV undone in the
434 current working directory.
434 current working directory.
435
435
436 If REV is the parent of the working directory, then this new changeset
436 If REV is the parent of the working directory, then this new changeset
437 is committed automatically. Otherwise, hg needs to merge the
437 is committed automatically. Otherwise, hg needs to merge the
438 changes and the merged result is left uncommitted.
438 changes and the merged result is left uncommitted.
439
439
440 .. note::
440 .. note::
441
441
442 backout cannot be used to fix either an unwanted or
442 backout cannot be used to fix either an unwanted or
443 incorrect merge.
443 incorrect merge.
444
444
445 .. container:: verbose
445 .. container:: verbose
446
446
447 By default, the pending changeset will have one parent,
447 By default, the pending changeset will have one parent,
448 maintaining a linear history. With --merge, the pending
448 maintaining a linear history. With --merge, the pending
449 changeset will instead have two parents: the old parent of the
449 changeset will instead have two parents: the old parent of the
450 working directory and a new child of REV that simply undoes REV.
450 working directory and a new child of REV that simply undoes REV.
451
451
452 Before version 1.7, the behavior without --merge was equivalent
452 Before version 1.7, the behavior without --merge was equivalent
453 to specifying --merge followed by :hg:`update --clean .` to
453 to specifying --merge followed by :hg:`update --clean .` to
454 cancel the merge and leave the child of REV as a head to be
454 cancel the merge and leave the child of REV as a head to be
455 merged separately.
455 merged separately.
456
456
457 See :hg:`help dates` for a list of formats valid for -d/--date.
457 See :hg:`help dates` for a list of formats valid for -d/--date.
458
458
459 Returns 0 on success, 1 if nothing to backout or there are unresolved
459 Returns 0 on success, 1 if nothing to backout or there are unresolved
460 files.
460 files.
461 '''
461 '''
462 if rev and node:
462 if rev and node:
463 raise util.Abort(_("please specify just one revision"))
463 raise util.Abort(_("please specify just one revision"))
464
464
465 if not rev:
465 if not rev:
466 rev = node
466 rev = node
467
467
468 if not rev:
468 if not rev:
469 raise util.Abort(_("please specify a revision to backout"))
469 raise util.Abort(_("please specify a revision to backout"))
470
470
471 date = opts.get('date')
471 date = opts.get('date')
472 if date:
472 if date:
473 opts['date'] = util.parsedate(date)
473 opts['date'] = util.parsedate(date)
474
474
475 cmdutil.checkunfinished(repo)
475 cmdutil.checkunfinished(repo)
476 cmdutil.bailifchanged(repo)
476 cmdutil.bailifchanged(repo)
477 node = scmutil.revsingle(repo, rev).node()
477 node = scmutil.revsingle(repo, rev).node()
478
478
479 op1, op2 = repo.dirstate.parents()
479 op1, op2 = repo.dirstate.parents()
480 if not repo.changelog.isancestor(node, op1):
480 if not repo.changelog.isancestor(node, op1):
481 raise util.Abort(_('cannot backout change that is not an ancestor'))
481 raise util.Abort(_('cannot backout change that is not an ancestor'))
482
482
483 p1, p2 = repo.changelog.parents(node)
483 p1, p2 = repo.changelog.parents(node)
484 if p1 == nullid:
484 if p1 == nullid:
485 raise util.Abort(_('cannot backout a change with no parents'))
485 raise util.Abort(_('cannot backout a change with no parents'))
486 if p2 != nullid:
486 if p2 != nullid:
487 if not opts.get('parent'):
487 if not opts.get('parent'):
488 raise util.Abort(_('cannot backout a merge changeset'))
488 raise util.Abort(_('cannot backout a merge changeset'))
489 p = repo.lookup(opts['parent'])
489 p = repo.lookup(opts['parent'])
490 if p not in (p1, p2):
490 if p not in (p1, p2):
491 raise util.Abort(_('%s is not a parent of %s') %
491 raise util.Abort(_('%s is not a parent of %s') %
492 (short(p), short(node)))
492 (short(p), short(node)))
493 parent = p
493 parent = p
494 else:
494 else:
495 if opts.get('parent'):
495 if opts.get('parent'):
496 raise util.Abort(_('cannot use --parent on non-merge changeset'))
496 raise util.Abort(_('cannot use --parent on non-merge changeset'))
497 parent = p1
497 parent = p1
498
498
499 # the backout should appear on the same branch
499 # the backout should appear on the same branch
500 wlock = repo.wlock()
500 wlock = repo.wlock()
501 try:
501 try:
502 branch = repo.dirstate.branch()
502 branch = repo.dirstate.branch()
503 bheads = repo.branchheads(branch)
503 bheads = repo.branchheads(branch)
504 rctx = scmutil.revsingle(repo, hex(parent))
504 rctx = scmutil.revsingle(repo, hex(parent))
505 if not opts.get('merge') and op1 != node:
505 if not opts.get('merge') and op1 != node:
506 try:
506 try:
507 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
507 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
508 'backout')
508 'backout')
509 repo.dirstate.beginparentchange()
509 repo.dirstate.beginparentchange()
510 stats = mergemod.update(repo, parent, True, True, False,
510 stats = mergemod.update(repo, parent, True, True, False,
511 node, False)
511 node, False)
512 repo.setparents(op1, op2)
512 repo.setparents(op1, op2)
513 repo.dirstate.endparentchange()
513 repo.dirstate.endparentchange()
514 hg._showstats(repo, stats)
514 hg._showstats(repo, stats)
515 if stats[3]:
515 if stats[3]:
516 repo.ui.status(_("use 'hg resolve' to retry unresolved "
516 repo.ui.status(_("use 'hg resolve' to retry unresolved "
517 "file merges\n"))
517 "file merges\n"))
518 else:
518 else:
519 msg = _("changeset %s backed out, "
519 msg = _("changeset %s backed out, "
520 "don't forget to commit.\n")
520 "don't forget to commit.\n")
521 ui.status(msg % short(node))
521 ui.status(msg % short(node))
522 return stats[3] > 0
522 return stats[3] > 0
523 finally:
523 finally:
524 ui.setconfig('ui', 'forcemerge', '', '')
524 ui.setconfig('ui', 'forcemerge', '', '')
525 else:
525 else:
526 hg.clean(repo, node, show_stats=False)
526 hg.clean(repo, node, show_stats=False)
527 repo.dirstate.setbranch(branch)
527 repo.dirstate.setbranch(branch)
528 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
528 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
529
529
530
530
531 def commitfunc(ui, repo, message, match, opts):
531 def commitfunc(ui, repo, message, match, opts):
532 editform = 'backout'
532 editform = 'backout'
533 e = cmdutil.getcommiteditor(editform=editform, **opts)
533 e = cmdutil.getcommiteditor(editform=editform, **opts)
534 if not message:
534 if not message:
535 # we don't translate commit messages
535 # we don't translate commit messages
536 message = "Backed out changeset %s" % short(node)
536 message = "Backed out changeset %s" % short(node)
537 e = cmdutil.getcommiteditor(edit=True, editform=editform)
537 e = cmdutil.getcommiteditor(edit=True, editform=editform)
538 return repo.commit(message, opts.get('user'), opts.get('date'),
538 return repo.commit(message, opts.get('user'), opts.get('date'),
539 match, editor=e)
539 match, editor=e)
540 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
540 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
541 if not newnode:
541 if not newnode:
542 ui.status(_("nothing changed\n"))
542 ui.status(_("nothing changed\n"))
543 return 1
543 return 1
544 cmdutil.commitstatus(repo, newnode, branch, bheads)
544 cmdutil.commitstatus(repo, newnode, branch, bheads)
545
545
546 def nice(node):
546 def nice(node):
547 return '%d:%s' % (repo.changelog.rev(node), short(node))
547 return '%d:%s' % (repo.changelog.rev(node), short(node))
548 ui.status(_('changeset %s backs out changeset %s\n') %
548 ui.status(_('changeset %s backs out changeset %s\n') %
549 (nice(repo.changelog.tip()), nice(node)))
549 (nice(repo.changelog.tip()), nice(node)))
550 if opts.get('merge') and op1 != node:
550 if opts.get('merge') and op1 != node:
551 hg.clean(repo, op1, show_stats=False)
551 hg.clean(repo, op1, show_stats=False)
552 ui.status(_('merging with changeset %s\n')
552 ui.status(_('merging with changeset %s\n')
553 % nice(repo.changelog.tip()))
553 % nice(repo.changelog.tip()))
554 try:
554 try:
555 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
555 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
556 'backout')
556 'backout')
557 return hg.merge(repo, hex(repo.changelog.tip()))
557 return hg.merge(repo, hex(repo.changelog.tip()))
558 finally:
558 finally:
559 ui.setconfig('ui', 'forcemerge', '', '')
559 ui.setconfig('ui', 'forcemerge', '', '')
560 finally:
560 finally:
561 wlock.release()
561 wlock.release()
562 return 0
562 return 0
563
563
564 @command('bisect',
564 @command('bisect',
565 [('r', 'reset', False, _('reset bisect state')),
565 [('r', 'reset', False, _('reset bisect state')),
566 ('g', 'good', False, _('mark changeset good')),
566 ('g', 'good', False, _('mark changeset good')),
567 ('b', 'bad', False, _('mark changeset bad')),
567 ('b', 'bad', False, _('mark changeset bad')),
568 ('s', 'skip', False, _('skip testing changeset')),
568 ('s', 'skip', False, _('skip testing changeset')),
569 ('e', 'extend', False, _('extend the bisect range')),
569 ('e', 'extend', False, _('extend the bisect range')),
570 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
570 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
571 ('U', 'noupdate', False, _('do not update to target'))],
571 ('U', 'noupdate', False, _('do not update to target'))],
572 _("[-gbsr] [-U] [-c CMD] [REV]"))
572 _("[-gbsr] [-U] [-c CMD] [REV]"))
573 def bisect(ui, repo, rev=None, extra=None, command=None,
573 def bisect(ui, repo, rev=None, extra=None, command=None,
574 reset=None, good=None, bad=None, skip=None, extend=None,
574 reset=None, good=None, bad=None, skip=None, extend=None,
575 noupdate=None):
575 noupdate=None):
576 """subdivision search of changesets
576 """subdivision search of changesets
577
577
578 This command helps to find changesets which introduce problems. To
578 This command helps to find changesets which introduce problems. To
579 use, mark the earliest changeset you know exhibits the problem as
579 use, mark the earliest changeset you know exhibits the problem as
580 bad, then mark the latest changeset which is free from the problem
580 bad, then mark the latest changeset which is free from the problem
581 as good. Bisect will update your working directory to a revision
581 as good. Bisect will update your working directory to a revision
582 for testing (unless the -U/--noupdate option is specified). Once
582 for testing (unless the -U/--noupdate option is specified). Once
583 you have performed tests, mark the working directory as good or
583 you have performed tests, mark the working directory as good or
584 bad, and bisect will either update to another candidate changeset
584 bad, and bisect will either update to another candidate changeset
585 or announce that it has found the bad revision.
585 or announce that it has found the bad revision.
586
586
587 As a shortcut, you can also use the revision argument to mark a
587 As a shortcut, you can also use the revision argument to mark a
588 revision as good or bad without checking it out first.
588 revision as good or bad without checking it out first.
589
589
590 If you supply a command, it will be used for automatic bisection.
590 If you supply a command, it will be used for automatic bisection.
591 The environment variable HG_NODE will contain the ID of the
591 The environment variable HG_NODE will contain the ID of the
592 changeset being tested. The exit status of the command will be
592 changeset being tested. The exit status of the command will be
593 used to mark revisions as good or bad: status 0 means good, 125
593 used to mark revisions as good or bad: status 0 means good, 125
594 means to skip the revision, 127 (command not found) will abort the
594 means to skip the revision, 127 (command not found) will abort the
595 bisection, and any other non-zero exit status means the revision
595 bisection, and any other non-zero exit status means the revision
596 is bad.
596 is bad.
597
597
598 .. container:: verbose
598 .. container:: verbose
599
599
600 Some examples:
600 Some examples:
601
601
602 - start a bisection with known bad revision 34, and good revision 12::
602 - start a bisection with known bad revision 34, and good revision 12::
603
603
604 hg bisect --bad 34
604 hg bisect --bad 34
605 hg bisect --good 12
605 hg bisect --good 12
606
606
607 - advance the current bisection by marking current revision as good or
607 - advance the current bisection by marking current revision as good or
608 bad::
608 bad::
609
609
610 hg bisect --good
610 hg bisect --good
611 hg bisect --bad
611 hg bisect --bad
612
612
613 - mark the current revision, or a known revision, to be skipped (e.g. if
613 - mark the current revision, or a known revision, to be skipped (e.g. if
614 that revision is not usable because of another issue)::
614 that revision is not usable because of another issue)::
615
615
616 hg bisect --skip
616 hg bisect --skip
617 hg bisect --skip 23
617 hg bisect --skip 23
618
618
619 - skip all revisions that do not touch directories ``foo`` or ``bar``::
619 - skip all revisions that do not touch directories ``foo`` or ``bar``::
620
620
621 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
621 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
622
622
623 - forget the current bisection::
623 - forget the current bisection::
624
624
625 hg bisect --reset
625 hg bisect --reset
626
626
627 - use 'make && make tests' to automatically find the first broken
627 - use 'make && make tests' to automatically find the first broken
628 revision::
628 revision::
629
629
630 hg bisect --reset
630 hg bisect --reset
631 hg bisect --bad 34
631 hg bisect --bad 34
632 hg bisect --good 12
632 hg bisect --good 12
633 hg bisect --command "make && make tests"
633 hg bisect --command "make && make tests"
634
634
635 - see all changesets whose states are already known in the current
635 - see all changesets whose states are already known in the current
636 bisection::
636 bisection::
637
637
638 hg log -r "bisect(pruned)"
638 hg log -r "bisect(pruned)"
639
639
640 - see the changeset currently being bisected (especially useful
640 - see the changeset currently being bisected (especially useful
641 if running with -U/--noupdate)::
641 if running with -U/--noupdate)::
642
642
643 hg log -r "bisect(current)"
643 hg log -r "bisect(current)"
644
644
645 - see all changesets that took part in the current bisection::
645 - see all changesets that took part in the current bisection::
646
646
647 hg log -r "bisect(range)"
647 hg log -r "bisect(range)"
648
648
649 - you can even get a nice graph::
649 - you can even get a nice graph::
650
650
651 hg log --graph -r "bisect(range)"
651 hg log --graph -r "bisect(range)"
652
652
653 See :hg:`help revsets` for more about the `bisect()` keyword.
653 See :hg:`help revsets` for more about the `bisect()` keyword.
654
654
655 Returns 0 on success.
655 Returns 0 on success.
656 """
656 """
657 def extendbisectrange(nodes, good):
657 def extendbisectrange(nodes, good):
658 # bisect is incomplete when it ends on a merge node and
658 # bisect is incomplete when it ends on a merge node and
659 # one of the parent was not checked.
659 # one of the parent was not checked.
660 parents = repo[nodes[0]].parents()
660 parents = repo[nodes[0]].parents()
661 if len(parents) > 1:
661 if len(parents) > 1:
662 side = good and state['bad'] or state['good']
662 side = good and state['bad'] or state['good']
663 num = len(set(i.node() for i in parents) & set(side))
663 num = len(set(i.node() for i in parents) & set(side))
664 if num == 1:
664 if num == 1:
665 return parents[0].ancestor(parents[1])
665 return parents[0].ancestor(parents[1])
666 return None
666 return None
667
667
668 def print_result(nodes, good):
668 def print_result(nodes, good):
669 displayer = cmdutil.show_changeset(ui, repo, {})
669 displayer = cmdutil.show_changeset(ui, repo, {})
670 if len(nodes) == 1:
670 if len(nodes) == 1:
671 # narrowed it down to a single revision
671 # narrowed it down to a single revision
672 if good:
672 if good:
673 ui.write(_("The first good revision is:\n"))
673 ui.write(_("The first good revision is:\n"))
674 else:
674 else:
675 ui.write(_("The first bad revision is:\n"))
675 ui.write(_("The first bad revision is:\n"))
676 displayer.show(repo[nodes[0]])
676 displayer.show(repo[nodes[0]])
677 extendnode = extendbisectrange(nodes, good)
677 extendnode = extendbisectrange(nodes, good)
678 if extendnode is not None:
678 if extendnode is not None:
679 ui.write(_('Not all ancestors of this changeset have been'
679 ui.write(_('Not all ancestors of this changeset have been'
680 ' checked.\nUse bisect --extend to continue the '
680 ' checked.\nUse bisect --extend to continue the '
681 'bisection from\nthe common ancestor, %s.\n')
681 'bisection from\nthe common ancestor, %s.\n')
682 % extendnode)
682 % extendnode)
683 else:
683 else:
684 # multiple possible revisions
684 # multiple possible revisions
685 if good:
685 if good:
686 ui.write(_("Due to skipped revisions, the first "
686 ui.write(_("Due to skipped revisions, the first "
687 "good revision could be any of:\n"))
687 "good revision could be any of:\n"))
688 else:
688 else:
689 ui.write(_("Due to skipped revisions, the first "
689 ui.write(_("Due to skipped revisions, the first "
690 "bad revision could be any of:\n"))
690 "bad revision could be any of:\n"))
691 for n in nodes:
691 for n in nodes:
692 displayer.show(repo[n])
692 displayer.show(repo[n])
693 displayer.close()
693 displayer.close()
694
694
695 def check_state(state, interactive=True):
695 def check_state(state, interactive=True):
696 if not state['good'] or not state['bad']:
696 if not state['good'] or not state['bad']:
697 if (good or bad or skip or reset) and interactive:
697 if (good or bad or skip or reset) and interactive:
698 return
698 return
699 if not state['good']:
699 if not state['good']:
700 raise util.Abort(_('cannot bisect (no known good revisions)'))
700 raise util.Abort(_('cannot bisect (no known good revisions)'))
701 else:
701 else:
702 raise util.Abort(_('cannot bisect (no known bad revisions)'))
702 raise util.Abort(_('cannot bisect (no known bad revisions)'))
703 return True
703 return True
704
704
705 # backward compatibility
705 # backward compatibility
706 if rev in "good bad reset init".split():
706 if rev in "good bad reset init".split():
707 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
707 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
708 cmd, rev, extra = rev, extra, None
708 cmd, rev, extra = rev, extra, None
709 if cmd == "good":
709 if cmd == "good":
710 good = True
710 good = True
711 elif cmd == "bad":
711 elif cmd == "bad":
712 bad = True
712 bad = True
713 else:
713 else:
714 reset = True
714 reset = True
715 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
715 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
716 raise util.Abort(_('incompatible arguments'))
716 raise util.Abort(_('incompatible arguments'))
717
717
718 cmdutil.checkunfinished(repo)
718 cmdutil.checkunfinished(repo)
719
719
720 if reset:
720 if reset:
721 p = repo.join("bisect.state")
721 p = repo.join("bisect.state")
722 if os.path.exists(p):
722 if os.path.exists(p):
723 os.unlink(p)
723 os.unlink(p)
724 return
724 return
725
725
726 state = hbisect.load_state(repo)
726 state = hbisect.load_state(repo)
727
727
728 if command:
728 if command:
729 changesets = 1
729 changesets = 1
730 if noupdate:
730 if noupdate:
731 try:
731 try:
732 node = state['current'][0]
732 node = state['current'][0]
733 except LookupError:
733 except LookupError:
734 raise util.Abort(_('current bisect revision is unknown - '
734 raise util.Abort(_('current bisect revision is unknown - '
735 'start a new bisect to fix'))
735 'start a new bisect to fix'))
736 else:
736 else:
737 node, p2 = repo.dirstate.parents()
737 node, p2 = repo.dirstate.parents()
738 if p2 != nullid:
738 if p2 != nullid:
739 raise util.Abort(_('current bisect revision is a merge'))
739 raise util.Abort(_('current bisect revision is a merge'))
740 try:
740 try:
741 while changesets:
741 while changesets:
742 # update state
742 # update state
743 state['current'] = [node]
743 state['current'] = [node]
744 hbisect.save_state(repo, state)
744 hbisect.save_state(repo, state)
745 status = util.system(command,
745 status = util.system(command,
746 environ={'HG_NODE': hex(node)},
746 environ={'HG_NODE': hex(node)},
747 out=ui.fout)
747 out=ui.fout)
748 if status == 125:
748 if status == 125:
749 transition = "skip"
749 transition = "skip"
750 elif status == 0:
750 elif status == 0:
751 transition = "good"
751 transition = "good"
752 # status < 0 means process was killed
752 # status < 0 means process was killed
753 elif status == 127:
753 elif status == 127:
754 raise util.Abort(_("failed to execute %s") % command)
754 raise util.Abort(_("failed to execute %s") % command)
755 elif status < 0:
755 elif status < 0:
756 raise util.Abort(_("%s killed") % command)
756 raise util.Abort(_("%s killed") % command)
757 else:
757 else:
758 transition = "bad"
758 transition = "bad"
759 ctx = scmutil.revsingle(repo, rev, node)
759 ctx = scmutil.revsingle(repo, rev, node)
760 rev = None # clear for future iterations
760 rev = None # clear for future iterations
761 state[transition].append(ctx.node())
761 state[transition].append(ctx.node())
762 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
762 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
763 check_state(state, interactive=False)
763 check_state(state, interactive=False)
764 # bisect
764 # bisect
765 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
765 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
766 # update to next check
766 # update to next check
767 node = nodes[0]
767 node = nodes[0]
768 if not noupdate:
768 if not noupdate:
769 cmdutil.bailifchanged(repo)
769 cmdutil.bailifchanged(repo)
770 hg.clean(repo, node, show_stats=False)
770 hg.clean(repo, node, show_stats=False)
771 finally:
771 finally:
772 state['current'] = [node]
772 state['current'] = [node]
773 hbisect.save_state(repo, state)
773 hbisect.save_state(repo, state)
774 print_result(nodes, bgood)
774 print_result(nodes, bgood)
775 return
775 return
776
776
777 # update state
777 # update state
778
778
779 if rev:
779 if rev:
780 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
780 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
781 else:
781 else:
782 nodes = [repo.lookup('.')]
782 nodes = [repo.lookup('.')]
783
783
784 if good or bad or skip:
784 if good or bad or skip:
785 if good:
785 if good:
786 state['good'] += nodes
786 state['good'] += nodes
787 elif bad:
787 elif bad:
788 state['bad'] += nodes
788 state['bad'] += nodes
789 elif skip:
789 elif skip:
790 state['skip'] += nodes
790 state['skip'] += nodes
791 hbisect.save_state(repo, state)
791 hbisect.save_state(repo, state)
792
792
793 if not check_state(state):
793 if not check_state(state):
794 return
794 return
795
795
796 # actually bisect
796 # actually bisect
797 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
797 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
798 if extend:
798 if extend:
799 if not changesets:
799 if not changesets:
800 extendnode = extendbisectrange(nodes, good)
800 extendnode = extendbisectrange(nodes, good)
801 if extendnode is not None:
801 if extendnode is not None:
802 ui.write(_("Extending search to changeset %d:%s\n")
802 ui.write(_("Extending search to changeset %d:%s\n")
803 % (extendnode.rev(), extendnode))
803 % (extendnode.rev(), extendnode))
804 state['current'] = [extendnode.node()]
804 state['current'] = [extendnode.node()]
805 hbisect.save_state(repo, state)
805 hbisect.save_state(repo, state)
806 if noupdate:
806 if noupdate:
807 return
807 return
808 cmdutil.bailifchanged(repo)
808 cmdutil.bailifchanged(repo)
809 return hg.clean(repo, extendnode.node())
809 return hg.clean(repo, extendnode.node())
810 raise util.Abort(_("nothing to extend"))
810 raise util.Abort(_("nothing to extend"))
811
811
812 if changesets == 0:
812 if changesets == 0:
813 print_result(nodes, good)
813 print_result(nodes, good)
814 else:
814 else:
815 assert len(nodes) == 1 # only a single node can be tested next
815 assert len(nodes) == 1 # only a single node can be tested next
816 node = nodes[0]
816 node = nodes[0]
817 # compute the approximate number of remaining tests
817 # compute the approximate number of remaining tests
818 tests, size = 0, 2
818 tests, size = 0, 2
819 while size <= changesets:
819 while size <= changesets:
820 tests, size = tests + 1, size * 2
820 tests, size = tests + 1, size * 2
821 rev = repo.changelog.rev(node)
821 rev = repo.changelog.rev(node)
822 ui.write(_("Testing changeset %d:%s "
822 ui.write(_("Testing changeset %d:%s "
823 "(%d changesets remaining, ~%d tests)\n")
823 "(%d changesets remaining, ~%d tests)\n")
824 % (rev, short(node), changesets, tests))
824 % (rev, short(node), changesets, tests))
825 state['current'] = [node]
825 state['current'] = [node]
826 hbisect.save_state(repo, state)
826 hbisect.save_state(repo, state)
827 if not noupdate:
827 if not noupdate:
828 cmdutil.bailifchanged(repo)
828 cmdutil.bailifchanged(repo)
829 return hg.clean(repo, node)
829 return hg.clean(repo, node)
830
830
831 @command('bookmarks|bookmark',
831 @command('bookmarks|bookmark',
832 [('f', 'force', False, _('force')),
832 [('f', 'force', False, _('force')),
833 ('r', 'rev', '', _('revision'), _('REV')),
833 ('r', 'rev', '', _('revision'), _('REV')),
834 ('d', 'delete', False, _('delete a given bookmark')),
834 ('d', 'delete', False, _('delete a given bookmark')),
835 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
835 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
836 ('i', 'inactive', False, _('mark a bookmark inactive'))],
836 ('i', 'inactive', False, _('mark a bookmark inactive'))],
837 _('hg bookmarks [OPTIONS]... [NAME]...'))
837 _('hg bookmarks [OPTIONS]... [NAME]...'))
838 def bookmark(ui, repo, *names, **opts):
838 def bookmark(ui, repo, *names, **opts):
839 '''create a new bookmark or list existing bookmarks
839 '''create a new bookmark or list existing bookmarks
840
840
841 Bookmarks are labels on changesets to help track lines of development.
841 Bookmarks are labels on changesets to help track lines of development.
842 Bookmarks are unversioned and can be moved, renamed and deleted.
842 Bookmarks are unversioned and can be moved, renamed and deleted.
843 Deleting or moving a bookmark has no effect on the associated changesets.
843 Deleting or moving a bookmark has no effect on the associated changesets.
844
844
845 Creating or updating to a bookmark causes it to be marked as 'active'.
845 Creating or updating to a bookmark causes it to be marked as 'active'.
846 The active bookmark is indicated with a '*'.
846 The active bookmark is indicated with a '*'.
847 When a commit is made, the active bookmark will advance to the new commit.
847 When a commit is made, the active bookmark will advance to the new commit.
848 A plain :hg:`update` will also advance an active bookmark, if possible.
848 A plain :hg:`update` will also advance an active bookmark, if possible.
849 Updating away from a bookmark will cause it to be deactivated.
849 Updating away from a bookmark will cause it to be deactivated.
850
850
851 Bookmarks can be pushed and pulled between repositories (see
851 Bookmarks can be pushed and pulled between repositories (see
852 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
852 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
853 diverged, a new 'divergent bookmark' of the form 'name@path' will
853 diverged, a new 'divergent bookmark' of the form 'name@path' will
854 be created. Using :hg:'merge' will resolve the divergence.
854 be created. Using :hg:'merge' will resolve the divergence.
855
855
856 A bookmark named '@' has the special property that :hg:`clone` will
856 A bookmark named '@' has the special property that :hg:`clone` will
857 check it out by default if it exists.
857 check it out by default if it exists.
858
858
859 .. container:: verbose
859 .. container:: verbose
860
860
861 Examples:
861 Examples:
862
862
863 - create an active bookmark for a new line of development::
863 - create an active bookmark for a new line of development::
864
864
865 hg book new-feature
865 hg book new-feature
866
866
867 - create an inactive bookmark as a place marker::
867 - create an inactive bookmark as a place marker::
868
868
869 hg book -i reviewed
869 hg book -i reviewed
870
870
871 - create an inactive bookmark on another changeset::
871 - create an inactive bookmark on another changeset::
872
872
873 hg book -r .^ tested
873 hg book -r .^ tested
874
874
875 - move the '@' bookmark from another branch::
875 - move the '@' bookmark from another branch::
876
876
877 hg book -f @
877 hg book -f @
878 '''
878 '''
879 force = opts.get('force')
879 force = opts.get('force')
880 rev = opts.get('rev')
880 rev = opts.get('rev')
881 delete = opts.get('delete')
881 delete = opts.get('delete')
882 rename = opts.get('rename')
882 rename = opts.get('rename')
883 inactive = opts.get('inactive')
883 inactive = opts.get('inactive')
884
884
885 def checkformat(mark):
885 def checkformat(mark):
886 mark = mark.strip()
886 mark = mark.strip()
887 if not mark:
887 if not mark:
888 raise util.Abort(_("bookmark names cannot consist entirely of "
888 raise util.Abort(_("bookmark names cannot consist entirely of "
889 "whitespace"))
889 "whitespace"))
890 scmutil.checknewlabel(repo, mark, 'bookmark')
890 scmutil.checknewlabel(repo, mark, 'bookmark')
891 return mark
891 return mark
892
892
893 def checkconflict(repo, mark, cur, force=False, target=None):
893 def checkconflict(repo, mark, cur, force=False, target=None):
894 if mark in marks and not force:
894 if mark in marks and not force:
895 if target:
895 if target:
896 if marks[mark] == target and target == cur:
896 if marks[mark] == target and target == cur:
897 # re-activating a bookmark
897 # re-activating a bookmark
898 return
898 return
899 anc = repo.changelog.ancestors([repo[target].rev()])
899 anc = repo.changelog.ancestors([repo[target].rev()])
900 bmctx = repo[marks[mark]]
900 bmctx = repo[marks[mark]]
901 divs = [repo[b].node() for b in marks
901 divs = [repo[b].node() for b in marks
902 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
902 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
903
903
904 # allow resolving a single divergent bookmark even if moving
904 # allow resolving a single divergent bookmark even if moving
905 # the bookmark across branches when a revision is specified
905 # the bookmark across branches when a revision is specified
906 # that contains a divergent bookmark
906 # that contains a divergent bookmark
907 if bmctx.rev() not in anc and target in divs:
907 if bmctx.rev() not in anc and target in divs:
908 bookmarks.deletedivergent(repo, [target], mark)
908 bookmarks.deletedivergent(repo, [target], mark)
909 return
909 return
910
910
911 deletefrom = [b for b in divs
911 deletefrom = [b for b in divs
912 if repo[b].rev() in anc or b == target]
912 if repo[b].rev() in anc or b == target]
913 bookmarks.deletedivergent(repo, deletefrom, mark)
913 bookmarks.deletedivergent(repo, deletefrom, mark)
914 if bookmarks.validdest(repo, bmctx, repo[target]):
914 if bookmarks.validdest(repo, bmctx, repo[target]):
915 ui.status(_("moving bookmark '%s' forward from %s\n") %
915 ui.status(_("moving bookmark '%s' forward from %s\n") %
916 (mark, short(bmctx.node())))
916 (mark, short(bmctx.node())))
917 return
917 return
918 raise util.Abort(_("bookmark '%s' already exists "
918 raise util.Abort(_("bookmark '%s' already exists "
919 "(use -f to force)") % mark)
919 "(use -f to force)") % mark)
920 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
920 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
921 and not force):
921 and not force):
922 raise util.Abort(
922 raise util.Abort(
923 _("a bookmark cannot have the name of an existing branch"))
923 _("a bookmark cannot have the name of an existing branch"))
924
924
925 if delete and rename:
925 if delete and rename:
926 raise util.Abort(_("--delete and --rename are incompatible"))
926 raise util.Abort(_("--delete and --rename are incompatible"))
927 if delete and rev:
927 if delete and rev:
928 raise util.Abort(_("--rev is incompatible with --delete"))
928 raise util.Abort(_("--rev is incompatible with --delete"))
929 if rename and rev:
929 if rename and rev:
930 raise util.Abort(_("--rev is incompatible with --rename"))
930 raise util.Abort(_("--rev is incompatible with --rename"))
931 if not names and (delete or rev):
931 if not names and (delete or rev):
932 raise util.Abort(_("bookmark name required"))
932 raise util.Abort(_("bookmark name required"))
933
933
934 if delete or rename or names or inactive:
934 if delete or rename or names or inactive:
935 wlock = repo.wlock()
935 wlock = repo.wlock()
936 try:
936 try:
937 cur = repo.changectx('.').node()
937 cur = repo.changectx('.').node()
938 marks = repo._bookmarks
938 marks = repo._bookmarks
939 if delete:
939 if delete:
940 for mark in names:
940 for mark in names:
941 if mark not in marks:
941 if mark not in marks:
942 raise util.Abort(_("bookmark '%s' does not exist") %
942 raise util.Abort(_("bookmark '%s' does not exist") %
943 mark)
943 mark)
944 if mark == repo._bookmarkcurrent:
944 if mark == repo._bookmarkcurrent:
945 bookmarks.unsetcurrent(repo)
945 bookmarks.unsetcurrent(repo)
946 del marks[mark]
946 del marks[mark]
947 marks.write()
947 marks.write()
948
948
949 elif rename:
949 elif rename:
950 if not names:
950 if not names:
951 raise util.Abort(_("new bookmark name required"))
951 raise util.Abort(_("new bookmark name required"))
952 elif len(names) > 1:
952 elif len(names) > 1:
953 raise util.Abort(_("only one new bookmark name allowed"))
953 raise util.Abort(_("only one new bookmark name allowed"))
954 mark = checkformat(names[0])
954 mark = checkformat(names[0])
955 if rename not in marks:
955 if rename not in marks:
956 raise util.Abort(_("bookmark '%s' does not exist") % rename)
956 raise util.Abort(_("bookmark '%s' does not exist") % rename)
957 checkconflict(repo, mark, cur, force)
957 checkconflict(repo, mark, cur, force)
958 marks[mark] = marks[rename]
958 marks[mark] = marks[rename]
959 if repo._bookmarkcurrent == rename and not inactive:
959 if repo._bookmarkcurrent == rename and not inactive:
960 bookmarks.setcurrent(repo, mark)
960 bookmarks.setcurrent(repo, mark)
961 del marks[rename]
961 del marks[rename]
962 marks.write()
962 marks.write()
963
963
964 elif names:
964 elif names:
965 newact = None
965 newact = None
966 for mark in names:
966 for mark in names:
967 mark = checkformat(mark)
967 mark = checkformat(mark)
968 if newact is None:
968 if newact is None:
969 newact = mark
969 newact = mark
970 if inactive and mark == repo._bookmarkcurrent:
970 if inactive and mark == repo._bookmarkcurrent:
971 bookmarks.unsetcurrent(repo)
971 bookmarks.unsetcurrent(repo)
972 return
972 return
973 tgt = cur
973 tgt = cur
974 if rev:
974 if rev:
975 tgt = scmutil.revsingle(repo, rev).node()
975 tgt = scmutil.revsingle(repo, rev).node()
976 checkconflict(repo, mark, cur, force, tgt)
976 checkconflict(repo, mark, cur, force, tgt)
977 marks[mark] = tgt
977 marks[mark] = tgt
978 if not inactive and cur == marks[newact] and not rev:
978 if not inactive and cur == marks[newact] and not rev:
979 bookmarks.setcurrent(repo, newact)
979 bookmarks.setcurrent(repo, newact)
980 elif cur != tgt and newact == repo._bookmarkcurrent:
980 elif cur != tgt and newact == repo._bookmarkcurrent:
981 bookmarks.unsetcurrent(repo)
981 bookmarks.unsetcurrent(repo)
982 marks.write()
982 marks.write()
983
983
984 elif inactive:
984 elif inactive:
985 if len(marks) == 0:
985 if len(marks) == 0:
986 ui.status(_("no bookmarks set\n"))
986 ui.status(_("no bookmarks set\n"))
987 elif not repo._bookmarkcurrent:
987 elif not repo._bookmarkcurrent:
988 ui.status(_("no active bookmark\n"))
988 ui.status(_("no active bookmark\n"))
989 else:
989 else:
990 bookmarks.unsetcurrent(repo)
990 bookmarks.unsetcurrent(repo)
991 finally:
991 finally:
992 wlock.release()
992 wlock.release()
993 else: # show bookmarks
993 else: # show bookmarks
994 hexfn = ui.debugflag and hex or short
994 hexfn = ui.debugflag and hex or short
995 marks = repo._bookmarks
995 marks = repo._bookmarks
996 if len(marks) == 0:
996 if len(marks) == 0:
997 ui.status(_("no bookmarks set\n"))
997 ui.status(_("no bookmarks set\n"))
998 else:
998 else:
999 for bmark, n in sorted(marks.iteritems()):
999 for bmark, n in sorted(marks.iteritems()):
1000 current = repo._bookmarkcurrent
1000 current = repo._bookmarkcurrent
1001 if bmark == current:
1001 if bmark == current:
1002 prefix, label = '*', 'bookmarks.current'
1002 prefix, label = '*', 'bookmarks.current'
1003 else:
1003 else:
1004 prefix, label = ' ', ''
1004 prefix, label = ' ', ''
1005
1005
1006 if ui.quiet:
1006 if ui.quiet:
1007 ui.write("%s\n" % bmark, label=label)
1007 ui.write("%s\n" % bmark, label=label)
1008 else:
1008 else:
1009 pad = " " * (25 - encoding.colwidth(bmark))
1009 pad = " " * (25 - encoding.colwidth(bmark))
1010 ui.write(" %s %s%s %d:%s\n" % (
1010 ui.write(" %s %s%s %d:%s\n" % (
1011 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
1011 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
1012 label=label)
1012 label=label)
1013
1013
1014 @command('branch',
1014 @command('branch',
1015 [('f', 'force', None,
1015 [('f', 'force', None,
1016 _('set branch name even if it shadows an existing branch')),
1016 _('set branch name even if it shadows an existing branch')),
1017 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1017 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1018 _('[-fC] [NAME]'))
1018 _('[-fC] [NAME]'))
1019 def branch(ui, repo, label=None, **opts):
1019 def branch(ui, repo, label=None, **opts):
1020 """set or show the current branch name
1020 """set or show the current branch name
1021
1021
1022 .. note::
1022 .. note::
1023
1023
1024 Branch names are permanent and global. Use :hg:`bookmark` to create a
1024 Branch names are permanent and global. Use :hg:`bookmark` to create a
1025 light-weight bookmark instead. See :hg:`help glossary` for more
1025 light-weight bookmark instead. See :hg:`help glossary` for more
1026 information about named branches and bookmarks.
1026 information about named branches and bookmarks.
1027
1027
1028 With no argument, show the current branch name. With one argument,
1028 With no argument, show the current branch name. With one argument,
1029 set the working directory branch name (the branch will not exist
1029 set the working directory branch name (the branch will not exist
1030 in the repository until the next commit). Standard practice
1030 in the repository until the next commit). Standard practice
1031 recommends that primary development take place on the 'default'
1031 recommends that primary development take place on the 'default'
1032 branch.
1032 branch.
1033
1033
1034 Unless -f/--force is specified, branch will not let you set a
1034 Unless -f/--force is specified, branch will not let you set a
1035 branch name that already exists, even if it's inactive.
1035 branch name that already exists, even if it's inactive.
1036
1036
1037 Use -C/--clean to reset the working directory branch to that of
1037 Use -C/--clean to reset the working directory branch to that of
1038 the parent of the working directory, negating a previous branch
1038 the parent of the working directory, negating a previous branch
1039 change.
1039 change.
1040
1040
1041 Use the command :hg:`update` to switch to an existing branch. Use
1041 Use the command :hg:`update` to switch to an existing branch. Use
1042 :hg:`commit --close-branch` to mark this branch as closed.
1042 :hg:`commit --close-branch` to mark this branch as closed.
1043
1043
1044 Returns 0 on success.
1044 Returns 0 on success.
1045 """
1045 """
1046 if label:
1046 if label:
1047 label = label.strip()
1047 label = label.strip()
1048
1048
1049 if not opts.get('clean') and not label:
1049 if not opts.get('clean') and not label:
1050 ui.write("%s\n" % repo.dirstate.branch())
1050 ui.write("%s\n" % repo.dirstate.branch())
1051 return
1051 return
1052
1052
1053 wlock = repo.wlock()
1053 wlock = repo.wlock()
1054 try:
1054 try:
1055 if opts.get('clean'):
1055 if opts.get('clean'):
1056 label = repo[None].p1().branch()
1056 label = repo[None].p1().branch()
1057 repo.dirstate.setbranch(label)
1057 repo.dirstate.setbranch(label)
1058 ui.status(_('reset working directory to branch %s\n') % label)
1058 ui.status(_('reset working directory to branch %s\n') % label)
1059 elif label:
1059 elif label:
1060 if not opts.get('force') and label in repo.branchmap():
1060 if not opts.get('force') and label in repo.branchmap():
1061 if label not in [p.branch() for p in repo.parents()]:
1061 if label not in [p.branch() for p in repo.parents()]:
1062 raise util.Abort(_('a branch of the same name already'
1062 raise util.Abort(_('a branch of the same name already'
1063 ' exists'),
1063 ' exists'),
1064 # i18n: "it" refers to an existing branch
1064 # i18n: "it" refers to an existing branch
1065 hint=_("use 'hg update' to switch to it"))
1065 hint=_("use 'hg update' to switch to it"))
1066 scmutil.checknewlabel(repo, label, 'branch')
1066 scmutil.checknewlabel(repo, label, 'branch')
1067 repo.dirstate.setbranch(label)
1067 repo.dirstate.setbranch(label)
1068 ui.status(_('marked working directory as branch %s\n') % label)
1068 ui.status(_('marked working directory as branch %s\n') % label)
1069 ui.status(_('(branches are permanent and global, '
1069 ui.status(_('(branches are permanent and global, '
1070 'did you want a bookmark?)\n'))
1070 'did you want a bookmark?)\n'))
1071 finally:
1071 finally:
1072 wlock.release()
1072 wlock.release()
1073
1073
1074 @command('branches',
1074 @command('branches',
1075 [('a', 'active', False, _('show only branches that have unmerged heads')),
1075 [('a', 'active', False, _('show only branches that have unmerged heads')),
1076 ('c', 'closed', False, _('show normal and closed branches'))],
1076 ('c', 'closed', False, _('show normal and closed branches')),
1077 ] + formatteropts,
1077 _('[-ac]'))
1078 _('[-ac]'))
1078 def branches(ui, repo, active=False, closed=False):
1079 def branches(ui, repo, active=False, closed=False, **opts):
1079 """list repository named branches
1080 """list repository named branches
1080
1081
1081 List the repository's named branches, indicating which ones are
1082 List the repository's named branches, indicating which ones are
1082 inactive. If -c/--closed is specified, also list branches which have
1083 inactive. If -c/--closed is specified, also list branches which have
1083 been marked closed (see :hg:`commit --close-branch`).
1084 been marked closed (see :hg:`commit --close-branch`).
1084
1085
1085 If -a/--active is specified, only show active branches. A branch
1086 If -a/--active is specified, only show active branches. A branch
1086 is considered active if it contains repository heads.
1087 is considered active if it contains repository heads.
1087
1088
1088 Use the command :hg:`update` to switch to an existing branch.
1089 Use the command :hg:`update` to switch to an existing branch.
1089
1090
1090 Returns 0.
1091 Returns 0.
1091 """
1092 """
1092
1093
1093 hexfunc = ui.debugflag and hex or short
1094 fm = ui.formatter('branches', opts)
1095 hexfunc = fm.hexfunc
1094
1096
1095 allheads = set(repo.heads())
1097 allheads = set(repo.heads())
1096 branches = []
1098 branches = []
1097 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1099 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1098 isactive = not isclosed and bool(set(heads) & allheads)
1100 isactive = not isclosed and bool(set(heads) & allheads)
1099 branches.append((tag, repo[tip], isactive, not isclosed))
1101 branches.append((tag, repo[tip], isactive, not isclosed))
1100 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1102 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1101 reverse=True)
1103 reverse=True)
1102
1104
1103 for tag, ctx, isactive, isopen in branches:
1105 for tag, ctx, isactive, isopen in branches:
1104 if active and not isactive:
1106 if active and not isactive:
1105 continue
1107 continue
1106 if isactive:
1108 if isactive:
1107 label = 'branches.active'
1109 label = 'branches.active'
1108 notice = ''
1110 notice = ''
1109 elif not isopen:
1111 elif not isopen:
1110 if not closed:
1112 if not closed:
1111 continue
1113 continue
1112 label = 'branches.closed'
1114 label = 'branches.closed'
1113 notice = _(' (closed)')
1115 notice = _(' (closed)')
1114 else:
1116 else:
1115 label = 'branches.inactive'
1117 label = 'branches.inactive'
1116 notice = _(' (inactive)')
1118 notice = _(' (inactive)')
1117 if tag == repo.dirstate.branch():
1119 if tag == repo.dirstate.branch():
1118 label = 'branches.current'
1120 label = 'branches.current'
1121
1122 fm.startitem()
1123 fm.write('branch', '%s', tag, label=label)
1119 rev = ctx.rev()
1124 rev = ctx.rev()
1120 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1125 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1121 fmt = ' ' * padsize + '%d:%s'
1126 fmt = ' ' * padsize + '%d:%s'
1122 rev = ui.label(fmt % (rev, hexfunc(ctx.node())),
1127 if not ui.quiet:
1123 'log.changeset changeset.%s' % ctx.phasestr())
1128 fm.plain(' ')
1124 labeledtag = ui.label(tag, label)
1129 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1125 if ui.quiet:
1130 label='log.changeset changeset.%s' % ctx.phasestr())
1126 ui.write("%s\n" % labeledtag)
1131 if not ui.quiet:
1127 else:
1132 fm.plain(notice)
1128 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1133 fm.plain('\n')
1134 fm.end()
1129
1135
1130 @command('bundle',
1136 @command('bundle',
1131 [('f', 'force', None, _('run even when the destination is unrelated')),
1137 [('f', 'force', None, _('run even when the destination is unrelated')),
1132 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1138 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1133 _('REV')),
1139 _('REV')),
1134 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1140 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1135 _('BRANCH')),
1141 _('BRANCH')),
1136 ('', 'base', [],
1142 ('', 'base', [],
1137 _('a base changeset assumed to be available at the destination'),
1143 _('a base changeset assumed to be available at the destination'),
1138 _('REV')),
1144 _('REV')),
1139 ('a', 'all', None, _('bundle all changesets in the repository')),
1145 ('a', 'all', None, _('bundle all changesets in the repository')),
1140 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1146 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1141 ] + remoteopts,
1147 ] + remoteopts,
1142 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1148 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1143 def bundle(ui, repo, fname, dest=None, **opts):
1149 def bundle(ui, repo, fname, dest=None, **opts):
1144 """create a changegroup file
1150 """create a changegroup file
1145
1151
1146 Generate a compressed changegroup file collecting changesets not
1152 Generate a compressed changegroup file collecting changesets not
1147 known to be in another repository.
1153 known to be in another repository.
1148
1154
1149 If you omit the destination repository, then hg assumes the
1155 If you omit the destination repository, then hg assumes the
1150 destination will have all the nodes you specify with --base
1156 destination will have all the nodes you specify with --base
1151 parameters. To create a bundle containing all changesets, use
1157 parameters. To create a bundle containing all changesets, use
1152 -a/--all (or --base null).
1158 -a/--all (or --base null).
1153
1159
1154 You can change compression method with the -t/--type option.
1160 You can change compression method with the -t/--type option.
1155 The available compression methods are: none, bzip2, and
1161 The available compression methods are: none, bzip2, and
1156 gzip (by default, bundles are compressed using bzip2).
1162 gzip (by default, bundles are compressed using bzip2).
1157
1163
1158 The bundle file can then be transferred using conventional means
1164 The bundle file can then be transferred using conventional means
1159 and applied to another repository with the unbundle or pull
1165 and applied to another repository with the unbundle or pull
1160 command. This is useful when direct push and pull are not
1166 command. This is useful when direct push and pull are not
1161 available or when exporting an entire repository is undesirable.
1167 available or when exporting an entire repository is undesirable.
1162
1168
1163 Applying bundles preserves all changeset contents including
1169 Applying bundles preserves all changeset contents including
1164 permissions, copy/rename information, and revision history.
1170 permissions, copy/rename information, and revision history.
1165
1171
1166 Returns 0 on success, 1 if no changes found.
1172 Returns 0 on success, 1 if no changes found.
1167 """
1173 """
1168 revs = None
1174 revs = None
1169 if 'rev' in opts:
1175 if 'rev' in opts:
1170 revs = scmutil.revrange(repo, opts['rev'])
1176 revs = scmutil.revrange(repo, opts['rev'])
1171
1177
1172 bundletype = opts.get('type', 'bzip2').lower()
1178 bundletype = opts.get('type', 'bzip2').lower()
1173 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1179 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1174 bundletype = btypes.get(bundletype)
1180 bundletype = btypes.get(bundletype)
1175 if bundletype not in changegroup.bundletypes:
1181 if bundletype not in changegroup.bundletypes:
1176 raise util.Abort(_('unknown bundle type specified with --type'))
1182 raise util.Abort(_('unknown bundle type specified with --type'))
1177
1183
1178 if opts.get('all'):
1184 if opts.get('all'):
1179 base = ['null']
1185 base = ['null']
1180 else:
1186 else:
1181 base = scmutil.revrange(repo, opts.get('base'))
1187 base = scmutil.revrange(repo, opts.get('base'))
1182 # TODO: get desired bundlecaps from command line.
1188 # TODO: get desired bundlecaps from command line.
1183 bundlecaps = None
1189 bundlecaps = None
1184 if base:
1190 if base:
1185 if dest:
1191 if dest:
1186 raise util.Abort(_("--base is incompatible with specifying "
1192 raise util.Abort(_("--base is incompatible with specifying "
1187 "a destination"))
1193 "a destination"))
1188 common = [repo.lookup(rev) for rev in base]
1194 common = [repo.lookup(rev) for rev in base]
1189 heads = revs and map(repo.lookup, revs) or revs
1195 heads = revs and map(repo.lookup, revs) or revs
1190 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1196 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1191 common=common, bundlecaps=bundlecaps)
1197 common=common, bundlecaps=bundlecaps)
1192 outgoing = None
1198 outgoing = None
1193 else:
1199 else:
1194 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1200 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1195 dest, branches = hg.parseurl(dest, opts.get('branch'))
1201 dest, branches = hg.parseurl(dest, opts.get('branch'))
1196 other = hg.peer(repo, opts, dest)
1202 other = hg.peer(repo, opts, dest)
1197 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1203 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1198 heads = revs and map(repo.lookup, revs) or revs
1204 heads = revs and map(repo.lookup, revs) or revs
1199 outgoing = discovery.findcommonoutgoing(repo, other,
1205 outgoing = discovery.findcommonoutgoing(repo, other,
1200 onlyheads=heads,
1206 onlyheads=heads,
1201 force=opts.get('force'),
1207 force=opts.get('force'),
1202 portable=True)
1208 portable=True)
1203 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1209 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1204 bundlecaps)
1210 bundlecaps)
1205 if not cg:
1211 if not cg:
1206 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1212 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1207 return 1
1213 return 1
1208
1214
1209 changegroup.writebundle(cg, fname, bundletype)
1215 changegroup.writebundle(cg, fname, bundletype)
1210
1216
1211 @command('cat',
1217 @command('cat',
1212 [('o', 'output', '',
1218 [('o', 'output', '',
1213 _('print output to file with formatted name'), _('FORMAT')),
1219 _('print output to file with formatted name'), _('FORMAT')),
1214 ('r', 'rev', '', _('print the given revision'), _('REV')),
1220 ('r', 'rev', '', _('print the given revision'), _('REV')),
1215 ('', 'decode', None, _('apply any matching decode filter')),
1221 ('', 'decode', None, _('apply any matching decode filter')),
1216 ] + walkopts,
1222 ] + walkopts,
1217 _('[OPTION]... FILE...'),
1223 _('[OPTION]... FILE...'),
1218 inferrepo=True)
1224 inferrepo=True)
1219 def cat(ui, repo, file1, *pats, **opts):
1225 def cat(ui, repo, file1, *pats, **opts):
1220 """output the current or given revision of files
1226 """output the current or given revision of files
1221
1227
1222 Print the specified files as they were at the given revision. If
1228 Print the specified files as they were at the given revision. If
1223 no revision is given, the parent of the working directory is used.
1229 no revision is given, the parent of the working directory is used.
1224
1230
1225 Output may be to a file, in which case the name of the file is
1231 Output may be to a file, in which case the name of the file is
1226 given using a format string. The formatting rules as follows:
1232 given using a format string. The formatting rules as follows:
1227
1233
1228 :``%%``: literal "%" character
1234 :``%%``: literal "%" character
1229 :``%s``: basename of file being printed
1235 :``%s``: basename of file being printed
1230 :``%d``: dirname of file being printed, or '.' if in repository root
1236 :``%d``: dirname of file being printed, or '.' if in repository root
1231 :``%p``: root-relative path name of file being printed
1237 :``%p``: root-relative path name of file being printed
1232 :``%H``: changeset hash (40 hexadecimal digits)
1238 :``%H``: changeset hash (40 hexadecimal digits)
1233 :``%R``: changeset revision number
1239 :``%R``: changeset revision number
1234 :``%h``: short-form changeset hash (12 hexadecimal digits)
1240 :``%h``: short-form changeset hash (12 hexadecimal digits)
1235 :``%r``: zero-padded changeset revision number
1241 :``%r``: zero-padded changeset revision number
1236 :``%b``: basename of the exporting repository
1242 :``%b``: basename of the exporting repository
1237
1243
1238 Returns 0 on success.
1244 Returns 0 on success.
1239 """
1245 """
1240 ctx = scmutil.revsingle(repo, opts.get('rev'))
1246 ctx = scmutil.revsingle(repo, opts.get('rev'))
1241 m = scmutil.match(ctx, (file1,) + pats, opts)
1247 m = scmutil.match(ctx, (file1,) + pats, opts)
1242
1248
1243 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1249 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1244
1250
1245 @command('^clone',
1251 @command('^clone',
1246 [('U', 'noupdate', None,
1252 [('U', 'noupdate', None,
1247 _('the clone will include an empty working copy (only a repository)')),
1253 _('the clone will include an empty working copy (only a repository)')),
1248 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1254 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1249 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1255 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1250 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1256 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1251 ('', 'pull', None, _('use pull protocol to copy metadata')),
1257 ('', 'pull', None, _('use pull protocol to copy metadata')),
1252 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1258 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1253 ] + remoteopts,
1259 ] + remoteopts,
1254 _('[OPTION]... SOURCE [DEST]'),
1260 _('[OPTION]... SOURCE [DEST]'),
1255 norepo=True)
1261 norepo=True)
1256 def clone(ui, source, dest=None, **opts):
1262 def clone(ui, source, dest=None, **opts):
1257 """make a copy of an existing repository
1263 """make a copy of an existing repository
1258
1264
1259 Create a copy of an existing repository in a new directory.
1265 Create a copy of an existing repository in a new directory.
1260
1266
1261 If no destination directory name is specified, it defaults to the
1267 If no destination directory name is specified, it defaults to the
1262 basename of the source.
1268 basename of the source.
1263
1269
1264 The location of the source is added to the new repository's
1270 The location of the source is added to the new repository's
1265 ``.hg/hgrc`` file, as the default to be used for future pulls.
1271 ``.hg/hgrc`` file, as the default to be used for future pulls.
1266
1272
1267 Only local paths and ``ssh://`` URLs are supported as
1273 Only local paths and ``ssh://`` URLs are supported as
1268 destinations. For ``ssh://`` destinations, no working directory or
1274 destinations. For ``ssh://`` destinations, no working directory or
1269 ``.hg/hgrc`` will be created on the remote side.
1275 ``.hg/hgrc`` will be created on the remote side.
1270
1276
1271 To pull only a subset of changesets, specify one or more revisions
1277 To pull only a subset of changesets, specify one or more revisions
1272 identifiers with -r/--rev or branches with -b/--branch. The
1278 identifiers with -r/--rev or branches with -b/--branch. The
1273 resulting clone will contain only the specified changesets and
1279 resulting clone will contain only the specified changesets and
1274 their ancestors. These options (or 'clone src#rev dest') imply
1280 their ancestors. These options (or 'clone src#rev dest') imply
1275 --pull, even for local source repositories. Note that specifying a
1281 --pull, even for local source repositories. Note that specifying a
1276 tag will include the tagged changeset but not the changeset
1282 tag will include the tagged changeset but not the changeset
1277 containing the tag.
1283 containing the tag.
1278
1284
1279 If the source repository has a bookmark called '@' set, that
1285 If the source repository has a bookmark called '@' set, that
1280 revision will be checked out in the new repository by default.
1286 revision will be checked out in the new repository by default.
1281
1287
1282 To check out a particular version, use -u/--update, or
1288 To check out a particular version, use -u/--update, or
1283 -U/--noupdate to create a clone with no working directory.
1289 -U/--noupdate to create a clone with no working directory.
1284
1290
1285 .. container:: verbose
1291 .. container:: verbose
1286
1292
1287 For efficiency, hardlinks are used for cloning whenever the
1293 For efficiency, hardlinks are used for cloning whenever the
1288 source and destination are on the same filesystem (note this
1294 source and destination are on the same filesystem (note this
1289 applies only to the repository data, not to the working
1295 applies only to the repository data, not to the working
1290 directory). Some filesystems, such as AFS, implement hardlinking
1296 directory). Some filesystems, such as AFS, implement hardlinking
1291 incorrectly, but do not report errors. In these cases, use the
1297 incorrectly, but do not report errors. In these cases, use the
1292 --pull option to avoid hardlinking.
1298 --pull option to avoid hardlinking.
1293
1299
1294 In some cases, you can clone repositories and the working
1300 In some cases, you can clone repositories and the working
1295 directory using full hardlinks with ::
1301 directory using full hardlinks with ::
1296
1302
1297 $ cp -al REPO REPOCLONE
1303 $ cp -al REPO REPOCLONE
1298
1304
1299 This is the fastest way to clone, but it is not always safe. The
1305 This is the fastest way to clone, but it is not always safe. The
1300 operation is not atomic (making sure REPO is not modified during
1306 operation is not atomic (making sure REPO is not modified during
1301 the operation is up to you) and you have to make sure your
1307 the operation is up to you) and you have to make sure your
1302 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1308 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1303 so). Also, this is not compatible with certain extensions that
1309 so). Also, this is not compatible with certain extensions that
1304 place their metadata under the .hg directory, such as mq.
1310 place their metadata under the .hg directory, such as mq.
1305
1311
1306 Mercurial will update the working directory to the first applicable
1312 Mercurial will update the working directory to the first applicable
1307 revision from this list:
1313 revision from this list:
1308
1314
1309 a) null if -U or the source repository has no changesets
1315 a) null if -U or the source repository has no changesets
1310 b) if -u . and the source repository is local, the first parent of
1316 b) if -u . and the source repository is local, the first parent of
1311 the source repository's working directory
1317 the source repository's working directory
1312 c) the changeset specified with -u (if a branch name, this means the
1318 c) the changeset specified with -u (if a branch name, this means the
1313 latest head of that branch)
1319 latest head of that branch)
1314 d) the changeset specified with -r
1320 d) the changeset specified with -r
1315 e) the tipmost head specified with -b
1321 e) the tipmost head specified with -b
1316 f) the tipmost head specified with the url#branch source syntax
1322 f) the tipmost head specified with the url#branch source syntax
1317 g) the revision marked with the '@' bookmark, if present
1323 g) the revision marked with the '@' bookmark, if present
1318 h) the tipmost head of the default branch
1324 h) the tipmost head of the default branch
1319 i) tip
1325 i) tip
1320
1326
1321 Examples:
1327 Examples:
1322
1328
1323 - clone a remote repository to a new directory named hg/::
1329 - clone a remote repository to a new directory named hg/::
1324
1330
1325 hg clone http://selenic.com/hg
1331 hg clone http://selenic.com/hg
1326
1332
1327 - create a lightweight local clone::
1333 - create a lightweight local clone::
1328
1334
1329 hg clone project/ project-feature/
1335 hg clone project/ project-feature/
1330
1336
1331 - clone from an absolute path on an ssh server (note double-slash)::
1337 - clone from an absolute path on an ssh server (note double-slash)::
1332
1338
1333 hg clone ssh://user@server//home/projects/alpha/
1339 hg clone ssh://user@server//home/projects/alpha/
1334
1340
1335 - do a high-speed clone over a LAN while checking out a
1341 - do a high-speed clone over a LAN while checking out a
1336 specified version::
1342 specified version::
1337
1343
1338 hg clone --uncompressed http://server/repo -u 1.5
1344 hg clone --uncompressed http://server/repo -u 1.5
1339
1345
1340 - create a repository without changesets after a particular revision::
1346 - create a repository without changesets after a particular revision::
1341
1347
1342 hg clone -r 04e544 experimental/ good/
1348 hg clone -r 04e544 experimental/ good/
1343
1349
1344 - clone (and track) a particular named branch::
1350 - clone (and track) a particular named branch::
1345
1351
1346 hg clone http://selenic.com/hg#stable
1352 hg clone http://selenic.com/hg#stable
1347
1353
1348 See :hg:`help urls` for details on specifying URLs.
1354 See :hg:`help urls` for details on specifying URLs.
1349
1355
1350 Returns 0 on success.
1356 Returns 0 on success.
1351 """
1357 """
1352 if opts.get('noupdate') and opts.get('updaterev'):
1358 if opts.get('noupdate') and opts.get('updaterev'):
1353 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1359 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1354
1360
1355 r = hg.clone(ui, opts, source, dest,
1361 r = hg.clone(ui, opts, source, dest,
1356 pull=opts.get('pull'),
1362 pull=opts.get('pull'),
1357 stream=opts.get('uncompressed'),
1363 stream=opts.get('uncompressed'),
1358 rev=opts.get('rev'),
1364 rev=opts.get('rev'),
1359 update=opts.get('updaterev') or not opts.get('noupdate'),
1365 update=opts.get('updaterev') or not opts.get('noupdate'),
1360 branch=opts.get('branch'))
1366 branch=opts.get('branch'))
1361
1367
1362 return r is None
1368 return r is None
1363
1369
1364 @command('^commit|ci',
1370 @command('^commit|ci',
1365 [('A', 'addremove', None,
1371 [('A', 'addremove', None,
1366 _('mark new/missing files as added/removed before committing')),
1372 _('mark new/missing files as added/removed before committing')),
1367 ('', 'close-branch', None,
1373 ('', 'close-branch', None,
1368 _('mark a branch as closed, hiding it from the branch list')),
1374 _('mark a branch as closed, hiding it from the branch list')),
1369 ('', 'amend', None, _('amend the parent of the working dir')),
1375 ('', 'amend', None, _('amend the parent of the working dir')),
1370 ('s', 'secret', None, _('use the secret phase for committing')),
1376 ('s', 'secret', None, _('use the secret phase for committing')),
1371 ('e', 'edit', None, _('invoke editor on commit messages')),
1377 ('e', 'edit', None, _('invoke editor on commit messages')),
1372 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1378 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1373 _('[OPTION]... [FILE]...'),
1379 _('[OPTION]... [FILE]...'),
1374 inferrepo=True)
1380 inferrepo=True)
1375 def commit(ui, repo, *pats, **opts):
1381 def commit(ui, repo, *pats, **opts):
1376 """commit the specified files or all outstanding changes
1382 """commit the specified files or all outstanding changes
1377
1383
1378 Commit changes to the given files into the repository. Unlike a
1384 Commit changes to the given files into the repository. Unlike a
1379 centralized SCM, this operation is a local operation. See
1385 centralized SCM, this operation is a local operation. See
1380 :hg:`push` for a way to actively distribute your changes.
1386 :hg:`push` for a way to actively distribute your changes.
1381
1387
1382 If a list of files is omitted, all changes reported by :hg:`status`
1388 If a list of files is omitted, all changes reported by :hg:`status`
1383 will be committed.
1389 will be committed.
1384
1390
1385 If you are committing the result of a merge, do not provide any
1391 If you are committing the result of a merge, do not provide any
1386 filenames or -I/-X filters.
1392 filenames or -I/-X filters.
1387
1393
1388 If no commit message is specified, Mercurial starts your
1394 If no commit message is specified, Mercurial starts your
1389 configured editor where you can enter a message. In case your
1395 configured editor where you can enter a message. In case your
1390 commit fails, you will find a backup of your message in
1396 commit fails, you will find a backup of your message in
1391 ``.hg/last-message.txt``.
1397 ``.hg/last-message.txt``.
1392
1398
1393 The --amend flag can be used to amend the parent of the
1399 The --amend flag can be used to amend the parent of the
1394 working directory with a new commit that contains the changes
1400 working directory with a new commit that contains the changes
1395 in the parent in addition to those currently reported by :hg:`status`,
1401 in the parent in addition to those currently reported by :hg:`status`,
1396 if there are any. The old commit is stored in a backup bundle in
1402 if there are any. The old commit is stored in a backup bundle in
1397 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1403 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1398 on how to restore it).
1404 on how to restore it).
1399
1405
1400 Message, user and date are taken from the amended commit unless
1406 Message, user and date are taken from the amended commit unless
1401 specified. When a message isn't specified on the command line,
1407 specified. When a message isn't specified on the command line,
1402 the editor will open with the message of the amended commit.
1408 the editor will open with the message of the amended commit.
1403
1409
1404 It is not possible to amend public changesets (see :hg:`help phases`)
1410 It is not possible to amend public changesets (see :hg:`help phases`)
1405 or changesets that have children.
1411 or changesets that have children.
1406
1412
1407 See :hg:`help dates` for a list of formats valid for -d/--date.
1413 See :hg:`help dates` for a list of formats valid for -d/--date.
1408
1414
1409 Returns 0 on success, 1 if nothing changed.
1415 Returns 0 on success, 1 if nothing changed.
1410 """
1416 """
1411 if opts.get('subrepos'):
1417 if opts.get('subrepos'):
1412 if opts.get('amend'):
1418 if opts.get('amend'):
1413 raise util.Abort(_('cannot amend with --subrepos'))
1419 raise util.Abort(_('cannot amend with --subrepos'))
1414 # Let --subrepos on the command line override config setting.
1420 # Let --subrepos on the command line override config setting.
1415 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1421 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1416
1422
1417 cmdutil.checkunfinished(repo, commit=True)
1423 cmdutil.checkunfinished(repo, commit=True)
1418
1424
1419 branch = repo[None].branch()
1425 branch = repo[None].branch()
1420 bheads = repo.branchheads(branch)
1426 bheads = repo.branchheads(branch)
1421
1427
1422 extra = {}
1428 extra = {}
1423 if opts.get('close_branch'):
1429 if opts.get('close_branch'):
1424 extra['close'] = 1
1430 extra['close'] = 1
1425
1431
1426 if not bheads:
1432 if not bheads:
1427 raise util.Abort(_('can only close branch heads'))
1433 raise util.Abort(_('can only close branch heads'))
1428 elif opts.get('amend'):
1434 elif opts.get('amend'):
1429 if repo.parents()[0].p1().branch() != branch and \
1435 if repo.parents()[0].p1().branch() != branch and \
1430 repo.parents()[0].p2().branch() != branch:
1436 repo.parents()[0].p2().branch() != branch:
1431 raise util.Abort(_('can only close branch heads'))
1437 raise util.Abort(_('can only close branch heads'))
1432
1438
1433 if opts.get('amend'):
1439 if opts.get('amend'):
1434 if ui.configbool('ui', 'commitsubrepos'):
1440 if ui.configbool('ui', 'commitsubrepos'):
1435 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1441 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1436
1442
1437 old = repo['.']
1443 old = repo['.']
1438 if not old.mutable():
1444 if not old.mutable():
1439 raise util.Abort(_('cannot amend public changesets'))
1445 raise util.Abort(_('cannot amend public changesets'))
1440 if len(repo[None].parents()) > 1:
1446 if len(repo[None].parents()) > 1:
1441 raise util.Abort(_('cannot amend while merging'))
1447 raise util.Abort(_('cannot amend while merging'))
1442 if (not obsolete._enabled) and old.children():
1448 if (not obsolete._enabled) and old.children():
1443 raise util.Abort(_('cannot amend changeset with children'))
1449 raise util.Abort(_('cannot amend changeset with children'))
1444
1450
1445 # commitfunc is used only for temporary amend commit by cmdutil.amend
1451 # commitfunc is used only for temporary amend commit by cmdutil.amend
1446 def commitfunc(ui, repo, message, match, opts):
1452 def commitfunc(ui, repo, message, match, opts):
1447 return repo.commit(message,
1453 return repo.commit(message,
1448 opts.get('user') or old.user(),
1454 opts.get('user') or old.user(),
1449 opts.get('date') or old.date(),
1455 opts.get('date') or old.date(),
1450 match,
1456 match,
1451 extra=extra)
1457 extra=extra)
1452
1458
1453 current = repo._bookmarkcurrent
1459 current = repo._bookmarkcurrent
1454 marks = old.bookmarks()
1460 marks = old.bookmarks()
1455 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1461 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1456 if node == old.node():
1462 if node == old.node():
1457 ui.status(_("nothing changed\n"))
1463 ui.status(_("nothing changed\n"))
1458 return 1
1464 return 1
1459 elif marks:
1465 elif marks:
1460 ui.debug('moving bookmarks %r from %s to %s\n' %
1466 ui.debug('moving bookmarks %r from %s to %s\n' %
1461 (marks, old.hex(), hex(node)))
1467 (marks, old.hex(), hex(node)))
1462 newmarks = repo._bookmarks
1468 newmarks = repo._bookmarks
1463 for bm in marks:
1469 for bm in marks:
1464 newmarks[bm] = node
1470 newmarks[bm] = node
1465 if bm == current:
1471 if bm == current:
1466 bookmarks.setcurrent(repo, bm)
1472 bookmarks.setcurrent(repo, bm)
1467 newmarks.write()
1473 newmarks.write()
1468 else:
1474 else:
1469 def commitfunc(ui, repo, message, match, opts):
1475 def commitfunc(ui, repo, message, match, opts):
1470 backup = ui.backupconfig('phases', 'new-commit')
1476 backup = ui.backupconfig('phases', 'new-commit')
1471 baseui = repo.baseui
1477 baseui = repo.baseui
1472 basebackup = baseui.backupconfig('phases', 'new-commit')
1478 basebackup = baseui.backupconfig('phases', 'new-commit')
1473 try:
1479 try:
1474 if opts.get('secret'):
1480 if opts.get('secret'):
1475 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1481 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1476 # Propagate to subrepos
1482 # Propagate to subrepos
1477 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1483 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1478
1484
1479 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1485 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1480 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1486 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1481 return repo.commit(message, opts.get('user'), opts.get('date'),
1487 return repo.commit(message, opts.get('user'), opts.get('date'),
1482 match,
1488 match,
1483 editor=editor,
1489 editor=editor,
1484 extra=extra)
1490 extra=extra)
1485 finally:
1491 finally:
1486 ui.restoreconfig(backup)
1492 ui.restoreconfig(backup)
1487 repo.baseui.restoreconfig(basebackup)
1493 repo.baseui.restoreconfig(basebackup)
1488
1494
1489
1495
1490 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1496 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1491
1497
1492 if not node:
1498 if not node:
1493 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1499 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1494 if stat[3]:
1500 if stat[3]:
1495 ui.status(_("nothing changed (%d missing files, see "
1501 ui.status(_("nothing changed (%d missing files, see "
1496 "'hg status')\n") % len(stat[3]))
1502 "'hg status')\n") % len(stat[3]))
1497 else:
1503 else:
1498 ui.status(_("nothing changed\n"))
1504 ui.status(_("nothing changed\n"))
1499 return 1
1505 return 1
1500
1506
1501 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1507 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1502
1508
1503 @command('config|showconfig|debugconfig',
1509 @command('config|showconfig|debugconfig',
1504 [('u', 'untrusted', None, _('show untrusted configuration options')),
1510 [('u', 'untrusted', None, _('show untrusted configuration options')),
1505 ('e', 'edit', None, _('edit user config')),
1511 ('e', 'edit', None, _('edit user config')),
1506 ('l', 'local', None, _('edit repository config')),
1512 ('l', 'local', None, _('edit repository config')),
1507 ('g', 'global', None, _('edit global config'))],
1513 ('g', 'global', None, _('edit global config'))],
1508 _('[-u] [NAME]...'),
1514 _('[-u] [NAME]...'),
1509 optionalrepo=True)
1515 optionalrepo=True)
1510 def config(ui, repo, *values, **opts):
1516 def config(ui, repo, *values, **opts):
1511 """show combined config settings from all hgrc files
1517 """show combined config settings from all hgrc files
1512
1518
1513 With no arguments, print names and values of all config items.
1519 With no arguments, print names and values of all config items.
1514
1520
1515 With one argument of the form section.name, print just the value
1521 With one argument of the form section.name, print just the value
1516 of that config item.
1522 of that config item.
1517
1523
1518 With multiple arguments, print names and values of all config
1524 With multiple arguments, print names and values of all config
1519 items with matching section names.
1525 items with matching section names.
1520
1526
1521 With --edit, start an editor on the user-level config file. With
1527 With --edit, start an editor on the user-level config file. With
1522 --global, edit the system-wide config file. With --local, edit the
1528 --global, edit the system-wide config file. With --local, edit the
1523 repository-level config file.
1529 repository-level config file.
1524
1530
1525 With --debug, the source (filename and line number) is printed
1531 With --debug, the source (filename and line number) is printed
1526 for each config item.
1532 for each config item.
1527
1533
1528 See :hg:`help config` for more information about config files.
1534 See :hg:`help config` for more information about config files.
1529
1535
1530 Returns 0 on success, 1 if NAME does not exist.
1536 Returns 0 on success, 1 if NAME does not exist.
1531
1537
1532 """
1538 """
1533
1539
1534 if opts.get('edit') or opts.get('local') or opts.get('global'):
1540 if opts.get('edit') or opts.get('local') or opts.get('global'):
1535 if opts.get('local') and opts.get('global'):
1541 if opts.get('local') and opts.get('global'):
1536 raise util.Abort(_("can't use --local and --global together"))
1542 raise util.Abort(_("can't use --local and --global together"))
1537
1543
1538 if opts.get('local'):
1544 if opts.get('local'):
1539 if not repo:
1545 if not repo:
1540 raise util.Abort(_("can't use --local outside a repository"))
1546 raise util.Abort(_("can't use --local outside a repository"))
1541 paths = [repo.join('hgrc')]
1547 paths = [repo.join('hgrc')]
1542 elif opts.get('global'):
1548 elif opts.get('global'):
1543 paths = scmutil.systemrcpath()
1549 paths = scmutil.systemrcpath()
1544 else:
1550 else:
1545 paths = scmutil.userrcpath()
1551 paths = scmutil.userrcpath()
1546
1552
1547 for f in paths:
1553 for f in paths:
1548 if os.path.exists(f):
1554 if os.path.exists(f):
1549 break
1555 break
1550 else:
1556 else:
1551 from ui import samplehgrcs
1557 from ui import samplehgrcs
1552
1558
1553 if opts.get('global'):
1559 if opts.get('global'):
1554 samplehgrc = samplehgrcs['global']
1560 samplehgrc = samplehgrcs['global']
1555 elif opts.get('local'):
1561 elif opts.get('local'):
1556 samplehgrc = samplehgrcs['local']
1562 samplehgrc = samplehgrcs['local']
1557 else:
1563 else:
1558 samplehgrc = samplehgrcs['user']
1564 samplehgrc = samplehgrcs['user']
1559
1565
1560 f = paths[0]
1566 f = paths[0]
1561 fp = open(f, "w")
1567 fp = open(f, "w")
1562 fp.write(samplehgrc)
1568 fp.write(samplehgrc)
1563 fp.close()
1569 fp.close()
1564
1570
1565 editor = ui.geteditor()
1571 editor = ui.geteditor()
1566 util.system("%s \"%s\"" % (editor, f),
1572 util.system("%s \"%s\"" % (editor, f),
1567 onerr=util.Abort, errprefix=_("edit failed"),
1573 onerr=util.Abort, errprefix=_("edit failed"),
1568 out=ui.fout)
1574 out=ui.fout)
1569 return
1575 return
1570
1576
1571 for f in scmutil.rcpath():
1577 for f in scmutil.rcpath():
1572 ui.debug('read config from: %s\n' % f)
1578 ui.debug('read config from: %s\n' % f)
1573 untrusted = bool(opts.get('untrusted'))
1579 untrusted = bool(opts.get('untrusted'))
1574 if values:
1580 if values:
1575 sections = [v for v in values if '.' not in v]
1581 sections = [v for v in values if '.' not in v]
1576 items = [v for v in values if '.' in v]
1582 items = [v for v in values if '.' in v]
1577 if len(items) > 1 or items and sections:
1583 if len(items) > 1 or items and sections:
1578 raise util.Abort(_('only one config item permitted'))
1584 raise util.Abort(_('only one config item permitted'))
1579 matched = False
1585 matched = False
1580 for section, name, value in ui.walkconfig(untrusted=untrusted):
1586 for section, name, value in ui.walkconfig(untrusted=untrusted):
1581 value = str(value).replace('\n', '\\n')
1587 value = str(value).replace('\n', '\\n')
1582 sectname = section + '.' + name
1588 sectname = section + '.' + name
1583 if values:
1589 if values:
1584 for v in values:
1590 for v in values:
1585 if v == section:
1591 if v == section:
1586 ui.debug('%s: ' %
1592 ui.debug('%s: ' %
1587 ui.configsource(section, name, untrusted))
1593 ui.configsource(section, name, untrusted))
1588 ui.write('%s=%s\n' % (sectname, value))
1594 ui.write('%s=%s\n' % (sectname, value))
1589 matched = True
1595 matched = True
1590 elif v == sectname:
1596 elif v == sectname:
1591 ui.debug('%s: ' %
1597 ui.debug('%s: ' %
1592 ui.configsource(section, name, untrusted))
1598 ui.configsource(section, name, untrusted))
1593 ui.write(value, '\n')
1599 ui.write(value, '\n')
1594 matched = True
1600 matched = True
1595 else:
1601 else:
1596 ui.debug('%s: ' %
1602 ui.debug('%s: ' %
1597 ui.configsource(section, name, untrusted))
1603 ui.configsource(section, name, untrusted))
1598 ui.write('%s=%s\n' % (sectname, value))
1604 ui.write('%s=%s\n' % (sectname, value))
1599 matched = True
1605 matched = True
1600 if matched:
1606 if matched:
1601 return 0
1607 return 0
1602 return 1
1608 return 1
1603
1609
1604 @command('copy|cp',
1610 @command('copy|cp',
1605 [('A', 'after', None, _('record a copy that has already occurred')),
1611 [('A', 'after', None, _('record a copy that has already occurred')),
1606 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1612 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1607 ] + walkopts + dryrunopts,
1613 ] + walkopts + dryrunopts,
1608 _('[OPTION]... [SOURCE]... DEST'))
1614 _('[OPTION]... [SOURCE]... DEST'))
1609 def copy(ui, repo, *pats, **opts):
1615 def copy(ui, repo, *pats, **opts):
1610 """mark files as copied for the next commit
1616 """mark files as copied for the next commit
1611
1617
1612 Mark dest as having copies of source files. If dest is a
1618 Mark dest as having copies of source files. If dest is a
1613 directory, copies are put in that directory. If dest is a file,
1619 directory, copies are put in that directory. If dest is a file,
1614 the source must be a single file.
1620 the source must be a single file.
1615
1621
1616 By default, this command copies the contents of files as they
1622 By default, this command copies the contents of files as they
1617 exist in the working directory. If invoked with -A/--after, the
1623 exist in the working directory. If invoked with -A/--after, the
1618 operation is recorded, but no copying is performed.
1624 operation is recorded, but no copying is performed.
1619
1625
1620 This command takes effect with the next commit. To undo a copy
1626 This command takes effect with the next commit. To undo a copy
1621 before that, see :hg:`revert`.
1627 before that, see :hg:`revert`.
1622
1628
1623 Returns 0 on success, 1 if errors are encountered.
1629 Returns 0 on success, 1 if errors are encountered.
1624 """
1630 """
1625 wlock = repo.wlock(False)
1631 wlock = repo.wlock(False)
1626 try:
1632 try:
1627 return cmdutil.copy(ui, repo, pats, opts)
1633 return cmdutil.copy(ui, repo, pats, opts)
1628 finally:
1634 finally:
1629 wlock.release()
1635 wlock.release()
1630
1636
1631 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1637 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1632 def debugancestor(ui, repo, *args):
1638 def debugancestor(ui, repo, *args):
1633 """find the ancestor revision of two revisions in a given index"""
1639 """find the ancestor revision of two revisions in a given index"""
1634 if len(args) == 3:
1640 if len(args) == 3:
1635 index, rev1, rev2 = args
1641 index, rev1, rev2 = args
1636 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1642 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1637 lookup = r.lookup
1643 lookup = r.lookup
1638 elif len(args) == 2:
1644 elif len(args) == 2:
1639 if not repo:
1645 if not repo:
1640 raise util.Abort(_("there is no Mercurial repository here "
1646 raise util.Abort(_("there is no Mercurial repository here "
1641 "(.hg not found)"))
1647 "(.hg not found)"))
1642 rev1, rev2 = args
1648 rev1, rev2 = args
1643 r = repo.changelog
1649 r = repo.changelog
1644 lookup = repo.lookup
1650 lookup = repo.lookup
1645 else:
1651 else:
1646 raise util.Abort(_('either two or three arguments required'))
1652 raise util.Abort(_('either two or three arguments required'))
1647 a = r.ancestor(lookup(rev1), lookup(rev2))
1653 a = r.ancestor(lookup(rev1), lookup(rev2))
1648 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1654 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1649
1655
1650 @command('debugbuilddag',
1656 @command('debugbuilddag',
1651 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1657 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1652 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1658 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1653 ('n', 'new-file', None, _('add new file at each rev'))],
1659 ('n', 'new-file', None, _('add new file at each rev'))],
1654 _('[OPTION]... [TEXT]'))
1660 _('[OPTION]... [TEXT]'))
1655 def debugbuilddag(ui, repo, text=None,
1661 def debugbuilddag(ui, repo, text=None,
1656 mergeable_file=False,
1662 mergeable_file=False,
1657 overwritten_file=False,
1663 overwritten_file=False,
1658 new_file=False):
1664 new_file=False):
1659 """builds a repo with a given DAG from scratch in the current empty repo
1665 """builds a repo with a given DAG from scratch in the current empty repo
1660
1666
1661 The description of the DAG is read from stdin if not given on the
1667 The description of the DAG is read from stdin if not given on the
1662 command line.
1668 command line.
1663
1669
1664 Elements:
1670 Elements:
1665
1671
1666 - "+n" is a linear run of n nodes based on the current default parent
1672 - "+n" is a linear run of n nodes based on the current default parent
1667 - "." is a single node based on the current default parent
1673 - "." is a single node based on the current default parent
1668 - "$" resets the default parent to null (implied at the start);
1674 - "$" resets the default parent to null (implied at the start);
1669 otherwise the default parent is always the last node created
1675 otherwise the default parent is always the last node created
1670 - "<p" sets the default parent to the backref p
1676 - "<p" sets the default parent to the backref p
1671 - "*p" is a fork at parent p, which is a backref
1677 - "*p" is a fork at parent p, which is a backref
1672 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1678 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1673 - "/p2" is a merge of the preceding node and p2
1679 - "/p2" is a merge of the preceding node and p2
1674 - ":tag" defines a local tag for the preceding node
1680 - ":tag" defines a local tag for the preceding node
1675 - "@branch" sets the named branch for subsequent nodes
1681 - "@branch" sets the named branch for subsequent nodes
1676 - "#...\\n" is a comment up to the end of the line
1682 - "#...\\n" is a comment up to the end of the line
1677
1683
1678 Whitespace between the above elements is ignored.
1684 Whitespace between the above elements is ignored.
1679
1685
1680 A backref is either
1686 A backref is either
1681
1687
1682 - a number n, which references the node curr-n, where curr is the current
1688 - a number n, which references the node curr-n, where curr is the current
1683 node, or
1689 node, or
1684 - the name of a local tag you placed earlier using ":tag", or
1690 - the name of a local tag you placed earlier using ":tag", or
1685 - empty to denote the default parent.
1691 - empty to denote the default parent.
1686
1692
1687 All string valued-elements are either strictly alphanumeric, or must
1693 All string valued-elements are either strictly alphanumeric, or must
1688 be enclosed in double quotes ("..."), with "\\" as escape character.
1694 be enclosed in double quotes ("..."), with "\\" as escape character.
1689 """
1695 """
1690
1696
1691 if text is None:
1697 if text is None:
1692 ui.status(_("reading DAG from stdin\n"))
1698 ui.status(_("reading DAG from stdin\n"))
1693 text = ui.fin.read()
1699 text = ui.fin.read()
1694
1700
1695 cl = repo.changelog
1701 cl = repo.changelog
1696 if len(cl) > 0:
1702 if len(cl) > 0:
1697 raise util.Abort(_('repository is not empty'))
1703 raise util.Abort(_('repository is not empty'))
1698
1704
1699 # determine number of revs in DAG
1705 # determine number of revs in DAG
1700 total = 0
1706 total = 0
1701 for type, data in dagparser.parsedag(text):
1707 for type, data in dagparser.parsedag(text):
1702 if type == 'n':
1708 if type == 'n':
1703 total += 1
1709 total += 1
1704
1710
1705 if mergeable_file:
1711 if mergeable_file:
1706 linesperrev = 2
1712 linesperrev = 2
1707 # make a file with k lines per rev
1713 # make a file with k lines per rev
1708 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1714 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1709 initialmergedlines.append("")
1715 initialmergedlines.append("")
1710
1716
1711 tags = []
1717 tags = []
1712
1718
1713 lock = tr = None
1719 lock = tr = None
1714 try:
1720 try:
1715 lock = repo.lock()
1721 lock = repo.lock()
1716 tr = repo.transaction("builddag")
1722 tr = repo.transaction("builddag")
1717
1723
1718 at = -1
1724 at = -1
1719 atbranch = 'default'
1725 atbranch = 'default'
1720 nodeids = []
1726 nodeids = []
1721 id = 0
1727 id = 0
1722 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1728 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1723 for type, data in dagparser.parsedag(text):
1729 for type, data in dagparser.parsedag(text):
1724 if type == 'n':
1730 if type == 'n':
1725 ui.note(('node %s\n' % str(data)))
1731 ui.note(('node %s\n' % str(data)))
1726 id, ps = data
1732 id, ps = data
1727
1733
1728 files = []
1734 files = []
1729 fctxs = {}
1735 fctxs = {}
1730
1736
1731 p2 = None
1737 p2 = None
1732 if mergeable_file:
1738 if mergeable_file:
1733 fn = "mf"
1739 fn = "mf"
1734 p1 = repo[ps[0]]
1740 p1 = repo[ps[0]]
1735 if len(ps) > 1:
1741 if len(ps) > 1:
1736 p2 = repo[ps[1]]
1742 p2 = repo[ps[1]]
1737 pa = p1.ancestor(p2)
1743 pa = p1.ancestor(p2)
1738 base, local, other = [x[fn].data() for x in (pa, p1,
1744 base, local, other = [x[fn].data() for x in (pa, p1,
1739 p2)]
1745 p2)]
1740 m3 = simplemerge.Merge3Text(base, local, other)
1746 m3 = simplemerge.Merge3Text(base, local, other)
1741 ml = [l.strip() for l in m3.merge_lines()]
1747 ml = [l.strip() for l in m3.merge_lines()]
1742 ml.append("")
1748 ml.append("")
1743 elif at > 0:
1749 elif at > 0:
1744 ml = p1[fn].data().split("\n")
1750 ml = p1[fn].data().split("\n")
1745 else:
1751 else:
1746 ml = initialmergedlines
1752 ml = initialmergedlines
1747 ml[id * linesperrev] += " r%i" % id
1753 ml[id * linesperrev] += " r%i" % id
1748 mergedtext = "\n".join(ml)
1754 mergedtext = "\n".join(ml)
1749 files.append(fn)
1755 files.append(fn)
1750 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1756 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1751
1757
1752 if overwritten_file:
1758 if overwritten_file:
1753 fn = "of"
1759 fn = "of"
1754 files.append(fn)
1760 files.append(fn)
1755 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1761 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1756
1762
1757 if new_file:
1763 if new_file:
1758 fn = "nf%i" % id
1764 fn = "nf%i" % id
1759 files.append(fn)
1765 files.append(fn)
1760 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1766 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1761 if len(ps) > 1:
1767 if len(ps) > 1:
1762 if not p2:
1768 if not p2:
1763 p2 = repo[ps[1]]
1769 p2 = repo[ps[1]]
1764 for fn in p2:
1770 for fn in p2:
1765 if fn.startswith("nf"):
1771 if fn.startswith("nf"):
1766 files.append(fn)
1772 files.append(fn)
1767 fctxs[fn] = p2[fn]
1773 fctxs[fn] = p2[fn]
1768
1774
1769 def fctxfn(repo, cx, path):
1775 def fctxfn(repo, cx, path):
1770 return fctxs.get(path)
1776 return fctxs.get(path)
1771
1777
1772 if len(ps) == 0 or ps[0] < 0:
1778 if len(ps) == 0 or ps[0] < 0:
1773 pars = [None, None]
1779 pars = [None, None]
1774 elif len(ps) == 1:
1780 elif len(ps) == 1:
1775 pars = [nodeids[ps[0]], None]
1781 pars = [nodeids[ps[0]], None]
1776 else:
1782 else:
1777 pars = [nodeids[p] for p in ps]
1783 pars = [nodeids[p] for p in ps]
1778 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1784 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1779 date=(id, 0),
1785 date=(id, 0),
1780 user="debugbuilddag",
1786 user="debugbuilddag",
1781 extra={'branch': atbranch})
1787 extra={'branch': atbranch})
1782 nodeid = repo.commitctx(cx)
1788 nodeid = repo.commitctx(cx)
1783 nodeids.append(nodeid)
1789 nodeids.append(nodeid)
1784 at = id
1790 at = id
1785 elif type == 'l':
1791 elif type == 'l':
1786 id, name = data
1792 id, name = data
1787 ui.note(('tag %s\n' % name))
1793 ui.note(('tag %s\n' % name))
1788 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1794 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1789 elif type == 'a':
1795 elif type == 'a':
1790 ui.note(('branch %s\n' % data))
1796 ui.note(('branch %s\n' % data))
1791 atbranch = data
1797 atbranch = data
1792 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1798 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1793 tr.close()
1799 tr.close()
1794
1800
1795 if tags:
1801 if tags:
1796 repo.opener.write("localtags", "".join(tags))
1802 repo.opener.write("localtags", "".join(tags))
1797 finally:
1803 finally:
1798 ui.progress(_('building'), None)
1804 ui.progress(_('building'), None)
1799 release(tr, lock)
1805 release(tr, lock)
1800
1806
1801 @command('debugbundle',
1807 @command('debugbundle',
1802 [('a', 'all', None, _('show all details'))],
1808 [('a', 'all', None, _('show all details'))],
1803 _('FILE'),
1809 _('FILE'),
1804 norepo=True)
1810 norepo=True)
1805 def debugbundle(ui, bundlepath, all=None, **opts):
1811 def debugbundle(ui, bundlepath, all=None, **opts):
1806 """lists the contents of a bundle"""
1812 """lists the contents of a bundle"""
1807 f = hg.openpath(ui, bundlepath)
1813 f = hg.openpath(ui, bundlepath)
1808 try:
1814 try:
1809 gen = exchange.readbundle(ui, f, bundlepath)
1815 gen = exchange.readbundle(ui, f, bundlepath)
1810 if all:
1816 if all:
1811 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1817 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1812
1818
1813 def showchunks(named):
1819 def showchunks(named):
1814 ui.write("\n%s\n" % named)
1820 ui.write("\n%s\n" % named)
1815 chain = None
1821 chain = None
1816 while True:
1822 while True:
1817 chunkdata = gen.deltachunk(chain)
1823 chunkdata = gen.deltachunk(chain)
1818 if not chunkdata:
1824 if not chunkdata:
1819 break
1825 break
1820 node = chunkdata['node']
1826 node = chunkdata['node']
1821 p1 = chunkdata['p1']
1827 p1 = chunkdata['p1']
1822 p2 = chunkdata['p2']
1828 p2 = chunkdata['p2']
1823 cs = chunkdata['cs']
1829 cs = chunkdata['cs']
1824 deltabase = chunkdata['deltabase']
1830 deltabase = chunkdata['deltabase']
1825 delta = chunkdata['delta']
1831 delta = chunkdata['delta']
1826 ui.write("%s %s %s %s %s %s\n" %
1832 ui.write("%s %s %s %s %s %s\n" %
1827 (hex(node), hex(p1), hex(p2),
1833 (hex(node), hex(p1), hex(p2),
1828 hex(cs), hex(deltabase), len(delta)))
1834 hex(cs), hex(deltabase), len(delta)))
1829 chain = node
1835 chain = node
1830
1836
1831 chunkdata = gen.changelogheader()
1837 chunkdata = gen.changelogheader()
1832 showchunks("changelog")
1838 showchunks("changelog")
1833 chunkdata = gen.manifestheader()
1839 chunkdata = gen.manifestheader()
1834 showchunks("manifest")
1840 showchunks("manifest")
1835 while True:
1841 while True:
1836 chunkdata = gen.filelogheader()
1842 chunkdata = gen.filelogheader()
1837 if not chunkdata:
1843 if not chunkdata:
1838 break
1844 break
1839 fname = chunkdata['filename']
1845 fname = chunkdata['filename']
1840 showchunks(fname)
1846 showchunks(fname)
1841 else:
1847 else:
1842 chunkdata = gen.changelogheader()
1848 chunkdata = gen.changelogheader()
1843 chain = None
1849 chain = None
1844 while True:
1850 while True:
1845 chunkdata = gen.deltachunk(chain)
1851 chunkdata = gen.deltachunk(chain)
1846 if not chunkdata:
1852 if not chunkdata:
1847 break
1853 break
1848 node = chunkdata['node']
1854 node = chunkdata['node']
1849 ui.write("%s\n" % hex(node))
1855 ui.write("%s\n" % hex(node))
1850 chain = node
1856 chain = node
1851 finally:
1857 finally:
1852 f.close()
1858 f.close()
1853
1859
1854 @command('debugcheckstate', [], '')
1860 @command('debugcheckstate', [], '')
1855 def debugcheckstate(ui, repo):
1861 def debugcheckstate(ui, repo):
1856 """validate the correctness of the current dirstate"""
1862 """validate the correctness of the current dirstate"""
1857 parent1, parent2 = repo.dirstate.parents()
1863 parent1, parent2 = repo.dirstate.parents()
1858 m1 = repo[parent1].manifest()
1864 m1 = repo[parent1].manifest()
1859 m2 = repo[parent2].manifest()
1865 m2 = repo[parent2].manifest()
1860 errors = 0
1866 errors = 0
1861 for f in repo.dirstate:
1867 for f in repo.dirstate:
1862 state = repo.dirstate[f]
1868 state = repo.dirstate[f]
1863 if state in "nr" and f not in m1:
1869 if state in "nr" and f not in m1:
1864 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1870 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1865 errors += 1
1871 errors += 1
1866 if state in "a" and f in m1:
1872 if state in "a" and f in m1:
1867 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1873 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1868 errors += 1
1874 errors += 1
1869 if state in "m" and f not in m1 and f not in m2:
1875 if state in "m" and f not in m1 and f not in m2:
1870 ui.warn(_("%s in state %s, but not in either manifest\n") %
1876 ui.warn(_("%s in state %s, but not in either manifest\n") %
1871 (f, state))
1877 (f, state))
1872 errors += 1
1878 errors += 1
1873 for f in m1:
1879 for f in m1:
1874 state = repo.dirstate[f]
1880 state = repo.dirstate[f]
1875 if state not in "nrm":
1881 if state not in "nrm":
1876 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1882 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1877 errors += 1
1883 errors += 1
1878 if errors:
1884 if errors:
1879 error = _(".hg/dirstate inconsistent with current parent's manifest")
1885 error = _(".hg/dirstate inconsistent with current parent's manifest")
1880 raise util.Abort(error)
1886 raise util.Abort(error)
1881
1887
1882 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1888 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1883 def debugcommands(ui, cmd='', *args):
1889 def debugcommands(ui, cmd='', *args):
1884 """list all available commands and options"""
1890 """list all available commands and options"""
1885 for cmd, vals in sorted(table.iteritems()):
1891 for cmd, vals in sorted(table.iteritems()):
1886 cmd = cmd.split('|')[0].strip('^')
1892 cmd = cmd.split('|')[0].strip('^')
1887 opts = ', '.join([i[1] for i in vals[1]])
1893 opts = ', '.join([i[1] for i in vals[1]])
1888 ui.write('%s: %s\n' % (cmd, opts))
1894 ui.write('%s: %s\n' % (cmd, opts))
1889
1895
1890 @command('debugcomplete',
1896 @command('debugcomplete',
1891 [('o', 'options', None, _('show the command options'))],
1897 [('o', 'options', None, _('show the command options'))],
1892 _('[-o] CMD'),
1898 _('[-o] CMD'),
1893 norepo=True)
1899 norepo=True)
1894 def debugcomplete(ui, cmd='', **opts):
1900 def debugcomplete(ui, cmd='', **opts):
1895 """returns the completion list associated with the given command"""
1901 """returns the completion list associated with the given command"""
1896
1902
1897 if opts.get('options'):
1903 if opts.get('options'):
1898 options = []
1904 options = []
1899 otables = [globalopts]
1905 otables = [globalopts]
1900 if cmd:
1906 if cmd:
1901 aliases, entry = cmdutil.findcmd(cmd, table, False)
1907 aliases, entry = cmdutil.findcmd(cmd, table, False)
1902 otables.append(entry[1])
1908 otables.append(entry[1])
1903 for t in otables:
1909 for t in otables:
1904 for o in t:
1910 for o in t:
1905 if "(DEPRECATED)" in o[3]:
1911 if "(DEPRECATED)" in o[3]:
1906 continue
1912 continue
1907 if o[0]:
1913 if o[0]:
1908 options.append('-%s' % o[0])
1914 options.append('-%s' % o[0])
1909 options.append('--%s' % o[1])
1915 options.append('--%s' % o[1])
1910 ui.write("%s\n" % "\n".join(options))
1916 ui.write("%s\n" % "\n".join(options))
1911 return
1917 return
1912
1918
1913 cmdlist = cmdutil.findpossible(cmd, table)
1919 cmdlist = cmdutil.findpossible(cmd, table)
1914 if ui.verbose:
1920 if ui.verbose:
1915 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1921 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1916 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1922 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1917
1923
1918 @command('debugdag',
1924 @command('debugdag',
1919 [('t', 'tags', None, _('use tags as labels')),
1925 [('t', 'tags', None, _('use tags as labels')),
1920 ('b', 'branches', None, _('annotate with branch names')),
1926 ('b', 'branches', None, _('annotate with branch names')),
1921 ('', 'dots', None, _('use dots for runs')),
1927 ('', 'dots', None, _('use dots for runs')),
1922 ('s', 'spaces', None, _('separate elements by spaces'))],
1928 ('s', 'spaces', None, _('separate elements by spaces'))],
1923 _('[OPTION]... [FILE [REV]...]'),
1929 _('[OPTION]... [FILE [REV]...]'),
1924 optionalrepo=True)
1930 optionalrepo=True)
1925 def debugdag(ui, repo, file_=None, *revs, **opts):
1931 def debugdag(ui, repo, file_=None, *revs, **opts):
1926 """format the changelog or an index DAG as a concise textual description
1932 """format the changelog or an index DAG as a concise textual description
1927
1933
1928 If you pass a revlog index, the revlog's DAG is emitted. If you list
1934 If you pass a revlog index, the revlog's DAG is emitted. If you list
1929 revision numbers, they get labeled in the output as rN.
1935 revision numbers, they get labeled in the output as rN.
1930
1936
1931 Otherwise, the changelog DAG of the current repo is emitted.
1937 Otherwise, the changelog DAG of the current repo is emitted.
1932 """
1938 """
1933 spaces = opts.get('spaces')
1939 spaces = opts.get('spaces')
1934 dots = opts.get('dots')
1940 dots = opts.get('dots')
1935 if file_:
1941 if file_:
1936 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1942 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1937 revs = set((int(r) for r in revs))
1943 revs = set((int(r) for r in revs))
1938 def events():
1944 def events():
1939 for r in rlog:
1945 for r in rlog:
1940 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1946 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1941 if p != -1))
1947 if p != -1))
1942 if r in revs:
1948 if r in revs:
1943 yield 'l', (r, "r%i" % r)
1949 yield 'l', (r, "r%i" % r)
1944 elif repo:
1950 elif repo:
1945 cl = repo.changelog
1951 cl = repo.changelog
1946 tags = opts.get('tags')
1952 tags = opts.get('tags')
1947 branches = opts.get('branches')
1953 branches = opts.get('branches')
1948 if tags:
1954 if tags:
1949 labels = {}
1955 labels = {}
1950 for l, n in repo.tags().items():
1956 for l, n in repo.tags().items():
1951 labels.setdefault(cl.rev(n), []).append(l)
1957 labels.setdefault(cl.rev(n), []).append(l)
1952 def events():
1958 def events():
1953 b = "default"
1959 b = "default"
1954 for r in cl:
1960 for r in cl:
1955 if branches:
1961 if branches:
1956 newb = cl.read(cl.node(r))[5]['branch']
1962 newb = cl.read(cl.node(r))[5]['branch']
1957 if newb != b:
1963 if newb != b:
1958 yield 'a', newb
1964 yield 'a', newb
1959 b = newb
1965 b = newb
1960 yield 'n', (r, list(p for p in cl.parentrevs(r)
1966 yield 'n', (r, list(p for p in cl.parentrevs(r)
1961 if p != -1))
1967 if p != -1))
1962 if tags:
1968 if tags:
1963 ls = labels.get(r)
1969 ls = labels.get(r)
1964 if ls:
1970 if ls:
1965 for l in ls:
1971 for l in ls:
1966 yield 'l', (r, l)
1972 yield 'l', (r, l)
1967 else:
1973 else:
1968 raise util.Abort(_('need repo for changelog dag'))
1974 raise util.Abort(_('need repo for changelog dag'))
1969
1975
1970 for line in dagparser.dagtextlines(events(),
1976 for line in dagparser.dagtextlines(events(),
1971 addspaces=spaces,
1977 addspaces=spaces,
1972 wraplabels=True,
1978 wraplabels=True,
1973 wrapannotations=True,
1979 wrapannotations=True,
1974 wrapnonlinear=dots,
1980 wrapnonlinear=dots,
1975 usedots=dots,
1981 usedots=dots,
1976 maxlinewidth=70):
1982 maxlinewidth=70):
1977 ui.write(line)
1983 ui.write(line)
1978 ui.write("\n")
1984 ui.write("\n")
1979
1985
1980 @command('debugdata',
1986 @command('debugdata',
1981 [('c', 'changelog', False, _('open changelog')),
1987 [('c', 'changelog', False, _('open changelog')),
1982 ('m', 'manifest', False, _('open manifest'))],
1988 ('m', 'manifest', False, _('open manifest'))],
1983 _('-c|-m|FILE REV'))
1989 _('-c|-m|FILE REV'))
1984 def debugdata(ui, repo, file_, rev=None, **opts):
1990 def debugdata(ui, repo, file_, rev=None, **opts):
1985 """dump the contents of a data file revision"""
1991 """dump the contents of a data file revision"""
1986 if opts.get('changelog') or opts.get('manifest'):
1992 if opts.get('changelog') or opts.get('manifest'):
1987 file_, rev = None, file_
1993 file_, rev = None, file_
1988 elif rev is None:
1994 elif rev is None:
1989 raise error.CommandError('debugdata', _('invalid arguments'))
1995 raise error.CommandError('debugdata', _('invalid arguments'))
1990 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1996 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1991 try:
1997 try:
1992 ui.write(r.revision(r.lookup(rev)))
1998 ui.write(r.revision(r.lookup(rev)))
1993 except KeyError:
1999 except KeyError:
1994 raise util.Abort(_('invalid revision identifier %s') % rev)
2000 raise util.Abort(_('invalid revision identifier %s') % rev)
1995
2001
1996 @command('debugdate',
2002 @command('debugdate',
1997 [('e', 'extended', None, _('try extended date formats'))],
2003 [('e', 'extended', None, _('try extended date formats'))],
1998 _('[-e] DATE [RANGE]'),
2004 _('[-e] DATE [RANGE]'),
1999 norepo=True, optionalrepo=True)
2005 norepo=True, optionalrepo=True)
2000 def debugdate(ui, date, range=None, **opts):
2006 def debugdate(ui, date, range=None, **opts):
2001 """parse and display a date"""
2007 """parse and display a date"""
2002 if opts["extended"]:
2008 if opts["extended"]:
2003 d = util.parsedate(date, util.extendeddateformats)
2009 d = util.parsedate(date, util.extendeddateformats)
2004 else:
2010 else:
2005 d = util.parsedate(date)
2011 d = util.parsedate(date)
2006 ui.write(("internal: %s %s\n") % d)
2012 ui.write(("internal: %s %s\n") % d)
2007 ui.write(("standard: %s\n") % util.datestr(d))
2013 ui.write(("standard: %s\n") % util.datestr(d))
2008 if range:
2014 if range:
2009 m = util.matchdate(range)
2015 m = util.matchdate(range)
2010 ui.write(("match: %s\n") % m(d[0]))
2016 ui.write(("match: %s\n") % m(d[0]))
2011
2017
2012 @command('debugdiscovery',
2018 @command('debugdiscovery',
2013 [('', 'old', None, _('use old-style discovery')),
2019 [('', 'old', None, _('use old-style discovery')),
2014 ('', 'nonheads', None,
2020 ('', 'nonheads', None,
2015 _('use old-style discovery with non-heads included')),
2021 _('use old-style discovery with non-heads included')),
2016 ] + remoteopts,
2022 ] + remoteopts,
2017 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2023 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2018 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2024 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2019 """runs the changeset discovery protocol in isolation"""
2025 """runs the changeset discovery protocol in isolation"""
2020 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2026 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2021 opts.get('branch'))
2027 opts.get('branch'))
2022 remote = hg.peer(repo, opts, remoteurl)
2028 remote = hg.peer(repo, opts, remoteurl)
2023 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2029 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2024
2030
2025 # make sure tests are repeatable
2031 # make sure tests are repeatable
2026 random.seed(12323)
2032 random.seed(12323)
2027
2033
2028 def doit(localheads, remoteheads, remote=remote):
2034 def doit(localheads, remoteheads, remote=remote):
2029 if opts.get('old'):
2035 if opts.get('old'):
2030 if localheads:
2036 if localheads:
2031 raise util.Abort('cannot use localheads with old style '
2037 raise util.Abort('cannot use localheads with old style '
2032 'discovery')
2038 'discovery')
2033 if not util.safehasattr(remote, 'branches'):
2039 if not util.safehasattr(remote, 'branches'):
2034 # enable in-client legacy support
2040 # enable in-client legacy support
2035 remote = localrepo.locallegacypeer(remote.local())
2041 remote = localrepo.locallegacypeer(remote.local())
2036 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2042 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2037 force=True)
2043 force=True)
2038 common = set(common)
2044 common = set(common)
2039 if not opts.get('nonheads'):
2045 if not opts.get('nonheads'):
2040 ui.write(("unpruned common: %s\n") %
2046 ui.write(("unpruned common: %s\n") %
2041 " ".join(sorted(short(n) for n in common)))
2047 " ".join(sorted(short(n) for n in common)))
2042 dag = dagutil.revlogdag(repo.changelog)
2048 dag = dagutil.revlogdag(repo.changelog)
2043 all = dag.ancestorset(dag.internalizeall(common))
2049 all = dag.ancestorset(dag.internalizeall(common))
2044 common = dag.externalizeall(dag.headsetofconnecteds(all))
2050 common = dag.externalizeall(dag.headsetofconnecteds(all))
2045 else:
2051 else:
2046 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2052 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2047 common = set(common)
2053 common = set(common)
2048 rheads = set(hds)
2054 rheads = set(hds)
2049 lheads = set(repo.heads())
2055 lheads = set(repo.heads())
2050 ui.write(("common heads: %s\n") %
2056 ui.write(("common heads: %s\n") %
2051 " ".join(sorted(short(n) for n in common)))
2057 " ".join(sorted(short(n) for n in common)))
2052 if lheads <= common:
2058 if lheads <= common:
2053 ui.write(("local is subset\n"))
2059 ui.write(("local is subset\n"))
2054 elif rheads <= common:
2060 elif rheads <= common:
2055 ui.write(("remote is subset\n"))
2061 ui.write(("remote is subset\n"))
2056
2062
2057 serverlogs = opts.get('serverlog')
2063 serverlogs = opts.get('serverlog')
2058 if serverlogs:
2064 if serverlogs:
2059 for filename in serverlogs:
2065 for filename in serverlogs:
2060 logfile = open(filename, 'r')
2066 logfile = open(filename, 'r')
2061 try:
2067 try:
2062 line = logfile.readline()
2068 line = logfile.readline()
2063 while line:
2069 while line:
2064 parts = line.strip().split(';')
2070 parts = line.strip().split(';')
2065 op = parts[1]
2071 op = parts[1]
2066 if op == 'cg':
2072 if op == 'cg':
2067 pass
2073 pass
2068 elif op == 'cgss':
2074 elif op == 'cgss':
2069 doit(parts[2].split(' '), parts[3].split(' '))
2075 doit(parts[2].split(' '), parts[3].split(' '))
2070 elif op == 'unb':
2076 elif op == 'unb':
2071 doit(parts[3].split(' '), parts[2].split(' '))
2077 doit(parts[3].split(' '), parts[2].split(' '))
2072 line = logfile.readline()
2078 line = logfile.readline()
2073 finally:
2079 finally:
2074 logfile.close()
2080 logfile.close()
2075
2081
2076 else:
2082 else:
2077 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2083 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2078 opts.get('remote_head'))
2084 opts.get('remote_head'))
2079 localrevs = opts.get('local_head')
2085 localrevs = opts.get('local_head')
2080 doit(localrevs, remoterevs)
2086 doit(localrevs, remoterevs)
2081
2087
2082 @command('debugfileset',
2088 @command('debugfileset',
2083 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2089 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2084 _('[-r REV] FILESPEC'))
2090 _('[-r REV] FILESPEC'))
2085 def debugfileset(ui, repo, expr, **opts):
2091 def debugfileset(ui, repo, expr, **opts):
2086 '''parse and apply a fileset specification'''
2092 '''parse and apply a fileset specification'''
2087 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2093 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2088 if ui.verbose:
2094 if ui.verbose:
2089 tree = fileset.parse(expr)[0]
2095 tree = fileset.parse(expr)[0]
2090 ui.note(tree, "\n")
2096 ui.note(tree, "\n")
2091
2097
2092 for f in ctx.getfileset(expr):
2098 for f in ctx.getfileset(expr):
2093 ui.write("%s\n" % f)
2099 ui.write("%s\n" % f)
2094
2100
2095 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2101 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2096 def debugfsinfo(ui, path="."):
2102 def debugfsinfo(ui, path="."):
2097 """show information detected about current filesystem"""
2103 """show information detected about current filesystem"""
2098 util.writefile('.debugfsinfo', '')
2104 util.writefile('.debugfsinfo', '')
2099 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2105 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2100 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2106 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2101 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2107 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2102 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2108 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2103 and 'yes' or 'no'))
2109 and 'yes' or 'no'))
2104 os.unlink('.debugfsinfo')
2110 os.unlink('.debugfsinfo')
2105
2111
2106 @command('debuggetbundle',
2112 @command('debuggetbundle',
2107 [('H', 'head', [], _('id of head node'), _('ID')),
2113 [('H', 'head', [], _('id of head node'), _('ID')),
2108 ('C', 'common', [], _('id of common node'), _('ID')),
2114 ('C', 'common', [], _('id of common node'), _('ID')),
2109 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2115 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2110 _('REPO FILE [-H|-C ID]...'),
2116 _('REPO FILE [-H|-C ID]...'),
2111 norepo=True)
2117 norepo=True)
2112 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2118 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2113 """retrieves a bundle from a repo
2119 """retrieves a bundle from a repo
2114
2120
2115 Every ID must be a full-length hex node id string. Saves the bundle to the
2121 Every ID must be a full-length hex node id string. Saves the bundle to the
2116 given file.
2122 given file.
2117 """
2123 """
2118 repo = hg.peer(ui, opts, repopath)
2124 repo = hg.peer(ui, opts, repopath)
2119 if not repo.capable('getbundle'):
2125 if not repo.capable('getbundle'):
2120 raise util.Abort("getbundle() not supported by target repository")
2126 raise util.Abort("getbundle() not supported by target repository")
2121 args = {}
2127 args = {}
2122 if common:
2128 if common:
2123 args['common'] = [bin(s) for s in common]
2129 args['common'] = [bin(s) for s in common]
2124 if head:
2130 if head:
2125 args['heads'] = [bin(s) for s in head]
2131 args['heads'] = [bin(s) for s in head]
2126 # TODO: get desired bundlecaps from command line.
2132 # TODO: get desired bundlecaps from command line.
2127 args['bundlecaps'] = None
2133 args['bundlecaps'] = None
2128 bundle = repo.getbundle('debug', **args)
2134 bundle = repo.getbundle('debug', **args)
2129
2135
2130 bundletype = opts.get('type', 'bzip2').lower()
2136 bundletype = opts.get('type', 'bzip2').lower()
2131 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2137 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2132 bundletype = btypes.get(bundletype)
2138 bundletype = btypes.get(bundletype)
2133 if bundletype not in changegroup.bundletypes:
2139 if bundletype not in changegroup.bundletypes:
2134 raise util.Abort(_('unknown bundle type specified with --type'))
2140 raise util.Abort(_('unknown bundle type specified with --type'))
2135 changegroup.writebundle(bundle, bundlepath, bundletype)
2141 changegroup.writebundle(bundle, bundlepath, bundletype)
2136
2142
2137 @command('debugignore', [], '')
2143 @command('debugignore', [], '')
2138 def debugignore(ui, repo, *values, **opts):
2144 def debugignore(ui, repo, *values, **opts):
2139 """display the combined ignore pattern"""
2145 """display the combined ignore pattern"""
2140 ignore = repo.dirstate._ignore
2146 ignore = repo.dirstate._ignore
2141 includepat = getattr(ignore, 'includepat', None)
2147 includepat = getattr(ignore, 'includepat', None)
2142 if includepat is not None:
2148 if includepat is not None:
2143 ui.write("%s\n" % includepat)
2149 ui.write("%s\n" % includepat)
2144 else:
2150 else:
2145 raise util.Abort(_("no ignore patterns found"))
2151 raise util.Abort(_("no ignore patterns found"))
2146
2152
2147 @command('debugindex',
2153 @command('debugindex',
2148 [('c', 'changelog', False, _('open changelog')),
2154 [('c', 'changelog', False, _('open changelog')),
2149 ('m', 'manifest', False, _('open manifest')),
2155 ('m', 'manifest', False, _('open manifest')),
2150 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2156 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2151 _('[-f FORMAT] -c|-m|FILE'),
2157 _('[-f FORMAT] -c|-m|FILE'),
2152 optionalrepo=True)
2158 optionalrepo=True)
2153 def debugindex(ui, repo, file_=None, **opts):
2159 def debugindex(ui, repo, file_=None, **opts):
2154 """dump the contents of an index file"""
2160 """dump the contents of an index file"""
2155 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2161 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2156 format = opts.get('format', 0)
2162 format = opts.get('format', 0)
2157 if format not in (0, 1):
2163 if format not in (0, 1):
2158 raise util.Abort(_("unknown format %d") % format)
2164 raise util.Abort(_("unknown format %d") % format)
2159
2165
2160 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2166 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2161 if generaldelta:
2167 if generaldelta:
2162 basehdr = ' delta'
2168 basehdr = ' delta'
2163 else:
2169 else:
2164 basehdr = ' base'
2170 basehdr = ' base'
2165
2171
2166 if format == 0:
2172 if format == 0:
2167 ui.write(" rev offset length " + basehdr + " linkrev"
2173 ui.write(" rev offset length " + basehdr + " linkrev"
2168 " nodeid p1 p2\n")
2174 " nodeid p1 p2\n")
2169 elif format == 1:
2175 elif format == 1:
2170 ui.write(" rev flag offset length"
2176 ui.write(" rev flag offset length"
2171 " size " + basehdr + " link p1 p2"
2177 " size " + basehdr + " link p1 p2"
2172 " nodeid\n")
2178 " nodeid\n")
2173
2179
2174 for i in r:
2180 for i in r:
2175 node = r.node(i)
2181 node = r.node(i)
2176 if generaldelta:
2182 if generaldelta:
2177 base = r.deltaparent(i)
2183 base = r.deltaparent(i)
2178 else:
2184 else:
2179 base = r.chainbase(i)
2185 base = r.chainbase(i)
2180 if format == 0:
2186 if format == 0:
2181 try:
2187 try:
2182 pp = r.parents(node)
2188 pp = r.parents(node)
2183 except Exception:
2189 except Exception:
2184 pp = [nullid, nullid]
2190 pp = [nullid, nullid]
2185 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2191 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2186 i, r.start(i), r.length(i), base, r.linkrev(i),
2192 i, r.start(i), r.length(i), base, r.linkrev(i),
2187 short(node), short(pp[0]), short(pp[1])))
2193 short(node), short(pp[0]), short(pp[1])))
2188 elif format == 1:
2194 elif format == 1:
2189 pr = r.parentrevs(i)
2195 pr = r.parentrevs(i)
2190 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2196 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2191 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2197 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2192 base, r.linkrev(i), pr[0], pr[1], short(node)))
2198 base, r.linkrev(i), pr[0], pr[1], short(node)))
2193
2199
2194 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2200 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2195 def debugindexdot(ui, repo, file_):
2201 def debugindexdot(ui, repo, file_):
2196 """dump an index DAG as a graphviz dot file"""
2202 """dump an index DAG as a graphviz dot file"""
2197 r = None
2203 r = None
2198 if repo:
2204 if repo:
2199 filelog = repo.file(file_)
2205 filelog = repo.file(file_)
2200 if len(filelog):
2206 if len(filelog):
2201 r = filelog
2207 r = filelog
2202 if not r:
2208 if not r:
2203 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2209 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2204 ui.write(("digraph G {\n"))
2210 ui.write(("digraph G {\n"))
2205 for i in r:
2211 for i in r:
2206 node = r.node(i)
2212 node = r.node(i)
2207 pp = r.parents(node)
2213 pp = r.parents(node)
2208 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2214 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2209 if pp[1] != nullid:
2215 if pp[1] != nullid:
2210 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2216 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2211 ui.write("}\n")
2217 ui.write("}\n")
2212
2218
2213 @command('debuginstall', [], '', norepo=True)
2219 @command('debuginstall', [], '', norepo=True)
2214 def debuginstall(ui):
2220 def debuginstall(ui):
2215 '''test Mercurial installation
2221 '''test Mercurial installation
2216
2222
2217 Returns 0 on success.
2223 Returns 0 on success.
2218 '''
2224 '''
2219
2225
2220 def writetemp(contents):
2226 def writetemp(contents):
2221 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2227 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2222 f = os.fdopen(fd, "wb")
2228 f = os.fdopen(fd, "wb")
2223 f.write(contents)
2229 f.write(contents)
2224 f.close()
2230 f.close()
2225 return name
2231 return name
2226
2232
2227 problems = 0
2233 problems = 0
2228
2234
2229 # encoding
2235 # encoding
2230 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2236 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2231 try:
2237 try:
2232 encoding.fromlocal("test")
2238 encoding.fromlocal("test")
2233 except util.Abort, inst:
2239 except util.Abort, inst:
2234 ui.write(" %s\n" % inst)
2240 ui.write(" %s\n" % inst)
2235 ui.write(_(" (check that your locale is properly set)\n"))
2241 ui.write(_(" (check that your locale is properly set)\n"))
2236 problems += 1
2242 problems += 1
2237
2243
2238 # Python
2244 # Python
2239 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2245 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2240 ui.status(_("checking Python version (%s)\n")
2246 ui.status(_("checking Python version (%s)\n")
2241 % ("%s.%s.%s" % sys.version_info[:3]))
2247 % ("%s.%s.%s" % sys.version_info[:3]))
2242 ui.status(_("checking Python lib (%s)...\n")
2248 ui.status(_("checking Python lib (%s)...\n")
2243 % os.path.dirname(os.__file__))
2249 % os.path.dirname(os.__file__))
2244
2250
2245 # compiled modules
2251 # compiled modules
2246 ui.status(_("checking installed modules (%s)...\n")
2252 ui.status(_("checking installed modules (%s)...\n")
2247 % os.path.dirname(__file__))
2253 % os.path.dirname(__file__))
2248 try:
2254 try:
2249 import bdiff, mpatch, base85, osutil
2255 import bdiff, mpatch, base85, osutil
2250 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2256 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2251 except Exception, inst:
2257 except Exception, inst:
2252 ui.write(" %s\n" % inst)
2258 ui.write(" %s\n" % inst)
2253 ui.write(_(" One or more extensions could not be found"))
2259 ui.write(_(" One or more extensions could not be found"))
2254 ui.write(_(" (check that you compiled the extensions)\n"))
2260 ui.write(_(" (check that you compiled the extensions)\n"))
2255 problems += 1
2261 problems += 1
2256
2262
2257 # templates
2263 # templates
2258 import templater
2264 import templater
2259 p = templater.templatepaths()
2265 p = templater.templatepaths()
2260 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2266 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2261 if p:
2267 if p:
2262 m = templater.templatepath("map-cmdline.default")
2268 m = templater.templatepath("map-cmdline.default")
2263 if m:
2269 if m:
2264 # template found, check if it is working
2270 # template found, check if it is working
2265 try:
2271 try:
2266 templater.templater(m)
2272 templater.templater(m)
2267 except Exception, inst:
2273 except Exception, inst:
2268 ui.write(" %s\n" % inst)
2274 ui.write(" %s\n" % inst)
2269 p = None
2275 p = None
2270 else:
2276 else:
2271 ui.write(_(" template 'default' not found\n"))
2277 ui.write(_(" template 'default' not found\n"))
2272 p = None
2278 p = None
2273 else:
2279 else:
2274 ui.write(_(" no template directories found\n"))
2280 ui.write(_(" no template directories found\n"))
2275 if not p:
2281 if not p:
2276 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2282 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2277 problems += 1
2283 problems += 1
2278
2284
2279 # editor
2285 # editor
2280 ui.status(_("checking commit editor...\n"))
2286 ui.status(_("checking commit editor...\n"))
2281 editor = ui.geteditor()
2287 editor = ui.geteditor()
2282 cmdpath = util.findexe(shlex.split(editor)[0])
2288 cmdpath = util.findexe(shlex.split(editor)[0])
2283 if not cmdpath:
2289 if not cmdpath:
2284 if editor == 'vi':
2290 if editor == 'vi':
2285 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2291 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2286 ui.write(_(" (specify a commit editor in your configuration"
2292 ui.write(_(" (specify a commit editor in your configuration"
2287 " file)\n"))
2293 " file)\n"))
2288 else:
2294 else:
2289 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2295 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2290 ui.write(_(" (specify a commit editor in your configuration"
2296 ui.write(_(" (specify a commit editor in your configuration"
2291 " file)\n"))
2297 " file)\n"))
2292 problems += 1
2298 problems += 1
2293
2299
2294 # check username
2300 # check username
2295 ui.status(_("checking username...\n"))
2301 ui.status(_("checking username...\n"))
2296 try:
2302 try:
2297 ui.username()
2303 ui.username()
2298 except util.Abort, e:
2304 except util.Abort, e:
2299 ui.write(" %s\n" % e)
2305 ui.write(" %s\n" % e)
2300 ui.write(_(" (specify a username in your configuration file)\n"))
2306 ui.write(_(" (specify a username in your configuration file)\n"))
2301 problems += 1
2307 problems += 1
2302
2308
2303 if not problems:
2309 if not problems:
2304 ui.status(_("no problems detected\n"))
2310 ui.status(_("no problems detected\n"))
2305 else:
2311 else:
2306 ui.write(_("%s problems detected,"
2312 ui.write(_("%s problems detected,"
2307 " please check your install!\n") % problems)
2313 " please check your install!\n") % problems)
2308
2314
2309 return problems
2315 return problems
2310
2316
2311 @command('debugknown', [], _('REPO ID...'), norepo=True)
2317 @command('debugknown', [], _('REPO ID...'), norepo=True)
2312 def debugknown(ui, repopath, *ids, **opts):
2318 def debugknown(ui, repopath, *ids, **opts):
2313 """test whether node ids are known to a repo
2319 """test whether node ids are known to a repo
2314
2320
2315 Every ID must be a full-length hex node id string. Returns a list of 0s
2321 Every ID must be a full-length hex node id string. Returns a list of 0s
2316 and 1s indicating unknown/known.
2322 and 1s indicating unknown/known.
2317 """
2323 """
2318 repo = hg.peer(ui, opts, repopath)
2324 repo = hg.peer(ui, opts, repopath)
2319 if not repo.capable('known'):
2325 if not repo.capable('known'):
2320 raise util.Abort("known() not supported by target repository")
2326 raise util.Abort("known() not supported by target repository")
2321 flags = repo.known([bin(s) for s in ids])
2327 flags = repo.known([bin(s) for s in ids])
2322 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2328 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2323
2329
2324 @command('debuglabelcomplete', [], _('LABEL...'))
2330 @command('debuglabelcomplete', [], _('LABEL...'))
2325 def debuglabelcomplete(ui, repo, *args):
2331 def debuglabelcomplete(ui, repo, *args):
2326 '''complete "labels" - tags, open branch names, bookmark names'''
2332 '''complete "labels" - tags, open branch names, bookmark names'''
2327
2333
2328 labels = set()
2334 labels = set()
2329 labels.update(t[0] for t in repo.tagslist())
2335 labels.update(t[0] for t in repo.tagslist())
2330 labels.update(repo._bookmarks.keys())
2336 labels.update(repo._bookmarks.keys())
2331 labels.update(tag for (tag, heads, tip, closed)
2337 labels.update(tag for (tag, heads, tip, closed)
2332 in repo.branchmap().iterbranches() if not closed)
2338 in repo.branchmap().iterbranches() if not closed)
2333 completions = set()
2339 completions = set()
2334 if not args:
2340 if not args:
2335 args = ['']
2341 args = ['']
2336 for a in args:
2342 for a in args:
2337 completions.update(l for l in labels if l.startswith(a))
2343 completions.update(l for l in labels if l.startswith(a))
2338 ui.write('\n'.join(sorted(completions)))
2344 ui.write('\n'.join(sorted(completions)))
2339 ui.write('\n')
2345 ui.write('\n')
2340
2346
2341 @command('debuglocks',
2347 @command('debuglocks',
2342 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2348 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2343 ('W', 'force-wlock', None,
2349 ('W', 'force-wlock', None,
2344 _('free the working state lock (DANGEROUS)'))],
2350 _('free the working state lock (DANGEROUS)'))],
2345 _(''))
2351 _(''))
2346 def debuglocks(ui, repo, **opts):
2352 def debuglocks(ui, repo, **opts):
2347 """show or modify state of locks
2353 """show or modify state of locks
2348
2354
2349 By default, this command will show which locks are held. This
2355 By default, this command will show which locks are held. This
2350 includes the user and process holding the lock, the amount of time
2356 includes the user and process holding the lock, the amount of time
2351 the lock has been held, and the machine name where the process is
2357 the lock has been held, and the machine name where the process is
2352 running if it's not local.
2358 running if it's not local.
2353
2359
2354 Locks protect the integrity of Mercurial's data, so should be
2360 Locks protect the integrity of Mercurial's data, so should be
2355 treated with care. System crashes or other interruptions may cause
2361 treated with care. System crashes or other interruptions may cause
2356 locks to not be properly released, though Mercurial will usually
2362 locks to not be properly released, though Mercurial will usually
2357 detect and remove such stale locks automatically.
2363 detect and remove such stale locks automatically.
2358
2364
2359 However, detecting stale locks may not always be possible (for
2365 However, detecting stale locks may not always be possible (for
2360 instance, on a shared filesystem). Removing locks may also be
2366 instance, on a shared filesystem). Removing locks may also be
2361 blocked by filesystem permissions.
2367 blocked by filesystem permissions.
2362
2368
2363 Returns 0 if no locks are held.
2369 Returns 0 if no locks are held.
2364
2370
2365 """
2371 """
2366
2372
2367 if opts.get('force_lock'):
2373 if opts.get('force_lock'):
2368 repo.svfs.unlink('lock')
2374 repo.svfs.unlink('lock')
2369 if opts.get('force_wlock'):
2375 if opts.get('force_wlock'):
2370 repo.vfs.unlink('wlock')
2376 repo.vfs.unlink('wlock')
2371 if opts.get('force_lock') or opts.get('force_lock'):
2377 if opts.get('force_lock') or opts.get('force_lock'):
2372 return 0
2378 return 0
2373
2379
2374 now = time.time()
2380 now = time.time()
2375 held = 0
2381 held = 0
2376
2382
2377 def report(vfs, name, method):
2383 def report(vfs, name, method):
2378 # this causes stale locks to get reaped for more accurate reporting
2384 # this causes stale locks to get reaped for more accurate reporting
2379 try:
2385 try:
2380 l = method(False)
2386 l = method(False)
2381 except error.LockHeld:
2387 except error.LockHeld:
2382 l = None
2388 l = None
2383
2389
2384 if l:
2390 if l:
2385 l.release()
2391 l.release()
2386 else:
2392 else:
2387 try:
2393 try:
2388 stat = repo.svfs.lstat(name)
2394 stat = repo.svfs.lstat(name)
2389 age = now - stat.st_mtime
2395 age = now - stat.st_mtime
2390 user = util.username(stat.st_uid)
2396 user = util.username(stat.st_uid)
2391 locker = vfs.readlock(name)
2397 locker = vfs.readlock(name)
2392 if ":" in locker:
2398 if ":" in locker:
2393 host, pid = locker.split(':')
2399 host, pid = locker.split(':')
2394 if host == socket.gethostname():
2400 if host == socket.gethostname():
2395 locker = 'user %s, process %s' % (user, pid)
2401 locker = 'user %s, process %s' % (user, pid)
2396 else:
2402 else:
2397 locker = 'user %s, process %s, host %s' \
2403 locker = 'user %s, process %s, host %s' \
2398 % (user, pid, host)
2404 % (user, pid, host)
2399 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2405 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2400 return 1
2406 return 1
2401 except OSError, e:
2407 except OSError, e:
2402 if e.errno != errno.ENOENT:
2408 if e.errno != errno.ENOENT:
2403 raise
2409 raise
2404
2410
2405 ui.write("%-6s free\n" % (name + ":"))
2411 ui.write("%-6s free\n" % (name + ":"))
2406 return 0
2412 return 0
2407
2413
2408 held += report(repo.svfs, "lock", repo.lock)
2414 held += report(repo.svfs, "lock", repo.lock)
2409 held += report(repo.vfs, "wlock", repo.wlock)
2415 held += report(repo.vfs, "wlock", repo.wlock)
2410
2416
2411 return held
2417 return held
2412
2418
2413 @command('debugobsolete',
2419 @command('debugobsolete',
2414 [('', 'flags', 0, _('markers flag')),
2420 [('', 'flags', 0, _('markers flag')),
2415 ('', 'record-parents', False,
2421 ('', 'record-parents', False,
2416 _('record parent information for the precursor')),
2422 _('record parent information for the precursor')),
2417 ('r', 'rev', [], _('display markers relevant to REV')),
2423 ('r', 'rev', [], _('display markers relevant to REV')),
2418 ] + commitopts2,
2424 ] + commitopts2,
2419 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2425 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2420 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2426 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2421 """create arbitrary obsolete marker
2427 """create arbitrary obsolete marker
2422
2428
2423 With no arguments, displays the list of obsolescence markers."""
2429 With no arguments, displays the list of obsolescence markers."""
2424
2430
2425 def parsenodeid(s):
2431 def parsenodeid(s):
2426 try:
2432 try:
2427 # We do not use revsingle/revrange functions here to accept
2433 # We do not use revsingle/revrange functions here to accept
2428 # arbitrary node identifiers, possibly not present in the
2434 # arbitrary node identifiers, possibly not present in the
2429 # local repository.
2435 # local repository.
2430 n = bin(s)
2436 n = bin(s)
2431 if len(n) != len(nullid):
2437 if len(n) != len(nullid):
2432 raise TypeError()
2438 raise TypeError()
2433 return n
2439 return n
2434 except TypeError:
2440 except TypeError:
2435 raise util.Abort('changeset references must be full hexadecimal '
2441 raise util.Abort('changeset references must be full hexadecimal '
2436 'node identifiers')
2442 'node identifiers')
2437
2443
2438 if precursor is not None:
2444 if precursor is not None:
2439 if opts['rev']:
2445 if opts['rev']:
2440 raise util.Abort('cannot select revision when creating marker')
2446 raise util.Abort('cannot select revision when creating marker')
2441 metadata = {}
2447 metadata = {}
2442 metadata['user'] = opts['user'] or ui.username()
2448 metadata['user'] = opts['user'] or ui.username()
2443 succs = tuple(parsenodeid(succ) for succ in successors)
2449 succs = tuple(parsenodeid(succ) for succ in successors)
2444 l = repo.lock()
2450 l = repo.lock()
2445 try:
2451 try:
2446 tr = repo.transaction('debugobsolete')
2452 tr = repo.transaction('debugobsolete')
2447 try:
2453 try:
2448 try:
2454 try:
2449 date = opts.get('date')
2455 date = opts.get('date')
2450 if date:
2456 if date:
2451 date = util.parsedate(date)
2457 date = util.parsedate(date)
2452 else:
2458 else:
2453 date = None
2459 date = None
2454 prec = parsenodeid(precursor)
2460 prec = parsenodeid(precursor)
2455 parents = None
2461 parents = None
2456 if opts['record_parents']:
2462 if opts['record_parents']:
2457 if prec not in repo.unfiltered():
2463 if prec not in repo.unfiltered():
2458 raise util.Abort('cannot used --record-parents on '
2464 raise util.Abort('cannot used --record-parents on '
2459 'unknown changesets')
2465 'unknown changesets')
2460 parents = repo.unfiltered()[prec].parents()
2466 parents = repo.unfiltered()[prec].parents()
2461 parents = tuple(p.node() for p in parents)
2467 parents = tuple(p.node() for p in parents)
2462 repo.obsstore.create(tr, prec, succs, opts['flags'],
2468 repo.obsstore.create(tr, prec, succs, opts['flags'],
2463 parents=parents, date=date,
2469 parents=parents, date=date,
2464 metadata=metadata)
2470 metadata=metadata)
2465 tr.close()
2471 tr.close()
2466 except ValueError, exc:
2472 except ValueError, exc:
2467 raise util.Abort(_('bad obsmarker input: %s') % exc)
2473 raise util.Abort(_('bad obsmarker input: %s') % exc)
2468 finally:
2474 finally:
2469 tr.release()
2475 tr.release()
2470 finally:
2476 finally:
2471 l.release()
2477 l.release()
2472 else:
2478 else:
2473 if opts['rev']:
2479 if opts['rev']:
2474 revs = scmutil.revrange(repo, opts['rev'])
2480 revs = scmutil.revrange(repo, opts['rev'])
2475 nodes = [repo[r].node() for r in revs]
2481 nodes = [repo[r].node() for r in revs]
2476 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2482 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2477 markers.sort(key=lambda x: x._data)
2483 markers.sort(key=lambda x: x._data)
2478 else:
2484 else:
2479 markers = obsolete.getmarkers(repo)
2485 markers = obsolete.getmarkers(repo)
2480
2486
2481 for m in markers:
2487 for m in markers:
2482 cmdutil.showmarker(ui, m)
2488 cmdutil.showmarker(ui, m)
2483
2489
2484 @command('debugpathcomplete',
2490 @command('debugpathcomplete',
2485 [('f', 'full', None, _('complete an entire path')),
2491 [('f', 'full', None, _('complete an entire path')),
2486 ('n', 'normal', None, _('show only normal files')),
2492 ('n', 'normal', None, _('show only normal files')),
2487 ('a', 'added', None, _('show only added files')),
2493 ('a', 'added', None, _('show only added files')),
2488 ('r', 'removed', None, _('show only removed files'))],
2494 ('r', 'removed', None, _('show only removed files'))],
2489 _('FILESPEC...'))
2495 _('FILESPEC...'))
2490 def debugpathcomplete(ui, repo, *specs, **opts):
2496 def debugpathcomplete(ui, repo, *specs, **opts):
2491 '''complete part or all of a tracked path
2497 '''complete part or all of a tracked path
2492
2498
2493 This command supports shells that offer path name completion. It
2499 This command supports shells that offer path name completion. It
2494 currently completes only files already known to the dirstate.
2500 currently completes only files already known to the dirstate.
2495
2501
2496 Completion extends only to the next path segment unless
2502 Completion extends only to the next path segment unless
2497 --full is specified, in which case entire paths are used.'''
2503 --full is specified, in which case entire paths are used.'''
2498
2504
2499 def complete(path, acceptable):
2505 def complete(path, acceptable):
2500 dirstate = repo.dirstate
2506 dirstate = repo.dirstate
2501 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2507 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2502 rootdir = repo.root + os.sep
2508 rootdir = repo.root + os.sep
2503 if spec != repo.root and not spec.startswith(rootdir):
2509 if spec != repo.root and not spec.startswith(rootdir):
2504 return [], []
2510 return [], []
2505 if os.path.isdir(spec):
2511 if os.path.isdir(spec):
2506 spec += '/'
2512 spec += '/'
2507 spec = spec[len(rootdir):]
2513 spec = spec[len(rootdir):]
2508 fixpaths = os.sep != '/'
2514 fixpaths = os.sep != '/'
2509 if fixpaths:
2515 if fixpaths:
2510 spec = spec.replace(os.sep, '/')
2516 spec = spec.replace(os.sep, '/')
2511 speclen = len(spec)
2517 speclen = len(spec)
2512 fullpaths = opts['full']
2518 fullpaths = opts['full']
2513 files, dirs = set(), set()
2519 files, dirs = set(), set()
2514 adddir, addfile = dirs.add, files.add
2520 adddir, addfile = dirs.add, files.add
2515 for f, st in dirstate.iteritems():
2521 for f, st in dirstate.iteritems():
2516 if f.startswith(spec) and st[0] in acceptable:
2522 if f.startswith(spec) and st[0] in acceptable:
2517 if fixpaths:
2523 if fixpaths:
2518 f = f.replace('/', os.sep)
2524 f = f.replace('/', os.sep)
2519 if fullpaths:
2525 if fullpaths:
2520 addfile(f)
2526 addfile(f)
2521 continue
2527 continue
2522 s = f.find(os.sep, speclen)
2528 s = f.find(os.sep, speclen)
2523 if s >= 0:
2529 if s >= 0:
2524 adddir(f[:s])
2530 adddir(f[:s])
2525 else:
2531 else:
2526 addfile(f)
2532 addfile(f)
2527 return files, dirs
2533 return files, dirs
2528
2534
2529 acceptable = ''
2535 acceptable = ''
2530 if opts['normal']:
2536 if opts['normal']:
2531 acceptable += 'nm'
2537 acceptable += 'nm'
2532 if opts['added']:
2538 if opts['added']:
2533 acceptable += 'a'
2539 acceptable += 'a'
2534 if opts['removed']:
2540 if opts['removed']:
2535 acceptable += 'r'
2541 acceptable += 'r'
2536 cwd = repo.getcwd()
2542 cwd = repo.getcwd()
2537 if not specs:
2543 if not specs:
2538 specs = ['.']
2544 specs = ['.']
2539
2545
2540 files, dirs = set(), set()
2546 files, dirs = set(), set()
2541 for spec in specs:
2547 for spec in specs:
2542 f, d = complete(spec, acceptable or 'nmar')
2548 f, d = complete(spec, acceptable or 'nmar')
2543 files.update(f)
2549 files.update(f)
2544 dirs.update(d)
2550 dirs.update(d)
2545 files.update(dirs)
2551 files.update(dirs)
2546 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2552 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2547 ui.write('\n')
2553 ui.write('\n')
2548
2554
2549 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2555 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2550 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2556 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2551 '''access the pushkey key/value protocol
2557 '''access the pushkey key/value protocol
2552
2558
2553 With two args, list the keys in the given namespace.
2559 With two args, list the keys in the given namespace.
2554
2560
2555 With five args, set a key to new if it currently is set to old.
2561 With five args, set a key to new if it currently is set to old.
2556 Reports success or failure.
2562 Reports success or failure.
2557 '''
2563 '''
2558
2564
2559 target = hg.peer(ui, {}, repopath)
2565 target = hg.peer(ui, {}, repopath)
2560 if keyinfo:
2566 if keyinfo:
2561 key, old, new = keyinfo
2567 key, old, new = keyinfo
2562 r = target.pushkey(namespace, key, old, new)
2568 r = target.pushkey(namespace, key, old, new)
2563 ui.status(str(r) + '\n')
2569 ui.status(str(r) + '\n')
2564 return not r
2570 return not r
2565 else:
2571 else:
2566 for k, v in sorted(target.listkeys(namespace).iteritems()):
2572 for k, v in sorted(target.listkeys(namespace).iteritems()):
2567 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2573 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2568 v.encode('string-escape')))
2574 v.encode('string-escape')))
2569
2575
2570 @command('debugpvec', [], _('A B'))
2576 @command('debugpvec', [], _('A B'))
2571 def debugpvec(ui, repo, a, b=None):
2577 def debugpvec(ui, repo, a, b=None):
2572 ca = scmutil.revsingle(repo, a)
2578 ca = scmutil.revsingle(repo, a)
2573 cb = scmutil.revsingle(repo, b)
2579 cb = scmutil.revsingle(repo, b)
2574 pa = pvec.ctxpvec(ca)
2580 pa = pvec.ctxpvec(ca)
2575 pb = pvec.ctxpvec(cb)
2581 pb = pvec.ctxpvec(cb)
2576 if pa == pb:
2582 if pa == pb:
2577 rel = "="
2583 rel = "="
2578 elif pa > pb:
2584 elif pa > pb:
2579 rel = ">"
2585 rel = ">"
2580 elif pa < pb:
2586 elif pa < pb:
2581 rel = "<"
2587 rel = "<"
2582 elif pa | pb:
2588 elif pa | pb:
2583 rel = "|"
2589 rel = "|"
2584 ui.write(_("a: %s\n") % pa)
2590 ui.write(_("a: %s\n") % pa)
2585 ui.write(_("b: %s\n") % pb)
2591 ui.write(_("b: %s\n") % pb)
2586 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2592 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2587 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2593 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2588 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2594 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2589 pa.distance(pb), rel))
2595 pa.distance(pb), rel))
2590
2596
2591 @command('debugrebuilddirstate|debugrebuildstate',
2597 @command('debugrebuilddirstate|debugrebuildstate',
2592 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2598 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2593 _('[-r REV]'))
2599 _('[-r REV]'))
2594 def debugrebuilddirstate(ui, repo, rev):
2600 def debugrebuilddirstate(ui, repo, rev):
2595 """rebuild the dirstate as it would look like for the given revision
2601 """rebuild the dirstate as it would look like for the given revision
2596
2602
2597 If no revision is specified the first current parent will be used.
2603 If no revision is specified the first current parent will be used.
2598
2604
2599 The dirstate will be set to the files of the given revision.
2605 The dirstate will be set to the files of the given revision.
2600 The actual working directory content or existing dirstate
2606 The actual working directory content or existing dirstate
2601 information such as adds or removes is not considered.
2607 information such as adds or removes is not considered.
2602
2608
2603 One use of this command is to make the next :hg:`status` invocation
2609 One use of this command is to make the next :hg:`status` invocation
2604 check the actual file content.
2610 check the actual file content.
2605 """
2611 """
2606 ctx = scmutil.revsingle(repo, rev)
2612 ctx = scmutil.revsingle(repo, rev)
2607 wlock = repo.wlock()
2613 wlock = repo.wlock()
2608 try:
2614 try:
2609 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2615 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2610 finally:
2616 finally:
2611 wlock.release()
2617 wlock.release()
2612
2618
2613 @command('debugrename',
2619 @command('debugrename',
2614 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2620 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2615 _('[-r REV] FILE'))
2621 _('[-r REV] FILE'))
2616 def debugrename(ui, repo, file1, *pats, **opts):
2622 def debugrename(ui, repo, file1, *pats, **opts):
2617 """dump rename information"""
2623 """dump rename information"""
2618
2624
2619 ctx = scmutil.revsingle(repo, opts.get('rev'))
2625 ctx = scmutil.revsingle(repo, opts.get('rev'))
2620 m = scmutil.match(ctx, (file1,) + pats, opts)
2626 m = scmutil.match(ctx, (file1,) + pats, opts)
2621 for abs in ctx.walk(m):
2627 for abs in ctx.walk(m):
2622 fctx = ctx[abs]
2628 fctx = ctx[abs]
2623 o = fctx.filelog().renamed(fctx.filenode())
2629 o = fctx.filelog().renamed(fctx.filenode())
2624 rel = m.rel(abs)
2630 rel = m.rel(abs)
2625 if o:
2631 if o:
2626 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2632 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2627 else:
2633 else:
2628 ui.write(_("%s not renamed\n") % rel)
2634 ui.write(_("%s not renamed\n") % rel)
2629
2635
2630 @command('debugrevlog',
2636 @command('debugrevlog',
2631 [('c', 'changelog', False, _('open changelog')),
2637 [('c', 'changelog', False, _('open changelog')),
2632 ('m', 'manifest', False, _('open manifest')),
2638 ('m', 'manifest', False, _('open manifest')),
2633 ('d', 'dump', False, _('dump index data'))],
2639 ('d', 'dump', False, _('dump index data'))],
2634 _('-c|-m|FILE'),
2640 _('-c|-m|FILE'),
2635 optionalrepo=True)
2641 optionalrepo=True)
2636 def debugrevlog(ui, repo, file_=None, **opts):
2642 def debugrevlog(ui, repo, file_=None, **opts):
2637 """show data and statistics about a revlog"""
2643 """show data and statistics about a revlog"""
2638 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2644 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2639
2645
2640 if opts.get("dump"):
2646 if opts.get("dump"):
2641 numrevs = len(r)
2647 numrevs = len(r)
2642 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2648 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2643 " rawsize totalsize compression heads chainlen\n")
2649 " rawsize totalsize compression heads chainlen\n")
2644 ts = 0
2650 ts = 0
2645 heads = set()
2651 heads = set()
2646 rindex = r.index
2652 rindex = r.index
2647
2653
2648 def chainbaseandlen(rev):
2654 def chainbaseandlen(rev):
2649 clen = 0
2655 clen = 0
2650 base = rindex[rev][3]
2656 base = rindex[rev][3]
2651 while base != rev:
2657 while base != rev:
2652 clen += 1
2658 clen += 1
2653 rev = base
2659 rev = base
2654 base = rindex[rev][3]
2660 base = rindex[rev][3]
2655 return base, clen
2661 return base, clen
2656
2662
2657 for rev in xrange(numrevs):
2663 for rev in xrange(numrevs):
2658 dbase = r.deltaparent(rev)
2664 dbase = r.deltaparent(rev)
2659 if dbase == -1:
2665 if dbase == -1:
2660 dbase = rev
2666 dbase = rev
2661 cbase, clen = chainbaseandlen(rev)
2667 cbase, clen = chainbaseandlen(rev)
2662 p1, p2 = r.parentrevs(rev)
2668 p1, p2 = r.parentrevs(rev)
2663 rs = r.rawsize(rev)
2669 rs = r.rawsize(rev)
2664 ts = ts + rs
2670 ts = ts + rs
2665 heads -= set(r.parentrevs(rev))
2671 heads -= set(r.parentrevs(rev))
2666 heads.add(rev)
2672 heads.add(rev)
2667 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2673 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2668 "%11d %5d %8d\n" %
2674 "%11d %5d %8d\n" %
2669 (rev, p1, p2, r.start(rev), r.end(rev),
2675 (rev, p1, p2, r.start(rev), r.end(rev),
2670 r.start(dbase), r.start(cbase),
2676 r.start(dbase), r.start(cbase),
2671 r.start(p1), r.start(p2),
2677 r.start(p1), r.start(p2),
2672 rs, ts, ts / r.end(rev), len(heads), clen))
2678 rs, ts, ts / r.end(rev), len(heads), clen))
2673 return 0
2679 return 0
2674
2680
2675 v = r.version
2681 v = r.version
2676 format = v & 0xFFFF
2682 format = v & 0xFFFF
2677 flags = []
2683 flags = []
2678 gdelta = False
2684 gdelta = False
2679 if v & revlog.REVLOGNGINLINEDATA:
2685 if v & revlog.REVLOGNGINLINEDATA:
2680 flags.append('inline')
2686 flags.append('inline')
2681 if v & revlog.REVLOGGENERALDELTA:
2687 if v & revlog.REVLOGGENERALDELTA:
2682 gdelta = True
2688 gdelta = True
2683 flags.append('generaldelta')
2689 flags.append('generaldelta')
2684 if not flags:
2690 if not flags:
2685 flags = ['(none)']
2691 flags = ['(none)']
2686
2692
2687 nummerges = 0
2693 nummerges = 0
2688 numfull = 0
2694 numfull = 0
2689 numprev = 0
2695 numprev = 0
2690 nump1 = 0
2696 nump1 = 0
2691 nump2 = 0
2697 nump2 = 0
2692 numother = 0
2698 numother = 0
2693 nump1prev = 0
2699 nump1prev = 0
2694 nump2prev = 0
2700 nump2prev = 0
2695 chainlengths = []
2701 chainlengths = []
2696
2702
2697 datasize = [None, 0, 0L]
2703 datasize = [None, 0, 0L]
2698 fullsize = [None, 0, 0L]
2704 fullsize = [None, 0, 0L]
2699 deltasize = [None, 0, 0L]
2705 deltasize = [None, 0, 0L]
2700
2706
2701 def addsize(size, l):
2707 def addsize(size, l):
2702 if l[0] is None or size < l[0]:
2708 if l[0] is None or size < l[0]:
2703 l[0] = size
2709 l[0] = size
2704 if size > l[1]:
2710 if size > l[1]:
2705 l[1] = size
2711 l[1] = size
2706 l[2] += size
2712 l[2] += size
2707
2713
2708 numrevs = len(r)
2714 numrevs = len(r)
2709 for rev in xrange(numrevs):
2715 for rev in xrange(numrevs):
2710 p1, p2 = r.parentrevs(rev)
2716 p1, p2 = r.parentrevs(rev)
2711 delta = r.deltaparent(rev)
2717 delta = r.deltaparent(rev)
2712 if format > 0:
2718 if format > 0:
2713 addsize(r.rawsize(rev), datasize)
2719 addsize(r.rawsize(rev), datasize)
2714 if p2 != nullrev:
2720 if p2 != nullrev:
2715 nummerges += 1
2721 nummerges += 1
2716 size = r.length(rev)
2722 size = r.length(rev)
2717 if delta == nullrev:
2723 if delta == nullrev:
2718 chainlengths.append(0)
2724 chainlengths.append(0)
2719 numfull += 1
2725 numfull += 1
2720 addsize(size, fullsize)
2726 addsize(size, fullsize)
2721 else:
2727 else:
2722 chainlengths.append(chainlengths[delta] + 1)
2728 chainlengths.append(chainlengths[delta] + 1)
2723 addsize(size, deltasize)
2729 addsize(size, deltasize)
2724 if delta == rev - 1:
2730 if delta == rev - 1:
2725 numprev += 1
2731 numprev += 1
2726 if delta == p1:
2732 if delta == p1:
2727 nump1prev += 1
2733 nump1prev += 1
2728 elif delta == p2:
2734 elif delta == p2:
2729 nump2prev += 1
2735 nump2prev += 1
2730 elif delta == p1:
2736 elif delta == p1:
2731 nump1 += 1
2737 nump1 += 1
2732 elif delta == p2:
2738 elif delta == p2:
2733 nump2 += 1
2739 nump2 += 1
2734 elif delta != nullrev:
2740 elif delta != nullrev:
2735 numother += 1
2741 numother += 1
2736
2742
2737 # Adjust size min value for empty cases
2743 # Adjust size min value for empty cases
2738 for size in (datasize, fullsize, deltasize):
2744 for size in (datasize, fullsize, deltasize):
2739 if size[0] is None:
2745 if size[0] is None:
2740 size[0] = 0
2746 size[0] = 0
2741
2747
2742 numdeltas = numrevs - numfull
2748 numdeltas = numrevs - numfull
2743 numoprev = numprev - nump1prev - nump2prev
2749 numoprev = numprev - nump1prev - nump2prev
2744 totalrawsize = datasize[2]
2750 totalrawsize = datasize[2]
2745 datasize[2] /= numrevs
2751 datasize[2] /= numrevs
2746 fulltotal = fullsize[2]
2752 fulltotal = fullsize[2]
2747 fullsize[2] /= numfull
2753 fullsize[2] /= numfull
2748 deltatotal = deltasize[2]
2754 deltatotal = deltasize[2]
2749 if numrevs - numfull > 0:
2755 if numrevs - numfull > 0:
2750 deltasize[2] /= numrevs - numfull
2756 deltasize[2] /= numrevs - numfull
2751 totalsize = fulltotal + deltatotal
2757 totalsize = fulltotal + deltatotal
2752 avgchainlen = sum(chainlengths) / numrevs
2758 avgchainlen = sum(chainlengths) / numrevs
2753 compratio = totalrawsize / totalsize
2759 compratio = totalrawsize / totalsize
2754
2760
2755 basedfmtstr = '%%%dd\n'
2761 basedfmtstr = '%%%dd\n'
2756 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2762 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2757
2763
2758 def dfmtstr(max):
2764 def dfmtstr(max):
2759 return basedfmtstr % len(str(max))
2765 return basedfmtstr % len(str(max))
2760 def pcfmtstr(max, padding=0):
2766 def pcfmtstr(max, padding=0):
2761 return basepcfmtstr % (len(str(max)), ' ' * padding)
2767 return basepcfmtstr % (len(str(max)), ' ' * padding)
2762
2768
2763 def pcfmt(value, total):
2769 def pcfmt(value, total):
2764 return (value, 100 * float(value) / total)
2770 return (value, 100 * float(value) / total)
2765
2771
2766 ui.write(('format : %d\n') % format)
2772 ui.write(('format : %d\n') % format)
2767 ui.write(('flags : %s\n') % ', '.join(flags))
2773 ui.write(('flags : %s\n') % ', '.join(flags))
2768
2774
2769 ui.write('\n')
2775 ui.write('\n')
2770 fmt = pcfmtstr(totalsize)
2776 fmt = pcfmtstr(totalsize)
2771 fmt2 = dfmtstr(totalsize)
2777 fmt2 = dfmtstr(totalsize)
2772 ui.write(('revisions : ') + fmt2 % numrevs)
2778 ui.write(('revisions : ') + fmt2 % numrevs)
2773 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2779 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2774 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2780 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2775 ui.write(('revisions : ') + fmt2 % numrevs)
2781 ui.write(('revisions : ') + fmt2 % numrevs)
2776 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2782 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2777 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2783 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2778 ui.write(('revision size : ') + fmt2 % totalsize)
2784 ui.write(('revision size : ') + fmt2 % totalsize)
2779 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2785 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2780 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2786 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2781
2787
2782 ui.write('\n')
2788 ui.write('\n')
2783 fmt = dfmtstr(max(avgchainlen, compratio))
2789 fmt = dfmtstr(max(avgchainlen, compratio))
2784 ui.write(('avg chain length : ') + fmt % avgchainlen)
2790 ui.write(('avg chain length : ') + fmt % avgchainlen)
2785 ui.write(('compression ratio : ') + fmt % compratio)
2791 ui.write(('compression ratio : ') + fmt % compratio)
2786
2792
2787 if format > 0:
2793 if format > 0:
2788 ui.write('\n')
2794 ui.write('\n')
2789 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2795 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2790 % tuple(datasize))
2796 % tuple(datasize))
2791 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2797 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2792 % tuple(fullsize))
2798 % tuple(fullsize))
2793 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2799 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2794 % tuple(deltasize))
2800 % tuple(deltasize))
2795
2801
2796 if numdeltas > 0:
2802 if numdeltas > 0:
2797 ui.write('\n')
2803 ui.write('\n')
2798 fmt = pcfmtstr(numdeltas)
2804 fmt = pcfmtstr(numdeltas)
2799 fmt2 = pcfmtstr(numdeltas, 4)
2805 fmt2 = pcfmtstr(numdeltas, 4)
2800 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2806 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2801 if numprev > 0:
2807 if numprev > 0:
2802 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2808 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2803 numprev))
2809 numprev))
2804 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2810 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2805 numprev))
2811 numprev))
2806 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2812 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2807 numprev))
2813 numprev))
2808 if gdelta:
2814 if gdelta:
2809 ui.write(('deltas against p1 : ')
2815 ui.write(('deltas against p1 : ')
2810 + fmt % pcfmt(nump1, numdeltas))
2816 + fmt % pcfmt(nump1, numdeltas))
2811 ui.write(('deltas against p2 : ')
2817 ui.write(('deltas against p2 : ')
2812 + fmt % pcfmt(nump2, numdeltas))
2818 + fmt % pcfmt(nump2, numdeltas))
2813 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2819 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2814 numdeltas))
2820 numdeltas))
2815
2821
2816 @command('debugrevspec',
2822 @command('debugrevspec',
2817 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2823 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2818 ('REVSPEC'))
2824 ('REVSPEC'))
2819 def debugrevspec(ui, repo, expr, **opts):
2825 def debugrevspec(ui, repo, expr, **opts):
2820 """parse and apply a revision specification
2826 """parse and apply a revision specification
2821
2827
2822 Use --verbose to print the parsed tree before and after aliases
2828 Use --verbose to print the parsed tree before and after aliases
2823 expansion.
2829 expansion.
2824 """
2830 """
2825 if ui.verbose:
2831 if ui.verbose:
2826 tree = revset.parse(expr)[0]
2832 tree = revset.parse(expr)[0]
2827 ui.note(revset.prettyformat(tree), "\n")
2833 ui.note(revset.prettyformat(tree), "\n")
2828 newtree = revset.findaliases(ui, tree)
2834 newtree = revset.findaliases(ui, tree)
2829 if newtree != tree:
2835 if newtree != tree:
2830 ui.note(revset.prettyformat(newtree), "\n")
2836 ui.note(revset.prettyformat(newtree), "\n")
2831 if opts["optimize"]:
2837 if opts["optimize"]:
2832 weight, optimizedtree = revset.optimize(newtree, True)
2838 weight, optimizedtree = revset.optimize(newtree, True)
2833 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2839 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2834 func = revset.match(ui, expr)
2840 func = revset.match(ui, expr)
2835 for c in func(repo, revset.spanset(repo)):
2841 for c in func(repo, revset.spanset(repo)):
2836 ui.write("%s\n" % c)
2842 ui.write("%s\n" % c)
2837
2843
2838 @command('debugsetparents', [], _('REV1 [REV2]'))
2844 @command('debugsetparents', [], _('REV1 [REV2]'))
2839 def debugsetparents(ui, repo, rev1, rev2=None):
2845 def debugsetparents(ui, repo, rev1, rev2=None):
2840 """manually set the parents of the current working directory
2846 """manually set the parents of the current working directory
2841
2847
2842 This is useful for writing repository conversion tools, but should
2848 This is useful for writing repository conversion tools, but should
2843 be used with care.
2849 be used with care.
2844
2850
2845 Returns 0 on success.
2851 Returns 0 on success.
2846 """
2852 """
2847
2853
2848 r1 = scmutil.revsingle(repo, rev1).node()
2854 r1 = scmutil.revsingle(repo, rev1).node()
2849 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2855 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2850
2856
2851 wlock = repo.wlock()
2857 wlock = repo.wlock()
2852 try:
2858 try:
2853 repo.dirstate.beginparentchange()
2859 repo.dirstate.beginparentchange()
2854 repo.setparents(r1, r2)
2860 repo.setparents(r1, r2)
2855 repo.dirstate.endparentchange()
2861 repo.dirstate.endparentchange()
2856 finally:
2862 finally:
2857 wlock.release()
2863 wlock.release()
2858
2864
2859 @command('debugdirstate|debugstate',
2865 @command('debugdirstate|debugstate',
2860 [('', 'nodates', None, _('do not display the saved mtime')),
2866 [('', 'nodates', None, _('do not display the saved mtime')),
2861 ('', 'datesort', None, _('sort by saved mtime'))],
2867 ('', 'datesort', None, _('sort by saved mtime'))],
2862 _('[OPTION]...'))
2868 _('[OPTION]...'))
2863 def debugstate(ui, repo, nodates=None, datesort=None):
2869 def debugstate(ui, repo, nodates=None, datesort=None):
2864 """show the contents of the current dirstate"""
2870 """show the contents of the current dirstate"""
2865 timestr = ""
2871 timestr = ""
2866 showdate = not nodates
2872 showdate = not nodates
2867 if datesort:
2873 if datesort:
2868 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2874 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2869 else:
2875 else:
2870 keyfunc = None # sort by filename
2876 keyfunc = None # sort by filename
2871 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2877 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2872 if showdate:
2878 if showdate:
2873 if ent[3] == -1:
2879 if ent[3] == -1:
2874 # Pad or slice to locale representation
2880 # Pad or slice to locale representation
2875 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2881 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2876 time.localtime(0)))
2882 time.localtime(0)))
2877 timestr = 'unset'
2883 timestr = 'unset'
2878 timestr = (timestr[:locale_len] +
2884 timestr = (timestr[:locale_len] +
2879 ' ' * (locale_len - len(timestr)))
2885 ' ' * (locale_len - len(timestr)))
2880 else:
2886 else:
2881 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2887 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2882 time.localtime(ent[3]))
2888 time.localtime(ent[3]))
2883 if ent[1] & 020000:
2889 if ent[1] & 020000:
2884 mode = 'lnk'
2890 mode = 'lnk'
2885 else:
2891 else:
2886 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2892 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2887 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2893 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2888 for f in repo.dirstate.copies():
2894 for f in repo.dirstate.copies():
2889 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2895 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2890
2896
2891 @command('debugsub',
2897 @command('debugsub',
2892 [('r', 'rev', '',
2898 [('r', 'rev', '',
2893 _('revision to check'), _('REV'))],
2899 _('revision to check'), _('REV'))],
2894 _('[-r REV] [REV]'))
2900 _('[-r REV] [REV]'))
2895 def debugsub(ui, repo, rev=None):
2901 def debugsub(ui, repo, rev=None):
2896 ctx = scmutil.revsingle(repo, rev, None)
2902 ctx = scmutil.revsingle(repo, rev, None)
2897 for k, v in sorted(ctx.substate.items()):
2903 for k, v in sorted(ctx.substate.items()):
2898 ui.write(('path %s\n') % k)
2904 ui.write(('path %s\n') % k)
2899 ui.write((' source %s\n') % v[0])
2905 ui.write((' source %s\n') % v[0])
2900 ui.write((' revision %s\n') % v[1])
2906 ui.write((' revision %s\n') % v[1])
2901
2907
2902 @command('debugsuccessorssets',
2908 @command('debugsuccessorssets',
2903 [],
2909 [],
2904 _('[REV]'))
2910 _('[REV]'))
2905 def debugsuccessorssets(ui, repo, *revs):
2911 def debugsuccessorssets(ui, repo, *revs):
2906 """show set of successors for revision
2912 """show set of successors for revision
2907
2913
2908 A successors set of changeset A is a consistent group of revisions that
2914 A successors set of changeset A is a consistent group of revisions that
2909 succeed A. It contains non-obsolete changesets only.
2915 succeed A. It contains non-obsolete changesets only.
2910
2916
2911 In most cases a changeset A has a single successors set containing a single
2917 In most cases a changeset A has a single successors set containing a single
2912 successor (changeset A replaced by A').
2918 successor (changeset A replaced by A').
2913
2919
2914 A changeset that is made obsolete with no successors are called "pruned".
2920 A changeset that is made obsolete with no successors are called "pruned".
2915 Such changesets have no successors sets at all.
2921 Such changesets have no successors sets at all.
2916
2922
2917 A changeset that has been "split" will have a successors set containing
2923 A changeset that has been "split" will have a successors set containing
2918 more than one successor.
2924 more than one successor.
2919
2925
2920 A changeset that has been rewritten in multiple different ways is called
2926 A changeset that has been rewritten in multiple different ways is called
2921 "divergent". Such changesets have multiple successor sets (each of which
2927 "divergent". Such changesets have multiple successor sets (each of which
2922 may also be split, i.e. have multiple successors).
2928 may also be split, i.e. have multiple successors).
2923
2929
2924 Results are displayed as follows::
2930 Results are displayed as follows::
2925
2931
2926 <rev1>
2932 <rev1>
2927 <successors-1A>
2933 <successors-1A>
2928 <rev2>
2934 <rev2>
2929 <successors-2A>
2935 <successors-2A>
2930 <successors-2B1> <successors-2B2> <successors-2B3>
2936 <successors-2B1> <successors-2B2> <successors-2B3>
2931
2937
2932 Here rev2 has two possible (i.e. divergent) successors sets. The first
2938 Here rev2 has two possible (i.e. divergent) successors sets. The first
2933 holds one element, whereas the second holds three (i.e. the changeset has
2939 holds one element, whereas the second holds three (i.e. the changeset has
2934 been split).
2940 been split).
2935 """
2941 """
2936 # passed to successorssets caching computation from one call to another
2942 # passed to successorssets caching computation from one call to another
2937 cache = {}
2943 cache = {}
2938 ctx2str = str
2944 ctx2str = str
2939 node2str = short
2945 node2str = short
2940 if ui.debug():
2946 if ui.debug():
2941 def ctx2str(ctx):
2947 def ctx2str(ctx):
2942 return ctx.hex()
2948 return ctx.hex()
2943 node2str = hex
2949 node2str = hex
2944 for rev in scmutil.revrange(repo, revs):
2950 for rev in scmutil.revrange(repo, revs):
2945 ctx = repo[rev]
2951 ctx = repo[rev]
2946 ui.write('%s\n'% ctx2str(ctx))
2952 ui.write('%s\n'% ctx2str(ctx))
2947 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2953 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2948 if succsset:
2954 if succsset:
2949 ui.write(' ')
2955 ui.write(' ')
2950 ui.write(node2str(succsset[0]))
2956 ui.write(node2str(succsset[0]))
2951 for node in succsset[1:]:
2957 for node in succsset[1:]:
2952 ui.write(' ')
2958 ui.write(' ')
2953 ui.write(node2str(node))
2959 ui.write(node2str(node))
2954 ui.write('\n')
2960 ui.write('\n')
2955
2961
2956 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2962 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2957 def debugwalk(ui, repo, *pats, **opts):
2963 def debugwalk(ui, repo, *pats, **opts):
2958 """show how files match on given patterns"""
2964 """show how files match on given patterns"""
2959 m = scmutil.match(repo[None], pats, opts)
2965 m = scmutil.match(repo[None], pats, opts)
2960 items = list(repo.walk(m))
2966 items = list(repo.walk(m))
2961 if not items:
2967 if not items:
2962 return
2968 return
2963 f = lambda fn: fn
2969 f = lambda fn: fn
2964 if ui.configbool('ui', 'slash') and os.sep != '/':
2970 if ui.configbool('ui', 'slash') and os.sep != '/':
2965 f = lambda fn: util.normpath(fn)
2971 f = lambda fn: util.normpath(fn)
2966 fmt = 'f %%-%ds %%-%ds %%s' % (
2972 fmt = 'f %%-%ds %%-%ds %%s' % (
2967 max([len(abs) for abs in items]),
2973 max([len(abs) for abs in items]),
2968 max([len(m.rel(abs)) for abs in items]))
2974 max([len(m.rel(abs)) for abs in items]))
2969 for abs in items:
2975 for abs in items:
2970 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2976 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2971 ui.write("%s\n" % line.rstrip())
2977 ui.write("%s\n" % line.rstrip())
2972
2978
2973 @command('debugwireargs',
2979 @command('debugwireargs',
2974 [('', 'three', '', 'three'),
2980 [('', 'three', '', 'three'),
2975 ('', 'four', '', 'four'),
2981 ('', 'four', '', 'four'),
2976 ('', 'five', '', 'five'),
2982 ('', 'five', '', 'five'),
2977 ] + remoteopts,
2983 ] + remoteopts,
2978 _('REPO [OPTIONS]... [ONE [TWO]]'),
2984 _('REPO [OPTIONS]... [ONE [TWO]]'),
2979 norepo=True)
2985 norepo=True)
2980 def debugwireargs(ui, repopath, *vals, **opts):
2986 def debugwireargs(ui, repopath, *vals, **opts):
2981 repo = hg.peer(ui, opts, repopath)
2987 repo = hg.peer(ui, opts, repopath)
2982 for opt in remoteopts:
2988 for opt in remoteopts:
2983 del opts[opt[1]]
2989 del opts[opt[1]]
2984 args = {}
2990 args = {}
2985 for k, v in opts.iteritems():
2991 for k, v in opts.iteritems():
2986 if v:
2992 if v:
2987 args[k] = v
2993 args[k] = v
2988 # run twice to check that we don't mess up the stream for the next command
2994 # run twice to check that we don't mess up the stream for the next command
2989 res1 = repo.debugwireargs(*vals, **args)
2995 res1 = repo.debugwireargs(*vals, **args)
2990 res2 = repo.debugwireargs(*vals, **args)
2996 res2 = repo.debugwireargs(*vals, **args)
2991 ui.write("%s\n" % res1)
2997 ui.write("%s\n" % res1)
2992 if res1 != res2:
2998 if res1 != res2:
2993 ui.warn("%s\n" % res2)
2999 ui.warn("%s\n" % res2)
2994
3000
2995 @command('^diff',
3001 @command('^diff',
2996 [('r', 'rev', [], _('revision'), _('REV')),
3002 [('r', 'rev', [], _('revision'), _('REV')),
2997 ('c', 'change', '', _('change made by revision'), _('REV'))
3003 ('c', 'change', '', _('change made by revision'), _('REV'))
2998 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3004 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2999 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3005 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3000 inferrepo=True)
3006 inferrepo=True)
3001 def diff(ui, repo, *pats, **opts):
3007 def diff(ui, repo, *pats, **opts):
3002 """diff repository (or selected files)
3008 """diff repository (or selected files)
3003
3009
3004 Show differences between revisions for the specified files.
3010 Show differences between revisions for the specified files.
3005
3011
3006 Differences between files are shown using the unified diff format.
3012 Differences between files are shown using the unified diff format.
3007
3013
3008 .. note::
3014 .. note::
3009
3015
3010 diff may generate unexpected results for merges, as it will
3016 diff may generate unexpected results for merges, as it will
3011 default to comparing against the working directory's first
3017 default to comparing against the working directory's first
3012 parent changeset if no revisions are specified.
3018 parent changeset if no revisions are specified.
3013
3019
3014 When two revision arguments are given, then changes are shown
3020 When two revision arguments are given, then changes are shown
3015 between those revisions. If only one revision is specified then
3021 between those revisions. If only one revision is specified then
3016 that revision is compared to the working directory, and, when no
3022 that revision is compared to the working directory, and, when no
3017 revisions are specified, the working directory files are compared
3023 revisions are specified, the working directory files are compared
3018 to its parent.
3024 to its parent.
3019
3025
3020 Alternatively you can specify -c/--change with a revision to see
3026 Alternatively you can specify -c/--change with a revision to see
3021 the changes in that changeset relative to its first parent.
3027 the changes in that changeset relative to its first parent.
3022
3028
3023 Without the -a/--text option, diff will avoid generating diffs of
3029 Without the -a/--text option, diff will avoid generating diffs of
3024 files it detects as binary. With -a, diff will generate a diff
3030 files it detects as binary. With -a, diff will generate a diff
3025 anyway, probably with undesirable results.
3031 anyway, probably with undesirable results.
3026
3032
3027 Use the -g/--git option to generate diffs in the git extended diff
3033 Use the -g/--git option to generate diffs in the git extended diff
3028 format. For more information, read :hg:`help diffs`.
3034 format. For more information, read :hg:`help diffs`.
3029
3035
3030 .. container:: verbose
3036 .. container:: verbose
3031
3037
3032 Examples:
3038 Examples:
3033
3039
3034 - compare a file in the current working directory to its parent::
3040 - compare a file in the current working directory to its parent::
3035
3041
3036 hg diff foo.c
3042 hg diff foo.c
3037
3043
3038 - compare two historical versions of a directory, with rename info::
3044 - compare two historical versions of a directory, with rename info::
3039
3045
3040 hg diff --git -r 1.0:1.2 lib/
3046 hg diff --git -r 1.0:1.2 lib/
3041
3047
3042 - get change stats relative to the last change on some date::
3048 - get change stats relative to the last change on some date::
3043
3049
3044 hg diff --stat -r "date('may 2')"
3050 hg diff --stat -r "date('may 2')"
3045
3051
3046 - diff all newly-added files that contain a keyword::
3052 - diff all newly-added files that contain a keyword::
3047
3053
3048 hg diff "set:added() and grep(GNU)"
3054 hg diff "set:added() and grep(GNU)"
3049
3055
3050 - compare a revision and its parents::
3056 - compare a revision and its parents::
3051
3057
3052 hg diff -c 9353 # compare against first parent
3058 hg diff -c 9353 # compare against first parent
3053 hg diff -r 9353^:9353 # same using revset syntax
3059 hg diff -r 9353^:9353 # same using revset syntax
3054 hg diff -r 9353^2:9353 # compare against the second parent
3060 hg diff -r 9353^2:9353 # compare against the second parent
3055
3061
3056 Returns 0 on success.
3062 Returns 0 on success.
3057 """
3063 """
3058
3064
3059 revs = opts.get('rev')
3065 revs = opts.get('rev')
3060 change = opts.get('change')
3066 change = opts.get('change')
3061 stat = opts.get('stat')
3067 stat = opts.get('stat')
3062 reverse = opts.get('reverse')
3068 reverse = opts.get('reverse')
3063
3069
3064 if revs and change:
3070 if revs and change:
3065 msg = _('cannot specify --rev and --change at the same time')
3071 msg = _('cannot specify --rev and --change at the same time')
3066 raise util.Abort(msg)
3072 raise util.Abort(msg)
3067 elif change:
3073 elif change:
3068 node2 = scmutil.revsingle(repo, change, None).node()
3074 node2 = scmutil.revsingle(repo, change, None).node()
3069 node1 = repo[node2].p1().node()
3075 node1 = repo[node2].p1().node()
3070 else:
3076 else:
3071 node1, node2 = scmutil.revpair(repo, revs)
3077 node1, node2 = scmutil.revpair(repo, revs)
3072
3078
3073 if reverse:
3079 if reverse:
3074 node1, node2 = node2, node1
3080 node1, node2 = node2, node1
3075
3081
3076 diffopts = patch.diffopts(ui, opts)
3082 diffopts = patch.diffopts(ui, opts)
3077 m = scmutil.match(repo[node2], pats, opts)
3083 m = scmutil.match(repo[node2], pats, opts)
3078 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3084 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3079 listsubrepos=opts.get('subrepos'))
3085 listsubrepos=opts.get('subrepos'))
3080
3086
3081 @command('^export',
3087 @command('^export',
3082 [('o', 'output', '',
3088 [('o', 'output', '',
3083 _('print output to file with formatted name'), _('FORMAT')),
3089 _('print output to file with formatted name'), _('FORMAT')),
3084 ('', 'switch-parent', None, _('diff against the second parent')),
3090 ('', 'switch-parent', None, _('diff against the second parent')),
3085 ('r', 'rev', [], _('revisions to export'), _('REV')),
3091 ('r', 'rev', [], _('revisions to export'), _('REV')),
3086 ] + diffopts,
3092 ] + diffopts,
3087 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3093 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3088 def export(ui, repo, *changesets, **opts):
3094 def export(ui, repo, *changesets, **opts):
3089 """dump the header and diffs for one or more changesets
3095 """dump the header and diffs for one or more changesets
3090
3096
3091 Print the changeset header and diffs for one or more revisions.
3097 Print the changeset header and diffs for one or more revisions.
3092 If no revision is given, the parent of the working directory is used.
3098 If no revision is given, the parent of the working directory is used.
3093
3099
3094 The information shown in the changeset header is: author, date,
3100 The information shown in the changeset header is: author, date,
3095 branch name (if non-default), changeset hash, parent(s) and commit
3101 branch name (if non-default), changeset hash, parent(s) and commit
3096 comment.
3102 comment.
3097
3103
3098 .. note::
3104 .. note::
3099
3105
3100 export may generate unexpected diff output for merge
3106 export may generate unexpected diff output for merge
3101 changesets, as it will compare the merge changeset against its
3107 changesets, as it will compare the merge changeset against its
3102 first parent only.
3108 first parent only.
3103
3109
3104 Output may be to a file, in which case the name of the file is
3110 Output may be to a file, in which case the name of the file is
3105 given using a format string. The formatting rules are as follows:
3111 given using a format string. The formatting rules are as follows:
3106
3112
3107 :``%%``: literal "%" character
3113 :``%%``: literal "%" character
3108 :``%H``: changeset hash (40 hexadecimal digits)
3114 :``%H``: changeset hash (40 hexadecimal digits)
3109 :``%N``: number of patches being generated
3115 :``%N``: number of patches being generated
3110 :``%R``: changeset revision number
3116 :``%R``: changeset revision number
3111 :``%b``: basename of the exporting repository
3117 :``%b``: basename of the exporting repository
3112 :``%h``: short-form changeset hash (12 hexadecimal digits)
3118 :``%h``: short-form changeset hash (12 hexadecimal digits)
3113 :``%m``: first line of the commit message (only alphanumeric characters)
3119 :``%m``: first line of the commit message (only alphanumeric characters)
3114 :``%n``: zero-padded sequence number, starting at 1
3120 :``%n``: zero-padded sequence number, starting at 1
3115 :``%r``: zero-padded changeset revision number
3121 :``%r``: zero-padded changeset revision number
3116
3122
3117 Without the -a/--text option, export will avoid generating diffs
3123 Without the -a/--text option, export will avoid generating diffs
3118 of files it detects as binary. With -a, export will generate a
3124 of files it detects as binary. With -a, export will generate a
3119 diff anyway, probably with undesirable results.
3125 diff anyway, probably with undesirable results.
3120
3126
3121 Use the -g/--git option to generate diffs in the git extended diff
3127 Use the -g/--git option to generate diffs in the git extended diff
3122 format. See :hg:`help diffs` for more information.
3128 format. See :hg:`help diffs` for more information.
3123
3129
3124 With the --switch-parent option, the diff will be against the
3130 With the --switch-parent option, the diff will be against the
3125 second parent. It can be useful to review a merge.
3131 second parent. It can be useful to review a merge.
3126
3132
3127 .. container:: verbose
3133 .. container:: verbose
3128
3134
3129 Examples:
3135 Examples:
3130
3136
3131 - use export and import to transplant a bugfix to the current
3137 - use export and import to transplant a bugfix to the current
3132 branch::
3138 branch::
3133
3139
3134 hg export -r 9353 | hg import -
3140 hg export -r 9353 | hg import -
3135
3141
3136 - export all the changesets between two revisions to a file with
3142 - export all the changesets between two revisions to a file with
3137 rename information::
3143 rename information::
3138
3144
3139 hg export --git -r 123:150 > changes.txt
3145 hg export --git -r 123:150 > changes.txt
3140
3146
3141 - split outgoing changes into a series of patches with
3147 - split outgoing changes into a series of patches with
3142 descriptive names::
3148 descriptive names::
3143
3149
3144 hg export -r "outgoing()" -o "%n-%m.patch"
3150 hg export -r "outgoing()" -o "%n-%m.patch"
3145
3151
3146 Returns 0 on success.
3152 Returns 0 on success.
3147 """
3153 """
3148 changesets += tuple(opts.get('rev', []))
3154 changesets += tuple(opts.get('rev', []))
3149 if not changesets:
3155 if not changesets:
3150 changesets = ['.']
3156 changesets = ['.']
3151 revs = scmutil.revrange(repo, changesets)
3157 revs = scmutil.revrange(repo, changesets)
3152 if not revs:
3158 if not revs:
3153 raise util.Abort(_("export requires at least one changeset"))
3159 raise util.Abort(_("export requires at least one changeset"))
3154 if len(revs) > 1:
3160 if len(revs) > 1:
3155 ui.note(_('exporting patches:\n'))
3161 ui.note(_('exporting patches:\n'))
3156 else:
3162 else:
3157 ui.note(_('exporting patch:\n'))
3163 ui.note(_('exporting patch:\n'))
3158 cmdutil.export(repo, revs, template=opts.get('output'),
3164 cmdutil.export(repo, revs, template=opts.get('output'),
3159 switch_parent=opts.get('switch_parent'),
3165 switch_parent=opts.get('switch_parent'),
3160 opts=patch.diffopts(ui, opts))
3166 opts=patch.diffopts(ui, opts))
3161
3167
3162 @command('files',
3168 @command('files',
3163 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3169 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3164 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3170 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3165 ] + walkopts + formatteropts,
3171 ] + walkopts + formatteropts,
3166 _('[OPTION]... [PATTERN]...'))
3172 _('[OPTION]... [PATTERN]...'))
3167 def files(ui, repo, *pats, **opts):
3173 def files(ui, repo, *pats, **opts):
3168 """list tracked files
3174 """list tracked files
3169
3175
3170 Print files under Mercurial control in the working directory or
3176 Print files under Mercurial control in the working directory or
3171 specified revision whose names match the given patterns (excluding
3177 specified revision whose names match the given patterns (excluding
3172 removed files).
3178 removed files).
3173
3179
3174 If no patterns are given to match, this command prints the names
3180 If no patterns are given to match, this command prints the names
3175 of all files under Mercurial control in the working copy.
3181 of all files under Mercurial control in the working copy.
3176
3182
3177 .. container:: verbose
3183 .. container:: verbose
3178
3184
3179 Examples:
3185 Examples:
3180
3186
3181 - list all files under the current directory::
3187 - list all files under the current directory::
3182
3188
3183 hg files .
3189 hg files .
3184
3190
3185 - shows sizes and flags for current revision::
3191 - shows sizes and flags for current revision::
3186
3192
3187 hg files -vr .
3193 hg files -vr .
3188
3194
3189 - list all files named README::
3195 - list all files named README::
3190
3196
3191 hg files -I "**/README"
3197 hg files -I "**/README"
3192
3198
3193 - list all binary files::
3199 - list all binary files::
3194
3200
3195 hg files "set:binary()"
3201 hg files "set:binary()"
3196
3202
3197 - find files containing a regular expression:
3203 - find files containing a regular expression:
3198
3204
3199 hg files "set:grep('bob')"
3205 hg files "set:grep('bob')"
3200
3206
3201 - search tracked file contents with xargs and grep::
3207 - search tracked file contents with xargs and grep::
3202
3208
3203 hg files -0 | xargs -0 grep foo
3209 hg files -0 | xargs -0 grep foo
3204
3210
3205 See :hg:'help pattern' and :hg:'help revsets' for more information
3211 See :hg:'help pattern' and :hg:'help revsets' for more information
3206 on specifying file patterns.
3212 on specifying file patterns.
3207
3213
3208 Returns 0 if a match is found, 1 otherwise.
3214 Returns 0 if a match is found, 1 otherwise.
3209
3215
3210 """
3216 """
3211 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3217 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3212 rev = ctx.rev()
3218 rev = ctx.rev()
3213 ret = 1
3219 ret = 1
3214
3220
3215 end = '\n'
3221 end = '\n'
3216 if opts.get('print0'):
3222 if opts.get('print0'):
3217 end = '\0'
3223 end = '\0'
3218 fm = ui.formatter('files', opts)
3224 fm = ui.formatter('files', opts)
3219 fmt = '%s' + end
3225 fmt = '%s' + end
3220
3226
3221 m = scmutil.match(ctx, pats, opts)
3227 m = scmutil.match(ctx, pats, opts)
3222 ds = repo.dirstate
3228 ds = repo.dirstate
3223 for f in ctx.matches(m):
3229 for f in ctx.matches(m):
3224 if rev is None and ds[f] == 'r':
3230 if rev is None and ds[f] == 'r':
3225 continue
3231 continue
3226 fm.startitem()
3232 fm.startitem()
3227 if ui.verbose:
3233 if ui.verbose:
3228 fc = ctx[f]
3234 fc = ctx[f]
3229 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3235 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3230 fm.data(abspath=f)
3236 fm.data(abspath=f)
3231 fm.write('path', fmt, m.rel(f))
3237 fm.write('path', fmt, m.rel(f))
3232 ret = 0
3238 ret = 0
3233
3239
3234 fm.end()
3240 fm.end()
3235
3241
3236 return ret
3242 return ret
3237
3243
3238 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3244 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3239 def forget(ui, repo, *pats, **opts):
3245 def forget(ui, repo, *pats, **opts):
3240 """forget the specified files on the next commit
3246 """forget the specified files on the next commit
3241
3247
3242 Mark the specified files so they will no longer be tracked
3248 Mark the specified files so they will no longer be tracked
3243 after the next commit.
3249 after the next commit.
3244
3250
3245 This only removes files from the current branch, not from the
3251 This only removes files from the current branch, not from the
3246 entire project history, and it does not delete them from the
3252 entire project history, and it does not delete them from the
3247 working directory.
3253 working directory.
3248
3254
3249 To undo a forget before the next commit, see :hg:`add`.
3255 To undo a forget before the next commit, see :hg:`add`.
3250
3256
3251 .. container:: verbose
3257 .. container:: verbose
3252
3258
3253 Examples:
3259 Examples:
3254
3260
3255 - forget newly-added binary files::
3261 - forget newly-added binary files::
3256
3262
3257 hg forget "set:added() and binary()"
3263 hg forget "set:added() and binary()"
3258
3264
3259 - forget files that would be excluded by .hgignore::
3265 - forget files that would be excluded by .hgignore::
3260
3266
3261 hg forget "set:hgignore()"
3267 hg forget "set:hgignore()"
3262
3268
3263 Returns 0 on success.
3269 Returns 0 on success.
3264 """
3270 """
3265
3271
3266 if not pats:
3272 if not pats:
3267 raise util.Abort(_('no files specified'))
3273 raise util.Abort(_('no files specified'))
3268
3274
3269 m = scmutil.match(repo[None], pats, opts)
3275 m = scmutil.match(repo[None], pats, opts)
3270 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3276 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3271 return rejected and 1 or 0
3277 return rejected and 1 or 0
3272
3278
3273 @command(
3279 @command(
3274 'graft',
3280 'graft',
3275 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3281 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3276 ('c', 'continue', False, _('resume interrupted graft')),
3282 ('c', 'continue', False, _('resume interrupted graft')),
3277 ('e', 'edit', False, _('invoke editor on commit messages')),
3283 ('e', 'edit', False, _('invoke editor on commit messages')),
3278 ('', 'log', None, _('append graft info to log message')),
3284 ('', 'log', None, _('append graft info to log message')),
3279 ('f', 'force', False, _('force graft')),
3285 ('f', 'force', False, _('force graft')),
3280 ('D', 'currentdate', False,
3286 ('D', 'currentdate', False,
3281 _('record the current date as commit date')),
3287 _('record the current date as commit date')),
3282 ('U', 'currentuser', False,
3288 ('U', 'currentuser', False,
3283 _('record the current user as committer'), _('DATE'))]
3289 _('record the current user as committer'), _('DATE'))]
3284 + commitopts2 + mergetoolopts + dryrunopts,
3290 + commitopts2 + mergetoolopts + dryrunopts,
3285 _('[OPTION]... [-r] REV...'))
3291 _('[OPTION]... [-r] REV...'))
3286 def graft(ui, repo, *revs, **opts):
3292 def graft(ui, repo, *revs, **opts):
3287 '''copy changes from other branches onto the current branch
3293 '''copy changes from other branches onto the current branch
3288
3294
3289 This command uses Mercurial's merge logic to copy individual
3295 This command uses Mercurial's merge logic to copy individual
3290 changes from other branches without merging branches in the
3296 changes from other branches without merging branches in the
3291 history graph. This is sometimes known as 'backporting' or
3297 history graph. This is sometimes known as 'backporting' or
3292 'cherry-picking'. By default, graft will copy user, date, and
3298 'cherry-picking'. By default, graft will copy user, date, and
3293 description from the source changesets.
3299 description from the source changesets.
3294
3300
3295 Changesets that are ancestors of the current revision, that have
3301 Changesets that are ancestors of the current revision, that have
3296 already been grafted, or that are merges will be skipped.
3302 already been grafted, or that are merges will be skipped.
3297
3303
3298 If --log is specified, log messages will have a comment appended
3304 If --log is specified, log messages will have a comment appended
3299 of the form::
3305 of the form::
3300
3306
3301 (grafted from CHANGESETHASH)
3307 (grafted from CHANGESETHASH)
3302
3308
3303 If --force is specified, revisions will be grafted even if they
3309 If --force is specified, revisions will be grafted even if they
3304 are already ancestors of or have been grafted to the destination.
3310 are already ancestors of or have been grafted to the destination.
3305 This is useful when the revisions have since been backed out.
3311 This is useful when the revisions have since been backed out.
3306
3312
3307 If a graft merge results in conflicts, the graft process is
3313 If a graft merge results in conflicts, the graft process is
3308 interrupted so that the current merge can be manually resolved.
3314 interrupted so that the current merge can be manually resolved.
3309 Once all conflicts are addressed, the graft process can be
3315 Once all conflicts are addressed, the graft process can be
3310 continued with the -c/--continue option.
3316 continued with the -c/--continue option.
3311
3317
3312 .. note::
3318 .. note::
3313
3319
3314 The -c/--continue option does not reapply earlier options, except
3320 The -c/--continue option does not reapply earlier options, except
3315 for --force.
3321 for --force.
3316
3322
3317 .. container:: verbose
3323 .. container:: verbose
3318
3324
3319 Examples:
3325 Examples:
3320
3326
3321 - copy a single change to the stable branch and edit its description::
3327 - copy a single change to the stable branch and edit its description::
3322
3328
3323 hg update stable
3329 hg update stable
3324 hg graft --edit 9393
3330 hg graft --edit 9393
3325
3331
3326 - graft a range of changesets with one exception, updating dates::
3332 - graft a range of changesets with one exception, updating dates::
3327
3333
3328 hg graft -D "2085::2093 and not 2091"
3334 hg graft -D "2085::2093 and not 2091"
3329
3335
3330 - continue a graft after resolving conflicts::
3336 - continue a graft after resolving conflicts::
3331
3337
3332 hg graft -c
3338 hg graft -c
3333
3339
3334 - show the source of a grafted changeset::
3340 - show the source of a grafted changeset::
3335
3341
3336 hg log --debug -r .
3342 hg log --debug -r .
3337
3343
3338 See :hg:`help revisions` and :hg:`help revsets` for more about
3344 See :hg:`help revisions` and :hg:`help revsets` for more about
3339 specifying revisions.
3345 specifying revisions.
3340
3346
3341 Returns 0 on successful completion.
3347 Returns 0 on successful completion.
3342 '''
3348 '''
3343
3349
3344 revs = list(revs)
3350 revs = list(revs)
3345 revs.extend(opts['rev'])
3351 revs.extend(opts['rev'])
3346
3352
3347 if not opts.get('user') and opts.get('currentuser'):
3353 if not opts.get('user') and opts.get('currentuser'):
3348 opts['user'] = ui.username()
3354 opts['user'] = ui.username()
3349 if not opts.get('date') and opts.get('currentdate'):
3355 if not opts.get('date') and opts.get('currentdate'):
3350 opts['date'] = "%d %d" % util.makedate()
3356 opts['date'] = "%d %d" % util.makedate()
3351
3357
3352 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3358 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3353
3359
3354 cont = False
3360 cont = False
3355 if opts['continue']:
3361 if opts['continue']:
3356 cont = True
3362 cont = True
3357 if revs:
3363 if revs:
3358 raise util.Abort(_("can't specify --continue and revisions"))
3364 raise util.Abort(_("can't specify --continue and revisions"))
3359 # read in unfinished revisions
3365 # read in unfinished revisions
3360 try:
3366 try:
3361 nodes = repo.opener.read('graftstate').splitlines()
3367 nodes = repo.opener.read('graftstate').splitlines()
3362 revs = [repo[node].rev() for node in nodes]
3368 revs = [repo[node].rev() for node in nodes]
3363 except IOError, inst:
3369 except IOError, inst:
3364 if inst.errno != errno.ENOENT:
3370 if inst.errno != errno.ENOENT:
3365 raise
3371 raise
3366 raise util.Abort(_("no graft state found, can't continue"))
3372 raise util.Abort(_("no graft state found, can't continue"))
3367 else:
3373 else:
3368 cmdutil.checkunfinished(repo)
3374 cmdutil.checkunfinished(repo)
3369 cmdutil.bailifchanged(repo)
3375 cmdutil.bailifchanged(repo)
3370 if not revs:
3376 if not revs:
3371 raise util.Abort(_('no revisions specified'))
3377 raise util.Abort(_('no revisions specified'))
3372 revs = scmutil.revrange(repo, revs)
3378 revs = scmutil.revrange(repo, revs)
3373
3379
3374 # check for merges
3380 # check for merges
3375 for rev in repo.revs('%ld and merge()', revs):
3381 for rev in repo.revs('%ld and merge()', revs):
3376 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3382 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3377 revs.remove(rev)
3383 revs.remove(rev)
3378 if not revs:
3384 if not revs:
3379 return -1
3385 return -1
3380
3386
3381 # Don't check in the --continue case, in effect retaining --force across
3387 # Don't check in the --continue case, in effect retaining --force across
3382 # --continues. That's because without --force, any revisions we decided to
3388 # --continues. That's because without --force, any revisions we decided to
3383 # skip would have been filtered out here, so they wouldn't have made their
3389 # skip would have been filtered out here, so they wouldn't have made their
3384 # way to the graftstate. With --force, any revisions we would have otherwise
3390 # way to the graftstate. With --force, any revisions we would have otherwise
3385 # skipped would not have been filtered out, and if they hadn't been applied
3391 # skipped would not have been filtered out, and if they hadn't been applied
3386 # already, they'd have been in the graftstate.
3392 # already, they'd have been in the graftstate.
3387 if not (cont or opts.get('force')):
3393 if not (cont or opts.get('force')):
3388 # check for ancestors of dest branch
3394 # check for ancestors of dest branch
3389 crev = repo['.'].rev()
3395 crev = repo['.'].rev()
3390 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3396 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3391 # Cannot use x.remove(y) on smart set, this has to be a list.
3397 # Cannot use x.remove(y) on smart set, this has to be a list.
3392 # XXX make this lazy in the future
3398 # XXX make this lazy in the future
3393 revs = list(revs)
3399 revs = list(revs)
3394 # don't mutate while iterating, create a copy
3400 # don't mutate while iterating, create a copy
3395 for rev in list(revs):
3401 for rev in list(revs):
3396 if rev in ancestors:
3402 if rev in ancestors:
3397 ui.warn(_('skipping ancestor revision %s\n') % rev)
3403 ui.warn(_('skipping ancestor revision %s\n') % rev)
3398 # XXX remove on list is slow
3404 # XXX remove on list is slow
3399 revs.remove(rev)
3405 revs.remove(rev)
3400 if not revs:
3406 if not revs:
3401 return -1
3407 return -1
3402
3408
3403 # analyze revs for earlier grafts
3409 # analyze revs for earlier grafts
3404 ids = {}
3410 ids = {}
3405 for ctx in repo.set("%ld", revs):
3411 for ctx in repo.set("%ld", revs):
3406 ids[ctx.hex()] = ctx.rev()
3412 ids[ctx.hex()] = ctx.rev()
3407 n = ctx.extra().get('source')
3413 n = ctx.extra().get('source')
3408 if n:
3414 if n:
3409 ids[n] = ctx.rev()
3415 ids[n] = ctx.rev()
3410
3416
3411 # check ancestors for earlier grafts
3417 # check ancestors for earlier grafts
3412 ui.debug('scanning for duplicate grafts\n')
3418 ui.debug('scanning for duplicate grafts\n')
3413
3419
3414 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3420 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3415 ctx = repo[rev]
3421 ctx = repo[rev]
3416 n = ctx.extra().get('source')
3422 n = ctx.extra().get('source')
3417 if n in ids:
3423 if n in ids:
3418 try:
3424 try:
3419 r = repo[n].rev()
3425 r = repo[n].rev()
3420 except error.RepoLookupError:
3426 except error.RepoLookupError:
3421 r = None
3427 r = None
3422 if r in revs:
3428 if r in revs:
3423 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3429 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3424 % (r, rev))
3430 % (r, rev))
3425 revs.remove(r)
3431 revs.remove(r)
3426 elif ids[n] in revs:
3432 elif ids[n] in revs:
3427 if r is None:
3433 if r is None:
3428 ui.warn(_('skipping already grafted revision %s '
3434 ui.warn(_('skipping already grafted revision %s '
3429 '(%s also has unknown origin %s)\n')
3435 '(%s also has unknown origin %s)\n')
3430 % (ids[n], rev, n))
3436 % (ids[n], rev, n))
3431 else:
3437 else:
3432 ui.warn(_('skipping already grafted revision %s '
3438 ui.warn(_('skipping already grafted revision %s '
3433 '(%s also has origin %d)\n')
3439 '(%s also has origin %d)\n')
3434 % (ids[n], rev, r))
3440 % (ids[n], rev, r))
3435 revs.remove(ids[n])
3441 revs.remove(ids[n])
3436 elif ctx.hex() in ids:
3442 elif ctx.hex() in ids:
3437 r = ids[ctx.hex()]
3443 r = ids[ctx.hex()]
3438 ui.warn(_('skipping already grafted revision %s '
3444 ui.warn(_('skipping already grafted revision %s '
3439 '(was grafted from %d)\n') % (r, rev))
3445 '(was grafted from %d)\n') % (r, rev))
3440 revs.remove(r)
3446 revs.remove(r)
3441 if not revs:
3447 if not revs:
3442 return -1
3448 return -1
3443
3449
3444 wlock = repo.wlock()
3450 wlock = repo.wlock()
3445 try:
3451 try:
3446 current = repo['.']
3452 current = repo['.']
3447 for pos, ctx in enumerate(repo.set("%ld", revs)):
3453 for pos, ctx in enumerate(repo.set("%ld", revs)):
3448
3454
3449 ui.status(_('grafting revision %s\n') % ctx.rev())
3455 ui.status(_('grafting revision %s\n') % ctx.rev())
3450 if opts.get('dry_run'):
3456 if opts.get('dry_run'):
3451 continue
3457 continue
3452
3458
3453 source = ctx.extra().get('source')
3459 source = ctx.extra().get('source')
3454 if not source:
3460 if not source:
3455 source = ctx.hex()
3461 source = ctx.hex()
3456 extra = {'source': source}
3462 extra = {'source': source}
3457 user = ctx.user()
3463 user = ctx.user()
3458 if opts.get('user'):
3464 if opts.get('user'):
3459 user = opts['user']
3465 user = opts['user']
3460 date = ctx.date()
3466 date = ctx.date()
3461 if opts.get('date'):
3467 if opts.get('date'):
3462 date = opts['date']
3468 date = opts['date']
3463 message = ctx.description()
3469 message = ctx.description()
3464 if opts.get('log'):
3470 if opts.get('log'):
3465 message += '\n(grafted from %s)' % ctx.hex()
3471 message += '\n(grafted from %s)' % ctx.hex()
3466
3472
3467 # we don't merge the first commit when continuing
3473 # we don't merge the first commit when continuing
3468 if not cont:
3474 if not cont:
3469 # perform the graft merge with p1(rev) as 'ancestor'
3475 # perform the graft merge with p1(rev) as 'ancestor'
3470 try:
3476 try:
3471 # ui.forcemerge is an internal variable, do not document
3477 # ui.forcemerge is an internal variable, do not document
3472 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3478 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3473 'graft')
3479 'graft')
3474 stats = mergemod.update(repo, ctx.node(), True, True, False,
3480 stats = mergemod.update(repo, ctx.node(), True, True, False,
3475 ctx.p1().node(),
3481 ctx.p1().node(),
3476 labels=['local', 'graft'])
3482 labels=['local', 'graft'])
3477 finally:
3483 finally:
3478 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3484 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3479 # report any conflicts
3485 # report any conflicts
3480 if stats and stats[3] > 0:
3486 if stats and stats[3] > 0:
3481 # write out state for --continue
3487 # write out state for --continue
3482 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3488 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3483 repo.opener.write('graftstate', ''.join(nodelines))
3489 repo.opener.write('graftstate', ''.join(nodelines))
3484 raise util.Abort(
3490 raise util.Abort(
3485 _("unresolved conflicts, can't continue"),
3491 _("unresolved conflicts, can't continue"),
3486 hint=_('use hg resolve and hg graft --continue'))
3492 hint=_('use hg resolve and hg graft --continue'))
3487 else:
3493 else:
3488 cont = False
3494 cont = False
3489
3495
3490 # drop the second merge parent
3496 # drop the second merge parent
3491 repo.dirstate.beginparentchange()
3497 repo.dirstate.beginparentchange()
3492 repo.setparents(current.node(), nullid)
3498 repo.setparents(current.node(), nullid)
3493 repo.dirstate.write()
3499 repo.dirstate.write()
3494 # fix up dirstate for copies and renames
3500 # fix up dirstate for copies and renames
3495 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3501 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3496 repo.dirstate.endparentchange()
3502 repo.dirstate.endparentchange()
3497
3503
3498 # commit
3504 # commit
3499 node = repo.commit(text=message, user=user,
3505 node = repo.commit(text=message, user=user,
3500 date=date, extra=extra, editor=editor)
3506 date=date, extra=extra, editor=editor)
3501 if node is None:
3507 if node is None:
3502 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3508 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3503 else:
3509 else:
3504 current = repo[node]
3510 current = repo[node]
3505 finally:
3511 finally:
3506 wlock.release()
3512 wlock.release()
3507
3513
3508 # remove state when we complete successfully
3514 # remove state when we complete successfully
3509 if not opts.get('dry_run'):
3515 if not opts.get('dry_run'):
3510 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3516 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3511
3517
3512 return 0
3518 return 0
3513
3519
3514 @command('grep',
3520 @command('grep',
3515 [('0', 'print0', None, _('end fields with NUL')),
3521 [('0', 'print0', None, _('end fields with NUL')),
3516 ('', 'all', None, _('print all revisions that match')),
3522 ('', 'all', None, _('print all revisions that match')),
3517 ('a', 'text', None, _('treat all files as text')),
3523 ('a', 'text', None, _('treat all files as text')),
3518 ('f', 'follow', None,
3524 ('f', 'follow', None,
3519 _('follow changeset history,'
3525 _('follow changeset history,'
3520 ' or file history across copies and renames')),
3526 ' or file history across copies and renames')),
3521 ('i', 'ignore-case', None, _('ignore case when matching')),
3527 ('i', 'ignore-case', None, _('ignore case when matching')),
3522 ('l', 'files-with-matches', None,
3528 ('l', 'files-with-matches', None,
3523 _('print only filenames and revisions that match')),
3529 _('print only filenames and revisions that match')),
3524 ('n', 'line-number', None, _('print matching line numbers')),
3530 ('n', 'line-number', None, _('print matching line numbers')),
3525 ('r', 'rev', [],
3531 ('r', 'rev', [],
3526 _('only search files changed within revision range'), _('REV')),
3532 _('only search files changed within revision range'), _('REV')),
3527 ('u', 'user', None, _('list the author (long with -v)')),
3533 ('u', 'user', None, _('list the author (long with -v)')),
3528 ('d', 'date', None, _('list the date (short with -q)')),
3534 ('d', 'date', None, _('list the date (short with -q)')),
3529 ] + walkopts,
3535 ] + walkopts,
3530 _('[OPTION]... PATTERN [FILE]...'),
3536 _('[OPTION]... PATTERN [FILE]...'),
3531 inferrepo=True)
3537 inferrepo=True)
3532 def grep(ui, repo, pattern, *pats, **opts):
3538 def grep(ui, repo, pattern, *pats, **opts):
3533 """search for a pattern in specified files and revisions
3539 """search for a pattern in specified files and revisions
3534
3540
3535 Search revisions of files for a regular expression.
3541 Search revisions of files for a regular expression.
3536
3542
3537 This command behaves differently than Unix grep. It only accepts
3543 This command behaves differently than Unix grep. It only accepts
3538 Python/Perl regexps. It searches repository history, not the
3544 Python/Perl regexps. It searches repository history, not the
3539 working directory. It always prints the revision number in which a
3545 working directory. It always prints the revision number in which a
3540 match appears.
3546 match appears.
3541
3547
3542 By default, grep only prints output for the first revision of a
3548 By default, grep only prints output for the first revision of a
3543 file in which it finds a match. To get it to print every revision
3549 file in which it finds a match. To get it to print every revision
3544 that contains a change in match status ("-" for a match that
3550 that contains a change in match status ("-" for a match that
3545 becomes a non-match, or "+" for a non-match that becomes a match),
3551 becomes a non-match, or "+" for a non-match that becomes a match),
3546 use the --all flag.
3552 use the --all flag.
3547
3553
3548 Returns 0 if a match is found, 1 otherwise.
3554 Returns 0 if a match is found, 1 otherwise.
3549 """
3555 """
3550 reflags = re.M
3556 reflags = re.M
3551 if opts.get('ignore_case'):
3557 if opts.get('ignore_case'):
3552 reflags |= re.I
3558 reflags |= re.I
3553 try:
3559 try:
3554 regexp = util.re.compile(pattern, reflags)
3560 regexp = util.re.compile(pattern, reflags)
3555 except re.error, inst:
3561 except re.error, inst:
3556 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3562 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3557 return 1
3563 return 1
3558 sep, eol = ':', '\n'
3564 sep, eol = ':', '\n'
3559 if opts.get('print0'):
3565 if opts.get('print0'):
3560 sep = eol = '\0'
3566 sep = eol = '\0'
3561
3567
3562 getfile = util.lrucachefunc(repo.file)
3568 getfile = util.lrucachefunc(repo.file)
3563
3569
3564 def matchlines(body):
3570 def matchlines(body):
3565 begin = 0
3571 begin = 0
3566 linenum = 0
3572 linenum = 0
3567 while begin < len(body):
3573 while begin < len(body):
3568 match = regexp.search(body, begin)
3574 match = regexp.search(body, begin)
3569 if not match:
3575 if not match:
3570 break
3576 break
3571 mstart, mend = match.span()
3577 mstart, mend = match.span()
3572 linenum += body.count('\n', begin, mstart) + 1
3578 linenum += body.count('\n', begin, mstart) + 1
3573 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3579 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3574 begin = body.find('\n', mend) + 1 or len(body) + 1
3580 begin = body.find('\n', mend) + 1 or len(body) + 1
3575 lend = begin - 1
3581 lend = begin - 1
3576 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3582 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3577
3583
3578 class linestate(object):
3584 class linestate(object):
3579 def __init__(self, line, linenum, colstart, colend):
3585 def __init__(self, line, linenum, colstart, colend):
3580 self.line = line
3586 self.line = line
3581 self.linenum = linenum
3587 self.linenum = linenum
3582 self.colstart = colstart
3588 self.colstart = colstart
3583 self.colend = colend
3589 self.colend = colend
3584
3590
3585 def __hash__(self):
3591 def __hash__(self):
3586 return hash((self.linenum, self.line))
3592 return hash((self.linenum, self.line))
3587
3593
3588 def __eq__(self, other):
3594 def __eq__(self, other):
3589 return self.line == other.line
3595 return self.line == other.line
3590
3596
3591 def __iter__(self):
3597 def __iter__(self):
3592 yield (self.line[:self.colstart], '')
3598 yield (self.line[:self.colstart], '')
3593 yield (self.line[self.colstart:self.colend], 'grep.match')
3599 yield (self.line[self.colstart:self.colend], 'grep.match')
3594 rest = self.line[self.colend:]
3600 rest = self.line[self.colend:]
3595 while rest != '':
3601 while rest != '':
3596 match = regexp.search(rest)
3602 match = regexp.search(rest)
3597 if not match:
3603 if not match:
3598 yield (rest, '')
3604 yield (rest, '')
3599 break
3605 break
3600 mstart, mend = match.span()
3606 mstart, mend = match.span()
3601 yield (rest[:mstart], '')
3607 yield (rest[:mstart], '')
3602 yield (rest[mstart:mend], 'grep.match')
3608 yield (rest[mstart:mend], 'grep.match')
3603 rest = rest[mend:]
3609 rest = rest[mend:]
3604
3610
3605 matches = {}
3611 matches = {}
3606 copies = {}
3612 copies = {}
3607 def grepbody(fn, rev, body):
3613 def grepbody(fn, rev, body):
3608 matches[rev].setdefault(fn, [])
3614 matches[rev].setdefault(fn, [])
3609 m = matches[rev][fn]
3615 m = matches[rev][fn]
3610 for lnum, cstart, cend, line in matchlines(body):
3616 for lnum, cstart, cend, line in matchlines(body):
3611 s = linestate(line, lnum, cstart, cend)
3617 s = linestate(line, lnum, cstart, cend)
3612 m.append(s)
3618 m.append(s)
3613
3619
3614 def difflinestates(a, b):
3620 def difflinestates(a, b):
3615 sm = difflib.SequenceMatcher(None, a, b)
3621 sm = difflib.SequenceMatcher(None, a, b)
3616 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3622 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3617 if tag == 'insert':
3623 if tag == 'insert':
3618 for i in xrange(blo, bhi):
3624 for i in xrange(blo, bhi):
3619 yield ('+', b[i])
3625 yield ('+', b[i])
3620 elif tag == 'delete':
3626 elif tag == 'delete':
3621 for i in xrange(alo, ahi):
3627 for i in xrange(alo, ahi):
3622 yield ('-', a[i])
3628 yield ('-', a[i])
3623 elif tag == 'replace':
3629 elif tag == 'replace':
3624 for i in xrange(alo, ahi):
3630 for i in xrange(alo, ahi):
3625 yield ('-', a[i])
3631 yield ('-', a[i])
3626 for i in xrange(blo, bhi):
3632 for i in xrange(blo, bhi):
3627 yield ('+', b[i])
3633 yield ('+', b[i])
3628
3634
3629 def display(fn, ctx, pstates, states):
3635 def display(fn, ctx, pstates, states):
3630 rev = ctx.rev()
3636 rev = ctx.rev()
3631 datefunc = ui.quiet and util.shortdate or util.datestr
3637 datefunc = ui.quiet and util.shortdate or util.datestr
3632 found = False
3638 found = False
3633 @util.cachefunc
3639 @util.cachefunc
3634 def binary():
3640 def binary():
3635 flog = getfile(fn)
3641 flog = getfile(fn)
3636 return util.binary(flog.read(ctx.filenode(fn)))
3642 return util.binary(flog.read(ctx.filenode(fn)))
3637
3643
3638 if opts.get('all'):
3644 if opts.get('all'):
3639 iter = difflinestates(pstates, states)
3645 iter = difflinestates(pstates, states)
3640 else:
3646 else:
3641 iter = [('', l) for l in states]
3647 iter = [('', l) for l in states]
3642 for change, l in iter:
3648 for change, l in iter:
3643 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3649 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3644
3650
3645 if opts.get('line_number'):
3651 if opts.get('line_number'):
3646 cols.append((str(l.linenum), 'grep.linenumber'))
3652 cols.append((str(l.linenum), 'grep.linenumber'))
3647 if opts.get('all'):
3653 if opts.get('all'):
3648 cols.append((change, 'grep.change'))
3654 cols.append((change, 'grep.change'))
3649 if opts.get('user'):
3655 if opts.get('user'):
3650 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3656 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3651 if opts.get('date'):
3657 if opts.get('date'):
3652 cols.append((datefunc(ctx.date()), 'grep.date'))
3658 cols.append((datefunc(ctx.date()), 'grep.date'))
3653 for col, label in cols[:-1]:
3659 for col, label in cols[:-1]:
3654 ui.write(col, label=label)
3660 ui.write(col, label=label)
3655 ui.write(sep, label='grep.sep')
3661 ui.write(sep, label='grep.sep')
3656 ui.write(cols[-1][0], label=cols[-1][1])
3662 ui.write(cols[-1][0], label=cols[-1][1])
3657 if not opts.get('files_with_matches'):
3663 if not opts.get('files_with_matches'):
3658 ui.write(sep, label='grep.sep')
3664 ui.write(sep, label='grep.sep')
3659 if not opts.get('text') and binary():
3665 if not opts.get('text') and binary():
3660 ui.write(" Binary file matches")
3666 ui.write(" Binary file matches")
3661 else:
3667 else:
3662 for s, label in l:
3668 for s, label in l:
3663 ui.write(s, label=label)
3669 ui.write(s, label=label)
3664 ui.write(eol)
3670 ui.write(eol)
3665 found = True
3671 found = True
3666 if opts.get('files_with_matches'):
3672 if opts.get('files_with_matches'):
3667 break
3673 break
3668 return found
3674 return found
3669
3675
3670 skip = {}
3676 skip = {}
3671 revfiles = {}
3677 revfiles = {}
3672 matchfn = scmutil.match(repo[None], pats, opts)
3678 matchfn = scmutil.match(repo[None], pats, opts)
3673 found = False
3679 found = False
3674 follow = opts.get('follow')
3680 follow = opts.get('follow')
3675
3681
3676 def prep(ctx, fns):
3682 def prep(ctx, fns):
3677 rev = ctx.rev()
3683 rev = ctx.rev()
3678 pctx = ctx.p1()
3684 pctx = ctx.p1()
3679 parent = pctx.rev()
3685 parent = pctx.rev()
3680 matches.setdefault(rev, {})
3686 matches.setdefault(rev, {})
3681 matches.setdefault(parent, {})
3687 matches.setdefault(parent, {})
3682 files = revfiles.setdefault(rev, [])
3688 files = revfiles.setdefault(rev, [])
3683 for fn in fns:
3689 for fn in fns:
3684 flog = getfile(fn)
3690 flog = getfile(fn)
3685 try:
3691 try:
3686 fnode = ctx.filenode(fn)
3692 fnode = ctx.filenode(fn)
3687 except error.LookupError:
3693 except error.LookupError:
3688 continue
3694 continue
3689
3695
3690 copied = flog.renamed(fnode)
3696 copied = flog.renamed(fnode)
3691 copy = follow and copied and copied[0]
3697 copy = follow and copied and copied[0]
3692 if copy:
3698 if copy:
3693 copies.setdefault(rev, {})[fn] = copy
3699 copies.setdefault(rev, {})[fn] = copy
3694 if fn in skip:
3700 if fn in skip:
3695 if copy:
3701 if copy:
3696 skip[copy] = True
3702 skip[copy] = True
3697 continue
3703 continue
3698 files.append(fn)
3704 files.append(fn)
3699
3705
3700 if fn not in matches[rev]:
3706 if fn not in matches[rev]:
3701 grepbody(fn, rev, flog.read(fnode))
3707 grepbody(fn, rev, flog.read(fnode))
3702
3708
3703 pfn = copy or fn
3709 pfn = copy or fn
3704 if pfn not in matches[parent]:
3710 if pfn not in matches[parent]:
3705 try:
3711 try:
3706 fnode = pctx.filenode(pfn)
3712 fnode = pctx.filenode(pfn)
3707 grepbody(pfn, parent, flog.read(fnode))
3713 grepbody(pfn, parent, flog.read(fnode))
3708 except error.LookupError:
3714 except error.LookupError:
3709 pass
3715 pass
3710
3716
3711 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3717 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3712 rev = ctx.rev()
3718 rev = ctx.rev()
3713 parent = ctx.p1().rev()
3719 parent = ctx.p1().rev()
3714 for fn in sorted(revfiles.get(rev, [])):
3720 for fn in sorted(revfiles.get(rev, [])):
3715 states = matches[rev][fn]
3721 states = matches[rev][fn]
3716 copy = copies.get(rev, {}).get(fn)
3722 copy = copies.get(rev, {}).get(fn)
3717 if fn in skip:
3723 if fn in skip:
3718 if copy:
3724 if copy:
3719 skip[copy] = True
3725 skip[copy] = True
3720 continue
3726 continue
3721 pstates = matches.get(parent, {}).get(copy or fn, [])
3727 pstates = matches.get(parent, {}).get(copy or fn, [])
3722 if pstates or states:
3728 if pstates or states:
3723 r = display(fn, ctx, pstates, states)
3729 r = display(fn, ctx, pstates, states)
3724 found = found or r
3730 found = found or r
3725 if r and not opts.get('all'):
3731 if r and not opts.get('all'):
3726 skip[fn] = True
3732 skip[fn] = True
3727 if copy:
3733 if copy:
3728 skip[copy] = True
3734 skip[copy] = True
3729 del matches[rev]
3735 del matches[rev]
3730 del revfiles[rev]
3736 del revfiles[rev]
3731
3737
3732 return not found
3738 return not found
3733
3739
3734 @command('heads',
3740 @command('heads',
3735 [('r', 'rev', '',
3741 [('r', 'rev', '',
3736 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3742 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3737 ('t', 'topo', False, _('show topological heads only')),
3743 ('t', 'topo', False, _('show topological heads only')),
3738 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3744 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3739 ('c', 'closed', False, _('show normal and closed branch heads')),
3745 ('c', 'closed', False, _('show normal and closed branch heads')),
3740 ] + templateopts,
3746 ] + templateopts,
3741 _('[-ct] [-r STARTREV] [REV]...'))
3747 _('[-ct] [-r STARTREV] [REV]...'))
3742 def heads(ui, repo, *branchrevs, **opts):
3748 def heads(ui, repo, *branchrevs, **opts):
3743 """show branch heads
3749 """show branch heads
3744
3750
3745 With no arguments, show all open branch heads in the repository.
3751 With no arguments, show all open branch heads in the repository.
3746 Branch heads are changesets that have no descendants on the
3752 Branch heads are changesets that have no descendants on the
3747 same branch. They are where development generally takes place and
3753 same branch. They are where development generally takes place and
3748 are the usual targets for update and merge operations.
3754 are the usual targets for update and merge operations.
3749
3755
3750 If one or more REVs are given, only open branch heads on the
3756 If one or more REVs are given, only open branch heads on the
3751 branches associated with the specified changesets are shown. This
3757 branches associated with the specified changesets are shown. This
3752 means that you can use :hg:`heads .` to see the heads on the
3758 means that you can use :hg:`heads .` to see the heads on the
3753 currently checked-out branch.
3759 currently checked-out branch.
3754
3760
3755 If -c/--closed is specified, also show branch heads marked closed
3761 If -c/--closed is specified, also show branch heads marked closed
3756 (see :hg:`commit --close-branch`).
3762 (see :hg:`commit --close-branch`).
3757
3763
3758 If STARTREV is specified, only those heads that are descendants of
3764 If STARTREV is specified, only those heads that are descendants of
3759 STARTREV will be displayed.
3765 STARTREV will be displayed.
3760
3766
3761 If -t/--topo is specified, named branch mechanics will be ignored and only
3767 If -t/--topo is specified, named branch mechanics will be ignored and only
3762 topological heads (changesets with no children) will be shown.
3768 topological heads (changesets with no children) will be shown.
3763
3769
3764 Returns 0 if matching heads are found, 1 if not.
3770 Returns 0 if matching heads are found, 1 if not.
3765 """
3771 """
3766
3772
3767 start = None
3773 start = None
3768 if 'rev' in opts:
3774 if 'rev' in opts:
3769 start = scmutil.revsingle(repo, opts['rev'], None).node()
3775 start = scmutil.revsingle(repo, opts['rev'], None).node()
3770
3776
3771 if opts.get('topo'):
3777 if opts.get('topo'):
3772 heads = [repo[h] for h in repo.heads(start)]
3778 heads = [repo[h] for h in repo.heads(start)]
3773 else:
3779 else:
3774 heads = []
3780 heads = []
3775 for branch in repo.branchmap():
3781 for branch in repo.branchmap():
3776 heads += repo.branchheads(branch, start, opts.get('closed'))
3782 heads += repo.branchheads(branch, start, opts.get('closed'))
3777 heads = [repo[h] for h in heads]
3783 heads = [repo[h] for h in heads]
3778
3784
3779 if branchrevs:
3785 if branchrevs:
3780 branches = set(repo[br].branch() for br in branchrevs)
3786 branches = set(repo[br].branch() for br in branchrevs)
3781 heads = [h for h in heads if h.branch() in branches]
3787 heads = [h for h in heads if h.branch() in branches]
3782
3788
3783 if opts.get('active') and branchrevs:
3789 if opts.get('active') and branchrevs:
3784 dagheads = repo.heads(start)
3790 dagheads = repo.heads(start)
3785 heads = [h for h in heads if h.node() in dagheads]
3791 heads = [h for h in heads if h.node() in dagheads]
3786
3792
3787 if branchrevs:
3793 if branchrevs:
3788 haveheads = set(h.branch() for h in heads)
3794 haveheads = set(h.branch() for h in heads)
3789 if branches - haveheads:
3795 if branches - haveheads:
3790 headless = ', '.join(b for b in branches - haveheads)
3796 headless = ', '.join(b for b in branches - haveheads)
3791 msg = _('no open branch heads found on branches %s')
3797 msg = _('no open branch heads found on branches %s')
3792 if opts.get('rev'):
3798 if opts.get('rev'):
3793 msg += _(' (started at %s)') % opts['rev']
3799 msg += _(' (started at %s)') % opts['rev']
3794 ui.warn((msg + '\n') % headless)
3800 ui.warn((msg + '\n') % headless)
3795
3801
3796 if not heads:
3802 if not heads:
3797 return 1
3803 return 1
3798
3804
3799 heads = sorted(heads, key=lambda x: -x.rev())
3805 heads = sorted(heads, key=lambda x: -x.rev())
3800 displayer = cmdutil.show_changeset(ui, repo, opts)
3806 displayer = cmdutil.show_changeset(ui, repo, opts)
3801 for ctx in heads:
3807 for ctx in heads:
3802 displayer.show(ctx)
3808 displayer.show(ctx)
3803 displayer.close()
3809 displayer.close()
3804
3810
3805 @command('help',
3811 @command('help',
3806 [('e', 'extension', None, _('show only help for extensions')),
3812 [('e', 'extension', None, _('show only help for extensions')),
3807 ('c', 'command', None, _('show only help for commands')),
3813 ('c', 'command', None, _('show only help for commands')),
3808 ('k', 'keyword', '', _('show topics matching keyword')),
3814 ('k', 'keyword', '', _('show topics matching keyword')),
3809 ],
3815 ],
3810 _('[-ec] [TOPIC]'),
3816 _('[-ec] [TOPIC]'),
3811 norepo=True)
3817 norepo=True)
3812 def help_(ui, name=None, **opts):
3818 def help_(ui, name=None, **opts):
3813 """show help for a given topic or a help overview
3819 """show help for a given topic or a help overview
3814
3820
3815 With no arguments, print a list of commands with short help messages.
3821 With no arguments, print a list of commands with short help messages.
3816
3822
3817 Given a topic, extension, or command name, print help for that
3823 Given a topic, extension, or command name, print help for that
3818 topic.
3824 topic.
3819
3825
3820 Returns 0 if successful.
3826 Returns 0 if successful.
3821 """
3827 """
3822
3828
3823 textwidth = min(ui.termwidth(), 80) - 2
3829 textwidth = min(ui.termwidth(), 80) - 2
3824
3830
3825 keep = []
3831 keep = []
3826 if ui.verbose:
3832 if ui.verbose:
3827 keep.append('verbose')
3833 keep.append('verbose')
3828 if sys.platform.startswith('win'):
3834 if sys.platform.startswith('win'):
3829 keep.append('windows')
3835 keep.append('windows')
3830 elif sys.platform == 'OpenVMS':
3836 elif sys.platform == 'OpenVMS':
3831 keep.append('vms')
3837 keep.append('vms')
3832 elif sys.platform == 'plan9':
3838 elif sys.platform == 'plan9':
3833 keep.append('plan9')
3839 keep.append('plan9')
3834 else:
3840 else:
3835 keep.append('unix')
3841 keep.append('unix')
3836 keep.append(sys.platform.lower())
3842 keep.append(sys.platform.lower())
3837
3843
3838 section = None
3844 section = None
3839 if name and '.' in name:
3845 if name and '.' in name:
3840 name, section = name.split('.')
3846 name, section = name.split('.')
3841
3847
3842 text = help.help_(ui, name, **opts)
3848 text = help.help_(ui, name, **opts)
3843
3849
3844 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3850 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3845 section=section)
3851 section=section)
3846 if section and not formatted:
3852 if section and not formatted:
3847 raise util.Abort(_("help section not found"))
3853 raise util.Abort(_("help section not found"))
3848
3854
3849 if 'verbose' in pruned:
3855 if 'verbose' in pruned:
3850 keep.append('omitted')
3856 keep.append('omitted')
3851 else:
3857 else:
3852 keep.append('notomitted')
3858 keep.append('notomitted')
3853 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3859 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3854 section=section)
3860 section=section)
3855 ui.write(formatted)
3861 ui.write(formatted)
3856
3862
3857
3863
3858 @command('identify|id',
3864 @command('identify|id',
3859 [('r', 'rev', '',
3865 [('r', 'rev', '',
3860 _('identify the specified revision'), _('REV')),
3866 _('identify the specified revision'), _('REV')),
3861 ('n', 'num', None, _('show local revision number')),
3867 ('n', 'num', None, _('show local revision number')),
3862 ('i', 'id', None, _('show global revision id')),
3868 ('i', 'id', None, _('show global revision id')),
3863 ('b', 'branch', None, _('show branch')),
3869 ('b', 'branch', None, _('show branch')),
3864 ('t', 'tags', None, _('show tags')),
3870 ('t', 'tags', None, _('show tags')),
3865 ('B', 'bookmarks', None, _('show bookmarks')),
3871 ('B', 'bookmarks', None, _('show bookmarks')),
3866 ] + remoteopts,
3872 ] + remoteopts,
3867 _('[-nibtB] [-r REV] [SOURCE]'),
3873 _('[-nibtB] [-r REV] [SOURCE]'),
3868 optionalrepo=True)
3874 optionalrepo=True)
3869 def identify(ui, repo, source=None, rev=None,
3875 def identify(ui, repo, source=None, rev=None,
3870 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3876 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3871 """identify the working copy or specified revision
3877 """identify the working copy or specified revision
3872
3878
3873 Print a summary identifying the repository state at REV using one or
3879 Print a summary identifying the repository state at REV using one or
3874 two parent hash identifiers, followed by a "+" if the working
3880 two parent hash identifiers, followed by a "+" if the working
3875 directory has uncommitted changes, the branch name (if not default),
3881 directory has uncommitted changes, the branch name (if not default),
3876 a list of tags, and a list of bookmarks.
3882 a list of tags, and a list of bookmarks.
3877
3883
3878 When REV is not given, print a summary of the current state of the
3884 When REV is not given, print a summary of the current state of the
3879 repository.
3885 repository.
3880
3886
3881 Specifying a path to a repository root or Mercurial bundle will
3887 Specifying a path to a repository root or Mercurial bundle will
3882 cause lookup to operate on that repository/bundle.
3888 cause lookup to operate on that repository/bundle.
3883
3889
3884 .. container:: verbose
3890 .. container:: verbose
3885
3891
3886 Examples:
3892 Examples:
3887
3893
3888 - generate a build identifier for the working directory::
3894 - generate a build identifier for the working directory::
3889
3895
3890 hg id --id > build-id.dat
3896 hg id --id > build-id.dat
3891
3897
3892 - find the revision corresponding to a tag::
3898 - find the revision corresponding to a tag::
3893
3899
3894 hg id -n -r 1.3
3900 hg id -n -r 1.3
3895
3901
3896 - check the most recent revision of a remote repository::
3902 - check the most recent revision of a remote repository::
3897
3903
3898 hg id -r tip http://selenic.com/hg/
3904 hg id -r tip http://selenic.com/hg/
3899
3905
3900 Returns 0 if successful.
3906 Returns 0 if successful.
3901 """
3907 """
3902
3908
3903 if not repo and not source:
3909 if not repo and not source:
3904 raise util.Abort(_("there is no Mercurial repository here "
3910 raise util.Abort(_("there is no Mercurial repository here "
3905 "(.hg not found)"))
3911 "(.hg not found)"))
3906
3912
3907 hexfunc = ui.debugflag and hex or short
3913 hexfunc = ui.debugflag and hex or short
3908 default = not (num or id or branch or tags or bookmarks)
3914 default = not (num or id or branch or tags or bookmarks)
3909 output = []
3915 output = []
3910 revs = []
3916 revs = []
3911
3917
3912 if source:
3918 if source:
3913 source, branches = hg.parseurl(ui.expandpath(source))
3919 source, branches = hg.parseurl(ui.expandpath(source))
3914 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3920 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3915 repo = peer.local()
3921 repo = peer.local()
3916 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3922 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3917
3923
3918 if not repo:
3924 if not repo:
3919 if num or branch or tags:
3925 if num or branch or tags:
3920 raise util.Abort(
3926 raise util.Abort(
3921 _("can't query remote revision number, branch, or tags"))
3927 _("can't query remote revision number, branch, or tags"))
3922 if not rev and revs:
3928 if not rev and revs:
3923 rev = revs[0]
3929 rev = revs[0]
3924 if not rev:
3930 if not rev:
3925 rev = "tip"
3931 rev = "tip"
3926
3932
3927 remoterev = peer.lookup(rev)
3933 remoterev = peer.lookup(rev)
3928 if default or id:
3934 if default or id:
3929 output = [hexfunc(remoterev)]
3935 output = [hexfunc(remoterev)]
3930
3936
3931 def getbms():
3937 def getbms():
3932 bms = []
3938 bms = []
3933
3939
3934 if 'bookmarks' in peer.listkeys('namespaces'):
3940 if 'bookmarks' in peer.listkeys('namespaces'):
3935 hexremoterev = hex(remoterev)
3941 hexremoterev = hex(remoterev)
3936 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3942 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3937 if bmr == hexremoterev]
3943 if bmr == hexremoterev]
3938
3944
3939 return sorted(bms)
3945 return sorted(bms)
3940
3946
3941 if bookmarks:
3947 if bookmarks:
3942 output.extend(getbms())
3948 output.extend(getbms())
3943 elif default and not ui.quiet:
3949 elif default and not ui.quiet:
3944 # multiple bookmarks for a single parent separated by '/'
3950 # multiple bookmarks for a single parent separated by '/'
3945 bm = '/'.join(getbms())
3951 bm = '/'.join(getbms())
3946 if bm:
3952 if bm:
3947 output.append(bm)
3953 output.append(bm)
3948 else:
3954 else:
3949 if not rev:
3955 if not rev:
3950 ctx = repo[None]
3956 ctx = repo[None]
3951 parents = ctx.parents()
3957 parents = ctx.parents()
3952 changed = ""
3958 changed = ""
3953 if default or id or num:
3959 if default or id or num:
3954 if (util.any(repo.status())
3960 if (util.any(repo.status())
3955 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3961 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3956 changed = '+'
3962 changed = '+'
3957 if default or id:
3963 if default or id:
3958 output = ["%s%s" %
3964 output = ["%s%s" %
3959 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3965 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3960 if num:
3966 if num:
3961 output.append("%s%s" %
3967 output.append("%s%s" %
3962 ('+'.join([str(p.rev()) for p in parents]), changed))
3968 ('+'.join([str(p.rev()) for p in parents]), changed))
3963 else:
3969 else:
3964 ctx = scmutil.revsingle(repo, rev)
3970 ctx = scmutil.revsingle(repo, rev)
3965 if default or id:
3971 if default or id:
3966 output = [hexfunc(ctx.node())]
3972 output = [hexfunc(ctx.node())]
3967 if num:
3973 if num:
3968 output.append(str(ctx.rev()))
3974 output.append(str(ctx.rev()))
3969
3975
3970 if default and not ui.quiet:
3976 if default and not ui.quiet:
3971 b = ctx.branch()
3977 b = ctx.branch()
3972 if b != 'default':
3978 if b != 'default':
3973 output.append("(%s)" % b)
3979 output.append("(%s)" % b)
3974
3980
3975 # multiple tags for a single parent separated by '/'
3981 # multiple tags for a single parent separated by '/'
3976 t = '/'.join(ctx.tags())
3982 t = '/'.join(ctx.tags())
3977 if t:
3983 if t:
3978 output.append(t)
3984 output.append(t)
3979
3985
3980 # multiple bookmarks for a single parent separated by '/'
3986 # multiple bookmarks for a single parent separated by '/'
3981 bm = '/'.join(ctx.bookmarks())
3987 bm = '/'.join(ctx.bookmarks())
3982 if bm:
3988 if bm:
3983 output.append(bm)
3989 output.append(bm)
3984 else:
3990 else:
3985 if branch:
3991 if branch:
3986 output.append(ctx.branch())
3992 output.append(ctx.branch())
3987
3993
3988 if tags:
3994 if tags:
3989 output.extend(ctx.tags())
3995 output.extend(ctx.tags())
3990
3996
3991 if bookmarks:
3997 if bookmarks:
3992 output.extend(ctx.bookmarks())
3998 output.extend(ctx.bookmarks())
3993
3999
3994 ui.write("%s\n" % ' '.join(output))
4000 ui.write("%s\n" % ' '.join(output))
3995
4001
3996 @command('import|patch',
4002 @command('import|patch',
3997 [('p', 'strip', 1,
4003 [('p', 'strip', 1,
3998 _('directory strip option for patch. This has the same '
4004 _('directory strip option for patch. This has the same '
3999 'meaning as the corresponding patch option'), _('NUM')),
4005 'meaning as the corresponding patch option'), _('NUM')),
4000 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4006 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4001 ('e', 'edit', False, _('invoke editor on commit messages')),
4007 ('e', 'edit', False, _('invoke editor on commit messages')),
4002 ('f', 'force', None,
4008 ('f', 'force', None,
4003 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4009 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4004 ('', 'no-commit', None,
4010 ('', 'no-commit', None,
4005 _("don't commit, just update the working directory")),
4011 _("don't commit, just update the working directory")),
4006 ('', 'bypass', None,
4012 ('', 'bypass', None,
4007 _("apply patch without touching the working directory")),
4013 _("apply patch without touching the working directory")),
4008 ('', 'partial', None,
4014 ('', 'partial', None,
4009 _('commit even if some hunks fail')),
4015 _('commit even if some hunks fail')),
4010 ('', 'exact', None,
4016 ('', 'exact', None,
4011 _('apply patch to the nodes from which it was generated')),
4017 _('apply patch to the nodes from which it was generated')),
4012 ('', 'import-branch', None,
4018 ('', 'import-branch', None,
4013 _('use any branch information in patch (implied by --exact)'))] +
4019 _('use any branch information in patch (implied by --exact)'))] +
4014 commitopts + commitopts2 + similarityopts,
4020 commitopts + commitopts2 + similarityopts,
4015 _('[OPTION]... PATCH...'))
4021 _('[OPTION]... PATCH...'))
4016 def import_(ui, repo, patch1=None, *patches, **opts):
4022 def import_(ui, repo, patch1=None, *patches, **opts):
4017 """import an ordered set of patches
4023 """import an ordered set of patches
4018
4024
4019 Import a list of patches and commit them individually (unless
4025 Import a list of patches and commit them individually (unless
4020 --no-commit is specified).
4026 --no-commit is specified).
4021
4027
4022 Because import first applies changes to the working directory,
4028 Because import first applies changes to the working directory,
4023 import will abort if there are outstanding changes.
4029 import will abort if there are outstanding changes.
4024
4030
4025 You can import a patch straight from a mail message. Even patches
4031 You can import a patch straight from a mail message. Even patches
4026 as attachments work (to use the body part, it must have type
4032 as attachments work (to use the body part, it must have type
4027 text/plain or text/x-patch). From and Subject headers of email
4033 text/plain or text/x-patch). From and Subject headers of email
4028 message are used as default committer and commit message. All
4034 message are used as default committer and commit message. All
4029 text/plain body parts before first diff are added to commit
4035 text/plain body parts before first diff are added to commit
4030 message.
4036 message.
4031
4037
4032 If the imported patch was generated by :hg:`export`, user and
4038 If the imported patch was generated by :hg:`export`, user and
4033 description from patch override values from message headers and
4039 description from patch override values from message headers and
4034 body. Values given on command line with -m/--message and -u/--user
4040 body. Values given on command line with -m/--message and -u/--user
4035 override these.
4041 override these.
4036
4042
4037 If --exact is specified, import will set the working directory to
4043 If --exact is specified, import will set the working directory to
4038 the parent of each patch before applying it, and will abort if the
4044 the parent of each patch before applying it, and will abort if the
4039 resulting changeset has a different ID than the one recorded in
4045 resulting changeset has a different ID than the one recorded in
4040 the patch. This may happen due to character set problems or other
4046 the patch. This may happen due to character set problems or other
4041 deficiencies in the text patch format.
4047 deficiencies in the text patch format.
4042
4048
4043 Use --bypass to apply and commit patches directly to the
4049 Use --bypass to apply and commit patches directly to the
4044 repository, not touching the working directory. Without --exact,
4050 repository, not touching the working directory. Without --exact,
4045 patches will be applied on top of the working directory parent
4051 patches will be applied on top of the working directory parent
4046 revision.
4052 revision.
4047
4053
4048 With -s/--similarity, hg will attempt to discover renames and
4054 With -s/--similarity, hg will attempt to discover renames and
4049 copies in the patch in the same way as :hg:`addremove`.
4055 copies in the patch in the same way as :hg:`addremove`.
4050
4056
4051 Use --partial to ensure a changeset will be created from the patch
4057 Use --partial to ensure a changeset will be created from the patch
4052 even if some hunks fail to apply. Hunks that fail to apply will be
4058 even if some hunks fail to apply. Hunks that fail to apply will be
4053 written to a <target-file>.rej file. Conflicts can then be resolved
4059 written to a <target-file>.rej file. Conflicts can then be resolved
4054 by hand before :hg:`commit --amend` is run to update the created
4060 by hand before :hg:`commit --amend` is run to update the created
4055 changeset. This flag exists to let people import patches that
4061 changeset. This flag exists to let people import patches that
4056 partially apply without losing the associated metadata (author,
4062 partially apply without losing the associated metadata (author,
4057 date, description, ...). Note that when none of the hunk applies
4063 date, description, ...). Note that when none of the hunk applies
4058 cleanly, :hg:`import --partial` will create an empty changeset,
4064 cleanly, :hg:`import --partial` will create an empty changeset,
4059 importing only the patch metadata.
4065 importing only the patch metadata.
4060
4066
4061 To read a patch from standard input, use "-" as the patch name. If
4067 To read a patch from standard input, use "-" as the patch name. If
4062 a URL is specified, the patch will be downloaded from it.
4068 a URL is specified, the patch will be downloaded from it.
4063 See :hg:`help dates` for a list of formats valid for -d/--date.
4069 See :hg:`help dates` for a list of formats valid for -d/--date.
4064
4070
4065 .. container:: verbose
4071 .. container:: verbose
4066
4072
4067 Examples:
4073 Examples:
4068
4074
4069 - import a traditional patch from a website and detect renames::
4075 - import a traditional patch from a website and detect renames::
4070
4076
4071 hg import -s 80 http://example.com/bugfix.patch
4077 hg import -s 80 http://example.com/bugfix.patch
4072
4078
4073 - import a changeset from an hgweb server::
4079 - import a changeset from an hgweb server::
4074
4080
4075 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4081 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4076
4082
4077 - import all the patches in an Unix-style mbox::
4083 - import all the patches in an Unix-style mbox::
4078
4084
4079 hg import incoming-patches.mbox
4085 hg import incoming-patches.mbox
4080
4086
4081 - attempt to exactly restore an exported changeset (not always
4087 - attempt to exactly restore an exported changeset (not always
4082 possible)::
4088 possible)::
4083
4089
4084 hg import --exact proposed-fix.patch
4090 hg import --exact proposed-fix.patch
4085
4091
4086 Returns 0 on success, 1 on partial success (see --partial).
4092 Returns 0 on success, 1 on partial success (see --partial).
4087 """
4093 """
4088
4094
4089 if not patch1:
4095 if not patch1:
4090 raise util.Abort(_('need at least one patch to import'))
4096 raise util.Abort(_('need at least one patch to import'))
4091
4097
4092 patches = (patch1,) + patches
4098 patches = (patch1,) + patches
4093
4099
4094 date = opts.get('date')
4100 date = opts.get('date')
4095 if date:
4101 if date:
4096 opts['date'] = util.parsedate(date)
4102 opts['date'] = util.parsedate(date)
4097
4103
4098 update = not opts.get('bypass')
4104 update = not opts.get('bypass')
4099 if not update and opts.get('no_commit'):
4105 if not update and opts.get('no_commit'):
4100 raise util.Abort(_('cannot use --no-commit with --bypass'))
4106 raise util.Abort(_('cannot use --no-commit with --bypass'))
4101 try:
4107 try:
4102 sim = float(opts.get('similarity') or 0)
4108 sim = float(opts.get('similarity') or 0)
4103 except ValueError:
4109 except ValueError:
4104 raise util.Abort(_('similarity must be a number'))
4110 raise util.Abort(_('similarity must be a number'))
4105 if sim < 0 or sim > 100:
4111 if sim < 0 or sim > 100:
4106 raise util.Abort(_('similarity must be between 0 and 100'))
4112 raise util.Abort(_('similarity must be between 0 and 100'))
4107 if sim and not update:
4113 if sim and not update:
4108 raise util.Abort(_('cannot use --similarity with --bypass'))
4114 raise util.Abort(_('cannot use --similarity with --bypass'))
4109 if opts.get('exact') and opts.get('edit'):
4115 if opts.get('exact') and opts.get('edit'):
4110 raise util.Abort(_('cannot use --exact with --edit'))
4116 raise util.Abort(_('cannot use --exact with --edit'))
4111
4117
4112 if update:
4118 if update:
4113 cmdutil.checkunfinished(repo)
4119 cmdutil.checkunfinished(repo)
4114 if (opts.get('exact') or not opts.get('force')) and update:
4120 if (opts.get('exact') or not opts.get('force')) and update:
4115 cmdutil.bailifchanged(repo)
4121 cmdutil.bailifchanged(repo)
4116
4122
4117 base = opts["base"]
4123 base = opts["base"]
4118 wlock = lock = tr = None
4124 wlock = lock = tr = None
4119 msgs = []
4125 msgs = []
4120 ret = 0
4126 ret = 0
4121
4127
4122
4128
4123 try:
4129 try:
4124 try:
4130 try:
4125 wlock = repo.wlock()
4131 wlock = repo.wlock()
4126 repo.dirstate.beginparentchange()
4132 repo.dirstate.beginparentchange()
4127 if not opts.get('no_commit'):
4133 if not opts.get('no_commit'):
4128 lock = repo.lock()
4134 lock = repo.lock()
4129 tr = repo.transaction('import')
4135 tr = repo.transaction('import')
4130 parents = repo.parents()
4136 parents = repo.parents()
4131 for patchurl in patches:
4137 for patchurl in patches:
4132 if patchurl == '-':
4138 if patchurl == '-':
4133 ui.status(_('applying patch from stdin\n'))
4139 ui.status(_('applying patch from stdin\n'))
4134 patchfile = ui.fin
4140 patchfile = ui.fin
4135 patchurl = 'stdin' # for error message
4141 patchurl = 'stdin' # for error message
4136 else:
4142 else:
4137 patchurl = os.path.join(base, patchurl)
4143 patchurl = os.path.join(base, patchurl)
4138 ui.status(_('applying %s\n') % patchurl)
4144 ui.status(_('applying %s\n') % patchurl)
4139 patchfile = hg.openpath(ui, patchurl)
4145 patchfile = hg.openpath(ui, patchurl)
4140
4146
4141 haspatch = False
4147 haspatch = False
4142 for hunk in patch.split(patchfile):
4148 for hunk in patch.split(patchfile):
4143 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4149 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4144 parents, opts,
4150 parents, opts,
4145 msgs, hg.clean)
4151 msgs, hg.clean)
4146 if msg:
4152 if msg:
4147 haspatch = True
4153 haspatch = True
4148 ui.note(msg + '\n')
4154 ui.note(msg + '\n')
4149 if update or opts.get('exact'):
4155 if update or opts.get('exact'):
4150 parents = repo.parents()
4156 parents = repo.parents()
4151 else:
4157 else:
4152 parents = [repo[node]]
4158 parents = [repo[node]]
4153 if rej:
4159 if rej:
4154 ui.write_err(_("patch applied partially\n"))
4160 ui.write_err(_("patch applied partially\n"))
4155 ui.write_err(_("(fix the .rej files and run "
4161 ui.write_err(_("(fix the .rej files and run "
4156 "`hg commit --amend`)\n"))
4162 "`hg commit --amend`)\n"))
4157 ret = 1
4163 ret = 1
4158 break
4164 break
4159
4165
4160 if not haspatch:
4166 if not haspatch:
4161 raise util.Abort(_('%s: no diffs found') % patchurl)
4167 raise util.Abort(_('%s: no diffs found') % patchurl)
4162
4168
4163 if tr:
4169 if tr:
4164 tr.close()
4170 tr.close()
4165 if msgs:
4171 if msgs:
4166 repo.savecommitmessage('\n* * *\n'.join(msgs))
4172 repo.savecommitmessage('\n* * *\n'.join(msgs))
4167 repo.dirstate.endparentchange()
4173 repo.dirstate.endparentchange()
4168 return ret
4174 return ret
4169 except: # re-raises
4175 except: # re-raises
4170 # wlock.release() indirectly calls dirstate.write(): since
4176 # wlock.release() indirectly calls dirstate.write(): since
4171 # we're crashing, we do not want to change the working dir
4177 # we're crashing, we do not want to change the working dir
4172 # parent after all, so make sure it writes nothing
4178 # parent after all, so make sure it writes nothing
4173 repo.dirstate.invalidate()
4179 repo.dirstate.invalidate()
4174 raise
4180 raise
4175 finally:
4181 finally:
4176 if tr:
4182 if tr:
4177 tr.release()
4183 tr.release()
4178 release(lock, wlock)
4184 release(lock, wlock)
4179
4185
4180 @command('incoming|in',
4186 @command('incoming|in',
4181 [('f', 'force', None,
4187 [('f', 'force', None,
4182 _('run even if remote repository is unrelated')),
4188 _('run even if remote repository is unrelated')),
4183 ('n', 'newest-first', None, _('show newest record first')),
4189 ('n', 'newest-first', None, _('show newest record first')),
4184 ('', 'bundle', '',
4190 ('', 'bundle', '',
4185 _('file to store the bundles into'), _('FILE')),
4191 _('file to store the bundles into'), _('FILE')),
4186 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4192 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4187 ('B', 'bookmarks', False, _("compare bookmarks")),
4193 ('B', 'bookmarks', False, _("compare bookmarks")),
4188 ('b', 'branch', [],
4194 ('b', 'branch', [],
4189 _('a specific branch you would like to pull'), _('BRANCH')),
4195 _('a specific branch you would like to pull'), _('BRANCH')),
4190 ] + logopts + remoteopts + subrepoopts,
4196 ] + logopts + remoteopts + subrepoopts,
4191 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4197 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4192 def incoming(ui, repo, source="default", **opts):
4198 def incoming(ui, repo, source="default", **opts):
4193 """show new changesets found in source
4199 """show new changesets found in source
4194
4200
4195 Show new changesets found in the specified path/URL or the default
4201 Show new changesets found in the specified path/URL or the default
4196 pull location. These are the changesets that would have been pulled
4202 pull location. These are the changesets that would have been pulled
4197 if a pull at the time you issued this command.
4203 if a pull at the time you issued this command.
4198
4204
4199 For remote repository, using --bundle avoids downloading the
4205 For remote repository, using --bundle avoids downloading the
4200 changesets twice if the incoming is followed by a pull.
4206 changesets twice if the incoming is followed by a pull.
4201
4207
4202 See pull for valid source format details.
4208 See pull for valid source format details.
4203
4209
4204 .. container:: verbose
4210 .. container:: verbose
4205
4211
4206 Examples:
4212 Examples:
4207
4213
4208 - show incoming changes with patches and full description::
4214 - show incoming changes with patches and full description::
4209
4215
4210 hg incoming -vp
4216 hg incoming -vp
4211
4217
4212 - show incoming changes excluding merges, store a bundle::
4218 - show incoming changes excluding merges, store a bundle::
4213
4219
4214 hg in -vpM --bundle incoming.hg
4220 hg in -vpM --bundle incoming.hg
4215 hg pull incoming.hg
4221 hg pull incoming.hg
4216
4222
4217 - briefly list changes inside a bundle::
4223 - briefly list changes inside a bundle::
4218
4224
4219 hg in changes.hg -T "{desc|firstline}\\n"
4225 hg in changes.hg -T "{desc|firstline}\\n"
4220
4226
4221 Returns 0 if there are incoming changes, 1 otherwise.
4227 Returns 0 if there are incoming changes, 1 otherwise.
4222 """
4228 """
4223 if opts.get('graph'):
4229 if opts.get('graph'):
4224 cmdutil.checkunsupportedgraphflags([], opts)
4230 cmdutil.checkunsupportedgraphflags([], opts)
4225 def display(other, chlist, displayer):
4231 def display(other, chlist, displayer):
4226 revdag = cmdutil.graphrevs(other, chlist, opts)
4232 revdag = cmdutil.graphrevs(other, chlist, opts)
4227 showparents = [ctx.node() for ctx in repo[None].parents()]
4233 showparents = [ctx.node() for ctx in repo[None].parents()]
4228 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4234 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4229 graphmod.asciiedges)
4235 graphmod.asciiedges)
4230
4236
4231 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4237 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4232 return 0
4238 return 0
4233
4239
4234 if opts.get('bundle') and opts.get('subrepos'):
4240 if opts.get('bundle') and opts.get('subrepos'):
4235 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4241 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4236
4242
4237 if opts.get('bookmarks'):
4243 if opts.get('bookmarks'):
4238 source, branches = hg.parseurl(ui.expandpath(source),
4244 source, branches = hg.parseurl(ui.expandpath(source),
4239 opts.get('branch'))
4245 opts.get('branch'))
4240 other = hg.peer(repo, opts, source)
4246 other = hg.peer(repo, opts, source)
4241 if 'bookmarks' not in other.listkeys('namespaces'):
4247 if 'bookmarks' not in other.listkeys('namespaces'):
4242 ui.warn(_("remote doesn't support bookmarks\n"))
4248 ui.warn(_("remote doesn't support bookmarks\n"))
4243 return 0
4249 return 0
4244 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4250 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4245 return bookmarks.diff(ui, repo, other)
4251 return bookmarks.diff(ui, repo, other)
4246
4252
4247 repo._subtoppath = ui.expandpath(source)
4253 repo._subtoppath = ui.expandpath(source)
4248 try:
4254 try:
4249 return hg.incoming(ui, repo, source, opts)
4255 return hg.incoming(ui, repo, source, opts)
4250 finally:
4256 finally:
4251 del repo._subtoppath
4257 del repo._subtoppath
4252
4258
4253
4259
4254 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4260 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4255 norepo=True)
4261 norepo=True)
4256 def init(ui, dest=".", **opts):
4262 def init(ui, dest=".", **opts):
4257 """create a new repository in the given directory
4263 """create a new repository in the given directory
4258
4264
4259 Initialize a new repository in the given directory. If the given
4265 Initialize a new repository in the given directory. If the given
4260 directory does not exist, it will be created.
4266 directory does not exist, it will be created.
4261
4267
4262 If no directory is given, the current directory is used.
4268 If no directory is given, the current directory is used.
4263
4269
4264 It is possible to specify an ``ssh://`` URL as the destination.
4270 It is possible to specify an ``ssh://`` URL as the destination.
4265 See :hg:`help urls` for more information.
4271 See :hg:`help urls` for more information.
4266
4272
4267 Returns 0 on success.
4273 Returns 0 on success.
4268 """
4274 """
4269 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4275 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4270
4276
4271 @command('locate',
4277 @command('locate',
4272 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4278 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4273 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4279 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4274 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4280 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4275 ] + walkopts,
4281 ] + walkopts,
4276 _('[OPTION]... [PATTERN]...'))
4282 _('[OPTION]... [PATTERN]...'))
4277 def locate(ui, repo, *pats, **opts):
4283 def locate(ui, repo, *pats, **opts):
4278 """locate files matching specific patterns (DEPRECATED)
4284 """locate files matching specific patterns (DEPRECATED)
4279
4285
4280 Print files under Mercurial control in the working directory whose
4286 Print files under Mercurial control in the working directory whose
4281 names match the given patterns.
4287 names match the given patterns.
4282
4288
4283 By default, this command searches all directories in the working
4289 By default, this command searches all directories in the working
4284 directory. To search just the current directory and its
4290 directory. To search just the current directory and its
4285 subdirectories, use "--include .".
4291 subdirectories, use "--include .".
4286
4292
4287 If no patterns are given to match, this command prints the names
4293 If no patterns are given to match, this command prints the names
4288 of all files under Mercurial control in the working directory.
4294 of all files under Mercurial control in the working directory.
4289
4295
4290 If you want to feed the output of this command into the "xargs"
4296 If you want to feed the output of this command into the "xargs"
4291 command, use the -0 option to both this command and "xargs". This
4297 command, use the -0 option to both this command and "xargs". This
4292 will avoid the problem of "xargs" treating single filenames that
4298 will avoid the problem of "xargs" treating single filenames that
4293 contain whitespace as multiple filenames.
4299 contain whitespace as multiple filenames.
4294
4300
4295 See :hg:`help files` for a more versatile command.
4301 See :hg:`help files` for a more versatile command.
4296
4302
4297 Returns 0 if a match is found, 1 otherwise.
4303 Returns 0 if a match is found, 1 otherwise.
4298 """
4304 """
4299 end = opts.get('print0') and '\0' or '\n'
4305 end = opts.get('print0') and '\0' or '\n'
4300 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4306 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4301
4307
4302 ret = 1
4308 ret = 1
4303 ctx = repo[rev]
4309 ctx = repo[rev]
4304 m = scmutil.match(ctx, pats, opts, default='relglob')
4310 m = scmutil.match(ctx, pats, opts, default='relglob')
4305 m.bad = lambda x, y: False
4311 m.bad = lambda x, y: False
4306
4312
4307 for abs in ctx.matches(m):
4313 for abs in ctx.matches(m):
4308 if opts.get('fullpath'):
4314 if opts.get('fullpath'):
4309 ui.write(repo.wjoin(abs), end)
4315 ui.write(repo.wjoin(abs), end)
4310 else:
4316 else:
4311 ui.write(((pats and m.rel(abs)) or abs), end)
4317 ui.write(((pats and m.rel(abs)) or abs), end)
4312 ret = 0
4318 ret = 0
4313
4319
4314 return ret
4320 return ret
4315
4321
4316 @command('^log|history',
4322 @command('^log|history',
4317 [('f', 'follow', None,
4323 [('f', 'follow', None,
4318 _('follow changeset history, or file history across copies and renames')),
4324 _('follow changeset history, or file history across copies and renames')),
4319 ('', 'follow-first', None,
4325 ('', 'follow-first', None,
4320 _('only follow the first parent of merge changesets (DEPRECATED)')),
4326 _('only follow the first parent of merge changesets (DEPRECATED)')),
4321 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4327 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4322 ('C', 'copies', None, _('show copied files')),
4328 ('C', 'copies', None, _('show copied files')),
4323 ('k', 'keyword', [],
4329 ('k', 'keyword', [],
4324 _('do case-insensitive search for a given text'), _('TEXT')),
4330 _('do case-insensitive search for a given text'), _('TEXT')),
4325 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4331 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4326 ('', 'removed', None, _('include revisions where files were removed')),
4332 ('', 'removed', None, _('include revisions where files were removed')),
4327 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4333 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4328 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4334 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4329 ('', 'only-branch', [],
4335 ('', 'only-branch', [],
4330 _('show only changesets within the given named branch (DEPRECATED)'),
4336 _('show only changesets within the given named branch (DEPRECATED)'),
4331 _('BRANCH')),
4337 _('BRANCH')),
4332 ('b', 'branch', [],
4338 ('b', 'branch', [],
4333 _('show changesets within the given named branch'), _('BRANCH')),
4339 _('show changesets within the given named branch'), _('BRANCH')),
4334 ('P', 'prune', [],
4340 ('P', 'prune', [],
4335 _('do not display revision or any of its ancestors'), _('REV')),
4341 _('do not display revision or any of its ancestors'), _('REV')),
4336 ] + logopts + walkopts,
4342 ] + logopts + walkopts,
4337 _('[OPTION]... [FILE]'),
4343 _('[OPTION]... [FILE]'),
4338 inferrepo=True)
4344 inferrepo=True)
4339 def log(ui, repo, *pats, **opts):
4345 def log(ui, repo, *pats, **opts):
4340 """show revision history of entire repository or files
4346 """show revision history of entire repository or files
4341
4347
4342 Print the revision history of the specified files or the entire
4348 Print the revision history of the specified files or the entire
4343 project.
4349 project.
4344
4350
4345 If no revision range is specified, the default is ``tip:0`` unless
4351 If no revision range is specified, the default is ``tip:0`` unless
4346 --follow is set, in which case the working directory parent is
4352 --follow is set, in which case the working directory parent is
4347 used as the starting revision.
4353 used as the starting revision.
4348
4354
4349 File history is shown without following rename or copy history of
4355 File history is shown without following rename or copy history of
4350 files. Use -f/--follow with a filename to follow history across
4356 files. Use -f/--follow with a filename to follow history across
4351 renames and copies. --follow without a filename will only show
4357 renames and copies. --follow without a filename will only show
4352 ancestors or descendants of the starting revision.
4358 ancestors or descendants of the starting revision.
4353
4359
4354 By default this command prints revision number and changeset id,
4360 By default this command prints revision number and changeset id,
4355 tags, non-trivial parents, user, date and time, and a summary for
4361 tags, non-trivial parents, user, date and time, and a summary for
4356 each commit. When the -v/--verbose switch is used, the list of
4362 each commit. When the -v/--verbose switch is used, the list of
4357 changed files and full commit message are shown.
4363 changed files and full commit message are shown.
4358
4364
4359 With --graph the revisions are shown as an ASCII art DAG with the most
4365 With --graph the revisions are shown as an ASCII art DAG with the most
4360 recent changeset at the top.
4366 recent changeset at the top.
4361 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4367 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4362 and '+' represents a fork where the changeset from the lines below is a
4368 and '+' represents a fork where the changeset from the lines below is a
4363 parent of the 'o' merge on the same line.
4369 parent of the 'o' merge on the same line.
4364
4370
4365 .. note::
4371 .. note::
4366
4372
4367 log -p/--patch may generate unexpected diff output for merge
4373 log -p/--patch may generate unexpected diff output for merge
4368 changesets, as it will only compare the merge changeset against
4374 changesets, as it will only compare the merge changeset against
4369 its first parent. Also, only files different from BOTH parents
4375 its first parent. Also, only files different from BOTH parents
4370 will appear in files:.
4376 will appear in files:.
4371
4377
4372 .. note::
4378 .. note::
4373
4379
4374 for performance reasons, log FILE may omit duplicate changes
4380 for performance reasons, log FILE may omit duplicate changes
4375 made on branches and will not show removals or mode changes. To
4381 made on branches and will not show removals or mode changes. To
4376 see all such changes, use the --removed switch.
4382 see all such changes, use the --removed switch.
4377
4383
4378 .. container:: verbose
4384 .. container:: verbose
4379
4385
4380 Some examples:
4386 Some examples:
4381
4387
4382 - changesets with full descriptions and file lists::
4388 - changesets with full descriptions and file lists::
4383
4389
4384 hg log -v
4390 hg log -v
4385
4391
4386 - changesets ancestral to the working directory::
4392 - changesets ancestral to the working directory::
4387
4393
4388 hg log -f
4394 hg log -f
4389
4395
4390 - last 10 commits on the current branch::
4396 - last 10 commits on the current branch::
4391
4397
4392 hg log -l 10 -b .
4398 hg log -l 10 -b .
4393
4399
4394 - changesets showing all modifications of a file, including removals::
4400 - changesets showing all modifications of a file, including removals::
4395
4401
4396 hg log --removed file.c
4402 hg log --removed file.c
4397
4403
4398 - all changesets that touch a directory, with diffs, excluding merges::
4404 - all changesets that touch a directory, with diffs, excluding merges::
4399
4405
4400 hg log -Mp lib/
4406 hg log -Mp lib/
4401
4407
4402 - all revision numbers that match a keyword::
4408 - all revision numbers that match a keyword::
4403
4409
4404 hg log -k bug --template "{rev}\\n"
4410 hg log -k bug --template "{rev}\\n"
4405
4411
4406 - list available log templates::
4412 - list available log templates::
4407
4413
4408 hg log -T list
4414 hg log -T list
4409
4415
4410 - check if a given changeset is included in a tagged release::
4416 - check if a given changeset is included in a tagged release::
4411
4417
4412 hg log -r "a21ccf and ancestor(1.9)"
4418 hg log -r "a21ccf and ancestor(1.9)"
4413
4419
4414 - find all changesets by some user in a date range::
4420 - find all changesets by some user in a date range::
4415
4421
4416 hg log -k alice -d "may 2008 to jul 2008"
4422 hg log -k alice -d "may 2008 to jul 2008"
4417
4423
4418 - summary of all changesets after the last tag::
4424 - summary of all changesets after the last tag::
4419
4425
4420 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4426 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4421
4427
4422 See :hg:`help dates` for a list of formats valid for -d/--date.
4428 See :hg:`help dates` for a list of formats valid for -d/--date.
4423
4429
4424 See :hg:`help revisions` and :hg:`help revsets` for more about
4430 See :hg:`help revisions` and :hg:`help revsets` for more about
4425 specifying revisions.
4431 specifying revisions.
4426
4432
4427 See :hg:`help templates` for more about pre-packaged styles and
4433 See :hg:`help templates` for more about pre-packaged styles and
4428 specifying custom templates.
4434 specifying custom templates.
4429
4435
4430 Returns 0 on success.
4436 Returns 0 on success.
4431
4437
4432 """
4438 """
4433 if opts.get('graph'):
4439 if opts.get('graph'):
4434 return cmdutil.graphlog(ui, repo, *pats, **opts)
4440 return cmdutil.graphlog(ui, repo, *pats, **opts)
4435
4441
4436 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4442 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4437 limit = cmdutil.loglimit(opts)
4443 limit = cmdutil.loglimit(opts)
4438 count = 0
4444 count = 0
4439
4445
4440 getrenamed = None
4446 getrenamed = None
4441 if opts.get('copies'):
4447 if opts.get('copies'):
4442 endrev = None
4448 endrev = None
4443 if opts.get('rev'):
4449 if opts.get('rev'):
4444 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4450 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4445 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4451 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4446
4452
4447 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4453 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4448 for rev in revs:
4454 for rev in revs:
4449 if count == limit:
4455 if count == limit:
4450 break
4456 break
4451 ctx = repo[rev]
4457 ctx = repo[rev]
4452 copies = None
4458 copies = None
4453 if getrenamed is not None and rev:
4459 if getrenamed is not None and rev:
4454 copies = []
4460 copies = []
4455 for fn in ctx.files():
4461 for fn in ctx.files():
4456 rename = getrenamed(fn, rev)
4462 rename = getrenamed(fn, rev)
4457 if rename:
4463 if rename:
4458 copies.append((fn, rename[0]))
4464 copies.append((fn, rename[0]))
4459 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4465 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4460 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4466 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4461 if displayer.flush(rev):
4467 if displayer.flush(rev):
4462 count += 1
4468 count += 1
4463
4469
4464 displayer.close()
4470 displayer.close()
4465
4471
4466 @command('manifest',
4472 @command('manifest',
4467 [('r', 'rev', '', _('revision to display'), _('REV')),
4473 [('r', 'rev', '', _('revision to display'), _('REV')),
4468 ('', 'all', False, _("list files from all revisions"))]
4474 ('', 'all', False, _("list files from all revisions"))]
4469 + formatteropts,
4475 + formatteropts,
4470 _('[-r REV]'))
4476 _('[-r REV]'))
4471 def manifest(ui, repo, node=None, rev=None, **opts):
4477 def manifest(ui, repo, node=None, rev=None, **opts):
4472 """output the current or given revision of the project manifest
4478 """output the current or given revision of the project manifest
4473
4479
4474 Print a list of version controlled files for the given revision.
4480 Print a list of version controlled files for the given revision.
4475 If no revision is given, the first parent of the working directory
4481 If no revision is given, the first parent of the working directory
4476 is used, or the null revision if no revision is checked out.
4482 is used, or the null revision if no revision is checked out.
4477
4483
4478 With -v, print file permissions, symlink and executable bits.
4484 With -v, print file permissions, symlink and executable bits.
4479 With --debug, print file revision hashes.
4485 With --debug, print file revision hashes.
4480
4486
4481 If option --all is specified, the list of all files from all revisions
4487 If option --all is specified, the list of all files from all revisions
4482 is printed. This includes deleted and renamed files.
4488 is printed. This includes deleted and renamed files.
4483
4489
4484 Returns 0 on success.
4490 Returns 0 on success.
4485 """
4491 """
4486
4492
4487 fm = ui.formatter('manifest', opts)
4493 fm = ui.formatter('manifest', opts)
4488
4494
4489 if opts.get('all'):
4495 if opts.get('all'):
4490 if rev or node:
4496 if rev or node:
4491 raise util.Abort(_("can't specify a revision with --all"))
4497 raise util.Abort(_("can't specify a revision with --all"))
4492
4498
4493 res = []
4499 res = []
4494 prefix = "data/"
4500 prefix = "data/"
4495 suffix = ".i"
4501 suffix = ".i"
4496 plen = len(prefix)
4502 plen = len(prefix)
4497 slen = len(suffix)
4503 slen = len(suffix)
4498 lock = repo.lock()
4504 lock = repo.lock()
4499 try:
4505 try:
4500 for fn, b, size in repo.store.datafiles():
4506 for fn, b, size in repo.store.datafiles():
4501 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4507 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4502 res.append(fn[plen:-slen])
4508 res.append(fn[plen:-slen])
4503 finally:
4509 finally:
4504 lock.release()
4510 lock.release()
4505 for f in res:
4511 for f in res:
4506 fm.startitem()
4512 fm.startitem()
4507 fm.write("path", '%s\n', f)
4513 fm.write("path", '%s\n', f)
4508 fm.end()
4514 fm.end()
4509 return
4515 return
4510
4516
4511 if rev and node:
4517 if rev and node:
4512 raise util.Abort(_("please specify just one revision"))
4518 raise util.Abort(_("please specify just one revision"))
4513
4519
4514 if not node:
4520 if not node:
4515 node = rev
4521 node = rev
4516
4522
4517 char = {'l': '@', 'x': '*', '': ''}
4523 char = {'l': '@', 'x': '*', '': ''}
4518 mode = {'l': '644', 'x': '755', '': '644'}
4524 mode = {'l': '644', 'x': '755', '': '644'}
4519 ctx = scmutil.revsingle(repo, node)
4525 ctx = scmutil.revsingle(repo, node)
4520 mf = ctx.manifest()
4526 mf = ctx.manifest()
4521 for f in ctx:
4527 for f in ctx:
4522 fm.startitem()
4528 fm.startitem()
4523 fl = ctx[f].flags()
4529 fl = ctx[f].flags()
4524 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4530 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4525 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4531 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4526 fm.write('path', '%s\n', f)
4532 fm.write('path', '%s\n', f)
4527 fm.end()
4533 fm.end()
4528
4534
4529 @command('^merge',
4535 @command('^merge',
4530 [('f', 'force', None,
4536 [('f', 'force', None,
4531 _('force a merge including outstanding changes (DEPRECATED)')),
4537 _('force a merge including outstanding changes (DEPRECATED)')),
4532 ('r', 'rev', '', _('revision to merge'), _('REV')),
4538 ('r', 'rev', '', _('revision to merge'), _('REV')),
4533 ('P', 'preview', None,
4539 ('P', 'preview', None,
4534 _('review revisions to merge (no merge is performed)'))
4540 _('review revisions to merge (no merge is performed)'))
4535 ] + mergetoolopts,
4541 ] + mergetoolopts,
4536 _('[-P] [-f] [[-r] REV]'))
4542 _('[-P] [-f] [[-r] REV]'))
4537 def merge(ui, repo, node=None, **opts):
4543 def merge(ui, repo, node=None, **opts):
4538 """merge working directory with another revision
4544 """merge working directory with another revision
4539
4545
4540 The current working directory is updated with all changes made in
4546 The current working directory is updated with all changes made in
4541 the requested revision since the last common predecessor revision.
4547 the requested revision since the last common predecessor revision.
4542
4548
4543 Files that changed between either parent are marked as changed for
4549 Files that changed between either parent are marked as changed for
4544 the next commit and a commit must be performed before any further
4550 the next commit and a commit must be performed before any further
4545 updates to the repository are allowed. The next commit will have
4551 updates to the repository are allowed. The next commit will have
4546 two parents.
4552 two parents.
4547
4553
4548 ``--tool`` can be used to specify the merge tool used for file
4554 ``--tool`` can be used to specify the merge tool used for file
4549 merges. It overrides the HGMERGE environment variable and your
4555 merges. It overrides the HGMERGE environment variable and your
4550 configuration files. See :hg:`help merge-tools` for options.
4556 configuration files. See :hg:`help merge-tools` for options.
4551
4557
4552 If no revision is specified, the working directory's parent is a
4558 If no revision is specified, the working directory's parent is a
4553 head revision, and the current branch contains exactly one other
4559 head revision, and the current branch contains exactly one other
4554 head, the other head is merged with by default. Otherwise, an
4560 head, the other head is merged with by default. Otherwise, an
4555 explicit revision with which to merge with must be provided.
4561 explicit revision with which to merge with must be provided.
4556
4562
4557 :hg:`resolve` must be used to resolve unresolved files.
4563 :hg:`resolve` must be used to resolve unresolved files.
4558
4564
4559 To undo an uncommitted merge, use :hg:`update --clean .` which
4565 To undo an uncommitted merge, use :hg:`update --clean .` which
4560 will check out a clean copy of the original merge parent, losing
4566 will check out a clean copy of the original merge parent, losing
4561 all changes.
4567 all changes.
4562
4568
4563 Returns 0 on success, 1 if there are unresolved files.
4569 Returns 0 on success, 1 if there are unresolved files.
4564 """
4570 """
4565
4571
4566 if opts.get('rev') and node:
4572 if opts.get('rev') and node:
4567 raise util.Abort(_("please specify just one revision"))
4573 raise util.Abort(_("please specify just one revision"))
4568 if not node:
4574 if not node:
4569 node = opts.get('rev')
4575 node = opts.get('rev')
4570
4576
4571 if node:
4577 if node:
4572 node = scmutil.revsingle(repo, node).node()
4578 node = scmutil.revsingle(repo, node).node()
4573
4579
4574 if not node and repo._bookmarkcurrent:
4580 if not node and repo._bookmarkcurrent:
4575 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4581 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4576 curhead = repo[repo._bookmarkcurrent].node()
4582 curhead = repo[repo._bookmarkcurrent].node()
4577 if len(bmheads) == 2:
4583 if len(bmheads) == 2:
4578 if curhead == bmheads[0]:
4584 if curhead == bmheads[0]:
4579 node = bmheads[1]
4585 node = bmheads[1]
4580 else:
4586 else:
4581 node = bmheads[0]
4587 node = bmheads[0]
4582 elif len(bmheads) > 2:
4588 elif len(bmheads) > 2:
4583 raise util.Abort(_("multiple matching bookmarks to merge - "
4589 raise util.Abort(_("multiple matching bookmarks to merge - "
4584 "please merge with an explicit rev or bookmark"),
4590 "please merge with an explicit rev or bookmark"),
4585 hint=_("run 'hg heads' to see all heads"))
4591 hint=_("run 'hg heads' to see all heads"))
4586 elif len(bmheads) <= 1:
4592 elif len(bmheads) <= 1:
4587 raise util.Abort(_("no matching bookmark to merge - "
4593 raise util.Abort(_("no matching bookmark to merge - "
4588 "please merge with an explicit rev or bookmark"),
4594 "please merge with an explicit rev or bookmark"),
4589 hint=_("run 'hg heads' to see all heads"))
4595 hint=_("run 'hg heads' to see all heads"))
4590
4596
4591 if not node and not repo._bookmarkcurrent:
4597 if not node and not repo._bookmarkcurrent:
4592 branch = repo[None].branch()
4598 branch = repo[None].branch()
4593 bheads = repo.branchheads(branch)
4599 bheads = repo.branchheads(branch)
4594 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4600 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4595
4601
4596 if len(nbhs) > 2:
4602 if len(nbhs) > 2:
4597 raise util.Abort(_("branch '%s' has %d heads - "
4603 raise util.Abort(_("branch '%s' has %d heads - "
4598 "please merge with an explicit rev")
4604 "please merge with an explicit rev")
4599 % (branch, len(bheads)),
4605 % (branch, len(bheads)),
4600 hint=_("run 'hg heads .' to see heads"))
4606 hint=_("run 'hg heads .' to see heads"))
4601
4607
4602 parent = repo.dirstate.p1()
4608 parent = repo.dirstate.p1()
4603 if len(nbhs) <= 1:
4609 if len(nbhs) <= 1:
4604 if len(bheads) > 1:
4610 if len(bheads) > 1:
4605 raise util.Abort(_("heads are bookmarked - "
4611 raise util.Abort(_("heads are bookmarked - "
4606 "please merge with an explicit rev"),
4612 "please merge with an explicit rev"),
4607 hint=_("run 'hg heads' to see all heads"))
4613 hint=_("run 'hg heads' to see all heads"))
4608 if len(repo.heads()) > 1:
4614 if len(repo.heads()) > 1:
4609 raise util.Abort(_("branch '%s' has one head - "
4615 raise util.Abort(_("branch '%s' has one head - "
4610 "please merge with an explicit rev")
4616 "please merge with an explicit rev")
4611 % branch,
4617 % branch,
4612 hint=_("run 'hg heads' to see all heads"))
4618 hint=_("run 'hg heads' to see all heads"))
4613 msg, hint = _('nothing to merge'), None
4619 msg, hint = _('nothing to merge'), None
4614 if parent != repo.lookup(branch):
4620 if parent != repo.lookup(branch):
4615 hint = _("use 'hg update' instead")
4621 hint = _("use 'hg update' instead")
4616 raise util.Abort(msg, hint=hint)
4622 raise util.Abort(msg, hint=hint)
4617
4623
4618 if parent not in bheads:
4624 if parent not in bheads:
4619 raise util.Abort(_('working directory not at a head revision'),
4625 raise util.Abort(_('working directory not at a head revision'),
4620 hint=_("use 'hg update' or merge with an "
4626 hint=_("use 'hg update' or merge with an "
4621 "explicit revision"))
4627 "explicit revision"))
4622 if parent == nbhs[0]:
4628 if parent == nbhs[0]:
4623 node = nbhs[-1]
4629 node = nbhs[-1]
4624 else:
4630 else:
4625 node = nbhs[0]
4631 node = nbhs[0]
4626
4632
4627 if opts.get('preview'):
4633 if opts.get('preview'):
4628 # find nodes that are ancestors of p2 but not of p1
4634 # find nodes that are ancestors of p2 but not of p1
4629 p1 = repo.lookup('.')
4635 p1 = repo.lookup('.')
4630 p2 = repo.lookup(node)
4636 p2 = repo.lookup(node)
4631 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4637 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4632
4638
4633 displayer = cmdutil.show_changeset(ui, repo, opts)
4639 displayer = cmdutil.show_changeset(ui, repo, opts)
4634 for node in nodes:
4640 for node in nodes:
4635 displayer.show(repo[node])
4641 displayer.show(repo[node])
4636 displayer.close()
4642 displayer.close()
4637 return 0
4643 return 0
4638
4644
4639 try:
4645 try:
4640 # ui.forcemerge is an internal variable, do not document
4646 # ui.forcemerge is an internal variable, do not document
4641 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4647 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4642 return hg.merge(repo, node, force=opts.get('force'))
4648 return hg.merge(repo, node, force=opts.get('force'))
4643 finally:
4649 finally:
4644 ui.setconfig('ui', 'forcemerge', '', 'merge')
4650 ui.setconfig('ui', 'forcemerge', '', 'merge')
4645
4651
4646 @command('outgoing|out',
4652 @command('outgoing|out',
4647 [('f', 'force', None, _('run even when the destination is unrelated')),
4653 [('f', 'force', None, _('run even when the destination is unrelated')),
4648 ('r', 'rev', [],
4654 ('r', 'rev', [],
4649 _('a changeset intended to be included in the destination'), _('REV')),
4655 _('a changeset intended to be included in the destination'), _('REV')),
4650 ('n', 'newest-first', None, _('show newest record first')),
4656 ('n', 'newest-first', None, _('show newest record first')),
4651 ('B', 'bookmarks', False, _('compare bookmarks')),
4657 ('B', 'bookmarks', False, _('compare bookmarks')),
4652 ('b', 'branch', [], _('a specific branch you would like to push'),
4658 ('b', 'branch', [], _('a specific branch you would like to push'),
4653 _('BRANCH')),
4659 _('BRANCH')),
4654 ] + logopts + remoteopts + subrepoopts,
4660 ] + logopts + remoteopts + subrepoopts,
4655 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4661 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4656 def outgoing(ui, repo, dest=None, **opts):
4662 def outgoing(ui, repo, dest=None, **opts):
4657 """show changesets not found in the destination
4663 """show changesets not found in the destination
4658
4664
4659 Show changesets not found in the specified destination repository
4665 Show changesets not found in the specified destination repository
4660 or the default push location. These are the changesets that would
4666 or the default push location. These are the changesets that would
4661 be pushed if a push was requested.
4667 be pushed if a push was requested.
4662
4668
4663 See pull for details of valid destination formats.
4669 See pull for details of valid destination formats.
4664
4670
4665 Returns 0 if there are outgoing changes, 1 otherwise.
4671 Returns 0 if there are outgoing changes, 1 otherwise.
4666 """
4672 """
4667 if opts.get('graph'):
4673 if opts.get('graph'):
4668 cmdutil.checkunsupportedgraphflags([], opts)
4674 cmdutil.checkunsupportedgraphflags([], opts)
4669 o, other = hg._outgoing(ui, repo, dest, opts)
4675 o, other = hg._outgoing(ui, repo, dest, opts)
4670 if not o:
4676 if not o:
4671 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4677 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4672 return
4678 return
4673
4679
4674 revdag = cmdutil.graphrevs(repo, o, opts)
4680 revdag = cmdutil.graphrevs(repo, o, opts)
4675 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4681 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4676 showparents = [ctx.node() for ctx in repo[None].parents()]
4682 showparents = [ctx.node() for ctx in repo[None].parents()]
4677 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4683 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4678 graphmod.asciiedges)
4684 graphmod.asciiedges)
4679 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4685 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4680 return 0
4686 return 0
4681
4687
4682 if opts.get('bookmarks'):
4688 if opts.get('bookmarks'):
4683 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4689 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4684 dest, branches = hg.parseurl(dest, opts.get('branch'))
4690 dest, branches = hg.parseurl(dest, opts.get('branch'))
4685 other = hg.peer(repo, opts, dest)
4691 other = hg.peer(repo, opts, dest)
4686 if 'bookmarks' not in other.listkeys('namespaces'):
4692 if 'bookmarks' not in other.listkeys('namespaces'):
4687 ui.warn(_("remote doesn't support bookmarks\n"))
4693 ui.warn(_("remote doesn't support bookmarks\n"))
4688 return 0
4694 return 0
4689 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4695 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4690 return bookmarks.diff(ui, other, repo)
4696 return bookmarks.diff(ui, other, repo)
4691
4697
4692 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4698 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4693 try:
4699 try:
4694 return hg.outgoing(ui, repo, dest, opts)
4700 return hg.outgoing(ui, repo, dest, opts)
4695 finally:
4701 finally:
4696 del repo._subtoppath
4702 del repo._subtoppath
4697
4703
4698 @command('parents',
4704 @command('parents',
4699 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4705 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4700 ] + templateopts,
4706 ] + templateopts,
4701 _('[-r REV] [FILE]'),
4707 _('[-r REV] [FILE]'),
4702 inferrepo=True)
4708 inferrepo=True)
4703 def parents(ui, repo, file_=None, **opts):
4709 def parents(ui, repo, file_=None, **opts):
4704 """show the parents of the working directory or revision (DEPRECATED)
4710 """show the parents of the working directory or revision (DEPRECATED)
4705
4711
4706 Print the working directory's parent revisions. If a revision is
4712 Print the working directory's parent revisions. If a revision is
4707 given via -r/--rev, the parent of that revision will be printed.
4713 given via -r/--rev, the parent of that revision will be printed.
4708 If a file argument is given, the revision in which the file was
4714 If a file argument is given, the revision in which the file was
4709 last changed (before the working directory revision or the
4715 last changed (before the working directory revision or the
4710 argument to --rev if given) is printed.
4716 argument to --rev if given) is printed.
4711
4717
4712 See :hg:`summary` and :hg:`help revsets` for related information.
4718 See :hg:`summary` and :hg:`help revsets` for related information.
4713
4719
4714 Returns 0 on success.
4720 Returns 0 on success.
4715 """
4721 """
4716
4722
4717 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4723 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4718
4724
4719 if file_:
4725 if file_:
4720 m = scmutil.match(ctx, (file_,), opts)
4726 m = scmutil.match(ctx, (file_,), opts)
4721 if m.anypats() or len(m.files()) != 1:
4727 if m.anypats() or len(m.files()) != 1:
4722 raise util.Abort(_('can only specify an explicit filename'))
4728 raise util.Abort(_('can only specify an explicit filename'))
4723 file_ = m.files()[0]
4729 file_ = m.files()[0]
4724 filenodes = []
4730 filenodes = []
4725 for cp in ctx.parents():
4731 for cp in ctx.parents():
4726 if not cp:
4732 if not cp:
4727 continue
4733 continue
4728 try:
4734 try:
4729 filenodes.append(cp.filenode(file_))
4735 filenodes.append(cp.filenode(file_))
4730 except error.LookupError:
4736 except error.LookupError:
4731 pass
4737 pass
4732 if not filenodes:
4738 if not filenodes:
4733 raise util.Abort(_("'%s' not found in manifest!") % file_)
4739 raise util.Abort(_("'%s' not found in manifest!") % file_)
4734 p = []
4740 p = []
4735 for fn in filenodes:
4741 for fn in filenodes:
4736 fctx = repo.filectx(file_, fileid=fn)
4742 fctx = repo.filectx(file_, fileid=fn)
4737 p.append(fctx.node())
4743 p.append(fctx.node())
4738 else:
4744 else:
4739 p = [cp.node() for cp in ctx.parents()]
4745 p = [cp.node() for cp in ctx.parents()]
4740
4746
4741 displayer = cmdutil.show_changeset(ui, repo, opts)
4747 displayer = cmdutil.show_changeset(ui, repo, opts)
4742 for n in p:
4748 for n in p:
4743 if n != nullid:
4749 if n != nullid:
4744 displayer.show(repo[n])
4750 displayer.show(repo[n])
4745 displayer.close()
4751 displayer.close()
4746
4752
4747 @command('paths', [], _('[NAME]'), optionalrepo=True)
4753 @command('paths', [], _('[NAME]'), optionalrepo=True)
4748 def paths(ui, repo, search=None):
4754 def paths(ui, repo, search=None):
4749 """show aliases for remote repositories
4755 """show aliases for remote repositories
4750
4756
4751 Show definition of symbolic path name NAME. If no name is given,
4757 Show definition of symbolic path name NAME. If no name is given,
4752 show definition of all available names.
4758 show definition of all available names.
4753
4759
4754 Option -q/--quiet suppresses all output when searching for NAME
4760 Option -q/--quiet suppresses all output when searching for NAME
4755 and shows only the path names when listing all definitions.
4761 and shows only the path names when listing all definitions.
4756
4762
4757 Path names are defined in the [paths] section of your
4763 Path names are defined in the [paths] section of your
4758 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4764 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4759 repository, ``.hg/hgrc`` is used, too.
4765 repository, ``.hg/hgrc`` is used, too.
4760
4766
4761 The path names ``default`` and ``default-push`` have a special
4767 The path names ``default`` and ``default-push`` have a special
4762 meaning. When performing a push or pull operation, they are used
4768 meaning. When performing a push or pull operation, they are used
4763 as fallbacks if no location is specified on the command-line.
4769 as fallbacks if no location is specified on the command-line.
4764 When ``default-push`` is set, it will be used for push and
4770 When ``default-push`` is set, it will be used for push and
4765 ``default`` will be used for pull; otherwise ``default`` is used
4771 ``default`` will be used for pull; otherwise ``default`` is used
4766 as the fallback for both. When cloning a repository, the clone
4772 as the fallback for both. When cloning a repository, the clone
4767 source is written as ``default`` in ``.hg/hgrc``. Note that
4773 source is written as ``default`` in ``.hg/hgrc``. Note that
4768 ``default`` and ``default-push`` apply to all inbound (e.g.
4774 ``default`` and ``default-push`` apply to all inbound (e.g.
4769 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4775 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4770 :hg:`bundle`) operations.
4776 :hg:`bundle`) operations.
4771
4777
4772 See :hg:`help urls` for more information.
4778 See :hg:`help urls` for more information.
4773
4779
4774 Returns 0 on success.
4780 Returns 0 on success.
4775 """
4781 """
4776 if search:
4782 if search:
4777 for name, path in ui.configitems("paths"):
4783 for name, path in ui.configitems("paths"):
4778 if name == search:
4784 if name == search:
4779 ui.status("%s\n" % util.hidepassword(path))
4785 ui.status("%s\n" % util.hidepassword(path))
4780 return
4786 return
4781 if not ui.quiet:
4787 if not ui.quiet:
4782 ui.warn(_("not found!\n"))
4788 ui.warn(_("not found!\n"))
4783 return 1
4789 return 1
4784 else:
4790 else:
4785 for name, path in ui.configitems("paths"):
4791 for name, path in ui.configitems("paths"):
4786 if ui.quiet:
4792 if ui.quiet:
4787 ui.write("%s\n" % name)
4793 ui.write("%s\n" % name)
4788 else:
4794 else:
4789 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4795 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4790
4796
4791 @command('phase',
4797 @command('phase',
4792 [('p', 'public', False, _('set changeset phase to public')),
4798 [('p', 'public', False, _('set changeset phase to public')),
4793 ('d', 'draft', False, _('set changeset phase to draft')),
4799 ('d', 'draft', False, _('set changeset phase to draft')),
4794 ('s', 'secret', False, _('set changeset phase to secret')),
4800 ('s', 'secret', False, _('set changeset phase to secret')),
4795 ('f', 'force', False, _('allow to move boundary backward')),
4801 ('f', 'force', False, _('allow to move boundary backward')),
4796 ('r', 'rev', [], _('target revision'), _('REV')),
4802 ('r', 'rev', [], _('target revision'), _('REV')),
4797 ],
4803 ],
4798 _('[-p|-d|-s] [-f] [-r] REV...'))
4804 _('[-p|-d|-s] [-f] [-r] REV...'))
4799 def phase(ui, repo, *revs, **opts):
4805 def phase(ui, repo, *revs, **opts):
4800 """set or show the current phase name
4806 """set or show the current phase name
4801
4807
4802 With no argument, show the phase name of specified revisions.
4808 With no argument, show the phase name of specified revisions.
4803
4809
4804 With one of -p/--public, -d/--draft or -s/--secret, change the
4810 With one of -p/--public, -d/--draft or -s/--secret, change the
4805 phase value of the specified revisions.
4811 phase value of the specified revisions.
4806
4812
4807 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4813 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4808 lower phase to an higher phase. Phases are ordered as follows::
4814 lower phase to an higher phase. Phases are ordered as follows::
4809
4815
4810 public < draft < secret
4816 public < draft < secret
4811
4817
4812 Returns 0 on success, 1 if no phases were changed or some could not
4818 Returns 0 on success, 1 if no phases were changed or some could not
4813 be changed.
4819 be changed.
4814 """
4820 """
4815 # search for a unique phase argument
4821 # search for a unique phase argument
4816 targetphase = None
4822 targetphase = None
4817 for idx, name in enumerate(phases.phasenames):
4823 for idx, name in enumerate(phases.phasenames):
4818 if opts[name]:
4824 if opts[name]:
4819 if targetphase is not None:
4825 if targetphase is not None:
4820 raise util.Abort(_('only one phase can be specified'))
4826 raise util.Abort(_('only one phase can be specified'))
4821 targetphase = idx
4827 targetphase = idx
4822
4828
4823 # look for specified revision
4829 # look for specified revision
4824 revs = list(revs)
4830 revs = list(revs)
4825 revs.extend(opts['rev'])
4831 revs.extend(opts['rev'])
4826 if not revs:
4832 if not revs:
4827 raise util.Abort(_('no revisions specified'))
4833 raise util.Abort(_('no revisions specified'))
4828
4834
4829 revs = scmutil.revrange(repo, revs)
4835 revs = scmutil.revrange(repo, revs)
4830
4836
4831 lock = None
4837 lock = None
4832 ret = 0
4838 ret = 0
4833 if targetphase is None:
4839 if targetphase is None:
4834 # display
4840 # display
4835 for r in revs:
4841 for r in revs:
4836 ctx = repo[r]
4842 ctx = repo[r]
4837 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4843 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4838 else:
4844 else:
4839 tr = None
4845 tr = None
4840 lock = repo.lock()
4846 lock = repo.lock()
4841 try:
4847 try:
4842 tr = repo.transaction("phase")
4848 tr = repo.transaction("phase")
4843 # set phase
4849 # set phase
4844 if not revs:
4850 if not revs:
4845 raise util.Abort(_('empty revision set'))
4851 raise util.Abort(_('empty revision set'))
4846 nodes = [repo[r].node() for r in revs]
4852 nodes = [repo[r].node() for r in revs]
4847 olddata = repo._phasecache.getphaserevs(repo)[:]
4853 olddata = repo._phasecache.getphaserevs(repo)[:]
4848 phases.advanceboundary(repo, tr, targetphase, nodes)
4854 phases.advanceboundary(repo, tr, targetphase, nodes)
4849 if opts['force']:
4855 if opts['force']:
4850 phases.retractboundary(repo, tr, targetphase, nodes)
4856 phases.retractboundary(repo, tr, targetphase, nodes)
4851 tr.close()
4857 tr.close()
4852 finally:
4858 finally:
4853 if tr is not None:
4859 if tr is not None:
4854 tr.release()
4860 tr.release()
4855 lock.release()
4861 lock.release()
4856 # moving revision from public to draft may hide them
4862 # moving revision from public to draft may hide them
4857 # We have to check result on an unfiltered repository
4863 # We have to check result on an unfiltered repository
4858 unfi = repo.unfiltered()
4864 unfi = repo.unfiltered()
4859 newdata = repo._phasecache.getphaserevs(unfi)
4865 newdata = repo._phasecache.getphaserevs(unfi)
4860 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4866 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4861 cl = unfi.changelog
4867 cl = unfi.changelog
4862 rejected = [n for n in nodes
4868 rejected = [n for n in nodes
4863 if newdata[cl.rev(n)] < targetphase]
4869 if newdata[cl.rev(n)] < targetphase]
4864 if rejected:
4870 if rejected:
4865 ui.warn(_('cannot move %i changesets to a higher '
4871 ui.warn(_('cannot move %i changesets to a higher '
4866 'phase, use --force\n') % len(rejected))
4872 'phase, use --force\n') % len(rejected))
4867 ret = 1
4873 ret = 1
4868 if changes:
4874 if changes:
4869 msg = _('phase changed for %i changesets\n') % changes
4875 msg = _('phase changed for %i changesets\n') % changes
4870 if ret:
4876 if ret:
4871 ui.status(msg)
4877 ui.status(msg)
4872 else:
4878 else:
4873 ui.note(msg)
4879 ui.note(msg)
4874 else:
4880 else:
4875 ui.warn(_('no phases changed\n'))
4881 ui.warn(_('no phases changed\n'))
4876 ret = 1
4882 ret = 1
4877 return ret
4883 return ret
4878
4884
4879 def postincoming(ui, repo, modheads, optupdate, checkout):
4885 def postincoming(ui, repo, modheads, optupdate, checkout):
4880 if modheads == 0:
4886 if modheads == 0:
4881 return
4887 return
4882 if optupdate:
4888 if optupdate:
4883 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4889 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4884 try:
4890 try:
4885 ret = hg.update(repo, checkout)
4891 ret = hg.update(repo, checkout)
4886 except util.Abort, inst:
4892 except util.Abort, inst:
4887 ui.warn(_("not updating: %s\n") % str(inst))
4893 ui.warn(_("not updating: %s\n") % str(inst))
4888 if inst.hint:
4894 if inst.hint:
4889 ui.warn(_("(%s)\n") % inst.hint)
4895 ui.warn(_("(%s)\n") % inst.hint)
4890 return 0
4896 return 0
4891 if not ret and not checkout:
4897 if not ret and not checkout:
4892 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4898 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4893 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4899 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4894 return ret
4900 return ret
4895 if modheads > 1:
4901 if modheads > 1:
4896 currentbranchheads = len(repo.branchheads())
4902 currentbranchheads = len(repo.branchheads())
4897 if currentbranchheads == modheads:
4903 if currentbranchheads == modheads:
4898 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4904 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4899 elif currentbranchheads > 1:
4905 elif currentbranchheads > 1:
4900 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4906 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4901 "merge)\n"))
4907 "merge)\n"))
4902 else:
4908 else:
4903 ui.status(_("(run 'hg heads' to see heads)\n"))
4909 ui.status(_("(run 'hg heads' to see heads)\n"))
4904 else:
4910 else:
4905 ui.status(_("(run 'hg update' to get a working copy)\n"))
4911 ui.status(_("(run 'hg update' to get a working copy)\n"))
4906
4912
4907 @command('^pull',
4913 @command('^pull',
4908 [('u', 'update', None,
4914 [('u', 'update', None,
4909 _('update to new branch head if changesets were pulled')),
4915 _('update to new branch head if changesets were pulled')),
4910 ('f', 'force', None, _('run even when remote repository is unrelated')),
4916 ('f', 'force', None, _('run even when remote repository is unrelated')),
4911 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4917 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4912 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4918 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4913 ('b', 'branch', [], _('a specific branch you would like to pull'),
4919 ('b', 'branch', [], _('a specific branch you would like to pull'),
4914 _('BRANCH')),
4920 _('BRANCH')),
4915 ] + remoteopts,
4921 ] + remoteopts,
4916 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4922 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4917 def pull(ui, repo, source="default", **opts):
4923 def pull(ui, repo, source="default", **opts):
4918 """pull changes from the specified source
4924 """pull changes from the specified source
4919
4925
4920 Pull changes from a remote repository to a local one.
4926 Pull changes from a remote repository to a local one.
4921
4927
4922 This finds all changes from the repository at the specified path
4928 This finds all changes from the repository at the specified path
4923 or URL and adds them to a local repository (the current one unless
4929 or URL and adds them to a local repository (the current one unless
4924 -R is specified). By default, this does not update the copy of the
4930 -R is specified). By default, this does not update the copy of the
4925 project in the working directory.
4931 project in the working directory.
4926
4932
4927 Use :hg:`incoming` if you want to see what would have been added
4933 Use :hg:`incoming` if you want to see what would have been added
4928 by a pull at the time you issued this command. If you then decide
4934 by a pull at the time you issued this command. If you then decide
4929 to add those changes to the repository, you should use :hg:`pull
4935 to add those changes to the repository, you should use :hg:`pull
4930 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4936 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4931
4937
4932 If SOURCE is omitted, the 'default' path will be used.
4938 If SOURCE is omitted, the 'default' path will be used.
4933 See :hg:`help urls` for more information.
4939 See :hg:`help urls` for more information.
4934
4940
4935 Returns 0 on success, 1 if an update had unresolved files.
4941 Returns 0 on success, 1 if an update had unresolved files.
4936 """
4942 """
4937 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4943 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4938 other = hg.peer(repo, opts, source)
4944 other = hg.peer(repo, opts, source)
4939 try:
4945 try:
4940 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4946 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4941 revs, checkout = hg.addbranchrevs(repo, other, branches,
4947 revs, checkout = hg.addbranchrevs(repo, other, branches,
4942 opts.get('rev'))
4948 opts.get('rev'))
4943
4949
4944 remotebookmarks = other.listkeys('bookmarks')
4950 remotebookmarks = other.listkeys('bookmarks')
4945
4951
4946 if opts.get('bookmark'):
4952 if opts.get('bookmark'):
4947 if not revs:
4953 if not revs:
4948 revs = []
4954 revs = []
4949 for b in opts['bookmark']:
4955 for b in opts['bookmark']:
4950 if b not in remotebookmarks:
4956 if b not in remotebookmarks:
4951 raise util.Abort(_('remote bookmark %s not found!') % b)
4957 raise util.Abort(_('remote bookmark %s not found!') % b)
4952 revs.append(remotebookmarks[b])
4958 revs.append(remotebookmarks[b])
4953
4959
4954 if revs:
4960 if revs:
4955 try:
4961 try:
4956 revs = [other.lookup(rev) for rev in revs]
4962 revs = [other.lookup(rev) for rev in revs]
4957 except error.CapabilityError:
4963 except error.CapabilityError:
4958 err = _("other repository doesn't support revision lookup, "
4964 err = _("other repository doesn't support revision lookup, "
4959 "so a rev cannot be specified.")
4965 "so a rev cannot be specified.")
4960 raise util.Abort(err)
4966 raise util.Abort(err)
4961
4967
4962 modheads = exchange.pull(repo, other, heads=revs,
4968 modheads = exchange.pull(repo, other, heads=revs,
4963 force=opts.get('force'),
4969 force=opts.get('force'),
4964 bookmarks=opts.get('bookmark', ())).cgresult
4970 bookmarks=opts.get('bookmark', ())).cgresult
4965 if checkout:
4971 if checkout:
4966 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4972 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4967 repo._subtoppath = source
4973 repo._subtoppath = source
4968 try:
4974 try:
4969 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4975 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4970
4976
4971 finally:
4977 finally:
4972 del repo._subtoppath
4978 del repo._subtoppath
4973
4979
4974 finally:
4980 finally:
4975 other.close()
4981 other.close()
4976 return ret
4982 return ret
4977
4983
4978 @command('^push',
4984 @command('^push',
4979 [('f', 'force', None, _('force push')),
4985 [('f', 'force', None, _('force push')),
4980 ('r', 'rev', [],
4986 ('r', 'rev', [],
4981 _('a changeset intended to be included in the destination'),
4987 _('a changeset intended to be included in the destination'),
4982 _('REV')),
4988 _('REV')),
4983 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4989 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4984 ('b', 'branch', [],
4990 ('b', 'branch', [],
4985 _('a specific branch you would like to push'), _('BRANCH')),
4991 _('a specific branch you would like to push'), _('BRANCH')),
4986 ('', 'new-branch', False, _('allow pushing a new branch')),
4992 ('', 'new-branch', False, _('allow pushing a new branch')),
4987 ] + remoteopts,
4993 ] + remoteopts,
4988 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4994 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4989 def push(ui, repo, dest=None, **opts):
4995 def push(ui, repo, dest=None, **opts):
4990 """push changes to the specified destination
4996 """push changes to the specified destination
4991
4997
4992 Push changesets from the local repository to the specified
4998 Push changesets from the local repository to the specified
4993 destination.
4999 destination.
4994
5000
4995 This operation is symmetrical to pull: it is identical to a pull
5001 This operation is symmetrical to pull: it is identical to a pull
4996 in the destination repository from the current one.
5002 in the destination repository from the current one.
4997
5003
4998 By default, push will not allow creation of new heads at the
5004 By default, push will not allow creation of new heads at the
4999 destination, since multiple heads would make it unclear which head
5005 destination, since multiple heads would make it unclear which head
5000 to use. In this situation, it is recommended to pull and merge
5006 to use. In this situation, it is recommended to pull and merge
5001 before pushing.
5007 before pushing.
5002
5008
5003 Use --new-branch if you want to allow push to create a new named
5009 Use --new-branch if you want to allow push to create a new named
5004 branch that is not present at the destination. This allows you to
5010 branch that is not present at the destination. This allows you to
5005 only create a new branch without forcing other changes.
5011 only create a new branch without forcing other changes.
5006
5012
5007 .. note::
5013 .. note::
5008
5014
5009 Extra care should be taken with the -f/--force option,
5015 Extra care should be taken with the -f/--force option,
5010 which will push all new heads on all branches, an action which will
5016 which will push all new heads on all branches, an action which will
5011 almost always cause confusion for collaborators.
5017 almost always cause confusion for collaborators.
5012
5018
5013 If -r/--rev is used, the specified revision and all its ancestors
5019 If -r/--rev is used, the specified revision and all its ancestors
5014 will be pushed to the remote repository.
5020 will be pushed to the remote repository.
5015
5021
5016 If -B/--bookmark is used, the specified bookmarked revision, its
5022 If -B/--bookmark is used, the specified bookmarked revision, its
5017 ancestors, and the bookmark will be pushed to the remote
5023 ancestors, and the bookmark will be pushed to the remote
5018 repository.
5024 repository.
5019
5025
5020 Please see :hg:`help urls` for important details about ``ssh://``
5026 Please see :hg:`help urls` for important details about ``ssh://``
5021 URLs. If DESTINATION is omitted, a default path will be used.
5027 URLs. If DESTINATION is omitted, a default path will be used.
5022
5028
5023 Returns 0 if push was successful, 1 if nothing to push.
5029 Returns 0 if push was successful, 1 if nothing to push.
5024 """
5030 """
5025
5031
5026 if opts.get('bookmark'):
5032 if opts.get('bookmark'):
5027 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5033 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5028 for b in opts['bookmark']:
5034 for b in opts['bookmark']:
5029 # translate -B options to -r so changesets get pushed
5035 # translate -B options to -r so changesets get pushed
5030 if b in repo._bookmarks:
5036 if b in repo._bookmarks:
5031 opts.setdefault('rev', []).append(b)
5037 opts.setdefault('rev', []).append(b)
5032 else:
5038 else:
5033 # if we try to push a deleted bookmark, translate it to null
5039 # if we try to push a deleted bookmark, translate it to null
5034 # this lets simultaneous -r, -b options continue working
5040 # this lets simultaneous -r, -b options continue working
5035 opts.setdefault('rev', []).append("null")
5041 opts.setdefault('rev', []).append("null")
5036
5042
5037 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5043 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5038 dest, branches = hg.parseurl(dest, opts.get('branch'))
5044 dest, branches = hg.parseurl(dest, opts.get('branch'))
5039 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5045 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5040 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5046 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5041 try:
5047 try:
5042 other = hg.peer(repo, opts, dest)
5048 other = hg.peer(repo, opts, dest)
5043 except error.RepoError:
5049 except error.RepoError:
5044 if dest == "default-push":
5050 if dest == "default-push":
5045 raise util.Abort(_("default repository not configured!"),
5051 raise util.Abort(_("default repository not configured!"),
5046 hint=_('see the "path" section in "hg help config"'))
5052 hint=_('see the "path" section in "hg help config"'))
5047 else:
5053 else:
5048 raise
5054 raise
5049
5055
5050 if revs:
5056 if revs:
5051 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5057 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5052
5058
5053 repo._subtoppath = dest
5059 repo._subtoppath = dest
5054 try:
5060 try:
5055 # push subrepos depth-first for coherent ordering
5061 # push subrepos depth-first for coherent ordering
5056 c = repo['']
5062 c = repo['']
5057 subs = c.substate # only repos that are committed
5063 subs = c.substate # only repos that are committed
5058 for s in sorted(subs):
5064 for s in sorted(subs):
5059 result = c.sub(s).push(opts)
5065 result = c.sub(s).push(opts)
5060 if result == 0:
5066 if result == 0:
5061 return not result
5067 return not result
5062 finally:
5068 finally:
5063 del repo._subtoppath
5069 del repo._subtoppath
5064 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5070 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5065 newbranch=opts.get('new_branch'),
5071 newbranch=opts.get('new_branch'),
5066 bookmarks=opts.get('bookmark', ()))
5072 bookmarks=opts.get('bookmark', ()))
5067
5073
5068 result = not pushop.cgresult
5074 result = not pushop.cgresult
5069
5075
5070 if pushop.bkresult is not None:
5076 if pushop.bkresult is not None:
5071 if pushop.bkresult == 2:
5077 if pushop.bkresult == 2:
5072 result = 2
5078 result = 2
5073 elif not result and pushop.bkresult:
5079 elif not result and pushop.bkresult:
5074 result = 2
5080 result = 2
5075
5081
5076 return result
5082 return result
5077
5083
5078 @command('recover', [])
5084 @command('recover', [])
5079 def recover(ui, repo):
5085 def recover(ui, repo):
5080 """roll back an interrupted transaction
5086 """roll back an interrupted transaction
5081
5087
5082 Recover from an interrupted commit or pull.
5088 Recover from an interrupted commit or pull.
5083
5089
5084 This command tries to fix the repository status after an
5090 This command tries to fix the repository status after an
5085 interrupted operation. It should only be necessary when Mercurial
5091 interrupted operation. It should only be necessary when Mercurial
5086 suggests it.
5092 suggests it.
5087
5093
5088 Returns 0 if successful, 1 if nothing to recover or verify fails.
5094 Returns 0 if successful, 1 if nothing to recover or verify fails.
5089 """
5095 """
5090 if repo.recover():
5096 if repo.recover():
5091 return hg.verify(repo)
5097 return hg.verify(repo)
5092 return 1
5098 return 1
5093
5099
5094 @command('^remove|rm',
5100 @command('^remove|rm',
5095 [('A', 'after', None, _('record delete for missing files')),
5101 [('A', 'after', None, _('record delete for missing files')),
5096 ('f', 'force', None,
5102 ('f', 'force', None,
5097 _('remove (and delete) file even if added or modified')),
5103 _('remove (and delete) file even if added or modified')),
5098 ] + walkopts,
5104 ] + walkopts,
5099 _('[OPTION]... FILE...'),
5105 _('[OPTION]... FILE...'),
5100 inferrepo=True)
5106 inferrepo=True)
5101 def remove(ui, repo, *pats, **opts):
5107 def remove(ui, repo, *pats, **opts):
5102 """remove the specified files on the next commit
5108 """remove the specified files on the next commit
5103
5109
5104 Schedule the indicated files for removal from the current branch.
5110 Schedule the indicated files for removal from the current branch.
5105
5111
5106 This command schedules the files to be removed at the next commit.
5112 This command schedules the files to be removed at the next commit.
5107 To undo a remove before that, see :hg:`revert`. To undo added
5113 To undo a remove before that, see :hg:`revert`. To undo added
5108 files, see :hg:`forget`.
5114 files, see :hg:`forget`.
5109
5115
5110 .. container:: verbose
5116 .. container:: verbose
5111
5117
5112 -A/--after can be used to remove only files that have already
5118 -A/--after can be used to remove only files that have already
5113 been deleted, -f/--force can be used to force deletion, and -Af
5119 been deleted, -f/--force can be used to force deletion, and -Af
5114 can be used to remove files from the next revision without
5120 can be used to remove files from the next revision without
5115 deleting them from the working directory.
5121 deleting them from the working directory.
5116
5122
5117 The following table details the behavior of remove for different
5123 The following table details the behavior of remove for different
5118 file states (columns) and option combinations (rows). The file
5124 file states (columns) and option combinations (rows). The file
5119 states are Added [A], Clean [C], Modified [M] and Missing [!]
5125 states are Added [A], Clean [C], Modified [M] and Missing [!]
5120 (as reported by :hg:`status`). The actions are Warn, Remove
5126 (as reported by :hg:`status`). The actions are Warn, Remove
5121 (from branch) and Delete (from disk):
5127 (from branch) and Delete (from disk):
5122
5128
5123 ========= == == == ==
5129 ========= == == == ==
5124 opt/state A C M !
5130 opt/state A C M !
5125 ========= == == == ==
5131 ========= == == == ==
5126 none W RD W R
5132 none W RD W R
5127 -f R RD RD R
5133 -f R RD RD R
5128 -A W W W R
5134 -A W W W R
5129 -Af R R R R
5135 -Af R R R R
5130 ========= == == == ==
5136 ========= == == == ==
5131
5137
5132 Note that remove never deletes files in Added [A] state from the
5138 Note that remove never deletes files in Added [A] state from the
5133 working directory, not even if option --force is specified.
5139 working directory, not even if option --force is specified.
5134
5140
5135 Returns 0 on success, 1 if any warnings encountered.
5141 Returns 0 on success, 1 if any warnings encountered.
5136 """
5142 """
5137
5143
5138 ret = 0
5144 ret = 0
5139 after, force = opts.get('after'), opts.get('force')
5145 after, force = opts.get('after'), opts.get('force')
5140 if not pats and not after:
5146 if not pats and not after:
5141 raise util.Abort(_('no files specified'))
5147 raise util.Abort(_('no files specified'))
5142
5148
5143 m = scmutil.match(repo[None], pats, opts)
5149 m = scmutil.match(repo[None], pats, opts)
5144 s = repo.status(match=m, clean=True)
5150 s = repo.status(match=m, clean=True)
5145 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5151 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5146
5152
5147 # warn about failure to delete explicit files/dirs
5153 # warn about failure to delete explicit files/dirs
5148 wctx = repo[None]
5154 wctx = repo[None]
5149 for f in m.files():
5155 for f in m.files():
5150 if f in repo.dirstate or f in wctx.dirs():
5156 if f in repo.dirstate or f in wctx.dirs():
5151 continue
5157 continue
5152 if os.path.exists(m.rel(f)):
5158 if os.path.exists(m.rel(f)):
5153 if os.path.isdir(m.rel(f)):
5159 if os.path.isdir(m.rel(f)):
5154 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5160 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5155 else:
5161 else:
5156 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5162 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5157 # missing files will generate a warning elsewhere
5163 # missing files will generate a warning elsewhere
5158 ret = 1
5164 ret = 1
5159
5165
5160 if force:
5166 if force:
5161 list = modified + deleted + clean + added
5167 list = modified + deleted + clean + added
5162 elif after:
5168 elif after:
5163 list = deleted
5169 list = deleted
5164 for f in modified + added + clean:
5170 for f in modified + added + clean:
5165 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5171 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5166 ret = 1
5172 ret = 1
5167 else:
5173 else:
5168 list = deleted + clean
5174 list = deleted + clean
5169 for f in modified:
5175 for f in modified:
5170 ui.warn(_('not removing %s: file is modified (use -f'
5176 ui.warn(_('not removing %s: file is modified (use -f'
5171 ' to force removal)\n') % m.rel(f))
5177 ' to force removal)\n') % m.rel(f))
5172 ret = 1
5178 ret = 1
5173 for f in added:
5179 for f in added:
5174 ui.warn(_('not removing %s: file has been marked for add'
5180 ui.warn(_('not removing %s: file has been marked for add'
5175 ' (use forget to undo)\n') % m.rel(f))
5181 ' (use forget to undo)\n') % m.rel(f))
5176 ret = 1
5182 ret = 1
5177
5183
5178 for f in sorted(list):
5184 for f in sorted(list):
5179 if ui.verbose or not m.exact(f):
5185 if ui.verbose or not m.exact(f):
5180 ui.status(_('removing %s\n') % m.rel(f))
5186 ui.status(_('removing %s\n') % m.rel(f))
5181
5187
5182 wlock = repo.wlock()
5188 wlock = repo.wlock()
5183 try:
5189 try:
5184 if not after:
5190 if not after:
5185 for f in list:
5191 for f in list:
5186 if f in added:
5192 if f in added:
5187 continue # we never unlink added files on remove
5193 continue # we never unlink added files on remove
5188 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5194 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5189 repo[None].forget(list)
5195 repo[None].forget(list)
5190 finally:
5196 finally:
5191 wlock.release()
5197 wlock.release()
5192
5198
5193 return ret
5199 return ret
5194
5200
5195 @command('rename|move|mv',
5201 @command('rename|move|mv',
5196 [('A', 'after', None, _('record a rename that has already occurred')),
5202 [('A', 'after', None, _('record a rename that has already occurred')),
5197 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5203 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5198 ] + walkopts + dryrunopts,
5204 ] + walkopts + dryrunopts,
5199 _('[OPTION]... SOURCE... DEST'))
5205 _('[OPTION]... SOURCE... DEST'))
5200 def rename(ui, repo, *pats, **opts):
5206 def rename(ui, repo, *pats, **opts):
5201 """rename files; equivalent of copy + remove
5207 """rename files; equivalent of copy + remove
5202
5208
5203 Mark dest as copies of sources; mark sources for deletion. If dest
5209 Mark dest as copies of sources; mark sources for deletion. If dest
5204 is a directory, copies are put in that directory. If dest is a
5210 is a directory, copies are put in that directory. If dest is a
5205 file, there can only be one source.
5211 file, there can only be one source.
5206
5212
5207 By default, this command copies the contents of files as they
5213 By default, this command copies the contents of files as they
5208 exist in the working directory. If invoked with -A/--after, the
5214 exist in the working directory. If invoked with -A/--after, the
5209 operation is recorded, but no copying is performed.
5215 operation is recorded, but no copying is performed.
5210
5216
5211 This command takes effect at the next commit. To undo a rename
5217 This command takes effect at the next commit. To undo a rename
5212 before that, see :hg:`revert`.
5218 before that, see :hg:`revert`.
5213
5219
5214 Returns 0 on success, 1 if errors are encountered.
5220 Returns 0 on success, 1 if errors are encountered.
5215 """
5221 """
5216 wlock = repo.wlock(False)
5222 wlock = repo.wlock(False)
5217 try:
5223 try:
5218 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5224 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5219 finally:
5225 finally:
5220 wlock.release()
5226 wlock.release()
5221
5227
5222 @command('resolve',
5228 @command('resolve',
5223 [('a', 'all', None, _('select all unresolved files')),
5229 [('a', 'all', None, _('select all unresolved files')),
5224 ('l', 'list', None, _('list state of files needing merge')),
5230 ('l', 'list', None, _('list state of files needing merge')),
5225 ('m', 'mark', None, _('mark files as resolved')),
5231 ('m', 'mark', None, _('mark files as resolved')),
5226 ('u', 'unmark', None, _('mark files as unresolved')),
5232 ('u', 'unmark', None, _('mark files as unresolved')),
5227 ('n', 'no-status', None, _('hide status prefix'))]
5233 ('n', 'no-status', None, _('hide status prefix'))]
5228 + mergetoolopts + walkopts,
5234 + mergetoolopts + walkopts,
5229 _('[OPTION]... [FILE]...'),
5235 _('[OPTION]... [FILE]...'),
5230 inferrepo=True)
5236 inferrepo=True)
5231 def resolve(ui, repo, *pats, **opts):
5237 def resolve(ui, repo, *pats, **opts):
5232 """redo merges or set/view the merge status of files
5238 """redo merges or set/view the merge status of files
5233
5239
5234 Merges with unresolved conflicts are often the result of
5240 Merges with unresolved conflicts are often the result of
5235 non-interactive merging using the ``internal:merge`` configuration
5241 non-interactive merging using the ``internal:merge`` configuration
5236 setting, or a command-line merge tool like ``diff3``. The resolve
5242 setting, or a command-line merge tool like ``diff3``. The resolve
5237 command is used to manage the files involved in a merge, after
5243 command is used to manage the files involved in a merge, after
5238 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5244 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5239 working directory must have two parents). See :hg:`help
5245 working directory must have two parents). See :hg:`help
5240 merge-tools` for information on configuring merge tools.
5246 merge-tools` for information on configuring merge tools.
5241
5247
5242 The resolve command can be used in the following ways:
5248 The resolve command can be used in the following ways:
5243
5249
5244 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5250 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5245 files, discarding any previous merge attempts. Re-merging is not
5251 files, discarding any previous merge attempts. Re-merging is not
5246 performed for files already marked as resolved. Use ``--all/-a``
5252 performed for files already marked as resolved. Use ``--all/-a``
5247 to select all unresolved files. ``--tool`` can be used to specify
5253 to select all unresolved files. ``--tool`` can be used to specify
5248 the merge tool used for the given files. It overrides the HGMERGE
5254 the merge tool used for the given files. It overrides the HGMERGE
5249 environment variable and your configuration files. Previous file
5255 environment variable and your configuration files. Previous file
5250 contents are saved with a ``.orig`` suffix.
5256 contents are saved with a ``.orig`` suffix.
5251
5257
5252 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5258 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5253 (e.g. after having manually fixed-up the files). The default is
5259 (e.g. after having manually fixed-up the files). The default is
5254 to mark all unresolved files.
5260 to mark all unresolved files.
5255
5261
5256 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5262 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5257 default is to mark all resolved files.
5263 default is to mark all resolved files.
5258
5264
5259 - :hg:`resolve -l`: list files which had or still have conflicts.
5265 - :hg:`resolve -l`: list files which had or still have conflicts.
5260 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5266 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5261
5267
5262 Note that Mercurial will not let you commit files with unresolved
5268 Note that Mercurial will not let you commit files with unresolved
5263 merge conflicts. You must use :hg:`resolve -m ...` before you can
5269 merge conflicts. You must use :hg:`resolve -m ...` before you can
5264 commit after a conflicting merge.
5270 commit after a conflicting merge.
5265
5271
5266 Returns 0 on success, 1 if any files fail a resolve attempt.
5272 Returns 0 on success, 1 if any files fail a resolve attempt.
5267 """
5273 """
5268
5274
5269 all, mark, unmark, show, nostatus = \
5275 all, mark, unmark, show, nostatus = \
5270 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5276 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5271
5277
5272 if (show and (mark or unmark)) or (mark and unmark):
5278 if (show and (mark or unmark)) or (mark and unmark):
5273 raise util.Abort(_("too many options specified"))
5279 raise util.Abort(_("too many options specified"))
5274 if pats and all:
5280 if pats and all:
5275 raise util.Abort(_("can't specify --all and patterns"))
5281 raise util.Abort(_("can't specify --all and patterns"))
5276 if not (all or pats or show or mark or unmark):
5282 if not (all or pats or show or mark or unmark):
5277 raise util.Abort(_('no files or directories specified'),
5283 raise util.Abort(_('no files or directories specified'),
5278 hint=('use --all to remerge all files'))
5284 hint=('use --all to remerge all files'))
5279
5285
5280 wlock = repo.wlock()
5286 wlock = repo.wlock()
5281 try:
5287 try:
5282 ms = mergemod.mergestate(repo)
5288 ms = mergemod.mergestate(repo)
5283
5289
5284 if not ms.active() and not show:
5290 if not ms.active() and not show:
5285 raise util.Abort(
5291 raise util.Abort(
5286 _('resolve command not applicable when not merging'))
5292 _('resolve command not applicable when not merging'))
5287
5293
5288 m = scmutil.match(repo[None], pats, opts)
5294 m = scmutil.match(repo[None], pats, opts)
5289 ret = 0
5295 ret = 0
5290 didwork = False
5296 didwork = False
5291
5297
5292 for f in ms:
5298 for f in ms:
5293 if not m(f):
5299 if not m(f):
5294 continue
5300 continue
5295
5301
5296 didwork = True
5302 didwork = True
5297
5303
5298 if show:
5304 if show:
5299 if nostatus:
5305 if nostatus:
5300 ui.write("%s\n" % f)
5306 ui.write("%s\n" % f)
5301 else:
5307 else:
5302 ui.write("%s %s\n" % (ms[f].upper(), f),
5308 ui.write("%s %s\n" % (ms[f].upper(), f),
5303 label='resolve.' +
5309 label='resolve.' +
5304 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5310 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5305 elif mark:
5311 elif mark:
5306 ms.mark(f, "r")
5312 ms.mark(f, "r")
5307 elif unmark:
5313 elif unmark:
5308 ms.mark(f, "u")
5314 ms.mark(f, "u")
5309 else:
5315 else:
5310 wctx = repo[None]
5316 wctx = repo[None]
5311
5317
5312 # backup pre-resolve (merge uses .orig for its own purposes)
5318 # backup pre-resolve (merge uses .orig for its own purposes)
5313 a = repo.wjoin(f)
5319 a = repo.wjoin(f)
5314 util.copyfile(a, a + ".resolve")
5320 util.copyfile(a, a + ".resolve")
5315
5321
5316 try:
5322 try:
5317 # resolve file
5323 # resolve file
5318 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5324 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5319 'resolve')
5325 'resolve')
5320 if ms.resolve(f, wctx):
5326 if ms.resolve(f, wctx):
5321 ret = 1
5327 ret = 1
5322 finally:
5328 finally:
5323 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5329 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5324 ms.commit()
5330 ms.commit()
5325
5331
5326 # replace filemerge's .orig file with our resolve file
5332 # replace filemerge's .orig file with our resolve file
5327 util.rename(a + ".resolve", a + ".orig")
5333 util.rename(a + ".resolve", a + ".orig")
5328
5334
5329 ms.commit()
5335 ms.commit()
5330
5336
5331 if not didwork and pats:
5337 if not didwork and pats:
5332 ui.warn(_("arguments do not match paths that need resolving\n"))
5338 ui.warn(_("arguments do not match paths that need resolving\n"))
5333
5339
5334 finally:
5340 finally:
5335 wlock.release()
5341 wlock.release()
5336
5342
5337 # Nudge users into finishing an unfinished operation. We don't print
5343 # Nudge users into finishing an unfinished operation. We don't print
5338 # this with the list/show operation because we want list/show to remain
5344 # this with the list/show operation because we want list/show to remain
5339 # machine readable.
5345 # machine readable.
5340 if not list(ms.unresolved()) and not show:
5346 if not list(ms.unresolved()) and not show:
5341 ui.status(_('(no more unresolved files)\n'))
5347 ui.status(_('(no more unresolved files)\n'))
5342
5348
5343 return ret
5349 return ret
5344
5350
5345 @command('revert',
5351 @command('revert',
5346 [('a', 'all', None, _('revert all changes when no arguments given')),
5352 [('a', 'all', None, _('revert all changes when no arguments given')),
5347 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5353 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5348 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5354 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5349 ('C', 'no-backup', None, _('do not save backup copies of files')),
5355 ('C', 'no-backup', None, _('do not save backup copies of files')),
5350 ] + walkopts + dryrunopts,
5356 ] + walkopts + dryrunopts,
5351 _('[OPTION]... [-r REV] [NAME]...'))
5357 _('[OPTION]... [-r REV] [NAME]...'))
5352 def revert(ui, repo, *pats, **opts):
5358 def revert(ui, repo, *pats, **opts):
5353 """restore files to their checkout state
5359 """restore files to their checkout state
5354
5360
5355 .. note::
5361 .. note::
5356
5362
5357 To check out earlier revisions, you should use :hg:`update REV`.
5363 To check out earlier revisions, you should use :hg:`update REV`.
5358 To cancel an uncommitted merge (and lose your changes),
5364 To cancel an uncommitted merge (and lose your changes),
5359 use :hg:`update --clean .`.
5365 use :hg:`update --clean .`.
5360
5366
5361 With no revision specified, revert the specified files or directories
5367 With no revision specified, revert the specified files or directories
5362 to the contents they had in the parent of the working directory.
5368 to the contents they had in the parent of the working directory.
5363 This restores the contents of files to an unmodified
5369 This restores the contents of files to an unmodified
5364 state and unschedules adds, removes, copies, and renames. If the
5370 state and unschedules adds, removes, copies, and renames. If the
5365 working directory has two parents, you must explicitly specify a
5371 working directory has two parents, you must explicitly specify a
5366 revision.
5372 revision.
5367
5373
5368 Using the -r/--rev or -d/--date options, revert the given files or
5374 Using the -r/--rev or -d/--date options, revert the given files or
5369 directories to their states as of a specific revision. Because
5375 directories to their states as of a specific revision. Because
5370 revert does not change the working directory parents, this will
5376 revert does not change the working directory parents, this will
5371 cause these files to appear modified. This can be helpful to "back
5377 cause these files to appear modified. This can be helpful to "back
5372 out" some or all of an earlier change. See :hg:`backout` for a
5378 out" some or all of an earlier change. See :hg:`backout` for a
5373 related method.
5379 related method.
5374
5380
5375 Modified files are saved with a .orig suffix before reverting.
5381 Modified files are saved with a .orig suffix before reverting.
5376 To disable these backups, use --no-backup.
5382 To disable these backups, use --no-backup.
5377
5383
5378 See :hg:`help dates` for a list of formats valid for -d/--date.
5384 See :hg:`help dates` for a list of formats valid for -d/--date.
5379
5385
5380 Returns 0 on success.
5386 Returns 0 on success.
5381 """
5387 """
5382
5388
5383 if opts.get("date"):
5389 if opts.get("date"):
5384 if opts.get("rev"):
5390 if opts.get("rev"):
5385 raise util.Abort(_("you can't specify a revision and a date"))
5391 raise util.Abort(_("you can't specify a revision and a date"))
5386 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5392 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5387
5393
5388 parent, p2 = repo.dirstate.parents()
5394 parent, p2 = repo.dirstate.parents()
5389 if not opts.get('rev') and p2 != nullid:
5395 if not opts.get('rev') and p2 != nullid:
5390 # revert after merge is a trap for new users (issue2915)
5396 # revert after merge is a trap for new users (issue2915)
5391 raise util.Abort(_('uncommitted merge with no revision specified'),
5397 raise util.Abort(_('uncommitted merge with no revision specified'),
5392 hint=_('use "hg update" or see "hg help revert"'))
5398 hint=_('use "hg update" or see "hg help revert"'))
5393
5399
5394 ctx = scmutil.revsingle(repo, opts.get('rev'))
5400 ctx = scmutil.revsingle(repo, opts.get('rev'))
5395
5401
5396 if not pats and not opts.get('all'):
5402 if not pats and not opts.get('all'):
5397 msg = _("no files or directories specified")
5403 msg = _("no files or directories specified")
5398 if p2 != nullid:
5404 if p2 != nullid:
5399 hint = _("uncommitted merge, use --all to discard all changes,"
5405 hint = _("uncommitted merge, use --all to discard all changes,"
5400 " or 'hg update -C .' to abort the merge")
5406 " or 'hg update -C .' to abort the merge")
5401 raise util.Abort(msg, hint=hint)
5407 raise util.Abort(msg, hint=hint)
5402 dirty = util.any(repo.status())
5408 dirty = util.any(repo.status())
5403 node = ctx.node()
5409 node = ctx.node()
5404 if node != parent:
5410 if node != parent:
5405 if dirty:
5411 if dirty:
5406 hint = _("uncommitted changes, use --all to discard all"
5412 hint = _("uncommitted changes, use --all to discard all"
5407 " changes, or 'hg update %s' to update") % ctx.rev()
5413 " changes, or 'hg update %s' to update") % ctx.rev()
5408 else:
5414 else:
5409 hint = _("use --all to revert all files,"
5415 hint = _("use --all to revert all files,"
5410 " or 'hg update %s' to update") % ctx.rev()
5416 " or 'hg update %s' to update") % ctx.rev()
5411 elif dirty:
5417 elif dirty:
5412 hint = _("uncommitted changes, use --all to discard all changes")
5418 hint = _("uncommitted changes, use --all to discard all changes")
5413 else:
5419 else:
5414 hint = _("use --all to revert all files")
5420 hint = _("use --all to revert all files")
5415 raise util.Abort(msg, hint=hint)
5421 raise util.Abort(msg, hint=hint)
5416
5422
5417 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5423 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5418
5424
5419 @command('rollback', dryrunopts +
5425 @command('rollback', dryrunopts +
5420 [('f', 'force', False, _('ignore safety measures'))])
5426 [('f', 'force', False, _('ignore safety measures'))])
5421 def rollback(ui, repo, **opts):
5427 def rollback(ui, repo, **opts):
5422 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5428 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5423
5429
5424 Please use :hg:`commit --amend` instead of rollback to correct
5430 Please use :hg:`commit --amend` instead of rollback to correct
5425 mistakes in the last commit.
5431 mistakes in the last commit.
5426
5432
5427 This command should be used with care. There is only one level of
5433 This command should be used with care. There is only one level of
5428 rollback, and there is no way to undo a rollback. It will also
5434 rollback, and there is no way to undo a rollback. It will also
5429 restore the dirstate at the time of the last transaction, losing
5435 restore the dirstate at the time of the last transaction, losing
5430 any dirstate changes since that time. This command does not alter
5436 any dirstate changes since that time. This command does not alter
5431 the working directory.
5437 the working directory.
5432
5438
5433 Transactions are used to encapsulate the effects of all commands
5439 Transactions are used to encapsulate the effects of all commands
5434 that create new changesets or propagate existing changesets into a
5440 that create new changesets or propagate existing changesets into a
5435 repository.
5441 repository.
5436
5442
5437 .. container:: verbose
5443 .. container:: verbose
5438
5444
5439 For example, the following commands are transactional, and their
5445 For example, the following commands are transactional, and their
5440 effects can be rolled back:
5446 effects can be rolled back:
5441
5447
5442 - commit
5448 - commit
5443 - import
5449 - import
5444 - pull
5450 - pull
5445 - push (with this repository as the destination)
5451 - push (with this repository as the destination)
5446 - unbundle
5452 - unbundle
5447
5453
5448 To avoid permanent data loss, rollback will refuse to rollback a
5454 To avoid permanent data loss, rollback will refuse to rollback a
5449 commit transaction if it isn't checked out. Use --force to
5455 commit transaction if it isn't checked out. Use --force to
5450 override this protection.
5456 override this protection.
5451
5457
5452 This command is not intended for use on public repositories. Once
5458 This command is not intended for use on public repositories. Once
5453 changes are visible for pull by other users, rolling a transaction
5459 changes are visible for pull by other users, rolling a transaction
5454 back locally is ineffective (someone else may already have pulled
5460 back locally is ineffective (someone else may already have pulled
5455 the changes). Furthermore, a race is possible with readers of the
5461 the changes). Furthermore, a race is possible with readers of the
5456 repository; for example an in-progress pull from the repository
5462 repository; for example an in-progress pull from the repository
5457 may fail if a rollback is performed.
5463 may fail if a rollback is performed.
5458
5464
5459 Returns 0 on success, 1 if no rollback data is available.
5465 Returns 0 on success, 1 if no rollback data is available.
5460 """
5466 """
5461 return repo.rollback(dryrun=opts.get('dry_run'),
5467 return repo.rollback(dryrun=opts.get('dry_run'),
5462 force=opts.get('force'))
5468 force=opts.get('force'))
5463
5469
5464 @command('root', [])
5470 @command('root', [])
5465 def root(ui, repo):
5471 def root(ui, repo):
5466 """print the root (top) of the current working directory
5472 """print the root (top) of the current working directory
5467
5473
5468 Print the root directory of the current repository.
5474 Print the root directory of the current repository.
5469
5475
5470 Returns 0 on success.
5476 Returns 0 on success.
5471 """
5477 """
5472 ui.write(repo.root + "\n")
5478 ui.write(repo.root + "\n")
5473
5479
5474 @command('^serve',
5480 @command('^serve',
5475 [('A', 'accesslog', '', _('name of access log file to write to'),
5481 [('A', 'accesslog', '', _('name of access log file to write to'),
5476 _('FILE')),
5482 _('FILE')),
5477 ('d', 'daemon', None, _('run server in background')),
5483 ('d', 'daemon', None, _('run server in background')),
5478 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5484 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5479 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5485 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5480 # use string type, then we can check if something was passed
5486 # use string type, then we can check if something was passed
5481 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5487 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5482 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5488 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5483 _('ADDR')),
5489 _('ADDR')),
5484 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5490 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5485 _('PREFIX')),
5491 _('PREFIX')),
5486 ('n', 'name', '',
5492 ('n', 'name', '',
5487 _('name to show in web pages (default: working directory)'), _('NAME')),
5493 _('name to show in web pages (default: working directory)'), _('NAME')),
5488 ('', 'web-conf', '',
5494 ('', 'web-conf', '',
5489 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5495 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5490 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5496 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5491 _('FILE')),
5497 _('FILE')),
5492 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5498 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5493 ('', 'stdio', None, _('for remote clients')),
5499 ('', 'stdio', None, _('for remote clients')),
5494 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5500 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5495 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5501 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5496 ('', 'style', '', _('template style to use'), _('STYLE')),
5502 ('', 'style', '', _('template style to use'), _('STYLE')),
5497 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5503 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5498 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5504 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5499 _('[OPTION]...'),
5505 _('[OPTION]...'),
5500 optionalrepo=True)
5506 optionalrepo=True)
5501 def serve(ui, repo, **opts):
5507 def serve(ui, repo, **opts):
5502 """start stand-alone webserver
5508 """start stand-alone webserver
5503
5509
5504 Start a local HTTP repository browser and pull server. You can use
5510 Start a local HTTP repository browser and pull server. You can use
5505 this for ad-hoc sharing and browsing of repositories. It is
5511 this for ad-hoc sharing and browsing of repositories. It is
5506 recommended to use a real web server to serve a repository for
5512 recommended to use a real web server to serve a repository for
5507 longer periods of time.
5513 longer periods of time.
5508
5514
5509 Please note that the server does not implement access control.
5515 Please note that the server does not implement access control.
5510 This means that, by default, anybody can read from the server and
5516 This means that, by default, anybody can read from the server and
5511 nobody can write to it by default. Set the ``web.allow_push``
5517 nobody can write to it by default. Set the ``web.allow_push``
5512 option to ``*`` to allow everybody to push to the server. You
5518 option to ``*`` to allow everybody to push to the server. You
5513 should use a real web server if you need to authenticate users.
5519 should use a real web server if you need to authenticate users.
5514
5520
5515 By default, the server logs accesses to stdout and errors to
5521 By default, the server logs accesses to stdout and errors to
5516 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5522 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5517 files.
5523 files.
5518
5524
5519 To have the server choose a free port number to listen on, specify
5525 To have the server choose a free port number to listen on, specify
5520 a port number of 0; in this case, the server will print the port
5526 a port number of 0; in this case, the server will print the port
5521 number it uses.
5527 number it uses.
5522
5528
5523 Returns 0 on success.
5529 Returns 0 on success.
5524 """
5530 """
5525
5531
5526 if opts["stdio"] and opts["cmdserver"]:
5532 if opts["stdio"] and opts["cmdserver"]:
5527 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5533 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5528
5534
5529 if opts["stdio"]:
5535 if opts["stdio"]:
5530 if repo is None:
5536 if repo is None:
5531 raise error.RepoError(_("there is no Mercurial repository here"
5537 raise error.RepoError(_("there is no Mercurial repository here"
5532 " (.hg not found)"))
5538 " (.hg not found)"))
5533 s = sshserver.sshserver(ui, repo)
5539 s = sshserver.sshserver(ui, repo)
5534 s.serve_forever()
5540 s.serve_forever()
5535
5541
5536 if opts["cmdserver"]:
5542 if opts["cmdserver"]:
5537 s = commandserver.server(ui, repo, opts["cmdserver"])
5543 s = commandserver.server(ui, repo, opts["cmdserver"])
5538 return s.serve()
5544 return s.serve()
5539
5545
5540 # this way we can check if something was given in the command-line
5546 # this way we can check if something was given in the command-line
5541 if opts.get('port'):
5547 if opts.get('port'):
5542 opts['port'] = util.getport(opts.get('port'))
5548 opts['port'] = util.getport(opts.get('port'))
5543
5549
5544 baseui = repo and repo.baseui or ui
5550 baseui = repo and repo.baseui or ui
5545 optlist = ("name templates style address port prefix ipv6"
5551 optlist = ("name templates style address port prefix ipv6"
5546 " accesslog errorlog certificate encoding")
5552 " accesslog errorlog certificate encoding")
5547 for o in optlist.split():
5553 for o in optlist.split():
5548 val = opts.get(o, '')
5554 val = opts.get(o, '')
5549 if val in (None, ''): # should check against default options instead
5555 if val in (None, ''): # should check against default options instead
5550 continue
5556 continue
5551 baseui.setconfig("web", o, val, 'serve')
5557 baseui.setconfig("web", o, val, 'serve')
5552 if repo and repo.ui != baseui:
5558 if repo and repo.ui != baseui:
5553 repo.ui.setconfig("web", o, val, 'serve')
5559 repo.ui.setconfig("web", o, val, 'serve')
5554
5560
5555 o = opts.get('web_conf') or opts.get('webdir_conf')
5561 o = opts.get('web_conf') or opts.get('webdir_conf')
5556 if not o:
5562 if not o:
5557 if not repo:
5563 if not repo:
5558 raise error.RepoError(_("there is no Mercurial repository"
5564 raise error.RepoError(_("there is no Mercurial repository"
5559 " here (.hg not found)"))
5565 " here (.hg not found)"))
5560 o = repo
5566 o = repo
5561
5567
5562 app = hgweb.hgweb(o, baseui=baseui)
5568 app = hgweb.hgweb(o, baseui=baseui)
5563 service = httpservice(ui, app, opts)
5569 service = httpservice(ui, app, opts)
5564 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5570 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5565
5571
5566 class httpservice(object):
5572 class httpservice(object):
5567 def __init__(self, ui, app, opts):
5573 def __init__(self, ui, app, opts):
5568 self.ui = ui
5574 self.ui = ui
5569 self.app = app
5575 self.app = app
5570 self.opts = opts
5576 self.opts = opts
5571
5577
5572 def init(self):
5578 def init(self):
5573 util.setsignalhandler()
5579 util.setsignalhandler()
5574 self.httpd = hgweb_server.create_server(self.ui, self.app)
5580 self.httpd = hgweb_server.create_server(self.ui, self.app)
5575
5581
5576 if self.opts['port'] and not self.ui.verbose:
5582 if self.opts['port'] and not self.ui.verbose:
5577 return
5583 return
5578
5584
5579 if self.httpd.prefix:
5585 if self.httpd.prefix:
5580 prefix = self.httpd.prefix.strip('/') + '/'
5586 prefix = self.httpd.prefix.strip('/') + '/'
5581 else:
5587 else:
5582 prefix = ''
5588 prefix = ''
5583
5589
5584 port = ':%d' % self.httpd.port
5590 port = ':%d' % self.httpd.port
5585 if port == ':80':
5591 if port == ':80':
5586 port = ''
5592 port = ''
5587
5593
5588 bindaddr = self.httpd.addr
5594 bindaddr = self.httpd.addr
5589 if bindaddr == '0.0.0.0':
5595 if bindaddr == '0.0.0.0':
5590 bindaddr = '*'
5596 bindaddr = '*'
5591 elif ':' in bindaddr: # IPv6
5597 elif ':' in bindaddr: # IPv6
5592 bindaddr = '[%s]' % bindaddr
5598 bindaddr = '[%s]' % bindaddr
5593
5599
5594 fqaddr = self.httpd.fqaddr
5600 fqaddr = self.httpd.fqaddr
5595 if ':' in fqaddr:
5601 if ':' in fqaddr:
5596 fqaddr = '[%s]' % fqaddr
5602 fqaddr = '[%s]' % fqaddr
5597 if self.opts['port']:
5603 if self.opts['port']:
5598 write = self.ui.status
5604 write = self.ui.status
5599 else:
5605 else:
5600 write = self.ui.write
5606 write = self.ui.write
5601 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5607 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5602 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5608 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5603 self.ui.flush() # avoid buffering of status message
5609 self.ui.flush() # avoid buffering of status message
5604
5610
5605 def run(self):
5611 def run(self):
5606 self.httpd.serve_forever()
5612 self.httpd.serve_forever()
5607
5613
5608
5614
5609 @command('^status|st',
5615 @command('^status|st',
5610 [('A', 'all', None, _('show status of all files')),
5616 [('A', 'all', None, _('show status of all files')),
5611 ('m', 'modified', None, _('show only modified files')),
5617 ('m', 'modified', None, _('show only modified files')),
5612 ('a', 'added', None, _('show only added files')),
5618 ('a', 'added', None, _('show only added files')),
5613 ('r', 'removed', None, _('show only removed files')),
5619 ('r', 'removed', None, _('show only removed files')),
5614 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5620 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5615 ('c', 'clean', None, _('show only files without changes')),
5621 ('c', 'clean', None, _('show only files without changes')),
5616 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5622 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5617 ('i', 'ignored', None, _('show only ignored files')),
5623 ('i', 'ignored', None, _('show only ignored files')),
5618 ('n', 'no-status', None, _('hide status prefix')),
5624 ('n', 'no-status', None, _('hide status prefix')),
5619 ('C', 'copies', None, _('show source of copied files')),
5625 ('C', 'copies', None, _('show source of copied files')),
5620 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5626 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5621 ('', 'rev', [], _('show difference from revision'), _('REV')),
5627 ('', 'rev', [], _('show difference from revision'), _('REV')),
5622 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5628 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5623 ] + walkopts + subrepoopts + formatteropts,
5629 ] + walkopts + subrepoopts + formatteropts,
5624 _('[OPTION]... [FILE]...'),
5630 _('[OPTION]... [FILE]...'),
5625 inferrepo=True)
5631 inferrepo=True)
5626 def status(ui, repo, *pats, **opts):
5632 def status(ui, repo, *pats, **opts):
5627 """show changed files in the working directory
5633 """show changed files in the working directory
5628
5634
5629 Show status of files in the repository. If names are given, only
5635 Show status of files in the repository. If names are given, only
5630 files that match are shown. Files that are clean or ignored or
5636 files that match are shown. Files that are clean or ignored or
5631 the source of a copy/move operation, are not listed unless
5637 the source of a copy/move operation, are not listed unless
5632 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5638 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5633 Unless options described with "show only ..." are given, the
5639 Unless options described with "show only ..." are given, the
5634 options -mardu are used.
5640 options -mardu are used.
5635
5641
5636 Option -q/--quiet hides untracked (unknown and ignored) files
5642 Option -q/--quiet hides untracked (unknown and ignored) files
5637 unless explicitly requested with -u/--unknown or -i/--ignored.
5643 unless explicitly requested with -u/--unknown or -i/--ignored.
5638
5644
5639 .. note::
5645 .. note::
5640
5646
5641 status may appear to disagree with diff if permissions have
5647 status may appear to disagree with diff if permissions have
5642 changed or a merge has occurred. The standard diff format does
5648 changed or a merge has occurred. The standard diff format does
5643 not report permission changes and diff only reports changes
5649 not report permission changes and diff only reports changes
5644 relative to one merge parent.
5650 relative to one merge parent.
5645
5651
5646 If one revision is given, it is used as the base revision.
5652 If one revision is given, it is used as the base revision.
5647 If two revisions are given, the differences between them are
5653 If two revisions are given, the differences between them are
5648 shown. The --change option can also be used as a shortcut to list
5654 shown. The --change option can also be used as a shortcut to list
5649 the changed files of a revision from its first parent.
5655 the changed files of a revision from its first parent.
5650
5656
5651 The codes used to show the status of files are::
5657 The codes used to show the status of files are::
5652
5658
5653 M = modified
5659 M = modified
5654 A = added
5660 A = added
5655 R = removed
5661 R = removed
5656 C = clean
5662 C = clean
5657 ! = missing (deleted by non-hg command, but still tracked)
5663 ! = missing (deleted by non-hg command, but still tracked)
5658 ? = not tracked
5664 ? = not tracked
5659 I = ignored
5665 I = ignored
5660 = origin of the previous file (with --copies)
5666 = origin of the previous file (with --copies)
5661
5667
5662 .. container:: verbose
5668 .. container:: verbose
5663
5669
5664 Examples:
5670 Examples:
5665
5671
5666 - show changes in the working directory relative to a
5672 - show changes in the working directory relative to a
5667 changeset::
5673 changeset::
5668
5674
5669 hg status --rev 9353
5675 hg status --rev 9353
5670
5676
5671 - show all changes including copies in an existing changeset::
5677 - show all changes including copies in an existing changeset::
5672
5678
5673 hg status --copies --change 9353
5679 hg status --copies --change 9353
5674
5680
5675 - get a NUL separated list of added files, suitable for xargs::
5681 - get a NUL separated list of added files, suitable for xargs::
5676
5682
5677 hg status -an0
5683 hg status -an0
5678
5684
5679 Returns 0 on success.
5685 Returns 0 on success.
5680 """
5686 """
5681
5687
5682 revs = opts.get('rev')
5688 revs = opts.get('rev')
5683 change = opts.get('change')
5689 change = opts.get('change')
5684
5690
5685 if revs and change:
5691 if revs and change:
5686 msg = _('cannot specify --rev and --change at the same time')
5692 msg = _('cannot specify --rev and --change at the same time')
5687 raise util.Abort(msg)
5693 raise util.Abort(msg)
5688 elif change:
5694 elif change:
5689 node2 = scmutil.revsingle(repo, change, None).node()
5695 node2 = scmutil.revsingle(repo, change, None).node()
5690 node1 = repo[node2].p1().node()
5696 node1 = repo[node2].p1().node()
5691 else:
5697 else:
5692 node1, node2 = scmutil.revpair(repo, revs)
5698 node1, node2 = scmutil.revpair(repo, revs)
5693
5699
5694 cwd = (pats and repo.getcwd()) or ''
5700 cwd = (pats and repo.getcwd()) or ''
5695 end = opts.get('print0') and '\0' or '\n'
5701 end = opts.get('print0') and '\0' or '\n'
5696 copy = {}
5702 copy = {}
5697 states = 'modified added removed deleted unknown ignored clean'.split()
5703 states = 'modified added removed deleted unknown ignored clean'.split()
5698 show = [k for k in states if opts.get(k)]
5704 show = [k for k in states if opts.get(k)]
5699 if opts.get('all'):
5705 if opts.get('all'):
5700 show += ui.quiet and (states[:4] + ['clean']) or states
5706 show += ui.quiet and (states[:4] + ['clean']) or states
5701 if not show:
5707 if not show:
5702 show = ui.quiet and states[:4] or states[:5]
5708 show = ui.quiet and states[:4] or states[:5]
5703
5709
5704 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5710 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5705 'ignored' in show, 'clean' in show, 'unknown' in show,
5711 'ignored' in show, 'clean' in show, 'unknown' in show,
5706 opts.get('subrepos'))
5712 opts.get('subrepos'))
5707 changestates = zip(states, 'MAR!?IC', stat)
5713 changestates = zip(states, 'MAR!?IC', stat)
5708
5714
5709 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5715 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5710 copy = copies.pathcopies(repo[node1], repo[node2])
5716 copy = copies.pathcopies(repo[node1], repo[node2])
5711
5717
5712 fm = ui.formatter('status', opts)
5718 fm = ui.formatter('status', opts)
5713 fmt = '%s' + end
5719 fmt = '%s' + end
5714 showchar = not opts.get('no_status')
5720 showchar = not opts.get('no_status')
5715
5721
5716 for state, char, files in changestates:
5722 for state, char, files in changestates:
5717 if state in show:
5723 if state in show:
5718 label = 'status.' + state
5724 label = 'status.' + state
5719 for f in files:
5725 for f in files:
5720 fm.startitem()
5726 fm.startitem()
5721 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5727 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5722 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5728 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5723 if f in copy:
5729 if f in copy:
5724 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5730 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5725 label='status.copied')
5731 label='status.copied')
5726 fm.end()
5732 fm.end()
5727
5733
5728 @command('^summary|sum',
5734 @command('^summary|sum',
5729 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5735 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5730 def summary(ui, repo, **opts):
5736 def summary(ui, repo, **opts):
5731 """summarize working directory state
5737 """summarize working directory state
5732
5738
5733 This generates a brief summary of the working directory state,
5739 This generates a brief summary of the working directory state,
5734 including parents, branch, commit status, and available updates.
5740 including parents, branch, commit status, and available updates.
5735
5741
5736 With the --remote option, this will check the default paths for
5742 With the --remote option, this will check the default paths for
5737 incoming and outgoing changes. This can be time-consuming.
5743 incoming and outgoing changes. This can be time-consuming.
5738
5744
5739 Returns 0 on success.
5745 Returns 0 on success.
5740 """
5746 """
5741
5747
5742 ctx = repo[None]
5748 ctx = repo[None]
5743 parents = ctx.parents()
5749 parents = ctx.parents()
5744 pnode = parents[0].node()
5750 pnode = parents[0].node()
5745 marks = []
5751 marks = []
5746
5752
5747 for p in parents:
5753 for p in parents:
5748 # label with log.changeset (instead of log.parent) since this
5754 # label with log.changeset (instead of log.parent) since this
5749 # shows a working directory parent *changeset*:
5755 # shows a working directory parent *changeset*:
5750 # i18n: column positioning for "hg summary"
5756 # i18n: column positioning for "hg summary"
5751 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5757 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5752 label='log.changeset changeset.%s' % p.phasestr())
5758 label='log.changeset changeset.%s' % p.phasestr())
5753 ui.write(' '.join(p.tags()), label='log.tag')
5759 ui.write(' '.join(p.tags()), label='log.tag')
5754 if p.bookmarks():
5760 if p.bookmarks():
5755 marks.extend(p.bookmarks())
5761 marks.extend(p.bookmarks())
5756 if p.rev() == -1:
5762 if p.rev() == -1:
5757 if not len(repo):
5763 if not len(repo):
5758 ui.write(_(' (empty repository)'))
5764 ui.write(_(' (empty repository)'))
5759 else:
5765 else:
5760 ui.write(_(' (no revision checked out)'))
5766 ui.write(_(' (no revision checked out)'))
5761 ui.write('\n')
5767 ui.write('\n')
5762 if p.description():
5768 if p.description():
5763 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5769 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5764 label='log.summary')
5770 label='log.summary')
5765
5771
5766 branch = ctx.branch()
5772 branch = ctx.branch()
5767 bheads = repo.branchheads(branch)
5773 bheads = repo.branchheads(branch)
5768 # i18n: column positioning for "hg summary"
5774 # i18n: column positioning for "hg summary"
5769 m = _('branch: %s\n') % branch
5775 m = _('branch: %s\n') % branch
5770 if branch != 'default':
5776 if branch != 'default':
5771 ui.write(m, label='log.branch')
5777 ui.write(m, label='log.branch')
5772 else:
5778 else:
5773 ui.status(m, label='log.branch')
5779 ui.status(m, label='log.branch')
5774
5780
5775 if marks:
5781 if marks:
5776 current = repo._bookmarkcurrent
5782 current = repo._bookmarkcurrent
5777 # i18n: column positioning for "hg summary"
5783 # i18n: column positioning for "hg summary"
5778 ui.write(_('bookmarks:'), label='log.bookmark')
5784 ui.write(_('bookmarks:'), label='log.bookmark')
5779 if current is not None:
5785 if current is not None:
5780 if current in marks:
5786 if current in marks:
5781 ui.write(' *' + current, label='bookmarks.current')
5787 ui.write(' *' + current, label='bookmarks.current')
5782 marks.remove(current)
5788 marks.remove(current)
5783 else:
5789 else:
5784 ui.write(' [%s]' % current, label='bookmarks.current')
5790 ui.write(' [%s]' % current, label='bookmarks.current')
5785 for m in marks:
5791 for m in marks:
5786 ui.write(' ' + m, label='log.bookmark')
5792 ui.write(' ' + m, label='log.bookmark')
5787 ui.write('\n', label='log.bookmark')
5793 ui.write('\n', label='log.bookmark')
5788
5794
5789 st = list(repo.status(unknown=True))[:5]
5795 st = list(repo.status(unknown=True))[:5]
5790
5796
5791 c = repo.dirstate.copies()
5797 c = repo.dirstate.copies()
5792 copied, renamed = [], []
5798 copied, renamed = [], []
5793 for d, s in c.iteritems():
5799 for d, s in c.iteritems():
5794 if s in st[2]:
5800 if s in st[2]:
5795 st[2].remove(s)
5801 st[2].remove(s)
5796 renamed.append(d)
5802 renamed.append(d)
5797 else:
5803 else:
5798 copied.append(d)
5804 copied.append(d)
5799 if d in st[1]:
5805 if d in st[1]:
5800 st[1].remove(d)
5806 st[1].remove(d)
5801 st.insert(3, renamed)
5807 st.insert(3, renamed)
5802 st.insert(4, copied)
5808 st.insert(4, copied)
5803
5809
5804 ms = mergemod.mergestate(repo)
5810 ms = mergemod.mergestate(repo)
5805 st.append([f for f in ms if ms[f] == 'u'])
5811 st.append([f for f in ms if ms[f] == 'u'])
5806
5812
5807 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5813 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5808 st.append(subs)
5814 st.append(subs)
5809
5815
5810 labels = [ui.label(_('%d modified'), 'status.modified'),
5816 labels = [ui.label(_('%d modified'), 'status.modified'),
5811 ui.label(_('%d added'), 'status.added'),
5817 ui.label(_('%d added'), 'status.added'),
5812 ui.label(_('%d removed'), 'status.removed'),
5818 ui.label(_('%d removed'), 'status.removed'),
5813 ui.label(_('%d renamed'), 'status.copied'),
5819 ui.label(_('%d renamed'), 'status.copied'),
5814 ui.label(_('%d copied'), 'status.copied'),
5820 ui.label(_('%d copied'), 'status.copied'),
5815 ui.label(_('%d deleted'), 'status.deleted'),
5821 ui.label(_('%d deleted'), 'status.deleted'),
5816 ui.label(_('%d unknown'), 'status.unknown'),
5822 ui.label(_('%d unknown'), 'status.unknown'),
5817 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5823 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5818 ui.label(_('%d subrepos'), 'status.modified')]
5824 ui.label(_('%d subrepos'), 'status.modified')]
5819 t = []
5825 t = []
5820 for s, l in zip(st, labels):
5826 for s, l in zip(st, labels):
5821 if s:
5827 if s:
5822 t.append(l % len(s))
5828 t.append(l % len(s))
5823
5829
5824 t = ', '.join(t)
5830 t = ', '.join(t)
5825 cleanworkdir = False
5831 cleanworkdir = False
5826
5832
5827 if repo.vfs.exists('updatestate'):
5833 if repo.vfs.exists('updatestate'):
5828 t += _(' (interrupted update)')
5834 t += _(' (interrupted update)')
5829 elif len(parents) > 1:
5835 elif len(parents) > 1:
5830 t += _(' (merge)')
5836 t += _(' (merge)')
5831 elif branch != parents[0].branch():
5837 elif branch != parents[0].branch():
5832 t += _(' (new branch)')
5838 t += _(' (new branch)')
5833 elif (parents[0].closesbranch() and
5839 elif (parents[0].closesbranch() and
5834 pnode in repo.branchheads(branch, closed=True)):
5840 pnode in repo.branchheads(branch, closed=True)):
5835 t += _(' (head closed)')
5841 t += _(' (head closed)')
5836 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[8]):
5842 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[8]):
5837 t += _(' (clean)')
5843 t += _(' (clean)')
5838 cleanworkdir = True
5844 cleanworkdir = True
5839 elif pnode not in bheads:
5845 elif pnode not in bheads:
5840 t += _(' (new branch head)')
5846 t += _(' (new branch head)')
5841
5847
5842 if cleanworkdir:
5848 if cleanworkdir:
5843 # i18n: column positioning for "hg summary"
5849 # i18n: column positioning for "hg summary"
5844 ui.status(_('commit: %s\n') % t.strip())
5850 ui.status(_('commit: %s\n') % t.strip())
5845 else:
5851 else:
5846 # i18n: column positioning for "hg summary"
5852 # i18n: column positioning for "hg summary"
5847 ui.write(_('commit: %s\n') % t.strip())
5853 ui.write(_('commit: %s\n') % t.strip())
5848
5854
5849 # all ancestors of branch heads - all ancestors of parent = new csets
5855 # all ancestors of branch heads - all ancestors of parent = new csets
5850 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5856 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5851 bheads))
5857 bheads))
5852
5858
5853 if new == 0:
5859 if new == 0:
5854 # i18n: column positioning for "hg summary"
5860 # i18n: column positioning for "hg summary"
5855 ui.status(_('update: (current)\n'))
5861 ui.status(_('update: (current)\n'))
5856 elif pnode not in bheads:
5862 elif pnode not in bheads:
5857 # i18n: column positioning for "hg summary"
5863 # i18n: column positioning for "hg summary"
5858 ui.write(_('update: %d new changesets (update)\n') % new)
5864 ui.write(_('update: %d new changesets (update)\n') % new)
5859 else:
5865 else:
5860 # i18n: column positioning for "hg summary"
5866 # i18n: column positioning for "hg summary"
5861 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5867 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5862 (new, len(bheads)))
5868 (new, len(bheads)))
5863
5869
5864 cmdutil.summaryhooks(ui, repo)
5870 cmdutil.summaryhooks(ui, repo)
5865
5871
5866 if opts.get('remote'):
5872 if opts.get('remote'):
5867 needsincoming, needsoutgoing = True, True
5873 needsincoming, needsoutgoing = True, True
5868 else:
5874 else:
5869 needsincoming, needsoutgoing = False, False
5875 needsincoming, needsoutgoing = False, False
5870 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5876 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5871 if i:
5877 if i:
5872 needsincoming = True
5878 needsincoming = True
5873 if o:
5879 if o:
5874 needsoutgoing = True
5880 needsoutgoing = True
5875 if not needsincoming and not needsoutgoing:
5881 if not needsincoming and not needsoutgoing:
5876 return
5882 return
5877
5883
5878 def getincoming():
5884 def getincoming():
5879 source, branches = hg.parseurl(ui.expandpath('default'))
5885 source, branches = hg.parseurl(ui.expandpath('default'))
5880 sbranch = branches[0]
5886 sbranch = branches[0]
5881 try:
5887 try:
5882 other = hg.peer(repo, {}, source)
5888 other = hg.peer(repo, {}, source)
5883 except error.RepoError:
5889 except error.RepoError:
5884 if opts.get('remote'):
5890 if opts.get('remote'):
5885 raise
5891 raise
5886 return source, sbranch, None, None, None
5892 return source, sbranch, None, None, None
5887 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5893 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5888 if revs:
5894 if revs:
5889 revs = [other.lookup(rev) for rev in revs]
5895 revs = [other.lookup(rev) for rev in revs]
5890 ui.debug('comparing with %s\n' % util.hidepassword(source))
5896 ui.debug('comparing with %s\n' % util.hidepassword(source))
5891 repo.ui.pushbuffer()
5897 repo.ui.pushbuffer()
5892 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5898 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5893 repo.ui.popbuffer()
5899 repo.ui.popbuffer()
5894 return source, sbranch, other, commoninc, commoninc[1]
5900 return source, sbranch, other, commoninc, commoninc[1]
5895
5901
5896 if needsincoming:
5902 if needsincoming:
5897 source, sbranch, sother, commoninc, incoming = getincoming()
5903 source, sbranch, sother, commoninc, incoming = getincoming()
5898 else:
5904 else:
5899 source = sbranch = sother = commoninc = incoming = None
5905 source = sbranch = sother = commoninc = incoming = None
5900
5906
5901 def getoutgoing():
5907 def getoutgoing():
5902 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5908 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5903 dbranch = branches[0]
5909 dbranch = branches[0]
5904 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5910 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5905 if source != dest:
5911 if source != dest:
5906 try:
5912 try:
5907 dother = hg.peer(repo, {}, dest)
5913 dother = hg.peer(repo, {}, dest)
5908 except error.RepoError:
5914 except error.RepoError:
5909 if opts.get('remote'):
5915 if opts.get('remote'):
5910 raise
5916 raise
5911 return dest, dbranch, None, None
5917 return dest, dbranch, None, None
5912 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5918 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5913 elif sother is None:
5919 elif sother is None:
5914 # there is no explicit destination peer, but source one is invalid
5920 # there is no explicit destination peer, but source one is invalid
5915 return dest, dbranch, None, None
5921 return dest, dbranch, None, None
5916 else:
5922 else:
5917 dother = sother
5923 dother = sother
5918 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5924 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5919 common = None
5925 common = None
5920 else:
5926 else:
5921 common = commoninc
5927 common = commoninc
5922 if revs:
5928 if revs:
5923 revs = [repo.lookup(rev) for rev in revs]
5929 revs = [repo.lookup(rev) for rev in revs]
5924 repo.ui.pushbuffer()
5930 repo.ui.pushbuffer()
5925 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5931 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5926 commoninc=common)
5932 commoninc=common)
5927 repo.ui.popbuffer()
5933 repo.ui.popbuffer()
5928 return dest, dbranch, dother, outgoing
5934 return dest, dbranch, dother, outgoing
5929
5935
5930 if needsoutgoing:
5936 if needsoutgoing:
5931 dest, dbranch, dother, outgoing = getoutgoing()
5937 dest, dbranch, dother, outgoing = getoutgoing()
5932 else:
5938 else:
5933 dest = dbranch = dother = outgoing = None
5939 dest = dbranch = dother = outgoing = None
5934
5940
5935 if opts.get('remote'):
5941 if opts.get('remote'):
5936 t = []
5942 t = []
5937 if incoming:
5943 if incoming:
5938 t.append(_('1 or more incoming'))
5944 t.append(_('1 or more incoming'))
5939 o = outgoing.missing
5945 o = outgoing.missing
5940 if o:
5946 if o:
5941 t.append(_('%d outgoing') % len(o))
5947 t.append(_('%d outgoing') % len(o))
5942 other = dother or sother
5948 other = dother or sother
5943 if 'bookmarks' in other.listkeys('namespaces'):
5949 if 'bookmarks' in other.listkeys('namespaces'):
5944 lmarks = repo.listkeys('bookmarks')
5950 lmarks = repo.listkeys('bookmarks')
5945 rmarks = other.listkeys('bookmarks')
5951 rmarks = other.listkeys('bookmarks')
5946 diff = set(rmarks) - set(lmarks)
5952 diff = set(rmarks) - set(lmarks)
5947 if len(diff) > 0:
5953 if len(diff) > 0:
5948 t.append(_('%d incoming bookmarks') % len(diff))
5954 t.append(_('%d incoming bookmarks') % len(diff))
5949 diff = set(lmarks) - set(rmarks)
5955 diff = set(lmarks) - set(rmarks)
5950 if len(diff) > 0:
5956 if len(diff) > 0:
5951 t.append(_('%d outgoing bookmarks') % len(diff))
5957 t.append(_('%d outgoing bookmarks') % len(diff))
5952
5958
5953 if t:
5959 if t:
5954 # i18n: column positioning for "hg summary"
5960 # i18n: column positioning for "hg summary"
5955 ui.write(_('remote: %s\n') % (', '.join(t)))
5961 ui.write(_('remote: %s\n') % (', '.join(t)))
5956 else:
5962 else:
5957 # i18n: column positioning for "hg summary"
5963 # i18n: column positioning for "hg summary"
5958 ui.status(_('remote: (synced)\n'))
5964 ui.status(_('remote: (synced)\n'))
5959
5965
5960 cmdutil.summaryremotehooks(ui, repo, opts,
5966 cmdutil.summaryremotehooks(ui, repo, opts,
5961 ((source, sbranch, sother, commoninc),
5967 ((source, sbranch, sother, commoninc),
5962 (dest, dbranch, dother, outgoing)))
5968 (dest, dbranch, dother, outgoing)))
5963
5969
5964 @command('tag',
5970 @command('tag',
5965 [('f', 'force', None, _('force tag')),
5971 [('f', 'force', None, _('force tag')),
5966 ('l', 'local', None, _('make the tag local')),
5972 ('l', 'local', None, _('make the tag local')),
5967 ('r', 'rev', '', _('revision to tag'), _('REV')),
5973 ('r', 'rev', '', _('revision to tag'), _('REV')),
5968 ('', 'remove', None, _('remove a tag')),
5974 ('', 'remove', None, _('remove a tag')),
5969 # -l/--local is already there, commitopts cannot be used
5975 # -l/--local is already there, commitopts cannot be used
5970 ('e', 'edit', None, _('invoke editor on commit messages')),
5976 ('e', 'edit', None, _('invoke editor on commit messages')),
5971 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5977 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5972 ] + commitopts2,
5978 ] + commitopts2,
5973 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5979 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5974 def tag(ui, repo, name1, *names, **opts):
5980 def tag(ui, repo, name1, *names, **opts):
5975 """add one or more tags for the current or given revision
5981 """add one or more tags for the current or given revision
5976
5982
5977 Name a particular revision using <name>.
5983 Name a particular revision using <name>.
5978
5984
5979 Tags are used to name particular revisions of the repository and are
5985 Tags are used to name particular revisions of the repository and are
5980 very useful to compare different revisions, to go back to significant
5986 very useful to compare different revisions, to go back to significant
5981 earlier versions or to mark branch points as releases, etc. Changing
5987 earlier versions or to mark branch points as releases, etc. Changing
5982 an existing tag is normally disallowed; use -f/--force to override.
5988 an existing tag is normally disallowed; use -f/--force to override.
5983
5989
5984 If no revision is given, the parent of the working directory is
5990 If no revision is given, the parent of the working directory is
5985 used.
5991 used.
5986
5992
5987 To facilitate version control, distribution, and merging of tags,
5993 To facilitate version control, distribution, and merging of tags,
5988 they are stored as a file named ".hgtags" which is managed similarly
5994 they are stored as a file named ".hgtags" which is managed similarly
5989 to other project files and can be hand-edited if necessary. This
5995 to other project files and can be hand-edited if necessary. This
5990 also means that tagging creates a new commit. The file
5996 also means that tagging creates a new commit. The file
5991 ".hg/localtags" is used for local tags (not shared among
5997 ".hg/localtags" is used for local tags (not shared among
5992 repositories).
5998 repositories).
5993
5999
5994 Tag commits are usually made at the head of a branch. If the parent
6000 Tag commits are usually made at the head of a branch. If the parent
5995 of the working directory is not a branch head, :hg:`tag` aborts; use
6001 of the working directory is not a branch head, :hg:`tag` aborts; use
5996 -f/--force to force the tag commit to be based on a non-head
6002 -f/--force to force the tag commit to be based on a non-head
5997 changeset.
6003 changeset.
5998
6004
5999 See :hg:`help dates` for a list of formats valid for -d/--date.
6005 See :hg:`help dates` for a list of formats valid for -d/--date.
6000
6006
6001 Since tag names have priority over branch names during revision
6007 Since tag names have priority over branch names during revision
6002 lookup, using an existing branch name as a tag name is discouraged.
6008 lookup, using an existing branch name as a tag name is discouraged.
6003
6009
6004 Returns 0 on success.
6010 Returns 0 on success.
6005 """
6011 """
6006 wlock = lock = None
6012 wlock = lock = None
6007 try:
6013 try:
6008 wlock = repo.wlock()
6014 wlock = repo.wlock()
6009 lock = repo.lock()
6015 lock = repo.lock()
6010 rev_ = "."
6016 rev_ = "."
6011 names = [t.strip() for t in (name1,) + names]
6017 names = [t.strip() for t in (name1,) + names]
6012 if len(names) != len(set(names)):
6018 if len(names) != len(set(names)):
6013 raise util.Abort(_('tag names must be unique'))
6019 raise util.Abort(_('tag names must be unique'))
6014 for n in names:
6020 for n in names:
6015 scmutil.checknewlabel(repo, n, 'tag')
6021 scmutil.checknewlabel(repo, n, 'tag')
6016 if not n:
6022 if not n:
6017 raise util.Abort(_('tag names cannot consist entirely of '
6023 raise util.Abort(_('tag names cannot consist entirely of '
6018 'whitespace'))
6024 'whitespace'))
6019 if opts.get('rev') and opts.get('remove'):
6025 if opts.get('rev') and opts.get('remove'):
6020 raise util.Abort(_("--rev and --remove are incompatible"))
6026 raise util.Abort(_("--rev and --remove are incompatible"))
6021 if opts.get('rev'):
6027 if opts.get('rev'):
6022 rev_ = opts['rev']
6028 rev_ = opts['rev']
6023 message = opts.get('message')
6029 message = opts.get('message')
6024 if opts.get('remove'):
6030 if opts.get('remove'):
6025 expectedtype = opts.get('local') and 'local' or 'global'
6031 expectedtype = opts.get('local') and 'local' or 'global'
6026 for n in names:
6032 for n in names:
6027 if not repo.tagtype(n):
6033 if not repo.tagtype(n):
6028 raise util.Abort(_("tag '%s' does not exist") % n)
6034 raise util.Abort(_("tag '%s' does not exist") % n)
6029 if repo.tagtype(n) != expectedtype:
6035 if repo.tagtype(n) != expectedtype:
6030 if expectedtype == 'global':
6036 if expectedtype == 'global':
6031 raise util.Abort(_("tag '%s' is not a global tag") % n)
6037 raise util.Abort(_("tag '%s' is not a global tag") % n)
6032 else:
6038 else:
6033 raise util.Abort(_("tag '%s' is not a local tag") % n)
6039 raise util.Abort(_("tag '%s' is not a local tag") % n)
6034 rev_ = nullid
6040 rev_ = nullid
6035 if not message:
6041 if not message:
6036 # we don't translate commit messages
6042 # we don't translate commit messages
6037 message = 'Removed tag %s' % ', '.join(names)
6043 message = 'Removed tag %s' % ', '.join(names)
6038 elif not opts.get('force'):
6044 elif not opts.get('force'):
6039 for n in names:
6045 for n in names:
6040 if n in repo.tags():
6046 if n in repo.tags():
6041 raise util.Abort(_("tag '%s' already exists "
6047 raise util.Abort(_("tag '%s' already exists "
6042 "(use -f to force)") % n)
6048 "(use -f to force)") % n)
6043 if not opts.get('local'):
6049 if not opts.get('local'):
6044 p1, p2 = repo.dirstate.parents()
6050 p1, p2 = repo.dirstate.parents()
6045 if p2 != nullid:
6051 if p2 != nullid:
6046 raise util.Abort(_('uncommitted merge'))
6052 raise util.Abort(_('uncommitted merge'))
6047 bheads = repo.branchheads()
6053 bheads = repo.branchheads()
6048 if not opts.get('force') and bheads and p1 not in bheads:
6054 if not opts.get('force') and bheads and p1 not in bheads:
6049 raise util.Abort(_('not at a branch head (use -f to force)'))
6055 raise util.Abort(_('not at a branch head (use -f to force)'))
6050 r = scmutil.revsingle(repo, rev_).node()
6056 r = scmutil.revsingle(repo, rev_).node()
6051
6057
6052 if not message:
6058 if not message:
6053 # we don't translate commit messages
6059 # we don't translate commit messages
6054 message = ('Added tag %s for changeset %s' %
6060 message = ('Added tag %s for changeset %s' %
6055 (', '.join(names), short(r)))
6061 (', '.join(names), short(r)))
6056
6062
6057 date = opts.get('date')
6063 date = opts.get('date')
6058 if date:
6064 if date:
6059 date = util.parsedate(date)
6065 date = util.parsedate(date)
6060
6066
6061 if opts.get('remove'):
6067 if opts.get('remove'):
6062 editform = 'tag.remove'
6068 editform = 'tag.remove'
6063 else:
6069 else:
6064 editform = 'tag.add'
6070 editform = 'tag.add'
6065 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6071 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6066
6072
6067 # don't allow tagging the null rev
6073 # don't allow tagging the null rev
6068 if (not opts.get('remove') and
6074 if (not opts.get('remove') and
6069 scmutil.revsingle(repo, rev_).rev() == nullrev):
6075 scmutil.revsingle(repo, rev_).rev() == nullrev):
6070 raise util.Abort(_("cannot tag null revision"))
6076 raise util.Abort(_("cannot tag null revision"))
6071
6077
6072 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6078 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6073 editor=editor)
6079 editor=editor)
6074 finally:
6080 finally:
6075 release(lock, wlock)
6081 release(lock, wlock)
6076
6082
6077 @command('tags', formatteropts, '')
6083 @command('tags', formatteropts, '')
6078 def tags(ui, repo, **opts):
6084 def tags(ui, repo, **opts):
6079 """list repository tags
6085 """list repository tags
6080
6086
6081 This lists both regular and local tags. When the -v/--verbose
6087 This lists both regular and local tags. When the -v/--verbose
6082 switch is used, a third column "local" is printed for local tags.
6088 switch is used, a third column "local" is printed for local tags.
6083
6089
6084 Returns 0 on success.
6090 Returns 0 on success.
6085 """
6091 """
6086
6092
6087 fm = ui.formatter('tags', opts)
6093 fm = ui.formatter('tags', opts)
6088 hexfunc = fm.hexfunc
6094 hexfunc = fm.hexfunc
6089 tagtype = ""
6095 tagtype = ""
6090
6096
6091 for t, n in reversed(repo.tagslist()):
6097 for t, n in reversed(repo.tagslist()):
6092 hn = hexfunc(n)
6098 hn = hexfunc(n)
6093 label = 'tags.normal'
6099 label = 'tags.normal'
6094 tagtype = ''
6100 tagtype = ''
6095 if repo.tagtype(t) == 'local':
6101 if repo.tagtype(t) == 'local':
6096 label = 'tags.local'
6102 label = 'tags.local'
6097 tagtype = 'local'
6103 tagtype = 'local'
6098
6104
6099 fm.startitem()
6105 fm.startitem()
6100 fm.write('tag', '%s', t, label=label)
6106 fm.write('tag', '%s', t, label=label)
6101 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6107 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6102 fm.condwrite(not ui.quiet, 'rev node', fmt,
6108 fm.condwrite(not ui.quiet, 'rev node', fmt,
6103 repo.changelog.rev(n), hn, label=label)
6109 repo.changelog.rev(n), hn, label=label)
6104 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6110 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6105 tagtype, label=label)
6111 tagtype, label=label)
6106 fm.plain('\n')
6112 fm.plain('\n')
6107 fm.end()
6113 fm.end()
6108
6114
6109 @command('tip',
6115 @command('tip',
6110 [('p', 'patch', None, _('show patch')),
6116 [('p', 'patch', None, _('show patch')),
6111 ('g', 'git', None, _('use git extended diff format')),
6117 ('g', 'git', None, _('use git extended diff format')),
6112 ] + templateopts,
6118 ] + templateopts,
6113 _('[-p] [-g]'))
6119 _('[-p] [-g]'))
6114 def tip(ui, repo, **opts):
6120 def tip(ui, repo, **opts):
6115 """show the tip revision (DEPRECATED)
6121 """show the tip revision (DEPRECATED)
6116
6122
6117 The tip revision (usually just called the tip) is the changeset
6123 The tip revision (usually just called the tip) is the changeset
6118 most recently added to the repository (and therefore the most
6124 most recently added to the repository (and therefore the most
6119 recently changed head).
6125 recently changed head).
6120
6126
6121 If you have just made a commit, that commit will be the tip. If
6127 If you have just made a commit, that commit will be the tip. If
6122 you have just pulled changes from another repository, the tip of
6128 you have just pulled changes from another repository, the tip of
6123 that repository becomes the current tip. The "tip" tag is special
6129 that repository becomes the current tip. The "tip" tag is special
6124 and cannot be renamed or assigned to a different changeset.
6130 and cannot be renamed or assigned to a different changeset.
6125
6131
6126 This command is deprecated, please use :hg:`heads` instead.
6132 This command is deprecated, please use :hg:`heads` instead.
6127
6133
6128 Returns 0 on success.
6134 Returns 0 on success.
6129 """
6135 """
6130 displayer = cmdutil.show_changeset(ui, repo, opts)
6136 displayer = cmdutil.show_changeset(ui, repo, opts)
6131 displayer.show(repo['tip'])
6137 displayer.show(repo['tip'])
6132 displayer.close()
6138 displayer.close()
6133
6139
6134 @command('unbundle',
6140 @command('unbundle',
6135 [('u', 'update', None,
6141 [('u', 'update', None,
6136 _('update to new branch head if changesets were unbundled'))],
6142 _('update to new branch head if changesets were unbundled'))],
6137 _('[-u] FILE...'))
6143 _('[-u] FILE...'))
6138 def unbundle(ui, repo, fname1, *fnames, **opts):
6144 def unbundle(ui, repo, fname1, *fnames, **opts):
6139 """apply one or more changegroup files
6145 """apply one or more changegroup files
6140
6146
6141 Apply one or more compressed changegroup files generated by the
6147 Apply one or more compressed changegroup files generated by the
6142 bundle command.
6148 bundle command.
6143
6149
6144 Returns 0 on success, 1 if an update has unresolved files.
6150 Returns 0 on success, 1 if an update has unresolved files.
6145 """
6151 """
6146 fnames = (fname1,) + fnames
6152 fnames = (fname1,) + fnames
6147
6153
6148 lock = repo.lock()
6154 lock = repo.lock()
6149 try:
6155 try:
6150 for fname in fnames:
6156 for fname in fnames:
6151 f = hg.openpath(ui, fname)
6157 f = hg.openpath(ui, fname)
6152 gen = exchange.readbundle(ui, f, fname)
6158 gen = exchange.readbundle(ui, f, fname)
6153 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6159 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6154 'bundle:' + fname)
6160 'bundle:' + fname)
6155 finally:
6161 finally:
6156 lock.release()
6162 lock.release()
6157
6163
6158 return postincoming(ui, repo, modheads, opts.get('update'), None)
6164 return postincoming(ui, repo, modheads, opts.get('update'), None)
6159
6165
6160 @command('^update|up|checkout|co',
6166 @command('^update|up|checkout|co',
6161 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6167 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6162 ('c', 'check', None,
6168 ('c', 'check', None,
6163 _('update across branches if no uncommitted changes')),
6169 _('update across branches if no uncommitted changes')),
6164 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6170 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6165 ('r', 'rev', '', _('revision'), _('REV'))
6171 ('r', 'rev', '', _('revision'), _('REV'))
6166 ] + mergetoolopts,
6172 ] + mergetoolopts,
6167 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6173 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6168 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6174 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6169 tool=None):
6175 tool=None):
6170 """update working directory (or switch revisions)
6176 """update working directory (or switch revisions)
6171
6177
6172 Update the repository's working directory to the specified
6178 Update the repository's working directory to the specified
6173 changeset. If no changeset is specified, update to the tip of the
6179 changeset. If no changeset is specified, update to the tip of the
6174 current named branch and move the current bookmark (see :hg:`help
6180 current named branch and move the current bookmark (see :hg:`help
6175 bookmarks`).
6181 bookmarks`).
6176
6182
6177 Update sets the working directory's parent revision to the specified
6183 Update sets the working directory's parent revision to the specified
6178 changeset (see :hg:`help parents`).
6184 changeset (see :hg:`help parents`).
6179
6185
6180 If the changeset is not a descendant or ancestor of the working
6186 If the changeset is not a descendant or ancestor of the working
6181 directory's parent, the update is aborted. With the -c/--check
6187 directory's parent, the update is aborted. With the -c/--check
6182 option, the working directory is checked for uncommitted changes; if
6188 option, the working directory is checked for uncommitted changes; if
6183 none are found, the working directory is updated to the specified
6189 none are found, the working directory is updated to the specified
6184 changeset.
6190 changeset.
6185
6191
6186 .. container:: verbose
6192 .. container:: verbose
6187
6193
6188 The following rules apply when the working directory contains
6194 The following rules apply when the working directory contains
6189 uncommitted changes:
6195 uncommitted changes:
6190
6196
6191 1. If neither -c/--check nor -C/--clean is specified, and if
6197 1. If neither -c/--check nor -C/--clean is specified, and if
6192 the requested changeset is an ancestor or descendant of
6198 the requested changeset is an ancestor or descendant of
6193 the working directory's parent, the uncommitted changes
6199 the working directory's parent, the uncommitted changes
6194 are merged into the requested changeset and the merged
6200 are merged into the requested changeset and the merged
6195 result is left uncommitted. If the requested changeset is
6201 result is left uncommitted. If the requested changeset is
6196 not an ancestor or descendant (that is, it is on another
6202 not an ancestor or descendant (that is, it is on another
6197 branch), the update is aborted and the uncommitted changes
6203 branch), the update is aborted and the uncommitted changes
6198 are preserved.
6204 are preserved.
6199
6205
6200 2. With the -c/--check option, the update is aborted and the
6206 2. With the -c/--check option, the update is aborted and the
6201 uncommitted changes are preserved.
6207 uncommitted changes are preserved.
6202
6208
6203 3. With the -C/--clean option, uncommitted changes are discarded and
6209 3. With the -C/--clean option, uncommitted changes are discarded and
6204 the working directory is updated to the requested changeset.
6210 the working directory is updated to the requested changeset.
6205
6211
6206 To cancel an uncommitted merge (and lose your changes), use
6212 To cancel an uncommitted merge (and lose your changes), use
6207 :hg:`update --clean .`.
6213 :hg:`update --clean .`.
6208
6214
6209 Use null as the changeset to remove the working directory (like
6215 Use null as the changeset to remove the working directory (like
6210 :hg:`clone -U`).
6216 :hg:`clone -U`).
6211
6217
6212 If you want to revert just one file to an older revision, use
6218 If you want to revert just one file to an older revision, use
6213 :hg:`revert [-r REV] NAME`.
6219 :hg:`revert [-r REV] NAME`.
6214
6220
6215 See :hg:`help dates` for a list of formats valid for -d/--date.
6221 See :hg:`help dates` for a list of formats valid for -d/--date.
6216
6222
6217 Returns 0 on success, 1 if there are unresolved files.
6223 Returns 0 on success, 1 if there are unresolved files.
6218 """
6224 """
6219 if rev and node:
6225 if rev and node:
6220 raise util.Abort(_("please specify just one revision"))
6226 raise util.Abort(_("please specify just one revision"))
6221
6227
6222 if rev is None or rev == '':
6228 if rev is None or rev == '':
6223 rev = node
6229 rev = node
6224
6230
6225 cmdutil.clearunfinished(repo)
6231 cmdutil.clearunfinished(repo)
6226
6232
6227 # with no argument, we also move the current bookmark, if any
6233 # with no argument, we also move the current bookmark, if any
6228 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6234 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6229
6235
6230 # if we defined a bookmark, we have to remember the original bookmark name
6236 # if we defined a bookmark, we have to remember the original bookmark name
6231 brev = rev
6237 brev = rev
6232 rev = scmutil.revsingle(repo, rev, rev).rev()
6238 rev = scmutil.revsingle(repo, rev, rev).rev()
6233
6239
6234 if check and clean:
6240 if check and clean:
6235 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6241 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6236
6242
6237 if date:
6243 if date:
6238 if rev is not None:
6244 if rev is not None:
6239 raise util.Abort(_("you can't specify a revision and a date"))
6245 raise util.Abort(_("you can't specify a revision and a date"))
6240 rev = cmdutil.finddate(ui, repo, date)
6246 rev = cmdutil.finddate(ui, repo, date)
6241
6247
6242 if check:
6248 if check:
6243 c = repo[None]
6249 c = repo[None]
6244 if c.dirty(merge=False, branch=False, missing=True):
6250 if c.dirty(merge=False, branch=False, missing=True):
6245 raise util.Abort(_("uncommitted changes"))
6251 raise util.Abort(_("uncommitted changes"))
6246 if rev is None:
6252 if rev is None:
6247 rev = repo[repo[None].branch()].rev()
6253 rev = repo[repo[None].branch()].rev()
6248 mergemod._checkunknown(repo, repo[None], repo[rev])
6254 mergemod._checkunknown(repo, repo[None], repo[rev])
6249
6255
6250 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6256 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6251
6257
6252 if clean:
6258 if clean:
6253 ret = hg.clean(repo, rev)
6259 ret = hg.clean(repo, rev)
6254 else:
6260 else:
6255 ret = hg.update(repo, rev)
6261 ret = hg.update(repo, rev)
6256
6262
6257 if not ret and movemarkfrom:
6263 if not ret and movemarkfrom:
6258 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6264 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6259 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6265 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6260 elif brev in repo._bookmarks:
6266 elif brev in repo._bookmarks:
6261 bookmarks.setcurrent(repo, brev)
6267 bookmarks.setcurrent(repo, brev)
6262 ui.status(_("(activating bookmark %s)\n") % brev)
6268 ui.status(_("(activating bookmark %s)\n") % brev)
6263 elif brev:
6269 elif brev:
6264 if repo._bookmarkcurrent:
6270 if repo._bookmarkcurrent:
6265 ui.status(_("(leaving bookmark %s)\n") %
6271 ui.status(_("(leaving bookmark %s)\n") %
6266 repo._bookmarkcurrent)
6272 repo._bookmarkcurrent)
6267 bookmarks.unsetcurrent(repo)
6273 bookmarks.unsetcurrent(repo)
6268
6274
6269 return ret
6275 return ret
6270
6276
6271 @command('verify', [])
6277 @command('verify', [])
6272 def verify(ui, repo):
6278 def verify(ui, repo):
6273 """verify the integrity of the repository
6279 """verify the integrity of the repository
6274
6280
6275 Verify the integrity of the current repository.
6281 Verify the integrity of the current repository.
6276
6282
6277 This will perform an extensive check of the repository's
6283 This will perform an extensive check of the repository's
6278 integrity, validating the hashes and checksums of each entry in
6284 integrity, validating the hashes and checksums of each entry in
6279 the changelog, manifest, and tracked files, as well as the
6285 the changelog, manifest, and tracked files, as well as the
6280 integrity of their crosslinks and indices.
6286 integrity of their crosslinks and indices.
6281
6287
6282 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6288 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6283 for more information about recovery from corruption of the
6289 for more information about recovery from corruption of the
6284 repository.
6290 repository.
6285
6291
6286 Returns 0 on success, 1 if errors are encountered.
6292 Returns 0 on success, 1 if errors are encountered.
6287 """
6293 """
6288 return hg.verify(repo)
6294 return hg.verify(repo)
6289
6295
6290 @command('version', [], norepo=True)
6296 @command('version', [], norepo=True)
6291 def version_(ui):
6297 def version_(ui):
6292 """output version and copyright information"""
6298 """output version and copyright information"""
6293 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6299 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6294 % util.version())
6300 % util.version())
6295 ui.status(_(
6301 ui.status(_(
6296 "(see http://mercurial.selenic.com for more information)\n"
6302 "(see http://mercurial.selenic.com for more information)\n"
6297 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6303 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6298 "This is free software; see the source for copying conditions. "
6304 "This is free software; see the source for copying conditions. "
6299 "There is NO\nwarranty; "
6305 "There is NO\nwarranty; "
6300 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6306 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6301 ))
6307 ))
6302
6308
6303 ui.note(_("\nEnabled extensions:\n\n"))
6309 ui.note(_("\nEnabled extensions:\n\n"))
6304 if ui.verbose:
6310 if ui.verbose:
6305 # format names and versions into columns
6311 # format names and versions into columns
6306 names = []
6312 names = []
6307 vers = []
6313 vers = []
6308 for name, module in extensions.extensions():
6314 for name, module in extensions.extensions():
6309 names.append(name)
6315 names.append(name)
6310 vers.append(extensions.moduleversion(module))
6316 vers.append(extensions.moduleversion(module))
6311 if names:
6317 if names:
6312 maxnamelen = max(len(n) for n in names)
6318 maxnamelen = max(len(n) for n in names)
6313 for i, name in enumerate(names):
6319 for i, name in enumerate(names):
6314 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6320 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,473 +1,504
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo 'root' >root
3 $ echo 'root' >root
4 $ hg add root
4 $ hg add root
5 $ hg commit -d '0 0' -m "Adding root node"
5 $ hg commit -d '0 0' -m "Adding root node"
6
6
7 $ echo 'a' >a
7 $ echo 'a' >a
8 $ hg add a
8 $ hg add a
9 $ hg branch a
9 $ hg branch a
10 marked working directory as branch a
10 marked working directory as branch a
11 (branches are permanent and global, did you want a bookmark?)
11 (branches are permanent and global, did you want a bookmark?)
12 $ hg commit -d '1 0' -m "Adding a branch"
12 $ hg commit -d '1 0' -m "Adding a branch"
13
13
14 $ hg branch q
14 $ hg branch q
15 marked working directory as branch q
15 marked working directory as branch q
16 (branches are permanent and global, did you want a bookmark?)
16 (branches are permanent and global, did you want a bookmark?)
17 $ echo 'aa' >a
17 $ echo 'aa' >a
18 $ hg branch -C
18 $ hg branch -C
19 reset working directory to branch a
19 reset working directory to branch a
20 $ hg commit -d '2 0' -m "Adding to a branch"
20 $ hg commit -d '2 0' -m "Adding to a branch"
21
21
22 $ hg update -C 0
22 $ hg update -C 0
23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
24 $ echo 'b' >b
24 $ echo 'b' >b
25 $ hg add b
25 $ hg add b
26 $ hg branch b
26 $ hg branch b
27 marked working directory as branch b
27 marked working directory as branch b
28 (branches are permanent and global, did you want a bookmark?)
28 (branches are permanent and global, did you want a bookmark?)
29 $ hg commit -d '2 0' -m "Adding b branch"
29 $ hg commit -d '2 0' -m "Adding b branch"
30
30
31 $ echo 'bh1' >bh1
31 $ echo 'bh1' >bh1
32 $ hg add bh1
32 $ hg add bh1
33 $ hg commit -d '3 0' -m "Adding b branch head 1"
33 $ hg commit -d '3 0' -m "Adding b branch head 1"
34
34
35 $ hg update -C 2
35 $ hg update -C 2
36 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
36 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
37 $ echo 'bh2' >bh2
37 $ echo 'bh2' >bh2
38 $ hg add bh2
38 $ hg add bh2
39 $ hg commit -d '4 0' -m "Adding b branch head 2"
39 $ hg commit -d '4 0' -m "Adding b branch head 2"
40
40
41 $ echo 'c' >c
41 $ echo 'c' >c
42 $ hg add c
42 $ hg add c
43 $ hg branch c
43 $ hg branch c
44 marked working directory as branch c
44 marked working directory as branch c
45 (branches are permanent and global, did you want a bookmark?)
45 (branches are permanent and global, did you want a bookmark?)
46 $ hg commit -d '5 0' -m "Adding c branch"
46 $ hg commit -d '5 0' -m "Adding c branch"
47
47
48 reserved names
48 reserved names
49
49
50 $ hg branch tip
50 $ hg branch tip
51 abort: the name 'tip' is reserved
51 abort: the name 'tip' is reserved
52 [255]
52 [255]
53 $ hg branch null
53 $ hg branch null
54 abort: the name 'null' is reserved
54 abort: the name 'null' is reserved
55 [255]
55 [255]
56 $ hg branch .
56 $ hg branch .
57 abort: the name '.' is reserved
57 abort: the name '.' is reserved
58 [255]
58 [255]
59
59
60 invalid characters
60 invalid characters
61
61
62 $ hg branch 'foo:bar'
62 $ hg branch 'foo:bar'
63 abort: ':' cannot be used in a name
63 abort: ':' cannot be used in a name
64 [255]
64 [255]
65
65
66 $ hg branch 'foo
66 $ hg branch 'foo
67 > bar'
67 > bar'
68 abort: '\n' cannot be used in a name
68 abort: '\n' cannot be used in a name
69 [255]
69 [255]
70
70
71 trailing or leading spaces should be stripped before testing duplicates
71 trailing or leading spaces should be stripped before testing duplicates
72
72
73 $ hg branch 'b '
73 $ hg branch 'b '
74 abort: a branch of the same name already exists
74 abort: a branch of the same name already exists
75 (use 'hg update' to switch to it)
75 (use 'hg update' to switch to it)
76 [255]
76 [255]
77
77
78 $ hg branch ' b'
78 $ hg branch ' b'
79 abort: a branch of the same name already exists
79 abort: a branch of the same name already exists
80 (use 'hg update' to switch to it)
80 (use 'hg update' to switch to it)
81 [255]
81 [255]
82
82
83 verify update will accept invalid legacy branch names
83 verify update will accept invalid legacy branch names
84
84
85 $ hg init test-invalid-branch-name
85 $ hg init test-invalid-branch-name
86 $ cd test-invalid-branch-name
86 $ cd test-invalid-branch-name
87 $ hg pull -u "$TESTDIR"/bundles/test-invalid-branch-name.hg
87 $ hg pull -u "$TESTDIR"/bundles/test-invalid-branch-name.hg
88 pulling from *test-invalid-branch-name.hg (glob)
88 pulling from *test-invalid-branch-name.hg (glob)
89 requesting all changes
89 requesting all changes
90 adding changesets
90 adding changesets
91 adding manifests
91 adding manifests
92 adding file changes
92 adding file changes
93 added 3 changesets with 3 changes to 2 files
93 added 3 changesets with 3 changes to 2 files
94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
95
95
96 $ hg update '"colon:test"'
96 $ hg update '"colon:test"'
97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 $ cd ..
98 $ cd ..
99
99
100 $ echo 'd' >d
100 $ echo 'd' >d
101 $ hg add d
101 $ hg add d
102 $ hg branch 'a branch name much longer than the default justification used by branches'
102 $ hg branch 'a branch name much longer than the default justification used by branches'
103 marked working directory as branch a branch name much longer than the default justification used by branches
103 marked working directory as branch a branch name much longer than the default justification used by branches
104 (branches are permanent and global, did you want a bookmark?)
104 (branches are permanent and global, did you want a bookmark?)
105 $ hg commit -d '6 0' -m "Adding d branch"
105 $ hg commit -d '6 0' -m "Adding d branch"
106
106
107 $ hg branches
107 $ hg branches
108 a branch name much longer than the default justification used by branches 7:10ff5895aa57
108 a branch name much longer than the default justification used by branches 7:10ff5895aa57
109 b 4:aee39cd168d0
109 b 4:aee39cd168d0
110 c 6:589736a22561 (inactive)
110 c 6:589736a22561 (inactive)
111 a 5:d8cbc61dbaa6 (inactive)
111 a 5:d8cbc61dbaa6 (inactive)
112 default 0:19709c5a4e75 (inactive)
112 default 0:19709c5a4e75 (inactive)
113
113
114 -------
114 -------
115
115
116 $ hg branches -a
116 $ hg branches -a
117 a branch name much longer than the default justification used by branches 7:10ff5895aa57
117 a branch name much longer than the default justification used by branches 7:10ff5895aa57
118 b 4:aee39cd168d0
118 b 4:aee39cd168d0
119
119
120 --- Branch a
120 --- Branch a
121
121
122 $ hg log -b a
122 $ hg log -b a
123 changeset: 5:d8cbc61dbaa6
123 changeset: 5:d8cbc61dbaa6
124 branch: a
124 branch: a
125 parent: 2:881fe2b92ad0
125 parent: 2:881fe2b92ad0
126 user: test
126 user: test
127 date: Thu Jan 01 00:00:04 1970 +0000
127 date: Thu Jan 01 00:00:04 1970 +0000
128 summary: Adding b branch head 2
128 summary: Adding b branch head 2
129
129
130 changeset: 2:881fe2b92ad0
130 changeset: 2:881fe2b92ad0
131 branch: a
131 branch: a
132 user: test
132 user: test
133 date: Thu Jan 01 00:00:02 1970 +0000
133 date: Thu Jan 01 00:00:02 1970 +0000
134 summary: Adding to a branch
134 summary: Adding to a branch
135
135
136 changeset: 1:dd6b440dd85a
136 changeset: 1:dd6b440dd85a
137 branch: a
137 branch: a
138 user: test
138 user: test
139 date: Thu Jan 01 00:00:01 1970 +0000
139 date: Thu Jan 01 00:00:01 1970 +0000
140 summary: Adding a branch
140 summary: Adding a branch
141
141
142
142
143 ---- Branch b
143 ---- Branch b
144
144
145 $ hg log -b b
145 $ hg log -b b
146 changeset: 4:aee39cd168d0
146 changeset: 4:aee39cd168d0
147 branch: b
147 branch: b
148 user: test
148 user: test
149 date: Thu Jan 01 00:00:03 1970 +0000
149 date: Thu Jan 01 00:00:03 1970 +0000
150 summary: Adding b branch head 1
150 summary: Adding b branch head 1
151
151
152 changeset: 3:ac22033332d1
152 changeset: 3:ac22033332d1
153 branch: b
153 branch: b
154 parent: 0:19709c5a4e75
154 parent: 0:19709c5a4e75
155 user: test
155 user: test
156 date: Thu Jan 01 00:00:02 1970 +0000
156 date: Thu Jan 01 00:00:02 1970 +0000
157 summary: Adding b branch
157 summary: Adding b branch
158
158
159
159
160 ---- going to test branch closing
160 ---- going to test branch closing
161
161
162 $ hg branches
162 $ hg branches
163 a branch name much longer than the default justification used by branches 7:10ff5895aa57
163 a branch name much longer than the default justification used by branches 7:10ff5895aa57
164 b 4:aee39cd168d0
164 b 4:aee39cd168d0
165 c 6:589736a22561 (inactive)
165 c 6:589736a22561 (inactive)
166 a 5:d8cbc61dbaa6 (inactive)
166 a 5:d8cbc61dbaa6 (inactive)
167 default 0:19709c5a4e75 (inactive)
167 default 0:19709c5a4e75 (inactive)
168 $ hg up -C b
168 $ hg up -C b
169 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
169 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
170 $ echo 'xxx1' >> b
170 $ echo 'xxx1' >> b
171 $ hg commit -d '7 0' -m 'adding cset to branch b'
171 $ hg commit -d '7 0' -m 'adding cset to branch b'
172 $ hg up -C aee39cd168d0
172 $ hg up -C aee39cd168d0
173 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
173 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 $ echo 'xxx2' >> b
174 $ echo 'xxx2' >> b
175 $ hg commit -d '8 0' -m 'adding head to branch b'
175 $ hg commit -d '8 0' -m 'adding head to branch b'
176 created new head
176 created new head
177 $ echo 'xxx3' >> b
177 $ echo 'xxx3' >> b
178 $ hg commit -d '9 0' -m 'adding another cset to branch b'
178 $ hg commit -d '9 0' -m 'adding another cset to branch b'
179 $ hg branches
179 $ hg branches
180 b 10:bfbe841b666e
180 b 10:bfbe841b666e
181 a branch name much longer than the default justification used by branches 7:10ff5895aa57
181 a branch name much longer than the default justification used by branches 7:10ff5895aa57
182 c 6:589736a22561 (inactive)
182 c 6:589736a22561 (inactive)
183 a 5:d8cbc61dbaa6 (inactive)
183 a 5:d8cbc61dbaa6 (inactive)
184 default 0:19709c5a4e75 (inactive)
184 default 0:19709c5a4e75 (inactive)
185 $ hg heads --closed
185 $ hg heads --closed
186 changeset: 10:bfbe841b666e
186 changeset: 10:bfbe841b666e
187 branch: b
187 branch: b
188 tag: tip
188 tag: tip
189 user: test
189 user: test
190 date: Thu Jan 01 00:00:09 1970 +0000
190 date: Thu Jan 01 00:00:09 1970 +0000
191 summary: adding another cset to branch b
191 summary: adding another cset to branch b
192
192
193 changeset: 8:eebb944467c9
193 changeset: 8:eebb944467c9
194 branch: b
194 branch: b
195 parent: 4:aee39cd168d0
195 parent: 4:aee39cd168d0
196 user: test
196 user: test
197 date: Thu Jan 01 00:00:07 1970 +0000
197 date: Thu Jan 01 00:00:07 1970 +0000
198 summary: adding cset to branch b
198 summary: adding cset to branch b
199
199
200 changeset: 7:10ff5895aa57
200 changeset: 7:10ff5895aa57
201 branch: a branch name much longer than the default justification used by branches
201 branch: a branch name much longer than the default justification used by branches
202 user: test
202 user: test
203 date: Thu Jan 01 00:00:06 1970 +0000
203 date: Thu Jan 01 00:00:06 1970 +0000
204 summary: Adding d branch
204 summary: Adding d branch
205
205
206 changeset: 6:589736a22561
206 changeset: 6:589736a22561
207 branch: c
207 branch: c
208 user: test
208 user: test
209 date: Thu Jan 01 00:00:05 1970 +0000
209 date: Thu Jan 01 00:00:05 1970 +0000
210 summary: Adding c branch
210 summary: Adding c branch
211
211
212 changeset: 5:d8cbc61dbaa6
212 changeset: 5:d8cbc61dbaa6
213 branch: a
213 branch: a
214 parent: 2:881fe2b92ad0
214 parent: 2:881fe2b92ad0
215 user: test
215 user: test
216 date: Thu Jan 01 00:00:04 1970 +0000
216 date: Thu Jan 01 00:00:04 1970 +0000
217 summary: Adding b branch head 2
217 summary: Adding b branch head 2
218
218
219 changeset: 0:19709c5a4e75
219 changeset: 0:19709c5a4e75
220 user: test
220 user: test
221 date: Thu Jan 01 00:00:00 1970 +0000
221 date: Thu Jan 01 00:00:00 1970 +0000
222 summary: Adding root node
222 summary: Adding root node
223
223
224 $ hg heads
224 $ hg heads
225 changeset: 10:bfbe841b666e
225 changeset: 10:bfbe841b666e
226 branch: b
226 branch: b
227 tag: tip
227 tag: tip
228 user: test
228 user: test
229 date: Thu Jan 01 00:00:09 1970 +0000
229 date: Thu Jan 01 00:00:09 1970 +0000
230 summary: adding another cset to branch b
230 summary: adding another cset to branch b
231
231
232 changeset: 8:eebb944467c9
232 changeset: 8:eebb944467c9
233 branch: b
233 branch: b
234 parent: 4:aee39cd168d0
234 parent: 4:aee39cd168d0
235 user: test
235 user: test
236 date: Thu Jan 01 00:00:07 1970 +0000
236 date: Thu Jan 01 00:00:07 1970 +0000
237 summary: adding cset to branch b
237 summary: adding cset to branch b
238
238
239 changeset: 7:10ff5895aa57
239 changeset: 7:10ff5895aa57
240 branch: a branch name much longer than the default justification used by branches
240 branch: a branch name much longer than the default justification used by branches
241 user: test
241 user: test
242 date: Thu Jan 01 00:00:06 1970 +0000
242 date: Thu Jan 01 00:00:06 1970 +0000
243 summary: Adding d branch
243 summary: Adding d branch
244
244
245 changeset: 6:589736a22561
245 changeset: 6:589736a22561
246 branch: c
246 branch: c
247 user: test
247 user: test
248 date: Thu Jan 01 00:00:05 1970 +0000
248 date: Thu Jan 01 00:00:05 1970 +0000
249 summary: Adding c branch
249 summary: Adding c branch
250
250
251 changeset: 5:d8cbc61dbaa6
251 changeset: 5:d8cbc61dbaa6
252 branch: a
252 branch: a
253 parent: 2:881fe2b92ad0
253 parent: 2:881fe2b92ad0
254 user: test
254 user: test
255 date: Thu Jan 01 00:00:04 1970 +0000
255 date: Thu Jan 01 00:00:04 1970 +0000
256 summary: Adding b branch head 2
256 summary: Adding b branch head 2
257
257
258 changeset: 0:19709c5a4e75
258 changeset: 0:19709c5a4e75
259 user: test
259 user: test
260 date: Thu Jan 01 00:00:00 1970 +0000
260 date: Thu Jan 01 00:00:00 1970 +0000
261 summary: Adding root node
261 summary: Adding root node
262
262
263 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
263 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
264 $ hg branches -a
264 $ hg branches -a
265 b 8:eebb944467c9
265 b 8:eebb944467c9
266 a branch name much longer than the default justification used by branches 7:10ff5895aa57
266 a branch name much longer than the default justification used by branches 7:10ff5895aa57
267 $ hg up -C b
267 $ hg up -C b
268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
269 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
270 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
270 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
271 abort: can only close branch heads
271 abort: can only close branch heads
272 [255]
272 [255]
273
273
274 $ hg log -r tip --debug
274 $ hg log -r tip --debug
275 changeset: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
275 changeset: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
276 branch: b
276 branch: b
277 tag: tip
277 tag: tip
278 phase: draft
278 phase: draft
279 parent: 8:eebb944467c9fb9651ed232aeaf31b3c0a7fc6c1
279 parent: 8:eebb944467c9fb9651ed232aeaf31b3c0a7fc6c1
280 parent: -1:0000000000000000000000000000000000000000
280 parent: -1:0000000000000000000000000000000000000000
281 manifest: 8:6f9ed32d2b310e391a4f107d5f0f071df785bfee
281 manifest: 8:6f9ed32d2b310e391a4f107d5f0f071df785bfee
282 user: test
282 user: test
283 date: Thu Jan 01 00:00:09 1970 +0000
283 date: Thu Jan 01 00:00:09 1970 +0000
284 extra: branch=b
284 extra: branch=b
285 extra: close=1
285 extra: close=1
286 description:
286 description:
287 close this part branch too
287 close this part branch too
288
288
289
289
290 --- b branch should be inactive
290 --- b branch should be inactive
291
291
292 $ hg branches
292 $ hg branches
293 a branch name much longer than the default justification used by branches 7:10ff5895aa57
293 a branch name much longer than the default justification used by branches 7:10ff5895aa57
294 c 6:589736a22561 (inactive)
294 c 6:589736a22561 (inactive)
295 a 5:d8cbc61dbaa6 (inactive)
295 a 5:d8cbc61dbaa6 (inactive)
296 default 0:19709c5a4e75 (inactive)
296 default 0:19709c5a4e75 (inactive)
297 $ hg branches -c
297 $ hg branches -c
298 a branch name much longer than the default justification used by branches 7:10ff5895aa57
298 a branch name much longer than the default justification used by branches 7:10ff5895aa57
299 b 12:e3d49c0575d8 (closed)
299 b 12:e3d49c0575d8 (closed)
300 c 6:589736a22561 (inactive)
300 c 6:589736a22561 (inactive)
301 a 5:d8cbc61dbaa6 (inactive)
301 a 5:d8cbc61dbaa6 (inactive)
302 default 0:19709c5a4e75 (inactive)
302 default 0:19709c5a4e75 (inactive)
303 $ hg branches -a
303 $ hg branches -a
304 a branch name much longer than the default justification used by branches 7:10ff5895aa57
304 a branch name much longer than the default justification used by branches 7:10ff5895aa57
305 $ hg branches -q
305 $ hg branches -q
306 a branch name much longer than the default justification used by branches
306 a branch name much longer than the default justification used by branches
307 c
307 c
308 a
308 a
309 default
309 default
310 $ hg heads b
310 $ hg heads b
311 no open branch heads found on branches b
311 no open branch heads found on branches b
312 [1]
312 [1]
313 $ hg heads --closed b
313 $ hg heads --closed b
314 changeset: 12:e3d49c0575d8
314 changeset: 12:e3d49c0575d8
315 branch: b
315 branch: b
316 tag: tip
316 tag: tip
317 parent: 8:eebb944467c9
317 parent: 8:eebb944467c9
318 user: test
318 user: test
319 date: Thu Jan 01 00:00:09 1970 +0000
319 date: Thu Jan 01 00:00:09 1970 +0000
320 summary: close this part branch too
320 summary: close this part branch too
321
321
322 changeset: 11:d3f163457ebf
322 changeset: 11:d3f163457ebf
323 branch: b
323 branch: b
324 user: test
324 user: test
325 date: Thu Jan 01 00:00:09 1970 +0000
325 date: Thu Jan 01 00:00:09 1970 +0000
326 summary: prune bad branch
326 summary: prune bad branch
327
327
328 $ echo 'xxx4' >> b
328 $ echo 'xxx4' >> b
329 $ hg commit -d '9 0' -m 'reopen branch with a change'
329 $ hg commit -d '9 0' -m 'reopen branch with a change'
330 reopening closed branch head 12
330 reopening closed branch head 12
331
331
332 --- branch b is back in action
332 --- branch b is back in action
333
333
334 $ hg branches -a
334 $ hg branches -a
335 b 13:e23b5505d1ad
335 b 13:e23b5505d1ad
336 a branch name much longer than the default justification used by branches 7:10ff5895aa57
336 a branch name much longer than the default justification used by branches 7:10ff5895aa57
337
337
338 ---- test heads listings
338 ---- test heads listings
339
339
340 $ hg heads
340 $ hg heads
341 changeset: 13:e23b5505d1ad
341 changeset: 13:e23b5505d1ad
342 branch: b
342 branch: b
343 tag: tip
343 tag: tip
344 user: test
344 user: test
345 date: Thu Jan 01 00:00:09 1970 +0000
345 date: Thu Jan 01 00:00:09 1970 +0000
346 summary: reopen branch with a change
346 summary: reopen branch with a change
347
347
348 changeset: 7:10ff5895aa57
348 changeset: 7:10ff5895aa57
349 branch: a branch name much longer than the default justification used by branches
349 branch: a branch name much longer than the default justification used by branches
350 user: test
350 user: test
351 date: Thu Jan 01 00:00:06 1970 +0000
351 date: Thu Jan 01 00:00:06 1970 +0000
352 summary: Adding d branch
352 summary: Adding d branch
353
353
354 changeset: 6:589736a22561
354 changeset: 6:589736a22561
355 branch: c
355 branch: c
356 user: test
356 user: test
357 date: Thu Jan 01 00:00:05 1970 +0000
357 date: Thu Jan 01 00:00:05 1970 +0000
358 summary: Adding c branch
358 summary: Adding c branch
359
359
360 changeset: 5:d8cbc61dbaa6
360 changeset: 5:d8cbc61dbaa6
361 branch: a
361 branch: a
362 parent: 2:881fe2b92ad0
362 parent: 2:881fe2b92ad0
363 user: test
363 user: test
364 date: Thu Jan 01 00:00:04 1970 +0000
364 date: Thu Jan 01 00:00:04 1970 +0000
365 summary: Adding b branch head 2
365 summary: Adding b branch head 2
366
366
367 changeset: 0:19709c5a4e75
367 changeset: 0:19709c5a4e75
368 user: test
368 user: test
369 date: Thu Jan 01 00:00:00 1970 +0000
369 date: Thu Jan 01 00:00:00 1970 +0000
370 summary: Adding root node
370 summary: Adding root node
371
371
372
372
373 branch default
373 branch default
374
374
375 $ hg heads default
375 $ hg heads default
376 changeset: 0:19709c5a4e75
376 changeset: 0:19709c5a4e75
377 user: test
377 user: test
378 date: Thu Jan 01 00:00:00 1970 +0000
378 date: Thu Jan 01 00:00:00 1970 +0000
379 summary: Adding root node
379 summary: Adding root node
380
380
381
381
382 branch a
382 branch a
383
383
384 $ hg heads a
384 $ hg heads a
385 changeset: 5:d8cbc61dbaa6
385 changeset: 5:d8cbc61dbaa6
386 branch: a
386 branch: a
387 parent: 2:881fe2b92ad0
387 parent: 2:881fe2b92ad0
388 user: test
388 user: test
389 date: Thu Jan 01 00:00:04 1970 +0000
389 date: Thu Jan 01 00:00:04 1970 +0000
390 summary: Adding b branch head 2
390 summary: Adding b branch head 2
391
391
392 $ hg heads --active a
392 $ hg heads --active a
393 no open branch heads found on branches a
393 no open branch heads found on branches a
394 [1]
394 [1]
395
395
396 branch b
396 branch b
397
397
398 $ hg heads b
398 $ hg heads b
399 changeset: 13:e23b5505d1ad
399 changeset: 13:e23b5505d1ad
400 branch: b
400 branch: b
401 tag: tip
401 tag: tip
402 user: test
402 user: test
403 date: Thu Jan 01 00:00:09 1970 +0000
403 date: Thu Jan 01 00:00:09 1970 +0000
404 summary: reopen branch with a change
404 summary: reopen branch with a change
405
405
406 $ hg heads --closed b
406 $ hg heads --closed b
407 changeset: 13:e23b5505d1ad
407 changeset: 13:e23b5505d1ad
408 branch: b
408 branch: b
409 tag: tip
409 tag: tip
410 user: test
410 user: test
411 date: Thu Jan 01 00:00:09 1970 +0000
411 date: Thu Jan 01 00:00:09 1970 +0000
412 summary: reopen branch with a change
412 summary: reopen branch with a change
413
413
414 changeset: 11:d3f163457ebf
414 changeset: 11:d3f163457ebf
415 branch: b
415 branch: b
416 user: test
416 user: test
417 date: Thu Jan 01 00:00:09 1970 +0000
417 date: Thu Jan 01 00:00:09 1970 +0000
418 summary: prune bad branch
418 summary: prune bad branch
419
419
420 default branch colors:
420 default branch colors:
421
421
422 $ echo "[extensions]" >> $HGRCPATH
422 $ echo "[extensions]" >> $HGRCPATH
423 $ echo "color =" >> $HGRCPATH
423 $ echo "color =" >> $HGRCPATH
424 $ echo "[color]" >> $HGRCPATH
424 $ echo "[color]" >> $HGRCPATH
425 $ echo "mode = ansi" >> $HGRCPATH
425 $ echo "mode = ansi" >> $HGRCPATH
426
426
427 $ hg up -C c
427 $ hg up -C c
428 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
428 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
429 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
429 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
430 $ hg up -C b
430 $ hg up -C b
431 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
431 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
432 $ hg branches --color=always
432 $ hg branches --color=always
433 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
433 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
434 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
434 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
435 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
435 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
436 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
436 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
437
437
438 default closed branch color:
438 default closed branch color:
439
439
440 $ hg branches --color=always --closed
440 $ hg branches --color=always --closed
441 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
441 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
442 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
442 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
443 \x1b[0;30;1mc\x1b[0m \x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
443 \x1b[0;30;1mc\x1b[0m \x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
444 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
444 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
445 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
445 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
446
446
447 $ echo "[extensions]" >> $HGRCPATH
447 $ echo "[extensions]" >> $HGRCPATH
448 $ echo "color =" >> $HGRCPATH
448 $ echo "color =" >> $HGRCPATH
449 $ echo "[color]" >> $HGRCPATH
449 $ echo "[color]" >> $HGRCPATH
450 $ echo "branches.active = green" >> $HGRCPATH
450 $ echo "branches.active = green" >> $HGRCPATH
451 $ echo "branches.closed = blue" >> $HGRCPATH
451 $ echo "branches.closed = blue" >> $HGRCPATH
452 $ echo "branches.current = red" >> $HGRCPATH
452 $ echo "branches.current = red" >> $HGRCPATH
453 $ echo "branches.inactive = magenta" >> $HGRCPATH
453 $ echo "branches.inactive = magenta" >> $HGRCPATH
454 $ echo "log.changeset = cyan" >> $HGRCPATH
454 $ echo "log.changeset = cyan" >> $HGRCPATH
455
455
456 custom branch colors:
456 custom branch colors:
457
457
458 $ hg branches --color=always
458 $ hg branches --color=always
459 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
459 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
460 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
460 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
461 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
461 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
462 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
462 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
463
463
464 custom closed branch color:
464 custom closed branch color:
465
465
466 $ hg branches --color=always --closed
466 $ hg branches --color=always --closed
467 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
467 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
468 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
468 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
469 \x1b[0;34mc\x1b[0m \x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
469 \x1b[0;34mc\x1b[0m \x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
470 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
470 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
471 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
471 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
472
472
473 template output:
474
475 $ hg branches -Tjson --closed
476 [
477 {
478 "branch": "b",
479 "node": "e23b5505d1ad24aab6f84fd8c7cb8cd8e5e93be0",
480 "rev": 13
481 },
482 {
483 "branch": "a branch name much longer than the default justification used by branches",
484 "node": "10ff5895aa5793bd378da574af8cec8ea408d831",
485 "rev": 7
486 },
487 {
488 "branch": "c",
489 "node": "f894c25619d3f1484639d81be950e0a07bc6f1f6",
490 "rev": 14
491 },
492 {
493 "branch": "a",
494 "node": "d8cbc61dbaa6dc817175d1e301eecb863f280832",
495 "rev": 5
496 },
497 {
498 "branch": "default",
499 "node": "19709c5a4e75bf938f8e349aff97438539bb729e",
500 "rev": 0
501 }
502 ]
503
473 $ cd ..
504 $ cd ..
@@ -1,336 +1,336
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 config
16 config
17 copy
17 copy
18 diff
18 diff
19 export
19 export
20 files
20 files
21 forget
21 forget
22 graft
22 graft
23 grep
23 grep
24 heads
24 heads
25 help
25 help
26 identify
26 identify
27 import
27 import
28 incoming
28 incoming
29 init
29 init
30 locate
30 locate
31 log
31 log
32 manifest
32 manifest
33 merge
33 merge
34 outgoing
34 outgoing
35 parents
35 parents
36 paths
36 paths
37 phase
37 phase
38 pull
38 pull
39 push
39 push
40 recover
40 recover
41 remove
41 remove
42 rename
42 rename
43 resolve
43 resolve
44 revert
44 revert
45 rollback
45 rollback
46 root
46 root
47 serve
47 serve
48 status
48 status
49 summary
49 summary
50 tag
50 tag
51 tags
51 tags
52 tip
52 tip
53 unbundle
53 unbundle
54 update
54 update
55 verify
55 verify
56 version
56 version
57
57
58 Show all commands that start with "a"
58 Show all commands that start with "a"
59 $ hg debugcomplete a
59 $ hg debugcomplete a
60 add
60 add
61 addremove
61 addremove
62 annotate
62 annotate
63 archive
63 archive
64
64
65 Do not show debug commands if there are other candidates
65 Do not show debug commands if there are other candidates
66 $ hg debugcomplete d
66 $ hg debugcomplete d
67 diff
67 diff
68
68
69 Show debug commands if there are no other candidates
69 Show debug commands if there are no other candidates
70 $ hg debugcomplete debug
70 $ hg debugcomplete debug
71 debugancestor
71 debugancestor
72 debugbuilddag
72 debugbuilddag
73 debugbundle
73 debugbundle
74 debugcheckstate
74 debugcheckstate
75 debugcommands
75 debugcommands
76 debugcomplete
76 debugcomplete
77 debugconfig
77 debugconfig
78 debugdag
78 debugdag
79 debugdata
79 debugdata
80 debugdate
80 debugdate
81 debugdirstate
81 debugdirstate
82 debugdiscovery
82 debugdiscovery
83 debugfileset
83 debugfileset
84 debugfsinfo
84 debugfsinfo
85 debuggetbundle
85 debuggetbundle
86 debugignore
86 debugignore
87 debugindex
87 debugindex
88 debugindexdot
88 debugindexdot
89 debuginstall
89 debuginstall
90 debugknown
90 debugknown
91 debuglabelcomplete
91 debuglabelcomplete
92 debuglocks
92 debuglocks
93 debugobsolete
93 debugobsolete
94 debugpathcomplete
94 debugpathcomplete
95 debugpushkey
95 debugpushkey
96 debugpvec
96 debugpvec
97 debugrebuilddirstate
97 debugrebuilddirstate
98 debugrename
98 debugrename
99 debugrevlog
99 debugrevlog
100 debugrevspec
100 debugrevspec
101 debugsetparents
101 debugsetparents
102 debugsub
102 debugsub
103 debugsuccessorssets
103 debugsuccessorssets
104 debugwalk
104 debugwalk
105 debugwireargs
105 debugwireargs
106
106
107 Do not show the alias of a debug command if there are other candidates
107 Do not show the alias of a debug command if there are other candidates
108 (this should hide rawcommit)
108 (this should hide rawcommit)
109 $ hg debugcomplete r
109 $ hg debugcomplete r
110 recover
110 recover
111 remove
111 remove
112 rename
112 rename
113 resolve
113 resolve
114 revert
114 revert
115 rollback
115 rollback
116 root
116 root
117 Show the alias of a debug command if there are no other candidates
117 Show the alias of a debug command if there are no other candidates
118 $ hg debugcomplete rawc
118 $ hg debugcomplete rawc
119
119
120
120
121 Show the global options
121 Show the global options
122 $ hg debugcomplete --options | sort
122 $ hg debugcomplete --options | sort
123 --config
123 --config
124 --cwd
124 --cwd
125 --debug
125 --debug
126 --debugger
126 --debugger
127 --encoding
127 --encoding
128 --encodingmode
128 --encodingmode
129 --help
129 --help
130 --hidden
130 --hidden
131 --noninteractive
131 --noninteractive
132 --profile
132 --profile
133 --quiet
133 --quiet
134 --repository
134 --repository
135 --time
135 --time
136 --traceback
136 --traceback
137 --verbose
137 --verbose
138 --version
138 --version
139 -R
139 -R
140 -h
140 -h
141 -q
141 -q
142 -v
142 -v
143 -y
143 -y
144
144
145 Show the options for the "serve" command
145 Show the options for the "serve" command
146 $ hg debugcomplete --options serve | sort
146 $ hg debugcomplete --options serve | sort
147 --accesslog
147 --accesslog
148 --address
148 --address
149 --certificate
149 --certificate
150 --cmdserver
150 --cmdserver
151 --config
151 --config
152 --cwd
152 --cwd
153 --daemon
153 --daemon
154 --daemon-pipefds
154 --daemon-pipefds
155 --debug
155 --debug
156 --debugger
156 --debugger
157 --encoding
157 --encoding
158 --encodingmode
158 --encodingmode
159 --errorlog
159 --errorlog
160 --help
160 --help
161 --hidden
161 --hidden
162 --ipv6
162 --ipv6
163 --name
163 --name
164 --noninteractive
164 --noninteractive
165 --pid-file
165 --pid-file
166 --port
166 --port
167 --prefix
167 --prefix
168 --profile
168 --profile
169 --quiet
169 --quiet
170 --repository
170 --repository
171 --stdio
171 --stdio
172 --style
172 --style
173 --templates
173 --templates
174 --time
174 --time
175 --traceback
175 --traceback
176 --verbose
176 --verbose
177 --version
177 --version
178 --web-conf
178 --web-conf
179 -6
179 -6
180 -A
180 -A
181 -E
181 -E
182 -R
182 -R
183 -a
183 -a
184 -d
184 -d
185 -h
185 -h
186 -n
186 -n
187 -p
187 -p
188 -q
188 -q
189 -t
189 -t
190 -v
190 -v
191 -y
191 -y
192
192
193 Show an error if we use --options with an ambiguous abbreviation
193 Show an error if we use --options with an ambiguous abbreviation
194 $ hg debugcomplete --options s
194 $ hg debugcomplete --options s
195 hg: command 's' is ambiguous:
195 hg: command 's' is ambiguous:
196 serve showconfig status summary
196 serve showconfig status summary
197 [255]
197 [255]
198
198
199 Show all commands + options
199 Show all commands + options
200 $ hg debugcommands
200 $ hg debugcommands
201 add: include, exclude, subrepos, dry-run
201 add: include, exclude, subrepos, dry-run
202 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
202 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
203 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
203 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
204 commit: addremove, close-branch, amend, secret, edit, include, exclude, message, logfile, date, user, subrepos
204 commit: addremove, close-branch, amend, secret, edit, include, exclude, message, logfile, date, user, subrepos
205 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
205 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
206 export: output, switch-parent, rev, text, git, nodates
206 export: output, switch-parent, rev, text, git, nodates
207 forget: include, exclude
207 forget: include, exclude
208 init: ssh, remotecmd, insecure
208 init: ssh, remotecmd, insecure
209 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
209 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
210 merge: force, rev, preview, tool
210 merge: force, rev, preview, tool
211 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
211 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
212 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
212 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
213 remove: after, force, include, exclude
213 remove: after, force, include, exclude
214 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
214 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
215 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
215 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
216 summary: remote
216 summary: remote
217 update: clean, check, date, rev, tool
217 update: clean, check, date, rev, tool
218 addremove: similarity, include, exclude, dry-run
218 addremove: similarity, include, exclude, dry-run
219 archive: no-decode, prefix, rev, type, subrepos, include, exclude
219 archive: no-decode, prefix, rev, type, subrepos, include, exclude
220 backout: merge, parent, rev, edit, tool, include, exclude, message, logfile, date, user
220 backout: merge, parent, rev, edit, tool, include, exclude, message, logfile, date, user
221 bisect: reset, good, bad, skip, extend, command, noupdate
221 bisect: reset, good, bad, skip, extend, command, noupdate
222 bookmarks: force, rev, delete, rename, inactive
222 bookmarks: force, rev, delete, rename, inactive
223 branch: force, clean
223 branch: force, clean
224 branches: active, closed
224 branches: active, closed, template
225 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
225 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
226 cat: output, rev, decode, include, exclude
226 cat: output, rev, decode, include, exclude
227 config: untrusted, edit, local, global
227 config: untrusted, edit, local, global
228 copy: after, force, include, exclude, dry-run
228 copy: after, force, include, exclude, dry-run
229 debugancestor:
229 debugancestor:
230 debugbuilddag: mergeable-file, overwritten-file, new-file
230 debugbuilddag: mergeable-file, overwritten-file, new-file
231 debugbundle: all
231 debugbundle: all
232 debugcheckstate:
232 debugcheckstate:
233 debugcommands:
233 debugcommands:
234 debugcomplete: options
234 debugcomplete: options
235 debugdag: tags, branches, dots, spaces
235 debugdag: tags, branches, dots, spaces
236 debugdata: changelog, manifest
236 debugdata: changelog, manifest
237 debugdate: extended
237 debugdate: extended
238 debugdirstate: nodates, datesort
238 debugdirstate: nodates, datesort
239 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
239 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
240 debugfileset: rev
240 debugfileset: rev
241 debugfsinfo:
241 debugfsinfo:
242 debuggetbundle: head, common, type
242 debuggetbundle: head, common, type
243 debugignore:
243 debugignore:
244 debugindex: changelog, manifest, format
244 debugindex: changelog, manifest, format
245 debugindexdot:
245 debugindexdot:
246 debuginstall:
246 debuginstall:
247 debugknown:
247 debugknown:
248 debuglabelcomplete:
248 debuglabelcomplete:
249 debuglocks: force-lock, force-wlock
249 debuglocks: force-lock, force-wlock
250 debugobsolete: flags, record-parents, rev, date, user
250 debugobsolete: flags, record-parents, rev, date, user
251 debugpathcomplete: full, normal, added, removed
251 debugpathcomplete: full, normal, added, removed
252 debugpushkey:
252 debugpushkey:
253 debugpvec:
253 debugpvec:
254 debugrebuilddirstate: rev
254 debugrebuilddirstate: rev
255 debugrename: rev
255 debugrename: rev
256 debugrevlog: changelog, manifest, dump
256 debugrevlog: changelog, manifest, dump
257 debugrevspec: optimize
257 debugrevspec: optimize
258 debugsetparents:
258 debugsetparents:
259 debugsub: rev
259 debugsub: rev
260 debugsuccessorssets:
260 debugsuccessorssets:
261 debugwalk: include, exclude
261 debugwalk: include, exclude
262 debugwireargs: three, four, five, ssh, remotecmd, insecure
262 debugwireargs: three, four, five, ssh, remotecmd, insecure
263 files: rev, print0, include, exclude, template
263 files: rev, print0, include, exclude, template
264 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
264 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
265 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
265 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
266 heads: rev, topo, active, closed, style, template
266 heads: rev, topo, active, closed, style, template
267 help: extension, command, keyword
267 help: extension, command, keyword
268 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
268 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
269 import: strip, base, edit, force, no-commit, bypass, partial, exact, import-branch, message, logfile, date, user, similarity
269 import: strip, base, edit, force, no-commit, bypass, partial, exact, import-branch, message, logfile, date, user, similarity
270 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
270 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
271 locate: rev, print0, fullpath, include, exclude
271 locate: rev, print0, fullpath, include, exclude
272 manifest: rev, all, template
272 manifest: rev, all, template
273 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
273 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
274 parents: rev, style, template
274 parents: rev, style, template
275 paths:
275 paths:
276 phase: public, draft, secret, force, rev
276 phase: public, draft, secret, force, rev
277 recover:
277 recover:
278 rename: after, force, include, exclude, dry-run
278 rename: after, force, include, exclude, dry-run
279 resolve: all, list, mark, unmark, no-status, tool, include, exclude
279 resolve: all, list, mark, unmark, no-status, tool, include, exclude
280 revert: all, date, rev, no-backup, include, exclude, dry-run
280 revert: all, date, rev, no-backup, include, exclude, dry-run
281 rollback: dry-run, force
281 rollback: dry-run, force
282 root:
282 root:
283 tag: force, local, rev, remove, edit, message, date, user
283 tag: force, local, rev, remove, edit, message, date, user
284 tags: template
284 tags: template
285 tip: patch, git, style, template
285 tip: patch, git, style, template
286 unbundle: update
286 unbundle: update
287 verify:
287 verify:
288 version:
288 version:
289
289
290 $ hg init a
290 $ hg init a
291 $ cd a
291 $ cd a
292 $ echo fee > fee
292 $ echo fee > fee
293 $ hg ci -q -Amfee
293 $ hg ci -q -Amfee
294 $ hg tag fee
294 $ hg tag fee
295 $ mkdir fie
295 $ mkdir fie
296 $ echo dead > fie/dead
296 $ echo dead > fie/dead
297 $ echo live > fie/live
297 $ echo live > fie/live
298 $ hg bookmark fo
298 $ hg bookmark fo
299 $ hg branch -q fie
299 $ hg branch -q fie
300 $ hg ci -q -Amfie
300 $ hg ci -q -Amfie
301 $ echo fo > fo
301 $ echo fo > fo
302 $ hg branch -qf default
302 $ hg branch -qf default
303 $ hg ci -q -Amfo
303 $ hg ci -q -Amfo
304 $ echo Fum > Fum
304 $ echo Fum > Fum
305 $ hg ci -q -AmFum
305 $ hg ci -q -AmFum
306 $ hg bookmark Fum
306 $ hg bookmark Fum
307
307
308 Test debugpathcomplete
308 Test debugpathcomplete
309
309
310 $ hg debugpathcomplete f
310 $ hg debugpathcomplete f
311 fee
311 fee
312 fie
312 fie
313 fo
313 fo
314 $ hg debugpathcomplete -f f
314 $ hg debugpathcomplete -f f
315 fee
315 fee
316 fie/dead
316 fie/dead
317 fie/live
317 fie/live
318 fo
318 fo
319
319
320 $ hg rm Fum
320 $ hg rm Fum
321 $ hg debugpathcomplete -r F
321 $ hg debugpathcomplete -r F
322 Fum
322 Fum
323
323
324 Test debuglabelcomplete
324 Test debuglabelcomplete
325
325
326 $ hg debuglabelcomplete
326 $ hg debuglabelcomplete
327 Fum
327 Fum
328 default
328 default
329 fee
329 fee
330 fie
330 fie
331 fo
331 fo
332 tip
332 tip
333 $ hg debuglabelcomplete f
333 $ hg debuglabelcomplete f
334 fee
334 fee
335 fie
335 fie
336 fo
336 fo
General Comments 0
You need to be logged in to leave comments. Login now