##// END OF EJS Templates
config: add example config file when -e called with no config
Matt Mackall -
r20573:02d0d3aa default
parent child Browse files
Show More
@@ -1,5865 +1,5881 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, commandserver
15 import sshserver, hgweb, commandserver
16 from hgweb import server as hgweb_server
16 from hgweb import server as hgweb_server
17 import merge as mergemod
17 import merge as mergemod
18 import minirst, revset, fileset
18 import minirst, revset, fileset
19 import dagparser, context, simplemerge, graphmod
19 import dagparser, context, simplemerge, graphmod
20 import random
20 import random
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import phases, obsolete
22 import phases, obsolete
23
23
24 table = {}
24 table = {}
25
25
26 command = cmdutil.command(table)
26 command = cmdutil.command(table)
27
27
28 # common command options
28 # common command options
29
29
30 globalopts = [
30 globalopts = [
31 ('R', 'repository', '',
31 ('R', 'repository', '',
32 _('repository root directory or name of overlay bundle file'),
32 _('repository root directory or name of overlay bundle file'),
33 _('REPO')),
33 _('REPO')),
34 ('', 'cwd', '',
34 ('', 'cwd', '',
35 _('change working directory'), _('DIR')),
35 _('change working directory'), _('DIR')),
36 ('y', 'noninteractive', None,
36 ('y', 'noninteractive', None,
37 _('do not prompt, automatically pick the first choice for all prompts')),
37 _('do not prompt, automatically pick the first choice for all prompts')),
38 ('q', 'quiet', None, _('suppress output')),
38 ('q', 'quiet', None, _('suppress output')),
39 ('v', 'verbose', None, _('enable additional output')),
39 ('v', 'verbose', None, _('enable additional output')),
40 ('', 'config', [],
40 ('', 'config', [],
41 _('set/override config option (use \'section.name=value\')'),
41 _('set/override config option (use \'section.name=value\')'),
42 _('CONFIG')),
42 _('CONFIG')),
43 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debugger', None, _('start debugger')),
44 ('', 'debugger', None, _('start debugger')),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 _('ENCODE')),
46 _('ENCODE')),
47 ('', 'encodingmode', encoding.encodingmode,
47 ('', 'encodingmode', encoding.encodingmode,
48 _('set the charset encoding mode'), _('MODE')),
48 _('set the charset encoding mode'), _('MODE')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'time', None, _('time how long the command takes')),
50 ('', 'time', None, _('time how long the command takes')),
51 ('', 'profile', None, _('print command execution profile')),
51 ('', 'profile', None, _('print command execution profile')),
52 ('', 'version', None, _('output version information and exit')),
52 ('', 'version', None, _('output version information and exit')),
53 ('h', 'help', None, _('display help and exit')),
53 ('h', 'help', None, _('display help and exit')),
54 ('', 'hidden', False, _('consider hidden changesets')),
54 ('', 'hidden', False, _('consider hidden changesets')),
55 ]
55 ]
56
56
57 dryrunopts = [('n', 'dry-run', None,
57 dryrunopts = [('n', 'dry-run', None,
58 _('do not perform actions, just print output'))]
58 _('do not perform actions, just print output'))]
59
59
60 remoteopts = [
60 remoteopts = [
61 ('e', 'ssh', '',
61 ('e', 'ssh', '',
62 _('specify ssh command to use'), _('CMD')),
62 _('specify ssh command to use'), _('CMD')),
63 ('', 'remotecmd', '',
63 ('', 'remotecmd', '',
64 _('specify hg command to run on the remote side'), _('CMD')),
64 _('specify hg command to run on the remote side'), _('CMD')),
65 ('', 'insecure', None,
65 ('', 'insecure', None,
66 _('do not verify server certificate (ignoring web.cacerts config)')),
66 _('do not verify server certificate (ignoring web.cacerts config)')),
67 ]
67 ]
68
68
69 walkopts = [
69 walkopts = [
70 ('I', 'include', [],
70 ('I', 'include', [],
71 _('include names matching the given patterns'), _('PATTERN')),
71 _('include names matching the given patterns'), _('PATTERN')),
72 ('X', 'exclude', [],
72 ('X', 'exclude', [],
73 _('exclude names matching the given patterns'), _('PATTERN')),
73 _('exclude names matching the given patterns'), _('PATTERN')),
74 ]
74 ]
75
75
76 commitopts = [
76 commitopts = [
77 ('m', 'message', '',
77 ('m', 'message', '',
78 _('use text as commit message'), _('TEXT')),
78 _('use text as commit message'), _('TEXT')),
79 ('l', 'logfile', '',
79 ('l', 'logfile', '',
80 _('read commit message from file'), _('FILE')),
80 _('read commit message from file'), _('FILE')),
81 ]
81 ]
82
82
83 commitopts2 = [
83 commitopts2 = [
84 ('d', 'date', '',
84 ('d', 'date', '',
85 _('record the specified date as commit date'), _('DATE')),
85 _('record the specified date as commit date'), _('DATE')),
86 ('u', 'user', '',
86 ('u', 'user', '',
87 _('record the specified user as committer'), _('USER')),
87 _('record the specified user as committer'), _('USER')),
88 ]
88 ]
89
89
90 templateopts = [
90 templateopts = [
91 ('', 'style', '',
91 ('', 'style', '',
92 _('display using template map file'), _('STYLE')),
92 _('display using template map file'), _('STYLE')),
93 ('', 'template', '',
93 ('', 'template', '',
94 _('display with template'), _('TEMPLATE')),
94 _('display with template'), _('TEMPLATE')),
95 ]
95 ]
96
96
97 logopts = [
97 logopts = [
98 ('p', 'patch', None, _('show patch')),
98 ('p', 'patch', None, _('show patch')),
99 ('g', 'git', None, _('use git extended diff format')),
99 ('g', 'git', None, _('use git extended diff format')),
100 ('l', 'limit', '',
100 ('l', 'limit', '',
101 _('limit number of changes displayed'), _('NUM')),
101 _('limit number of changes displayed'), _('NUM')),
102 ('M', 'no-merges', None, _('do not show merges')),
102 ('M', 'no-merges', None, _('do not show merges')),
103 ('', 'stat', None, _('output diffstat-style summary of changes')),
103 ('', 'stat', None, _('output diffstat-style summary of changes')),
104 ('G', 'graph', None, _("show the revision DAG")),
104 ('G', 'graph', None, _("show the revision DAG")),
105 ] + templateopts
105 ] + templateopts
106
106
107 diffopts = [
107 diffopts = [
108 ('a', 'text', None, _('treat all files as text')),
108 ('a', 'text', None, _('treat all files as text')),
109 ('g', 'git', None, _('use git extended diff format')),
109 ('g', 'git', None, _('use git extended diff format')),
110 ('', 'nodates', None, _('omit dates from diff headers'))
110 ('', 'nodates', None, _('omit dates from diff headers'))
111 ]
111 ]
112
112
113 diffwsopts = [
113 diffwsopts = [
114 ('w', 'ignore-all-space', None,
114 ('w', 'ignore-all-space', None,
115 _('ignore white space when comparing lines')),
115 _('ignore white space when comparing lines')),
116 ('b', 'ignore-space-change', None,
116 ('b', 'ignore-space-change', None,
117 _('ignore changes in the amount of white space')),
117 _('ignore changes in the amount of white space')),
118 ('B', 'ignore-blank-lines', None,
118 ('B', 'ignore-blank-lines', None,
119 _('ignore changes whose lines are all blank')),
119 _('ignore changes whose lines are all blank')),
120 ]
120 ]
121
121
122 diffopts2 = [
122 diffopts2 = [
123 ('p', 'show-function', None, _('show which function each change is in')),
123 ('p', 'show-function', None, _('show which function each change is in')),
124 ('', 'reverse', None, _('produce a diff that undoes the changes')),
124 ('', 'reverse', None, _('produce a diff that undoes the changes')),
125 ] + diffwsopts + [
125 ] + diffwsopts + [
126 ('U', 'unified', '',
126 ('U', 'unified', '',
127 _('number of lines of context to show'), _('NUM')),
127 _('number of lines of context to show'), _('NUM')),
128 ('', 'stat', None, _('output diffstat-style summary of changes')),
128 ('', 'stat', None, _('output diffstat-style summary of changes')),
129 ]
129 ]
130
130
131 mergetoolopts = [
131 mergetoolopts = [
132 ('t', 'tool', '', _('specify merge tool')),
132 ('t', 'tool', '', _('specify merge tool')),
133 ]
133 ]
134
134
135 similarityopts = [
135 similarityopts = [
136 ('s', 'similarity', '',
136 ('s', 'similarity', '',
137 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
137 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
138 ]
138 ]
139
139
140 subrepoopts = [
140 subrepoopts = [
141 ('S', 'subrepos', None,
141 ('S', 'subrepos', None,
142 _('recurse into subrepositories'))
142 _('recurse into subrepositories'))
143 ]
143 ]
144
144
145 # Commands start here, listed alphabetically
145 # Commands start here, listed alphabetically
146
146
147 @command('^add',
147 @command('^add',
148 walkopts + subrepoopts + dryrunopts,
148 walkopts + subrepoopts + dryrunopts,
149 _('[OPTION]... [FILE]...'))
149 _('[OPTION]... [FILE]...'))
150 def add(ui, repo, *pats, **opts):
150 def add(ui, repo, *pats, **opts):
151 """add the specified files on the next commit
151 """add the specified files on the next commit
152
152
153 Schedule files to be version controlled and added to the
153 Schedule files to be version controlled and added to the
154 repository.
154 repository.
155
155
156 The files will be added to the repository at the next commit. To
156 The files will be added to the repository at the next commit. To
157 undo an add before that, see :hg:`forget`.
157 undo an add before that, see :hg:`forget`.
158
158
159 If no names are given, add all files to the repository.
159 If no names are given, add all files to the repository.
160
160
161 .. container:: verbose
161 .. container:: verbose
162
162
163 An example showing how new (unknown) files are added
163 An example showing how new (unknown) files are added
164 automatically by :hg:`add`::
164 automatically by :hg:`add`::
165
165
166 $ ls
166 $ ls
167 foo.c
167 foo.c
168 $ hg status
168 $ hg status
169 ? foo.c
169 ? foo.c
170 $ hg add
170 $ hg add
171 adding foo.c
171 adding foo.c
172 $ hg status
172 $ hg status
173 A foo.c
173 A foo.c
174
174
175 Returns 0 if all files are successfully added.
175 Returns 0 if all files are successfully added.
176 """
176 """
177
177
178 m = scmutil.match(repo[None], pats, opts)
178 m = scmutil.match(repo[None], pats, opts)
179 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
179 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
180 opts.get('subrepos'), prefix="", explicitonly=False)
180 opts.get('subrepos'), prefix="", explicitonly=False)
181 return rejected and 1 or 0
181 return rejected and 1 or 0
182
182
183 @command('addremove',
183 @command('addremove',
184 similarityopts + walkopts + dryrunopts,
184 similarityopts + walkopts + dryrunopts,
185 _('[OPTION]... [FILE]...'))
185 _('[OPTION]... [FILE]...'))
186 def addremove(ui, repo, *pats, **opts):
186 def addremove(ui, repo, *pats, **opts):
187 """add all new files, delete all missing files
187 """add all new files, delete all missing files
188
188
189 Add all new files and remove all missing files from the
189 Add all new files and remove all missing files from the
190 repository.
190 repository.
191
191
192 New files are ignored if they match any of the patterns in
192 New files are ignored if they match any of the patterns in
193 ``.hgignore``. As with add, these changes take effect at the next
193 ``.hgignore``. As with add, these changes take effect at the next
194 commit.
194 commit.
195
195
196 Use the -s/--similarity option to detect renamed files. This
196 Use the -s/--similarity option to detect renamed files. This
197 option takes a percentage between 0 (disabled) and 100 (files must
197 option takes a percentage between 0 (disabled) and 100 (files must
198 be identical) as its parameter. With a parameter greater than 0,
198 be identical) as its parameter. With a parameter greater than 0,
199 this compares every removed file with every added file and records
199 this compares every removed file with every added file and records
200 those similar enough as renames. Detecting renamed files this way
200 those similar enough as renames. Detecting renamed files this way
201 can be expensive. After using this option, :hg:`status -C` can be
201 can be expensive. After using this option, :hg:`status -C` can be
202 used to check which files were identified as moved or renamed. If
202 used to check which files were identified as moved or renamed. If
203 not specified, -s/--similarity defaults to 100 and only renames of
203 not specified, -s/--similarity defaults to 100 and only renames of
204 identical files are detected.
204 identical files are detected.
205
205
206 Returns 0 if all files are successfully added.
206 Returns 0 if all files are successfully added.
207 """
207 """
208 try:
208 try:
209 sim = float(opts.get('similarity') or 100)
209 sim = float(opts.get('similarity') or 100)
210 except ValueError:
210 except ValueError:
211 raise util.Abort(_('similarity must be a number'))
211 raise util.Abort(_('similarity must be a number'))
212 if sim < 0 or sim > 100:
212 if sim < 0 or sim > 100:
213 raise util.Abort(_('similarity must be between 0 and 100'))
213 raise util.Abort(_('similarity must be between 0 and 100'))
214 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
214 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
215
215
216 @command('^annotate|blame',
216 @command('^annotate|blame',
217 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
217 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
218 ('', 'follow', None,
218 ('', 'follow', None,
219 _('follow copies/renames and list the filename (DEPRECATED)')),
219 _('follow copies/renames and list the filename (DEPRECATED)')),
220 ('', 'no-follow', None, _("don't follow copies and renames")),
220 ('', 'no-follow', None, _("don't follow copies and renames")),
221 ('a', 'text', None, _('treat all files as text')),
221 ('a', 'text', None, _('treat all files as text')),
222 ('u', 'user', None, _('list the author (long with -v)')),
222 ('u', 'user', None, _('list the author (long with -v)')),
223 ('f', 'file', None, _('list the filename')),
223 ('f', 'file', None, _('list the filename')),
224 ('d', 'date', None, _('list the date (short with -q)')),
224 ('d', 'date', None, _('list the date (short with -q)')),
225 ('n', 'number', None, _('list the revision number (default)')),
225 ('n', 'number', None, _('list the revision number (default)')),
226 ('c', 'changeset', None, _('list the changeset')),
226 ('c', 'changeset', None, _('list the changeset')),
227 ('l', 'line-number', None, _('show line number at the first appearance'))
227 ('l', 'line-number', None, _('show line number at the first appearance'))
228 ] + diffwsopts + walkopts,
228 ] + diffwsopts + walkopts,
229 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
229 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
230 def annotate(ui, repo, *pats, **opts):
230 def annotate(ui, repo, *pats, **opts):
231 """show changeset information by line for each file
231 """show changeset information by line for each file
232
232
233 List changes in files, showing the revision id responsible for
233 List changes in files, showing the revision id responsible for
234 each line
234 each line
235
235
236 This command is useful for discovering when a change was made and
236 This command is useful for discovering when a change was made and
237 by whom.
237 by whom.
238
238
239 Without the -a/--text option, annotate will avoid processing files
239 Without the -a/--text option, annotate will avoid processing files
240 it detects as binary. With -a, annotate will annotate the file
240 it detects as binary. With -a, annotate will annotate the file
241 anyway, although the results will probably be neither useful
241 anyway, although the results will probably be neither useful
242 nor desirable.
242 nor desirable.
243
243
244 Returns 0 on success.
244 Returns 0 on success.
245 """
245 """
246 if opts.get('follow'):
246 if opts.get('follow'):
247 # --follow is deprecated and now just an alias for -f/--file
247 # --follow is deprecated and now just an alias for -f/--file
248 # to mimic the behavior of Mercurial before version 1.5
248 # to mimic the behavior of Mercurial before version 1.5
249 opts['file'] = True
249 opts['file'] = True
250
250
251 datefunc = ui.quiet and util.shortdate or util.datestr
251 datefunc = ui.quiet and util.shortdate or util.datestr
252 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
252 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
253
253
254 if not pats:
254 if not pats:
255 raise util.Abort(_('at least one filename or pattern is required'))
255 raise util.Abort(_('at least one filename or pattern is required'))
256
256
257 hexfn = ui.debugflag and hex or short
257 hexfn = ui.debugflag and hex or short
258
258
259 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
259 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
260 ('number', ' ', lambda x: str(x[0].rev())),
260 ('number', ' ', lambda x: str(x[0].rev())),
261 ('changeset', ' ', lambda x: hexfn(x[0].node())),
261 ('changeset', ' ', lambda x: hexfn(x[0].node())),
262 ('date', ' ', getdate),
262 ('date', ' ', getdate),
263 ('file', ' ', lambda x: x[0].path()),
263 ('file', ' ', lambda x: x[0].path()),
264 ('line_number', ':', lambda x: str(x[1])),
264 ('line_number', ':', lambda x: str(x[1])),
265 ]
265 ]
266
266
267 if (not opts.get('user') and not opts.get('changeset')
267 if (not opts.get('user') and not opts.get('changeset')
268 and not opts.get('date') and not opts.get('file')):
268 and not opts.get('date') and not opts.get('file')):
269 opts['number'] = True
269 opts['number'] = True
270
270
271 linenumber = opts.get('line_number') is not None
271 linenumber = opts.get('line_number') is not None
272 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
272 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
273 raise util.Abort(_('at least one of -n/-c is required for -l'))
273 raise util.Abort(_('at least one of -n/-c is required for -l'))
274
274
275 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
275 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
276 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
276 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
277
277
278 def bad(x, y):
278 def bad(x, y):
279 raise util.Abort("%s: %s" % (x, y))
279 raise util.Abort("%s: %s" % (x, y))
280
280
281 ctx = scmutil.revsingle(repo, opts.get('rev'))
281 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 m = scmutil.match(ctx, pats, opts)
282 m = scmutil.match(ctx, pats, opts)
283 m.bad = bad
283 m.bad = bad
284 follow = not opts.get('no_follow')
284 follow = not opts.get('no_follow')
285 diffopts = patch.diffopts(ui, opts, section='annotate')
285 diffopts = patch.diffopts(ui, opts, section='annotate')
286 for abs in ctx.walk(m):
286 for abs in ctx.walk(m):
287 fctx = ctx[abs]
287 fctx = ctx[abs]
288 if not opts.get('text') and util.binary(fctx.data()):
288 if not opts.get('text') and util.binary(fctx.data()):
289 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
289 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
290 continue
290 continue
291
291
292 lines = fctx.annotate(follow=follow, linenumber=linenumber,
292 lines = fctx.annotate(follow=follow, linenumber=linenumber,
293 diffopts=diffopts)
293 diffopts=diffopts)
294 pieces = []
294 pieces = []
295
295
296 for f, sep in funcmap:
296 for f, sep in funcmap:
297 l = [f(n) for n, dummy in lines]
297 l = [f(n) for n, dummy in lines]
298 if l:
298 if l:
299 sized = [(x, encoding.colwidth(x)) for x in l]
299 sized = [(x, encoding.colwidth(x)) for x in l]
300 ml = max([w for x, w in sized])
300 ml = max([w for x, w in sized])
301 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
301 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
302 for x, w in sized])
302 for x, w in sized])
303
303
304 if pieces:
304 if pieces:
305 for p, l in zip(zip(*pieces), lines):
305 for p, l in zip(zip(*pieces), lines):
306 ui.write("%s: %s" % ("".join(p), l[1]))
306 ui.write("%s: %s" % ("".join(p), l[1]))
307
307
308 if lines and not lines[-1][1].endswith('\n'):
308 if lines and not lines[-1][1].endswith('\n'):
309 ui.write('\n')
309 ui.write('\n')
310
310
311 @command('archive',
311 @command('archive',
312 [('', 'no-decode', None, _('do not pass files through decoders')),
312 [('', 'no-decode', None, _('do not pass files through decoders')),
313 ('p', 'prefix', '', _('directory prefix for files in archive'),
313 ('p', 'prefix', '', _('directory prefix for files in archive'),
314 _('PREFIX')),
314 _('PREFIX')),
315 ('r', 'rev', '', _('revision to distribute'), _('REV')),
315 ('r', 'rev', '', _('revision to distribute'), _('REV')),
316 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
316 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
317 ] + subrepoopts + walkopts,
317 ] + subrepoopts + walkopts,
318 _('[OPTION]... DEST'))
318 _('[OPTION]... DEST'))
319 def archive(ui, repo, dest, **opts):
319 def archive(ui, repo, dest, **opts):
320 '''create an unversioned archive of a repository revision
320 '''create an unversioned archive of a repository revision
321
321
322 By default, the revision used is the parent of the working
322 By default, the revision used is the parent of the working
323 directory; use -r/--rev to specify a different revision.
323 directory; use -r/--rev to specify a different revision.
324
324
325 The archive type is automatically detected based on file
325 The archive type is automatically detected based on file
326 extension (or override using -t/--type).
326 extension (or override using -t/--type).
327
327
328 .. container:: verbose
328 .. container:: verbose
329
329
330 Examples:
330 Examples:
331
331
332 - create a zip file containing the 1.0 release::
332 - create a zip file containing the 1.0 release::
333
333
334 hg archive -r 1.0 project-1.0.zip
334 hg archive -r 1.0 project-1.0.zip
335
335
336 - create a tarball excluding .hg files::
336 - create a tarball excluding .hg files::
337
337
338 hg archive project.tar.gz -X ".hg*"
338 hg archive project.tar.gz -X ".hg*"
339
339
340 Valid types are:
340 Valid types are:
341
341
342 :``files``: a directory full of files (default)
342 :``files``: a directory full of files (default)
343 :``tar``: tar archive, uncompressed
343 :``tar``: tar archive, uncompressed
344 :``tbz2``: tar archive, compressed using bzip2
344 :``tbz2``: tar archive, compressed using bzip2
345 :``tgz``: tar archive, compressed using gzip
345 :``tgz``: tar archive, compressed using gzip
346 :``uzip``: zip archive, uncompressed
346 :``uzip``: zip archive, uncompressed
347 :``zip``: zip archive, compressed using deflate
347 :``zip``: zip archive, compressed using deflate
348
348
349 The exact name of the destination archive or directory is given
349 The exact name of the destination archive or directory is given
350 using a format string; see :hg:`help export` for details.
350 using a format string; see :hg:`help export` for details.
351
351
352 Each member added to an archive file has a directory prefix
352 Each member added to an archive file has a directory prefix
353 prepended. Use -p/--prefix to specify a format string for the
353 prepended. Use -p/--prefix to specify a format string for the
354 prefix. The default is the basename of the archive, with suffixes
354 prefix. The default is the basename of the archive, with suffixes
355 removed.
355 removed.
356
356
357 Returns 0 on success.
357 Returns 0 on success.
358 '''
358 '''
359
359
360 ctx = scmutil.revsingle(repo, opts.get('rev'))
360 ctx = scmutil.revsingle(repo, opts.get('rev'))
361 if not ctx:
361 if not ctx:
362 raise util.Abort(_('no working directory: please specify a revision'))
362 raise util.Abort(_('no working directory: please specify a revision'))
363 node = ctx.node()
363 node = ctx.node()
364 dest = cmdutil.makefilename(repo, dest, node)
364 dest = cmdutil.makefilename(repo, dest, node)
365 if os.path.realpath(dest) == repo.root:
365 if os.path.realpath(dest) == repo.root:
366 raise util.Abort(_('repository root cannot be destination'))
366 raise util.Abort(_('repository root cannot be destination'))
367
367
368 kind = opts.get('type') or archival.guesskind(dest) or 'files'
368 kind = opts.get('type') or archival.guesskind(dest) or 'files'
369 prefix = opts.get('prefix')
369 prefix = opts.get('prefix')
370
370
371 if dest == '-':
371 if dest == '-':
372 if kind == 'files':
372 if kind == 'files':
373 raise util.Abort(_('cannot archive plain files to stdout'))
373 raise util.Abort(_('cannot archive plain files to stdout'))
374 dest = cmdutil.makefileobj(repo, dest)
374 dest = cmdutil.makefileobj(repo, dest)
375 if not prefix:
375 if not prefix:
376 prefix = os.path.basename(repo.root) + '-%h'
376 prefix = os.path.basename(repo.root) + '-%h'
377
377
378 prefix = cmdutil.makefilename(repo, prefix, node)
378 prefix = cmdutil.makefilename(repo, prefix, node)
379 matchfn = scmutil.match(ctx, [], opts)
379 matchfn = scmutil.match(ctx, [], opts)
380 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
380 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
381 matchfn, prefix, subrepos=opts.get('subrepos'))
381 matchfn, prefix, subrepos=opts.get('subrepos'))
382
382
383 @command('backout',
383 @command('backout',
384 [('', 'merge', None, _('merge with old dirstate parent after backout')),
384 [('', 'merge', None, _('merge with old dirstate parent after backout')),
385 ('', 'parent', '',
385 ('', 'parent', '',
386 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
386 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
387 ('r', 'rev', '', _('revision to backout'), _('REV')),
387 ('r', 'rev', '', _('revision to backout'), _('REV')),
388 ] + mergetoolopts + walkopts + commitopts + commitopts2,
388 ] + mergetoolopts + walkopts + commitopts + commitopts2,
389 _('[OPTION]... [-r] REV'))
389 _('[OPTION]... [-r] REV'))
390 def backout(ui, repo, node=None, rev=None, **opts):
390 def backout(ui, repo, node=None, rev=None, **opts):
391 '''reverse effect of earlier changeset
391 '''reverse effect of earlier changeset
392
392
393 Prepare a new changeset with the effect of REV undone in the
393 Prepare a new changeset with the effect of REV undone in the
394 current working directory.
394 current working directory.
395
395
396 If REV is the parent of the working directory, then this new changeset
396 If REV is the parent of the working directory, then this new changeset
397 is committed automatically. Otherwise, hg needs to merge the
397 is committed automatically. Otherwise, hg needs to merge the
398 changes and the merged result is left uncommitted.
398 changes and the merged result is left uncommitted.
399
399
400 .. note::
400 .. note::
401
401
402 backout cannot be used to fix either an unwanted or
402 backout cannot be used to fix either an unwanted or
403 incorrect merge.
403 incorrect merge.
404
404
405 .. container:: verbose
405 .. container:: verbose
406
406
407 By default, the pending changeset will have one parent,
407 By default, the pending changeset will have one parent,
408 maintaining a linear history. With --merge, the pending
408 maintaining a linear history. With --merge, the pending
409 changeset will instead have two parents: the old parent of the
409 changeset will instead have two parents: the old parent of the
410 working directory and a new child of REV that simply undoes REV.
410 working directory and a new child of REV that simply undoes REV.
411
411
412 Before version 1.7, the behavior without --merge was equivalent
412 Before version 1.7, the behavior without --merge was equivalent
413 to specifying --merge followed by :hg:`update --clean .` to
413 to specifying --merge followed by :hg:`update --clean .` to
414 cancel the merge and leave the child of REV as a head to be
414 cancel the merge and leave the child of REV as a head to be
415 merged separately.
415 merged separately.
416
416
417 See :hg:`help dates` for a list of formats valid for -d/--date.
417 See :hg:`help dates` for a list of formats valid for -d/--date.
418
418
419 Returns 0 on success.
419 Returns 0 on success.
420 '''
420 '''
421 if rev and node:
421 if rev and node:
422 raise util.Abort(_("please specify just one revision"))
422 raise util.Abort(_("please specify just one revision"))
423
423
424 if not rev:
424 if not rev:
425 rev = node
425 rev = node
426
426
427 if not rev:
427 if not rev:
428 raise util.Abort(_("please specify a revision to backout"))
428 raise util.Abort(_("please specify a revision to backout"))
429
429
430 date = opts.get('date')
430 date = opts.get('date')
431 if date:
431 if date:
432 opts['date'] = util.parsedate(date)
432 opts['date'] = util.parsedate(date)
433
433
434 cmdutil.checkunfinished(repo)
434 cmdutil.checkunfinished(repo)
435 cmdutil.bailifchanged(repo)
435 cmdutil.bailifchanged(repo)
436 node = scmutil.revsingle(repo, rev).node()
436 node = scmutil.revsingle(repo, rev).node()
437
437
438 op1, op2 = repo.dirstate.parents()
438 op1, op2 = repo.dirstate.parents()
439 a = repo.changelog.ancestor(op1, node)
439 a = repo.changelog.ancestor(op1, node)
440 if a != node:
440 if a != node:
441 raise util.Abort(_('cannot backout change on a different branch'))
441 raise util.Abort(_('cannot backout change on a different branch'))
442
442
443 p1, p2 = repo.changelog.parents(node)
443 p1, p2 = repo.changelog.parents(node)
444 if p1 == nullid:
444 if p1 == nullid:
445 raise util.Abort(_('cannot backout a change with no parents'))
445 raise util.Abort(_('cannot backout a change with no parents'))
446 if p2 != nullid:
446 if p2 != nullid:
447 if not opts.get('parent'):
447 if not opts.get('parent'):
448 raise util.Abort(_('cannot backout a merge changeset'))
448 raise util.Abort(_('cannot backout a merge changeset'))
449 p = repo.lookup(opts['parent'])
449 p = repo.lookup(opts['parent'])
450 if p not in (p1, p2):
450 if p not in (p1, p2):
451 raise util.Abort(_('%s is not a parent of %s') %
451 raise util.Abort(_('%s is not a parent of %s') %
452 (short(p), short(node)))
452 (short(p), short(node)))
453 parent = p
453 parent = p
454 else:
454 else:
455 if opts.get('parent'):
455 if opts.get('parent'):
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 parent = p1
457 parent = p1
458
458
459 # the backout should appear on the same branch
459 # the backout should appear on the same branch
460 wlock = repo.wlock()
460 wlock = repo.wlock()
461 try:
461 try:
462 branch = repo.dirstate.branch()
462 branch = repo.dirstate.branch()
463 bheads = repo.branchheads(branch)
463 bheads = repo.branchheads(branch)
464 rctx = scmutil.revsingle(repo, hex(parent))
464 rctx = scmutil.revsingle(repo, hex(parent))
465 if not opts.get('merge') and op1 != node:
465 if not opts.get('merge') and op1 != node:
466 try:
466 try:
467 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 stats = mergemod.update(repo, parent, True, True, False,
468 stats = mergemod.update(repo, parent, True, True, False,
469 node, False)
469 node, False)
470 repo.setparents(op1, op2)
470 repo.setparents(op1, op2)
471 hg._showstats(repo, stats)
471 hg._showstats(repo, stats)
472 if stats[3]:
472 if stats[3]:
473 repo.ui.status(_("use 'hg resolve' to retry unresolved "
473 repo.ui.status(_("use 'hg resolve' to retry unresolved "
474 "file merges\n"))
474 "file merges\n"))
475 else:
475 else:
476 msg = _("changeset %s backed out, "
476 msg = _("changeset %s backed out, "
477 "don't forget to commit.\n")
477 "don't forget to commit.\n")
478 ui.status(msg % short(node))
478 ui.status(msg % short(node))
479 return stats[3] > 0
479 return stats[3] > 0
480 finally:
480 finally:
481 ui.setconfig('ui', 'forcemerge', '')
481 ui.setconfig('ui', 'forcemerge', '')
482 else:
482 else:
483 hg.clean(repo, node, show_stats=False)
483 hg.clean(repo, node, show_stats=False)
484 repo.dirstate.setbranch(branch)
484 repo.dirstate.setbranch(branch)
485 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
485 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
486
486
487
487
488 e = cmdutil.commiteditor
488 e = cmdutil.commiteditor
489 if not opts['message'] and not opts['logfile']:
489 if not opts['message'] and not opts['logfile']:
490 # we don't translate commit messages
490 # we don't translate commit messages
491 opts['message'] = "Backed out changeset %s" % short(node)
491 opts['message'] = "Backed out changeset %s" % short(node)
492 e = cmdutil.commitforceeditor
492 e = cmdutil.commitforceeditor
493
493
494 def commitfunc(ui, repo, message, match, opts):
494 def commitfunc(ui, repo, message, match, opts):
495 return repo.commit(message, opts.get('user'), opts.get('date'),
495 return repo.commit(message, opts.get('user'), opts.get('date'),
496 match, editor=e)
496 match, editor=e)
497 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
497 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
498 cmdutil.commitstatus(repo, newnode, branch, bheads)
498 cmdutil.commitstatus(repo, newnode, branch, bheads)
499
499
500 def nice(node):
500 def nice(node):
501 return '%d:%s' % (repo.changelog.rev(node), short(node))
501 return '%d:%s' % (repo.changelog.rev(node), short(node))
502 ui.status(_('changeset %s backs out changeset %s\n') %
502 ui.status(_('changeset %s backs out changeset %s\n') %
503 (nice(repo.changelog.tip()), nice(node)))
503 (nice(repo.changelog.tip()), nice(node)))
504 if opts.get('merge') and op1 != node:
504 if opts.get('merge') and op1 != node:
505 hg.clean(repo, op1, show_stats=False)
505 hg.clean(repo, op1, show_stats=False)
506 ui.status(_('merging with changeset %s\n')
506 ui.status(_('merging with changeset %s\n')
507 % nice(repo.changelog.tip()))
507 % nice(repo.changelog.tip()))
508 try:
508 try:
509 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
509 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
510 return hg.merge(repo, hex(repo.changelog.tip()))
510 return hg.merge(repo, hex(repo.changelog.tip()))
511 finally:
511 finally:
512 ui.setconfig('ui', 'forcemerge', '')
512 ui.setconfig('ui', 'forcemerge', '')
513 finally:
513 finally:
514 wlock.release()
514 wlock.release()
515 return 0
515 return 0
516
516
517 @command('bisect',
517 @command('bisect',
518 [('r', 'reset', False, _('reset bisect state')),
518 [('r', 'reset', False, _('reset bisect state')),
519 ('g', 'good', False, _('mark changeset good')),
519 ('g', 'good', False, _('mark changeset good')),
520 ('b', 'bad', False, _('mark changeset bad')),
520 ('b', 'bad', False, _('mark changeset bad')),
521 ('s', 'skip', False, _('skip testing changeset')),
521 ('s', 'skip', False, _('skip testing changeset')),
522 ('e', 'extend', False, _('extend the bisect range')),
522 ('e', 'extend', False, _('extend the bisect range')),
523 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
523 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
524 ('U', 'noupdate', False, _('do not update to target'))],
524 ('U', 'noupdate', False, _('do not update to target'))],
525 _("[-gbsr] [-U] [-c CMD] [REV]"))
525 _("[-gbsr] [-U] [-c CMD] [REV]"))
526 def bisect(ui, repo, rev=None, extra=None, command=None,
526 def bisect(ui, repo, rev=None, extra=None, command=None,
527 reset=None, good=None, bad=None, skip=None, extend=None,
527 reset=None, good=None, bad=None, skip=None, extend=None,
528 noupdate=None):
528 noupdate=None):
529 """subdivision search of changesets
529 """subdivision search of changesets
530
530
531 This command helps to find changesets which introduce problems. To
531 This command helps to find changesets which introduce problems. To
532 use, mark the earliest changeset you know exhibits the problem as
532 use, mark the earliest changeset you know exhibits the problem as
533 bad, then mark the latest changeset which is free from the problem
533 bad, then mark the latest changeset which is free from the problem
534 as good. Bisect will update your working directory to a revision
534 as good. Bisect will update your working directory to a revision
535 for testing (unless the -U/--noupdate option is specified). Once
535 for testing (unless the -U/--noupdate option is specified). Once
536 you have performed tests, mark the working directory as good or
536 you have performed tests, mark the working directory as good or
537 bad, and bisect will either update to another candidate changeset
537 bad, and bisect will either update to another candidate changeset
538 or announce that it has found the bad revision.
538 or announce that it has found the bad revision.
539
539
540 As a shortcut, you can also use the revision argument to mark a
540 As a shortcut, you can also use the revision argument to mark a
541 revision as good or bad without checking it out first.
541 revision as good or bad without checking it out first.
542
542
543 If you supply a command, it will be used for automatic bisection.
543 If you supply a command, it will be used for automatic bisection.
544 The environment variable HG_NODE will contain the ID of the
544 The environment variable HG_NODE will contain the ID of the
545 changeset being tested. The exit status of the command will be
545 changeset being tested. The exit status of the command will be
546 used to mark revisions as good or bad: status 0 means good, 125
546 used to mark revisions as good or bad: status 0 means good, 125
547 means to skip the revision, 127 (command not found) will abort the
547 means to skip the revision, 127 (command not found) will abort the
548 bisection, and any other non-zero exit status means the revision
548 bisection, and any other non-zero exit status means the revision
549 is bad.
549 is bad.
550
550
551 .. container:: verbose
551 .. container:: verbose
552
552
553 Some examples:
553 Some examples:
554
554
555 - start a bisection with known bad revision 34, and good revision 12::
555 - start a bisection with known bad revision 34, and good revision 12::
556
556
557 hg bisect --bad 34
557 hg bisect --bad 34
558 hg bisect --good 12
558 hg bisect --good 12
559
559
560 - advance the current bisection by marking current revision as good or
560 - advance the current bisection by marking current revision as good or
561 bad::
561 bad::
562
562
563 hg bisect --good
563 hg bisect --good
564 hg bisect --bad
564 hg bisect --bad
565
565
566 - mark the current revision, or a known revision, to be skipped (e.g. if
566 - mark the current revision, or a known revision, to be skipped (e.g. if
567 that revision is not usable because of another issue)::
567 that revision is not usable because of another issue)::
568
568
569 hg bisect --skip
569 hg bisect --skip
570 hg bisect --skip 23
570 hg bisect --skip 23
571
571
572 - skip all revisions that do not touch directories ``foo`` or ``bar``::
572 - skip all revisions that do not touch directories ``foo`` or ``bar``::
573
573
574 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
574 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
575
575
576 - forget the current bisection::
576 - forget the current bisection::
577
577
578 hg bisect --reset
578 hg bisect --reset
579
579
580 - use 'make && make tests' to automatically find the first broken
580 - use 'make && make tests' to automatically find the first broken
581 revision::
581 revision::
582
582
583 hg bisect --reset
583 hg bisect --reset
584 hg bisect --bad 34
584 hg bisect --bad 34
585 hg bisect --good 12
585 hg bisect --good 12
586 hg bisect --command "make && make tests"
586 hg bisect --command "make && make tests"
587
587
588 - see all changesets whose states are already known in the current
588 - see all changesets whose states are already known in the current
589 bisection::
589 bisection::
590
590
591 hg log -r "bisect(pruned)"
591 hg log -r "bisect(pruned)"
592
592
593 - see the changeset currently being bisected (especially useful
593 - see the changeset currently being bisected (especially useful
594 if running with -U/--noupdate)::
594 if running with -U/--noupdate)::
595
595
596 hg log -r "bisect(current)"
596 hg log -r "bisect(current)"
597
597
598 - see all changesets that took part in the current bisection::
598 - see all changesets that took part in the current bisection::
599
599
600 hg log -r "bisect(range)"
600 hg log -r "bisect(range)"
601
601
602 - you can even get a nice graph::
602 - you can even get a nice graph::
603
603
604 hg log --graph -r "bisect(range)"
604 hg log --graph -r "bisect(range)"
605
605
606 See :hg:`help revsets` for more about the `bisect()` keyword.
606 See :hg:`help revsets` for more about the `bisect()` keyword.
607
607
608 Returns 0 on success.
608 Returns 0 on success.
609 """
609 """
610 def extendbisectrange(nodes, good):
610 def extendbisectrange(nodes, good):
611 # bisect is incomplete when it ends on a merge node and
611 # bisect is incomplete when it ends on a merge node and
612 # one of the parent was not checked.
612 # one of the parent was not checked.
613 parents = repo[nodes[0]].parents()
613 parents = repo[nodes[0]].parents()
614 if len(parents) > 1:
614 if len(parents) > 1:
615 side = good and state['bad'] or state['good']
615 side = good and state['bad'] or state['good']
616 num = len(set(i.node() for i in parents) & set(side))
616 num = len(set(i.node() for i in parents) & set(side))
617 if num == 1:
617 if num == 1:
618 return parents[0].ancestor(parents[1])
618 return parents[0].ancestor(parents[1])
619 return None
619 return None
620
620
621 def print_result(nodes, good):
621 def print_result(nodes, good):
622 displayer = cmdutil.show_changeset(ui, repo, {})
622 displayer = cmdutil.show_changeset(ui, repo, {})
623 if len(nodes) == 1:
623 if len(nodes) == 1:
624 # narrowed it down to a single revision
624 # narrowed it down to a single revision
625 if good:
625 if good:
626 ui.write(_("The first good revision is:\n"))
626 ui.write(_("The first good revision is:\n"))
627 else:
627 else:
628 ui.write(_("The first bad revision is:\n"))
628 ui.write(_("The first bad revision is:\n"))
629 displayer.show(repo[nodes[0]])
629 displayer.show(repo[nodes[0]])
630 extendnode = extendbisectrange(nodes, good)
630 extendnode = extendbisectrange(nodes, good)
631 if extendnode is not None:
631 if extendnode is not None:
632 ui.write(_('Not all ancestors of this changeset have been'
632 ui.write(_('Not all ancestors of this changeset have been'
633 ' checked.\nUse bisect --extend to continue the '
633 ' checked.\nUse bisect --extend to continue the '
634 'bisection from\nthe common ancestor, %s.\n')
634 'bisection from\nthe common ancestor, %s.\n')
635 % extendnode)
635 % extendnode)
636 else:
636 else:
637 # multiple possible revisions
637 # multiple possible revisions
638 if good:
638 if good:
639 ui.write(_("Due to skipped revisions, the first "
639 ui.write(_("Due to skipped revisions, the first "
640 "good revision could be any of:\n"))
640 "good revision could be any of:\n"))
641 else:
641 else:
642 ui.write(_("Due to skipped revisions, the first "
642 ui.write(_("Due to skipped revisions, the first "
643 "bad revision could be any of:\n"))
643 "bad revision could be any of:\n"))
644 for n in nodes:
644 for n in nodes:
645 displayer.show(repo[n])
645 displayer.show(repo[n])
646 displayer.close()
646 displayer.close()
647
647
648 def check_state(state, interactive=True):
648 def check_state(state, interactive=True):
649 if not state['good'] or not state['bad']:
649 if not state['good'] or not state['bad']:
650 if (good or bad or skip or reset) and interactive:
650 if (good or bad or skip or reset) and interactive:
651 return
651 return
652 if not state['good']:
652 if not state['good']:
653 raise util.Abort(_('cannot bisect (no known good revisions)'))
653 raise util.Abort(_('cannot bisect (no known good revisions)'))
654 else:
654 else:
655 raise util.Abort(_('cannot bisect (no known bad revisions)'))
655 raise util.Abort(_('cannot bisect (no known bad revisions)'))
656 return True
656 return True
657
657
658 # backward compatibility
658 # backward compatibility
659 if rev in "good bad reset init".split():
659 if rev in "good bad reset init".split():
660 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
660 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
661 cmd, rev, extra = rev, extra, None
661 cmd, rev, extra = rev, extra, None
662 if cmd == "good":
662 if cmd == "good":
663 good = True
663 good = True
664 elif cmd == "bad":
664 elif cmd == "bad":
665 bad = True
665 bad = True
666 else:
666 else:
667 reset = True
667 reset = True
668 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
668 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
669 raise util.Abort(_('incompatible arguments'))
669 raise util.Abort(_('incompatible arguments'))
670
670
671 cmdutil.checkunfinished(repo)
671 cmdutil.checkunfinished(repo)
672
672
673 if reset:
673 if reset:
674 p = repo.join("bisect.state")
674 p = repo.join("bisect.state")
675 if os.path.exists(p):
675 if os.path.exists(p):
676 os.unlink(p)
676 os.unlink(p)
677 return
677 return
678
678
679 state = hbisect.load_state(repo)
679 state = hbisect.load_state(repo)
680
680
681 if command:
681 if command:
682 changesets = 1
682 changesets = 1
683 if noupdate:
683 if noupdate:
684 try:
684 try:
685 node = state['current'][0]
685 node = state['current'][0]
686 except LookupError:
686 except LookupError:
687 raise util.Abort(_('current bisect revision is unknown - '
687 raise util.Abort(_('current bisect revision is unknown - '
688 'start a new bisect to fix'))
688 'start a new bisect to fix'))
689 else:
689 else:
690 node, p2 = repo.dirstate.parents()
690 node, p2 = repo.dirstate.parents()
691 if p2 != nullid:
691 if p2 != nullid:
692 raise util.Abort(_('current bisect revision is a merge'))
692 raise util.Abort(_('current bisect revision is a merge'))
693 try:
693 try:
694 while changesets:
694 while changesets:
695 # update state
695 # update state
696 state['current'] = [node]
696 state['current'] = [node]
697 hbisect.save_state(repo, state)
697 hbisect.save_state(repo, state)
698 status = util.system(command,
698 status = util.system(command,
699 environ={'HG_NODE': hex(node)},
699 environ={'HG_NODE': hex(node)},
700 out=ui.fout)
700 out=ui.fout)
701 if status == 125:
701 if status == 125:
702 transition = "skip"
702 transition = "skip"
703 elif status == 0:
703 elif status == 0:
704 transition = "good"
704 transition = "good"
705 # status < 0 means process was killed
705 # status < 0 means process was killed
706 elif status == 127:
706 elif status == 127:
707 raise util.Abort(_("failed to execute %s") % command)
707 raise util.Abort(_("failed to execute %s") % command)
708 elif status < 0:
708 elif status < 0:
709 raise util.Abort(_("%s killed") % command)
709 raise util.Abort(_("%s killed") % command)
710 else:
710 else:
711 transition = "bad"
711 transition = "bad"
712 ctx = scmutil.revsingle(repo, rev, node)
712 ctx = scmutil.revsingle(repo, rev, node)
713 rev = None # clear for future iterations
713 rev = None # clear for future iterations
714 state[transition].append(ctx.node())
714 state[transition].append(ctx.node())
715 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
715 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
716 check_state(state, interactive=False)
716 check_state(state, interactive=False)
717 # bisect
717 # bisect
718 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
718 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
719 # update to next check
719 # update to next check
720 node = nodes[0]
720 node = nodes[0]
721 if not noupdate:
721 if not noupdate:
722 cmdutil.bailifchanged(repo)
722 cmdutil.bailifchanged(repo)
723 hg.clean(repo, node, show_stats=False)
723 hg.clean(repo, node, show_stats=False)
724 finally:
724 finally:
725 state['current'] = [node]
725 state['current'] = [node]
726 hbisect.save_state(repo, state)
726 hbisect.save_state(repo, state)
727 print_result(nodes, bgood)
727 print_result(nodes, bgood)
728 return
728 return
729
729
730 # update state
730 # update state
731
731
732 if rev:
732 if rev:
733 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
733 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
734 else:
734 else:
735 nodes = [repo.lookup('.')]
735 nodes = [repo.lookup('.')]
736
736
737 if good or bad or skip:
737 if good or bad or skip:
738 if good:
738 if good:
739 state['good'] += nodes
739 state['good'] += nodes
740 elif bad:
740 elif bad:
741 state['bad'] += nodes
741 state['bad'] += nodes
742 elif skip:
742 elif skip:
743 state['skip'] += nodes
743 state['skip'] += nodes
744 hbisect.save_state(repo, state)
744 hbisect.save_state(repo, state)
745
745
746 if not check_state(state):
746 if not check_state(state):
747 return
747 return
748
748
749 # actually bisect
749 # actually bisect
750 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
750 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
751 if extend:
751 if extend:
752 if not changesets:
752 if not changesets:
753 extendnode = extendbisectrange(nodes, good)
753 extendnode = extendbisectrange(nodes, good)
754 if extendnode is not None:
754 if extendnode is not None:
755 ui.write(_("Extending search to changeset %d:%s\n"
755 ui.write(_("Extending search to changeset %d:%s\n"
756 % (extendnode.rev(), extendnode)))
756 % (extendnode.rev(), extendnode)))
757 state['current'] = [extendnode.node()]
757 state['current'] = [extendnode.node()]
758 hbisect.save_state(repo, state)
758 hbisect.save_state(repo, state)
759 if noupdate:
759 if noupdate:
760 return
760 return
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, extendnode.node())
762 return hg.clean(repo, extendnode.node())
763 raise util.Abort(_("nothing to extend"))
763 raise util.Abort(_("nothing to extend"))
764
764
765 if changesets == 0:
765 if changesets == 0:
766 print_result(nodes, good)
766 print_result(nodes, good)
767 else:
767 else:
768 assert len(nodes) == 1 # only a single node can be tested next
768 assert len(nodes) == 1 # only a single node can be tested next
769 node = nodes[0]
769 node = nodes[0]
770 # compute the approximate number of remaining tests
770 # compute the approximate number of remaining tests
771 tests, size = 0, 2
771 tests, size = 0, 2
772 while size <= changesets:
772 while size <= changesets:
773 tests, size = tests + 1, size * 2
773 tests, size = tests + 1, size * 2
774 rev = repo.changelog.rev(node)
774 rev = repo.changelog.rev(node)
775 ui.write(_("Testing changeset %d:%s "
775 ui.write(_("Testing changeset %d:%s "
776 "(%d changesets remaining, ~%d tests)\n")
776 "(%d changesets remaining, ~%d tests)\n")
777 % (rev, short(node), changesets, tests))
777 % (rev, short(node), changesets, tests))
778 state['current'] = [node]
778 state['current'] = [node]
779 hbisect.save_state(repo, state)
779 hbisect.save_state(repo, state)
780 if not noupdate:
780 if not noupdate:
781 cmdutil.bailifchanged(repo)
781 cmdutil.bailifchanged(repo)
782 return hg.clean(repo, node)
782 return hg.clean(repo, node)
783
783
784 @command('bookmarks|bookmark',
784 @command('bookmarks|bookmark',
785 [('f', 'force', False, _('force')),
785 [('f', 'force', False, _('force')),
786 ('r', 'rev', '', _('revision'), _('REV')),
786 ('r', 'rev', '', _('revision'), _('REV')),
787 ('d', 'delete', False, _('delete a given bookmark')),
787 ('d', 'delete', False, _('delete a given bookmark')),
788 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
788 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
789 ('i', 'inactive', False, _('mark a bookmark inactive'))],
789 ('i', 'inactive', False, _('mark a bookmark inactive'))],
790 _('hg bookmarks [OPTIONS]... [NAME]...'))
790 _('hg bookmarks [OPTIONS]... [NAME]...'))
791 def bookmark(ui, repo, *names, **opts):
791 def bookmark(ui, repo, *names, **opts):
792 '''track a line of development with movable markers
792 '''track a line of development with movable markers
793
793
794 Bookmarks are pointers to certain commits that move when committing.
794 Bookmarks are pointers to certain commits that move when committing.
795 Bookmarks are local. They can be renamed, copied and deleted. It is
795 Bookmarks are local. They can be renamed, copied and deleted. It is
796 possible to use :hg:`merge NAME` to merge from a given bookmark, and
796 possible to use :hg:`merge NAME` to merge from a given bookmark, and
797 :hg:`update NAME` to update to a given bookmark.
797 :hg:`update NAME` to update to a given bookmark.
798
798
799 You can use :hg:`bookmark NAME` to set a bookmark on the working
799 You can use :hg:`bookmark NAME` to set a bookmark on the working
800 directory's parent revision with the given name. If you specify
800 directory's parent revision with the given name. If you specify
801 a revision using -r REV (where REV may be an existing bookmark),
801 a revision using -r REV (where REV may be an existing bookmark),
802 the bookmark is assigned to that revision.
802 the bookmark is assigned to that revision.
803
803
804 Bookmarks can be pushed and pulled between repositories (see :hg:`help
804 Bookmarks can be pushed and pulled between repositories (see :hg:`help
805 push` and :hg:`help pull`). This requires both the local and remote
805 push` and :hg:`help pull`). This requires both the local and remote
806 repositories to support bookmarks. For versions prior to 1.8, this means
806 repositories to support bookmarks. For versions prior to 1.8, this means
807 the bookmarks extension must be enabled.
807 the bookmarks extension must be enabled.
808
808
809 If you set a bookmark called '@', new clones of the repository will
809 If you set a bookmark called '@', new clones of the repository will
810 have that revision checked out (and the bookmark made active) by
810 have that revision checked out (and the bookmark made active) by
811 default.
811 default.
812
812
813 With -i/--inactive, the new bookmark will not be made the active
813 With -i/--inactive, the new bookmark will not be made the active
814 bookmark. If -r/--rev is given, the new bookmark will not be made
814 bookmark. If -r/--rev is given, the new bookmark will not be made
815 active even if -i/--inactive is not given. If no NAME is given, the
815 active even if -i/--inactive is not given. If no NAME is given, the
816 current active bookmark will be marked inactive.
816 current active bookmark will be marked inactive.
817 '''
817 '''
818 force = opts.get('force')
818 force = opts.get('force')
819 rev = opts.get('rev')
819 rev = opts.get('rev')
820 delete = opts.get('delete')
820 delete = opts.get('delete')
821 rename = opts.get('rename')
821 rename = opts.get('rename')
822 inactive = opts.get('inactive')
822 inactive = opts.get('inactive')
823
823
824 def checkformat(mark):
824 def checkformat(mark):
825 mark = mark.strip()
825 mark = mark.strip()
826 if not mark:
826 if not mark:
827 raise util.Abort(_("bookmark names cannot consist entirely of "
827 raise util.Abort(_("bookmark names cannot consist entirely of "
828 "whitespace"))
828 "whitespace"))
829 scmutil.checknewlabel(repo, mark, 'bookmark')
829 scmutil.checknewlabel(repo, mark, 'bookmark')
830 return mark
830 return mark
831
831
832 def checkconflict(repo, mark, cur, force=False, target=None):
832 def checkconflict(repo, mark, cur, force=False, target=None):
833 if mark in marks and not force:
833 if mark in marks and not force:
834 if target:
834 if target:
835 if marks[mark] == target and target == cur:
835 if marks[mark] == target and target == cur:
836 # re-activating a bookmark
836 # re-activating a bookmark
837 return
837 return
838 anc = repo.changelog.ancestors([repo[target].rev()])
838 anc = repo.changelog.ancestors([repo[target].rev()])
839 bmctx = repo[marks[mark]]
839 bmctx = repo[marks[mark]]
840 divs = [repo[b].node() for b in marks
840 divs = [repo[b].node() for b in marks
841 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
841 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
842
842
843 # allow resolving a single divergent bookmark even if moving
843 # allow resolving a single divergent bookmark even if moving
844 # the bookmark across branches when a revision is specified
844 # the bookmark across branches when a revision is specified
845 # that contains a divergent bookmark
845 # that contains a divergent bookmark
846 if bmctx.rev() not in anc and target in divs:
846 if bmctx.rev() not in anc and target in divs:
847 bookmarks.deletedivergent(repo, [target], mark)
847 bookmarks.deletedivergent(repo, [target], mark)
848 return
848 return
849
849
850 deletefrom = [b for b in divs
850 deletefrom = [b for b in divs
851 if repo[b].rev() in anc or b == target]
851 if repo[b].rev() in anc or b == target]
852 bookmarks.deletedivergent(repo, deletefrom, mark)
852 bookmarks.deletedivergent(repo, deletefrom, mark)
853 if bookmarks.validdest(repo, bmctx, repo[target]):
853 if bookmarks.validdest(repo, bmctx, repo[target]):
854 ui.status(_("moving bookmark '%s' forward from %s\n") %
854 ui.status(_("moving bookmark '%s' forward from %s\n") %
855 (mark, short(bmctx.node())))
855 (mark, short(bmctx.node())))
856 return
856 return
857 raise util.Abort(_("bookmark '%s' already exists "
857 raise util.Abort(_("bookmark '%s' already exists "
858 "(use -f to force)") % mark)
858 "(use -f to force)") % mark)
859 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
859 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
860 and not force):
860 and not force):
861 raise util.Abort(
861 raise util.Abort(
862 _("a bookmark cannot have the name of an existing branch"))
862 _("a bookmark cannot have the name of an existing branch"))
863
863
864 if delete and rename:
864 if delete and rename:
865 raise util.Abort(_("--delete and --rename are incompatible"))
865 raise util.Abort(_("--delete and --rename are incompatible"))
866 if delete and rev:
866 if delete and rev:
867 raise util.Abort(_("--rev is incompatible with --delete"))
867 raise util.Abort(_("--rev is incompatible with --delete"))
868 if rename and rev:
868 if rename and rev:
869 raise util.Abort(_("--rev is incompatible with --rename"))
869 raise util.Abort(_("--rev is incompatible with --rename"))
870 if not names and (delete or rev):
870 if not names and (delete or rev):
871 raise util.Abort(_("bookmark name required"))
871 raise util.Abort(_("bookmark name required"))
872
872
873 if delete or rename or names or inactive:
873 if delete or rename or names or inactive:
874 wlock = repo.wlock()
874 wlock = repo.wlock()
875 try:
875 try:
876 cur = repo.changectx('.').node()
876 cur = repo.changectx('.').node()
877 marks = repo._bookmarks
877 marks = repo._bookmarks
878 if delete:
878 if delete:
879 for mark in names:
879 for mark in names:
880 if mark not in marks:
880 if mark not in marks:
881 raise util.Abort(_("bookmark '%s' does not exist") %
881 raise util.Abort(_("bookmark '%s' does not exist") %
882 mark)
882 mark)
883 if mark == repo._bookmarkcurrent:
883 if mark == repo._bookmarkcurrent:
884 bookmarks.unsetcurrent(repo)
884 bookmarks.unsetcurrent(repo)
885 del marks[mark]
885 del marks[mark]
886 marks.write()
886 marks.write()
887
887
888 elif rename:
888 elif rename:
889 if not names:
889 if not names:
890 raise util.Abort(_("new bookmark name required"))
890 raise util.Abort(_("new bookmark name required"))
891 elif len(names) > 1:
891 elif len(names) > 1:
892 raise util.Abort(_("only one new bookmark name allowed"))
892 raise util.Abort(_("only one new bookmark name allowed"))
893 mark = checkformat(names[0])
893 mark = checkformat(names[0])
894 if rename not in marks:
894 if rename not in marks:
895 raise util.Abort(_("bookmark '%s' does not exist") % rename)
895 raise util.Abort(_("bookmark '%s' does not exist") % rename)
896 checkconflict(repo, mark, cur, force)
896 checkconflict(repo, mark, cur, force)
897 marks[mark] = marks[rename]
897 marks[mark] = marks[rename]
898 if repo._bookmarkcurrent == rename and not inactive:
898 if repo._bookmarkcurrent == rename and not inactive:
899 bookmarks.setcurrent(repo, mark)
899 bookmarks.setcurrent(repo, mark)
900 del marks[rename]
900 del marks[rename]
901 marks.write()
901 marks.write()
902
902
903 elif names:
903 elif names:
904 newact = None
904 newact = None
905 for mark in names:
905 for mark in names:
906 mark = checkformat(mark)
906 mark = checkformat(mark)
907 if newact is None:
907 if newact is None:
908 newact = mark
908 newact = mark
909 if inactive and mark == repo._bookmarkcurrent:
909 if inactive and mark == repo._bookmarkcurrent:
910 bookmarks.unsetcurrent(repo)
910 bookmarks.unsetcurrent(repo)
911 return
911 return
912 tgt = cur
912 tgt = cur
913 if rev:
913 if rev:
914 tgt = scmutil.revsingle(repo, rev).node()
914 tgt = scmutil.revsingle(repo, rev).node()
915 checkconflict(repo, mark, cur, force, tgt)
915 checkconflict(repo, mark, cur, force, tgt)
916 marks[mark] = tgt
916 marks[mark] = tgt
917 if not inactive and cur == marks[newact] and not rev:
917 if not inactive and cur == marks[newact] and not rev:
918 bookmarks.setcurrent(repo, newact)
918 bookmarks.setcurrent(repo, newact)
919 elif cur != tgt and newact == repo._bookmarkcurrent:
919 elif cur != tgt and newact == repo._bookmarkcurrent:
920 bookmarks.unsetcurrent(repo)
920 bookmarks.unsetcurrent(repo)
921 marks.write()
921 marks.write()
922
922
923 elif inactive:
923 elif inactive:
924 if len(marks) == 0:
924 if len(marks) == 0:
925 ui.status(_("no bookmarks set\n"))
925 ui.status(_("no bookmarks set\n"))
926 elif not repo._bookmarkcurrent:
926 elif not repo._bookmarkcurrent:
927 ui.status(_("no active bookmark\n"))
927 ui.status(_("no active bookmark\n"))
928 else:
928 else:
929 bookmarks.unsetcurrent(repo)
929 bookmarks.unsetcurrent(repo)
930 finally:
930 finally:
931 wlock.release()
931 wlock.release()
932 else: # show bookmarks
932 else: # show bookmarks
933 hexfn = ui.debugflag and hex or short
933 hexfn = ui.debugflag and hex or short
934 marks = repo._bookmarks
934 marks = repo._bookmarks
935 if len(marks) == 0:
935 if len(marks) == 0:
936 ui.status(_("no bookmarks set\n"))
936 ui.status(_("no bookmarks set\n"))
937 else:
937 else:
938 for bmark, n in sorted(marks.iteritems()):
938 for bmark, n in sorted(marks.iteritems()):
939 current = repo._bookmarkcurrent
939 current = repo._bookmarkcurrent
940 if bmark == current:
940 if bmark == current:
941 prefix, label = '*', 'bookmarks.current'
941 prefix, label = '*', 'bookmarks.current'
942 else:
942 else:
943 prefix, label = ' ', ''
943 prefix, label = ' ', ''
944
944
945 if ui.quiet:
945 if ui.quiet:
946 ui.write("%s\n" % bmark, label=label)
946 ui.write("%s\n" % bmark, label=label)
947 else:
947 else:
948 ui.write(" %s %-25s %d:%s\n" % (
948 ui.write(" %s %-25s %d:%s\n" % (
949 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
949 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
950 label=label)
950 label=label)
951
951
952 @command('branch',
952 @command('branch',
953 [('f', 'force', None,
953 [('f', 'force', None,
954 _('set branch name even if it shadows an existing branch')),
954 _('set branch name even if it shadows an existing branch')),
955 ('C', 'clean', None, _('reset branch name to parent branch name'))],
955 ('C', 'clean', None, _('reset branch name to parent branch name'))],
956 _('[-fC] [NAME]'))
956 _('[-fC] [NAME]'))
957 def branch(ui, repo, label=None, **opts):
957 def branch(ui, repo, label=None, **opts):
958 """set or show the current branch name
958 """set or show the current branch name
959
959
960 .. note::
960 .. note::
961
961
962 Branch names are permanent and global. Use :hg:`bookmark` to create a
962 Branch names are permanent and global. Use :hg:`bookmark` to create a
963 light-weight bookmark instead. See :hg:`help glossary` for more
963 light-weight bookmark instead. See :hg:`help glossary` for more
964 information about named branches and bookmarks.
964 information about named branches and bookmarks.
965
965
966 With no argument, show the current branch name. With one argument,
966 With no argument, show the current branch name. With one argument,
967 set the working directory branch name (the branch will not exist
967 set the working directory branch name (the branch will not exist
968 in the repository until the next commit). Standard practice
968 in the repository until the next commit). Standard practice
969 recommends that primary development take place on the 'default'
969 recommends that primary development take place on the 'default'
970 branch.
970 branch.
971
971
972 Unless -f/--force is specified, branch will not let you set a
972 Unless -f/--force is specified, branch will not let you set a
973 branch name that already exists, even if it's inactive.
973 branch name that already exists, even if it's inactive.
974
974
975 Use -C/--clean to reset the working directory branch to that of
975 Use -C/--clean to reset the working directory branch to that of
976 the parent of the working directory, negating a previous branch
976 the parent of the working directory, negating a previous branch
977 change.
977 change.
978
978
979 Use the command :hg:`update` to switch to an existing branch. Use
979 Use the command :hg:`update` to switch to an existing branch. Use
980 :hg:`commit --close-branch` to mark this branch as closed.
980 :hg:`commit --close-branch` to mark this branch as closed.
981
981
982 Returns 0 on success.
982 Returns 0 on success.
983 """
983 """
984 if label:
984 if label:
985 label = label.strip()
985 label = label.strip()
986
986
987 if not opts.get('clean') and not label:
987 if not opts.get('clean') and not label:
988 ui.write("%s\n" % repo.dirstate.branch())
988 ui.write("%s\n" % repo.dirstate.branch())
989 return
989 return
990
990
991 wlock = repo.wlock()
991 wlock = repo.wlock()
992 try:
992 try:
993 if opts.get('clean'):
993 if opts.get('clean'):
994 label = repo[None].p1().branch()
994 label = repo[None].p1().branch()
995 repo.dirstate.setbranch(label)
995 repo.dirstate.setbranch(label)
996 ui.status(_('reset working directory to branch %s\n') % label)
996 ui.status(_('reset working directory to branch %s\n') % label)
997 elif label:
997 elif label:
998 if not opts.get('force') and label in repo.branchmap():
998 if not opts.get('force') and label in repo.branchmap():
999 if label not in [p.branch() for p in repo.parents()]:
999 if label not in [p.branch() for p in repo.parents()]:
1000 raise util.Abort(_('a branch of the same name already'
1000 raise util.Abort(_('a branch of the same name already'
1001 ' exists'),
1001 ' exists'),
1002 # i18n: "it" refers to an existing branch
1002 # i18n: "it" refers to an existing branch
1003 hint=_("use 'hg update' to switch to it"))
1003 hint=_("use 'hg update' to switch to it"))
1004 scmutil.checknewlabel(repo, label, 'branch')
1004 scmutil.checknewlabel(repo, label, 'branch')
1005 repo.dirstate.setbranch(label)
1005 repo.dirstate.setbranch(label)
1006 ui.status(_('marked working directory as branch %s\n') % label)
1006 ui.status(_('marked working directory as branch %s\n') % label)
1007 ui.status(_('(branches are permanent and global, '
1007 ui.status(_('(branches are permanent and global, '
1008 'did you want a bookmark?)\n'))
1008 'did you want a bookmark?)\n'))
1009 finally:
1009 finally:
1010 wlock.release()
1010 wlock.release()
1011
1011
1012 @command('branches',
1012 @command('branches',
1013 [('a', 'active', False, _('show only branches that have unmerged heads')),
1013 [('a', 'active', False, _('show only branches that have unmerged heads')),
1014 ('c', 'closed', False, _('show normal and closed branches'))],
1014 ('c', 'closed', False, _('show normal and closed branches'))],
1015 _('[-ac]'))
1015 _('[-ac]'))
1016 def branches(ui, repo, active=False, closed=False):
1016 def branches(ui, repo, active=False, closed=False):
1017 """list repository named branches
1017 """list repository named branches
1018
1018
1019 List the repository's named branches, indicating which ones are
1019 List the repository's named branches, indicating which ones are
1020 inactive. If -c/--closed is specified, also list branches which have
1020 inactive. If -c/--closed is specified, also list branches which have
1021 been marked closed (see :hg:`commit --close-branch`).
1021 been marked closed (see :hg:`commit --close-branch`).
1022
1022
1023 If -a/--active is specified, only show active branches. A branch
1023 If -a/--active is specified, only show active branches. A branch
1024 is considered active if it contains repository heads.
1024 is considered active if it contains repository heads.
1025
1025
1026 Use the command :hg:`update` to switch to an existing branch.
1026 Use the command :hg:`update` to switch to an existing branch.
1027
1027
1028 Returns 0.
1028 Returns 0.
1029 """
1029 """
1030
1030
1031 hexfunc = ui.debugflag and hex or short
1031 hexfunc = ui.debugflag and hex or short
1032
1032
1033 allheads = set(repo.heads())
1033 allheads = set(repo.heads())
1034 branches = []
1034 branches = []
1035 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1035 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1036 isactive = not isclosed and bool(set(heads) & allheads)
1036 isactive = not isclosed and bool(set(heads) & allheads)
1037 branches.append((tag, repo[tip], isactive, not isclosed))
1037 branches.append((tag, repo[tip], isactive, not isclosed))
1038 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1038 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1039 reverse=True)
1039 reverse=True)
1040
1040
1041 for tag, ctx, isactive, isopen in branches:
1041 for tag, ctx, isactive, isopen in branches:
1042 if (not active) or isactive:
1042 if (not active) or isactive:
1043 if isactive:
1043 if isactive:
1044 label = 'branches.active'
1044 label = 'branches.active'
1045 notice = ''
1045 notice = ''
1046 elif not isopen:
1046 elif not isopen:
1047 if not closed:
1047 if not closed:
1048 continue
1048 continue
1049 label = 'branches.closed'
1049 label = 'branches.closed'
1050 notice = _(' (closed)')
1050 notice = _(' (closed)')
1051 else:
1051 else:
1052 label = 'branches.inactive'
1052 label = 'branches.inactive'
1053 notice = _(' (inactive)')
1053 notice = _(' (inactive)')
1054 if tag == repo.dirstate.branch():
1054 if tag == repo.dirstate.branch():
1055 label = 'branches.current'
1055 label = 'branches.current'
1056 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1056 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1057 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1057 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1058 'log.changeset changeset.%s' % ctx.phasestr())
1058 'log.changeset changeset.%s' % ctx.phasestr())
1059 labeledtag = ui.label(tag, label)
1059 labeledtag = ui.label(tag, label)
1060 if ui.quiet:
1060 if ui.quiet:
1061 ui.write("%s\n" % labeledtag)
1061 ui.write("%s\n" % labeledtag)
1062 else:
1062 else:
1063 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1063 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1064
1064
1065 @command('bundle',
1065 @command('bundle',
1066 [('f', 'force', None, _('run even when the destination is unrelated')),
1066 [('f', 'force', None, _('run even when the destination is unrelated')),
1067 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1067 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1068 _('REV')),
1068 _('REV')),
1069 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1069 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1070 _('BRANCH')),
1070 _('BRANCH')),
1071 ('', 'base', [],
1071 ('', 'base', [],
1072 _('a base changeset assumed to be available at the destination'),
1072 _('a base changeset assumed to be available at the destination'),
1073 _('REV')),
1073 _('REV')),
1074 ('a', 'all', None, _('bundle all changesets in the repository')),
1074 ('a', 'all', None, _('bundle all changesets in the repository')),
1075 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1075 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1076 ] + remoteopts,
1076 ] + remoteopts,
1077 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1077 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1078 def bundle(ui, repo, fname, dest=None, **opts):
1078 def bundle(ui, repo, fname, dest=None, **opts):
1079 """create a changegroup file
1079 """create a changegroup file
1080
1080
1081 Generate a compressed changegroup file collecting changesets not
1081 Generate a compressed changegroup file collecting changesets not
1082 known to be in another repository.
1082 known to be in another repository.
1083
1083
1084 If you omit the destination repository, then hg assumes the
1084 If you omit the destination repository, then hg assumes the
1085 destination will have all the nodes you specify with --base
1085 destination will have all the nodes you specify with --base
1086 parameters. To create a bundle containing all changesets, use
1086 parameters. To create a bundle containing all changesets, use
1087 -a/--all (or --base null).
1087 -a/--all (or --base null).
1088
1088
1089 You can change compression method with the -t/--type option.
1089 You can change compression method with the -t/--type option.
1090 The available compression methods are: none, bzip2, and
1090 The available compression methods are: none, bzip2, and
1091 gzip (by default, bundles are compressed using bzip2).
1091 gzip (by default, bundles are compressed using bzip2).
1092
1092
1093 The bundle file can then be transferred using conventional means
1093 The bundle file can then be transferred using conventional means
1094 and applied to another repository with the unbundle or pull
1094 and applied to another repository with the unbundle or pull
1095 command. This is useful when direct push and pull are not
1095 command. This is useful when direct push and pull are not
1096 available or when exporting an entire repository is undesirable.
1096 available or when exporting an entire repository is undesirable.
1097
1097
1098 Applying bundles preserves all changeset contents including
1098 Applying bundles preserves all changeset contents including
1099 permissions, copy/rename information, and revision history.
1099 permissions, copy/rename information, and revision history.
1100
1100
1101 Returns 0 on success, 1 if no changes found.
1101 Returns 0 on success, 1 if no changes found.
1102 """
1102 """
1103 revs = None
1103 revs = None
1104 if 'rev' in opts:
1104 if 'rev' in opts:
1105 revs = scmutil.revrange(repo, opts['rev'])
1105 revs = scmutil.revrange(repo, opts['rev'])
1106
1106
1107 bundletype = opts.get('type', 'bzip2').lower()
1107 bundletype = opts.get('type', 'bzip2').lower()
1108 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1108 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1109 bundletype = btypes.get(bundletype)
1109 bundletype = btypes.get(bundletype)
1110 if bundletype not in changegroup.bundletypes:
1110 if bundletype not in changegroup.bundletypes:
1111 raise util.Abort(_('unknown bundle type specified with --type'))
1111 raise util.Abort(_('unknown bundle type specified with --type'))
1112
1112
1113 if opts.get('all'):
1113 if opts.get('all'):
1114 base = ['null']
1114 base = ['null']
1115 else:
1115 else:
1116 base = scmutil.revrange(repo, opts.get('base'))
1116 base = scmutil.revrange(repo, opts.get('base'))
1117 # TODO: get desired bundlecaps from command line.
1117 # TODO: get desired bundlecaps from command line.
1118 bundlecaps = None
1118 bundlecaps = None
1119 if base:
1119 if base:
1120 if dest:
1120 if dest:
1121 raise util.Abort(_("--base is incompatible with specifying "
1121 raise util.Abort(_("--base is incompatible with specifying "
1122 "a destination"))
1122 "a destination"))
1123 common = [repo.lookup(rev) for rev in base]
1123 common = [repo.lookup(rev) for rev in base]
1124 heads = revs and map(repo.lookup, revs) or revs
1124 heads = revs and map(repo.lookup, revs) or revs
1125 cg = repo.getbundle('bundle', heads=heads, common=common,
1125 cg = repo.getbundle('bundle', heads=heads, common=common,
1126 bundlecaps=bundlecaps)
1126 bundlecaps=bundlecaps)
1127 outgoing = None
1127 outgoing = None
1128 else:
1128 else:
1129 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1129 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1130 dest, branches = hg.parseurl(dest, opts.get('branch'))
1130 dest, branches = hg.parseurl(dest, opts.get('branch'))
1131 other = hg.peer(repo, opts, dest)
1131 other = hg.peer(repo, opts, dest)
1132 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1132 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1133 heads = revs and map(repo.lookup, revs) or revs
1133 heads = revs and map(repo.lookup, revs) or revs
1134 outgoing = discovery.findcommonoutgoing(repo, other,
1134 outgoing = discovery.findcommonoutgoing(repo, other,
1135 onlyheads=heads,
1135 onlyheads=heads,
1136 force=opts.get('force'),
1136 force=opts.get('force'),
1137 portable=True)
1137 portable=True)
1138 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1138 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1139 if not cg:
1139 if not cg:
1140 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1140 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1141 return 1
1141 return 1
1142
1142
1143 changegroup.writebundle(cg, fname, bundletype)
1143 changegroup.writebundle(cg, fname, bundletype)
1144
1144
1145 @command('cat',
1145 @command('cat',
1146 [('o', 'output', '',
1146 [('o', 'output', '',
1147 _('print output to file with formatted name'), _('FORMAT')),
1147 _('print output to file with formatted name'), _('FORMAT')),
1148 ('r', 'rev', '', _('print the given revision'), _('REV')),
1148 ('r', 'rev', '', _('print the given revision'), _('REV')),
1149 ('', 'decode', None, _('apply any matching decode filter')),
1149 ('', 'decode', None, _('apply any matching decode filter')),
1150 ] + walkopts,
1150 ] + walkopts,
1151 _('[OPTION]... FILE...'))
1151 _('[OPTION]... FILE...'))
1152 def cat(ui, repo, file1, *pats, **opts):
1152 def cat(ui, repo, file1, *pats, **opts):
1153 """output the current or given revision of files
1153 """output the current or given revision of files
1154
1154
1155 Print the specified files as they were at the given revision. If
1155 Print the specified files as they were at the given revision. If
1156 no revision is given, the parent of the working directory is used.
1156 no revision is given, the parent of the working directory is used.
1157
1157
1158 Output may be to a file, in which case the name of the file is
1158 Output may be to a file, in which case the name of the file is
1159 given using a format string. The formatting rules are the same as
1159 given using a format string. The formatting rules are the same as
1160 for the export command, with the following additions:
1160 for the export command, with the following additions:
1161
1161
1162 :``%s``: basename of file being printed
1162 :``%s``: basename of file being printed
1163 :``%d``: dirname of file being printed, or '.' if in repository root
1163 :``%d``: dirname of file being printed, or '.' if in repository root
1164 :``%p``: root-relative path name of file being printed
1164 :``%p``: root-relative path name of file being printed
1165
1165
1166 Returns 0 on success.
1166 Returns 0 on success.
1167 """
1167 """
1168 ctx = scmutil.revsingle(repo, opts.get('rev'))
1168 ctx = scmutil.revsingle(repo, opts.get('rev'))
1169 err = 1
1169 err = 1
1170 m = scmutil.match(ctx, (file1,) + pats, opts)
1170 m = scmutil.match(ctx, (file1,) + pats, opts)
1171
1171
1172 def write(path):
1172 def write(path):
1173 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1173 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1174 pathname=path)
1174 pathname=path)
1175 data = ctx[path].data()
1175 data = ctx[path].data()
1176 if opts.get('decode'):
1176 if opts.get('decode'):
1177 data = repo.wwritedata(path, data)
1177 data = repo.wwritedata(path, data)
1178 fp.write(data)
1178 fp.write(data)
1179 fp.close()
1179 fp.close()
1180
1180
1181 # Automation often uses hg cat on single files, so special case it
1181 # Automation often uses hg cat on single files, so special case it
1182 # for performance to avoid the cost of parsing the manifest.
1182 # for performance to avoid the cost of parsing the manifest.
1183 if len(m.files()) == 1 and not m.anypats():
1183 if len(m.files()) == 1 and not m.anypats():
1184 file = m.files()[0]
1184 file = m.files()[0]
1185 mf = repo.manifest
1185 mf = repo.manifest
1186 mfnode = ctx._changeset[0]
1186 mfnode = ctx._changeset[0]
1187 if mf.find(mfnode, file)[0]:
1187 if mf.find(mfnode, file)[0]:
1188 write(file)
1188 write(file)
1189 return 0
1189 return 0
1190
1190
1191 for abs in ctx.walk(m):
1191 for abs in ctx.walk(m):
1192 write(abs)
1192 write(abs)
1193 err = 0
1193 err = 0
1194 return err
1194 return err
1195
1195
1196 @command('^clone',
1196 @command('^clone',
1197 [('U', 'noupdate', None,
1197 [('U', 'noupdate', None,
1198 _('the clone will include an empty working copy (only a repository)')),
1198 _('the clone will include an empty working copy (only a repository)')),
1199 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1199 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1200 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1200 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1201 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1201 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1202 ('', 'pull', None, _('use pull protocol to copy metadata')),
1202 ('', 'pull', None, _('use pull protocol to copy metadata')),
1203 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1203 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1204 ] + remoteopts,
1204 ] + remoteopts,
1205 _('[OPTION]... SOURCE [DEST]'))
1205 _('[OPTION]... SOURCE [DEST]'))
1206 def clone(ui, source, dest=None, **opts):
1206 def clone(ui, source, dest=None, **opts):
1207 """make a copy of an existing repository
1207 """make a copy of an existing repository
1208
1208
1209 Create a copy of an existing repository in a new directory.
1209 Create a copy of an existing repository in a new directory.
1210
1210
1211 If no destination directory name is specified, it defaults to the
1211 If no destination directory name is specified, it defaults to the
1212 basename of the source.
1212 basename of the source.
1213
1213
1214 The location of the source is added to the new repository's
1214 The location of the source is added to the new repository's
1215 ``.hg/hgrc`` file, as the default to be used for future pulls.
1215 ``.hg/hgrc`` file, as the default to be used for future pulls.
1216
1216
1217 Only local paths and ``ssh://`` URLs are supported as
1217 Only local paths and ``ssh://`` URLs are supported as
1218 destinations. For ``ssh://`` destinations, no working directory or
1218 destinations. For ``ssh://`` destinations, no working directory or
1219 ``.hg/hgrc`` will be created on the remote side.
1219 ``.hg/hgrc`` will be created on the remote side.
1220
1220
1221 To pull only a subset of changesets, specify one or more revisions
1221 To pull only a subset of changesets, specify one or more revisions
1222 identifiers with -r/--rev or branches with -b/--branch. The
1222 identifiers with -r/--rev or branches with -b/--branch. The
1223 resulting clone will contain only the specified changesets and
1223 resulting clone will contain only the specified changesets and
1224 their ancestors. These options (or 'clone src#rev dest') imply
1224 their ancestors. These options (or 'clone src#rev dest') imply
1225 --pull, even for local source repositories. Note that specifying a
1225 --pull, even for local source repositories. Note that specifying a
1226 tag will include the tagged changeset but not the changeset
1226 tag will include the tagged changeset but not the changeset
1227 containing the tag.
1227 containing the tag.
1228
1228
1229 If the source repository has a bookmark called '@' set, that
1229 If the source repository has a bookmark called '@' set, that
1230 revision will be checked out in the new repository by default.
1230 revision will be checked out in the new repository by default.
1231
1231
1232 To check out a particular version, use -u/--update, or
1232 To check out a particular version, use -u/--update, or
1233 -U/--noupdate to create a clone with no working directory.
1233 -U/--noupdate to create a clone with no working directory.
1234
1234
1235 .. container:: verbose
1235 .. container:: verbose
1236
1236
1237 For efficiency, hardlinks are used for cloning whenever the
1237 For efficiency, hardlinks are used for cloning whenever the
1238 source and destination are on the same filesystem (note this
1238 source and destination are on the same filesystem (note this
1239 applies only to the repository data, not to the working
1239 applies only to the repository data, not to the working
1240 directory). Some filesystems, such as AFS, implement hardlinking
1240 directory). Some filesystems, such as AFS, implement hardlinking
1241 incorrectly, but do not report errors. In these cases, use the
1241 incorrectly, but do not report errors. In these cases, use the
1242 --pull option to avoid hardlinking.
1242 --pull option to avoid hardlinking.
1243
1243
1244 In some cases, you can clone repositories and the working
1244 In some cases, you can clone repositories and the working
1245 directory using full hardlinks with ::
1245 directory using full hardlinks with ::
1246
1246
1247 $ cp -al REPO REPOCLONE
1247 $ cp -al REPO REPOCLONE
1248
1248
1249 This is the fastest way to clone, but it is not always safe. The
1249 This is the fastest way to clone, but it is not always safe. The
1250 operation is not atomic (making sure REPO is not modified during
1250 operation is not atomic (making sure REPO is not modified during
1251 the operation is up to you) and you have to make sure your
1251 the operation is up to you) and you have to make sure your
1252 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1252 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1253 so). Also, this is not compatible with certain extensions that
1253 so). Also, this is not compatible with certain extensions that
1254 place their metadata under the .hg directory, such as mq.
1254 place their metadata under the .hg directory, such as mq.
1255
1255
1256 Mercurial will update the working directory to the first applicable
1256 Mercurial will update the working directory to the first applicable
1257 revision from this list:
1257 revision from this list:
1258
1258
1259 a) null if -U or the source repository has no changesets
1259 a) null if -U or the source repository has no changesets
1260 b) if -u . and the source repository is local, the first parent of
1260 b) if -u . and the source repository is local, the first parent of
1261 the source repository's working directory
1261 the source repository's working directory
1262 c) the changeset specified with -u (if a branch name, this means the
1262 c) the changeset specified with -u (if a branch name, this means the
1263 latest head of that branch)
1263 latest head of that branch)
1264 d) the changeset specified with -r
1264 d) the changeset specified with -r
1265 e) the tipmost head specified with -b
1265 e) the tipmost head specified with -b
1266 f) the tipmost head specified with the url#branch source syntax
1266 f) the tipmost head specified with the url#branch source syntax
1267 g) the revision marked with the '@' bookmark, if present
1267 g) the revision marked with the '@' bookmark, if present
1268 h) the tipmost head of the default branch
1268 h) the tipmost head of the default branch
1269 i) tip
1269 i) tip
1270
1270
1271 Examples:
1271 Examples:
1272
1272
1273 - clone a remote repository to a new directory named hg/::
1273 - clone a remote repository to a new directory named hg/::
1274
1274
1275 hg clone http://selenic.com/hg
1275 hg clone http://selenic.com/hg
1276
1276
1277 - create a lightweight local clone::
1277 - create a lightweight local clone::
1278
1278
1279 hg clone project/ project-feature/
1279 hg clone project/ project-feature/
1280
1280
1281 - clone from an absolute path on an ssh server (note double-slash)::
1281 - clone from an absolute path on an ssh server (note double-slash)::
1282
1282
1283 hg clone ssh://user@server//home/projects/alpha/
1283 hg clone ssh://user@server//home/projects/alpha/
1284
1284
1285 - do a high-speed clone over a LAN while checking out a
1285 - do a high-speed clone over a LAN while checking out a
1286 specified version::
1286 specified version::
1287
1287
1288 hg clone --uncompressed http://server/repo -u 1.5
1288 hg clone --uncompressed http://server/repo -u 1.5
1289
1289
1290 - create a repository without changesets after a particular revision::
1290 - create a repository without changesets after a particular revision::
1291
1291
1292 hg clone -r 04e544 experimental/ good/
1292 hg clone -r 04e544 experimental/ good/
1293
1293
1294 - clone (and track) a particular named branch::
1294 - clone (and track) a particular named branch::
1295
1295
1296 hg clone http://selenic.com/hg#stable
1296 hg clone http://selenic.com/hg#stable
1297
1297
1298 See :hg:`help urls` for details on specifying URLs.
1298 See :hg:`help urls` for details on specifying URLs.
1299
1299
1300 Returns 0 on success.
1300 Returns 0 on success.
1301 """
1301 """
1302 if opts.get('noupdate') and opts.get('updaterev'):
1302 if opts.get('noupdate') and opts.get('updaterev'):
1303 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1303 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1304
1304
1305 r = hg.clone(ui, opts, source, dest,
1305 r = hg.clone(ui, opts, source, dest,
1306 pull=opts.get('pull'),
1306 pull=opts.get('pull'),
1307 stream=opts.get('uncompressed'),
1307 stream=opts.get('uncompressed'),
1308 rev=opts.get('rev'),
1308 rev=opts.get('rev'),
1309 update=opts.get('updaterev') or not opts.get('noupdate'),
1309 update=opts.get('updaterev') or not opts.get('noupdate'),
1310 branch=opts.get('branch'))
1310 branch=opts.get('branch'))
1311
1311
1312 return r is None
1312 return r is None
1313
1313
1314 @command('^commit|ci',
1314 @command('^commit|ci',
1315 [('A', 'addremove', None,
1315 [('A', 'addremove', None,
1316 _('mark new/missing files as added/removed before committing')),
1316 _('mark new/missing files as added/removed before committing')),
1317 ('', 'close-branch', None,
1317 ('', 'close-branch', None,
1318 _('mark a branch as closed, hiding it from the branch list')),
1318 _('mark a branch as closed, hiding it from the branch list')),
1319 ('', 'amend', None, _('amend the parent of the working dir')),
1319 ('', 'amend', None, _('amend the parent of the working dir')),
1320 ('s', 'secret', None, _('use the secret phase for committing')),
1320 ('s', 'secret', None, _('use the secret phase for committing')),
1321 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1321 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1322 _('[OPTION]... [FILE]...'))
1322 _('[OPTION]... [FILE]...'))
1323 def commit(ui, repo, *pats, **opts):
1323 def commit(ui, repo, *pats, **opts):
1324 """commit the specified files or all outstanding changes
1324 """commit the specified files or all outstanding changes
1325
1325
1326 Commit changes to the given files into the repository. Unlike a
1326 Commit changes to the given files into the repository. Unlike a
1327 centralized SCM, this operation is a local operation. See
1327 centralized SCM, this operation is a local operation. See
1328 :hg:`push` for a way to actively distribute your changes.
1328 :hg:`push` for a way to actively distribute your changes.
1329
1329
1330 If a list of files is omitted, all changes reported by :hg:`status`
1330 If a list of files is omitted, all changes reported by :hg:`status`
1331 will be committed.
1331 will be committed.
1332
1332
1333 If you are committing the result of a merge, do not provide any
1333 If you are committing the result of a merge, do not provide any
1334 filenames or -I/-X filters.
1334 filenames or -I/-X filters.
1335
1335
1336 If no commit message is specified, Mercurial starts your
1336 If no commit message is specified, Mercurial starts your
1337 configured editor where you can enter a message. In case your
1337 configured editor where you can enter a message. In case your
1338 commit fails, you will find a backup of your message in
1338 commit fails, you will find a backup of your message in
1339 ``.hg/last-message.txt``.
1339 ``.hg/last-message.txt``.
1340
1340
1341 The --amend flag can be used to amend the parent of the
1341 The --amend flag can be used to amend the parent of the
1342 working directory with a new commit that contains the changes
1342 working directory with a new commit that contains the changes
1343 in the parent in addition to those currently reported by :hg:`status`,
1343 in the parent in addition to those currently reported by :hg:`status`,
1344 if there are any. The old commit is stored in a backup bundle in
1344 if there are any. The old commit is stored in a backup bundle in
1345 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1345 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1346 on how to restore it).
1346 on how to restore it).
1347
1347
1348 Message, user and date are taken from the amended commit unless
1348 Message, user and date are taken from the amended commit unless
1349 specified. When a message isn't specified on the command line,
1349 specified. When a message isn't specified on the command line,
1350 the editor will open with the message of the amended commit.
1350 the editor will open with the message of the amended commit.
1351
1351
1352 It is not possible to amend public changesets (see :hg:`help phases`)
1352 It is not possible to amend public changesets (see :hg:`help phases`)
1353 or changesets that have children.
1353 or changesets that have children.
1354
1354
1355 See :hg:`help dates` for a list of formats valid for -d/--date.
1355 See :hg:`help dates` for a list of formats valid for -d/--date.
1356
1356
1357 Returns 0 on success, 1 if nothing changed.
1357 Returns 0 on success, 1 if nothing changed.
1358 """
1358 """
1359 if opts.get('subrepos'):
1359 if opts.get('subrepos'):
1360 if opts.get('amend'):
1360 if opts.get('amend'):
1361 raise util.Abort(_('cannot amend with --subrepos'))
1361 raise util.Abort(_('cannot amend with --subrepos'))
1362 # Let --subrepos on the command line override config setting.
1362 # Let --subrepos on the command line override config setting.
1363 ui.setconfig('ui', 'commitsubrepos', True)
1363 ui.setconfig('ui', 'commitsubrepos', True)
1364
1364
1365 # Save this for restoring it later
1365 # Save this for restoring it later
1366 oldcommitphase = ui.config('phases', 'new-commit')
1366 oldcommitphase = ui.config('phases', 'new-commit')
1367
1367
1368 cmdutil.checkunfinished(repo, commit=True)
1368 cmdutil.checkunfinished(repo, commit=True)
1369
1369
1370 branch = repo[None].branch()
1370 branch = repo[None].branch()
1371 bheads = repo.branchheads(branch)
1371 bheads = repo.branchheads(branch)
1372
1372
1373 extra = {}
1373 extra = {}
1374 if opts.get('close_branch'):
1374 if opts.get('close_branch'):
1375 extra['close'] = 1
1375 extra['close'] = 1
1376
1376
1377 if not bheads:
1377 if not bheads:
1378 raise util.Abort(_('can only close branch heads'))
1378 raise util.Abort(_('can only close branch heads'))
1379 elif opts.get('amend'):
1379 elif opts.get('amend'):
1380 if repo.parents()[0].p1().branch() != branch and \
1380 if repo.parents()[0].p1().branch() != branch and \
1381 repo.parents()[0].p2().branch() != branch:
1381 repo.parents()[0].p2().branch() != branch:
1382 raise util.Abort(_('can only close branch heads'))
1382 raise util.Abort(_('can only close branch heads'))
1383
1383
1384 if opts.get('amend'):
1384 if opts.get('amend'):
1385 if ui.configbool('ui', 'commitsubrepos'):
1385 if ui.configbool('ui', 'commitsubrepos'):
1386 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1386 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1387
1387
1388 old = repo['.']
1388 old = repo['.']
1389 if old.phase() == phases.public:
1389 if old.phase() == phases.public:
1390 raise util.Abort(_('cannot amend public changesets'))
1390 raise util.Abort(_('cannot amend public changesets'))
1391 if len(repo[None].parents()) > 1:
1391 if len(repo[None].parents()) > 1:
1392 raise util.Abort(_('cannot amend while merging'))
1392 raise util.Abort(_('cannot amend while merging'))
1393 if (not obsolete._enabled) and old.children():
1393 if (not obsolete._enabled) and old.children():
1394 raise util.Abort(_('cannot amend changeset with children'))
1394 raise util.Abort(_('cannot amend changeset with children'))
1395
1395
1396 e = cmdutil.commiteditor
1396 e = cmdutil.commiteditor
1397 if opts.get('force_editor'):
1397 if opts.get('force_editor'):
1398 e = cmdutil.commitforceeditor
1398 e = cmdutil.commitforceeditor
1399
1399
1400 def commitfunc(ui, repo, message, match, opts):
1400 def commitfunc(ui, repo, message, match, opts):
1401 editor = e
1401 editor = e
1402 # message contains text from -m or -l, if it's empty,
1402 # message contains text from -m or -l, if it's empty,
1403 # open the editor with the old message
1403 # open the editor with the old message
1404 if not message:
1404 if not message:
1405 message = old.description()
1405 message = old.description()
1406 editor = cmdutil.commitforceeditor
1406 editor = cmdutil.commitforceeditor
1407 try:
1407 try:
1408 if opts.get('secret'):
1408 if opts.get('secret'):
1409 ui.setconfig('phases', 'new-commit', 'secret')
1409 ui.setconfig('phases', 'new-commit', 'secret')
1410
1410
1411 return repo.commit(message,
1411 return repo.commit(message,
1412 opts.get('user') or old.user(),
1412 opts.get('user') or old.user(),
1413 opts.get('date') or old.date(),
1413 opts.get('date') or old.date(),
1414 match,
1414 match,
1415 editor=editor,
1415 editor=editor,
1416 extra=extra)
1416 extra=extra)
1417 finally:
1417 finally:
1418 ui.setconfig('phases', 'new-commit', oldcommitphase)
1418 ui.setconfig('phases', 'new-commit', oldcommitphase)
1419
1419
1420 current = repo._bookmarkcurrent
1420 current = repo._bookmarkcurrent
1421 marks = old.bookmarks()
1421 marks = old.bookmarks()
1422 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1422 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1423 if node == old.node():
1423 if node == old.node():
1424 ui.status(_("nothing changed\n"))
1424 ui.status(_("nothing changed\n"))
1425 return 1
1425 return 1
1426 elif marks:
1426 elif marks:
1427 ui.debug('moving bookmarks %r from %s to %s\n' %
1427 ui.debug('moving bookmarks %r from %s to %s\n' %
1428 (marks, old.hex(), hex(node)))
1428 (marks, old.hex(), hex(node)))
1429 newmarks = repo._bookmarks
1429 newmarks = repo._bookmarks
1430 for bm in marks:
1430 for bm in marks:
1431 newmarks[bm] = node
1431 newmarks[bm] = node
1432 if bm == current:
1432 if bm == current:
1433 bookmarks.setcurrent(repo, bm)
1433 bookmarks.setcurrent(repo, bm)
1434 newmarks.write()
1434 newmarks.write()
1435 else:
1435 else:
1436 e = cmdutil.commiteditor
1436 e = cmdutil.commiteditor
1437 if opts.get('force_editor'):
1437 if opts.get('force_editor'):
1438 e = cmdutil.commitforceeditor
1438 e = cmdutil.commitforceeditor
1439
1439
1440 def commitfunc(ui, repo, message, match, opts):
1440 def commitfunc(ui, repo, message, match, opts):
1441 try:
1441 try:
1442 if opts.get('secret'):
1442 if opts.get('secret'):
1443 ui.setconfig('phases', 'new-commit', 'secret')
1443 ui.setconfig('phases', 'new-commit', 'secret')
1444
1444
1445 return repo.commit(message, opts.get('user'), opts.get('date'),
1445 return repo.commit(message, opts.get('user'), opts.get('date'),
1446 match, editor=e, extra=extra)
1446 match, editor=e, extra=extra)
1447 finally:
1447 finally:
1448 ui.setconfig('phases', 'new-commit', oldcommitphase)
1448 ui.setconfig('phases', 'new-commit', oldcommitphase)
1449
1449
1450
1450
1451 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1451 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1452
1452
1453 if not node:
1453 if not node:
1454 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1454 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1455 if stat[3]:
1455 if stat[3]:
1456 ui.status(_("nothing changed (%d missing files, see "
1456 ui.status(_("nothing changed (%d missing files, see "
1457 "'hg status')\n") % len(stat[3]))
1457 "'hg status')\n") % len(stat[3]))
1458 else:
1458 else:
1459 ui.status(_("nothing changed\n"))
1459 ui.status(_("nothing changed\n"))
1460 return 1
1460 return 1
1461
1461
1462 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1462 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1463
1463
1464 @command('config|showconfig|debugconfig',
1464 @command('config|showconfig|debugconfig',
1465 [('u', 'untrusted', None, _('show untrusted configuration options')),
1465 [('u', 'untrusted', None, _('show untrusted configuration options')),
1466 ('e', 'edit', None, _('start editor'))],
1466 ('e', 'edit', None, _('start editor'))],
1467 _('[-u] [NAME]...'))
1467 _('[-u] [NAME]...'))
1468 def config(ui, repo, *values, **opts):
1468 def config(ui, repo, *values, **opts):
1469 """show combined config settings from all hgrc files
1469 """show combined config settings from all hgrc files
1470
1470
1471 With no arguments, print names and values of all config items.
1471 With no arguments, print names and values of all config items.
1472
1472
1473 With one argument of the form section.name, print just the value
1473 With one argument of the form section.name, print just the value
1474 of that config item.
1474 of that config item.
1475
1475
1476 With multiple arguments, print names and values of all config
1476 With multiple arguments, print names and values of all config
1477 items with matching section names.
1477 items with matching section names.
1478
1478
1479 With --debug, the source (filename and line number) is printed
1479 With --debug, the source (filename and line number) is printed
1480 for each config item.
1480 for each config item.
1481
1481
1482 Returns 0 on success.
1482 Returns 0 on success.
1483 """
1483 """
1484
1484
1485 if opts.get('edit'):
1485 if opts.get('edit'):
1486 paths = scmutil.userrcpath()
1486 paths = scmutil.userrcpath()
1487 for f in paths:
1487 for f in paths:
1488 if os.path.exists(f):
1488 if os.path.exists(f):
1489 break
1489 break
1490 else:
1490 else:
1491 f = paths[0]
1491 f = paths[0]
1492 fp = open(f, "w")
1493 fp.write(
1494 '# example config (see "hg help config" for more info)\n'
1495 '\n'
1496 '[ui]\n'
1497 '# set this to your full email address\n'
1498 'username =\n'
1499 '\n'
1500 '[extensions]\n'
1501 '# uncomment these lines to enable some popular extensions\n'
1502 '# (see "hg help extensions" for more info)\n'
1503 '# pager =\n'
1504 '# progress =\n'
1505 '# color =\n')
1506 fp.close()
1507
1492 editor = ui.geteditor()
1508 editor = ui.geteditor()
1493 util.system("%s \"%s\"" % (editor, f),
1509 util.system("%s \"%s\"" % (editor, f),
1494 onerr=util.Abort, errprefix=_("edit failed"),
1510 onerr=util.Abort, errprefix=_("edit failed"),
1495 out=ui.fout)
1511 out=ui.fout)
1496 return
1512 return
1497
1513
1498 for f in scmutil.rcpath():
1514 for f in scmutil.rcpath():
1499 ui.debug('read config from: %s\n' % f)
1515 ui.debug('read config from: %s\n' % f)
1500 untrusted = bool(opts.get('untrusted'))
1516 untrusted = bool(opts.get('untrusted'))
1501 if values:
1517 if values:
1502 sections = [v for v in values if '.' not in v]
1518 sections = [v for v in values if '.' not in v]
1503 items = [v for v in values if '.' in v]
1519 items = [v for v in values if '.' in v]
1504 if len(items) > 1 or items and sections:
1520 if len(items) > 1 or items and sections:
1505 raise util.Abort(_('only one config item permitted'))
1521 raise util.Abort(_('only one config item permitted'))
1506 for section, name, value in ui.walkconfig(untrusted=untrusted):
1522 for section, name, value in ui.walkconfig(untrusted=untrusted):
1507 value = str(value).replace('\n', '\\n')
1523 value = str(value).replace('\n', '\\n')
1508 sectname = section + '.' + name
1524 sectname = section + '.' + name
1509 if values:
1525 if values:
1510 for v in values:
1526 for v in values:
1511 if v == section:
1527 if v == section:
1512 ui.debug('%s: ' %
1528 ui.debug('%s: ' %
1513 ui.configsource(section, name, untrusted))
1529 ui.configsource(section, name, untrusted))
1514 ui.write('%s=%s\n' % (sectname, value))
1530 ui.write('%s=%s\n' % (sectname, value))
1515 elif v == sectname:
1531 elif v == sectname:
1516 ui.debug('%s: ' %
1532 ui.debug('%s: ' %
1517 ui.configsource(section, name, untrusted))
1533 ui.configsource(section, name, untrusted))
1518 ui.write(value, '\n')
1534 ui.write(value, '\n')
1519 else:
1535 else:
1520 ui.debug('%s: ' %
1536 ui.debug('%s: ' %
1521 ui.configsource(section, name, untrusted))
1537 ui.configsource(section, name, untrusted))
1522 ui.write('%s=%s\n' % (sectname, value))
1538 ui.write('%s=%s\n' % (sectname, value))
1523
1539
1524 @command('copy|cp',
1540 @command('copy|cp',
1525 [('A', 'after', None, _('record a copy that has already occurred')),
1541 [('A', 'after', None, _('record a copy that has already occurred')),
1526 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1542 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1527 ] + walkopts + dryrunopts,
1543 ] + walkopts + dryrunopts,
1528 _('[OPTION]... [SOURCE]... DEST'))
1544 _('[OPTION]... [SOURCE]... DEST'))
1529 def copy(ui, repo, *pats, **opts):
1545 def copy(ui, repo, *pats, **opts):
1530 """mark files as copied for the next commit
1546 """mark files as copied for the next commit
1531
1547
1532 Mark dest as having copies of source files. If dest is a
1548 Mark dest as having copies of source files. If dest is a
1533 directory, copies are put in that directory. If dest is a file,
1549 directory, copies are put in that directory. If dest is a file,
1534 the source must be a single file.
1550 the source must be a single file.
1535
1551
1536 By default, this command copies the contents of files as they
1552 By default, this command copies the contents of files as they
1537 exist in the working directory. If invoked with -A/--after, the
1553 exist in the working directory. If invoked with -A/--after, the
1538 operation is recorded, but no copying is performed.
1554 operation is recorded, but no copying is performed.
1539
1555
1540 This command takes effect with the next commit. To undo a copy
1556 This command takes effect with the next commit. To undo a copy
1541 before that, see :hg:`revert`.
1557 before that, see :hg:`revert`.
1542
1558
1543 Returns 0 on success, 1 if errors are encountered.
1559 Returns 0 on success, 1 if errors are encountered.
1544 """
1560 """
1545 wlock = repo.wlock(False)
1561 wlock = repo.wlock(False)
1546 try:
1562 try:
1547 return cmdutil.copy(ui, repo, pats, opts)
1563 return cmdutil.copy(ui, repo, pats, opts)
1548 finally:
1564 finally:
1549 wlock.release()
1565 wlock.release()
1550
1566
1551 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1567 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1552 def debugancestor(ui, repo, *args):
1568 def debugancestor(ui, repo, *args):
1553 """find the ancestor revision of two revisions in a given index"""
1569 """find the ancestor revision of two revisions in a given index"""
1554 if len(args) == 3:
1570 if len(args) == 3:
1555 index, rev1, rev2 = args
1571 index, rev1, rev2 = args
1556 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1572 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1557 lookup = r.lookup
1573 lookup = r.lookup
1558 elif len(args) == 2:
1574 elif len(args) == 2:
1559 if not repo:
1575 if not repo:
1560 raise util.Abort(_("there is no Mercurial repository here "
1576 raise util.Abort(_("there is no Mercurial repository here "
1561 "(.hg not found)"))
1577 "(.hg not found)"))
1562 rev1, rev2 = args
1578 rev1, rev2 = args
1563 r = repo.changelog
1579 r = repo.changelog
1564 lookup = repo.lookup
1580 lookup = repo.lookup
1565 else:
1581 else:
1566 raise util.Abort(_('either two or three arguments required'))
1582 raise util.Abort(_('either two or three arguments required'))
1567 a = r.ancestor(lookup(rev1), lookup(rev2))
1583 a = r.ancestor(lookup(rev1), lookup(rev2))
1568 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1584 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1569
1585
1570 @command('debugbuilddag',
1586 @command('debugbuilddag',
1571 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1587 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1572 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1588 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1573 ('n', 'new-file', None, _('add new file at each rev'))],
1589 ('n', 'new-file', None, _('add new file at each rev'))],
1574 _('[OPTION]... [TEXT]'))
1590 _('[OPTION]... [TEXT]'))
1575 def debugbuilddag(ui, repo, text=None,
1591 def debugbuilddag(ui, repo, text=None,
1576 mergeable_file=False,
1592 mergeable_file=False,
1577 overwritten_file=False,
1593 overwritten_file=False,
1578 new_file=False):
1594 new_file=False):
1579 """builds a repo with a given DAG from scratch in the current empty repo
1595 """builds a repo with a given DAG from scratch in the current empty repo
1580
1596
1581 The description of the DAG is read from stdin if not given on the
1597 The description of the DAG is read from stdin if not given on the
1582 command line.
1598 command line.
1583
1599
1584 Elements:
1600 Elements:
1585
1601
1586 - "+n" is a linear run of n nodes based on the current default parent
1602 - "+n" is a linear run of n nodes based on the current default parent
1587 - "." is a single node based on the current default parent
1603 - "." is a single node based on the current default parent
1588 - "$" resets the default parent to null (implied at the start);
1604 - "$" resets the default parent to null (implied at the start);
1589 otherwise the default parent is always the last node created
1605 otherwise the default parent is always the last node created
1590 - "<p" sets the default parent to the backref p
1606 - "<p" sets the default parent to the backref p
1591 - "*p" is a fork at parent p, which is a backref
1607 - "*p" is a fork at parent p, which is a backref
1592 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1608 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1593 - "/p2" is a merge of the preceding node and p2
1609 - "/p2" is a merge of the preceding node and p2
1594 - ":tag" defines a local tag for the preceding node
1610 - ":tag" defines a local tag for the preceding node
1595 - "@branch" sets the named branch for subsequent nodes
1611 - "@branch" sets the named branch for subsequent nodes
1596 - "#...\\n" is a comment up to the end of the line
1612 - "#...\\n" is a comment up to the end of the line
1597
1613
1598 Whitespace between the above elements is ignored.
1614 Whitespace between the above elements is ignored.
1599
1615
1600 A backref is either
1616 A backref is either
1601
1617
1602 - a number n, which references the node curr-n, where curr is the current
1618 - a number n, which references the node curr-n, where curr is the current
1603 node, or
1619 node, or
1604 - the name of a local tag you placed earlier using ":tag", or
1620 - the name of a local tag you placed earlier using ":tag", or
1605 - empty to denote the default parent.
1621 - empty to denote the default parent.
1606
1622
1607 All string valued-elements are either strictly alphanumeric, or must
1623 All string valued-elements are either strictly alphanumeric, or must
1608 be enclosed in double quotes ("..."), with "\\" as escape character.
1624 be enclosed in double quotes ("..."), with "\\" as escape character.
1609 """
1625 """
1610
1626
1611 if text is None:
1627 if text is None:
1612 ui.status(_("reading DAG from stdin\n"))
1628 ui.status(_("reading DAG from stdin\n"))
1613 text = ui.fin.read()
1629 text = ui.fin.read()
1614
1630
1615 cl = repo.changelog
1631 cl = repo.changelog
1616 if len(cl) > 0:
1632 if len(cl) > 0:
1617 raise util.Abort(_('repository is not empty'))
1633 raise util.Abort(_('repository is not empty'))
1618
1634
1619 # determine number of revs in DAG
1635 # determine number of revs in DAG
1620 total = 0
1636 total = 0
1621 for type, data in dagparser.parsedag(text):
1637 for type, data in dagparser.parsedag(text):
1622 if type == 'n':
1638 if type == 'n':
1623 total += 1
1639 total += 1
1624
1640
1625 if mergeable_file:
1641 if mergeable_file:
1626 linesperrev = 2
1642 linesperrev = 2
1627 # make a file with k lines per rev
1643 # make a file with k lines per rev
1628 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1644 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1629 initialmergedlines.append("")
1645 initialmergedlines.append("")
1630
1646
1631 tags = []
1647 tags = []
1632
1648
1633 lock = tr = None
1649 lock = tr = None
1634 try:
1650 try:
1635 lock = repo.lock()
1651 lock = repo.lock()
1636 tr = repo.transaction("builddag")
1652 tr = repo.transaction("builddag")
1637
1653
1638 at = -1
1654 at = -1
1639 atbranch = 'default'
1655 atbranch = 'default'
1640 nodeids = []
1656 nodeids = []
1641 id = 0
1657 id = 0
1642 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1658 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1643 for type, data in dagparser.parsedag(text):
1659 for type, data in dagparser.parsedag(text):
1644 if type == 'n':
1660 if type == 'n':
1645 ui.note(('node %s\n' % str(data)))
1661 ui.note(('node %s\n' % str(data)))
1646 id, ps = data
1662 id, ps = data
1647
1663
1648 files = []
1664 files = []
1649 fctxs = {}
1665 fctxs = {}
1650
1666
1651 p2 = None
1667 p2 = None
1652 if mergeable_file:
1668 if mergeable_file:
1653 fn = "mf"
1669 fn = "mf"
1654 p1 = repo[ps[0]]
1670 p1 = repo[ps[0]]
1655 if len(ps) > 1:
1671 if len(ps) > 1:
1656 p2 = repo[ps[1]]
1672 p2 = repo[ps[1]]
1657 pa = p1.ancestor(p2)
1673 pa = p1.ancestor(p2)
1658 base, local, other = [x[fn].data() for x in (pa, p1,
1674 base, local, other = [x[fn].data() for x in (pa, p1,
1659 p2)]
1675 p2)]
1660 m3 = simplemerge.Merge3Text(base, local, other)
1676 m3 = simplemerge.Merge3Text(base, local, other)
1661 ml = [l.strip() for l in m3.merge_lines()]
1677 ml = [l.strip() for l in m3.merge_lines()]
1662 ml.append("")
1678 ml.append("")
1663 elif at > 0:
1679 elif at > 0:
1664 ml = p1[fn].data().split("\n")
1680 ml = p1[fn].data().split("\n")
1665 else:
1681 else:
1666 ml = initialmergedlines
1682 ml = initialmergedlines
1667 ml[id * linesperrev] += " r%i" % id
1683 ml[id * linesperrev] += " r%i" % id
1668 mergedtext = "\n".join(ml)
1684 mergedtext = "\n".join(ml)
1669 files.append(fn)
1685 files.append(fn)
1670 fctxs[fn] = context.memfilectx(fn, mergedtext)
1686 fctxs[fn] = context.memfilectx(fn, mergedtext)
1671
1687
1672 if overwritten_file:
1688 if overwritten_file:
1673 fn = "of"
1689 fn = "of"
1674 files.append(fn)
1690 files.append(fn)
1675 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1691 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1676
1692
1677 if new_file:
1693 if new_file:
1678 fn = "nf%i" % id
1694 fn = "nf%i" % id
1679 files.append(fn)
1695 files.append(fn)
1680 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1696 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1681 if len(ps) > 1:
1697 if len(ps) > 1:
1682 if not p2:
1698 if not p2:
1683 p2 = repo[ps[1]]
1699 p2 = repo[ps[1]]
1684 for fn in p2:
1700 for fn in p2:
1685 if fn.startswith("nf"):
1701 if fn.startswith("nf"):
1686 files.append(fn)
1702 files.append(fn)
1687 fctxs[fn] = p2[fn]
1703 fctxs[fn] = p2[fn]
1688
1704
1689 def fctxfn(repo, cx, path):
1705 def fctxfn(repo, cx, path):
1690 return fctxs.get(path)
1706 return fctxs.get(path)
1691
1707
1692 if len(ps) == 0 or ps[0] < 0:
1708 if len(ps) == 0 or ps[0] < 0:
1693 pars = [None, None]
1709 pars = [None, None]
1694 elif len(ps) == 1:
1710 elif len(ps) == 1:
1695 pars = [nodeids[ps[0]], None]
1711 pars = [nodeids[ps[0]], None]
1696 else:
1712 else:
1697 pars = [nodeids[p] for p in ps]
1713 pars = [nodeids[p] for p in ps]
1698 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1714 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1699 date=(id, 0),
1715 date=(id, 0),
1700 user="debugbuilddag",
1716 user="debugbuilddag",
1701 extra={'branch': atbranch})
1717 extra={'branch': atbranch})
1702 nodeid = repo.commitctx(cx)
1718 nodeid = repo.commitctx(cx)
1703 nodeids.append(nodeid)
1719 nodeids.append(nodeid)
1704 at = id
1720 at = id
1705 elif type == 'l':
1721 elif type == 'l':
1706 id, name = data
1722 id, name = data
1707 ui.note(('tag %s\n' % name))
1723 ui.note(('tag %s\n' % name))
1708 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1724 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1709 elif type == 'a':
1725 elif type == 'a':
1710 ui.note(('branch %s\n' % data))
1726 ui.note(('branch %s\n' % data))
1711 atbranch = data
1727 atbranch = data
1712 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1728 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1713 tr.close()
1729 tr.close()
1714
1730
1715 if tags:
1731 if tags:
1716 repo.opener.write("localtags", "".join(tags))
1732 repo.opener.write("localtags", "".join(tags))
1717 finally:
1733 finally:
1718 ui.progress(_('building'), None)
1734 ui.progress(_('building'), None)
1719 release(tr, lock)
1735 release(tr, lock)
1720
1736
1721 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1737 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1722 def debugbundle(ui, bundlepath, all=None, **opts):
1738 def debugbundle(ui, bundlepath, all=None, **opts):
1723 """lists the contents of a bundle"""
1739 """lists the contents of a bundle"""
1724 f = hg.openpath(ui, bundlepath)
1740 f = hg.openpath(ui, bundlepath)
1725 try:
1741 try:
1726 gen = changegroup.readbundle(f, bundlepath)
1742 gen = changegroup.readbundle(f, bundlepath)
1727 if all:
1743 if all:
1728 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1744 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1729
1745
1730 def showchunks(named):
1746 def showchunks(named):
1731 ui.write("\n%s\n" % named)
1747 ui.write("\n%s\n" % named)
1732 chain = None
1748 chain = None
1733 while True:
1749 while True:
1734 chunkdata = gen.deltachunk(chain)
1750 chunkdata = gen.deltachunk(chain)
1735 if not chunkdata:
1751 if not chunkdata:
1736 break
1752 break
1737 node = chunkdata['node']
1753 node = chunkdata['node']
1738 p1 = chunkdata['p1']
1754 p1 = chunkdata['p1']
1739 p2 = chunkdata['p2']
1755 p2 = chunkdata['p2']
1740 cs = chunkdata['cs']
1756 cs = chunkdata['cs']
1741 deltabase = chunkdata['deltabase']
1757 deltabase = chunkdata['deltabase']
1742 delta = chunkdata['delta']
1758 delta = chunkdata['delta']
1743 ui.write("%s %s %s %s %s %s\n" %
1759 ui.write("%s %s %s %s %s %s\n" %
1744 (hex(node), hex(p1), hex(p2),
1760 (hex(node), hex(p1), hex(p2),
1745 hex(cs), hex(deltabase), len(delta)))
1761 hex(cs), hex(deltabase), len(delta)))
1746 chain = node
1762 chain = node
1747
1763
1748 chunkdata = gen.changelogheader()
1764 chunkdata = gen.changelogheader()
1749 showchunks("changelog")
1765 showchunks("changelog")
1750 chunkdata = gen.manifestheader()
1766 chunkdata = gen.manifestheader()
1751 showchunks("manifest")
1767 showchunks("manifest")
1752 while True:
1768 while True:
1753 chunkdata = gen.filelogheader()
1769 chunkdata = gen.filelogheader()
1754 if not chunkdata:
1770 if not chunkdata:
1755 break
1771 break
1756 fname = chunkdata['filename']
1772 fname = chunkdata['filename']
1757 showchunks(fname)
1773 showchunks(fname)
1758 else:
1774 else:
1759 chunkdata = gen.changelogheader()
1775 chunkdata = gen.changelogheader()
1760 chain = None
1776 chain = None
1761 while True:
1777 while True:
1762 chunkdata = gen.deltachunk(chain)
1778 chunkdata = gen.deltachunk(chain)
1763 if not chunkdata:
1779 if not chunkdata:
1764 break
1780 break
1765 node = chunkdata['node']
1781 node = chunkdata['node']
1766 ui.write("%s\n" % hex(node))
1782 ui.write("%s\n" % hex(node))
1767 chain = node
1783 chain = node
1768 finally:
1784 finally:
1769 f.close()
1785 f.close()
1770
1786
1771 @command('debugcheckstate', [], '')
1787 @command('debugcheckstate', [], '')
1772 def debugcheckstate(ui, repo):
1788 def debugcheckstate(ui, repo):
1773 """validate the correctness of the current dirstate"""
1789 """validate the correctness of the current dirstate"""
1774 parent1, parent2 = repo.dirstate.parents()
1790 parent1, parent2 = repo.dirstate.parents()
1775 m1 = repo[parent1].manifest()
1791 m1 = repo[parent1].manifest()
1776 m2 = repo[parent2].manifest()
1792 m2 = repo[parent2].manifest()
1777 errors = 0
1793 errors = 0
1778 for f in repo.dirstate:
1794 for f in repo.dirstate:
1779 state = repo.dirstate[f]
1795 state = repo.dirstate[f]
1780 if state in "nr" and f not in m1:
1796 if state in "nr" and f not in m1:
1781 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1797 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1782 errors += 1
1798 errors += 1
1783 if state in "a" and f in m1:
1799 if state in "a" and f in m1:
1784 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1800 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1785 errors += 1
1801 errors += 1
1786 if state in "m" and f not in m1 and f not in m2:
1802 if state in "m" and f not in m1 and f not in m2:
1787 ui.warn(_("%s in state %s, but not in either manifest\n") %
1803 ui.warn(_("%s in state %s, but not in either manifest\n") %
1788 (f, state))
1804 (f, state))
1789 errors += 1
1805 errors += 1
1790 for f in m1:
1806 for f in m1:
1791 state = repo.dirstate[f]
1807 state = repo.dirstate[f]
1792 if state not in "nrm":
1808 if state not in "nrm":
1793 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1809 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1794 errors += 1
1810 errors += 1
1795 if errors:
1811 if errors:
1796 error = _(".hg/dirstate inconsistent with current parent's manifest")
1812 error = _(".hg/dirstate inconsistent with current parent's manifest")
1797 raise util.Abort(error)
1813 raise util.Abort(error)
1798
1814
1799 @command('debugcommands', [], _('[COMMAND]'))
1815 @command('debugcommands', [], _('[COMMAND]'))
1800 def debugcommands(ui, cmd='', *args):
1816 def debugcommands(ui, cmd='', *args):
1801 """list all available commands and options"""
1817 """list all available commands and options"""
1802 for cmd, vals in sorted(table.iteritems()):
1818 for cmd, vals in sorted(table.iteritems()):
1803 cmd = cmd.split('|')[0].strip('^')
1819 cmd = cmd.split('|')[0].strip('^')
1804 opts = ', '.join([i[1] for i in vals[1]])
1820 opts = ', '.join([i[1] for i in vals[1]])
1805 ui.write('%s: %s\n' % (cmd, opts))
1821 ui.write('%s: %s\n' % (cmd, opts))
1806
1822
1807 @command('debugcomplete',
1823 @command('debugcomplete',
1808 [('o', 'options', None, _('show the command options'))],
1824 [('o', 'options', None, _('show the command options'))],
1809 _('[-o] CMD'))
1825 _('[-o] CMD'))
1810 def debugcomplete(ui, cmd='', **opts):
1826 def debugcomplete(ui, cmd='', **opts):
1811 """returns the completion list associated with the given command"""
1827 """returns the completion list associated with the given command"""
1812
1828
1813 if opts.get('options'):
1829 if opts.get('options'):
1814 options = []
1830 options = []
1815 otables = [globalopts]
1831 otables = [globalopts]
1816 if cmd:
1832 if cmd:
1817 aliases, entry = cmdutil.findcmd(cmd, table, False)
1833 aliases, entry = cmdutil.findcmd(cmd, table, False)
1818 otables.append(entry[1])
1834 otables.append(entry[1])
1819 for t in otables:
1835 for t in otables:
1820 for o in t:
1836 for o in t:
1821 if "(DEPRECATED)" in o[3]:
1837 if "(DEPRECATED)" in o[3]:
1822 continue
1838 continue
1823 if o[0]:
1839 if o[0]:
1824 options.append('-%s' % o[0])
1840 options.append('-%s' % o[0])
1825 options.append('--%s' % o[1])
1841 options.append('--%s' % o[1])
1826 ui.write("%s\n" % "\n".join(options))
1842 ui.write("%s\n" % "\n".join(options))
1827 return
1843 return
1828
1844
1829 cmdlist = cmdutil.findpossible(cmd, table)
1845 cmdlist = cmdutil.findpossible(cmd, table)
1830 if ui.verbose:
1846 if ui.verbose:
1831 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1847 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1832 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1848 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1833
1849
1834 @command('debugdag',
1850 @command('debugdag',
1835 [('t', 'tags', None, _('use tags as labels')),
1851 [('t', 'tags', None, _('use tags as labels')),
1836 ('b', 'branches', None, _('annotate with branch names')),
1852 ('b', 'branches', None, _('annotate with branch names')),
1837 ('', 'dots', None, _('use dots for runs')),
1853 ('', 'dots', None, _('use dots for runs')),
1838 ('s', 'spaces', None, _('separate elements by spaces'))],
1854 ('s', 'spaces', None, _('separate elements by spaces'))],
1839 _('[OPTION]... [FILE [REV]...]'))
1855 _('[OPTION]... [FILE [REV]...]'))
1840 def debugdag(ui, repo, file_=None, *revs, **opts):
1856 def debugdag(ui, repo, file_=None, *revs, **opts):
1841 """format the changelog or an index DAG as a concise textual description
1857 """format the changelog or an index DAG as a concise textual description
1842
1858
1843 If you pass a revlog index, the revlog's DAG is emitted. If you list
1859 If you pass a revlog index, the revlog's DAG is emitted. If you list
1844 revision numbers, they get labeled in the output as rN.
1860 revision numbers, they get labeled in the output as rN.
1845
1861
1846 Otherwise, the changelog DAG of the current repo is emitted.
1862 Otherwise, the changelog DAG of the current repo is emitted.
1847 """
1863 """
1848 spaces = opts.get('spaces')
1864 spaces = opts.get('spaces')
1849 dots = opts.get('dots')
1865 dots = opts.get('dots')
1850 if file_:
1866 if file_:
1851 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1867 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1852 revs = set((int(r) for r in revs))
1868 revs = set((int(r) for r in revs))
1853 def events():
1869 def events():
1854 for r in rlog:
1870 for r in rlog:
1855 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1871 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1856 if p != -1)))
1872 if p != -1)))
1857 if r in revs:
1873 if r in revs:
1858 yield 'l', (r, "r%i" % r)
1874 yield 'l', (r, "r%i" % r)
1859 elif repo:
1875 elif repo:
1860 cl = repo.changelog
1876 cl = repo.changelog
1861 tags = opts.get('tags')
1877 tags = opts.get('tags')
1862 branches = opts.get('branches')
1878 branches = opts.get('branches')
1863 if tags:
1879 if tags:
1864 labels = {}
1880 labels = {}
1865 for l, n in repo.tags().items():
1881 for l, n in repo.tags().items():
1866 labels.setdefault(cl.rev(n), []).append(l)
1882 labels.setdefault(cl.rev(n), []).append(l)
1867 def events():
1883 def events():
1868 b = "default"
1884 b = "default"
1869 for r in cl:
1885 for r in cl:
1870 if branches:
1886 if branches:
1871 newb = cl.read(cl.node(r))[5]['branch']
1887 newb = cl.read(cl.node(r))[5]['branch']
1872 if newb != b:
1888 if newb != b:
1873 yield 'a', newb
1889 yield 'a', newb
1874 b = newb
1890 b = newb
1875 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1891 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1876 if p != -1)))
1892 if p != -1)))
1877 if tags:
1893 if tags:
1878 ls = labels.get(r)
1894 ls = labels.get(r)
1879 if ls:
1895 if ls:
1880 for l in ls:
1896 for l in ls:
1881 yield 'l', (r, l)
1897 yield 'l', (r, l)
1882 else:
1898 else:
1883 raise util.Abort(_('need repo for changelog dag'))
1899 raise util.Abort(_('need repo for changelog dag'))
1884
1900
1885 for line in dagparser.dagtextlines(events(),
1901 for line in dagparser.dagtextlines(events(),
1886 addspaces=spaces,
1902 addspaces=spaces,
1887 wraplabels=True,
1903 wraplabels=True,
1888 wrapannotations=True,
1904 wrapannotations=True,
1889 wrapnonlinear=dots,
1905 wrapnonlinear=dots,
1890 usedots=dots,
1906 usedots=dots,
1891 maxlinewidth=70):
1907 maxlinewidth=70):
1892 ui.write(line)
1908 ui.write(line)
1893 ui.write("\n")
1909 ui.write("\n")
1894
1910
1895 @command('debugdata',
1911 @command('debugdata',
1896 [('c', 'changelog', False, _('open changelog')),
1912 [('c', 'changelog', False, _('open changelog')),
1897 ('m', 'manifest', False, _('open manifest'))],
1913 ('m', 'manifest', False, _('open manifest'))],
1898 _('-c|-m|FILE REV'))
1914 _('-c|-m|FILE REV'))
1899 def debugdata(ui, repo, file_, rev=None, **opts):
1915 def debugdata(ui, repo, file_, rev=None, **opts):
1900 """dump the contents of a data file revision"""
1916 """dump the contents of a data file revision"""
1901 if opts.get('changelog') or opts.get('manifest'):
1917 if opts.get('changelog') or opts.get('manifest'):
1902 file_, rev = None, file_
1918 file_, rev = None, file_
1903 elif rev is None:
1919 elif rev is None:
1904 raise error.CommandError('debugdata', _('invalid arguments'))
1920 raise error.CommandError('debugdata', _('invalid arguments'))
1905 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1921 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1906 try:
1922 try:
1907 ui.write(r.revision(r.lookup(rev)))
1923 ui.write(r.revision(r.lookup(rev)))
1908 except KeyError:
1924 except KeyError:
1909 raise util.Abort(_('invalid revision identifier %s') % rev)
1925 raise util.Abort(_('invalid revision identifier %s') % rev)
1910
1926
1911 @command('debugdate',
1927 @command('debugdate',
1912 [('e', 'extended', None, _('try extended date formats'))],
1928 [('e', 'extended', None, _('try extended date formats'))],
1913 _('[-e] DATE [RANGE]'))
1929 _('[-e] DATE [RANGE]'))
1914 def debugdate(ui, date, range=None, **opts):
1930 def debugdate(ui, date, range=None, **opts):
1915 """parse and display a date"""
1931 """parse and display a date"""
1916 if opts["extended"]:
1932 if opts["extended"]:
1917 d = util.parsedate(date, util.extendeddateformats)
1933 d = util.parsedate(date, util.extendeddateformats)
1918 else:
1934 else:
1919 d = util.parsedate(date)
1935 d = util.parsedate(date)
1920 ui.write(("internal: %s %s\n") % d)
1936 ui.write(("internal: %s %s\n") % d)
1921 ui.write(("standard: %s\n") % util.datestr(d))
1937 ui.write(("standard: %s\n") % util.datestr(d))
1922 if range:
1938 if range:
1923 m = util.matchdate(range)
1939 m = util.matchdate(range)
1924 ui.write(("match: %s\n") % m(d[0]))
1940 ui.write(("match: %s\n") % m(d[0]))
1925
1941
1926 @command('debugdiscovery',
1942 @command('debugdiscovery',
1927 [('', 'old', None, _('use old-style discovery')),
1943 [('', 'old', None, _('use old-style discovery')),
1928 ('', 'nonheads', None,
1944 ('', 'nonheads', None,
1929 _('use old-style discovery with non-heads included')),
1945 _('use old-style discovery with non-heads included')),
1930 ] + remoteopts,
1946 ] + remoteopts,
1931 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1947 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1932 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1948 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1933 """runs the changeset discovery protocol in isolation"""
1949 """runs the changeset discovery protocol in isolation"""
1934 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1950 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1935 opts.get('branch'))
1951 opts.get('branch'))
1936 remote = hg.peer(repo, opts, remoteurl)
1952 remote = hg.peer(repo, opts, remoteurl)
1937 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1953 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1938
1954
1939 # make sure tests are repeatable
1955 # make sure tests are repeatable
1940 random.seed(12323)
1956 random.seed(12323)
1941
1957
1942 def doit(localheads, remoteheads, remote=remote):
1958 def doit(localheads, remoteheads, remote=remote):
1943 if opts.get('old'):
1959 if opts.get('old'):
1944 if localheads:
1960 if localheads:
1945 raise util.Abort('cannot use localheads with old style '
1961 raise util.Abort('cannot use localheads with old style '
1946 'discovery')
1962 'discovery')
1947 if not util.safehasattr(remote, 'branches'):
1963 if not util.safehasattr(remote, 'branches'):
1948 # enable in-client legacy support
1964 # enable in-client legacy support
1949 remote = localrepo.locallegacypeer(remote.local())
1965 remote = localrepo.locallegacypeer(remote.local())
1950 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1966 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1951 force=True)
1967 force=True)
1952 common = set(common)
1968 common = set(common)
1953 if not opts.get('nonheads'):
1969 if not opts.get('nonheads'):
1954 ui.write(("unpruned common: %s\n") %
1970 ui.write(("unpruned common: %s\n") %
1955 " ".join(sorted(short(n) for n in common)))
1971 " ".join(sorted(short(n) for n in common)))
1956 dag = dagutil.revlogdag(repo.changelog)
1972 dag = dagutil.revlogdag(repo.changelog)
1957 all = dag.ancestorset(dag.internalizeall(common))
1973 all = dag.ancestorset(dag.internalizeall(common))
1958 common = dag.externalizeall(dag.headsetofconnecteds(all))
1974 common = dag.externalizeall(dag.headsetofconnecteds(all))
1959 else:
1975 else:
1960 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1976 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1961 common = set(common)
1977 common = set(common)
1962 rheads = set(hds)
1978 rheads = set(hds)
1963 lheads = set(repo.heads())
1979 lheads = set(repo.heads())
1964 ui.write(("common heads: %s\n") %
1980 ui.write(("common heads: %s\n") %
1965 " ".join(sorted(short(n) for n in common)))
1981 " ".join(sorted(short(n) for n in common)))
1966 if lheads <= common:
1982 if lheads <= common:
1967 ui.write(("local is subset\n"))
1983 ui.write(("local is subset\n"))
1968 elif rheads <= common:
1984 elif rheads <= common:
1969 ui.write(("remote is subset\n"))
1985 ui.write(("remote is subset\n"))
1970
1986
1971 serverlogs = opts.get('serverlog')
1987 serverlogs = opts.get('serverlog')
1972 if serverlogs:
1988 if serverlogs:
1973 for filename in serverlogs:
1989 for filename in serverlogs:
1974 logfile = open(filename, 'r')
1990 logfile = open(filename, 'r')
1975 try:
1991 try:
1976 line = logfile.readline()
1992 line = logfile.readline()
1977 while line:
1993 while line:
1978 parts = line.strip().split(';')
1994 parts = line.strip().split(';')
1979 op = parts[1]
1995 op = parts[1]
1980 if op == 'cg':
1996 if op == 'cg':
1981 pass
1997 pass
1982 elif op == 'cgss':
1998 elif op == 'cgss':
1983 doit(parts[2].split(' '), parts[3].split(' '))
1999 doit(parts[2].split(' '), parts[3].split(' '))
1984 elif op == 'unb':
2000 elif op == 'unb':
1985 doit(parts[3].split(' '), parts[2].split(' '))
2001 doit(parts[3].split(' '), parts[2].split(' '))
1986 line = logfile.readline()
2002 line = logfile.readline()
1987 finally:
2003 finally:
1988 logfile.close()
2004 logfile.close()
1989
2005
1990 else:
2006 else:
1991 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2007 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1992 opts.get('remote_head'))
2008 opts.get('remote_head'))
1993 localrevs = opts.get('local_head')
2009 localrevs = opts.get('local_head')
1994 doit(localrevs, remoterevs)
2010 doit(localrevs, remoterevs)
1995
2011
1996 @command('debugfileset',
2012 @command('debugfileset',
1997 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2013 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1998 _('[-r REV] FILESPEC'))
2014 _('[-r REV] FILESPEC'))
1999 def debugfileset(ui, repo, expr, **opts):
2015 def debugfileset(ui, repo, expr, **opts):
2000 '''parse and apply a fileset specification'''
2016 '''parse and apply a fileset specification'''
2001 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2017 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2002 if ui.verbose:
2018 if ui.verbose:
2003 tree = fileset.parse(expr)[0]
2019 tree = fileset.parse(expr)[0]
2004 ui.note(tree, "\n")
2020 ui.note(tree, "\n")
2005
2021
2006 for f in ctx.getfileset(expr):
2022 for f in ctx.getfileset(expr):
2007 ui.write("%s\n" % f)
2023 ui.write("%s\n" % f)
2008
2024
2009 @command('debugfsinfo', [], _('[PATH]'))
2025 @command('debugfsinfo', [], _('[PATH]'))
2010 def debugfsinfo(ui, path="."):
2026 def debugfsinfo(ui, path="."):
2011 """show information detected about current filesystem"""
2027 """show information detected about current filesystem"""
2012 util.writefile('.debugfsinfo', '')
2028 util.writefile('.debugfsinfo', '')
2013 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2029 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2014 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2030 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2015 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2031 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2016 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2032 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2017 and 'yes' or 'no'))
2033 and 'yes' or 'no'))
2018 os.unlink('.debugfsinfo')
2034 os.unlink('.debugfsinfo')
2019
2035
2020 @command('debuggetbundle',
2036 @command('debuggetbundle',
2021 [('H', 'head', [], _('id of head node'), _('ID')),
2037 [('H', 'head', [], _('id of head node'), _('ID')),
2022 ('C', 'common', [], _('id of common node'), _('ID')),
2038 ('C', 'common', [], _('id of common node'), _('ID')),
2023 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2039 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2024 _('REPO FILE [-H|-C ID]...'))
2040 _('REPO FILE [-H|-C ID]...'))
2025 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2041 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2026 """retrieves a bundle from a repo
2042 """retrieves a bundle from a repo
2027
2043
2028 Every ID must be a full-length hex node id string. Saves the bundle to the
2044 Every ID must be a full-length hex node id string. Saves the bundle to the
2029 given file.
2045 given file.
2030 """
2046 """
2031 repo = hg.peer(ui, opts, repopath)
2047 repo = hg.peer(ui, opts, repopath)
2032 if not repo.capable('getbundle'):
2048 if not repo.capable('getbundle'):
2033 raise util.Abort("getbundle() not supported by target repository")
2049 raise util.Abort("getbundle() not supported by target repository")
2034 args = {}
2050 args = {}
2035 if common:
2051 if common:
2036 args['common'] = [bin(s) for s in common]
2052 args['common'] = [bin(s) for s in common]
2037 if head:
2053 if head:
2038 args['heads'] = [bin(s) for s in head]
2054 args['heads'] = [bin(s) for s in head]
2039 # TODO: get desired bundlecaps from command line.
2055 # TODO: get desired bundlecaps from command line.
2040 args['bundlecaps'] = None
2056 args['bundlecaps'] = None
2041 bundle = repo.getbundle('debug', **args)
2057 bundle = repo.getbundle('debug', **args)
2042
2058
2043 bundletype = opts.get('type', 'bzip2').lower()
2059 bundletype = opts.get('type', 'bzip2').lower()
2044 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2060 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2045 bundletype = btypes.get(bundletype)
2061 bundletype = btypes.get(bundletype)
2046 if bundletype not in changegroup.bundletypes:
2062 if bundletype not in changegroup.bundletypes:
2047 raise util.Abort(_('unknown bundle type specified with --type'))
2063 raise util.Abort(_('unknown bundle type specified with --type'))
2048 changegroup.writebundle(bundle, bundlepath, bundletype)
2064 changegroup.writebundle(bundle, bundlepath, bundletype)
2049
2065
2050 @command('debugignore', [], '')
2066 @command('debugignore', [], '')
2051 def debugignore(ui, repo, *values, **opts):
2067 def debugignore(ui, repo, *values, **opts):
2052 """display the combined ignore pattern"""
2068 """display the combined ignore pattern"""
2053 ignore = repo.dirstate._ignore
2069 ignore = repo.dirstate._ignore
2054 includepat = getattr(ignore, 'includepat', None)
2070 includepat = getattr(ignore, 'includepat', None)
2055 if includepat is not None:
2071 if includepat is not None:
2056 ui.write("%s\n" % includepat)
2072 ui.write("%s\n" % includepat)
2057 else:
2073 else:
2058 raise util.Abort(_("no ignore patterns found"))
2074 raise util.Abort(_("no ignore patterns found"))
2059
2075
2060 @command('debugindex',
2076 @command('debugindex',
2061 [('c', 'changelog', False, _('open changelog')),
2077 [('c', 'changelog', False, _('open changelog')),
2062 ('m', 'manifest', False, _('open manifest')),
2078 ('m', 'manifest', False, _('open manifest')),
2063 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2079 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2064 _('[-f FORMAT] -c|-m|FILE'))
2080 _('[-f FORMAT] -c|-m|FILE'))
2065 def debugindex(ui, repo, file_=None, **opts):
2081 def debugindex(ui, repo, file_=None, **opts):
2066 """dump the contents of an index file"""
2082 """dump the contents of an index file"""
2067 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2083 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2068 format = opts.get('format', 0)
2084 format = opts.get('format', 0)
2069 if format not in (0, 1):
2085 if format not in (0, 1):
2070 raise util.Abort(_("unknown format %d") % format)
2086 raise util.Abort(_("unknown format %d") % format)
2071
2087
2072 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2088 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2073 if generaldelta:
2089 if generaldelta:
2074 basehdr = ' delta'
2090 basehdr = ' delta'
2075 else:
2091 else:
2076 basehdr = ' base'
2092 basehdr = ' base'
2077
2093
2078 if format == 0:
2094 if format == 0:
2079 ui.write(" rev offset length " + basehdr + " linkrev"
2095 ui.write(" rev offset length " + basehdr + " linkrev"
2080 " nodeid p1 p2\n")
2096 " nodeid p1 p2\n")
2081 elif format == 1:
2097 elif format == 1:
2082 ui.write(" rev flag offset length"
2098 ui.write(" rev flag offset length"
2083 " size " + basehdr + " link p1 p2"
2099 " size " + basehdr + " link p1 p2"
2084 " nodeid\n")
2100 " nodeid\n")
2085
2101
2086 for i in r:
2102 for i in r:
2087 node = r.node(i)
2103 node = r.node(i)
2088 if generaldelta:
2104 if generaldelta:
2089 base = r.deltaparent(i)
2105 base = r.deltaparent(i)
2090 else:
2106 else:
2091 base = r.chainbase(i)
2107 base = r.chainbase(i)
2092 if format == 0:
2108 if format == 0:
2093 try:
2109 try:
2094 pp = r.parents(node)
2110 pp = r.parents(node)
2095 except Exception:
2111 except Exception:
2096 pp = [nullid, nullid]
2112 pp = [nullid, nullid]
2097 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2113 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2098 i, r.start(i), r.length(i), base, r.linkrev(i),
2114 i, r.start(i), r.length(i), base, r.linkrev(i),
2099 short(node), short(pp[0]), short(pp[1])))
2115 short(node), short(pp[0]), short(pp[1])))
2100 elif format == 1:
2116 elif format == 1:
2101 pr = r.parentrevs(i)
2117 pr = r.parentrevs(i)
2102 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2118 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2103 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2119 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2104 base, r.linkrev(i), pr[0], pr[1], short(node)))
2120 base, r.linkrev(i), pr[0], pr[1], short(node)))
2105
2121
2106 @command('debugindexdot', [], _('FILE'))
2122 @command('debugindexdot', [], _('FILE'))
2107 def debugindexdot(ui, repo, file_):
2123 def debugindexdot(ui, repo, file_):
2108 """dump an index DAG as a graphviz dot file"""
2124 """dump an index DAG as a graphviz dot file"""
2109 r = None
2125 r = None
2110 if repo:
2126 if repo:
2111 filelog = repo.file(file_)
2127 filelog = repo.file(file_)
2112 if len(filelog):
2128 if len(filelog):
2113 r = filelog
2129 r = filelog
2114 if not r:
2130 if not r:
2115 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2131 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2116 ui.write(("digraph G {\n"))
2132 ui.write(("digraph G {\n"))
2117 for i in r:
2133 for i in r:
2118 node = r.node(i)
2134 node = r.node(i)
2119 pp = r.parents(node)
2135 pp = r.parents(node)
2120 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2136 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2121 if pp[1] != nullid:
2137 if pp[1] != nullid:
2122 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2138 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2123 ui.write("}\n")
2139 ui.write("}\n")
2124
2140
2125 @command('debuginstall', [], '')
2141 @command('debuginstall', [], '')
2126 def debuginstall(ui):
2142 def debuginstall(ui):
2127 '''test Mercurial installation
2143 '''test Mercurial installation
2128
2144
2129 Returns 0 on success.
2145 Returns 0 on success.
2130 '''
2146 '''
2131
2147
2132 def writetemp(contents):
2148 def writetemp(contents):
2133 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2149 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2134 f = os.fdopen(fd, "wb")
2150 f = os.fdopen(fd, "wb")
2135 f.write(contents)
2151 f.write(contents)
2136 f.close()
2152 f.close()
2137 return name
2153 return name
2138
2154
2139 problems = 0
2155 problems = 0
2140
2156
2141 # encoding
2157 # encoding
2142 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2158 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2143 try:
2159 try:
2144 encoding.fromlocal("test")
2160 encoding.fromlocal("test")
2145 except util.Abort, inst:
2161 except util.Abort, inst:
2146 ui.write(" %s\n" % inst)
2162 ui.write(" %s\n" % inst)
2147 ui.write(_(" (check that your locale is properly set)\n"))
2163 ui.write(_(" (check that your locale is properly set)\n"))
2148 problems += 1
2164 problems += 1
2149
2165
2150 # Python lib
2166 # Python lib
2151 ui.status(_("checking Python lib (%s)...\n")
2167 ui.status(_("checking Python lib (%s)...\n")
2152 % os.path.dirname(os.__file__))
2168 % os.path.dirname(os.__file__))
2153
2169
2154 # compiled modules
2170 # compiled modules
2155 ui.status(_("checking installed modules (%s)...\n")
2171 ui.status(_("checking installed modules (%s)...\n")
2156 % os.path.dirname(__file__))
2172 % os.path.dirname(__file__))
2157 try:
2173 try:
2158 import bdiff, mpatch, base85, osutil
2174 import bdiff, mpatch, base85, osutil
2159 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2175 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2160 except Exception, inst:
2176 except Exception, inst:
2161 ui.write(" %s\n" % inst)
2177 ui.write(" %s\n" % inst)
2162 ui.write(_(" One or more extensions could not be found"))
2178 ui.write(_(" One or more extensions could not be found"))
2163 ui.write(_(" (check that you compiled the extensions)\n"))
2179 ui.write(_(" (check that you compiled the extensions)\n"))
2164 problems += 1
2180 problems += 1
2165
2181
2166 # templates
2182 # templates
2167 import templater
2183 import templater
2168 p = templater.templatepath()
2184 p = templater.templatepath()
2169 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2185 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2170 if p:
2186 if p:
2171 m = templater.templatepath("map-cmdline.default")
2187 m = templater.templatepath("map-cmdline.default")
2172 if m:
2188 if m:
2173 # template found, check if it is working
2189 # template found, check if it is working
2174 try:
2190 try:
2175 templater.templater(m)
2191 templater.templater(m)
2176 except Exception, inst:
2192 except Exception, inst:
2177 ui.write(" %s\n" % inst)
2193 ui.write(" %s\n" % inst)
2178 p = None
2194 p = None
2179 else:
2195 else:
2180 ui.write(_(" template 'default' not found\n"))
2196 ui.write(_(" template 'default' not found\n"))
2181 p = None
2197 p = None
2182 else:
2198 else:
2183 ui.write(_(" no template directories found\n"))
2199 ui.write(_(" no template directories found\n"))
2184 if not p:
2200 if not p:
2185 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2201 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2186 problems += 1
2202 problems += 1
2187
2203
2188 # editor
2204 # editor
2189 ui.status(_("checking commit editor...\n"))
2205 ui.status(_("checking commit editor...\n"))
2190 editor = ui.geteditor()
2206 editor = ui.geteditor()
2191 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2207 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2192 if not cmdpath:
2208 if not cmdpath:
2193 if editor == 'vi':
2209 if editor == 'vi':
2194 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2210 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2195 ui.write(_(" (specify a commit editor in your configuration"
2211 ui.write(_(" (specify a commit editor in your configuration"
2196 " file)\n"))
2212 " file)\n"))
2197 else:
2213 else:
2198 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2214 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2199 ui.write(_(" (specify a commit editor in your configuration"
2215 ui.write(_(" (specify a commit editor in your configuration"
2200 " file)\n"))
2216 " file)\n"))
2201 problems += 1
2217 problems += 1
2202
2218
2203 # check username
2219 # check username
2204 ui.status(_("checking username...\n"))
2220 ui.status(_("checking username...\n"))
2205 try:
2221 try:
2206 ui.username()
2222 ui.username()
2207 except util.Abort, e:
2223 except util.Abort, e:
2208 ui.write(" %s\n" % e)
2224 ui.write(" %s\n" % e)
2209 ui.write(_(" (specify a username in your configuration file)\n"))
2225 ui.write(_(" (specify a username in your configuration file)\n"))
2210 problems += 1
2226 problems += 1
2211
2227
2212 if not problems:
2228 if not problems:
2213 ui.status(_("no problems detected\n"))
2229 ui.status(_("no problems detected\n"))
2214 else:
2230 else:
2215 ui.write(_("%s problems detected,"
2231 ui.write(_("%s problems detected,"
2216 " please check your install!\n") % problems)
2232 " please check your install!\n") % problems)
2217
2233
2218 return problems
2234 return problems
2219
2235
2220 @command('debugknown', [], _('REPO ID...'))
2236 @command('debugknown', [], _('REPO ID...'))
2221 def debugknown(ui, repopath, *ids, **opts):
2237 def debugknown(ui, repopath, *ids, **opts):
2222 """test whether node ids are known to a repo
2238 """test whether node ids are known to a repo
2223
2239
2224 Every ID must be a full-length hex node id string. Returns a list of 0s
2240 Every ID must be a full-length hex node id string. Returns a list of 0s
2225 and 1s indicating unknown/known.
2241 and 1s indicating unknown/known.
2226 """
2242 """
2227 repo = hg.peer(ui, opts, repopath)
2243 repo = hg.peer(ui, opts, repopath)
2228 if not repo.capable('known'):
2244 if not repo.capable('known'):
2229 raise util.Abort("known() not supported by target repository")
2245 raise util.Abort("known() not supported by target repository")
2230 flags = repo.known([bin(s) for s in ids])
2246 flags = repo.known([bin(s) for s in ids])
2231 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2247 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2232
2248
2233 @command('debuglabelcomplete', [], _('LABEL...'))
2249 @command('debuglabelcomplete', [], _('LABEL...'))
2234 def debuglabelcomplete(ui, repo, *args):
2250 def debuglabelcomplete(ui, repo, *args):
2235 '''complete "labels" - tags, open branch names, bookmark names'''
2251 '''complete "labels" - tags, open branch names, bookmark names'''
2236
2252
2237 labels = set()
2253 labels = set()
2238 labels.update(t[0] for t in repo.tagslist())
2254 labels.update(t[0] for t in repo.tagslist())
2239 labels.update(repo._bookmarks.keys())
2255 labels.update(repo._bookmarks.keys())
2240 labels.update(tag for (tag, heads, tip, closed)
2256 labels.update(tag for (tag, heads, tip, closed)
2241 in repo.branchmap().iterbranches() if not closed)
2257 in repo.branchmap().iterbranches() if not closed)
2242 completions = set()
2258 completions = set()
2243 if not args:
2259 if not args:
2244 args = ['']
2260 args = ['']
2245 for a in args:
2261 for a in args:
2246 completions.update(l for l in labels if l.startswith(a))
2262 completions.update(l for l in labels if l.startswith(a))
2247 ui.write('\n'.join(sorted(completions)))
2263 ui.write('\n'.join(sorted(completions)))
2248 ui.write('\n')
2264 ui.write('\n')
2249
2265
2250 @command('debugobsolete',
2266 @command('debugobsolete',
2251 [('', 'flags', 0, _('markers flag')),
2267 [('', 'flags', 0, _('markers flag')),
2252 ] + commitopts2,
2268 ] + commitopts2,
2253 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2269 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2254 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2270 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2255 """create arbitrary obsolete marker
2271 """create arbitrary obsolete marker
2256
2272
2257 With no arguments, displays the list of obsolescence markers."""
2273 With no arguments, displays the list of obsolescence markers."""
2258 def parsenodeid(s):
2274 def parsenodeid(s):
2259 try:
2275 try:
2260 # We do not use revsingle/revrange functions here to accept
2276 # We do not use revsingle/revrange functions here to accept
2261 # arbitrary node identifiers, possibly not present in the
2277 # arbitrary node identifiers, possibly not present in the
2262 # local repository.
2278 # local repository.
2263 n = bin(s)
2279 n = bin(s)
2264 if len(n) != len(nullid):
2280 if len(n) != len(nullid):
2265 raise TypeError()
2281 raise TypeError()
2266 return n
2282 return n
2267 except TypeError:
2283 except TypeError:
2268 raise util.Abort('changeset references must be full hexadecimal '
2284 raise util.Abort('changeset references must be full hexadecimal '
2269 'node identifiers')
2285 'node identifiers')
2270
2286
2271 if precursor is not None:
2287 if precursor is not None:
2272 metadata = {}
2288 metadata = {}
2273 if 'date' in opts:
2289 if 'date' in opts:
2274 metadata['date'] = opts['date']
2290 metadata['date'] = opts['date']
2275 metadata['user'] = opts['user'] or ui.username()
2291 metadata['user'] = opts['user'] or ui.username()
2276 succs = tuple(parsenodeid(succ) for succ in successors)
2292 succs = tuple(parsenodeid(succ) for succ in successors)
2277 l = repo.lock()
2293 l = repo.lock()
2278 try:
2294 try:
2279 tr = repo.transaction('debugobsolete')
2295 tr = repo.transaction('debugobsolete')
2280 try:
2296 try:
2281 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2297 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2282 opts['flags'], metadata)
2298 opts['flags'], metadata)
2283 tr.close()
2299 tr.close()
2284 finally:
2300 finally:
2285 tr.release()
2301 tr.release()
2286 finally:
2302 finally:
2287 l.release()
2303 l.release()
2288 else:
2304 else:
2289 for m in obsolete.allmarkers(repo):
2305 for m in obsolete.allmarkers(repo):
2290 cmdutil.showmarker(ui, m)
2306 cmdutil.showmarker(ui, m)
2291
2307
2292 @command('debugpathcomplete',
2308 @command('debugpathcomplete',
2293 [('f', 'full', None, _('complete an entire path')),
2309 [('f', 'full', None, _('complete an entire path')),
2294 ('n', 'normal', None, _('show only normal files')),
2310 ('n', 'normal', None, _('show only normal files')),
2295 ('a', 'added', None, _('show only added files')),
2311 ('a', 'added', None, _('show only added files')),
2296 ('r', 'removed', None, _('show only removed files'))],
2312 ('r', 'removed', None, _('show only removed files'))],
2297 _('FILESPEC...'))
2313 _('FILESPEC...'))
2298 def debugpathcomplete(ui, repo, *specs, **opts):
2314 def debugpathcomplete(ui, repo, *specs, **opts):
2299 '''complete part or all of a tracked path
2315 '''complete part or all of a tracked path
2300
2316
2301 This command supports shells that offer path name completion. It
2317 This command supports shells that offer path name completion. It
2302 currently completes only files already known to the dirstate.
2318 currently completes only files already known to the dirstate.
2303
2319
2304 Completion extends only to the next path segment unless
2320 Completion extends only to the next path segment unless
2305 --full is specified, in which case entire paths are used.'''
2321 --full is specified, in which case entire paths are used.'''
2306
2322
2307 def complete(path, acceptable):
2323 def complete(path, acceptable):
2308 dirstate = repo.dirstate
2324 dirstate = repo.dirstate
2309 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2325 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2310 rootdir = repo.root + os.sep
2326 rootdir = repo.root + os.sep
2311 if spec != repo.root and not spec.startswith(rootdir):
2327 if spec != repo.root and not spec.startswith(rootdir):
2312 return [], []
2328 return [], []
2313 if os.path.isdir(spec):
2329 if os.path.isdir(spec):
2314 spec += '/'
2330 spec += '/'
2315 spec = spec[len(rootdir):]
2331 spec = spec[len(rootdir):]
2316 fixpaths = os.sep != '/'
2332 fixpaths = os.sep != '/'
2317 if fixpaths:
2333 if fixpaths:
2318 spec = spec.replace(os.sep, '/')
2334 spec = spec.replace(os.sep, '/')
2319 speclen = len(spec)
2335 speclen = len(spec)
2320 fullpaths = opts['full']
2336 fullpaths = opts['full']
2321 files, dirs = set(), set()
2337 files, dirs = set(), set()
2322 adddir, addfile = dirs.add, files.add
2338 adddir, addfile = dirs.add, files.add
2323 for f, st in dirstate.iteritems():
2339 for f, st in dirstate.iteritems():
2324 if f.startswith(spec) and st[0] in acceptable:
2340 if f.startswith(spec) and st[0] in acceptable:
2325 if fixpaths:
2341 if fixpaths:
2326 f = f.replace('/', os.sep)
2342 f = f.replace('/', os.sep)
2327 if fullpaths:
2343 if fullpaths:
2328 addfile(f)
2344 addfile(f)
2329 continue
2345 continue
2330 s = f.find(os.sep, speclen)
2346 s = f.find(os.sep, speclen)
2331 if s >= 0:
2347 if s >= 0:
2332 adddir(f[:s])
2348 adddir(f[:s])
2333 else:
2349 else:
2334 addfile(f)
2350 addfile(f)
2335 return files, dirs
2351 return files, dirs
2336
2352
2337 acceptable = ''
2353 acceptable = ''
2338 if opts['normal']:
2354 if opts['normal']:
2339 acceptable += 'nm'
2355 acceptable += 'nm'
2340 if opts['added']:
2356 if opts['added']:
2341 acceptable += 'a'
2357 acceptable += 'a'
2342 if opts['removed']:
2358 if opts['removed']:
2343 acceptable += 'r'
2359 acceptable += 'r'
2344 cwd = repo.getcwd()
2360 cwd = repo.getcwd()
2345 if not specs:
2361 if not specs:
2346 specs = ['.']
2362 specs = ['.']
2347
2363
2348 files, dirs = set(), set()
2364 files, dirs = set(), set()
2349 for spec in specs:
2365 for spec in specs:
2350 f, d = complete(spec, acceptable or 'nmar')
2366 f, d = complete(spec, acceptable or 'nmar')
2351 files.update(f)
2367 files.update(f)
2352 dirs.update(d)
2368 dirs.update(d)
2353 files.update(dirs)
2369 files.update(dirs)
2354 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2370 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2355 ui.write('\n')
2371 ui.write('\n')
2356
2372
2357 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2373 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2358 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2374 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2359 '''access the pushkey key/value protocol
2375 '''access the pushkey key/value protocol
2360
2376
2361 With two args, list the keys in the given namespace.
2377 With two args, list the keys in the given namespace.
2362
2378
2363 With five args, set a key to new if it currently is set to old.
2379 With five args, set a key to new if it currently is set to old.
2364 Reports success or failure.
2380 Reports success or failure.
2365 '''
2381 '''
2366
2382
2367 target = hg.peer(ui, {}, repopath)
2383 target = hg.peer(ui, {}, repopath)
2368 if keyinfo:
2384 if keyinfo:
2369 key, old, new = keyinfo
2385 key, old, new = keyinfo
2370 r = target.pushkey(namespace, key, old, new)
2386 r = target.pushkey(namespace, key, old, new)
2371 ui.status(str(r) + '\n')
2387 ui.status(str(r) + '\n')
2372 return not r
2388 return not r
2373 else:
2389 else:
2374 for k, v in sorted(target.listkeys(namespace).iteritems()):
2390 for k, v in sorted(target.listkeys(namespace).iteritems()):
2375 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2391 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2376 v.encode('string-escape')))
2392 v.encode('string-escape')))
2377
2393
2378 @command('debugpvec', [], _('A B'))
2394 @command('debugpvec', [], _('A B'))
2379 def debugpvec(ui, repo, a, b=None):
2395 def debugpvec(ui, repo, a, b=None):
2380 ca = scmutil.revsingle(repo, a)
2396 ca = scmutil.revsingle(repo, a)
2381 cb = scmutil.revsingle(repo, b)
2397 cb = scmutil.revsingle(repo, b)
2382 pa = pvec.ctxpvec(ca)
2398 pa = pvec.ctxpvec(ca)
2383 pb = pvec.ctxpvec(cb)
2399 pb = pvec.ctxpvec(cb)
2384 if pa == pb:
2400 if pa == pb:
2385 rel = "="
2401 rel = "="
2386 elif pa > pb:
2402 elif pa > pb:
2387 rel = ">"
2403 rel = ">"
2388 elif pa < pb:
2404 elif pa < pb:
2389 rel = "<"
2405 rel = "<"
2390 elif pa | pb:
2406 elif pa | pb:
2391 rel = "|"
2407 rel = "|"
2392 ui.write(_("a: %s\n") % pa)
2408 ui.write(_("a: %s\n") % pa)
2393 ui.write(_("b: %s\n") % pb)
2409 ui.write(_("b: %s\n") % pb)
2394 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2410 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2395 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2411 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2396 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2412 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2397 pa.distance(pb), rel))
2413 pa.distance(pb), rel))
2398
2414
2399 @command('debugrebuilddirstate|debugrebuildstate',
2415 @command('debugrebuilddirstate|debugrebuildstate',
2400 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2416 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2401 _('[-r REV]'))
2417 _('[-r REV]'))
2402 def debugrebuilddirstate(ui, repo, rev):
2418 def debugrebuilddirstate(ui, repo, rev):
2403 """rebuild the dirstate as it would look like for the given revision
2419 """rebuild the dirstate as it would look like for the given revision
2404
2420
2405 If no revision is specified the first current parent will be used.
2421 If no revision is specified the first current parent will be used.
2406
2422
2407 The dirstate will be set to the files of the given revision.
2423 The dirstate will be set to the files of the given revision.
2408 The actual working directory content or existing dirstate
2424 The actual working directory content or existing dirstate
2409 information such as adds or removes is not considered.
2425 information such as adds or removes is not considered.
2410
2426
2411 One use of this command is to make the next :hg:`status` invocation
2427 One use of this command is to make the next :hg:`status` invocation
2412 check the actual file content.
2428 check the actual file content.
2413 """
2429 """
2414 ctx = scmutil.revsingle(repo, rev)
2430 ctx = scmutil.revsingle(repo, rev)
2415 wlock = repo.wlock()
2431 wlock = repo.wlock()
2416 try:
2432 try:
2417 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2433 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2418 finally:
2434 finally:
2419 wlock.release()
2435 wlock.release()
2420
2436
2421 @command('debugrename',
2437 @command('debugrename',
2422 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2438 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2423 _('[-r REV] FILE'))
2439 _('[-r REV] FILE'))
2424 def debugrename(ui, repo, file1, *pats, **opts):
2440 def debugrename(ui, repo, file1, *pats, **opts):
2425 """dump rename information"""
2441 """dump rename information"""
2426
2442
2427 ctx = scmutil.revsingle(repo, opts.get('rev'))
2443 ctx = scmutil.revsingle(repo, opts.get('rev'))
2428 m = scmutil.match(ctx, (file1,) + pats, opts)
2444 m = scmutil.match(ctx, (file1,) + pats, opts)
2429 for abs in ctx.walk(m):
2445 for abs in ctx.walk(m):
2430 fctx = ctx[abs]
2446 fctx = ctx[abs]
2431 o = fctx.filelog().renamed(fctx.filenode())
2447 o = fctx.filelog().renamed(fctx.filenode())
2432 rel = m.rel(abs)
2448 rel = m.rel(abs)
2433 if o:
2449 if o:
2434 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2450 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2435 else:
2451 else:
2436 ui.write(_("%s not renamed\n") % rel)
2452 ui.write(_("%s not renamed\n") % rel)
2437
2453
2438 @command('debugrevlog',
2454 @command('debugrevlog',
2439 [('c', 'changelog', False, _('open changelog')),
2455 [('c', 'changelog', False, _('open changelog')),
2440 ('m', 'manifest', False, _('open manifest')),
2456 ('m', 'manifest', False, _('open manifest')),
2441 ('d', 'dump', False, _('dump index data'))],
2457 ('d', 'dump', False, _('dump index data'))],
2442 _('-c|-m|FILE'))
2458 _('-c|-m|FILE'))
2443 def debugrevlog(ui, repo, file_=None, **opts):
2459 def debugrevlog(ui, repo, file_=None, **opts):
2444 """show data and statistics about a revlog"""
2460 """show data and statistics about a revlog"""
2445 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2461 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2446
2462
2447 if opts.get("dump"):
2463 if opts.get("dump"):
2448 numrevs = len(r)
2464 numrevs = len(r)
2449 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2465 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2450 " rawsize totalsize compression heads\n")
2466 " rawsize totalsize compression heads\n")
2451 ts = 0
2467 ts = 0
2452 heads = set()
2468 heads = set()
2453 for rev in xrange(numrevs):
2469 for rev in xrange(numrevs):
2454 dbase = r.deltaparent(rev)
2470 dbase = r.deltaparent(rev)
2455 if dbase == -1:
2471 if dbase == -1:
2456 dbase = rev
2472 dbase = rev
2457 cbase = r.chainbase(rev)
2473 cbase = r.chainbase(rev)
2458 p1, p2 = r.parentrevs(rev)
2474 p1, p2 = r.parentrevs(rev)
2459 rs = r.rawsize(rev)
2475 rs = r.rawsize(rev)
2460 ts = ts + rs
2476 ts = ts + rs
2461 heads -= set(r.parentrevs(rev))
2477 heads -= set(r.parentrevs(rev))
2462 heads.add(rev)
2478 heads.add(rev)
2463 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2479 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2464 (rev, p1, p2, r.start(rev), r.end(rev),
2480 (rev, p1, p2, r.start(rev), r.end(rev),
2465 r.start(dbase), r.start(cbase),
2481 r.start(dbase), r.start(cbase),
2466 r.start(p1), r.start(p2),
2482 r.start(p1), r.start(p2),
2467 rs, ts, ts / r.end(rev), len(heads)))
2483 rs, ts, ts / r.end(rev), len(heads)))
2468 return 0
2484 return 0
2469
2485
2470 v = r.version
2486 v = r.version
2471 format = v & 0xFFFF
2487 format = v & 0xFFFF
2472 flags = []
2488 flags = []
2473 gdelta = False
2489 gdelta = False
2474 if v & revlog.REVLOGNGINLINEDATA:
2490 if v & revlog.REVLOGNGINLINEDATA:
2475 flags.append('inline')
2491 flags.append('inline')
2476 if v & revlog.REVLOGGENERALDELTA:
2492 if v & revlog.REVLOGGENERALDELTA:
2477 gdelta = True
2493 gdelta = True
2478 flags.append('generaldelta')
2494 flags.append('generaldelta')
2479 if not flags:
2495 if not flags:
2480 flags = ['(none)']
2496 flags = ['(none)']
2481
2497
2482 nummerges = 0
2498 nummerges = 0
2483 numfull = 0
2499 numfull = 0
2484 numprev = 0
2500 numprev = 0
2485 nump1 = 0
2501 nump1 = 0
2486 nump2 = 0
2502 nump2 = 0
2487 numother = 0
2503 numother = 0
2488 nump1prev = 0
2504 nump1prev = 0
2489 nump2prev = 0
2505 nump2prev = 0
2490 chainlengths = []
2506 chainlengths = []
2491
2507
2492 datasize = [None, 0, 0L]
2508 datasize = [None, 0, 0L]
2493 fullsize = [None, 0, 0L]
2509 fullsize = [None, 0, 0L]
2494 deltasize = [None, 0, 0L]
2510 deltasize = [None, 0, 0L]
2495
2511
2496 def addsize(size, l):
2512 def addsize(size, l):
2497 if l[0] is None or size < l[0]:
2513 if l[0] is None or size < l[0]:
2498 l[0] = size
2514 l[0] = size
2499 if size > l[1]:
2515 if size > l[1]:
2500 l[1] = size
2516 l[1] = size
2501 l[2] += size
2517 l[2] += size
2502
2518
2503 numrevs = len(r)
2519 numrevs = len(r)
2504 for rev in xrange(numrevs):
2520 for rev in xrange(numrevs):
2505 p1, p2 = r.parentrevs(rev)
2521 p1, p2 = r.parentrevs(rev)
2506 delta = r.deltaparent(rev)
2522 delta = r.deltaparent(rev)
2507 if format > 0:
2523 if format > 0:
2508 addsize(r.rawsize(rev), datasize)
2524 addsize(r.rawsize(rev), datasize)
2509 if p2 != nullrev:
2525 if p2 != nullrev:
2510 nummerges += 1
2526 nummerges += 1
2511 size = r.length(rev)
2527 size = r.length(rev)
2512 if delta == nullrev:
2528 if delta == nullrev:
2513 chainlengths.append(0)
2529 chainlengths.append(0)
2514 numfull += 1
2530 numfull += 1
2515 addsize(size, fullsize)
2531 addsize(size, fullsize)
2516 else:
2532 else:
2517 chainlengths.append(chainlengths[delta] + 1)
2533 chainlengths.append(chainlengths[delta] + 1)
2518 addsize(size, deltasize)
2534 addsize(size, deltasize)
2519 if delta == rev - 1:
2535 if delta == rev - 1:
2520 numprev += 1
2536 numprev += 1
2521 if delta == p1:
2537 if delta == p1:
2522 nump1prev += 1
2538 nump1prev += 1
2523 elif delta == p2:
2539 elif delta == p2:
2524 nump2prev += 1
2540 nump2prev += 1
2525 elif delta == p1:
2541 elif delta == p1:
2526 nump1 += 1
2542 nump1 += 1
2527 elif delta == p2:
2543 elif delta == p2:
2528 nump2 += 1
2544 nump2 += 1
2529 elif delta != nullrev:
2545 elif delta != nullrev:
2530 numother += 1
2546 numother += 1
2531
2547
2532 # Adjust size min value for empty cases
2548 # Adjust size min value for empty cases
2533 for size in (datasize, fullsize, deltasize):
2549 for size in (datasize, fullsize, deltasize):
2534 if size[0] is None:
2550 if size[0] is None:
2535 size[0] = 0
2551 size[0] = 0
2536
2552
2537 numdeltas = numrevs - numfull
2553 numdeltas = numrevs - numfull
2538 numoprev = numprev - nump1prev - nump2prev
2554 numoprev = numprev - nump1prev - nump2prev
2539 totalrawsize = datasize[2]
2555 totalrawsize = datasize[2]
2540 datasize[2] /= numrevs
2556 datasize[2] /= numrevs
2541 fulltotal = fullsize[2]
2557 fulltotal = fullsize[2]
2542 fullsize[2] /= numfull
2558 fullsize[2] /= numfull
2543 deltatotal = deltasize[2]
2559 deltatotal = deltasize[2]
2544 if numrevs - numfull > 0:
2560 if numrevs - numfull > 0:
2545 deltasize[2] /= numrevs - numfull
2561 deltasize[2] /= numrevs - numfull
2546 totalsize = fulltotal + deltatotal
2562 totalsize = fulltotal + deltatotal
2547 avgchainlen = sum(chainlengths) / numrevs
2563 avgchainlen = sum(chainlengths) / numrevs
2548 compratio = totalrawsize / totalsize
2564 compratio = totalrawsize / totalsize
2549
2565
2550 basedfmtstr = '%%%dd\n'
2566 basedfmtstr = '%%%dd\n'
2551 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2567 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2552
2568
2553 def dfmtstr(max):
2569 def dfmtstr(max):
2554 return basedfmtstr % len(str(max))
2570 return basedfmtstr % len(str(max))
2555 def pcfmtstr(max, padding=0):
2571 def pcfmtstr(max, padding=0):
2556 return basepcfmtstr % (len(str(max)), ' ' * padding)
2572 return basepcfmtstr % (len(str(max)), ' ' * padding)
2557
2573
2558 def pcfmt(value, total):
2574 def pcfmt(value, total):
2559 return (value, 100 * float(value) / total)
2575 return (value, 100 * float(value) / total)
2560
2576
2561 ui.write(('format : %d\n') % format)
2577 ui.write(('format : %d\n') % format)
2562 ui.write(('flags : %s\n') % ', '.join(flags))
2578 ui.write(('flags : %s\n') % ', '.join(flags))
2563
2579
2564 ui.write('\n')
2580 ui.write('\n')
2565 fmt = pcfmtstr(totalsize)
2581 fmt = pcfmtstr(totalsize)
2566 fmt2 = dfmtstr(totalsize)
2582 fmt2 = dfmtstr(totalsize)
2567 ui.write(('revisions : ') + fmt2 % numrevs)
2583 ui.write(('revisions : ') + fmt2 % numrevs)
2568 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2584 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2569 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2585 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2570 ui.write(('revisions : ') + fmt2 % numrevs)
2586 ui.write(('revisions : ') + fmt2 % numrevs)
2571 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2587 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2572 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2588 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2573 ui.write(('revision size : ') + fmt2 % totalsize)
2589 ui.write(('revision size : ') + fmt2 % totalsize)
2574 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2590 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2575 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2591 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2576
2592
2577 ui.write('\n')
2593 ui.write('\n')
2578 fmt = dfmtstr(max(avgchainlen, compratio))
2594 fmt = dfmtstr(max(avgchainlen, compratio))
2579 ui.write(('avg chain length : ') + fmt % avgchainlen)
2595 ui.write(('avg chain length : ') + fmt % avgchainlen)
2580 ui.write(('compression ratio : ') + fmt % compratio)
2596 ui.write(('compression ratio : ') + fmt % compratio)
2581
2597
2582 if format > 0:
2598 if format > 0:
2583 ui.write('\n')
2599 ui.write('\n')
2584 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2600 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2585 % tuple(datasize))
2601 % tuple(datasize))
2586 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2602 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2587 % tuple(fullsize))
2603 % tuple(fullsize))
2588 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2604 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2589 % tuple(deltasize))
2605 % tuple(deltasize))
2590
2606
2591 if numdeltas > 0:
2607 if numdeltas > 0:
2592 ui.write('\n')
2608 ui.write('\n')
2593 fmt = pcfmtstr(numdeltas)
2609 fmt = pcfmtstr(numdeltas)
2594 fmt2 = pcfmtstr(numdeltas, 4)
2610 fmt2 = pcfmtstr(numdeltas, 4)
2595 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2611 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2596 if numprev > 0:
2612 if numprev > 0:
2597 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2613 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2598 numprev))
2614 numprev))
2599 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2615 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2600 numprev))
2616 numprev))
2601 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2617 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2602 numprev))
2618 numprev))
2603 if gdelta:
2619 if gdelta:
2604 ui.write(('deltas against p1 : ')
2620 ui.write(('deltas against p1 : ')
2605 + fmt % pcfmt(nump1, numdeltas))
2621 + fmt % pcfmt(nump1, numdeltas))
2606 ui.write(('deltas against p2 : ')
2622 ui.write(('deltas against p2 : ')
2607 + fmt % pcfmt(nump2, numdeltas))
2623 + fmt % pcfmt(nump2, numdeltas))
2608 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2624 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2609 numdeltas))
2625 numdeltas))
2610
2626
2611 @command('debugrevspec',
2627 @command('debugrevspec',
2612 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2628 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2613 ('REVSPEC'))
2629 ('REVSPEC'))
2614 def debugrevspec(ui, repo, expr, **opts):
2630 def debugrevspec(ui, repo, expr, **opts):
2615 """parse and apply a revision specification
2631 """parse and apply a revision specification
2616
2632
2617 Use --verbose to print the parsed tree before and after aliases
2633 Use --verbose to print the parsed tree before and after aliases
2618 expansion.
2634 expansion.
2619 """
2635 """
2620 if ui.verbose:
2636 if ui.verbose:
2621 tree = revset.parse(expr)[0]
2637 tree = revset.parse(expr)[0]
2622 ui.note(revset.prettyformat(tree), "\n")
2638 ui.note(revset.prettyformat(tree), "\n")
2623 newtree = revset.findaliases(ui, tree)
2639 newtree = revset.findaliases(ui, tree)
2624 if newtree != tree:
2640 if newtree != tree:
2625 ui.note(revset.prettyformat(newtree), "\n")
2641 ui.note(revset.prettyformat(newtree), "\n")
2626 if opts["optimize"]:
2642 if opts["optimize"]:
2627 weight, optimizedtree = revset.optimize(newtree, True)
2643 weight, optimizedtree = revset.optimize(newtree, True)
2628 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2644 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2629 func = revset.match(ui, expr)
2645 func = revset.match(ui, expr)
2630 for c in func(repo, revset.spanset(repo)):
2646 for c in func(repo, revset.spanset(repo)):
2631 ui.write("%s\n" % c)
2647 ui.write("%s\n" % c)
2632
2648
2633 @command('debugsetparents', [], _('REV1 [REV2]'))
2649 @command('debugsetparents', [], _('REV1 [REV2]'))
2634 def debugsetparents(ui, repo, rev1, rev2=None):
2650 def debugsetparents(ui, repo, rev1, rev2=None):
2635 """manually set the parents of the current working directory
2651 """manually set the parents of the current working directory
2636
2652
2637 This is useful for writing repository conversion tools, but should
2653 This is useful for writing repository conversion tools, but should
2638 be used with care.
2654 be used with care.
2639
2655
2640 Returns 0 on success.
2656 Returns 0 on success.
2641 """
2657 """
2642
2658
2643 r1 = scmutil.revsingle(repo, rev1).node()
2659 r1 = scmutil.revsingle(repo, rev1).node()
2644 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2660 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2645
2661
2646 wlock = repo.wlock()
2662 wlock = repo.wlock()
2647 try:
2663 try:
2648 repo.setparents(r1, r2)
2664 repo.setparents(r1, r2)
2649 finally:
2665 finally:
2650 wlock.release()
2666 wlock.release()
2651
2667
2652 @command('debugdirstate|debugstate',
2668 @command('debugdirstate|debugstate',
2653 [('', 'nodates', None, _('do not display the saved mtime')),
2669 [('', 'nodates', None, _('do not display the saved mtime')),
2654 ('', 'datesort', None, _('sort by saved mtime'))],
2670 ('', 'datesort', None, _('sort by saved mtime'))],
2655 _('[OPTION]...'))
2671 _('[OPTION]...'))
2656 def debugstate(ui, repo, nodates=None, datesort=None):
2672 def debugstate(ui, repo, nodates=None, datesort=None):
2657 """show the contents of the current dirstate"""
2673 """show the contents of the current dirstate"""
2658 timestr = ""
2674 timestr = ""
2659 showdate = not nodates
2675 showdate = not nodates
2660 if datesort:
2676 if datesort:
2661 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2677 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2662 else:
2678 else:
2663 keyfunc = None # sort by filename
2679 keyfunc = None # sort by filename
2664 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2680 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2665 if showdate:
2681 if showdate:
2666 if ent[3] == -1:
2682 if ent[3] == -1:
2667 # Pad or slice to locale representation
2683 # Pad or slice to locale representation
2668 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2684 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2669 time.localtime(0)))
2685 time.localtime(0)))
2670 timestr = 'unset'
2686 timestr = 'unset'
2671 timestr = (timestr[:locale_len] +
2687 timestr = (timestr[:locale_len] +
2672 ' ' * (locale_len - len(timestr)))
2688 ' ' * (locale_len - len(timestr)))
2673 else:
2689 else:
2674 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2690 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2675 time.localtime(ent[3]))
2691 time.localtime(ent[3]))
2676 if ent[1] & 020000:
2692 if ent[1] & 020000:
2677 mode = 'lnk'
2693 mode = 'lnk'
2678 else:
2694 else:
2679 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2695 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2680 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2696 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2681 for f in repo.dirstate.copies():
2697 for f in repo.dirstate.copies():
2682 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2698 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2683
2699
2684 @command('debugsub',
2700 @command('debugsub',
2685 [('r', 'rev', '',
2701 [('r', 'rev', '',
2686 _('revision to check'), _('REV'))],
2702 _('revision to check'), _('REV'))],
2687 _('[-r REV] [REV]'))
2703 _('[-r REV] [REV]'))
2688 def debugsub(ui, repo, rev=None):
2704 def debugsub(ui, repo, rev=None):
2689 ctx = scmutil.revsingle(repo, rev, None)
2705 ctx = scmutil.revsingle(repo, rev, None)
2690 for k, v in sorted(ctx.substate.items()):
2706 for k, v in sorted(ctx.substate.items()):
2691 ui.write(('path %s\n') % k)
2707 ui.write(('path %s\n') % k)
2692 ui.write((' source %s\n') % v[0])
2708 ui.write((' source %s\n') % v[0])
2693 ui.write((' revision %s\n') % v[1])
2709 ui.write((' revision %s\n') % v[1])
2694
2710
2695 @command('debugsuccessorssets',
2711 @command('debugsuccessorssets',
2696 [],
2712 [],
2697 _('[REV]'))
2713 _('[REV]'))
2698 def debugsuccessorssets(ui, repo, *revs):
2714 def debugsuccessorssets(ui, repo, *revs):
2699 """show set of successors for revision
2715 """show set of successors for revision
2700
2716
2701 A successors set of changeset A is a consistent group of revisions that
2717 A successors set of changeset A is a consistent group of revisions that
2702 succeed A. It contains non-obsolete changesets only.
2718 succeed A. It contains non-obsolete changesets only.
2703
2719
2704 In most cases a changeset A has a single successors set containing a single
2720 In most cases a changeset A has a single successors set containing a single
2705 successor (changeset A replaced by A').
2721 successor (changeset A replaced by A').
2706
2722
2707 A changeset that is made obsolete with no successors are called "pruned".
2723 A changeset that is made obsolete with no successors are called "pruned".
2708 Such changesets have no successors sets at all.
2724 Such changesets have no successors sets at all.
2709
2725
2710 A changeset that has been "split" will have a successors set containing
2726 A changeset that has been "split" will have a successors set containing
2711 more than one successor.
2727 more than one successor.
2712
2728
2713 A changeset that has been rewritten in multiple different ways is called
2729 A changeset that has been rewritten in multiple different ways is called
2714 "divergent". Such changesets have multiple successor sets (each of which
2730 "divergent". Such changesets have multiple successor sets (each of which
2715 may also be split, i.e. have multiple successors).
2731 may also be split, i.e. have multiple successors).
2716
2732
2717 Results are displayed as follows::
2733 Results are displayed as follows::
2718
2734
2719 <rev1>
2735 <rev1>
2720 <successors-1A>
2736 <successors-1A>
2721 <rev2>
2737 <rev2>
2722 <successors-2A>
2738 <successors-2A>
2723 <successors-2B1> <successors-2B2> <successors-2B3>
2739 <successors-2B1> <successors-2B2> <successors-2B3>
2724
2740
2725 Here rev2 has two possible (i.e. divergent) successors sets. The first
2741 Here rev2 has two possible (i.e. divergent) successors sets. The first
2726 holds one element, whereas the second holds three (i.e. the changeset has
2742 holds one element, whereas the second holds three (i.e. the changeset has
2727 been split).
2743 been split).
2728 """
2744 """
2729 # passed to successorssets caching computation from one call to another
2745 # passed to successorssets caching computation from one call to another
2730 cache = {}
2746 cache = {}
2731 ctx2str = str
2747 ctx2str = str
2732 node2str = short
2748 node2str = short
2733 if ui.debug():
2749 if ui.debug():
2734 def ctx2str(ctx):
2750 def ctx2str(ctx):
2735 return ctx.hex()
2751 return ctx.hex()
2736 node2str = hex
2752 node2str = hex
2737 for rev in scmutil.revrange(repo, revs):
2753 for rev in scmutil.revrange(repo, revs):
2738 ctx = repo[rev]
2754 ctx = repo[rev]
2739 ui.write('%s\n'% ctx2str(ctx))
2755 ui.write('%s\n'% ctx2str(ctx))
2740 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2756 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2741 if succsset:
2757 if succsset:
2742 ui.write(' ')
2758 ui.write(' ')
2743 ui.write(node2str(succsset[0]))
2759 ui.write(node2str(succsset[0]))
2744 for node in succsset[1:]:
2760 for node in succsset[1:]:
2745 ui.write(' ')
2761 ui.write(' ')
2746 ui.write(node2str(node))
2762 ui.write(node2str(node))
2747 ui.write('\n')
2763 ui.write('\n')
2748
2764
2749 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2765 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2750 def debugwalk(ui, repo, *pats, **opts):
2766 def debugwalk(ui, repo, *pats, **opts):
2751 """show how files match on given patterns"""
2767 """show how files match on given patterns"""
2752 m = scmutil.match(repo[None], pats, opts)
2768 m = scmutil.match(repo[None], pats, opts)
2753 items = list(repo.walk(m))
2769 items = list(repo.walk(m))
2754 if not items:
2770 if not items:
2755 return
2771 return
2756 f = lambda fn: fn
2772 f = lambda fn: fn
2757 if ui.configbool('ui', 'slash') and os.sep != '/':
2773 if ui.configbool('ui', 'slash') and os.sep != '/':
2758 f = lambda fn: util.normpath(fn)
2774 f = lambda fn: util.normpath(fn)
2759 fmt = 'f %%-%ds %%-%ds %%s' % (
2775 fmt = 'f %%-%ds %%-%ds %%s' % (
2760 max([len(abs) for abs in items]),
2776 max([len(abs) for abs in items]),
2761 max([len(m.rel(abs)) for abs in items]))
2777 max([len(m.rel(abs)) for abs in items]))
2762 for abs in items:
2778 for abs in items:
2763 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2779 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2764 ui.write("%s\n" % line.rstrip())
2780 ui.write("%s\n" % line.rstrip())
2765
2781
2766 @command('debugwireargs',
2782 @command('debugwireargs',
2767 [('', 'three', '', 'three'),
2783 [('', 'three', '', 'three'),
2768 ('', 'four', '', 'four'),
2784 ('', 'four', '', 'four'),
2769 ('', 'five', '', 'five'),
2785 ('', 'five', '', 'five'),
2770 ] + remoteopts,
2786 ] + remoteopts,
2771 _('REPO [OPTIONS]... [ONE [TWO]]'))
2787 _('REPO [OPTIONS]... [ONE [TWO]]'))
2772 def debugwireargs(ui, repopath, *vals, **opts):
2788 def debugwireargs(ui, repopath, *vals, **opts):
2773 repo = hg.peer(ui, opts, repopath)
2789 repo = hg.peer(ui, opts, repopath)
2774 for opt in remoteopts:
2790 for opt in remoteopts:
2775 del opts[opt[1]]
2791 del opts[opt[1]]
2776 args = {}
2792 args = {}
2777 for k, v in opts.iteritems():
2793 for k, v in opts.iteritems():
2778 if v:
2794 if v:
2779 args[k] = v
2795 args[k] = v
2780 # run twice to check that we don't mess up the stream for the next command
2796 # run twice to check that we don't mess up the stream for the next command
2781 res1 = repo.debugwireargs(*vals, **args)
2797 res1 = repo.debugwireargs(*vals, **args)
2782 res2 = repo.debugwireargs(*vals, **args)
2798 res2 = repo.debugwireargs(*vals, **args)
2783 ui.write("%s\n" % res1)
2799 ui.write("%s\n" % res1)
2784 if res1 != res2:
2800 if res1 != res2:
2785 ui.warn("%s\n" % res2)
2801 ui.warn("%s\n" % res2)
2786
2802
2787 @command('^diff',
2803 @command('^diff',
2788 [('r', 'rev', [], _('revision'), _('REV')),
2804 [('r', 'rev', [], _('revision'), _('REV')),
2789 ('c', 'change', '', _('change made by revision'), _('REV'))
2805 ('c', 'change', '', _('change made by revision'), _('REV'))
2790 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2806 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2791 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2807 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2792 def diff(ui, repo, *pats, **opts):
2808 def diff(ui, repo, *pats, **opts):
2793 """diff repository (or selected files)
2809 """diff repository (or selected files)
2794
2810
2795 Show differences between revisions for the specified files.
2811 Show differences between revisions for the specified files.
2796
2812
2797 Differences between files are shown using the unified diff format.
2813 Differences between files are shown using the unified diff format.
2798
2814
2799 .. note::
2815 .. note::
2800
2816
2801 diff may generate unexpected results for merges, as it will
2817 diff may generate unexpected results for merges, as it will
2802 default to comparing against the working directory's first
2818 default to comparing against the working directory's first
2803 parent changeset if no revisions are specified.
2819 parent changeset if no revisions are specified.
2804
2820
2805 When two revision arguments are given, then changes are shown
2821 When two revision arguments are given, then changes are shown
2806 between those revisions. If only one revision is specified then
2822 between those revisions. If only one revision is specified then
2807 that revision is compared to the working directory, and, when no
2823 that revision is compared to the working directory, and, when no
2808 revisions are specified, the working directory files are compared
2824 revisions are specified, the working directory files are compared
2809 to its parent.
2825 to its parent.
2810
2826
2811 Alternatively you can specify -c/--change with a revision to see
2827 Alternatively you can specify -c/--change with a revision to see
2812 the changes in that changeset relative to its first parent.
2828 the changes in that changeset relative to its first parent.
2813
2829
2814 Without the -a/--text option, diff will avoid generating diffs of
2830 Without the -a/--text option, diff will avoid generating diffs of
2815 files it detects as binary. With -a, diff will generate a diff
2831 files it detects as binary. With -a, diff will generate a diff
2816 anyway, probably with undesirable results.
2832 anyway, probably with undesirable results.
2817
2833
2818 Use the -g/--git option to generate diffs in the git extended diff
2834 Use the -g/--git option to generate diffs in the git extended diff
2819 format. For more information, read :hg:`help diffs`.
2835 format. For more information, read :hg:`help diffs`.
2820
2836
2821 .. container:: verbose
2837 .. container:: verbose
2822
2838
2823 Examples:
2839 Examples:
2824
2840
2825 - compare a file in the current working directory to its parent::
2841 - compare a file in the current working directory to its parent::
2826
2842
2827 hg diff foo.c
2843 hg diff foo.c
2828
2844
2829 - compare two historical versions of a directory, with rename info::
2845 - compare two historical versions of a directory, with rename info::
2830
2846
2831 hg diff --git -r 1.0:1.2 lib/
2847 hg diff --git -r 1.0:1.2 lib/
2832
2848
2833 - get change stats relative to the last change on some date::
2849 - get change stats relative to the last change on some date::
2834
2850
2835 hg diff --stat -r "date('may 2')"
2851 hg diff --stat -r "date('may 2')"
2836
2852
2837 - diff all newly-added files that contain a keyword::
2853 - diff all newly-added files that contain a keyword::
2838
2854
2839 hg diff "set:added() and grep(GNU)"
2855 hg diff "set:added() and grep(GNU)"
2840
2856
2841 - compare a revision and its parents::
2857 - compare a revision and its parents::
2842
2858
2843 hg diff -c 9353 # compare against first parent
2859 hg diff -c 9353 # compare against first parent
2844 hg diff -r 9353^:9353 # same using revset syntax
2860 hg diff -r 9353^:9353 # same using revset syntax
2845 hg diff -r 9353^2:9353 # compare against the second parent
2861 hg diff -r 9353^2:9353 # compare against the second parent
2846
2862
2847 Returns 0 on success.
2863 Returns 0 on success.
2848 """
2864 """
2849
2865
2850 revs = opts.get('rev')
2866 revs = opts.get('rev')
2851 change = opts.get('change')
2867 change = opts.get('change')
2852 stat = opts.get('stat')
2868 stat = opts.get('stat')
2853 reverse = opts.get('reverse')
2869 reverse = opts.get('reverse')
2854
2870
2855 if revs and change:
2871 if revs and change:
2856 msg = _('cannot specify --rev and --change at the same time')
2872 msg = _('cannot specify --rev and --change at the same time')
2857 raise util.Abort(msg)
2873 raise util.Abort(msg)
2858 elif change:
2874 elif change:
2859 node2 = scmutil.revsingle(repo, change, None).node()
2875 node2 = scmutil.revsingle(repo, change, None).node()
2860 node1 = repo[node2].p1().node()
2876 node1 = repo[node2].p1().node()
2861 else:
2877 else:
2862 node1, node2 = scmutil.revpair(repo, revs)
2878 node1, node2 = scmutil.revpair(repo, revs)
2863
2879
2864 if reverse:
2880 if reverse:
2865 node1, node2 = node2, node1
2881 node1, node2 = node2, node1
2866
2882
2867 diffopts = patch.diffopts(ui, opts)
2883 diffopts = patch.diffopts(ui, opts)
2868 m = scmutil.match(repo[node2], pats, opts)
2884 m = scmutil.match(repo[node2], pats, opts)
2869 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2885 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2870 listsubrepos=opts.get('subrepos'))
2886 listsubrepos=opts.get('subrepos'))
2871
2887
2872 @command('^export',
2888 @command('^export',
2873 [('o', 'output', '',
2889 [('o', 'output', '',
2874 _('print output to file with formatted name'), _('FORMAT')),
2890 _('print output to file with formatted name'), _('FORMAT')),
2875 ('', 'switch-parent', None, _('diff against the second parent')),
2891 ('', 'switch-parent', None, _('diff against the second parent')),
2876 ('r', 'rev', [], _('revisions to export'), _('REV')),
2892 ('r', 'rev', [], _('revisions to export'), _('REV')),
2877 ] + diffopts,
2893 ] + diffopts,
2878 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2894 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2879 def export(ui, repo, *changesets, **opts):
2895 def export(ui, repo, *changesets, **opts):
2880 """dump the header and diffs for one or more changesets
2896 """dump the header and diffs for one or more changesets
2881
2897
2882 Print the changeset header and diffs for one or more revisions.
2898 Print the changeset header and diffs for one or more revisions.
2883 If no revision is given, the parent of the working directory is used.
2899 If no revision is given, the parent of the working directory is used.
2884
2900
2885 The information shown in the changeset header is: author, date,
2901 The information shown in the changeset header is: author, date,
2886 branch name (if non-default), changeset hash, parent(s) and commit
2902 branch name (if non-default), changeset hash, parent(s) and commit
2887 comment.
2903 comment.
2888
2904
2889 .. note::
2905 .. note::
2890
2906
2891 export may generate unexpected diff output for merge
2907 export may generate unexpected diff output for merge
2892 changesets, as it will compare the merge changeset against its
2908 changesets, as it will compare the merge changeset against its
2893 first parent only.
2909 first parent only.
2894
2910
2895 Output may be to a file, in which case the name of the file is
2911 Output may be to a file, in which case the name of the file is
2896 given using a format string. The formatting rules are as follows:
2912 given using a format string. The formatting rules are as follows:
2897
2913
2898 :``%%``: literal "%" character
2914 :``%%``: literal "%" character
2899 :``%H``: changeset hash (40 hexadecimal digits)
2915 :``%H``: changeset hash (40 hexadecimal digits)
2900 :``%N``: number of patches being generated
2916 :``%N``: number of patches being generated
2901 :``%R``: changeset revision number
2917 :``%R``: changeset revision number
2902 :``%b``: basename of the exporting repository
2918 :``%b``: basename of the exporting repository
2903 :``%h``: short-form changeset hash (12 hexadecimal digits)
2919 :``%h``: short-form changeset hash (12 hexadecimal digits)
2904 :``%m``: first line of the commit message (only alphanumeric characters)
2920 :``%m``: first line of the commit message (only alphanumeric characters)
2905 :``%n``: zero-padded sequence number, starting at 1
2921 :``%n``: zero-padded sequence number, starting at 1
2906 :``%r``: zero-padded changeset revision number
2922 :``%r``: zero-padded changeset revision number
2907
2923
2908 Without the -a/--text option, export will avoid generating diffs
2924 Without the -a/--text option, export will avoid generating diffs
2909 of files it detects as binary. With -a, export will generate a
2925 of files it detects as binary. With -a, export will generate a
2910 diff anyway, probably with undesirable results.
2926 diff anyway, probably with undesirable results.
2911
2927
2912 Use the -g/--git option to generate diffs in the git extended diff
2928 Use the -g/--git option to generate diffs in the git extended diff
2913 format. See :hg:`help diffs` for more information.
2929 format. See :hg:`help diffs` for more information.
2914
2930
2915 With the --switch-parent option, the diff will be against the
2931 With the --switch-parent option, the diff will be against the
2916 second parent. It can be useful to review a merge.
2932 second parent. It can be useful to review a merge.
2917
2933
2918 .. container:: verbose
2934 .. container:: verbose
2919
2935
2920 Examples:
2936 Examples:
2921
2937
2922 - use export and import to transplant a bugfix to the current
2938 - use export and import to transplant a bugfix to the current
2923 branch::
2939 branch::
2924
2940
2925 hg export -r 9353 | hg import -
2941 hg export -r 9353 | hg import -
2926
2942
2927 - export all the changesets between two revisions to a file with
2943 - export all the changesets between two revisions to a file with
2928 rename information::
2944 rename information::
2929
2945
2930 hg export --git -r 123:150 > changes.txt
2946 hg export --git -r 123:150 > changes.txt
2931
2947
2932 - split outgoing changes into a series of patches with
2948 - split outgoing changes into a series of patches with
2933 descriptive names::
2949 descriptive names::
2934
2950
2935 hg export -r "outgoing()" -o "%n-%m.patch"
2951 hg export -r "outgoing()" -o "%n-%m.patch"
2936
2952
2937 Returns 0 on success.
2953 Returns 0 on success.
2938 """
2954 """
2939 changesets += tuple(opts.get('rev', []))
2955 changesets += tuple(opts.get('rev', []))
2940 if not changesets:
2956 if not changesets:
2941 changesets = ['.']
2957 changesets = ['.']
2942 revs = scmutil.revrange(repo, changesets)
2958 revs = scmutil.revrange(repo, changesets)
2943 if not revs:
2959 if not revs:
2944 raise util.Abort(_("export requires at least one changeset"))
2960 raise util.Abort(_("export requires at least one changeset"))
2945 if len(revs) > 1:
2961 if len(revs) > 1:
2946 ui.note(_('exporting patches:\n'))
2962 ui.note(_('exporting patches:\n'))
2947 else:
2963 else:
2948 ui.note(_('exporting patch:\n'))
2964 ui.note(_('exporting patch:\n'))
2949 cmdutil.export(repo, revs, template=opts.get('output'),
2965 cmdutil.export(repo, revs, template=opts.get('output'),
2950 switch_parent=opts.get('switch_parent'),
2966 switch_parent=opts.get('switch_parent'),
2951 opts=patch.diffopts(ui, opts))
2967 opts=patch.diffopts(ui, opts))
2952
2968
2953 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2969 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2954 def forget(ui, repo, *pats, **opts):
2970 def forget(ui, repo, *pats, **opts):
2955 """forget the specified files on the next commit
2971 """forget the specified files on the next commit
2956
2972
2957 Mark the specified files so they will no longer be tracked
2973 Mark the specified files so they will no longer be tracked
2958 after the next commit.
2974 after the next commit.
2959
2975
2960 This only removes files from the current branch, not from the
2976 This only removes files from the current branch, not from the
2961 entire project history, and it does not delete them from the
2977 entire project history, and it does not delete them from the
2962 working directory.
2978 working directory.
2963
2979
2964 To undo a forget before the next commit, see :hg:`add`.
2980 To undo a forget before the next commit, see :hg:`add`.
2965
2981
2966 .. container:: verbose
2982 .. container:: verbose
2967
2983
2968 Examples:
2984 Examples:
2969
2985
2970 - forget newly-added binary files::
2986 - forget newly-added binary files::
2971
2987
2972 hg forget "set:added() and binary()"
2988 hg forget "set:added() and binary()"
2973
2989
2974 - forget files that would be excluded by .hgignore::
2990 - forget files that would be excluded by .hgignore::
2975
2991
2976 hg forget "set:hgignore()"
2992 hg forget "set:hgignore()"
2977
2993
2978 Returns 0 on success.
2994 Returns 0 on success.
2979 """
2995 """
2980
2996
2981 if not pats:
2997 if not pats:
2982 raise util.Abort(_('no files specified'))
2998 raise util.Abort(_('no files specified'))
2983
2999
2984 m = scmutil.match(repo[None], pats, opts)
3000 m = scmutil.match(repo[None], pats, opts)
2985 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3001 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2986 return rejected and 1 or 0
3002 return rejected and 1 or 0
2987
3003
2988 @command(
3004 @command(
2989 'graft',
3005 'graft',
2990 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3006 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2991 ('c', 'continue', False, _('resume interrupted graft')),
3007 ('c', 'continue', False, _('resume interrupted graft')),
2992 ('e', 'edit', False, _('invoke editor on commit messages')),
3008 ('e', 'edit', False, _('invoke editor on commit messages')),
2993 ('', 'log', None, _('append graft info to log message')),
3009 ('', 'log', None, _('append graft info to log message')),
2994 ('D', 'currentdate', False,
3010 ('D', 'currentdate', False,
2995 _('record the current date as commit date')),
3011 _('record the current date as commit date')),
2996 ('U', 'currentuser', False,
3012 ('U', 'currentuser', False,
2997 _('record the current user as committer'), _('DATE'))]
3013 _('record the current user as committer'), _('DATE'))]
2998 + commitopts2 + mergetoolopts + dryrunopts,
3014 + commitopts2 + mergetoolopts + dryrunopts,
2999 _('[OPTION]... [-r] REV...'))
3015 _('[OPTION]... [-r] REV...'))
3000 def graft(ui, repo, *revs, **opts):
3016 def graft(ui, repo, *revs, **opts):
3001 '''copy changes from other branches onto the current branch
3017 '''copy changes from other branches onto the current branch
3002
3018
3003 This command uses Mercurial's merge logic to copy individual
3019 This command uses Mercurial's merge logic to copy individual
3004 changes from other branches without merging branches in the
3020 changes from other branches without merging branches in the
3005 history graph. This is sometimes known as 'backporting' or
3021 history graph. This is sometimes known as 'backporting' or
3006 'cherry-picking'. By default, graft will copy user, date, and
3022 'cherry-picking'. By default, graft will copy user, date, and
3007 description from the source changesets.
3023 description from the source changesets.
3008
3024
3009 Changesets that are ancestors of the current revision, that have
3025 Changesets that are ancestors of the current revision, that have
3010 already been grafted, or that are merges will be skipped.
3026 already been grafted, or that are merges will be skipped.
3011
3027
3012 If --log is specified, log messages will have a comment appended
3028 If --log is specified, log messages will have a comment appended
3013 of the form::
3029 of the form::
3014
3030
3015 (grafted from CHANGESETHASH)
3031 (grafted from CHANGESETHASH)
3016
3032
3017 If a graft merge results in conflicts, the graft process is
3033 If a graft merge results in conflicts, the graft process is
3018 interrupted so that the current merge can be manually resolved.
3034 interrupted so that the current merge can be manually resolved.
3019 Once all conflicts are addressed, the graft process can be
3035 Once all conflicts are addressed, the graft process can be
3020 continued with the -c/--continue option.
3036 continued with the -c/--continue option.
3021
3037
3022 .. note::
3038 .. note::
3023
3039
3024 The -c/--continue option does not reapply earlier options.
3040 The -c/--continue option does not reapply earlier options.
3025
3041
3026 .. container:: verbose
3042 .. container:: verbose
3027
3043
3028 Examples:
3044 Examples:
3029
3045
3030 - copy a single change to the stable branch and edit its description::
3046 - copy a single change to the stable branch and edit its description::
3031
3047
3032 hg update stable
3048 hg update stable
3033 hg graft --edit 9393
3049 hg graft --edit 9393
3034
3050
3035 - graft a range of changesets with one exception, updating dates::
3051 - graft a range of changesets with one exception, updating dates::
3036
3052
3037 hg graft -D "2085::2093 and not 2091"
3053 hg graft -D "2085::2093 and not 2091"
3038
3054
3039 - continue a graft after resolving conflicts::
3055 - continue a graft after resolving conflicts::
3040
3056
3041 hg graft -c
3057 hg graft -c
3042
3058
3043 - show the source of a grafted changeset::
3059 - show the source of a grafted changeset::
3044
3060
3045 hg log --debug -r .
3061 hg log --debug -r .
3046
3062
3047 Returns 0 on successful completion.
3063 Returns 0 on successful completion.
3048 '''
3064 '''
3049
3065
3050 revs = list(revs)
3066 revs = list(revs)
3051 revs.extend(opts['rev'])
3067 revs.extend(opts['rev'])
3052
3068
3053 if not opts.get('user') and opts.get('currentuser'):
3069 if not opts.get('user') and opts.get('currentuser'):
3054 opts['user'] = ui.username()
3070 opts['user'] = ui.username()
3055 if not opts.get('date') and opts.get('currentdate'):
3071 if not opts.get('date') and opts.get('currentdate'):
3056 opts['date'] = "%d %d" % util.makedate()
3072 opts['date'] = "%d %d" % util.makedate()
3057
3073
3058 editor = None
3074 editor = None
3059 if opts.get('edit'):
3075 if opts.get('edit'):
3060 editor = cmdutil.commitforceeditor
3076 editor = cmdutil.commitforceeditor
3061
3077
3062 cont = False
3078 cont = False
3063 if opts['continue']:
3079 if opts['continue']:
3064 cont = True
3080 cont = True
3065 if revs:
3081 if revs:
3066 raise util.Abort(_("can't specify --continue and revisions"))
3082 raise util.Abort(_("can't specify --continue and revisions"))
3067 # read in unfinished revisions
3083 # read in unfinished revisions
3068 try:
3084 try:
3069 nodes = repo.opener.read('graftstate').splitlines()
3085 nodes = repo.opener.read('graftstate').splitlines()
3070 revs = [repo[node].rev() for node in nodes]
3086 revs = [repo[node].rev() for node in nodes]
3071 except IOError, inst:
3087 except IOError, inst:
3072 if inst.errno != errno.ENOENT:
3088 if inst.errno != errno.ENOENT:
3073 raise
3089 raise
3074 raise util.Abort(_("no graft state found, can't continue"))
3090 raise util.Abort(_("no graft state found, can't continue"))
3075 else:
3091 else:
3076 cmdutil.checkunfinished(repo)
3092 cmdutil.checkunfinished(repo)
3077 cmdutil.bailifchanged(repo)
3093 cmdutil.bailifchanged(repo)
3078 if not revs:
3094 if not revs:
3079 raise util.Abort(_('no revisions specified'))
3095 raise util.Abort(_('no revisions specified'))
3080 revs = scmutil.revrange(repo, revs)
3096 revs = scmutil.revrange(repo, revs)
3081
3097
3082 # check for merges
3098 # check for merges
3083 for rev in repo.revs('%ld and merge()', revs):
3099 for rev in repo.revs('%ld and merge()', revs):
3084 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3100 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3085 revs.remove(rev)
3101 revs.remove(rev)
3086 if not revs:
3102 if not revs:
3087 return -1
3103 return -1
3088
3104
3089 # check for ancestors of dest branch
3105 # check for ancestors of dest branch
3090 crev = repo['.'].rev()
3106 crev = repo['.'].rev()
3091 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3107 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3092 # don't mutate while iterating, create a copy
3108 # don't mutate while iterating, create a copy
3093 for rev in list(revs):
3109 for rev in list(revs):
3094 if rev in ancestors:
3110 if rev in ancestors:
3095 ui.warn(_('skipping ancestor revision %s\n') % rev)
3111 ui.warn(_('skipping ancestor revision %s\n') % rev)
3096 revs.remove(rev)
3112 revs.remove(rev)
3097 if not revs:
3113 if not revs:
3098 return -1
3114 return -1
3099
3115
3100 # analyze revs for earlier grafts
3116 # analyze revs for earlier grafts
3101 ids = {}
3117 ids = {}
3102 for ctx in repo.set("%ld", revs):
3118 for ctx in repo.set("%ld", revs):
3103 ids[ctx.hex()] = ctx.rev()
3119 ids[ctx.hex()] = ctx.rev()
3104 n = ctx.extra().get('source')
3120 n = ctx.extra().get('source')
3105 if n:
3121 if n:
3106 ids[n] = ctx.rev()
3122 ids[n] = ctx.rev()
3107
3123
3108 # check ancestors for earlier grafts
3124 # check ancestors for earlier grafts
3109 ui.debug('scanning for duplicate grafts\n')
3125 ui.debug('scanning for duplicate grafts\n')
3110
3126
3111 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3127 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3112 ctx = repo[rev]
3128 ctx = repo[rev]
3113 n = ctx.extra().get('source')
3129 n = ctx.extra().get('source')
3114 if n in ids:
3130 if n in ids:
3115 r = repo[n].rev()
3131 r = repo[n].rev()
3116 if r in revs:
3132 if r in revs:
3117 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3133 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3118 % (r, rev))
3134 % (r, rev))
3119 revs.remove(r)
3135 revs.remove(r)
3120 elif ids[n] in revs:
3136 elif ids[n] in revs:
3121 ui.warn(_('skipping already grafted revision %s '
3137 ui.warn(_('skipping already grafted revision %s '
3122 '(%s also has origin %d)\n') % (ids[n], rev, r))
3138 '(%s also has origin %d)\n') % (ids[n], rev, r))
3123 revs.remove(ids[n])
3139 revs.remove(ids[n])
3124 elif ctx.hex() in ids:
3140 elif ctx.hex() in ids:
3125 r = ids[ctx.hex()]
3141 r = ids[ctx.hex()]
3126 ui.warn(_('skipping already grafted revision %s '
3142 ui.warn(_('skipping already grafted revision %s '
3127 '(was grafted from %d)\n') % (r, rev))
3143 '(was grafted from %d)\n') % (r, rev))
3128 revs.remove(r)
3144 revs.remove(r)
3129 if not revs:
3145 if not revs:
3130 return -1
3146 return -1
3131
3147
3132 wlock = repo.wlock()
3148 wlock = repo.wlock()
3133 try:
3149 try:
3134 current = repo['.']
3150 current = repo['.']
3135 for pos, ctx in enumerate(repo.set("%ld", revs)):
3151 for pos, ctx in enumerate(repo.set("%ld", revs)):
3136
3152
3137 ui.status(_('grafting revision %s\n') % ctx.rev())
3153 ui.status(_('grafting revision %s\n') % ctx.rev())
3138 if opts.get('dry_run'):
3154 if opts.get('dry_run'):
3139 continue
3155 continue
3140
3156
3141 source = ctx.extra().get('source')
3157 source = ctx.extra().get('source')
3142 if not source:
3158 if not source:
3143 source = ctx.hex()
3159 source = ctx.hex()
3144 extra = {'source': source}
3160 extra = {'source': source}
3145 user = ctx.user()
3161 user = ctx.user()
3146 if opts.get('user'):
3162 if opts.get('user'):
3147 user = opts['user']
3163 user = opts['user']
3148 date = ctx.date()
3164 date = ctx.date()
3149 if opts.get('date'):
3165 if opts.get('date'):
3150 date = opts['date']
3166 date = opts['date']
3151 message = ctx.description()
3167 message = ctx.description()
3152 if opts.get('log'):
3168 if opts.get('log'):
3153 message += '\n(grafted from %s)' % ctx.hex()
3169 message += '\n(grafted from %s)' % ctx.hex()
3154
3170
3155 # we don't merge the first commit when continuing
3171 # we don't merge the first commit when continuing
3156 if not cont:
3172 if not cont:
3157 # perform the graft merge with p1(rev) as 'ancestor'
3173 # perform the graft merge with p1(rev) as 'ancestor'
3158 try:
3174 try:
3159 # ui.forcemerge is an internal variable, do not document
3175 # ui.forcemerge is an internal variable, do not document
3160 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3176 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3161 stats = mergemod.update(repo, ctx.node(), True, True, False,
3177 stats = mergemod.update(repo, ctx.node(), True, True, False,
3162 ctx.p1().node())
3178 ctx.p1().node())
3163 finally:
3179 finally:
3164 repo.ui.setconfig('ui', 'forcemerge', '')
3180 repo.ui.setconfig('ui', 'forcemerge', '')
3165 # report any conflicts
3181 # report any conflicts
3166 if stats and stats[3] > 0:
3182 if stats and stats[3] > 0:
3167 # write out state for --continue
3183 # write out state for --continue
3168 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3184 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3169 repo.opener.write('graftstate', ''.join(nodelines))
3185 repo.opener.write('graftstate', ''.join(nodelines))
3170 raise util.Abort(
3186 raise util.Abort(
3171 _("unresolved conflicts, can't continue"),
3187 _("unresolved conflicts, can't continue"),
3172 hint=_('use hg resolve and hg graft --continue'))
3188 hint=_('use hg resolve and hg graft --continue'))
3173 else:
3189 else:
3174 cont = False
3190 cont = False
3175
3191
3176 # drop the second merge parent
3192 # drop the second merge parent
3177 repo.setparents(current.node(), nullid)
3193 repo.setparents(current.node(), nullid)
3178 repo.dirstate.write()
3194 repo.dirstate.write()
3179 # fix up dirstate for copies and renames
3195 # fix up dirstate for copies and renames
3180 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3196 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3181
3197
3182 # commit
3198 # commit
3183 node = repo.commit(text=message, user=user,
3199 node = repo.commit(text=message, user=user,
3184 date=date, extra=extra, editor=editor)
3200 date=date, extra=extra, editor=editor)
3185 if node is None:
3201 if node is None:
3186 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3202 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3187 else:
3203 else:
3188 current = repo[node]
3204 current = repo[node]
3189 finally:
3205 finally:
3190 wlock.release()
3206 wlock.release()
3191
3207
3192 # remove state when we complete successfully
3208 # remove state when we complete successfully
3193 if not opts.get('dry_run'):
3209 if not opts.get('dry_run'):
3194 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3210 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3195
3211
3196 return 0
3212 return 0
3197
3213
3198 @command('grep',
3214 @command('grep',
3199 [('0', 'print0', None, _('end fields with NUL')),
3215 [('0', 'print0', None, _('end fields with NUL')),
3200 ('', 'all', None, _('print all revisions that match')),
3216 ('', 'all', None, _('print all revisions that match')),
3201 ('a', 'text', None, _('treat all files as text')),
3217 ('a', 'text', None, _('treat all files as text')),
3202 ('f', 'follow', None,
3218 ('f', 'follow', None,
3203 _('follow changeset history,'
3219 _('follow changeset history,'
3204 ' or file history across copies and renames')),
3220 ' or file history across copies and renames')),
3205 ('i', 'ignore-case', None, _('ignore case when matching')),
3221 ('i', 'ignore-case', None, _('ignore case when matching')),
3206 ('l', 'files-with-matches', None,
3222 ('l', 'files-with-matches', None,
3207 _('print only filenames and revisions that match')),
3223 _('print only filenames and revisions that match')),
3208 ('n', 'line-number', None, _('print matching line numbers')),
3224 ('n', 'line-number', None, _('print matching line numbers')),
3209 ('r', 'rev', [],
3225 ('r', 'rev', [],
3210 _('only search files changed within revision range'), _('REV')),
3226 _('only search files changed within revision range'), _('REV')),
3211 ('u', 'user', None, _('list the author (long with -v)')),
3227 ('u', 'user', None, _('list the author (long with -v)')),
3212 ('d', 'date', None, _('list the date (short with -q)')),
3228 ('d', 'date', None, _('list the date (short with -q)')),
3213 ] + walkopts,
3229 ] + walkopts,
3214 _('[OPTION]... PATTERN [FILE]...'))
3230 _('[OPTION]... PATTERN [FILE]...'))
3215 def grep(ui, repo, pattern, *pats, **opts):
3231 def grep(ui, repo, pattern, *pats, **opts):
3216 """search for a pattern in specified files and revisions
3232 """search for a pattern in specified files and revisions
3217
3233
3218 Search revisions of files for a regular expression.
3234 Search revisions of files for a regular expression.
3219
3235
3220 This command behaves differently than Unix grep. It only accepts
3236 This command behaves differently than Unix grep. It only accepts
3221 Python/Perl regexps. It searches repository history, not the
3237 Python/Perl regexps. It searches repository history, not the
3222 working directory. It always prints the revision number in which a
3238 working directory. It always prints the revision number in which a
3223 match appears.
3239 match appears.
3224
3240
3225 By default, grep only prints output for the first revision of a
3241 By default, grep only prints output for the first revision of a
3226 file in which it finds a match. To get it to print every revision
3242 file in which it finds a match. To get it to print every revision
3227 that contains a change in match status ("-" for a match that
3243 that contains a change in match status ("-" for a match that
3228 becomes a non-match, or "+" for a non-match that becomes a match),
3244 becomes a non-match, or "+" for a non-match that becomes a match),
3229 use the --all flag.
3245 use the --all flag.
3230
3246
3231 Returns 0 if a match is found, 1 otherwise.
3247 Returns 0 if a match is found, 1 otherwise.
3232 """
3248 """
3233 reflags = re.M
3249 reflags = re.M
3234 if opts.get('ignore_case'):
3250 if opts.get('ignore_case'):
3235 reflags |= re.I
3251 reflags |= re.I
3236 try:
3252 try:
3237 regexp = util.compilere(pattern, reflags)
3253 regexp = util.compilere(pattern, reflags)
3238 except re.error, inst:
3254 except re.error, inst:
3239 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3255 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3240 return 1
3256 return 1
3241 sep, eol = ':', '\n'
3257 sep, eol = ':', '\n'
3242 if opts.get('print0'):
3258 if opts.get('print0'):
3243 sep = eol = '\0'
3259 sep = eol = '\0'
3244
3260
3245 getfile = util.lrucachefunc(repo.file)
3261 getfile = util.lrucachefunc(repo.file)
3246
3262
3247 def matchlines(body):
3263 def matchlines(body):
3248 begin = 0
3264 begin = 0
3249 linenum = 0
3265 linenum = 0
3250 while begin < len(body):
3266 while begin < len(body):
3251 match = regexp.search(body, begin)
3267 match = regexp.search(body, begin)
3252 if not match:
3268 if not match:
3253 break
3269 break
3254 mstart, mend = match.span()
3270 mstart, mend = match.span()
3255 linenum += body.count('\n', begin, mstart) + 1
3271 linenum += body.count('\n', begin, mstart) + 1
3256 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3272 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3257 begin = body.find('\n', mend) + 1 or len(body) + 1
3273 begin = body.find('\n', mend) + 1 or len(body) + 1
3258 lend = begin - 1
3274 lend = begin - 1
3259 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3275 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3260
3276
3261 class linestate(object):
3277 class linestate(object):
3262 def __init__(self, line, linenum, colstart, colend):
3278 def __init__(self, line, linenum, colstart, colend):
3263 self.line = line
3279 self.line = line
3264 self.linenum = linenum
3280 self.linenum = linenum
3265 self.colstart = colstart
3281 self.colstart = colstart
3266 self.colend = colend
3282 self.colend = colend
3267
3283
3268 def __hash__(self):
3284 def __hash__(self):
3269 return hash((self.linenum, self.line))
3285 return hash((self.linenum, self.line))
3270
3286
3271 def __eq__(self, other):
3287 def __eq__(self, other):
3272 return self.line == other.line
3288 return self.line == other.line
3273
3289
3274 matches = {}
3290 matches = {}
3275 copies = {}
3291 copies = {}
3276 def grepbody(fn, rev, body):
3292 def grepbody(fn, rev, body):
3277 matches[rev].setdefault(fn, [])
3293 matches[rev].setdefault(fn, [])
3278 m = matches[rev][fn]
3294 m = matches[rev][fn]
3279 for lnum, cstart, cend, line in matchlines(body):
3295 for lnum, cstart, cend, line in matchlines(body):
3280 s = linestate(line, lnum, cstart, cend)
3296 s = linestate(line, lnum, cstart, cend)
3281 m.append(s)
3297 m.append(s)
3282
3298
3283 def difflinestates(a, b):
3299 def difflinestates(a, b):
3284 sm = difflib.SequenceMatcher(None, a, b)
3300 sm = difflib.SequenceMatcher(None, a, b)
3285 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3301 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3286 if tag == 'insert':
3302 if tag == 'insert':
3287 for i in xrange(blo, bhi):
3303 for i in xrange(blo, bhi):
3288 yield ('+', b[i])
3304 yield ('+', b[i])
3289 elif tag == 'delete':
3305 elif tag == 'delete':
3290 for i in xrange(alo, ahi):
3306 for i in xrange(alo, ahi):
3291 yield ('-', a[i])
3307 yield ('-', a[i])
3292 elif tag == 'replace':
3308 elif tag == 'replace':
3293 for i in xrange(alo, ahi):
3309 for i in xrange(alo, ahi):
3294 yield ('-', a[i])
3310 yield ('-', a[i])
3295 for i in xrange(blo, bhi):
3311 for i in xrange(blo, bhi):
3296 yield ('+', b[i])
3312 yield ('+', b[i])
3297
3313
3298 def display(fn, ctx, pstates, states):
3314 def display(fn, ctx, pstates, states):
3299 rev = ctx.rev()
3315 rev = ctx.rev()
3300 datefunc = ui.quiet and util.shortdate or util.datestr
3316 datefunc = ui.quiet and util.shortdate or util.datestr
3301 found = False
3317 found = False
3302 filerevmatches = {}
3318 filerevmatches = {}
3303 def binary():
3319 def binary():
3304 flog = getfile(fn)
3320 flog = getfile(fn)
3305 return util.binary(flog.read(ctx.filenode(fn)))
3321 return util.binary(flog.read(ctx.filenode(fn)))
3306
3322
3307 if opts.get('all'):
3323 if opts.get('all'):
3308 iter = difflinestates(pstates, states)
3324 iter = difflinestates(pstates, states)
3309 else:
3325 else:
3310 iter = [('', l) for l in states]
3326 iter = [('', l) for l in states]
3311 for change, l in iter:
3327 for change, l in iter:
3312 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3328 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3313 before, match, after = None, None, None
3329 before, match, after = None, None, None
3314
3330
3315 if opts.get('line_number'):
3331 if opts.get('line_number'):
3316 cols.append((str(l.linenum), 'grep.linenumber'))
3332 cols.append((str(l.linenum), 'grep.linenumber'))
3317 if opts.get('all'):
3333 if opts.get('all'):
3318 cols.append((change, 'grep.change'))
3334 cols.append((change, 'grep.change'))
3319 if opts.get('user'):
3335 if opts.get('user'):
3320 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3336 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3321 if opts.get('date'):
3337 if opts.get('date'):
3322 cols.append((datefunc(ctx.date()), 'grep.date'))
3338 cols.append((datefunc(ctx.date()), 'grep.date'))
3323 if opts.get('files_with_matches'):
3339 if opts.get('files_with_matches'):
3324 c = (fn, rev)
3340 c = (fn, rev)
3325 if c in filerevmatches:
3341 if c in filerevmatches:
3326 continue
3342 continue
3327 filerevmatches[c] = 1
3343 filerevmatches[c] = 1
3328 else:
3344 else:
3329 before = l.line[:l.colstart]
3345 before = l.line[:l.colstart]
3330 match = l.line[l.colstart:l.colend]
3346 match = l.line[l.colstart:l.colend]
3331 after = l.line[l.colend:]
3347 after = l.line[l.colend:]
3332 for col, label in cols[:-1]:
3348 for col, label in cols[:-1]:
3333 ui.write(col, label=label)
3349 ui.write(col, label=label)
3334 ui.write(sep, label='grep.sep')
3350 ui.write(sep, label='grep.sep')
3335 ui.write(cols[-1][0], label=cols[-1][1])
3351 ui.write(cols[-1][0], label=cols[-1][1])
3336 if before is not None:
3352 if before is not None:
3337 ui.write(sep, label='grep.sep')
3353 ui.write(sep, label='grep.sep')
3338 if not opts.get('text') and binary():
3354 if not opts.get('text') and binary():
3339 ui.write(" Binary file matches")
3355 ui.write(" Binary file matches")
3340 else:
3356 else:
3341 ui.write(before)
3357 ui.write(before)
3342 ui.write(match, label='grep.match')
3358 ui.write(match, label='grep.match')
3343 ui.write(after)
3359 ui.write(after)
3344 ui.write(eol)
3360 ui.write(eol)
3345 found = True
3361 found = True
3346 return found
3362 return found
3347
3363
3348 skip = {}
3364 skip = {}
3349 revfiles = {}
3365 revfiles = {}
3350 matchfn = scmutil.match(repo[None], pats, opts)
3366 matchfn = scmutil.match(repo[None], pats, opts)
3351 found = False
3367 found = False
3352 follow = opts.get('follow')
3368 follow = opts.get('follow')
3353
3369
3354 def prep(ctx, fns):
3370 def prep(ctx, fns):
3355 rev = ctx.rev()
3371 rev = ctx.rev()
3356 pctx = ctx.p1()
3372 pctx = ctx.p1()
3357 parent = pctx.rev()
3373 parent = pctx.rev()
3358 matches.setdefault(rev, {})
3374 matches.setdefault(rev, {})
3359 matches.setdefault(parent, {})
3375 matches.setdefault(parent, {})
3360 files = revfiles.setdefault(rev, [])
3376 files = revfiles.setdefault(rev, [])
3361 for fn in fns:
3377 for fn in fns:
3362 flog = getfile(fn)
3378 flog = getfile(fn)
3363 try:
3379 try:
3364 fnode = ctx.filenode(fn)
3380 fnode = ctx.filenode(fn)
3365 except error.LookupError:
3381 except error.LookupError:
3366 continue
3382 continue
3367
3383
3368 copied = flog.renamed(fnode)
3384 copied = flog.renamed(fnode)
3369 copy = follow and copied and copied[0]
3385 copy = follow and copied and copied[0]
3370 if copy:
3386 if copy:
3371 copies.setdefault(rev, {})[fn] = copy
3387 copies.setdefault(rev, {})[fn] = copy
3372 if fn in skip:
3388 if fn in skip:
3373 if copy:
3389 if copy:
3374 skip[copy] = True
3390 skip[copy] = True
3375 continue
3391 continue
3376 files.append(fn)
3392 files.append(fn)
3377
3393
3378 if fn not in matches[rev]:
3394 if fn not in matches[rev]:
3379 grepbody(fn, rev, flog.read(fnode))
3395 grepbody(fn, rev, flog.read(fnode))
3380
3396
3381 pfn = copy or fn
3397 pfn = copy or fn
3382 if pfn not in matches[parent]:
3398 if pfn not in matches[parent]:
3383 try:
3399 try:
3384 fnode = pctx.filenode(pfn)
3400 fnode = pctx.filenode(pfn)
3385 grepbody(pfn, parent, flog.read(fnode))
3401 grepbody(pfn, parent, flog.read(fnode))
3386 except error.LookupError:
3402 except error.LookupError:
3387 pass
3403 pass
3388
3404
3389 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3405 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3390 rev = ctx.rev()
3406 rev = ctx.rev()
3391 parent = ctx.p1().rev()
3407 parent = ctx.p1().rev()
3392 for fn in sorted(revfiles.get(rev, [])):
3408 for fn in sorted(revfiles.get(rev, [])):
3393 states = matches[rev][fn]
3409 states = matches[rev][fn]
3394 copy = copies.get(rev, {}).get(fn)
3410 copy = copies.get(rev, {}).get(fn)
3395 if fn in skip:
3411 if fn in skip:
3396 if copy:
3412 if copy:
3397 skip[copy] = True
3413 skip[copy] = True
3398 continue
3414 continue
3399 pstates = matches.get(parent, {}).get(copy or fn, [])
3415 pstates = matches.get(parent, {}).get(copy or fn, [])
3400 if pstates or states:
3416 if pstates or states:
3401 r = display(fn, ctx, pstates, states)
3417 r = display(fn, ctx, pstates, states)
3402 found = found or r
3418 found = found or r
3403 if r and not opts.get('all'):
3419 if r and not opts.get('all'):
3404 skip[fn] = True
3420 skip[fn] = True
3405 if copy:
3421 if copy:
3406 skip[copy] = True
3422 skip[copy] = True
3407 del matches[rev]
3423 del matches[rev]
3408 del revfiles[rev]
3424 del revfiles[rev]
3409
3425
3410 return not found
3426 return not found
3411
3427
3412 @command('heads',
3428 @command('heads',
3413 [('r', 'rev', '',
3429 [('r', 'rev', '',
3414 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3430 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3415 ('t', 'topo', False, _('show topological heads only')),
3431 ('t', 'topo', False, _('show topological heads only')),
3416 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3432 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3417 ('c', 'closed', False, _('show normal and closed branch heads')),
3433 ('c', 'closed', False, _('show normal and closed branch heads')),
3418 ] + templateopts,
3434 ] + templateopts,
3419 _('[-ct] [-r STARTREV] [REV]...'))
3435 _('[-ct] [-r STARTREV] [REV]...'))
3420 def heads(ui, repo, *branchrevs, **opts):
3436 def heads(ui, repo, *branchrevs, **opts):
3421 """show branch heads
3437 """show branch heads
3422
3438
3423 With no arguments, show all open branch heads in the repository.
3439 With no arguments, show all open branch heads in the repository.
3424 Branch heads are changesets that have no descendants on the
3440 Branch heads are changesets that have no descendants on the
3425 same branch. They are where development generally takes place and
3441 same branch. They are where development generally takes place and
3426 are the usual targets for update and merge operations.
3442 are the usual targets for update and merge operations.
3427
3443
3428 If one or more REVs are given, only open branch heads on the
3444 If one or more REVs are given, only open branch heads on the
3429 branches associated with the specified changesets are shown. This
3445 branches associated with the specified changesets are shown. This
3430 means that you can use :hg:`heads .` to see the heads on the
3446 means that you can use :hg:`heads .` to see the heads on the
3431 currently checked-out branch.
3447 currently checked-out branch.
3432
3448
3433 If -c/--closed is specified, also show branch heads marked closed
3449 If -c/--closed is specified, also show branch heads marked closed
3434 (see :hg:`commit --close-branch`).
3450 (see :hg:`commit --close-branch`).
3435
3451
3436 If STARTREV is specified, only those heads that are descendants of
3452 If STARTREV is specified, only those heads that are descendants of
3437 STARTREV will be displayed.
3453 STARTREV will be displayed.
3438
3454
3439 If -t/--topo is specified, named branch mechanics will be ignored and only
3455 If -t/--topo is specified, named branch mechanics will be ignored and only
3440 topological heads (changesets with no children) will be shown.
3456 topological heads (changesets with no children) will be shown.
3441
3457
3442 Returns 0 if matching heads are found, 1 if not.
3458 Returns 0 if matching heads are found, 1 if not.
3443 """
3459 """
3444
3460
3445 start = None
3461 start = None
3446 if 'rev' in opts:
3462 if 'rev' in opts:
3447 start = scmutil.revsingle(repo, opts['rev'], None).node()
3463 start = scmutil.revsingle(repo, opts['rev'], None).node()
3448
3464
3449 if opts.get('topo'):
3465 if opts.get('topo'):
3450 heads = [repo[h] for h in repo.heads(start)]
3466 heads = [repo[h] for h in repo.heads(start)]
3451 else:
3467 else:
3452 heads = []
3468 heads = []
3453 for branch in repo.branchmap():
3469 for branch in repo.branchmap():
3454 heads += repo.branchheads(branch, start, opts.get('closed'))
3470 heads += repo.branchheads(branch, start, opts.get('closed'))
3455 heads = [repo[h] for h in heads]
3471 heads = [repo[h] for h in heads]
3456
3472
3457 if branchrevs:
3473 if branchrevs:
3458 branches = set(repo[br].branch() for br in branchrevs)
3474 branches = set(repo[br].branch() for br in branchrevs)
3459 heads = [h for h in heads if h.branch() in branches]
3475 heads = [h for h in heads if h.branch() in branches]
3460
3476
3461 if opts.get('active') and branchrevs:
3477 if opts.get('active') and branchrevs:
3462 dagheads = repo.heads(start)
3478 dagheads = repo.heads(start)
3463 heads = [h for h in heads if h.node() in dagheads]
3479 heads = [h for h in heads if h.node() in dagheads]
3464
3480
3465 if branchrevs:
3481 if branchrevs:
3466 haveheads = set(h.branch() for h in heads)
3482 haveheads = set(h.branch() for h in heads)
3467 if branches - haveheads:
3483 if branches - haveheads:
3468 headless = ', '.join(b for b in branches - haveheads)
3484 headless = ', '.join(b for b in branches - haveheads)
3469 msg = _('no open branch heads found on branches %s')
3485 msg = _('no open branch heads found on branches %s')
3470 if opts.get('rev'):
3486 if opts.get('rev'):
3471 msg += _(' (started at %s)') % opts['rev']
3487 msg += _(' (started at %s)') % opts['rev']
3472 ui.warn((msg + '\n') % headless)
3488 ui.warn((msg + '\n') % headless)
3473
3489
3474 if not heads:
3490 if not heads:
3475 return 1
3491 return 1
3476
3492
3477 heads = sorted(heads, key=lambda x: -x.rev())
3493 heads = sorted(heads, key=lambda x: -x.rev())
3478 displayer = cmdutil.show_changeset(ui, repo, opts)
3494 displayer = cmdutil.show_changeset(ui, repo, opts)
3479 for ctx in heads:
3495 for ctx in heads:
3480 displayer.show(ctx)
3496 displayer.show(ctx)
3481 displayer.close()
3497 displayer.close()
3482
3498
3483 @command('help',
3499 @command('help',
3484 [('e', 'extension', None, _('show only help for extensions')),
3500 [('e', 'extension', None, _('show only help for extensions')),
3485 ('c', 'command', None, _('show only help for commands')),
3501 ('c', 'command', None, _('show only help for commands')),
3486 ('k', 'keyword', '', _('show topics matching keyword')),
3502 ('k', 'keyword', '', _('show topics matching keyword')),
3487 ],
3503 ],
3488 _('[-ec] [TOPIC]'))
3504 _('[-ec] [TOPIC]'))
3489 def help_(ui, name=None, **opts):
3505 def help_(ui, name=None, **opts):
3490 """show help for a given topic or a help overview
3506 """show help for a given topic or a help overview
3491
3507
3492 With no arguments, print a list of commands with short help messages.
3508 With no arguments, print a list of commands with short help messages.
3493
3509
3494 Given a topic, extension, or command name, print help for that
3510 Given a topic, extension, or command name, print help for that
3495 topic.
3511 topic.
3496
3512
3497 Returns 0 if successful.
3513 Returns 0 if successful.
3498 """
3514 """
3499
3515
3500 textwidth = min(ui.termwidth(), 80) - 2
3516 textwidth = min(ui.termwidth(), 80) - 2
3501
3517
3502 keep = ui.verbose and ['verbose'] or []
3518 keep = ui.verbose and ['verbose'] or []
3503 text = help.help_(ui, name, **opts)
3519 text = help.help_(ui, name, **opts)
3504
3520
3505 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3521 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3506 if 'verbose' in pruned:
3522 if 'verbose' in pruned:
3507 keep.append('omitted')
3523 keep.append('omitted')
3508 else:
3524 else:
3509 keep.append('notomitted')
3525 keep.append('notomitted')
3510 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3526 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3511 ui.write(formatted)
3527 ui.write(formatted)
3512
3528
3513
3529
3514 @command('identify|id',
3530 @command('identify|id',
3515 [('r', 'rev', '',
3531 [('r', 'rev', '',
3516 _('identify the specified revision'), _('REV')),
3532 _('identify the specified revision'), _('REV')),
3517 ('n', 'num', None, _('show local revision number')),
3533 ('n', 'num', None, _('show local revision number')),
3518 ('i', 'id', None, _('show global revision id')),
3534 ('i', 'id', None, _('show global revision id')),
3519 ('b', 'branch', None, _('show branch')),
3535 ('b', 'branch', None, _('show branch')),
3520 ('t', 'tags', None, _('show tags')),
3536 ('t', 'tags', None, _('show tags')),
3521 ('B', 'bookmarks', None, _('show bookmarks')),
3537 ('B', 'bookmarks', None, _('show bookmarks')),
3522 ] + remoteopts,
3538 ] + remoteopts,
3523 _('[-nibtB] [-r REV] [SOURCE]'))
3539 _('[-nibtB] [-r REV] [SOURCE]'))
3524 def identify(ui, repo, source=None, rev=None,
3540 def identify(ui, repo, source=None, rev=None,
3525 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3541 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3526 """identify the working copy or specified revision
3542 """identify the working copy or specified revision
3527
3543
3528 Print a summary identifying the repository state at REV using one or
3544 Print a summary identifying the repository state at REV using one or
3529 two parent hash identifiers, followed by a "+" if the working
3545 two parent hash identifiers, followed by a "+" if the working
3530 directory has uncommitted changes, the branch name (if not default),
3546 directory has uncommitted changes, the branch name (if not default),
3531 a list of tags, and a list of bookmarks.
3547 a list of tags, and a list of bookmarks.
3532
3548
3533 When REV is not given, print a summary of the current state of the
3549 When REV is not given, print a summary of the current state of the
3534 repository.
3550 repository.
3535
3551
3536 Specifying a path to a repository root or Mercurial bundle will
3552 Specifying a path to a repository root or Mercurial bundle will
3537 cause lookup to operate on that repository/bundle.
3553 cause lookup to operate on that repository/bundle.
3538
3554
3539 .. container:: verbose
3555 .. container:: verbose
3540
3556
3541 Examples:
3557 Examples:
3542
3558
3543 - generate a build identifier for the working directory::
3559 - generate a build identifier for the working directory::
3544
3560
3545 hg id --id > build-id.dat
3561 hg id --id > build-id.dat
3546
3562
3547 - find the revision corresponding to a tag::
3563 - find the revision corresponding to a tag::
3548
3564
3549 hg id -n -r 1.3
3565 hg id -n -r 1.3
3550
3566
3551 - check the most recent revision of a remote repository::
3567 - check the most recent revision of a remote repository::
3552
3568
3553 hg id -r tip http://selenic.com/hg/
3569 hg id -r tip http://selenic.com/hg/
3554
3570
3555 Returns 0 if successful.
3571 Returns 0 if successful.
3556 """
3572 """
3557
3573
3558 if not repo and not source:
3574 if not repo and not source:
3559 raise util.Abort(_("there is no Mercurial repository here "
3575 raise util.Abort(_("there is no Mercurial repository here "
3560 "(.hg not found)"))
3576 "(.hg not found)"))
3561
3577
3562 hexfunc = ui.debugflag and hex or short
3578 hexfunc = ui.debugflag and hex or short
3563 default = not (num or id or branch or tags or bookmarks)
3579 default = not (num or id or branch or tags or bookmarks)
3564 output = []
3580 output = []
3565 revs = []
3581 revs = []
3566
3582
3567 if source:
3583 if source:
3568 source, branches = hg.parseurl(ui.expandpath(source))
3584 source, branches = hg.parseurl(ui.expandpath(source))
3569 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3585 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3570 repo = peer.local()
3586 repo = peer.local()
3571 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3587 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3572
3588
3573 if not repo:
3589 if not repo:
3574 if num or branch or tags:
3590 if num or branch or tags:
3575 raise util.Abort(
3591 raise util.Abort(
3576 _("can't query remote revision number, branch, or tags"))
3592 _("can't query remote revision number, branch, or tags"))
3577 if not rev and revs:
3593 if not rev and revs:
3578 rev = revs[0]
3594 rev = revs[0]
3579 if not rev:
3595 if not rev:
3580 rev = "tip"
3596 rev = "tip"
3581
3597
3582 remoterev = peer.lookup(rev)
3598 remoterev = peer.lookup(rev)
3583 if default or id:
3599 if default or id:
3584 output = [hexfunc(remoterev)]
3600 output = [hexfunc(remoterev)]
3585
3601
3586 def getbms():
3602 def getbms():
3587 bms = []
3603 bms = []
3588
3604
3589 if 'bookmarks' in peer.listkeys('namespaces'):
3605 if 'bookmarks' in peer.listkeys('namespaces'):
3590 hexremoterev = hex(remoterev)
3606 hexremoterev = hex(remoterev)
3591 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3607 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3592 if bmr == hexremoterev]
3608 if bmr == hexremoterev]
3593
3609
3594 return sorted(bms)
3610 return sorted(bms)
3595
3611
3596 if bookmarks:
3612 if bookmarks:
3597 output.extend(getbms())
3613 output.extend(getbms())
3598 elif default and not ui.quiet:
3614 elif default and not ui.quiet:
3599 # multiple bookmarks for a single parent separated by '/'
3615 # multiple bookmarks for a single parent separated by '/'
3600 bm = '/'.join(getbms())
3616 bm = '/'.join(getbms())
3601 if bm:
3617 if bm:
3602 output.append(bm)
3618 output.append(bm)
3603 else:
3619 else:
3604 if not rev:
3620 if not rev:
3605 ctx = repo[None]
3621 ctx = repo[None]
3606 parents = ctx.parents()
3622 parents = ctx.parents()
3607 changed = ""
3623 changed = ""
3608 if default or id or num:
3624 if default or id or num:
3609 if (util.any(repo.status())
3625 if (util.any(repo.status())
3610 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3626 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3611 changed = '+'
3627 changed = '+'
3612 if default or id:
3628 if default or id:
3613 output = ["%s%s" %
3629 output = ["%s%s" %
3614 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3630 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3615 if num:
3631 if num:
3616 output.append("%s%s" %
3632 output.append("%s%s" %
3617 ('+'.join([str(p.rev()) for p in parents]), changed))
3633 ('+'.join([str(p.rev()) for p in parents]), changed))
3618 else:
3634 else:
3619 ctx = scmutil.revsingle(repo, rev)
3635 ctx = scmutil.revsingle(repo, rev)
3620 if default or id:
3636 if default or id:
3621 output = [hexfunc(ctx.node())]
3637 output = [hexfunc(ctx.node())]
3622 if num:
3638 if num:
3623 output.append(str(ctx.rev()))
3639 output.append(str(ctx.rev()))
3624
3640
3625 if default and not ui.quiet:
3641 if default and not ui.quiet:
3626 b = ctx.branch()
3642 b = ctx.branch()
3627 if b != 'default':
3643 if b != 'default':
3628 output.append("(%s)" % b)
3644 output.append("(%s)" % b)
3629
3645
3630 # multiple tags for a single parent separated by '/'
3646 # multiple tags for a single parent separated by '/'
3631 t = '/'.join(ctx.tags())
3647 t = '/'.join(ctx.tags())
3632 if t:
3648 if t:
3633 output.append(t)
3649 output.append(t)
3634
3650
3635 # multiple bookmarks for a single parent separated by '/'
3651 # multiple bookmarks for a single parent separated by '/'
3636 bm = '/'.join(ctx.bookmarks())
3652 bm = '/'.join(ctx.bookmarks())
3637 if bm:
3653 if bm:
3638 output.append(bm)
3654 output.append(bm)
3639 else:
3655 else:
3640 if branch:
3656 if branch:
3641 output.append(ctx.branch())
3657 output.append(ctx.branch())
3642
3658
3643 if tags:
3659 if tags:
3644 output.extend(ctx.tags())
3660 output.extend(ctx.tags())
3645
3661
3646 if bookmarks:
3662 if bookmarks:
3647 output.extend(ctx.bookmarks())
3663 output.extend(ctx.bookmarks())
3648
3664
3649 ui.write("%s\n" % ' '.join(output))
3665 ui.write("%s\n" % ' '.join(output))
3650
3666
3651 @command('import|patch',
3667 @command('import|patch',
3652 [('p', 'strip', 1,
3668 [('p', 'strip', 1,
3653 _('directory strip option for patch. This has the same '
3669 _('directory strip option for patch. This has the same '
3654 'meaning as the corresponding patch option'), _('NUM')),
3670 'meaning as the corresponding patch option'), _('NUM')),
3655 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3671 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3656 ('e', 'edit', False, _('invoke editor on commit messages')),
3672 ('e', 'edit', False, _('invoke editor on commit messages')),
3657 ('f', 'force', None,
3673 ('f', 'force', None,
3658 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3674 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3659 ('', 'no-commit', None,
3675 ('', 'no-commit', None,
3660 _("don't commit, just update the working directory")),
3676 _("don't commit, just update the working directory")),
3661 ('', 'bypass', None,
3677 ('', 'bypass', None,
3662 _("apply patch without touching the working directory")),
3678 _("apply patch without touching the working directory")),
3663 ('', 'exact', None,
3679 ('', 'exact', None,
3664 _('apply patch to the nodes from which it was generated')),
3680 _('apply patch to the nodes from which it was generated')),
3665 ('', 'import-branch', None,
3681 ('', 'import-branch', None,
3666 _('use any branch information in patch (implied by --exact)'))] +
3682 _('use any branch information in patch (implied by --exact)'))] +
3667 commitopts + commitopts2 + similarityopts,
3683 commitopts + commitopts2 + similarityopts,
3668 _('[OPTION]... PATCH...'))
3684 _('[OPTION]... PATCH...'))
3669 def import_(ui, repo, patch1=None, *patches, **opts):
3685 def import_(ui, repo, patch1=None, *patches, **opts):
3670 """import an ordered set of patches
3686 """import an ordered set of patches
3671
3687
3672 Import a list of patches and commit them individually (unless
3688 Import a list of patches and commit them individually (unless
3673 --no-commit is specified).
3689 --no-commit is specified).
3674
3690
3675 Because import first applies changes to the working directory,
3691 Because import first applies changes to the working directory,
3676 import will abort if there are outstanding changes.
3692 import will abort if there are outstanding changes.
3677
3693
3678 You can import a patch straight from a mail message. Even patches
3694 You can import a patch straight from a mail message. Even patches
3679 as attachments work (to use the body part, it must have type
3695 as attachments work (to use the body part, it must have type
3680 text/plain or text/x-patch). From and Subject headers of email
3696 text/plain or text/x-patch). From and Subject headers of email
3681 message are used as default committer and commit message. All
3697 message are used as default committer and commit message. All
3682 text/plain body parts before first diff are added to commit
3698 text/plain body parts before first diff are added to commit
3683 message.
3699 message.
3684
3700
3685 If the imported patch was generated by :hg:`export`, user and
3701 If the imported patch was generated by :hg:`export`, user and
3686 description from patch override values from message headers and
3702 description from patch override values from message headers and
3687 body. Values given on command line with -m/--message and -u/--user
3703 body. Values given on command line with -m/--message and -u/--user
3688 override these.
3704 override these.
3689
3705
3690 If --exact is specified, import will set the working directory to
3706 If --exact is specified, import will set the working directory to
3691 the parent of each patch before applying it, and will abort if the
3707 the parent of each patch before applying it, and will abort if the
3692 resulting changeset has a different ID than the one recorded in
3708 resulting changeset has a different ID than the one recorded in
3693 the patch. This may happen due to character set problems or other
3709 the patch. This may happen due to character set problems or other
3694 deficiencies in the text patch format.
3710 deficiencies in the text patch format.
3695
3711
3696 Use --bypass to apply and commit patches directly to the
3712 Use --bypass to apply and commit patches directly to the
3697 repository, not touching the working directory. Without --exact,
3713 repository, not touching the working directory. Without --exact,
3698 patches will be applied on top of the working directory parent
3714 patches will be applied on top of the working directory parent
3699 revision.
3715 revision.
3700
3716
3701 With -s/--similarity, hg will attempt to discover renames and
3717 With -s/--similarity, hg will attempt to discover renames and
3702 copies in the patch in the same way as :hg:`addremove`.
3718 copies in the patch in the same way as :hg:`addremove`.
3703
3719
3704 To read a patch from standard input, use "-" as the patch name. If
3720 To read a patch from standard input, use "-" as the patch name. If
3705 a URL is specified, the patch will be downloaded from it.
3721 a URL is specified, the patch will be downloaded from it.
3706 See :hg:`help dates` for a list of formats valid for -d/--date.
3722 See :hg:`help dates` for a list of formats valid for -d/--date.
3707
3723
3708 .. container:: verbose
3724 .. container:: verbose
3709
3725
3710 Examples:
3726 Examples:
3711
3727
3712 - import a traditional patch from a website and detect renames::
3728 - import a traditional patch from a website and detect renames::
3713
3729
3714 hg import -s 80 http://example.com/bugfix.patch
3730 hg import -s 80 http://example.com/bugfix.patch
3715
3731
3716 - import a changeset from an hgweb server::
3732 - import a changeset from an hgweb server::
3717
3733
3718 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3734 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3719
3735
3720 - import all the patches in an Unix-style mbox::
3736 - import all the patches in an Unix-style mbox::
3721
3737
3722 hg import incoming-patches.mbox
3738 hg import incoming-patches.mbox
3723
3739
3724 - attempt to exactly restore an exported changeset (not always
3740 - attempt to exactly restore an exported changeset (not always
3725 possible)::
3741 possible)::
3726
3742
3727 hg import --exact proposed-fix.patch
3743 hg import --exact proposed-fix.patch
3728
3744
3729 Returns 0 on success.
3745 Returns 0 on success.
3730 """
3746 """
3731
3747
3732 if not patch1:
3748 if not patch1:
3733 raise util.Abort(_('need at least one patch to import'))
3749 raise util.Abort(_('need at least one patch to import'))
3734
3750
3735 patches = (patch1,) + patches
3751 patches = (patch1,) + patches
3736
3752
3737 date = opts.get('date')
3753 date = opts.get('date')
3738 if date:
3754 if date:
3739 opts['date'] = util.parsedate(date)
3755 opts['date'] = util.parsedate(date)
3740
3756
3741 update = not opts.get('bypass')
3757 update = not opts.get('bypass')
3742 if not update and opts.get('no_commit'):
3758 if not update and opts.get('no_commit'):
3743 raise util.Abort(_('cannot use --no-commit with --bypass'))
3759 raise util.Abort(_('cannot use --no-commit with --bypass'))
3744 try:
3760 try:
3745 sim = float(opts.get('similarity') or 0)
3761 sim = float(opts.get('similarity') or 0)
3746 except ValueError:
3762 except ValueError:
3747 raise util.Abort(_('similarity must be a number'))
3763 raise util.Abort(_('similarity must be a number'))
3748 if sim < 0 or sim > 100:
3764 if sim < 0 or sim > 100:
3749 raise util.Abort(_('similarity must be between 0 and 100'))
3765 raise util.Abort(_('similarity must be between 0 and 100'))
3750 if sim and not update:
3766 if sim and not update:
3751 raise util.Abort(_('cannot use --similarity with --bypass'))
3767 raise util.Abort(_('cannot use --similarity with --bypass'))
3752
3768
3753 if update:
3769 if update:
3754 cmdutil.checkunfinished(repo)
3770 cmdutil.checkunfinished(repo)
3755 if (opts.get('exact') or not opts.get('force')) and update:
3771 if (opts.get('exact') or not opts.get('force')) and update:
3756 cmdutil.bailifchanged(repo)
3772 cmdutil.bailifchanged(repo)
3757
3773
3758 base = opts["base"]
3774 base = opts["base"]
3759 wlock = lock = tr = None
3775 wlock = lock = tr = None
3760 msgs = []
3776 msgs = []
3761
3777
3762
3778
3763 try:
3779 try:
3764 try:
3780 try:
3765 wlock = repo.wlock()
3781 wlock = repo.wlock()
3766 if not opts.get('no_commit'):
3782 if not opts.get('no_commit'):
3767 lock = repo.lock()
3783 lock = repo.lock()
3768 tr = repo.transaction('import')
3784 tr = repo.transaction('import')
3769 parents = repo.parents()
3785 parents = repo.parents()
3770 for patchurl in patches:
3786 for patchurl in patches:
3771 if patchurl == '-':
3787 if patchurl == '-':
3772 ui.status(_('applying patch from stdin\n'))
3788 ui.status(_('applying patch from stdin\n'))
3773 patchfile = ui.fin
3789 patchfile = ui.fin
3774 patchurl = 'stdin' # for error message
3790 patchurl = 'stdin' # for error message
3775 else:
3791 else:
3776 patchurl = os.path.join(base, patchurl)
3792 patchurl = os.path.join(base, patchurl)
3777 ui.status(_('applying %s\n') % patchurl)
3793 ui.status(_('applying %s\n') % patchurl)
3778 patchfile = hg.openpath(ui, patchurl)
3794 patchfile = hg.openpath(ui, patchurl)
3779
3795
3780 haspatch = False
3796 haspatch = False
3781 for hunk in patch.split(patchfile):
3797 for hunk in patch.split(patchfile):
3782 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3798 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3783 opts, msgs, hg.clean)
3799 opts, msgs, hg.clean)
3784 if msg:
3800 if msg:
3785 haspatch = True
3801 haspatch = True
3786 ui.note(msg + '\n')
3802 ui.note(msg + '\n')
3787 if update or opts.get('exact'):
3803 if update or opts.get('exact'):
3788 parents = repo.parents()
3804 parents = repo.parents()
3789 else:
3805 else:
3790 parents = [repo[node]]
3806 parents = [repo[node]]
3791
3807
3792 if not haspatch:
3808 if not haspatch:
3793 raise util.Abort(_('%s: no diffs found') % patchurl)
3809 raise util.Abort(_('%s: no diffs found') % patchurl)
3794
3810
3795 if tr:
3811 if tr:
3796 tr.close()
3812 tr.close()
3797 if msgs:
3813 if msgs:
3798 repo.savecommitmessage('\n* * *\n'.join(msgs))
3814 repo.savecommitmessage('\n* * *\n'.join(msgs))
3799 except: # re-raises
3815 except: # re-raises
3800 # wlock.release() indirectly calls dirstate.write(): since
3816 # wlock.release() indirectly calls dirstate.write(): since
3801 # we're crashing, we do not want to change the working dir
3817 # we're crashing, we do not want to change the working dir
3802 # parent after all, so make sure it writes nothing
3818 # parent after all, so make sure it writes nothing
3803 repo.dirstate.invalidate()
3819 repo.dirstate.invalidate()
3804 raise
3820 raise
3805 finally:
3821 finally:
3806 if tr:
3822 if tr:
3807 tr.release()
3823 tr.release()
3808 release(lock, wlock)
3824 release(lock, wlock)
3809
3825
3810 @command('incoming|in',
3826 @command('incoming|in',
3811 [('f', 'force', None,
3827 [('f', 'force', None,
3812 _('run even if remote repository is unrelated')),
3828 _('run even if remote repository is unrelated')),
3813 ('n', 'newest-first', None, _('show newest record first')),
3829 ('n', 'newest-first', None, _('show newest record first')),
3814 ('', 'bundle', '',
3830 ('', 'bundle', '',
3815 _('file to store the bundles into'), _('FILE')),
3831 _('file to store the bundles into'), _('FILE')),
3816 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3832 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3817 ('B', 'bookmarks', False, _("compare bookmarks")),
3833 ('B', 'bookmarks', False, _("compare bookmarks")),
3818 ('b', 'branch', [],
3834 ('b', 'branch', [],
3819 _('a specific branch you would like to pull'), _('BRANCH')),
3835 _('a specific branch you would like to pull'), _('BRANCH')),
3820 ] + logopts + remoteopts + subrepoopts,
3836 ] + logopts + remoteopts + subrepoopts,
3821 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3837 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3822 def incoming(ui, repo, source="default", **opts):
3838 def incoming(ui, repo, source="default", **opts):
3823 """show new changesets found in source
3839 """show new changesets found in source
3824
3840
3825 Show new changesets found in the specified path/URL or the default
3841 Show new changesets found in the specified path/URL or the default
3826 pull location. These are the changesets that would have been pulled
3842 pull location. These are the changesets that would have been pulled
3827 if a pull at the time you issued this command.
3843 if a pull at the time you issued this command.
3828
3844
3829 For remote repository, using --bundle avoids downloading the
3845 For remote repository, using --bundle avoids downloading the
3830 changesets twice if the incoming is followed by a pull.
3846 changesets twice if the incoming is followed by a pull.
3831
3847
3832 See pull for valid source format details.
3848 See pull for valid source format details.
3833
3849
3834 Returns 0 if there are incoming changes, 1 otherwise.
3850 Returns 0 if there are incoming changes, 1 otherwise.
3835 """
3851 """
3836 if opts.get('graph'):
3852 if opts.get('graph'):
3837 cmdutil.checkunsupportedgraphflags([], opts)
3853 cmdutil.checkunsupportedgraphflags([], opts)
3838 def display(other, chlist, displayer):
3854 def display(other, chlist, displayer):
3839 revdag = cmdutil.graphrevs(other, chlist, opts)
3855 revdag = cmdutil.graphrevs(other, chlist, opts)
3840 showparents = [ctx.node() for ctx in repo[None].parents()]
3856 showparents = [ctx.node() for ctx in repo[None].parents()]
3841 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3857 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3842 graphmod.asciiedges)
3858 graphmod.asciiedges)
3843
3859
3844 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3860 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3845 return 0
3861 return 0
3846
3862
3847 if opts.get('bundle') and opts.get('subrepos'):
3863 if opts.get('bundle') and opts.get('subrepos'):
3848 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3864 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3849
3865
3850 if opts.get('bookmarks'):
3866 if opts.get('bookmarks'):
3851 source, branches = hg.parseurl(ui.expandpath(source),
3867 source, branches = hg.parseurl(ui.expandpath(source),
3852 opts.get('branch'))
3868 opts.get('branch'))
3853 other = hg.peer(repo, opts, source)
3869 other = hg.peer(repo, opts, source)
3854 if 'bookmarks' not in other.listkeys('namespaces'):
3870 if 'bookmarks' not in other.listkeys('namespaces'):
3855 ui.warn(_("remote doesn't support bookmarks\n"))
3871 ui.warn(_("remote doesn't support bookmarks\n"))
3856 return 0
3872 return 0
3857 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3873 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3858 return bookmarks.diff(ui, repo, other)
3874 return bookmarks.diff(ui, repo, other)
3859
3875
3860 repo._subtoppath = ui.expandpath(source)
3876 repo._subtoppath = ui.expandpath(source)
3861 try:
3877 try:
3862 return hg.incoming(ui, repo, source, opts)
3878 return hg.incoming(ui, repo, source, opts)
3863 finally:
3879 finally:
3864 del repo._subtoppath
3880 del repo._subtoppath
3865
3881
3866
3882
3867 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3883 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3868 def init(ui, dest=".", **opts):
3884 def init(ui, dest=".", **opts):
3869 """create a new repository in the given directory
3885 """create a new repository in the given directory
3870
3886
3871 Initialize a new repository in the given directory. If the given
3887 Initialize a new repository in the given directory. If the given
3872 directory does not exist, it will be created.
3888 directory does not exist, it will be created.
3873
3889
3874 If no directory is given, the current directory is used.
3890 If no directory is given, the current directory is used.
3875
3891
3876 It is possible to specify an ``ssh://`` URL as the destination.
3892 It is possible to specify an ``ssh://`` URL as the destination.
3877 See :hg:`help urls` for more information.
3893 See :hg:`help urls` for more information.
3878
3894
3879 Returns 0 on success.
3895 Returns 0 on success.
3880 """
3896 """
3881 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3897 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3882
3898
3883 @command('locate',
3899 @command('locate',
3884 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3900 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3885 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3901 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3886 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3902 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3887 ] + walkopts,
3903 ] + walkopts,
3888 _('[OPTION]... [PATTERN]...'))
3904 _('[OPTION]... [PATTERN]...'))
3889 def locate(ui, repo, *pats, **opts):
3905 def locate(ui, repo, *pats, **opts):
3890 """locate files matching specific patterns
3906 """locate files matching specific patterns
3891
3907
3892 Print files under Mercurial control in the working directory whose
3908 Print files under Mercurial control in the working directory whose
3893 names match the given patterns.
3909 names match the given patterns.
3894
3910
3895 By default, this command searches all directories in the working
3911 By default, this command searches all directories in the working
3896 directory. To search just the current directory and its
3912 directory. To search just the current directory and its
3897 subdirectories, use "--include .".
3913 subdirectories, use "--include .".
3898
3914
3899 If no patterns are given to match, this command prints the names
3915 If no patterns are given to match, this command prints the names
3900 of all files under Mercurial control in the working directory.
3916 of all files under Mercurial control in the working directory.
3901
3917
3902 If you want to feed the output of this command into the "xargs"
3918 If you want to feed the output of this command into the "xargs"
3903 command, use the -0 option to both this command and "xargs". This
3919 command, use the -0 option to both this command and "xargs". This
3904 will avoid the problem of "xargs" treating single filenames that
3920 will avoid the problem of "xargs" treating single filenames that
3905 contain whitespace as multiple filenames.
3921 contain whitespace as multiple filenames.
3906
3922
3907 Returns 0 if a match is found, 1 otherwise.
3923 Returns 0 if a match is found, 1 otherwise.
3908 """
3924 """
3909 end = opts.get('print0') and '\0' or '\n'
3925 end = opts.get('print0') and '\0' or '\n'
3910 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3926 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3911
3927
3912 ret = 1
3928 ret = 1
3913 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3929 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3914 m.bad = lambda x, y: False
3930 m.bad = lambda x, y: False
3915 for abs in repo[rev].walk(m):
3931 for abs in repo[rev].walk(m):
3916 if not rev and abs not in repo.dirstate:
3932 if not rev and abs not in repo.dirstate:
3917 continue
3933 continue
3918 if opts.get('fullpath'):
3934 if opts.get('fullpath'):
3919 ui.write(repo.wjoin(abs), end)
3935 ui.write(repo.wjoin(abs), end)
3920 else:
3936 else:
3921 ui.write(((pats and m.rel(abs)) or abs), end)
3937 ui.write(((pats and m.rel(abs)) or abs), end)
3922 ret = 0
3938 ret = 0
3923
3939
3924 return ret
3940 return ret
3925
3941
3926 @command('^log|history',
3942 @command('^log|history',
3927 [('f', 'follow', None,
3943 [('f', 'follow', None,
3928 _('follow changeset history, or file history across copies and renames')),
3944 _('follow changeset history, or file history across copies and renames')),
3929 ('', 'follow-first', None,
3945 ('', 'follow-first', None,
3930 _('only follow the first parent of merge changesets (DEPRECATED)')),
3946 _('only follow the first parent of merge changesets (DEPRECATED)')),
3931 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3947 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3932 ('C', 'copies', None, _('show copied files')),
3948 ('C', 'copies', None, _('show copied files')),
3933 ('k', 'keyword', [],
3949 ('k', 'keyword', [],
3934 _('do case-insensitive search for a given text'), _('TEXT')),
3950 _('do case-insensitive search for a given text'), _('TEXT')),
3935 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3951 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3936 ('', 'removed', None, _('include revisions where files were removed')),
3952 ('', 'removed', None, _('include revisions where files were removed')),
3937 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3953 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3938 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3954 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3939 ('', 'only-branch', [],
3955 ('', 'only-branch', [],
3940 _('show only changesets within the given named branch (DEPRECATED)'),
3956 _('show only changesets within the given named branch (DEPRECATED)'),
3941 _('BRANCH')),
3957 _('BRANCH')),
3942 ('b', 'branch', [],
3958 ('b', 'branch', [],
3943 _('show changesets within the given named branch'), _('BRANCH')),
3959 _('show changesets within the given named branch'), _('BRANCH')),
3944 ('P', 'prune', [],
3960 ('P', 'prune', [],
3945 _('do not display revision or any of its ancestors'), _('REV')),
3961 _('do not display revision or any of its ancestors'), _('REV')),
3946 ] + logopts + walkopts,
3962 ] + logopts + walkopts,
3947 _('[OPTION]... [FILE]'))
3963 _('[OPTION]... [FILE]'))
3948 def log(ui, repo, *pats, **opts):
3964 def log(ui, repo, *pats, **opts):
3949 """show revision history of entire repository or files
3965 """show revision history of entire repository or files
3950
3966
3951 Print the revision history of the specified files or the entire
3967 Print the revision history of the specified files or the entire
3952 project.
3968 project.
3953
3969
3954 If no revision range is specified, the default is ``tip:0`` unless
3970 If no revision range is specified, the default is ``tip:0`` unless
3955 --follow is set, in which case the working directory parent is
3971 --follow is set, in which case the working directory parent is
3956 used as the starting revision.
3972 used as the starting revision.
3957
3973
3958 File history is shown without following rename or copy history of
3974 File history is shown without following rename or copy history of
3959 files. Use -f/--follow with a filename to follow history across
3975 files. Use -f/--follow with a filename to follow history across
3960 renames and copies. --follow without a filename will only show
3976 renames and copies. --follow without a filename will only show
3961 ancestors or descendants of the starting revision.
3977 ancestors or descendants of the starting revision.
3962
3978
3963 By default this command prints revision number and changeset id,
3979 By default this command prints revision number and changeset id,
3964 tags, non-trivial parents, user, date and time, and a summary for
3980 tags, non-trivial parents, user, date and time, and a summary for
3965 each commit. When the -v/--verbose switch is used, the list of
3981 each commit. When the -v/--verbose switch is used, the list of
3966 changed files and full commit message are shown.
3982 changed files and full commit message are shown.
3967
3983
3968 With --graph the revisions are shown as an ASCII art DAG with the most
3984 With --graph the revisions are shown as an ASCII art DAG with the most
3969 recent changeset at the top.
3985 recent changeset at the top.
3970 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3986 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3971 and '+' represents a fork where the changeset from the lines below is a
3987 and '+' represents a fork where the changeset from the lines below is a
3972 parent of the 'o' merge on the same same line.
3988 parent of the 'o' merge on the same same line.
3973
3989
3974 .. note::
3990 .. note::
3975
3991
3976 log -p/--patch may generate unexpected diff output for merge
3992 log -p/--patch may generate unexpected diff output for merge
3977 changesets, as it will only compare the merge changeset against
3993 changesets, as it will only compare the merge changeset against
3978 its first parent. Also, only files different from BOTH parents
3994 its first parent. Also, only files different from BOTH parents
3979 will appear in files:.
3995 will appear in files:.
3980
3996
3981 .. note::
3997 .. note::
3982
3998
3983 for performance reasons, log FILE may omit duplicate changes
3999 for performance reasons, log FILE may omit duplicate changes
3984 made on branches and will not show deletions. To see all
4000 made on branches and will not show deletions. To see all
3985 changes including duplicates and deletions, use the --removed
4001 changes including duplicates and deletions, use the --removed
3986 switch.
4002 switch.
3987
4003
3988 .. container:: verbose
4004 .. container:: verbose
3989
4005
3990 Some examples:
4006 Some examples:
3991
4007
3992 - changesets with full descriptions and file lists::
4008 - changesets with full descriptions and file lists::
3993
4009
3994 hg log -v
4010 hg log -v
3995
4011
3996 - changesets ancestral to the working directory::
4012 - changesets ancestral to the working directory::
3997
4013
3998 hg log -f
4014 hg log -f
3999
4015
4000 - last 10 commits on the current branch::
4016 - last 10 commits on the current branch::
4001
4017
4002 hg log -l 10 -b .
4018 hg log -l 10 -b .
4003
4019
4004 - changesets showing all modifications of a file, including removals::
4020 - changesets showing all modifications of a file, including removals::
4005
4021
4006 hg log --removed file.c
4022 hg log --removed file.c
4007
4023
4008 - all changesets that touch a directory, with diffs, excluding merges::
4024 - all changesets that touch a directory, with diffs, excluding merges::
4009
4025
4010 hg log -Mp lib/
4026 hg log -Mp lib/
4011
4027
4012 - all revision numbers that match a keyword::
4028 - all revision numbers that match a keyword::
4013
4029
4014 hg log -k bug --template "{rev}\\n"
4030 hg log -k bug --template "{rev}\\n"
4015
4031
4016 - check if a given changeset is included is a tagged release::
4032 - check if a given changeset is included is a tagged release::
4017
4033
4018 hg log -r "a21ccf and ancestor(1.9)"
4034 hg log -r "a21ccf and ancestor(1.9)"
4019
4035
4020 - find all changesets by some user in a date range::
4036 - find all changesets by some user in a date range::
4021
4037
4022 hg log -k alice -d "may 2008 to jul 2008"
4038 hg log -k alice -d "may 2008 to jul 2008"
4023
4039
4024 - summary of all changesets after the last tag::
4040 - summary of all changesets after the last tag::
4025
4041
4026 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4042 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4027
4043
4028 See :hg:`help dates` for a list of formats valid for -d/--date.
4044 See :hg:`help dates` for a list of formats valid for -d/--date.
4029
4045
4030 See :hg:`help revisions` and :hg:`help revsets` for more about
4046 See :hg:`help revisions` and :hg:`help revsets` for more about
4031 specifying revisions.
4047 specifying revisions.
4032
4048
4033 See :hg:`help templates` for more about pre-packaged styles and
4049 See :hg:`help templates` for more about pre-packaged styles and
4034 specifying custom templates.
4050 specifying custom templates.
4035
4051
4036 Returns 0 on success.
4052 Returns 0 on success.
4037 """
4053 """
4038 if opts.get('graph'):
4054 if opts.get('graph'):
4039 return cmdutil.graphlog(ui, repo, *pats, **opts)
4055 return cmdutil.graphlog(ui, repo, *pats, **opts)
4040
4056
4041 matchfn = scmutil.match(repo[None], pats, opts)
4057 matchfn = scmutil.match(repo[None], pats, opts)
4042 limit = cmdutil.loglimit(opts)
4058 limit = cmdutil.loglimit(opts)
4043 count = 0
4059 count = 0
4044
4060
4045 getrenamed, endrev = None, None
4061 getrenamed, endrev = None, None
4046 if opts.get('copies'):
4062 if opts.get('copies'):
4047 if opts.get('rev'):
4063 if opts.get('rev'):
4048 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4064 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4049 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4065 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4050
4066
4051 df = False
4067 df = False
4052 if opts.get("date"):
4068 if opts.get("date"):
4053 df = util.matchdate(opts["date"])
4069 df = util.matchdate(opts["date"])
4054
4070
4055 branches = opts.get('branch', []) + opts.get('only_branch', [])
4071 branches = opts.get('branch', []) + opts.get('only_branch', [])
4056 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4072 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4057
4073
4058 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4074 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4059 def prep(ctx, fns):
4075 def prep(ctx, fns):
4060 rev = ctx.rev()
4076 rev = ctx.rev()
4061 parents = [p for p in repo.changelog.parentrevs(rev)
4077 parents = [p for p in repo.changelog.parentrevs(rev)
4062 if p != nullrev]
4078 if p != nullrev]
4063 if opts.get('no_merges') and len(parents) == 2:
4079 if opts.get('no_merges') and len(parents) == 2:
4064 return
4080 return
4065 if opts.get('only_merges') and len(parents) != 2:
4081 if opts.get('only_merges') and len(parents) != 2:
4066 return
4082 return
4067 if opts.get('branch') and ctx.branch() not in opts['branch']:
4083 if opts.get('branch') and ctx.branch() not in opts['branch']:
4068 return
4084 return
4069 if df and not df(ctx.date()[0]):
4085 if df and not df(ctx.date()[0]):
4070 return
4086 return
4071
4087
4072 lower = encoding.lower
4088 lower = encoding.lower
4073 if opts.get('user'):
4089 if opts.get('user'):
4074 luser = lower(ctx.user())
4090 luser = lower(ctx.user())
4075 for k in [lower(x) for x in opts['user']]:
4091 for k in [lower(x) for x in opts['user']]:
4076 if (k in luser):
4092 if (k in luser):
4077 break
4093 break
4078 else:
4094 else:
4079 return
4095 return
4080 if opts.get('keyword'):
4096 if opts.get('keyword'):
4081 luser = lower(ctx.user())
4097 luser = lower(ctx.user())
4082 ldesc = lower(ctx.description())
4098 ldesc = lower(ctx.description())
4083 lfiles = lower(" ".join(ctx.files()))
4099 lfiles = lower(" ".join(ctx.files()))
4084 for k in [lower(x) for x in opts['keyword']]:
4100 for k in [lower(x) for x in opts['keyword']]:
4085 if (k in luser or k in ldesc or k in lfiles):
4101 if (k in luser or k in ldesc or k in lfiles):
4086 break
4102 break
4087 else:
4103 else:
4088 return
4104 return
4089
4105
4090 copies = None
4106 copies = None
4091 if getrenamed is not None and rev:
4107 if getrenamed is not None and rev:
4092 copies = []
4108 copies = []
4093 for fn in ctx.files():
4109 for fn in ctx.files():
4094 rename = getrenamed(fn, rev)
4110 rename = getrenamed(fn, rev)
4095 if rename:
4111 if rename:
4096 copies.append((fn, rename[0]))
4112 copies.append((fn, rename[0]))
4097
4113
4098 revmatchfn = None
4114 revmatchfn = None
4099 if opts.get('patch') or opts.get('stat'):
4115 if opts.get('patch') or opts.get('stat'):
4100 if opts.get('follow') or opts.get('follow_first'):
4116 if opts.get('follow') or opts.get('follow_first'):
4101 # note: this might be wrong when following through merges
4117 # note: this might be wrong when following through merges
4102 revmatchfn = scmutil.match(repo[None], fns, default='path')
4118 revmatchfn = scmutil.match(repo[None], fns, default='path')
4103 else:
4119 else:
4104 revmatchfn = matchfn
4120 revmatchfn = matchfn
4105
4121
4106 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4122 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4107
4123
4108 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4124 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4109 if displayer.flush(ctx.rev()):
4125 if displayer.flush(ctx.rev()):
4110 count += 1
4126 count += 1
4111 if count == limit:
4127 if count == limit:
4112 break
4128 break
4113 displayer.close()
4129 displayer.close()
4114
4130
4115 @command('manifest',
4131 @command('manifest',
4116 [('r', 'rev', '', _('revision to display'), _('REV')),
4132 [('r', 'rev', '', _('revision to display'), _('REV')),
4117 ('', 'all', False, _("list files from all revisions"))],
4133 ('', 'all', False, _("list files from all revisions"))],
4118 _('[-r REV]'))
4134 _('[-r REV]'))
4119 def manifest(ui, repo, node=None, rev=None, **opts):
4135 def manifest(ui, repo, node=None, rev=None, **opts):
4120 """output the current or given revision of the project manifest
4136 """output the current or given revision of the project manifest
4121
4137
4122 Print a list of version controlled files for the given revision.
4138 Print a list of version controlled files for the given revision.
4123 If no revision is given, the first parent of the working directory
4139 If no revision is given, the first parent of the working directory
4124 is used, or the null revision if no revision is checked out.
4140 is used, or the null revision if no revision is checked out.
4125
4141
4126 With -v, print file permissions, symlink and executable bits.
4142 With -v, print file permissions, symlink and executable bits.
4127 With --debug, print file revision hashes.
4143 With --debug, print file revision hashes.
4128
4144
4129 If option --all is specified, the list of all files from all revisions
4145 If option --all is specified, the list of all files from all revisions
4130 is printed. This includes deleted and renamed files.
4146 is printed. This includes deleted and renamed files.
4131
4147
4132 Returns 0 on success.
4148 Returns 0 on success.
4133 """
4149 """
4134
4150
4135 fm = ui.formatter('manifest', opts)
4151 fm = ui.formatter('manifest', opts)
4136
4152
4137 if opts.get('all'):
4153 if opts.get('all'):
4138 if rev or node:
4154 if rev or node:
4139 raise util.Abort(_("can't specify a revision with --all"))
4155 raise util.Abort(_("can't specify a revision with --all"))
4140
4156
4141 res = []
4157 res = []
4142 prefix = "data/"
4158 prefix = "data/"
4143 suffix = ".i"
4159 suffix = ".i"
4144 plen = len(prefix)
4160 plen = len(prefix)
4145 slen = len(suffix)
4161 slen = len(suffix)
4146 lock = repo.lock()
4162 lock = repo.lock()
4147 try:
4163 try:
4148 for fn, b, size in repo.store.datafiles():
4164 for fn, b, size in repo.store.datafiles():
4149 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4165 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4150 res.append(fn[plen:-slen])
4166 res.append(fn[plen:-slen])
4151 finally:
4167 finally:
4152 lock.release()
4168 lock.release()
4153 for f in res:
4169 for f in res:
4154 fm.startitem()
4170 fm.startitem()
4155 fm.write("path", '%s\n', f)
4171 fm.write("path", '%s\n', f)
4156 fm.end()
4172 fm.end()
4157 return
4173 return
4158
4174
4159 if rev and node:
4175 if rev and node:
4160 raise util.Abort(_("please specify just one revision"))
4176 raise util.Abort(_("please specify just one revision"))
4161
4177
4162 if not node:
4178 if not node:
4163 node = rev
4179 node = rev
4164
4180
4165 char = {'l': '@', 'x': '*', '': ''}
4181 char = {'l': '@', 'x': '*', '': ''}
4166 mode = {'l': '644', 'x': '755', '': '644'}
4182 mode = {'l': '644', 'x': '755', '': '644'}
4167 ctx = scmutil.revsingle(repo, node)
4183 ctx = scmutil.revsingle(repo, node)
4168 mf = ctx.manifest()
4184 mf = ctx.manifest()
4169 for f in ctx:
4185 for f in ctx:
4170 fm.startitem()
4186 fm.startitem()
4171 fl = ctx[f].flags()
4187 fl = ctx[f].flags()
4172 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4188 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4173 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4189 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4174 fm.write('path', '%s\n', f)
4190 fm.write('path', '%s\n', f)
4175 fm.end()
4191 fm.end()
4176
4192
4177 @command('^merge',
4193 @command('^merge',
4178 [('f', 'force', None,
4194 [('f', 'force', None,
4179 _('force a merge including outstanding changes (DEPRECATED)')),
4195 _('force a merge including outstanding changes (DEPRECATED)')),
4180 ('r', 'rev', '', _('revision to merge'), _('REV')),
4196 ('r', 'rev', '', _('revision to merge'), _('REV')),
4181 ('P', 'preview', None,
4197 ('P', 'preview', None,
4182 _('review revisions to merge (no merge is performed)'))
4198 _('review revisions to merge (no merge is performed)'))
4183 ] + mergetoolopts,
4199 ] + mergetoolopts,
4184 _('[-P] [-f] [[-r] REV]'))
4200 _('[-P] [-f] [[-r] REV]'))
4185 def merge(ui, repo, node=None, **opts):
4201 def merge(ui, repo, node=None, **opts):
4186 """merge working directory with another revision
4202 """merge working directory with another revision
4187
4203
4188 The current working directory is updated with all changes made in
4204 The current working directory is updated with all changes made in
4189 the requested revision since the last common predecessor revision.
4205 the requested revision since the last common predecessor revision.
4190
4206
4191 Files that changed between either parent are marked as changed for
4207 Files that changed between either parent are marked as changed for
4192 the next commit and a commit must be performed before any further
4208 the next commit and a commit must be performed before any further
4193 updates to the repository are allowed. The next commit will have
4209 updates to the repository are allowed. The next commit will have
4194 two parents.
4210 two parents.
4195
4211
4196 ``--tool`` can be used to specify the merge tool used for file
4212 ``--tool`` can be used to specify the merge tool used for file
4197 merges. It overrides the HGMERGE environment variable and your
4213 merges. It overrides the HGMERGE environment variable and your
4198 configuration files. See :hg:`help merge-tools` for options.
4214 configuration files. See :hg:`help merge-tools` for options.
4199
4215
4200 If no revision is specified, the working directory's parent is a
4216 If no revision is specified, the working directory's parent is a
4201 head revision, and the current branch contains exactly one other
4217 head revision, and the current branch contains exactly one other
4202 head, the other head is merged with by default. Otherwise, an
4218 head, the other head is merged with by default. Otherwise, an
4203 explicit revision with which to merge with must be provided.
4219 explicit revision with which to merge with must be provided.
4204
4220
4205 :hg:`resolve` must be used to resolve unresolved files.
4221 :hg:`resolve` must be used to resolve unresolved files.
4206
4222
4207 To undo an uncommitted merge, use :hg:`update --clean .` which
4223 To undo an uncommitted merge, use :hg:`update --clean .` which
4208 will check out a clean copy of the original merge parent, losing
4224 will check out a clean copy of the original merge parent, losing
4209 all changes.
4225 all changes.
4210
4226
4211 Returns 0 on success, 1 if there are unresolved files.
4227 Returns 0 on success, 1 if there are unresolved files.
4212 """
4228 """
4213
4229
4214 if opts.get('rev') and node:
4230 if opts.get('rev') and node:
4215 raise util.Abort(_("please specify just one revision"))
4231 raise util.Abort(_("please specify just one revision"))
4216 if not node:
4232 if not node:
4217 node = opts.get('rev')
4233 node = opts.get('rev')
4218
4234
4219 if node:
4235 if node:
4220 node = scmutil.revsingle(repo, node).node()
4236 node = scmutil.revsingle(repo, node).node()
4221
4237
4222 if not node and repo._bookmarkcurrent:
4238 if not node and repo._bookmarkcurrent:
4223 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4239 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4224 curhead = repo[repo._bookmarkcurrent].node()
4240 curhead = repo[repo._bookmarkcurrent].node()
4225 if len(bmheads) == 2:
4241 if len(bmheads) == 2:
4226 if curhead == bmheads[0]:
4242 if curhead == bmheads[0]:
4227 node = bmheads[1]
4243 node = bmheads[1]
4228 else:
4244 else:
4229 node = bmheads[0]
4245 node = bmheads[0]
4230 elif len(bmheads) > 2:
4246 elif len(bmheads) > 2:
4231 raise util.Abort(_("multiple matching bookmarks to merge - "
4247 raise util.Abort(_("multiple matching bookmarks to merge - "
4232 "please merge with an explicit rev or bookmark"),
4248 "please merge with an explicit rev or bookmark"),
4233 hint=_("run 'hg heads' to see all heads"))
4249 hint=_("run 'hg heads' to see all heads"))
4234 elif len(bmheads) <= 1:
4250 elif len(bmheads) <= 1:
4235 raise util.Abort(_("no matching bookmark to merge - "
4251 raise util.Abort(_("no matching bookmark to merge - "
4236 "please merge with an explicit rev or bookmark"),
4252 "please merge with an explicit rev or bookmark"),
4237 hint=_("run 'hg heads' to see all heads"))
4253 hint=_("run 'hg heads' to see all heads"))
4238
4254
4239 if not node and not repo._bookmarkcurrent:
4255 if not node and not repo._bookmarkcurrent:
4240 branch = repo[None].branch()
4256 branch = repo[None].branch()
4241 bheads = repo.branchheads(branch)
4257 bheads = repo.branchheads(branch)
4242 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4258 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4243
4259
4244 if len(nbhs) > 2:
4260 if len(nbhs) > 2:
4245 raise util.Abort(_("branch '%s' has %d heads - "
4261 raise util.Abort(_("branch '%s' has %d heads - "
4246 "please merge with an explicit rev")
4262 "please merge with an explicit rev")
4247 % (branch, len(bheads)),
4263 % (branch, len(bheads)),
4248 hint=_("run 'hg heads .' to see heads"))
4264 hint=_("run 'hg heads .' to see heads"))
4249
4265
4250 parent = repo.dirstate.p1()
4266 parent = repo.dirstate.p1()
4251 if len(nbhs) <= 1:
4267 if len(nbhs) <= 1:
4252 if len(bheads) > 1:
4268 if len(bheads) > 1:
4253 raise util.Abort(_("heads are bookmarked - "
4269 raise util.Abort(_("heads are bookmarked - "
4254 "please merge with an explicit rev"),
4270 "please merge with an explicit rev"),
4255 hint=_("run 'hg heads' to see all heads"))
4271 hint=_("run 'hg heads' to see all heads"))
4256 if len(repo.heads()) > 1:
4272 if len(repo.heads()) > 1:
4257 raise util.Abort(_("branch '%s' has one head - "
4273 raise util.Abort(_("branch '%s' has one head - "
4258 "please merge with an explicit rev")
4274 "please merge with an explicit rev")
4259 % branch,
4275 % branch,
4260 hint=_("run 'hg heads' to see all heads"))
4276 hint=_("run 'hg heads' to see all heads"))
4261 msg, hint = _('nothing to merge'), None
4277 msg, hint = _('nothing to merge'), None
4262 if parent != repo.lookup(branch):
4278 if parent != repo.lookup(branch):
4263 hint = _("use 'hg update' instead")
4279 hint = _("use 'hg update' instead")
4264 raise util.Abort(msg, hint=hint)
4280 raise util.Abort(msg, hint=hint)
4265
4281
4266 if parent not in bheads:
4282 if parent not in bheads:
4267 raise util.Abort(_('working directory not at a head revision'),
4283 raise util.Abort(_('working directory not at a head revision'),
4268 hint=_("use 'hg update' or merge with an "
4284 hint=_("use 'hg update' or merge with an "
4269 "explicit revision"))
4285 "explicit revision"))
4270 if parent == nbhs[0]:
4286 if parent == nbhs[0]:
4271 node = nbhs[-1]
4287 node = nbhs[-1]
4272 else:
4288 else:
4273 node = nbhs[0]
4289 node = nbhs[0]
4274
4290
4275 if opts.get('preview'):
4291 if opts.get('preview'):
4276 # find nodes that are ancestors of p2 but not of p1
4292 # find nodes that are ancestors of p2 but not of p1
4277 p1 = repo.lookup('.')
4293 p1 = repo.lookup('.')
4278 p2 = repo.lookup(node)
4294 p2 = repo.lookup(node)
4279 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4295 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4280
4296
4281 displayer = cmdutil.show_changeset(ui, repo, opts)
4297 displayer = cmdutil.show_changeset(ui, repo, opts)
4282 for node in nodes:
4298 for node in nodes:
4283 displayer.show(repo[node])
4299 displayer.show(repo[node])
4284 displayer.close()
4300 displayer.close()
4285 return 0
4301 return 0
4286
4302
4287 try:
4303 try:
4288 # ui.forcemerge is an internal variable, do not document
4304 # ui.forcemerge is an internal variable, do not document
4289 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4305 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4290 return hg.merge(repo, node, force=opts.get('force'))
4306 return hg.merge(repo, node, force=opts.get('force'))
4291 finally:
4307 finally:
4292 ui.setconfig('ui', 'forcemerge', '')
4308 ui.setconfig('ui', 'forcemerge', '')
4293
4309
4294 @command('outgoing|out',
4310 @command('outgoing|out',
4295 [('f', 'force', None, _('run even when the destination is unrelated')),
4311 [('f', 'force', None, _('run even when the destination is unrelated')),
4296 ('r', 'rev', [],
4312 ('r', 'rev', [],
4297 _('a changeset intended to be included in the destination'), _('REV')),
4313 _('a changeset intended to be included in the destination'), _('REV')),
4298 ('n', 'newest-first', None, _('show newest record first')),
4314 ('n', 'newest-first', None, _('show newest record first')),
4299 ('B', 'bookmarks', False, _('compare bookmarks')),
4315 ('B', 'bookmarks', False, _('compare bookmarks')),
4300 ('b', 'branch', [], _('a specific branch you would like to push'),
4316 ('b', 'branch', [], _('a specific branch you would like to push'),
4301 _('BRANCH')),
4317 _('BRANCH')),
4302 ] + logopts + remoteopts + subrepoopts,
4318 ] + logopts + remoteopts + subrepoopts,
4303 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4319 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4304 def outgoing(ui, repo, dest=None, **opts):
4320 def outgoing(ui, repo, dest=None, **opts):
4305 """show changesets not found in the destination
4321 """show changesets not found in the destination
4306
4322
4307 Show changesets not found in the specified destination repository
4323 Show changesets not found in the specified destination repository
4308 or the default push location. These are the changesets that would
4324 or the default push location. These are the changesets that would
4309 be pushed if a push was requested.
4325 be pushed if a push was requested.
4310
4326
4311 See pull for details of valid destination formats.
4327 See pull for details of valid destination formats.
4312
4328
4313 Returns 0 if there are outgoing changes, 1 otherwise.
4329 Returns 0 if there are outgoing changes, 1 otherwise.
4314 """
4330 """
4315 if opts.get('graph'):
4331 if opts.get('graph'):
4316 cmdutil.checkunsupportedgraphflags([], opts)
4332 cmdutil.checkunsupportedgraphflags([], opts)
4317 o = hg._outgoing(ui, repo, dest, opts)
4333 o = hg._outgoing(ui, repo, dest, opts)
4318 if o is None:
4334 if o is None:
4319 return
4335 return
4320
4336
4321 revdag = cmdutil.graphrevs(repo, o, opts)
4337 revdag = cmdutil.graphrevs(repo, o, opts)
4322 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4338 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4323 showparents = [ctx.node() for ctx in repo[None].parents()]
4339 showparents = [ctx.node() for ctx in repo[None].parents()]
4324 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4340 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4325 graphmod.asciiedges)
4341 graphmod.asciiedges)
4326 return 0
4342 return 0
4327
4343
4328 if opts.get('bookmarks'):
4344 if opts.get('bookmarks'):
4329 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4345 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4330 dest, branches = hg.parseurl(dest, opts.get('branch'))
4346 dest, branches = hg.parseurl(dest, opts.get('branch'))
4331 other = hg.peer(repo, opts, dest)
4347 other = hg.peer(repo, opts, dest)
4332 if 'bookmarks' not in other.listkeys('namespaces'):
4348 if 'bookmarks' not in other.listkeys('namespaces'):
4333 ui.warn(_("remote doesn't support bookmarks\n"))
4349 ui.warn(_("remote doesn't support bookmarks\n"))
4334 return 0
4350 return 0
4335 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4351 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4336 return bookmarks.diff(ui, other, repo)
4352 return bookmarks.diff(ui, other, repo)
4337
4353
4338 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4354 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4339 try:
4355 try:
4340 return hg.outgoing(ui, repo, dest, opts)
4356 return hg.outgoing(ui, repo, dest, opts)
4341 finally:
4357 finally:
4342 del repo._subtoppath
4358 del repo._subtoppath
4343
4359
4344 @command('parents',
4360 @command('parents',
4345 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4361 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4346 ] + templateopts,
4362 ] + templateopts,
4347 _('[-r REV] [FILE]'))
4363 _('[-r REV] [FILE]'))
4348 def parents(ui, repo, file_=None, **opts):
4364 def parents(ui, repo, file_=None, **opts):
4349 """show the parents of the working directory or revision
4365 """show the parents of the working directory or revision
4350
4366
4351 Print the working directory's parent revisions. If a revision is
4367 Print the working directory's parent revisions. If a revision is
4352 given via -r/--rev, the parent of that revision will be printed.
4368 given via -r/--rev, the parent of that revision will be printed.
4353 If a file argument is given, the revision in which the file was
4369 If a file argument is given, the revision in which the file was
4354 last changed (before the working directory revision or the
4370 last changed (before the working directory revision or the
4355 argument to --rev if given) is printed.
4371 argument to --rev if given) is printed.
4356
4372
4357 Returns 0 on success.
4373 Returns 0 on success.
4358 """
4374 """
4359
4375
4360 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4376 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4361
4377
4362 if file_:
4378 if file_:
4363 m = scmutil.match(ctx, (file_,), opts)
4379 m = scmutil.match(ctx, (file_,), opts)
4364 if m.anypats() or len(m.files()) != 1:
4380 if m.anypats() or len(m.files()) != 1:
4365 raise util.Abort(_('can only specify an explicit filename'))
4381 raise util.Abort(_('can only specify an explicit filename'))
4366 file_ = m.files()[0]
4382 file_ = m.files()[0]
4367 filenodes = []
4383 filenodes = []
4368 for cp in ctx.parents():
4384 for cp in ctx.parents():
4369 if not cp:
4385 if not cp:
4370 continue
4386 continue
4371 try:
4387 try:
4372 filenodes.append(cp.filenode(file_))
4388 filenodes.append(cp.filenode(file_))
4373 except error.LookupError:
4389 except error.LookupError:
4374 pass
4390 pass
4375 if not filenodes:
4391 if not filenodes:
4376 raise util.Abort(_("'%s' not found in manifest!") % file_)
4392 raise util.Abort(_("'%s' not found in manifest!") % file_)
4377 p = []
4393 p = []
4378 for fn in filenodes:
4394 for fn in filenodes:
4379 fctx = repo.filectx(file_, fileid=fn)
4395 fctx = repo.filectx(file_, fileid=fn)
4380 p.append(fctx.node())
4396 p.append(fctx.node())
4381 else:
4397 else:
4382 p = [cp.node() for cp in ctx.parents()]
4398 p = [cp.node() for cp in ctx.parents()]
4383
4399
4384 displayer = cmdutil.show_changeset(ui, repo, opts)
4400 displayer = cmdutil.show_changeset(ui, repo, opts)
4385 for n in p:
4401 for n in p:
4386 if n != nullid:
4402 if n != nullid:
4387 displayer.show(repo[n])
4403 displayer.show(repo[n])
4388 displayer.close()
4404 displayer.close()
4389
4405
4390 @command('paths', [], _('[NAME]'))
4406 @command('paths', [], _('[NAME]'))
4391 def paths(ui, repo, search=None):
4407 def paths(ui, repo, search=None):
4392 """show aliases for remote repositories
4408 """show aliases for remote repositories
4393
4409
4394 Show definition of symbolic path name NAME. If no name is given,
4410 Show definition of symbolic path name NAME. If no name is given,
4395 show definition of all available names.
4411 show definition of all available names.
4396
4412
4397 Option -q/--quiet suppresses all output when searching for NAME
4413 Option -q/--quiet suppresses all output when searching for NAME
4398 and shows only the path names when listing all definitions.
4414 and shows only the path names when listing all definitions.
4399
4415
4400 Path names are defined in the [paths] section of your
4416 Path names are defined in the [paths] section of your
4401 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4417 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4402 repository, ``.hg/hgrc`` is used, too.
4418 repository, ``.hg/hgrc`` is used, too.
4403
4419
4404 The path names ``default`` and ``default-push`` have a special
4420 The path names ``default`` and ``default-push`` have a special
4405 meaning. When performing a push or pull operation, they are used
4421 meaning. When performing a push or pull operation, they are used
4406 as fallbacks if no location is specified on the command-line.
4422 as fallbacks if no location is specified on the command-line.
4407 When ``default-push`` is set, it will be used for push and
4423 When ``default-push`` is set, it will be used for push and
4408 ``default`` will be used for pull; otherwise ``default`` is used
4424 ``default`` will be used for pull; otherwise ``default`` is used
4409 as the fallback for both. When cloning a repository, the clone
4425 as the fallback for both. When cloning a repository, the clone
4410 source is written as ``default`` in ``.hg/hgrc``. Note that
4426 source is written as ``default`` in ``.hg/hgrc``. Note that
4411 ``default`` and ``default-push`` apply to all inbound (e.g.
4427 ``default`` and ``default-push`` apply to all inbound (e.g.
4412 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4428 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4413 :hg:`bundle`) operations.
4429 :hg:`bundle`) operations.
4414
4430
4415 See :hg:`help urls` for more information.
4431 See :hg:`help urls` for more information.
4416
4432
4417 Returns 0 on success.
4433 Returns 0 on success.
4418 """
4434 """
4419 if search:
4435 if search:
4420 for name, path in ui.configitems("paths"):
4436 for name, path in ui.configitems("paths"):
4421 if name == search:
4437 if name == search:
4422 ui.status("%s\n" % util.hidepassword(path))
4438 ui.status("%s\n" % util.hidepassword(path))
4423 return
4439 return
4424 if not ui.quiet:
4440 if not ui.quiet:
4425 ui.warn(_("not found!\n"))
4441 ui.warn(_("not found!\n"))
4426 return 1
4442 return 1
4427 else:
4443 else:
4428 for name, path in ui.configitems("paths"):
4444 for name, path in ui.configitems("paths"):
4429 if ui.quiet:
4445 if ui.quiet:
4430 ui.write("%s\n" % name)
4446 ui.write("%s\n" % name)
4431 else:
4447 else:
4432 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4448 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4433
4449
4434 @command('phase',
4450 @command('phase',
4435 [('p', 'public', False, _('set changeset phase to public')),
4451 [('p', 'public', False, _('set changeset phase to public')),
4436 ('d', 'draft', False, _('set changeset phase to draft')),
4452 ('d', 'draft', False, _('set changeset phase to draft')),
4437 ('s', 'secret', False, _('set changeset phase to secret')),
4453 ('s', 'secret', False, _('set changeset phase to secret')),
4438 ('f', 'force', False, _('allow to move boundary backward')),
4454 ('f', 'force', False, _('allow to move boundary backward')),
4439 ('r', 'rev', [], _('target revision'), _('REV')),
4455 ('r', 'rev', [], _('target revision'), _('REV')),
4440 ],
4456 ],
4441 _('[-p|-d|-s] [-f] [-r] REV...'))
4457 _('[-p|-d|-s] [-f] [-r] REV...'))
4442 def phase(ui, repo, *revs, **opts):
4458 def phase(ui, repo, *revs, **opts):
4443 """set or show the current phase name
4459 """set or show the current phase name
4444
4460
4445 With no argument, show the phase name of specified revisions.
4461 With no argument, show the phase name of specified revisions.
4446
4462
4447 With one of -p/--public, -d/--draft or -s/--secret, change the
4463 With one of -p/--public, -d/--draft or -s/--secret, change the
4448 phase value of the specified revisions.
4464 phase value of the specified revisions.
4449
4465
4450 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4466 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4451 lower phase to an higher phase. Phases are ordered as follows::
4467 lower phase to an higher phase. Phases are ordered as follows::
4452
4468
4453 public < draft < secret
4469 public < draft < secret
4454
4470
4455 Return 0 on success, 1 if no phases were changed or some could not
4471 Return 0 on success, 1 if no phases were changed or some could not
4456 be changed.
4472 be changed.
4457 """
4473 """
4458 # search for a unique phase argument
4474 # search for a unique phase argument
4459 targetphase = None
4475 targetphase = None
4460 for idx, name in enumerate(phases.phasenames):
4476 for idx, name in enumerate(phases.phasenames):
4461 if opts[name]:
4477 if opts[name]:
4462 if targetphase is not None:
4478 if targetphase is not None:
4463 raise util.Abort(_('only one phase can be specified'))
4479 raise util.Abort(_('only one phase can be specified'))
4464 targetphase = idx
4480 targetphase = idx
4465
4481
4466 # look for specified revision
4482 # look for specified revision
4467 revs = list(revs)
4483 revs = list(revs)
4468 revs.extend(opts['rev'])
4484 revs.extend(opts['rev'])
4469 if not revs:
4485 if not revs:
4470 raise util.Abort(_('no revisions specified'))
4486 raise util.Abort(_('no revisions specified'))
4471
4487
4472 revs = scmutil.revrange(repo, revs)
4488 revs = scmutil.revrange(repo, revs)
4473
4489
4474 lock = None
4490 lock = None
4475 ret = 0
4491 ret = 0
4476 if targetphase is None:
4492 if targetphase is None:
4477 # display
4493 # display
4478 for r in revs:
4494 for r in revs:
4479 ctx = repo[r]
4495 ctx = repo[r]
4480 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4496 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4481 else:
4497 else:
4482 lock = repo.lock()
4498 lock = repo.lock()
4483 try:
4499 try:
4484 # set phase
4500 # set phase
4485 if not revs:
4501 if not revs:
4486 raise util.Abort(_('empty revision set'))
4502 raise util.Abort(_('empty revision set'))
4487 nodes = [repo[r].node() for r in revs]
4503 nodes = [repo[r].node() for r in revs]
4488 olddata = repo._phasecache.getphaserevs(repo)[:]
4504 olddata = repo._phasecache.getphaserevs(repo)[:]
4489 phases.advanceboundary(repo, targetphase, nodes)
4505 phases.advanceboundary(repo, targetphase, nodes)
4490 if opts['force']:
4506 if opts['force']:
4491 phases.retractboundary(repo, targetphase, nodes)
4507 phases.retractboundary(repo, targetphase, nodes)
4492 finally:
4508 finally:
4493 lock.release()
4509 lock.release()
4494 # moving revision from public to draft may hide them
4510 # moving revision from public to draft may hide them
4495 # We have to check result on an unfiltered repository
4511 # We have to check result on an unfiltered repository
4496 unfi = repo.unfiltered()
4512 unfi = repo.unfiltered()
4497 newdata = repo._phasecache.getphaserevs(unfi)
4513 newdata = repo._phasecache.getphaserevs(unfi)
4498 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4514 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4499 cl = unfi.changelog
4515 cl = unfi.changelog
4500 rejected = [n for n in nodes
4516 rejected = [n for n in nodes
4501 if newdata[cl.rev(n)] < targetphase]
4517 if newdata[cl.rev(n)] < targetphase]
4502 if rejected:
4518 if rejected:
4503 ui.warn(_('cannot move %i changesets to a higher '
4519 ui.warn(_('cannot move %i changesets to a higher '
4504 'phase, use --force\n') % len(rejected))
4520 'phase, use --force\n') % len(rejected))
4505 ret = 1
4521 ret = 1
4506 if changes:
4522 if changes:
4507 msg = _('phase changed for %i changesets\n') % changes
4523 msg = _('phase changed for %i changesets\n') % changes
4508 if ret:
4524 if ret:
4509 ui.status(msg)
4525 ui.status(msg)
4510 else:
4526 else:
4511 ui.note(msg)
4527 ui.note(msg)
4512 else:
4528 else:
4513 ui.warn(_('no phases changed\n'))
4529 ui.warn(_('no phases changed\n'))
4514 ret = 1
4530 ret = 1
4515 return ret
4531 return ret
4516
4532
4517 def postincoming(ui, repo, modheads, optupdate, checkout):
4533 def postincoming(ui, repo, modheads, optupdate, checkout):
4518 if modheads == 0:
4534 if modheads == 0:
4519 return
4535 return
4520 if optupdate:
4536 if optupdate:
4521 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4537 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4522 try:
4538 try:
4523 ret = hg.update(repo, checkout)
4539 ret = hg.update(repo, checkout)
4524 except util.Abort, inst:
4540 except util.Abort, inst:
4525 ui.warn(_("not updating: %s\n") % str(inst))
4541 ui.warn(_("not updating: %s\n") % str(inst))
4526 if inst.hint:
4542 if inst.hint:
4527 ui.warn(_("(%s)\n") % inst.hint)
4543 ui.warn(_("(%s)\n") % inst.hint)
4528 return 0
4544 return 0
4529 if not ret and not checkout:
4545 if not ret and not checkout:
4530 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4546 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4531 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4547 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4532 return ret
4548 return ret
4533 if modheads > 1:
4549 if modheads > 1:
4534 currentbranchheads = len(repo.branchheads())
4550 currentbranchheads = len(repo.branchheads())
4535 if currentbranchheads == modheads:
4551 if currentbranchheads == modheads:
4536 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4552 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4537 elif currentbranchheads > 1:
4553 elif currentbranchheads > 1:
4538 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4554 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4539 "merge)\n"))
4555 "merge)\n"))
4540 else:
4556 else:
4541 ui.status(_("(run 'hg heads' to see heads)\n"))
4557 ui.status(_("(run 'hg heads' to see heads)\n"))
4542 else:
4558 else:
4543 ui.status(_("(run 'hg update' to get a working copy)\n"))
4559 ui.status(_("(run 'hg update' to get a working copy)\n"))
4544
4560
4545 @command('^pull',
4561 @command('^pull',
4546 [('u', 'update', None,
4562 [('u', 'update', None,
4547 _('update to new branch head if changesets were pulled')),
4563 _('update to new branch head if changesets were pulled')),
4548 ('f', 'force', None, _('run even when remote repository is unrelated')),
4564 ('f', 'force', None, _('run even when remote repository is unrelated')),
4549 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4565 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4550 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4566 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4551 ('b', 'branch', [], _('a specific branch you would like to pull'),
4567 ('b', 'branch', [], _('a specific branch you would like to pull'),
4552 _('BRANCH')),
4568 _('BRANCH')),
4553 ] + remoteopts,
4569 ] + remoteopts,
4554 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4570 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4555 def pull(ui, repo, source="default", **opts):
4571 def pull(ui, repo, source="default", **opts):
4556 """pull changes from the specified source
4572 """pull changes from the specified source
4557
4573
4558 Pull changes from a remote repository to a local one.
4574 Pull changes from a remote repository to a local one.
4559
4575
4560 This finds all changes from the repository at the specified path
4576 This finds all changes from the repository at the specified path
4561 or URL and adds them to a local repository (the current one unless
4577 or URL and adds them to a local repository (the current one unless
4562 -R is specified). By default, this does not update the copy of the
4578 -R is specified). By default, this does not update the copy of the
4563 project in the working directory.
4579 project in the working directory.
4564
4580
4565 Use :hg:`incoming` if you want to see what would have been added
4581 Use :hg:`incoming` if you want to see what would have been added
4566 by a pull at the time you issued this command. If you then decide
4582 by a pull at the time you issued this command. If you then decide
4567 to add those changes to the repository, you should use :hg:`pull
4583 to add those changes to the repository, you should use :hg:`pull
4568 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4584 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4569
4585
4570 If SOURCE is omitted, the 'default' path will be used.
4586 If SOURCE is omitted, the 'default' path will be used.
4571 See :hg:`help urls` for more information.
4587 See :hg:`help urls` for more information.
4572
4588
4573 Returns 0 on success, 1 if an update had unresolved files.
4589 Returns 0 on success, 1 if an update had unresolved files.
4574 """
4590 """
4575 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4591 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4576 other = hg.peer(repo, opts, source)
4592 other = hg.peer(repo, opts, source)
4577 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4593 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4578 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4594 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4579
4595
4580 remotebookmarks = other.listkeys('bookmarks')
4596 remotebookmarks = other.listkeys('bookmarks')
4581
4597
4582 if opts.get('bookmark'):
4598 if opts.get('bookmark'):
4583 if not revs:
4599 if not revs:
4584 revs = []
4600 revs = []
4585 for b in opts['bookmark']:
4601 for b in opts['bookmark']:
4586 if b not in remotebookmarks:
4602 if b not in remotebookmarks:
4587 raise util.Abort(_('remote bookmark %s not found!') % b)
4603 raise util.Abort(_('remote bookmark %s not found!') % b)
4588 revs.append(remotebookmarks[b])
4604 revs.append(remotebookmarks[b])
4589
4605
4590 if revs:
4606 if revs:
4591 try:
4607 try:
4592 revs = [other.lookup(rev) for rev in revs]
4608 revs = [other.lookup(rev) for rev in revs]
4593 except error.CapabilityError:
4609 except error.CapabilityError:
4594 err = _("other repository doesn't support revision lookup, "
4610 err = _("other repository doesn't support revision lookup, "
4595 "so a rev cannot be specified.")
4611 "so a rev cannot be specified.")
4596 raise util.Abort(err)
4612 raise util.Abort(err)
4597
4613
4598 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4614 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4599 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4615 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4600 if checkout:
4616 if checkout:
4601 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4617 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4602 repo._subtoppath = source
4618 repo._subtoppath = source
4603 try:
4619 try:
4604 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4620 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4605
4621
4606 finally:
4622 finally:
4607 del repo._subtoppath
4623 del repo._subtoppath
4608
4624
4609 # update specified bookmarks
4625 # update specified bookmarks
4610 if opts.get('bookmark'):
4626 if opts.get('bookmark'):
4611 marks = repo._bookmarks
4627 marks = repo._bookmarks
4612 for b in opts['bookmark']:
4628 for b in opts['bookmark']:
4613 # explicit pull overrides local bookmark if any
4629 # explicit pull overrides local bookmark if any
4614 ui.status(_("importing bookmark %s\n") % b)
4630 ui.status(_("importing bookmark %s\n") % b)
4615 marks[b] = repo[remotebookmarks[b]].node()
4631 marks[b] = repo[remotebookmarks[b]].node()
4616 marks.write()
4632 marks.write()
4617
4633
4618 return ret
4634 return ret
4619
4635
4620 @command('^push',
4636 @command('^push',
4621 [('f', 'force', None, _('force push')),
4637 [('f', 'force', None, _('force push')),
4622 ('r', 'rev', [],
4638 ('r', 'rev', [],
4623 _('a changeset intended to be included in the destination'),
4639 _('a changeset intended to be included in the destination'),
4624 _('REV')),
4640 _('REV')),
4625 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4641 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4626 ('b', 'branch', [],
4642 ('b', 'branch', [],
4627 _('a specific branch you would like to push'), _('BRANCH')),
4643 _('a specific branch you would like to push'), _('BRANCH')),
4628 ('', 'new-branch', False, _('allow pushing a new branch')),
4644 ('', 'new-branch', False, _('allow pushing a new branch')),
4629 ] + remoteopts,
4645 ] + remoteopts,
4630 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4646 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4631 def push(ui, repo, dest=None, **opts):
4647 def push(ui, repo, dest=None, **opts):
4632 """push changes to the specified destination
4648 """push changes to the specified destination
4633
4649
4634 Push changesets from the local repository to the specified
4650 Push changesets from the local repository to the specified
4635 destination.
4651 destination.
4636
4652
4637 This operation is symmetrical to pull: it is identical to a pull
4653 This operation is symmetrical to pull: it is identical to a pull
4638 in the destination repository from the current one.
4654 in the destination repository from the current one.
4639
4655
4640 By default, push will not allow creation of new heads at the
4656 By default, push will not allow creation of new heads at the
4641 destination, since multiple heads would make it unclear which head
4657 destination, since multiple heads would make it unclear which head
4642 to use. In this situation, it is recommended to pull and merge
4658 to use. In this situation, it is recommended to pull and merge
4643 before pushing.
4659 before pushing.
4644
4660
4645 Use --new-branch if you want to allow push to create a new named
4661 Use --new-branch if you want to allow push to create a new named
4646 branch that is not present at the destination. This allows you to
4662 branch that is not present at the destination. This allows you to
4647 only create a new branch without forcing other changes.
4663 only create a new branch without forcing other changes.
4648
4664
4649 .. note::
4665 .. note::
4650
4666
4651 Extra care should be taken with the -f/--force option,
4667 Extra care should be taken with the -f/--force option,
4652 which will push all new heads on all branches, an action which will
4668 which will push all new heads on all branches, an action which will
4653 almost always cause confusion for collaborators.
4669 almost always cause confusion for collaborators.
4654
4670
4655 If -r/--rev is used, the specified revision and all its ancestors
4671 If -r/--rev is used, the specified revision and all its ancestors
4656 will be pushed to the remote repository.
4672 will be pushed to the remote repository.
4657
4673
4658 If -B/--bookmark is used, the specified bookmarked revision, its
4674 If -B/--bookmark is used, the specified bookmarked revision, its
4659 ancestors, and the bookmark will be pushed to the remote
4675 ancestors, and the bookmark will be pushed to the remote
4660 repository.
4676 repository.
4661
4677
4662 Please see :hg:`help urls` for important details about ``ssh://``
4678 Please see :hg:`help urls` for important details about ``ssh://``
4663 URLs. If DESTINATION is omitted, a default path will be used.
4679 URLs. If DESTINATION is omitted, a default path will be used.
4664
4680
4665 Returns 0 if push was successful, 1 if nothing to push.
4681 Returns 0 if push was successful, 1 if nothing to push.
4666 """
4682 """
4667
4683
4668 if opts.get('bookmark'):
4684 if opts.get('bookmark'):
4669 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4685 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4670 for b in opts['bookmark']:
4686 for b in opts['bookmark']:
4671 # translate -B options to -r so changesets get pushed
4687 # translate -B options to -r so changesets get pushed
4672 if b in repo._bookmarks:
4688 if b in repo._bookmarks:
4673 opts.setdefault('rev', []).append(b)
4689 opts.setdefault('rev', []).append(b)
4674 else:
4690 else:
4675 # if we try to push a deleted bookmark, translate it to null
4691 # if we try to push a deleted bookmark, translate it to null
4676 # this lets simultaneous -r, -b options continue working
4692 # this lets simultaneous -r, -b options continue working
4677 opts.setdefault('rev', []).append("null")
4693 opts.setdefault('rev', []).append("null")
4678
4694
4679 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4695 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4680 dest, branches = hg.parseurl(dest, opts.get('branch'))
4696 dest, branches = hg.parseurl(dest, opts.get('branch'))
4681 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4697 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4682 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4698 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4683 try:
4699 try:
4684 other = hg.peer(repo, opts, dest)
4700 other = hg.peer(repo, opts, dest)
4685 except error.RepoError:
4701 except error.RepoError:
4686 if dest == "default-push":
4702 if dest == "default-push":
4687 raise util.Abort(_("default repository not configured!"),
4703 raise util.Abort(_("default repository not configured!"),
4688 hint=_('see the "path" section in "hg help config"'))
4704 hint=_('see the "path" section in "hg help config"'))
4689 else:
4705 else:
4690 raise
4706 raise
4691
4707
4692 if revs:
4708 if revs:
4693 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4709 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4694
4710
4695 repo._subtoppath = dest
4711 repo._subtoppath = dest
4696 try:
4712 try:
4697 # push subrepos depth-first for coherent ordering
4713 # push subrepos depth-first for coherent ordering
4698 c = repo['']
4714 c = repo['']
4699 subs = c.substate # only repos that are committed
4715 subs = c.substate # only repos that are committed
4700 for s in sorted(subs):
4716 for s in sorted(subs):
4701 if c.sub(s).push(opts) == 0:
4717 if c.sub(s).push(opts) == 0:
4702 return False
4718 return False
4703 finally:
4719 finally:
4704 del repo._subtoppath
4720 del repo._subtoppath
4705 result = repo.push(other, opts.get('force'), revs=revs,
4721 result = repo.push(other, opts.get('force'), revs=revs,
4706 newbranch=opts.get('new_branch'))
4722 newbranch=opts.get('new_branch'))
4707
4723
4708 result = not result
4724 result = not result
4709
4725
4710 if opts.get('bookmark'):
4726 if opts.get('bookmark'):
4711 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4727 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4712 if bresult == 2:
4728 if bresult == 2:
4713 return 2
4729 return 2
4714 if not result and bresult:
4730 if not result and bresult:
4715 result = 2
4731 result = 2
4716
4732
4717 return result
4733 return result
4718
4734
4719 @command('recover', [])
4735 @command('recover', [])
4720 def recover(ui, repo):
4736 def recover(ui, repo):
4721 """roll back an interrupted transaction
4737 """roll back an interrupted transaction
4722
4738
4723 Recover from an interrupted commit or pull.
4739 Recover from an interrupted commit or pull.
4724
4740
4725 This command tries to fix the repository status after an
4741 This command tries to fix the repository status after an
4726 interrupted operation. It should only be necessary when Mercurial
4742 interrupted operation. It should only be necessary when Mercurial
4727 suggests it.
4743 suggests it.
4728
4744
4729 Returns 0 if successful, 1 if nothing to recover or verify fails.
4745 Returns 0 if successful, 1 if nothing to recover or verify fails.
4730 """
4746 """
4731 if repo.recover():
4747 if repo.recover():
4732 return hg.verify(repo)
4748 return hg.verify(repo)
4733 return 1
4749 return 1
4734
4750
4735 @command('^remove|rm',
4751 @command('^remove|rm',
4736 [('A', 'after', None, _('record delete for missing files')),
4752 [('A', 'after', None, _('record delete for missing files')),
4737 ('f', 'force', None,
4753 ('f', 'force', None,
4738 _('remove (and delete) file even if added or modified')),
4754 _('remove (and delete) file even if added or modified')),
4739 ] + walkopts,
4755 ] + walkopts,
4740 _('[OPTION]... FILE...'))
4756 _('[OPTION]... FILE...'))
4741 def remove(ui, repo, *pats, **opts):
4757 def remove(ui, repo, *pats, **opts):
4742 """remove the specified files on the next commit
4758 """remove the specified files on the next commit
4743
4759
4744 Schedule the indicated files for removal from the current branch.
4760 Schedule the indicated files for removal from the current branch.
4745
4761
4746 This command schedules the files to be removed at the next commit.
4762 This command schedules the files to be removed at the next commit.
4747 To undo a remove before that, see :hg:`revert`. To undo added
4763 To undo a remove before that, see :hg:`revert`. To undo added
4748 files, see :hg:`forget`.
4764 files, see :hg:`forget`.
4749
4765
4750 .. container:: verbose
4766 .. container:: verbose
4751
4767
4752 -A/--after can be used to remove only files that have already
4768 -A/--after can be used to remove only files that have already
4753 been deleted, -f/--force can be used to force deletion, and -Af
4769 been deleted, -f/--force can be used to force deletion, and -Af
4754 can be used to remove files from the next revision without
4770 can be used to remove files from the next revision without
4755 deleting them from the working directory.
4771 deleting them from the working directory.
4756
4772
4757 The following table details the behavior of remove for different
4773 The following table details the behavior of remove for different
4758 file states (columns) and option combinations (rows). The file
4774 file states (columns) and option combinations (rows). The file
4759 states are Added [A], Clean [C], Modified [M] and Missing [!]
4775 states are Added [A], Clean [C], Modified [M] and Missing [!]
4760 (as reported by :hg:`status`). The actions are Warn, Remove
4776 (as reported by :hg:`status`). The actions are Warn, Remove
4761 (from branch) and Delete (from disk):
4777 (from branch) and Delete (from disk):
4762
4778
4763 ========= == == == ==
4779 ========= == == == ==
4764 opt/state A C M !
4780 opt/state A C M !
4765 ========= == == == ==
4781 ========= == == == ==
4766 none W RD W R
4782 none W RD W R
4767 -f R RD RD R
4783 -f R RD RD R
4768 -A W W W R
4784 -A W W W R
4769 -Af R R R R
4785 -Af R R R R
4770 ========= == == == ==
4786 ========= == == == ==
4771
4787
4772 Note that remove never deletes files in Added [A] state from the
4788 Note that remove never deletes files in Added [A] state from the
4773 working directory, not even if option --force is specified.
4789 working directory, not even if option --force is specified.
4774
4790
4775 Returns 0 on success, 1 if any warnings encountered.
4791 Returns 0 on success, 1 if any warnings encountered.
4776 """
4792 """
4777
4793
4778 ret = 0
4794 ret = 0
4779 after, force = opts.get('after'), opts.get('force')
4795 after, force = opts.get('after'), opts.get('force')
4780 if not pats and not after:
4796 if not pats and not after:
4781 raise util.Abort(_('no files specified'))
4797 raise util.Abort(_('no files specified'))
4782
4798
4783 m = scmutil.match(repo[None], pats, opts)
4799 m = scmutil.match(repo[None], pats, opts)
4784 s = repo.status(match=m, clean=True)
4800 s = repo.status(match=m, clean=True)
4785 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4801 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4786
4802
4787 # warn about failure to delete explicit files/dirs
4803 # warn about failure to delete explicit files/dirs
4788 wctx = repo[None]
4804 wctx = repo[None]
4789 for f in m.files():
4805 for f in m.files():
4790 if f in repo.dirstate or f in wctx.dirs():
4806 if f in repo.dirstate or f in wctx.dirs():
4791 continue
4807 continue
4792 if os.path.exists(m.rel(f)):
4808 if os.path.exists(m.rel(f)):
4793 if os.path.isdir(m.rel(f)):
4809 if os.path.isdir(m.rel(f)):
4794 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4810 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4795 else:
4811 else:
4796 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4812 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4797 # missing files will generate a warning elsewhere
4813 # missing files will generate a warning elsewhere
4798 ret = 1
4814 ret = 1
4799
4815
4800 if force:
4816 if force:
4801 list = modified + deleted + clean + added
4817 list = modified + deleted + clean + added
4802 elif after:
4818 elif after:
4803 list = deleted
4819 list = deleted
4804 for f in modified + added + clean:
4820 for f in modified + added + clean:
4805 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4821 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4806 ret = 1
4822 ret = 1
4807 else:
4823 else:
4808 list = deleted + clean
4824 list = deleted + clean
4809 for f in modified:
4825 for f in modified:
4810 ui.warn(_('not removing %s: file is modified (use -f'
4826 ui.warn(_('not removing %s: file is modified (use -f'
4811 ' to force removal)\n') % m.rel(f))
4827 ' to force removal)\n') % m.rel(f))
4812 ret = 1
4828 ret = 1
4813 for f in added:
4829 for f in added:
4814 ui.warn(_('not removing %s: file has been marked for add'
4830 ui.warn(_('not removing %s: file has been marked for add'
4815 ' (use forget to undo)\n') % m.rel(f))
4831 ' (use forget to undo)\n') % m.rel(f))
4816 ret = 1
4832 ret = 1
4817
4833
4818 for f in sorted(list):
4834 for f in sorted(list):
4819 if ui.verbose or not m.exact(f):
4835 if ui.verbose or not m.exact(f):
4820 ui.status(_('removing %s\n') % m.rel(f))
4836 ui.status(_('removing %s\n') % m.rel(f))
4821
4837
4822 wlock = repo.wlock()
4838 wlock = repo.wlock()
4823 try:
4839 try:
4824 if not after:
4840 if not after:
4825 for f in list:
4841 for f in list:
4826 if f in added:
4842 if f in added:
4827 continue # we never unlink added files on remove
4843 continue # we never unlink added files on remove
4828 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4844 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4829 repo[None].forget(list)
4845 repo[None].forget(list)
4830 finally:
4846 finally:
4831 wlock.release()
4847 wlock.release()
4832
4848
4833 return ret
4849 return ret
4834
4850
4835 @command('rename|move|mv',
4851 @command('rename|move|mv',
4836 [('A', 'after', None, _('record a rename that has already occurred')),
4852 [('A', 'after', None, _('record a rename that has already occurred')),
4837 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4853 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4838 ] + walkopts + dryrunopts,
4854 ] + walkopts + dryrunopts,
4839 _('[OPTION]... SOURCE... DEST'))
4855 _('[OPTION]... SOURCE... DEST'))
4840 def rename(ui, repo, *pats, **opts):
4856 def rename(ui, repo, *pats, **opts):
4841 """rename files; equivalent of copy + remove
4857 """rename files; equivalent of copy + remove
4842
4858
4843 Mark dest as copies of sources; mark sources for deletion. If dest
4859 Mark dest as copies of sources; mark sources for deletion. If dest
4844 is a directory, copies are put in that directory. If dest is a
4860 is a directory, copies are put in that directory. If dest is a
4845 file, there can only be one source.
4861 file, there can only be one source.
4846
4862
4847 By default, this command copies the contents of files as they
4863 By default, this command copies the contents of files as they
4848 exist in the working directory. If invoked with -A/--after, the
4864 exist in the working directory. If invoked with -A/--after, the
4849 operation is recorded, but no copying is performed.
4865 operation is recorded, but no copying is performed.
4850
4866
4851 This command takes effect at the next commit. To undo a rename
4867 This command takes effect at the next commit. To undo a rename
4852 before that, see :hg:`revert`.
4868 before that, see :hg:`revert`.
4853
4869
4854 Returns 0 on success, 1 if errors are encountered.
4870 Returns 0 on success, 1 if errors are encountered.
4855 """
4871 """
4856 wlock = repo.wlock(False)
4872 wlock = repo.wlock(False)
4857 try:
4873 try:
4858 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4874 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4859 finally:
4875 finally:
4860 wlock.release()
4876 wlock.release()
4861
4877
4862 @command('resolve',
4878 @command('resolve',
4863 [('a', 'all', None, _('select all unresolved files')),
4879 [('a', 'all', None, _('select all unresolved files')),
4864 ('l', 'list', None, _('list state of files needing merge')),
4880 ('l', 'list', None, _('list state of files needing merge')),
4865 ('m', 'mark', None, _('mark files as resolved')),
4881 ('m', 'mark', None, _('mark files as resolved')),
4866 ('u', 'unmark', None, _('mark files as unresolved')),
4882 ('u', 'unmark', None, _('mark files as unresolved')),
4867 ('n', 'no-status', None, _('hide status prefix'))]
4883 ('n', 'no-status', None, _('hide status prefix'))]
4868 + mergetoolopts + walkopts,
4884 + mergetoolopts + walkopts,
4869 _('[OPTION]... [FILE]...'))
4885 _('[OPTION]... [FILE]...'))
4870 def resolve(ui, repo, *pats, **opts):
4886 def resolve(ui, repo, *pats, **opts):
4871 """redo merges or set/view the merge status of files
4887 """redo merges or set/view the merge status of files
4872
4888
4873 Merges with unresolved conflicts are often the result of
4889 Merges with unresolved conflicts are often the result of
4874 non-interactive merging using the ``internal:merge`` configuration
4890 non-interactive merging using the ``internal:merge`` configuration
4875 setting, or a command-line merge tool like ``diff3``. The resolve
4891 setting, or a command-line merge tool like ``diff3``. The resolve
4876 command is used to manage the files involved in a merge, after
4892 command is used to manage the files involved in a merge, after
4877 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4893 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4878 working directory must have two parents). See :hg:`help
4894 working directory must have two parents). See :hg:`help
4879 merge-tools` for information on configuring merge tools.
4895 merge-tools` for information on configuring merge tools.
4880
4896
4881 The resolve command can be used in the following ways:
4897 The resolve command can be used in the following ways:
4882
4898
4883 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4899 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4884 files, discarding any previous merge attempts. Re-merging is not
4900 files, discarding any previous merge attempts. Re-merging is not
4885 performed for files already marked as resolved. Use ``--all/-a``
4901 performed for files already marked as resolved. Use ``--all/-a``
4886 to select all unresolved files. ``--tool`` can be used to specify
4902 to select all unresolved files. ``--tool`` can be used to specify
4887 the merge tool used for the given files. It overrides the HGMERGE
4903 the merge tool used for the given files. It overrides the HGMERGE
4888 environment variable and your configuration files. Previous file
4904 environment variable and your configuration files. Previous file
4889 contents are saved with a ``.orig`` suffix.
4905 contents are saved with a ``.orig`` suffix.
4890
4906
4891 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4907 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4892 (e.g. after having manually fixed-up the files). The default is
4908 (e.g. after having manually fixed-up the files). The default is
4893 to mark all unresolved files.
4909 to mark all unresolved files.
4894
4910
4895 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4911 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4896 default is to mark all resolved files.
4912 default is to mark all resolved files.
4897
4913
4898 - :hg:`resolve -l`: list files which had or still have conflicts.
4914 - :hg:`resolve -l`: list files which had or still have conflicts.
4899 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4915 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4900
4916
4901 Note that Mercurial will not let you commit files with unresolved
4917 Note that Mercurial will not let you commit files with unresolved
4902 merge conflicts. You must use :hg:`resolve -m ...` before you can
4918 merge conflicts. You must use :hg:`resolve -m ...` before you can
4903 commit after a conflicting merge.
4919 commit after a conflicting merge.
4904
4920
4905 Returns 0 on success, 1 if any files fail a resolve attempt.
4921 Returns 0 on success, 1 if any files fail a resolve attempt.
4906 """
4922 """
4907
4923
4908 all, mark, unmark, show, nostatus = \
4924 all, mark, unmark, show, nostatus = \
4909 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4925 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4910
4926
4911 if (show and (mark or unmark)) or (mark and unmark):
4927 if (show and (mark or unmark)) or (mark and unmark):
4912 raise util.Abort(_("too many options specified"))
4928 raise util.Abort(_("too many options specified"))
4913 if pats and all:
4929 if pats and all:
4914 raise util.Abort(_("can't specify --all and patterns"))
4930 raise util.Abort(_("can't specify --all and patterns"))
4915 if not (all or pats or show or mark or unmark):
4931 if not (all or pats or show or mark or unmark):
4916 raise util.Abort(_('no files or directories specified; '
4932 raise util.Abort(_('no files or directories specified; '
4917 'use --all to remerge all files'))
4933 'use --all to remerge all files'))
4918
4934
4919 ms = mergemod.mergestate(repo)
4935 ms = mergemod.mergestate(repo)
4920 m = scmutil.match(repo[None], pats, opts)
4936 m = scmutil.match(repo[None], pats, opts)
4921 ret = 0
4937 ret = 0
4922
4938
4923 for f in ms:
4939 for f in ms:
4924 if m(f):
4940 if m(f):
4925 if show:
4941 if show:
4926 if nostatus:
4942 if nostatus:
4927 ui.write("%s\n" % f)
4943 ui.write("%s\n" % f)
4928 else:
4944 else:
4929 ui.write("%s %s\n" % (ms[f].upper(), f),
4945 ui.write("%s %s\n" % (ms[f].upper(), f),
4930 label='resolve.' +
4946 label='resolve.' +
4931 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4947 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4932 elif mark:
4948 elif mark:
4933 ms.mark(f, "r")
4949 ms.mark(f, "r")
4934 elif unmark:
4950 elif unmark:
4935 ms.mark(f, "u")
4951 ms.mark(f, "u")
4936 else:
4952 else:
4937 wctx = repo[None]
4953 wctx = repo[None]
4938 mctx = wctx.parents()[-1]
4954 mctx = wctx.parents()[-1]
4939
4955
4940 # backup pre-resolve (merge uses .orig for its own purposes)
4956 # backup pre-resolve (merge uses .orig for its own purposes)
4941 a = repo.wjoin(f)
4957 a = repo.wjoin(f)
4942 util.copyfile(a, a + ".resolve")
4958 util.copyfile(a, a + ".resolve")
4943
4959
4944 try:
4960 try:
4945 # resolve file
4961 # resolve file
4946 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4962 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4947 if ms.resolve(f, wctx, mctx):
4963 if ms.resolve(f, wctx, mctx):
4948 ret = 1
4964 ret = 1
4949 finally:
4965 finally:
4950 ui.setconfig('ui', 'forcemerge', '')
4966 ui.setconfig('ui', 'forcemerge', '')
4951 ms.commit()
4967 ms.commit()
4952
4968
4953 # replace filemerge's .orig file with our resolve file
4969 # replace filemerge's .orig file with our resolve file
4954 util.rename(a + ".resolve", a + ".orig")
4970 util.rename(a + ".resolve", a + ".orig")
4955
4971
4956 ms.commit()
4972 ms.commit()
4957 return ret
4973 return ret
4958
4974
4959 @command('revert',
4975 @command('revert',
4960 [('a', 'all', None, _('revert all changes when no arguments given')),
4976 [('a', 'all', None, _('revert all changes when no arguments given')),
4961 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4977 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4962 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4978 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4963 ('C', 'no-backup', None, _('do not save backup copies of files')),
4979 ('C', 'no-backup', None, _('do not save backup copies of files')),
4964 ] + walkopts + dryrunopts,
4980 ] + walkopts + dryrunopts,
4965 _('[OPTION]... [-r REV] [NAME]...'))
4981 _('[OPTION]... [-r REV] [NAME]...'))
4966 def revert(ui, repo, *pats, **opts):
4982 def revert(ui, repo, *pats, **opts):
4967 """restore files to their checkout state
4983 """restore files to their checkout state
4968
4984
4969 .. note::
4985 .. note::
4970
4986
4971 To check out earlier revisions, you should use :hg:`update REV`.
4987 To check out earlier revisions, you should use :hg:`update REV`.
4972 To cancel an uncommitted merge (and lose your changes),
4988 To cancel an uncommitted merge (and lose your changes),
4973 use :hg:`update --clean .`.
4989 use :hg:`update --clean .`.
4974
4990
4975 With no revision specified, revert the specified files or directories
4991 With no revision specified, revert the specified files or directories
4976 to the contents they had in the parent of the working directory.
4992 to the contents they had in the parent of the working directory.
4977 This restores the contents of files to an unmodified
4993 This restores the contents of files to an unmodified
4978 state and unschedules adds, removes, copies, and renames. If the
4994 state and unschedules adds, removes, copies, and renames. If the
4979 working directory has two parents, you must explicitly specify a
4995 working directory has two parents, you must explicitly specify a
4980 revision.
4996 revision.
4981
4997
4982 Using the -r/--rev or -d/--date options, revert the given files or
4998 Using the -r/--rev or -d/--date options, revert the given files or
4983 directories to their states as of a specific revision. Because
4999 directories to their states as of a specific revision. Because
4984 revert does not change the working directory parents, this will
5000 revert does not change the working directory parents, this will
4985 cause these files to appear modified. This can be helpful to "back
5001 cause these files to appear modified. This can be helpful to "back
4986 out" some or all of an earlier change. See :hg:`backout` for a
5002 out" some or all of an earlier change. See :hg:`backout` for a
4987 related method.
5003 related method.
4988
5004
4989 Modified files are saved with a .orig suffix before reverting.
5005 Modified files are saved with a .orig suffix before reverting.
4990 To disable these backups, use --no-backup.
5006 To disable these backups, use --no-backup.
4991
5007
4992 See :hg:`help dates` for a list of formats valid for -d/--date.
5008 See :hg:`help dates` for a list of formats valid for -d/--date.
4993
5009
4994 Returns 0 on success.
5010 Returns 0 on success.
4995 """
5011 """
4996
5012
4997 if opts.get("date"):
5013 if opts.get("date"):
4998 if opts.get("rev"):
5014 if opts.get("rev"):
4999 raise util.Abort(_("you can't specify a revision and a date"))
5015 raise util.Abort(_("you can't specify a revision and a date"))
5000 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5016 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5001
5017
5002 parent, p2 = repo.dirstate.parents()
5018 parent, p2 = repo.dirstate.parents()
5003 if not opts.get('rev') and p2 != nullid:
5019 if not opts.get('rev') and p2 != nullid:
5004 # revert after merge is a trap for new users (issue2915)
5020 # revert after merge is a trap for new users (issue2915)
5005 raise util.Abort(_('uncommitted merge with no revision specified'),
5021 raise util.Abort(_('uncommitted merge with no revision specified'),
5006 hint=_('use "hg update" or see "hg help revert"'))
5022 hint=_('use "hg update" or see "hg help revert"'))
5007
5023
5008 ctx = scmutil.revsingle(repo, opts.get('rev'))
5024 ctx = scmutil.revsingle(repo, opts.get('rev'))
5009
5025
5010 if not pats and not opts.get('all'):
5026 if not pats and not opts.get('all'):
5011 msg = _("no files or directories specified")
5027 msg = _("no files or directories specified")
5012 if p2 != nullid:
5028 if p2 != nullid:
5013 hint = _("uncommitted merge, use --all to discard all changes,"
5029 hint = _("uncommitted merge, use --all to discard all changes,"
5014 " or 'hg update -C .' to abort the merge")
5030 " or 'hg update -C .' to abort the merge")
5015 raise util.Abort(msg, hint=hint)
5031 raise util.Abort(msg, hint=hint)
5016 dirty = util.any(repo.status())
5032 dirty = util.any(repo.status())
5017 node = ctx.node()
5033 node = ctx.node()
5018 if node != parent:
5034 if node != parent:
5019 if dirty:
5035 if dirty:
5020 hint = _("uncommitted changes, use --all to discard all"
5036 hint = _("uncommitted changes, use --all to discard all"
5021 " changes, or 'hg update %s' to update") % ctx.rev()
5037 " changes, or 'hg update %s' to update") % ctx.rev()
5022 else:
5038 else:
5023 hint = _("use --all to revert all files,"
5039 hint = _("use --all to revert all files,"
5024 " or 'hg update %s' to update") % ctx.rev()
5040 " or 'hg update %s' to update") % ctx.rev()
5025 elif dirty:
5041 elif dirty:
5026 hint = _("uncommitted changes, use --all to discard all changes")
5042 hint = _("uncommitted changes, use --all to discard all changes")
5027 else:
5043 else:
5028 hint = _("use --all to revert all files")
5044 hint = _("use --all to revert all files")
5029 raise util.Abort(msg, hint=hint)
5045 raise util.Abort(msg, hint=hint)
5030
5046
5031 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5047 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5032
5048
5033 @command('rollback', dryrunopts +
5049 @command('rollback', dryrunopts +
5034 [('f', 'force', False, _('ignore safety measures'))])
5050 [('f', 'force', False, _('ignore safety measures'))])
5035 def rollback(ui, repo, **opts):
5051 def rollback(ui, repo, **opts):
5036 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5052 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5037
5053
5038 Please use :hg:`commit --amend` instead of rollback to correct
5054 Please use :hg:`commit --amend` instead of rollback to correct
5039 mistakes in the last commit.
5055 mistakes in the last commit.
5040
5056
5041 This command should be used with care. There is only one level of
5057 This command should be used with care. There is only one level of
5042 rollback, and there is no way to undo a rollback. It will also
5058 rollback, and there is no way to undo a rollback. It will also
5043 restore the dirstate at the time of the last transaction, losing
5059 restore the dirstate at the time of the last transaction, losing
5044 any dirstate changes since that time. This command does not alter
5060 any dirstate changes since that time. This command does not alter
5045 the working directory.
5061 the working directory.
5046
5062
5047 Transactions are used to encapsulate the effects of all commands
5063 Transactions are used to encapsulate the effects of all commands
5048 that create new changesets or propagate existing changesets into a
5064 that create new changesets or propagate existing changesets into a
5049 repository.
5065 repository.
5050
5066
5051 .. container:: verbose
5067 .. container:: verbose
5052
5068
5053 For example, the following commands are transactional, and their
5069 For example, the following commands are transactional, and their
5054 effects can be rolled back:
5070 effects can be rolled back:
5055
5071
5056 - commit
5072 - commit
5057 - import
5073 - import
5058 - pull
5074 - pull
5059 - push (with this repository as the destination)
5075 - push (with this repository as the destination)
5060 - unbundle
5076 - unbundle
5061
5077
5062 To avoid permanent data loss, rollback will refuse to rollback a
5078 To avoid permanent data loss, rollback will refuse to rollback a
5063 commit transaction if it isn't checked out. Use --force to
5079 commit transaction if it isn't checked out. Use --force to
5064 override this protection.
5080 override this protection.
5065
5081
5066 This command is not intended for use on public repositories. Once
5082 This command is not intended for use on public repositories. Once
5067 changes are visible for pull by other users, rolling a transaction
5083 changes are visible for pull by other users, rolling a transaction
5068 back locally is ineffective (someone else may already have pulled
5084 back locally is ineffective (someone else may already have pulled
5069 the changes). Furthermore, a race is possible with readers of the
5085 the changes). Furthermore, a race is possible with readers of the
5070 repository; for example an in-progress pull from the repository
5086 repository; for example an in-progress pull from the repository
5071 may fail if a rollback is performed.
5087 may fail if a rollback is performed.
5072
5088
5073 Returns 0 on success, 1 if no rollback data is available.
5089 Returns 0 on success, 1 if no rollback data is available.
5074 """
5090 """
5075 return repo.rollback(dryrun=opts.get('dry_run'),
5091 return repo.rollback(dryrun=opts.get('dry_run'),
5076 force=opts.get('force'))
5092 force=opts.get('force'))
5077
5093
5078 @command('root', [])
5094 @command('root', [])
5079 def root(ui, repo):
5095 def root(ui, repo):
5080 """print the root (top) of the current working directory
5096 """print the root (top) of the current working directory
5081
5097
5082 Print the root directory of the current repository.
5098 Print the root directory of the current repository.
5083
5099
5084 Returns 0 on success.
5100 Returns 0 on success.
5085 """
5101 """
5086 ui.write(repo.root + "\n")
5102 ui.write(repo.root + "\n")
5087
5103
5088 @command('^serve',
5104 @command('^serve',
5089 [('A', 'accesslog', '', _('name of access log file to write to'),
5105 [('A', 'accesslog', '', _('name of access log file to write to'),
5090 _('FILE')),
5106 _('FILE')),
5091 ('d', 'daemon', None, _('run server in background')),
5107 ('d', 'daemon', None, _('run server in background')),
5092 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5108 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5093 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5109 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5094 # use string type, then we can check if something was passed
5110 # use string type, then we can check if something was passed
5095 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5111 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5096 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5112 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5097 _('ADDR')),
5113 _('ADDR')),
5098 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5114 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5099 _('PREFIX')),
5115 _('PREFIX')),
5100 ('n', 'name', '',
5116 ('n', 'name', '',
5101 _('name to show in web pages (default: working directory)'), _('NAME')),
5117 _('name to show in web pages (default: working directory)'), _('NAME')),
5102 ('', 'web-conf', '',
5118 ('', 'web-conf', '',
5103 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5119 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5104 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5120 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5105 _('FILE')),
5121 _('FILE')),
5106 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5122 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5107 ('', 'stdio', None, _('for remote clients')),
5123 ('', 'stdio', None, _('for remote clients')),
5108 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5124 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5109 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5125 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5110 ('', 'style', '', _('template style to use'), _('STYLE')),
5126 ('', 'style', '', _('template style to use'), _('STYLE')),
5111 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5127 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5112 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5128 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5113 _('[OPTION]...'))
5129 _('[OPTION]...'))
5114 def serve(ui, repo, **opts):
5130 def serve(ui, repo, **opts):
5115 """start stand-alone webserver
5131 """start stand-alone webserver
5116
5132
5117 Start a local HTTP repository browser and pull server. You can use
5133 Start a local HTTP repository browser and pull server. You can use
5118 this for ad-hoc sharing and browsing of repositories. It is
5134 this for ad-hoc sharing and browsing of repositories. It is
5119 recommended to use a real web server to serve a repository for
5135 recommended to use a real web server to serve a repository for
5120 longer periods of time.
5136 longer periods of time.
5121
5137
5122 Please note that the server does not implement access control.
5138 Please note that the server does not implement access control.
5123 This means that, by default, anybody can read from the server and
5139 This means that, by default, anybody can read from the server and
5124 nobody can write to it by default. Set the ``web.allow_push``
5140 nobody can write to it by default. Set the ``web.allow_push``
5125 option to ``*`` to allow everybody to push to the server. You
5141 option to ``*`` to allow everybody to push to the server. You
5126 should use a real web server if you need to authenticate users.
5142 should use a real web server if you need to authenticate users.
5127
5143
5128 By default, the server logs accesses to stdout and errors to
5144 By default, the server logs accesses to stdout and errors to
5129 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5145 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5130 files.
5146 files.
5131
5147
5132 To have the server choose a free port number to listen on, specify
5148 To have the server choose a free port number to listen on, specify
5133 a port number of 0; in this case, the server will print the port
5149 a port number of 0; in this case, the server will print the port
5134 number it uses.
5150 number it uses.
5135
5151
5136 Returns 0 on success.
5152 Returns 0 on success.
5137 """
5153 """
5138
5154
5139 if opts["stdio"] and opts["cmdserver"]:
5155 if opts["stdio"] and opts["cmdserver"]:
5140 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5156 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5141
5157
5142 def checkrepo():
5158 def checkrepo():
5143 if repo is None:
5159 if repo is None:
5144 raise error.RepoError(_("there is no Mercurial repository here"
5160 raise error.RepoError(_("there is no Mercurial repository here"
5145 " (.hg not found)"))
5161 " (.hg not found)"))
5146
5162
5147 if opts["stdio"]:
5163 if opts["stdio"]:
5148 checkrepo()
5164 checkrepo()
5149 s = sshserver.sshserver(ui, repo)
5165 s = sshserver.sshserver(ui, repo)
5150 s.serve_forever()
5166 s.serve_forever()
5151
5167
5152 if opts["cmdserver"]:
5168 if opts["cmdserver"]:
5153 checkrepo()
5169 checkrepo()
5154 s = commandserver.server(ui, repo, opts["cmdserver"])
5170 s = commandserver.server(ui, repo, opts["cmdserver"])
5155 return s.serve()
5171 return s.serve()
5156
5172
5157 # this way we can check if something was given in the command-line
5173 # this way we can check if something was given in the command-line
5158 if opts.get('port'):
5174 if opts.get('port'):
5159 opts['port'] = util.getport(opts.get('port'))
5175 opts['port'] = util.getport(opts.get('port'))
5160
5176
5161 baseui = repo and repo.baseui or ui
5177 baseui = repo and repo.baseui or ui
5162 optlist = ("name templates style address port prefix ipv6"
5178 optlist = ("name templates style address port prefix ipv6"
5163 " accesslog errorlog certificate encoding")
5179 " accesslog errorlog certificate encoding")
5164 for o in optlist.split():
5180 for o in optlist.split():
5165 val = opts.get(o, '')
5181 val = opts.get(o, '')
5166 if val in (None, ''): # should check against default options instead
5182 if val in (None, ''): # should check against default options instead
5167 continue
5183 continue
5168 baseui.setconfig("web", o, val)
5184 baseui.setconfig("web", o, val)
5169 if repo and repo.ui != baseui:
5185 if repo and repo.ui != baseui:
5170 repo.ui.setconfig("web", o, val)
5186 repo.ui.setconfig("web", o, val)
5171
5187
5172 o = opts.get('web_conf') or opts.get('webdir_conf')
5188 o = opts.get('web_conf') or opts.get('webdir_conf')
5173 if not o:
5189 if not o:
5174 if not repo:
5190 if not repo:
5175 raise error.RepoError(_("there is no Mercurial repository"
5191 raise error.RepoError(_("there is no Mercurial repository"
5176 " here (.hg not found)"))
5192 " here (.hg not found)"))
5177 o = repo
5193 o = repo
5178
5194
5179 app = hgweb.hgweb(o, baseui=baseui)
5195 app = hgweb.hgweb(o, baseui=baseui)
5180 service = httpservice(ui, app, opts)
5196 service = httpservice(ui, app, opts)
5181 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5197 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5182
5198
5183 class httpservice(object):
5199 class httpservice(object):
5184 def __init__(self, ui, app, opts):
5200 def __init__(self, ui, app, opts):
5185 self.ui = ui
5201 self.ui = ui
5186 self.app = app
5202 self.app = app
5187 self.opts = opts
5203 self.opts = opts
5188
5204
5189 def init(self):
5205 def init(self):
5190 util.setsignalhandler()
5206 util.setsignalhandler()
5191 self.httpd = hgweb_server.create_server(self.ui, self.app)
5207 self.httpd = hgweb_server.create_server(self.ui, self.app)
5192
5208
5193 if self.opts['port'] and not self.ui.verbose:
5209 if self.opts['port'] and not self.ui.verbose:
5194 return
5210 return
5195
5211
5196 if self.httpd.prefix:
5212 if self.httpd.prefix:
5197 prefix = self.httpd.prefix.strip('/') + '/'
5213 prefix = self.httpd.prefix.strip('/') + '/'
5198 else:
5214 else:
5199 prefix = ''
5215 prefix = ''
5200
5216
5201 port = ':%d' % self.httpd.port
5217 port = ':%d' % self.httpd.port
5202 if port == ':80':
5218 if port == ':80':
5203 port = ''
5219 port = ''
5204
5220
5205 bindaddr = self.httpd.addr
5221 bindaddr = self.httpd.addr
5206 if bindaddr == '0.0.0.0':
5222 if bindaddr == '0.0.0.0':
5207 bindaddr = '*'
5223 bindaddr = '*'
5208 elif ':' in bindaddr: # IPv6
5224 elif ':' in bindaddr: # IPv6
5209 bindaddr = '[%s]' % bindaddr
5225 bindaddr = '[%s]' % bindaddr
5210
5226
5211 fqaddr = self.httpd.fqaddr
5227 fqaddr = self.httpd.fqaddr
5212 if ':' in fqaddr:
5228 if ':' in fqaddr:
5213 fqaddr = '[%s]' % fqaddr
5229 fqaddr = '[%s]' % fqaddr
5214 if self.opts['port']:
5230 if self.opts['port']:
5215 write = self.ui.status
5231 write = self.ui.status
5216 else:
5232 else:
5217 write = self.ui.write
5233 write = self.ui.write
5218 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5234 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5219 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5235 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5220
5236
5221 def run(self):
5237 def run(self):
5222 self.httpd.serve_forever()
5238 self.httpd.serve_forever()
5223
5239
5224
5240
5225 @command('^status|st',
5241 @command('^status|st',
5226 [('A', 'all', None, _('show status of all files')),
5242 [('A', 'all', None, _('show status of all files')),
5227 ('m', 'modified', None, _('show only modified files')),
5243 ('m', 'modified', None, _('show only modified files')),
5228 ('a', 'added', None, _('show only added files')),
5244 ('a', 'added', None, _('show only added files')),
5229 ('r', 'removed', None, _('show only removed files')),
5245 ('r', 'removed', None, _('show only removed files')),
5230 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5246 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5231 ('c', 'clean', None, _('show only files without changes')),
5247 ('c', 'clean', None, _('show only files without changes')),
5232 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5248 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5233 ('i', 'ignored', None, _('show only ignored files')),
5249 ('i', 'ignored', None, _('show only ignored files')),
5234 ('n', 'no-status', None, _('hide status prefix')),
5250 ('n', 'no-status', None, _('hide status prefix')),
5235 ('C', 'copies', None, _('show source of copied files')),
5251 ('C', 'copies', None, _('show source of copied files')),
5236 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5252 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5237 ('', 'rev', [], _('show difference from revision'), _('REV')),
5253 ('', 'rev', [], _('show difference from revision'), _('REV')),
5238 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5254 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5239 ] + walkopts + subrepoopts,
5255 ] + walkopts + subrepoopts,
5240 _('[OPTION]... [FILE]...'))
5256 _('[OPTION]... [FILE]...'))
5241 def status(ui, repo, *pats, **opts):
5257 def status(ui, repo, *pats, **opts):
5242 """show changed files in the working directory
5258 """show changed files in the working directory
5243
5259
5244 Show status of files in the repository. If names are given, only
5260 Show status of files in the repository. If names are given, only
5245 files that match are shown. Files that are clean or ignored or
5261 files that match are shown. Files that are clean or ignored or
5246 the source of a copy/move operation, are not listed unless
5262 the source of a copy/move operation, are not listed unless
5247 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5263 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5248 Unless options described with "show only ..." are given, the
5264 Unless options described with "show only ..." are given, the
5249 options -mardu are used.
5265 options -mardu are used.
5250
5266
5251 Option -q/--quiet hides untracked (unknown and ignored) files
5267 Option -q/--quiet hides untracked (unknown and ignored) files
5252 unless explicitly requested with -u/--unknown or -i/--ignored.
5268 unless explicitly requested with -u/--unknown or -i/--ignored.
5253
5269
5254 .. note::
5270 .. note::
5255
5271
5256 status may appear to disagree with diff if permissions have
5272 status may appear to disagree with diff if permissions have
5257 changed or a merge has occurred. The standard diff format does
5273 changed or a merge has occurred. The standard diff format does
5258 not report permission changes and diff only reports changes
5274 not report permission changes and diff only reports changes
5259 relative to one merge parent.
5275 relative to one merge parent.
5260
5276
5261 If one revision is given, it is used as the base revision.
5277 If one revision is given, it is used as the base revision.
5262 If two revisions are given, the differences between them are
5278 If two revisions are given, the differences between them are
5263 shown. The --change option can also be used as a shortcut to list
5279 shown. The --change option can also be used as a shortcut to list
5264 the changed files of a revision from its first parent.
5280 the changed files of a revision from its first parent.
5265
5281
5266 The codes used to show the status of files are::
5282 The codes used to show the status of files are::
5267
5283
5268 M = modified
5284 M = modified
5269 A = added
5285 A = added
5270 R = removed
5286 R = removed
5271 C = clean
5287 C = clean
5272 ! = missing (deleted by non-hg command, but still tracked)
5288 ! = missing (deleted by non-hg command, but still tracked)
5273 ? = not tracked
5289 ? = not tracked
5274 I = ignored
5290 I = ignored
5275 = origin of the previous file listed as A (added)
5291 = origin of the previous file listed as A (added)
5276
5292
5277 .. container:: verbose
5293 .. container:: verbose
5278
5294
5279 Examples:
5295 Examples:
5280
5296
5281 - show changes in the working directory relative to a
5297 - show changes in the working directory relative to a
5282 changeset::
5298 changeset::
5283
5299
5284 hg status --rev 9353
5300 hg status --rev 9353
5285
5301
5286 - show all changes including copies in an existing changeset::
5302 - show all changes including copies in an existing changeset::
5287
5303
5288 hg status --copies --change 9353
5304 hg status --copies --change 9353
5289
5305
5290 - get a NUL separated list of added files, suitable for xargs::
5306 - get a NUL separated list of added files, suitable for xargs::
5291
5307
5292 hg status -an0
5308 hg status -an0
5293
5309
5294 Returns 0 on success.
5310 Returns 0 on success.
5295 """
5311 """
5296
5312
5297 revs = opts.get('rev')
5313 revs = opts.get('rev')
5298 change = opts.get('change')
5314 change = opts.get('change')
5299
5315
5300 if revs and change:
5316 if revs and change:
5301 msg = _('cannot specify --rev and --change at the same time')
5317 msg = _('cannot specify --rev and --change at the same time')
5302 raise util.Abort(msg)
5318 raise util.Abort(msg)
5303 elif change:
5319 elif change:
5304 node2 = scmutil.revsingle(repo, change, None).node()
5320 node2 = scmutil.revsingle(repo, change, None).node()
5305 node1 = repo[node2].p1().node()
5321 node1 = repo[node2].p1().node()
5306 else:
5322 else:
5307 node1, node2 = scmutil.revpair(repo, revs)
5323 node1, node2 = scmutil.revpair(repo, revs)
5308
5324
5309 cwd = (pats and repo.getcwd()) or ''
5325 cwd = (pats and repo.getcwd()) or ''
5310 end = opts.get('print0') and '\0' or '\n'
5326 end = opts.get('print0') and '\0' or '\n'
5311 copy = {}
5327 copy = {}
5312 states = 'modified added removed deleted unknown ignored clean'.split()
5328 states = 'modified added removed deleted unknown ignored clean'.split()
5313 show = [k for k in states if opts.get(k)]
5329 show = [k for k in states if opts.get(k)]
5314 if opts.get('all'):
5330 if opts.get('all'):
5315 show += ui.quiet and (states[:4] + ['clean']) or states
5331 show += ui.quiet and (states[:4] + ['clean']) or states
5316 if not show:
5332 if not show:
5317 show = ui.quiet and states[:4] or states[:5]
5333 show = ui.quiet and states[:4] or states[:5]
5318
5334
5319 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5335 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5320 'ignored' in show, 'clean' in show, 'unknown' in show,
5336 'ignored' in show, 'clean' in show, 'unknown' in show,
5321 opts.get('subrepos'))
5337 opts.get('subrepos'))
5322 changestates = zip(states, 'MAR!?IC', stat)
5338 changestates = zip(states, 'MAR!?IC', stat)
5323
5339
5324 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5340 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5325 copy = copies.pathcopies(repo[node1], repo[node2])
5341 copy = copies.pathcopies(repo[node1], repo[node2])
5326
5342
5327 fm = ui.formatter('status', opts)
5343 fm = ui.formatter('status', opts)
5328 fmt = '%s' + end
5344 fmt = '%s' + end
5329 showchar = not opts.get('no_status')
5345 showchar = not opts.get('no_status')
5330
5346
5331 for state, char, files in changestates:
5347 for state, char, files in changestates:
5332 if state in show:
5348 if state in show:
5333 label = 'status.' + state
5349 label = 'status.' + state
5334 for f in files:
5350 for f in files:
5335 fm.startitem()
5351 fm.startitem()
5336 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5352 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5337 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5353 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5338 if f in copy:
5354 if f in copy:
5339 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5355 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5340 label='status.copied')
5356 label='status.copied')
5341 fm.end()
5357 fm.end()
5342
5358
5343 @command('^summary|sum',
5359 @command('^summary|sum',
5344 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5360 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5345 def summary(ui, repo, **opts):
5361 def summary(ui, repo, **opts):
5346 """summarize working directory state
5362 """summarize working directory state
5347
5363
5348 This generates a brief summary of the working directory state,
5364 This generates a brief summary of the working directory state,
5349 including parents, branch, commit status, and available updates.
5365 including parents, branch, commit status, and available updates.
5350
5366
5351 With the --remote option, this will check the default paths for
5367 With the --remote option, this will check the default paths for
5352 incoming and outgoing changes. This can be time-consuming.
5368 incoming and outgoing changes. This can be time-consuming.
5353
5369
5354 Returns 0 on success.
5370 Returns 0 on success.
5355 """
5371 """
5356
5372
5357 ctx = repo[None]
5373 ctx = repo[None]
5358 parents = ctx.parents()
5374 parents = ctx.parents()
5359 pnode = parents[0].node()
5375 pnode = parents[0].node()
5360 marks = []
5376 marks = []
5361
5377
5362 for p in parents:
5378 for p in parents:
5363 # label with log.changeset (instead of log.parent) since this
5379 # label with log.changeset (instead of log.parent) since this
5364 # shows a working directory parent *changeset*:
5380 # shows a working directory parent *changeset*:
5365 # i18n: column positioning for "hg summary"
5381 # i18n: column positioning for "hg summary"
5366 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5382 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5367 label='log.changeset changeset.%s' % p.phasestr())
5383 label='log.changeset changeset.%s' % p.phasestr())
5368 ui.write(' '.join(p.tags()), label='log.tag')
5384 ui.write(' '.join(p.tags()), label='log.tag')
5369 if p.bookmarks():
5385 if p.bookmarks():
5370 marks.extend(p.bookmarks())
5386 marks.extend(p.bookmarks())
5371 if p.rev() == -1:
5387 if p.rev() == -1:
5372 if not len(repo):
5388 if not len(repo):
5373 ui.write(_(' (empty repository)'))
5389 ui.write(_(' (empty repository)'))
5374 else:
5390 else:
5375 ui.write(_(' (no revision checked out)'))
5391 ui.write(_(' (no revision checked out)'))
5376 ui.write('\n')
5392 ui.write('\n')
5377 if p.description():
5393 if p.description():
5378 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5394 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5379 label='log.summary')
5395 label='log.summary')
5380
5396
5381 branch = ctx.branch()
5397 branch = ctx.branch()
5382 bheads = repo.branchheads(branch)
5398 bheads = repo.branchheads(branch)
5383 # i18n: column positioning for "hg summary"
5399 # i18n: column positioning for "hg summary"
5384 m = _('branch: %s\n') % branch
5400 m = _('branch: %s\n') % branch
5385 if branch != 'default':
5401 if branch != 'default':
5386 ui.write(m, label='log.branch')
5402 ui.write(m, label='log.branch')
5387 else:
5403 else:
5388 ui.status(m, label='log.branch')
5404 ui.status(m, label='log.branch')
5389
5405
5390 if marks:
5406 if marks:
5391 current = repo._bookmarkcurrent
5407 current = repo._bookmarkcurrent
5392 # i18n: column positioning for "hg summary"
5408 # i18n: column positioning for "hg summary"
5393 ui.write(_('bookmarks:'), label='log.bookmark')
5409 ui.write(_('bookmarks:'), label='log.bookmark')
5394 if current is not None:
5410 if current is not None:
5395 if current in marks:
5411 if current in marks:
5396 ui.write(' *' + current, label='bookmarks.current')
5412 ui.write(' *' + current, label='bookmarks.current')
5397 marks.remove(current)
5413 marks.remove(current)
5398 else:
5414 else:
5399 ui.write(' [%s]' % current, label='bookmarks.current')
5415 ui.write(' [%s]' % current, label='bookmarks.current')
5400 for m in marks:
5416 for m in marks:
5401 ui.write(' ' + m, label='log.bookmark')
5417 ui.write(' ' + m, label='log.bookmark')
5402 ui.write('\n', label='log.bookmark')
5418 ui.write('\n', label='log.bookmark')
5403
5419
5404 st = list(repo.status(unknown=True))[:6]
5420 st = list(repo.status(unknown=True))[:6]
5405
5421
5406 c = repo.dirstate.copies()
5422 c = repo.dirstate.copies()
5407 copied, renamed = [], []
5423 copied, renamed = [], []
5408 for d, s in c.iteritems():
5424 for d, s in c.iteritems():
5409 if s in st[2]:
5425 if s in st[2]:
5410 st[2].remove(s)
5426 st[2].remove(s)
5411 renamed.append(d)
5427 renamed.append(d)
5412 else:
5428 else:
5413 copied.append(d)
5429 copied.append(d)
5414 if d in st[1]:
5430 if d in st[1]:
5415 st[1].remove(d)
5431 st[1].remove(d)
5416 st.insert(3, renamed)
5432 st.insert(3, renamed)
5417 st.insert(4, copied)
5433 st.insert(4, copied)
5418
5434
5419 ms = mergemod.mergestate(repo)
5435 ms = mergemod.mergestate(repo)
5420 st.append([f for f in ms if ms[f] == 'u'])
5436 st.append([f for f in ms if ms[f] == 'u'])
5421
5437
5422 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5438 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5423 st.append(subs)
5439 st.append(subs)
5424
5440
5425 labels = [ui.label(_('%d modified'), 'status.modified'),
5441 labels = [ui.label(_('%d modified'), 'status.modified'),
5426 ui.label(_('%d added'), 'status.added'),
5442 ui.label(_('%d added'), 'status.added'),
5427 ui.label(_('%d removed'), 'status.removed'),
5443 ui.label(_('%d removed'), 'status.removed'),
5428 ui.label(_('%d renamed'), 'status.copied'),
5444 ui.label(_('%d renamed'), 'status.copied'),
5429 ui.label(_('%d copied'), 'status.copied'),
5445 ui.label(_('%d copied'), 'status.copied'),
5430 ui.label(_('%d deleted'), 'status.deleted'),
5446 ui.label(_('%d deleted'), 'status.deleted'),
5431 ui.label(_('%d unknown'), 'status.unknown'),
5447 ui.label(_('%d unknown'), 'status.unknown'),
5432 ui.label(_('%d ignored'), 'status.ignored'),
5448 ui.label(_('%d ignored'), 'status.ignored'),
5433 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5449 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5434 ui.label(_('%d subrepos'), 'status.modified')]
5450 ui.label(_('%d subrepos'), 'status.modified')]
5435 t = []
5451 t = []
5436 for s, l in zip(st, labels):
5452 for s, l in zip(st, labels):
5437 if s:
5453 if s:
5438 t.append(l % len(s))
5454 t.append(l % len(s))
5439
5455
5440 t = ', '.join(t)
5456 t = ', '.join(t)
5441 cleanworkdir = False
5457 cleanworkdir = False
5442
5458
5443 if repo.vfs.exists('updatestate'):
5459 if repo.vfs.exists('updatestate'):
5444 t += _(' (interrupted update)')
5460 t += _(' (interrupted update)')
5445 elif len(parents) > 1:
5461 elif len(parents) > 1:
5446 t += _(' (merge)')
5462 t += _(' (merge)')
5447 elif branch != parents[0].branch():
5463 elif branch != parents[0].branch():
5448 t += _(' (new branch)')
5464 t += _(' (new branch)')
5449 elif (parents[0].closesbranch() and
5465 elif (parents[0].closesbranch() and
5450 pnode in repo.branchheads(branch, closed=True)):
5466 pnode in repo.branchheads(branch, closed=True)):
5451 t += _(' (head closed)')
5467 t += _(' (head closed)')
5452 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5468 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5453 t += _(' (clean)')
5469 t += _(' (clean)')
5454 cleanworkdir = True
5470 cleanworkdir = True
5455 elif pnode not in bheads:
5471 elif pnode not in bheads:
5456 t += _(' (new branch head)')
5472 t += _(' (new branch head)')
5457
5473
5458 if cleanworkdir:
5474 if cleanworkdir:
5459 # i18n: column positioning for "hg summary"
5475 # i18n: column positioning for "hg summary"
5460 ui.status(_('commit: %s\n') % t.strip())
5476 ui.status(_('commit: %s\n') % t.strip())
5461 else:
5477 else:
5462 # i18n: column positioning for "hg summary"
5478 # i18n: column positioning for "hg summary"
5463 ui.write(_('commit: %s\n') % t.strip())
5479 ui.write(_('commit: %s\n') % t.strip())
5464
5480
5465 # all ancestors of branch heads - all ancestors of parent = new csets
5481 # all ancestors of branch heads - all ancestors of parent = new csets
5466 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5482 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5467 bheads))
5483 bheads))
5468
5484
5469 if new == 0:
5485 if new == 0:
5470 # i18n: column positioning for "hg summary"
5486 # i18n: column positioning for "hg summary"
5471 ui.status(_('update: (current)\n'))
5487 ui.status(_('update: (current)\n'))
5472 elif pnode not in bheads:
5488 elif pnode not in bheads:
5473 # i18n: column positioning for "hg summary"
5489 # i18n: column positioning for "hg summary"
5474 ui.write(_('update: %d new changesets (update)\n') % new)
5490 ui.write(_('update: %d new changesets (update)\n') % new)
5475 else:
5491 else:
5476 # i18n: column positioning for "hg summary"
5492 # i18n: column positioning for "hg summary"
5477 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5493 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5478 (new, len(bheads)))
5494 (new, len(bheads)))
5479
5495
5480 cmdutil.summaryhooks(ui, repo)
5496 cmdutil.summaryhooks(ui, repo)
5481
5497
5482 if opts.get('remote'):
5498 if opts.get('remote'):
5483 t = []
5499 t = []
5484 source, branches = hg.parseurl(ui.expandpath('default'))
5500 source, branches = hg.parseurl(ui.expandpath('default'))
5485 sbranch = branches[0]
5501 sbranch = branches[0]
5486 other = hg.peer(repo, {}, source)
5502 other = hg.peer(repo, {}, source)
5487 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5503 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5488 if revs:
5504 if revs:
5489 revs = [other.lookup(rev) for rev in revs]
5505 revs = [other.lookup(rev) for rev in revs]
5490 ui.debug('comparing with %s\n' % util.hidepassword(source))
5506 ui.debug('comparing with %s\n' % util.hidepassword(source))
5491 repo.ui.pushbuffer()
5507 repo.ui.pushbuffer()
5492 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5508 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5493 _common, incoming, _rheads = commoninc
5509 _common, incoming, _rheads = commoninc
5494 repo.ui.popbuffer()
5510 repo.ui.popbuffer()
5495 if incoming:
5511 if incoming:
5496 t.append(_('1 or more incoming'))
5512 t.append(_('1 or more incoming'))
5497
5513
5498 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5514 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5499 dbranch = branches[0]
5515 dbranch = branches[0]
5500 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5516 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5501 if source != dest:
5517 if source != dest:
5502 other = hg.peer(repo, {}, dest)
5518 other = hg.peer(repo, {}, dest)
5503 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5519 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5504 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5520 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5505 commoninc = None
5521 commoninc = None
5506 if revs:
5522 if revs:
5507 revs = [repo.lookup(rev) for rev in revs]
5523 revs = [repo.lookup(rev) for rev in revs]
5508 repo.ui.pushbuffer()
5524 repo.ui.pushbuffer()
5509 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5525 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5510 commoninc=commoninc)
5526 commoninc=commoninc)
5511 repo.ui.popbuffer()
5527 repo.ui.popbuffer()
5512 o = outgoing.missing
5528 o = outgoing.missing
5513 if o:
5529 if o:
5514 t.append(_('%d outgoing') % len(o))
5530 t.append(_('%d outgoing') % len(o))
5515 if 'bookmarks' in other.listkeys('namespaces'):
5531 if 'bookmarks' in other.listkeys('namespaces'):
5516 lmarks = repo.listkeys('bookmarks')
5532 lmarks = repo.listkeys('bookmarks')
5517 rmarks = other.listkeys('bookmarks')
5533 rmarks = other.listkeys('bookmarks')
5518 diff = set(rmarks) - set(lmarks)
5534 diff = set(rmarks) - set(lmarks)
5519 if len(diff) > 0:
5535 if len(diff) > 0:
5520 t.append(_('%d incoming bookmarks') % len(diff))
5536 t.append(_('%d incoming bookmarks') % len(diff))
5521 diff = set(lmarks) - set(rmarks)
5537 diff = set(lmarks) - set(rmarks)
5522 if len(diff) > 0:
5538 if len(diff) > 0:
5523 t.append(_('%d outgoing bookmarks') % len(diff))
5539 t.append(_('%d outgoing bookmarks') % len(diff))
5524
5540
5525 if t:
5541 if t:
5526 # i18n: column positioning for "hg summary"
5542 # i18n: column positioning for "hg summary"
5527 ui.write(_('remote: %s\n') % (', '.join(t)))
5543 ui.write(_('remote: %s\n') % (', '.join(t)))
5528 else:
5544 else:
5529 # i18n: column positioning for "hg summary"
5545 # i18n: column positioning for "hg summary"
5530 ui.status(_('remote: (synced)\n'))
5546 ui.status(_('remote: (synced)\n'))
5531
5547
5532 @command('tag',
5548 @command('tag',
5533 [('f', 'force', None, _('force tag')),
5549 [('f', 'force', None, _('force tag')),
5534 ('l', 'local', None, _('make the tag local')),
5550 ('l', 'local', None, _('make the tag local')),
5535 ('r', 'rev', '', _('revision to tag'), _('REV')),
5551 ('r', 'rev', '', _('revision to tag'), _('REV')),
5536 ('', 'remove', None, _('remove a tag')),
5552 ('', 'remove', None, _('remove a tag')),
5537 # -l/--local is already there, commitopts cannot be used
5553 # -l/--local is already there, commitopts cannot be used
5538 ('e', 'edit', None, _('edit commit message')),
5554 ('e', 'edit', None, _('edit commit message')),
5539 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5555 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5540 ] + commitopts2,
5556 ] + commitopts2,
5541 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5557 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5542 def tag(ui, repo, name1, *names, **opts):
5558 def tag(ui, repo, name1, *names, **opts):
5543 """add one or more tags for the current or given revision
5559 """add one or more tags for the current or given revision
5544
5560
5545 Name a particular revision using <name>.
5561 Name a particular revision using <name>.
5546
5562
5547 Tags are used to name particular revisions of the repository and are
5563 Tags are used to name particular revisions of the repository and are
5548 very useful to compare different revisions, to go back to significant
5564 very useful to compare different revisions, to go back to significant
5549 earlier versions or to mark branch points as releases, etc. Changing
5565 earlier versions or to mark branch points as releases, etc. Changing
5550 an existing tag is normally disallowed; use -f/--force to override.
5566 an existing tag is normally disallowed; use -f/--force to override.
5551
5567
5552 If no revision is given, the parent of the working directory is
5568 If no revision is given, the parent of the working directory is
5553 used.
5569 used.
5554
5570
5555 To facilitate version control, distribution, and merging of tags,
5571 To facilitate version control, distribution, and merging of tags,
5556 they are stored as a file named ".hgtags" which is managed similarly
5572 they are stored as a file named ".hgtags" which is managed similarly
5557 to other project files and can be hand-edited if necessary. This
5573 to other project files and can be hand-edited if necessary. This
5558 also means that tagging creates a new commit. The file
5574 also means that tagging creates a new commit. The file
5559 ".hg/localtags" is used for local tags (not shared among
5575 ".hg/localtags" is used for local tags (not shared among
5560 repositories).
5576 repositories).
5561
5577
5562 Tag commits are usually made at the head of a branch. If the parent
5578 Tag commits are usually made at the head of a branch. If the parent
5563 of the working directory is not a branch head, :hg:`tag` aborts; use
5579 of the working directory is not a branch head, :hg:`tag` aborts; use
5564 -f/--force to force the tag commit to be based on a non-head
5580 -f/--force to force the tag commit to be based on a non-head
5565 changeset.
5581 changeset.
5566
5582
5567 See :hg:`help dates` for a list of formats valid for -d/--date.
5583 See :hg:`help dates` for a list of formats valid for -d/--date.
5568
5584
5569 Since tag names have priority over branch names during revision
5585 Since tag names have priority over branch names during revision
5570 lookup, using an existing branch name as a tag name is discouraged.
5586 lookup, using an existing branch name as a tag name is discouraged.
5571
5587
5572 Returns 0 on success.
5588 Returns 0 on success.
5573 """
5589 """
5574 wlock = lock = None
5590 wlock = lock = None
5575 try:
5591 try:
5576 wlock = repo.wlock()
5592 wlock = repo.wlock()
5577 lock = repo.lock()
5593 lock = repo.lock()
5578 rev_ = "."
5594 rev_ = "."
5579 names = [t.strip() for t in (name1,) + names]
5595 names = [t.strip() for t in (name1,) + names]
5580 if len(names) != len(set(names)):
5596 if len(names) != len(set(names)):
5581 raise util.Abort(_('tag names must be unique'))
5597 raise util.Abort(_('tag names must be unique'))
5582 for n in names:
5598 for n in names:
5583 scmutil.checknewlabel(repo, n, 'tag')
5599 scmutil.checknewlabel(repo, n, 'tag')
5584 if not n:
5600 if not n:
5585 raise util.Abort(_('tag names cannot consist entirely of '
5601 raise util.Abort(_('tag names cannot consist entirely of '
5586 'whitespace'))
5602 'whitespace'))
5587 if opts.get('rev') and opts.get('remove'):
5603 if opts.get('rev') and opts.get('remove'):
5588 raise util.Abort(_("--rev and --remove are incompatible"))
5604 raise util.Abort(_("--rev and --remove are incompatible"))
5589 if opts.get('rev'):
5605 if opts.get('rev'):
5590 rev_ = opts['rev']
5606 rev_ = opts['rev']
5591 message = opts.get('message')
5607 message = opts.get('message')
5592 if opts.get('remove'):
5608 if opts.get('remove'):
5593 expectedtype = opts.get('local') and 'local' or 'global'
5609 expectedtype = opts.get('local') and 'local' or 'global'
5594 for n in names:
5610 for n in names:
5595 if not repo.tagtype(n):
5611 if not repo.tagtype(n):
5596 raise util.Abort(_("tag '%s' does not exist") % n)
5612 raise util.Abort(_("tag '%s' does not exist") % n)
5597 if repo.tagtype(n) != expectedtype:
5613 if repo.tagtype(n) != expectedtype:
5598 if expectedtype == 'global':
5614 if expectedtype == 'global':
5599 raise util.Abort(_("tag '%s' is not a global tag") % n)
5615 raise util.Abort(_("tag '%s' is not a global tag") % n)
5600 else:
5616 else:
5601 raise util.Abort(_("tag '%s' is not a local tag") % n)
5617 raise util.Abort(_("tag '%s' is not a local tag") % n)
5602 rev_ = nullid
5618 rev_ = nullid
5603 if not message:
5619 if not message:
5604 # we don't translate commit messages
5620 # we don't translate commit messages
5605 message = 'Removed tag %s' % ', '.join(names)
5621 message = 'Removed tag %s' % ', '.join(names)
5606 elif not opts.get('force'):
5622 elif not opts.get('force'):
5607 for n in names:
5623 for n in names:
5608 if n in repo.tags():
5624 if n in repo.tags():
5609 raise util.Abort(_("tag '%s' already exists "
5625 raise util.Abort(_("tag '%s' already exists "
5610 "(use -f to force)") % n)
5626 "(use -f to force)") % n)
5611 if not opts.get('local'):
5627 if not opts.get('local'):
5612 p1, p2 = repo.dirstate.parents()
5628 p1, p2 = repo.dirstate.parents()
5613 if p2 != nullid:
5629 if p2 != nullid:
5614 raise util.Abort(_('uncommitted merge'))
5630 raise util.Abort(_('uncommitted merge'))
5615 bheads = repo.branchheads()
5631 bheads = repo.branchheads()
5616 if not opts.get('force') and bheads and p1 not in bheads:
5632 if not opts.get('force') and bheads and p1 not in bheads:
5617 raise util.Abort(_('not at a branch head (use -f to force)'))
5633 raise util.Abort(_('not at a branch head (use -f to force)'))
5618 r = scmutil.revsingle(repo, rev_).node()
5634 r = scmutil.revsingle(repo, rev_).node()
5619
5635
5620 if not message:
5636 if not message:
5621 # we don't translate commit messages
5637 # we don't translate commit messages
5622 message = ('Added tag %s for changeset %s' %
5638 message = ('Added tag %s for changeset %s' %
5623 (', '.join(names), short(r)))
5639 (', '.join(names), short(r)))
5624
5640
5625 date = opts.get('date')
5641 date = opts.get('date')
5626 if date:
5642 if date:
5627 date = util.parsedate(date)
5643 date = util.parsedate(date)
5628
5644
5629 if opts.get('edit'):
5645 if opts.get('edit'):
5630 message = ui.edit(message, ui.username())
5646 message = ui.edit(message, ui.username())
5631
5647
5632 # don't allow tagging the null rev
5648 # don't allow tagging the null rev
5633 if (not opts.get('remove') and
5649 if (not opts.get('remove') and
5634 scmutil.revsingle(repo, rev_).rev() == nullrev):
5650 scmutil.revsingle(repo, rev_).rev() == nullrev):
5635 raise util.Abort(_("cannot tag null revision"))
5651 raise util.Abort(_("cannot tag null revision"))
5636
5652
5637 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5653 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5638 finally:
5654 finally:
5639 release(lock, wlock)
5655 release(lock, wlock)
5640
5656
5641 @command('tags', [], '')
5657 @command('tags', [], '')
5642 def tags(ui, repo, **opts):
5658 def tags(ui, repo, **opts):
5643 """list repository tags
5659 """list repository tags
5644
5660
5645 This lists both regular and local tags. When the -v/--verbose
5661 This lists both regular and local tags. When the -v/--verbose
5646 switch is used, a third column "local" is printed for local tags.
5662 switch is used, a third column "local" is printed for local tags.
5647
5663
5648 Returns 0 on success.
5664 Returns 0 on success.
5649 """
5665 """
5650
5666
5651 fm = ui.formatter('tags', opts)
5667 fm = ui.formatter('tags', opts)
5652 hexfunc = ui.debugflag and hex or short
5668 hexfunc = ui.debugflag and hex or short
5653 tagtype = ""
5669 tagtype = ""
5654
5670
5655 for t, n in reversed(repo.tagslist()):
5671 for t, n in reversed(repo.tagslist()):
5656 hn = hexfunc(n)
5672 hn = hexfunc(n)
5657 label = 'tags.normal'
5673 label = 'tags.normal'
5658 tagtype = ''
5674 tagtype = ''
5659 if repo.tagtype(t) == 'local':
5675 if repo.tagtype(t) == 'local':
5660 label = 'tags.local'
5676 label = 'tags.local'
5661 tagtype = 'local'
5677 tagtype = 'local'
5662
5678
5663 fm.startitem()
5679 fm.startitem()
5664 fm.write('tag', '%s', t, label=label)
5680 fm.write('tag', '%s', t, label=label)
5665 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5681 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5666 fm.condwrite(not ui.quiet, 'rev id', fmt,
5682 fm.condwrite(not ui.quiet, 'rev id', fmt,
5667 repo.changelog.rev(n), hn, label=label)
5683 repo.changelog.rev(n), hn, label=label)
5668 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5684 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5669 tagtype, label=label)
5685 tagtype, label=label)
5670 fm.plain('\n')
5686 fm.plain('\n')
5671 fm.end()
5687 fm.end()
5672
5688
5673 @command('tip',
5689 @command('tip',
5674 [('p', 'patch', None, _('show patch')),
5690 [('p', 'patch', None, _('show patch')),
5675 ('g', 'git', None, _('use git extended diff format')),
5691 ('g', 'git', None, _('use git extended diff format')),
5676 ] + templateopts,
5692 ] + templateopts,
5677 _('[-p] [-g]'))
5693 _('[-p] [-g]'))
5678 def tip(ui, repo, **opts):
5694 def tip(ui, repo, **opts):
5679 """show the tip revision (DEPRECATED)
5695 """show the tip revision (DEPRECATED)
5680
5696
5681 The tip revision (usually just called the tip) is the changeset
5697 The tip revision (usually just called the tip) is the changeset
5682 most recently added to the repository (and therefore the most
5698 most recently added to the repository (and therefore the most
5683 recently changed head).
5699 recently changed head).
5684
5700
5685 If you have just made a commit, that commit will be the tip. If
5701 If you have just made a commit, that commit will be the tip. If
5686 you have just pulled changes from another repository, the tip of
5702 you have just pulled changes from another repository, the tip of
5687 that repository becomes the current tip. The "tip" tag is special
5703 that repository becomes the current tip. The "tip" tag is special
5688 and cannot be renamed or assigned to a different changeset.
5704 and cannot be renamed or assigned to a different changeset.
5689
5705
5690 This command is deprecated, please use :hg:`heads` instead.
5706 This command is deprecated, please use :hg:`heads` instead.
5691
5707
5692 Returns 0 on success.
5708 Returns 0 on success.
5693 """
5709 """
5694 displayer = cmdutil.show_changeset(ui, repo, opts)
5710 displayer = cmdutil.show_changeset(ui, repo, opts)
5695 displayer.show(repo['tip'])
5711 displayer.show(repo['tip'])
5696 displayer.close()
5712 displayer.close()
5697
5713
5698 @command('unbundle',
5714 @command('unbundle',
5699 [('u', 'update', None,
5715 [('u', 'update', None,
5700 _('update to new branch head if changesets were unbundled'))],
5716 _('update to new branch head if changesets were unbundled'))],
5701 _('[-u] FILE...'))
5717 _('[-u] FILE...'))
5702 def unbundle(ui, repo, fname1, *fnames, **opts):
5718 def unbundle(ui, repo, fname1, *fnames, **opts):
5703 """apply one or more changegroup files
5719 """apply one or more changegroup files
5704
5720
5705 Apply one or more compressed changegroup files generated by the
5721 Apply one or more compressed changegroup files generated by the
5706 bundle command.
5722 bundle command.
5707
5723
5708 Returns 0 on success, 1 if an update has unresolved files.
5724 Returns 0 on success, 1 if an update has unresolved files.
5709 """
5725 """
5710 fnames = (fname1,) + fnames
5726 fnames = (fname1,) + fnames
5711
5727
5712 lock = repo.lock()
5728 lock = repo.lock()
5713 wc = repo['.']
5729 wc = repo['.']
5714 try:
5730 try:
5715 for fname in fnames:
5731 for fname in fnames:
5716 f = hg.openpath(ui, fname)
5732 f = hg.openpath(ui, fname)
5717 gen = changegroup.readbundle(f, fname)
5733 gen = changegroup.readbundle(f, fname)
5718 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5734 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5719 finally:
5735 finally:
5720 lock.release()
5736 lock.release()
5721 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5737 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5722 return postincoming(ui, repo, modheads, opts.get('update'), None)
5738 return postincoming(ui, repo, modheads, opts.get('update'), None)
5723
5739
5724 @command('^update|up|checkout|co',
5740 @command('^update|up|checkout|co',
5725 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5741 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5726 ('c', 'check', None,
5742 ('c', 'check', None,
5727 _('update across branches if no uncommitted changes')),
5743 _('update across branches if no uncommitted changes')),
5728 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5744 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5729 ('r', 'rev', '', _('revision'), _('REV'))],
5745 ('r', 'rev', '', _('revision'), _('REV'))],
5730 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5746 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5731 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5747 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5732 """update working directory (or switch revisions)
5748 """update working directory (or switch revisions)
5733
5749
5734 Update the repository's working directory to the specified
5750 Update the repository's working directory to the specified
5735 changeset. If no changeset is specified, update to the tip of the
5751 changeset. If no changeset is specified, update to the tip of the
5736 current named branch and move the current bookmark (see :hg:`help
5752 current named branch and move the current bookmark (see :hg:`help
5737 bookmarks`).
5753 bookmarks`).
5738
5754
5739 Update sets the working directory's parent revision to the specified
5755 Update sets the working directory's parent revision to the specified
5740 changeset (see :hg:`help parents`).
5756 changeset (see :hg:`help parents`).
5741
5757
5742 If the changeset is not a descendant or ancestor of the working
5758 If the changeset is not a descendant or ancestor of the working
5743 directory's parent, the update is aborted. With the -c/--check
5759 directory's parent, the update is aborted. With the -c/--check
5744 option, the working directory is checked for uncommitted changes; if
5760 option, the working directory is checked for uncommitted changes; if
5745 none are found, the working directory is updated to the specified
5761 none are found, the working directory is updated to the specified
5746 changeset.
5762 changeset.
5747
5763
5748 .. container:: verbose
5764 .. container:: verbose
5749
5765
5750 The following rules apply when the working directory contains
5766 The following rules apply when the working directory contains
5751 uncommitted changes:
5767 uncommitted changes:
5752
5768
5753 1. If neither -c/--check nor -C/--clean is specified, and if
5769 1. If neither -c/--check nor -C/--clean is specified, and if
5754 the requested changeset is an ancestor or descendant of
5770 the requested changeset is an ancestor or descendant of
5755 the working directory's parent, the uncommitted changes
5771 the working directory's parent, the uncommitted changes
5756 are merged into the requested changeset and the merged
5772 are merged into the requested changeset and the merged
5757 result is left uncommitted. If the requested changeset is
5773 result is left uncommitted. If the requested changeset is
5758 not an ancestor or descendant (that is, it is on another
5774 not an ancestor or descendant (that is, it is on another
5759 branch), the update is aborted and the uncommitted changes
5775 branch), the update is aborted and the uncommitted changes
5760 are preserved.
5776 are preserved.
5761
5777
5762 2. With the -c/--check option, the update is aborted and the
5778 2. With the -c/--check option, the update is aborted and the
5763 uncommitted changes are preserved.
5779 uncommitted changes are preserved.
5764
5780
5765 3. With the -C/--clean option, uncommitted changes are discarded and
5781 3. With the -C/--clean option, uncommitted changes are discarded and
5766 the working directory is updated to the requested changeset.
5782 the working directory is updated to the requested changeset.
5767
5783
5768 To cancel an uncommitted merge (and lose your changes), use
5784 To cancel an uncommitted merge (and lose your changes), use
5769 :hg:`update --clean .`.
5785 :hg:`update --clean .`.
5770
5786
5771 Use null as the changeset to remove the working directory (like
5787 Use null as the changeset to remove the working directory (like
5772 :hg:`clone -U`).
5788 :hg:`clone -U`).
5773
5789
5774 If you want to revert just one file to an older revision, use
5790 If you want to revert just one file to an older revision, use
5775 :hg:`revert [-r REV] NAME`.
5791 :hg:`revert [-r REV] NAME`.
5776
5792
5777 See :hg:`help dates` for a list of formats valid for -d/--date.
5793 See :hg:`help dates` for a list of formats valid for -d/--date.
5778
5794
5779 Returns 0 on success, 1 if there are unresolved files.
5795 Returns 0 on success, 1 if there are unresolved files.
5780 """
5796 """
5781 if rev and node:
5797 if rev and node:
5782 raise util.Abort(_("please specify just one revision"))
5798 raise util.Abort(_("please specify just one revision"))
5783
5799
5784 if rev is None or rev == '':
5800 if rev is None or rev == '':
5785 rev = node
5801 rev = node
5786
5802
5787 cmdutil.clearunfinished(repo)
5803 cmdutil.clearunfinished(repo)
5788
5804
5789 # with no argument, we also move the current bookmark, if any
5805 # with no argument, we also move the current bookmark, if any
5790 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5806 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5791
5807
5792 # if we defined a bookmark, we have to remember the original bookmark name
5808 # if we defined a bookmark, we have to remember the original bookmark name
5793 brev = rev
5809 brev = rev
5794 rev = scmutil.revsingle(repo, rev, rev).rev()
5810 rev = scmutil.revsingle(repo, rev, rev).rev()
5795
5811
5796 if check and clean:
5812 if check and clean:
5797 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5813 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5798
5814
5799 if date:
5815 if date:
5800 if rev is not None:
5816 if rev is not None:
5801 raise util.Abort(_("you can't specify a revision and a date"))
5817 raise util.Abort(_("you can't specify a revision and a date"))
5802 rev = cmdutil.finddate(ui, repo, date)
5818 rev = cmdutil.finddate(ui, repo, date)
5803
5819
5804 if check:
5820 if check:
5805 c = repo[None]
5821 c = repo[None]
5806 if c.dirty(merge=False, branch=False, missing=True):
5822 if c.dirty(merge=False, branch=False, missing=True):
5807 raise util.Abort(_("uncommitted changes"))
5823 raise util.Abort(_("uncommitted changes"))
5808 if rev is None:
5824 if rev is None:
5809 rev = repo[repo[None].branch()].rev()
5825 rev = repo[repo[None].branch()].rev()
5810 mergemod._checkunknown(repo, repo[None], repo[rev])
5826 mergemod._checkunknown(repo, repo[None], repo[rev])
5811
5827
5812 if clean:
5828 if clean:
5813 ret = hg.clean(repo, rev)
5829 ret = hg.clean(repo, rev)
5814 else:
5830 else:
5815 ret = hg.update(repo, rev)
5831 ret = hg.update(repo, rev)
5816
5832
5817 if not ret and movemarkfrom:
5833 if not ret and movemarkfrom:
5818 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5834 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5819 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5835 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5820 elif brev in repo._bookmarks:
5836 elif brev in repo._bookmarks:
5821 bookmarks.setcurrent(repo, brev)
5837 bookmarks.setcurrent(repo, brev)
5822 elif brev:
5838 elif brev:
5823 bookmarks.unsetcurrent(repo)
5839 bookmarks.unsetcurrent(repo)
5824
5840
5825 return ret
5841 return ret
5826
5842
5827 @command('verify', [])
5843 @command('verify', [])
5828 def verify(ui, repo):
5844 def verify(ui, repo):
5829 """verify the integrity of the repository
5845 """verify the integrity of the repository
5830
5846
5831 Verify the integrity of the current repository.
5847 Verify the integrity of the current repository.
5832
5848
5833 This will perform an extensive check of the repository's
5849 This will perform an extensive check of the repository's
5834 integrity, validating the hashes and checksums of each entry in
5850 integrity, validating the hashes and checksums of each entry in
5835 the changelog, manifest, and tracked files, as well as the
5851 the changelog, manifest, and tracked files, as well as the
5836 integrity of their crosslinks and indices.
5852 integrity of their crosslinks and indices.
5837
5853
5838 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5854 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5839 for more information about recovery from corruption of the
5855 for more information about recovery from corruption of the
5840 repository.
5856 repository.
5841
5857
5842 Returns 0 on success, 1 if errors are encountered.
5858 Returns 0 on success, 1 if errors are encountered.
5843 """
5859 """
5844 return hg.verify(repo)
5860 return hg.verify(repo)
5845
5861
5846 @command('version', [])
5862 @command('version', [])
5847 def version_(ui):
5863 def version_(ui):
5848 """output version and copyright information"""
5864 """output version and copyright information"""
5849 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5865 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5850 % util.version())
5866 % util.version())
5851 ui.status(_(
5867 ui.status(_(
5852 "(see http://mercurial.selenic.com for more information)\n"
5868 "(see http://mercurial.selenic.com for more information)\n"
5853 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5869 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5854 "This is free software; see the source for copying conditions. "
5870 "This is free software; see the source for copying conditions. "
5855 "There is NO\nwarranty; "
5871 "There is NO\nwarranty; "
5856 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5872 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5857 ))
5873 ))
5858
5874
5859 norepo = ("clone init version help debugcommands debugcomplete"
5875 norepo = ("clone init version help debugcommands debugcomplete"
5860 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5876 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5861 " debugknown debuggetbundle debugbundle")
5877 " debugknown debuggetbundle debugbundle")
5862 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5878 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5863 " debugdata debugindex debugindexdot debugrevlog")
5879 " debugdata debugindex debugindexdot debugrevlog")
5864 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5880 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5865 " remove resolve status debugwalk")
5881 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now