##// END OF EJS Templates
backout: correct commit status of no changes made (BC) (issue4190)...
Yuya Nishihara -
r20872:3f83fc5c 2.9.2 stable
parent child Browse files
Show More
@@ -1,5935 +1,5939 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, 1 if there are unresolved files.
419 Returns 0 on success, 1 if nothing to backout or there are unresolved
420 files.
420 '''
421 '''
421 if rev and node:
422 if rev and node:
422 raise util.Abort(_("please specify just one revision"))
423 raise util.Abort(_("please specify just one revision"))
423
424
424 if not rev:
425 if not rev:
425 rev = node
426 rev = node
426
427
427 if not rev:
428 if not rev:
428 raise util.Abort(_("please specify a revision to backout"))
429 raise util.Abort(_("please specify a revision to backout"))
429
430
430 date = opts.get('date')
431 date = opts.get('date')
431 if date:
432 if date:
432 opts['date'] = util.parsedate(date)
433 opts['date'] = util.parsedate(date)
433
434
434 cmdutil.checkunfinished(repo)
435 cmdutil.checkunfinished(repo)
435 cmdutil.bailifchanged(repo)
436 cmdutil.bailifchanged(repo)
436 node = scmutil.revsingle(repo, rev).node()
437 node = scmutil.revsingle(repo, rev).node()
437
438
438 op1, op2 = repo.dirstate.parents()
439 op1, op2 = repo.dirstate.parents()
439 a = repo.changelog.ancestor(op1, node)
440 a = repo.changelog.ancestor(op1, node)
440 if a != node:
441 if a != node:
441 raise util.Abort(_('cannot backout change on a different branch'))
442 raise util.Abort(_('cannot backout change on a different branch'))
442
443
443 p1, p2 = repo.changelog.parents(node)
444 p1, p2 = repo.changelog.parents(node)
444 if p1 == nullid:
445 if p1 == nullid:
445 raise util.Abort(_('cannot backout a change with no parents'))
446 raise util.Abort(_('cannot backout a change with no parents'))
446 if p2 != nullid:
447 if p2 != nullid:
447 if not opts.get('parent'):
448 if not opts.get('parent'):
448 raise util.Abort(_('cannot backout a merge changeset'))
449 raise util.Abort(_('cannot backout a merge changeset'))
449 p = repo.lookup(opts['parent'])
450 p = repo.lookup(opts['parent'])
450 if p not in (p1, p2):
451 if p not in (p1, p2):
451 raise util.Abort(_('%s is not a parent of %s') %
452 raise util.Abort(_('%s is not a parent of %s') %
452 (short(p), short(node)))
453 (short(p), short(node)))
453 parent = p
454 parent = p
454 else:
455 else:
455 if opts.get('parent'):
456 if opts.get('parent'):
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 parent = p1
458 parent = p1
458
459
459 # the backout should appear on the same branch
460 # the backout should appear on the same branch
460 wlock = repo.wlock()
461 wlock = repo.wlock()
461 try:
462 try:
462 branch = repo.dirstate.branch()
463 branch = repo.dirstate.branch()
463 bheads = repo.branchheads(branch)
464 bheads = repo.branchheads(branch)
464 rctx = scmutil.revsingle(repo, hex(parent))
465 rctx = scmutil.revsingle(repo, hex(parent))
465 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
466 try:
467 try:
467 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 stats = mergemod.update(repo, parent, True, True, False,
469 stats = mergemod.update(repo, parent, True, True, False,
469 node, False)
470 node, False)
470 repo.setparents(op1, op2)
471 repo.setparents(op1, op2)
471 hg._showstats(repo, stats)
472 hg._showstats(repo, stats)
472 if stats[3]:
473 if stats[3]:
473 repo.ui.status(_("use 'hg resolve' to retry unresolved "
474 repo.ui.status(_("use 'hg resolve' to retry unresolved "
474 "file merges\n"))
475 "file merges\n"))
475 else:
476 else:
476 msg = _("changeset %s backed out, "
477 msg = _("changeset %s backed out, "
477 "don't forget to commit.\n")
478 "don't forget to commit.\n")
478 ui.status(msg % short(node))
479 ui.status(msg % short(node))
479 return stats[3] > 0
480 return stats[3] > 0
480 finally:
481 finally:
481 ui.setconfig('ui', 'forcemerge', '')
482 ui.setconfig('ui', 'forcemerge', '')
482 else:
483 else:
483 hg.clean(repo, node, show_stats=False)
484 hg.clean(repo, node, show_stats=False)
484 repo.dirstate.setbranch(branch)
485 repo.dirstate.setbranch(branch)
485 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
486 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
486
487
487
488
488 e = cmdutil.commiteditor
489 e = cmdutil.commiteditor
489 if not opts['message'] and not opts['logfile']:
490 if not opts['message'] and not opts['logfile']:
490 # we don't translate commit messages
491 # we don't translate commit messages
491 opts['message'] = "Backed out changeset %s" % short(node)
492 opts['message'] = "Backed out changeset %s" % short(node)
492 e = cmdutil.commitforceeditor
493 e = cmdutil.commitforceeditor
493
494
494 def commitfunc(ui, repo, message, match, opts):
495 def commitfunc(ui, repo, message, match, opts):
495 return repo.commit(message, opts.get('user'), opts.get('date'),
496 return repo.commit(message, opts.get('user'), opts.get('date'),
496 match, editor=e)
497 match, editor=e)
497 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
498 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
499 if not newnode:
500 ui.status(_("nothing changed\n"))
501 return 1
498 cmdutil.commitstatus(repo, newnode, branch, bheads)
502 cmdutil.commitstatus(repo, newnode, branch, bheads)
499
503
500 def nice(node):
504 def nice(node):
501 return '%d:%s' % (repo.changelog.rev(node), short(node))
505 return '%d:%s' % (repo.changelog.rev(node), short(node))
502 ui.status(_('changeset %s backs out changeset %s\n') %
506 ui.status(_('changeset %s backs out changeset %s\n') %
503 (nice(repo.changelog.tip()), nice(node)))
507 (nice(repo.changelog.tip()), nice(node)))
504 if opts.get('merge') and op1 != node:
508 if opts.get('merge') and op1 != node:
505 hg.clean(repo, op1, show_stats=False)
509 hg.clean(repo, op1, show_stats=False)
506 ui.status(_('merging with changeset %s\n')
510 ui.status(_('merging with changeset %s\n')
507 % nice(repo.changelog.tip()))
511 % nice(repo.changelog.tip()))
508 try:
512 try:
509 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
513 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
510 return hg.merge(repo, hex(repo.changelog.tip()))
514 return hg.merge(repo, hex(repo.changelog.tip()))
511 finally:
515 finally:
512 ui.setconfig('ui', 'forcemerge', '')
516 ui.setconfig('ui', 'forcemerge', '')
513 finally:
517 finally:
514 wlock.release()
518 wlock.release()
515 return 0
519 return 0
516
520
517 @command('bisect',
521 @command('bisect',
518 [('r', 'reset', False, _('reset bisect state')),
522 [('r', 'reset', False, _('reset bisect state')),
519 ('g', 'good', False, _('mark changeset good')),
523 ('g', 'good', False, _('mark changeset good')),
520 ('b', 'bad', False, _('mark changeset bad')),
524 ('b', 'bad', False, _('mark changeset bad')),
521 ('s', 'skip', False, _('skip testing changeset')),
525 ('s', 'skip', False, _('skip testing changeset')),
522 ('e', 'extend', False, _('extend the bisect range')),
526 ('e', 'extend', False, _('extend the bisect range')),
523 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
527 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
524 ('U', 'noupdate', False, _('do not update to target'))],
528 ('U', 'noupdate', False, _('do not update to target'))],
525 _("[-gbsr] [-U] [-c CMD] [REV]"))
529 _("[-gbsr] [-U] [-c CMD] [REV]"))
526 def bisect(ui, repo, rev=None, extra=None, command=None,
530 def bisect(ui, repo, rev=None, extra=None, command=None,
527 reset=None, good=None, bad=None, skip=None, extend=None,
531 reset=None, good=None, bad=None, skip=None, extend=None,
528 noupdate=None):
532 noupdate=None):
529 """subdivision search of changesets
533 """subdivision search of changesets
530
534
531 This command helps to find changesets which introduce problems. To
535 This command helps to find changesets which introduce problems. To
532 use, mark the earliest changeset you know exhibits the problem as
536 use, mark the earliest changeset you know exhibits the problem as
533 bad, then mark the latest changeset which is free from the problem
537 bad, then mark the latest changeset which is free from the problem
534 as good. Bisect will update your working directory to a revision
538 as good. Bisect will update your working directory to a revision
535 for testing (unless the -U/--noupdate option is specified). Once
539 for testing (unless the -U/--noupdate option is specified). Once
536 you have performed tests, mark the working directory as good or
540 you have performed tests, mark the working directory as good or
537 bad, and bisect will either update to another candidate changeset
541 bad, and bisect will either update to another candidate changeset
538 or announce that it has found the bad revision.
542 or announce that it has found the bad revision.
539
543
540 As a shortcut, you can also use the revision argument to mark a
544 As a shortcut, you can also use the revision argument to mark a
541 revision as good or bad without checking it out first.
545 revision as good or bad without checking it out first.
542
546
543 If you supply a command, it will be used for automatic bisection.
547 If you supply a command, it will be used for automatic bisection.
544 The environment variable HG_NODE will contain the ID of the
548 The environment variable HG_NODE will contain the ID of the
545 changeset being tested. The exit status of the command will be
549 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
550 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
551 means to skip the revision, 127 (command not found) will abort the
548 bisection, and any other non-zero exit status means the revision
552 bisection, and any other non-zero exit status means the revision
549 is bad.
553 is bad.
550
554
551 .. container:: verbose
555 .. container:: verbose
552
556
553 Some examples:
557 Some examples:
554
558
555 - start a bisection with known bad revision 34, and good revision 12::
559 - start a bisection with known bad revision 34, and good revision 12::
556
560
557 hg bisect --bad 34
561 hg bisect --bad 34
558 hg bisect --good 12
562 hg bisect --good 12
559
563
560 - advance the current bisection by marking current revision as good or
564 - advance the current bisection by marking current revision as good or
561 bad::
565 bad::
562
566
563 hg bisect --good
567 hg bisect --good
564 hg bisect --bad
568 hg bisect --bad
565
569
566 - mark the current revision, or a known revision, to be skipped (e.g. if
570 - mark the current revision, or a known revision, to be skipped (e.g. if
567 that revision is not usable because of another issue)::
571 that revision is not usable because of another issue)::
568
572
569 hg bisect --skip
573 hg bisect --skip
570 hg bisect --skip 23
574 hg bisect --skip 23
571
575
572 - skip all revisions that do not touch directories ``foo`` or ``bar``::
576 - skip all revisions that do not touch directories ``foo`` or ``bar``::
573
577
574 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
578 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
575
579
576 - forget the current bisection::
580 - forget the current bisection::
577
581
578 hg bisect --reset
582 hg bisect --reset
579
583
580 - use 'make && make tests' to automatically find the first broken
584 - use 'make && make tests' to automatically find the first broken
581 revision::
585 revision::
582
586
583 hg bisect --reset
587 hg bisect --reset
584 hg bisect --bad 34
588 hg bisect --bad 34
585 hg bisect --good 12
589 hg bisect --good 12
586 hg bisect --command "make && make tests"
590 hg bisect --command "make && make tests"
587
591
588 - see all changesets whose states are already known in the current
592 - see all changesets whose states are already known in the current
589 bisection::
593 bisection::
590
594
591 hg log -r "bisect(pruned)"
595 hg log -r "bisect(pruned)"
592
596
593 - see the changeset currently being bisected (especially useful
597 - see the changeset currently being bisected (especially useful
594 if running with -U/--noupdate)::
598 if running with -U/--noupdate)::
595
599
596 hg log -r "bisect(current)"
600 hg log -r "bisect(current)"
597
601
598 - see all changesets that took part in the current bisection::
602 - see all changesets that took part in the current bisection::
599
603
600 hg log -r "bisect(range)"
604 hg log -r "bisect(range)"
601
605
602 - you can even get a nice graph::
606 - you can even get a nice graph::
603
607
604 hg log --graph -r "bisect(range)"
608 hg log --graph -r "bisect(range)"
605
609
606 See :hg:`help revsets` for more about the `bisect()` keyword.
610 See :hg:`help revsets` for more about the `bisect()` keyword.
607
611
608 Returns 0 on success.
612 Returns 0 on success.
609 """
613 """
610 def extendbisectrange(nodes, good):
614 def extendbisectrange(nodes, good):
611 # bisect is incomplete when it ends on a merge node and
615 # bisect is incomplete when it ends on a merge node and
612 # one of the parent was not checked.
616 # one of the parent was not checked.
613 parents = repo[nodes[0]].parents()
617 parents = repo[nodes[0]].parents()
614 if len(parents) > 1:
618 if len(parents) > 1:
615 side = good and state['bad'] or state['good']
619 side = good and state['bad'] or state['good']
616 num = len(set(i.node() for i in parents) & set(side))
620 num = len(set(i.node() for i in parents) & set(side))
617 if num == 1:
621 if num == 1:
618 return parents[0].ancestor(parents[1])
622 return parents[0].ancestor(parents[1])
619 return None
623 return None
620
624
621 def print_result(nodes, good):
625 def print_result(nodes, good):
622 displayer = cmdutil.show_changeset(ui, repo, {})
626 displayer = cmdutil.show_changeset(ui, repo, {})
623 if len(nodes) == 1:
627 if len(nodes) == 1:
624 # narrowed it down to a single revision
628 # narrowed it down to a single revision
625 if good:
629 if good:
626 ui.write(_("The first good revision is:\n"))
630 ui.write(_("The first good revision is:\n"))
627 else:
631 else:
628 ui.write(_("The first bad revision is:\n"))
632 ui.write(_("The first bad revision is:\n"))
629 displayer.show(repo[nodes[0]])
633 displayer.show(repo[nodes[0]])
630 extendnode = extendbisectrange(nodes, good)
634 extendnode = extendbisectrange(nodes, good)
631 if extendnode is not None:
635 if extendnode is not None:
632 ui.write(_('Not all ancestors of this changeset have been'
636 ui.write(_('Not all ancestors of this changeset have been'
633 ' checked.\nUse bisect --extend to continue the '
637 ' checked.\nUse bisect --extend to continue the '
634 'bisection from\nthe common ancestor, %s.\n')
638 'bisection from\nthe common ancestor, %s.\n')
635 % extendnode)
639 % extendnode)
636 else:
640 else:
637 # multiple possible revisions
641 # multiple possible revisions
638 if good:
642 if good:
639 ui.write(_("Due to skipped revisions, the first "
643 ui.write(_("Due to skipped revisions, the first "
640 "good revision could be any of:\n"))
644 "good revision could be any of:\n"))
641 else:
645 else:
642 ui.write(_("Due to skipped revisions, the first "
646 ui.write(_("Due to skipped revisions, the first "
643 "bad revision could be any of:\n"))
647 "bad revision could be any of:\n"))
644 for n in nodes:
648 for n in nodes:
645 displayer.show(repo[n])
649 displayer.show(repo[n])
646 displayer.close()
650 displayer.close()
647
651
648 def check_state(state, interactive=True):
652 def check_state(state, interactive=True):
649 if not state['good'] or not state['bad']:
653 if not state['good'] or not state['bad']:
650 if (good or bad or skip or reset) and interactive:
654 if (good or bad or skip or reset) and interactive:
651 return
655 return
652 if not state['good']:
656 if not state['good']:
653 raise util.Abort(_('cannot bisect (no known good revisions)'))
657 raise util.Abort(_('cannot bisect (no known good revisions)'))
654 else:
658 else:
655 raise util.Abort(_('cannot bisect (no known bad revisions)'))
659 raise util.Abort(_('cannot bisect (no known bad revisions)'))
656 return True
660 return True
657
661
658 # backward compatibility
662 # backward compatibility
659 if rev in "good bad reset init".split():
663 if rev in "good bad reset init".split():
660 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
664 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
661 cmd, rev, extra = rev, extra, None
665 cmd, rev, extra = rev, extra, None
662 if cmd == "good":
666 if cmd == "good":
663 good = True
667 good = True
664 elif cmd == "bad":
668 elif cmd == "bad":
665 bad = True
669 bad = True
666 else:
670 else:
667 reset = True
671 reset = True
668 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
672 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
669 raise util.Abort(_('incompatible arguments'))
673 raise util.Abort(_('incompatible arguments'))
670
674
671 cmdutil.checkunfinished(repo)
675 cmdutil.checkunfinished(repo)
672
676
673 if reset:
677 if reset:
674 p = repo.join("bisect.state")
678 p = repo.join("bisect.state")
675 if os.path.exists(p):
679 if os.path.exists(p):
676 os.unlink(p)
680 os.unlink(p)
677 return
681 return
678
682
679 state = hbisect.load_state(repo)
683 state = hbisect.load_state(repo)
680
684
681 if command:
685 if command:
682 changesets = 1
686 changesets = 1
683 if noupdate:
687 if noupdate:
684 try:
688 try:
685 node = state['current'][0]
689 node = state['current'][0]
686 except LookupError:
690 except LookupError:
687 raise util.Abort(_('current bisect revision is unknown - '
691 raise util.Abort(_('current bisect revision is unknown - '
688 'start a new bisect to fix'))
692 'start a new bisect to fix'))
689 else:
693 else:
690 node, p2 = repo.dirstate.parents()
694 node, p2 = repo.dirstate.parents()
691 if p2 != nullid:
695 if p2 != nullid:
692 raise util.Abort(_('current bisect revision is a merge'))
696 raise util.Abort(_('current bisect revision is a merge'))
693 try:
697 try:
694 while changesets:
698 while changesets:
695 # update state
699 # update state
696 state['current'] = [node]
700 state['current'] = [node]
697 hbisect.save_state(repo, state)
701 hbisect.save_state(repo, state)
698 status = util.system(command,
702 status = util.system(command,
699 environ={'HG_NODE': hex(node)},
703 environ={'HG_NODE': hex(node)},
700 out=ui.fout)
704 out=ui.fout)
701 if status == 125:
705 if status == 125:
702 transition = "skip"
706 transition = "skip"
703 elif status == 0:
707 elif status == 0:
704 transition = "good"
708 transition = "good"
705 # status < 0 means process was killed
709 # status < 0 means process was killed
706 elif status == 127:
710 elif status == 127:
707 raise util.Abort(_("failed to execute %s") % command)
711 raise util.Abort(_("failed to execute %s") % command)
708 elif status < 0:
712 elif status < 0:
709 raise util.Abort(_("%s killed") % command)
713 raise util.Abort(_("%s killed") % command)
710 else:
714 else:
711 transition = "bad"
715 transition = "bad"
712 ctx = scmutil.revsingle(repo, rev, node)
716 ctx = scmutil.revsingle(repo, rev, node)
713 rev = None # clear for future iterations
717 rev = None # clear for future iterations
714 state[transition].append(ctx.node())
718 state[transition].append(ctx.node())
715 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
719 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
716 check_state(state, interactive=False)
720 check_state(state, interactive=False)
717 # bisect
721 # bisect
718 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
722 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
719 # update to next check
723 # update to next check
720 node = nodes[0]
724 node = nodes[0]
721 if not noupdate:
725 if not noupdate:
722 cmdutil.bailifchanged(repo)
726 cmdutil.bailifchanged(repo)
723 hg.clean(repo, node, show_stats=False)
727 hg.clean(repo, node, show_stats=False)
724 finally:
728 finally:
725 state['current'] = [node]
729 state['current'] = [node]
726 hbisect.save_state(repo, state)
730 hbisect.save_state(repo, state)
727 print_result(nodes, bgood)
731 print_result(nodes, bgood)
728 return
732 return
729
733
730 # update state
734 # update state
731
735
732 if rev:
736 if rev:
733 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
737 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
734 else:
738 else:
735 nodes = [repo.lookup('.')]
739 nodes = [repo.lookup('.')]
736
740
737 if good or bad or skip:
741 if good or bad or skip:
738 if good:
742 if good:
739 state['good'] += nodes
743 state['good'] += nodes
740 elif bad:
744 elif bad:
741 state['bad'] += nodes
745 state['bad'] += nodes
742 elif skip:
746 elif skip:
743 state['skip'] += nodes
747 state['skip'] += nodes
744 hbisect.save_state(repo, state)
748 hbisect.save_state(repo, state)
745
749
746 if not check_state(state):
750 if not check_state(state):
747 return
751 return
748
752
749 # actually bisect
753 # actually bisect
750 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
754 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
751 if extend:
755 if extend:
752 if not changesets:
756 if not changesets:
753 extendnode = extendbisectrange(nodes, good)
757 extendnode = extendbisectrange(nodes, good)
754 if extendnode is not None:
758 if extendnode is not None:
755 ui.write(_("Extending search to changeset %d:%s\n")
759 ui.write(_("Extending search to changeset %d:%s\n")
756 % (extendnode.rev(), extendnode))
760 % (extendnode.rev(), extendnode))
757 state['current'] = [extendnode.node()]
761 state['current'] = [extendnode.node()]
758 hbisect.save_state(repo, state)
762 hbisect.save_state(repo, state)
759 if noupdate:
763 if noupdate:
760 return
764 return
761 cmdutil.bailifchanged(repo)
765 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, extendnode.node())
766 return hg.clean(repo, extendnode.node())
763 raise util.Abort(_("nothing to extend"))
767 raise util.Abort(_("nothing to extend"))
764
768
765 if changesets == 0:
769 if changesets == 0:
766 print_result(nodes, good)
770 print_result(nodes, good)
767 else:
771 else:
768 assert len(nodes) == 1 # only a single node can be tested next
772 assert len(nodes) == 1 # only a single node can be tested next
769 node = nodes[0]
773 node = nodes[0]
770 # compute the approximate number of remaining tests
774 # compute the approximate number of remaining tests
771 tests, size = 0, 2
775 tests, size = 0, 2
772 while size <= changesets:
776 while size <= changesets:
773 tests, size = tests + 1, size * 2
777 tests, size = tests + 1, size * 2
774 rev = repo.changelog.rev(node)
778 rev = repo.changelog.rev(node)
775 ui.write(_("Testing changeset %d:%s "
779 ui.write(_("Testing changeset %d:%s "
776 "(%d changesets remaining, ~%d tests)\n")
780 "(%d changesets remaining, ~%d tests)\n")
777 % (rev, short(node), changesets, tests))
781 % (rev, short(node), changesets, tests))
778 state['current'] = [node]
782 state['current'] = [node]
779 hbisect.save_state(repo, state)
783 hbisect.save_state(repo, state)
780 if not noupdate:
784 if not noupdate:
781 cmdutil.bailifchanged(repo)
785 cmdutil.bailifchanged(repo)
782 return hg.clean(repo, node)
786 return hg.clean(repo, node)
783
787
784 @command('bookmarks|bookmark',
788 @command('bookmarks|bookmark',
785 [('f', 'force', False, _('force')),
789 [('f', 'force', False, _('force')),
786 ('r', 'rev', '', _('revision'), _('REV')),
790 ('r', 'rev', '', _('revision'), _('REV')),
787 ('d', 'delete', False, _('delete a given bookmark')),
791 ('d', 'delete', False, _('delete a given bookmark')),
788 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
792 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
789 ('i', 'inactive', False, _('mark a bookmark inactive'))],
793 ('i', 'inactive', False, _('mark a bookmark inactive'))],
790 _('hg bookmarks [OPTIONS]... [NAME]...'))
794 _('hg bookmarks [OPTIONS]... [NAME]...'))
791 def bookmark(ui, repo, *names, **opts):
795 def bookmark(ui, repo, *names, **opts):
792 '''track a line of development with movable markers
796 '''track a line of development with movable markers
793
797
794 Bookmarks are pointers to certain commits that move when committing.
798 Bookmarks are pointers to certain commits that move when committing.
795 Bookmarks are local. They can be renamed, copied and deleted. It is
799 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
800 possible to use :hg:`merge NAME` to merge from a given bookmark, and
797 :hg:`update NAME` to update to a given bookmark.
801 :hg:`update NAME` to update to a given bookmark.
798
802
799 You can use :hg:`bookmark NAME` to set a bookmark on the working
803 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
804 directory's parent revision with the given name. If you specify
801 a revision using -r REV (where REV may be an existing bookmark),
805 a revision using -r REV (where REV may be an existing bookmark),
802 the bookmark is assigned to that revision.
806 the bookmark is assigned to that revision.
803
807
804 Bookmarks can be pushed and pulled between repositories (see :hg:`help
808 Bookmarks can be pushed and pulled between repositories (see :hg:`help
805 push` and :hg:`help pull`). This requires both the local and remote
809 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
810 repositories to support bookmarks. For versions prior to 1.8, this means
807 the bookmarks extension must be enabled.
811 the bookmarks extension must be enabled.
808
812
809 If you set a bookmark called '@', new clones of the repository will
813 If you set a bookmark called '@', new clones of the repository will
810 have that revision checked out (and the bookmark made active) by
814 have that revision checked out (and the bookmark made active) by
811 default.
815 default.
812
816
813 With -i/--inactive, the new bookmark will not be made the active
817 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
818 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
819 active even if -i/--inactive is not given. If no NAME is given, the
816 current active bookmark will be marked inactive.
820 current active bookmark will be marked inactive.
817 '''
821 '''
818 force = opts.get('force')
822 force = opts.get('force')
819 rev = opts.get('rev')
823 rev = opts.get('rev')
820 delete = opts.get('delete')
824 delete = opts.get('delete')
821 rename = opts.get('rename')
825 rename = opts.get('rename')
822 inactive = opts.get('inactive')
826 inactive = opts.get('inactive')
823
827
824 def checkformat(mark):
828 def checkformat(mark):
825 mark = mark.strip()
829 mark = mark.strip()
826 if not mark:
830 if not mark:
827 raise util.Abort(_("bookmark names cannot consist entirely of "
831 raise util.Abort(_("bookmark names cannot consist entirely of "
828 "whitespace"))
832 "whitespace"))
829 scmutil.checknewlabel(repo, mark, 'bookmark')
833 scmutil.checknewlabel(repo, mark, 'bookmark')
830 return mark
834 return mark
831
835
832 def checkconflict(repo, mark, cur, force=False, target=None):
836 def checkconflict(repo, mark, cur, force=False, target=None):
833 if mark in marks and not force:
837 if mark in marks and not force:
834 if target:
838 if target:
835 if marks[mark] == target and target == cur:
839 if marks[mark] == target and target == cur:
836 # re-activating a bookmark
840 # re-activating a bookmark
837 return
841 return
838 anc = repo.changelog.ancestors([repo[target].rev()])
842 anc = repo.changelog.ancestors([repo[target].rev()])
839 bmctx = repo[marks[mark]]
843 bmctx = repo[marks[mark]]
840 divs = [repo[b].node() for b in marks
844 divs = [repo[b].node() for b in marks
841 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
845 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
842
846
843 # allow resolving a single divergent bookmark even if moving
847 # allow resolving a single divergent bookmark even if moving
844 # the bookmark across branches when a revision is specified
848 # the bookmark across branches when a revision is specified
845 # that contains a divergent bookmark
849 # that contains a divergent bookmark
846 if bmctx.rev() not in anc and target in divs:
850 if bmctx.rev() not in anc and target in divs:
847 bookmarks.deletedivergent(repo, [target], mark)
851 bookmarks.deletedivergent(repo, [target], mark)
848 return
852 return
849
853
850 deletefrom = [b for b in divs
854 deletefrom = [b for b in divs
851 if repo[b].rev() in anc or b == target]
855 if repo[b].rev() in anc or b == target]
852 bookmarks.deletedivergent(repo, deletefrom, mark)
856 bookmarks.deletedivergent(repo, deletefrom, mark)
853 if bookmarks.validdest(repo, bmctx, repo[target]):
857 if bookmarks.validdest(repo, bmctx, repo[target]):
854 ui.status(_("moving bookmark '%s' forward from %s\n") %
858 ui.status(_("moving bookmark '%s' forward from %s\n") %
855 (mark, short(bmctx.node())))
859 (mark, short(bmctx.node())))
856 return
860 return
857 raise util.Abort(_("bookmark '%s' already exists "
861 raise util.Abort(_("bookmark '%s' already exists "
858 "(use -f to force)") % mark)
862 "(use -f to force)") % mark)
859 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
863 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
860 and not force):
864 and not force):
861 raise util.Abort(
865 raise util.Abort(
862 _("a bookmark cannot have the name of an existing branch"))
866 _("a bookmark cannot have the name of an existing branch"))
863
867
864 if delete and rename:
868 if delete and rename:
865 raise util.Abort(_("--delete and --rename are incompatible"))
869 raise util.Abort(_("--delete and --rename are incompatible"))
866 if delete and rev:
870 if delete and rev:
867 raise util.Abort(_("--rev is incompatible with --delete"))
871 raise util.Abort(_("--rev is incompatible with --delete"))
868 if rename and rev:
872 if rename and rev:
869 raise util.Abort(_("--rev is incompatible with --rename"))
873 raise util.Abort(_("--rev is incompatible with --rename"))
870 if not names and (delete or rev):
874 if not names and (delete or rev):
871 raise util.Abort(_("bookmark name required"))
875 raise util.Abort(_("bookmark name required"))
872
876
873 if delete or rename or names or inactive:
877 if delete or rename or names or inactive:
874 wlock = repo.wlock()
878 wlock = repo.wlock()
875 try:
879 try:
876 cur = repo.changectx('.').node()
880 cur = repo.changectx('.').node()
877 marks = repo._bookmarks
881 marks = repo._bookmarks
878 if delete:
882 if delete:
879 for mark in names:
883 for mark in names:
880 if mark not in marks:
884 if mark not in marks:
881 raise util.Abort(_("bookmark '%s' does not exist") %
885 raise util.Abort(_("bookmark '%s' does not exist") %
882 mark)
886 mark)
883 if mark == repo._bookmarkcurrent:
887 if mark == repo._bookmarkcurrent:
884 bookmarks.unsetcurrent(repo)
888 bookmarks.unsetcurrent(repo)
885 del marks[mark]
889 del marks[mark]
886 marks.write()
890 marks.write()
887
891
888 elif rename:
892 elif rename:
889 if not names:
893 if not names:
890 raise util.Abort(_("new bookmark name required"))
894 raise util.Abort(_("new bookmark name required"))
891 elif len(names) > 1:
895 elif len(names) > 1:
892 raise util.Abort(_("only one new bookmark name allowed"))
896 raise util.Abort(_("only one new bookmark name allowed"))
893 mark = checkformat(names[0])
897 mark = checkformat(names[0])
894 if rename not in marks:
898 if rename not in marks:
895 raise util.Abort(_("bookmark '%s' does not exist") % rename)
899 raise util.Abort(_("bookmark '%s' does not exist") % rename)
896 checkconflict(repo, mark, cur, force)
900 checkconflict(repo, mark, cur, force)
897 marks[mark] = marks[rename]
901 marks[mark] = marks[rename]
898 if repo._bookmarkcurrent == rename and not inactive:
902 if repo._bookmarkcurrent == rename and not inactive:
899 bookmarks.setcurrent(repo, mark)
903 bookmarks.setcurrent(repo, mark)
900 del marks[rename]
904 del marks[rename]
901 marks.write()
905 marks.write()
902
906
903 elif names:
907 elif names:
904 newact = None
908 newact = None
905 for mark in names:
909 for mark in names:
906 mark = checkformat(mark)
910 mark = checkformat(mark)
907 if newact is None:
911 if newact is None:
908 newact = mark
912 newact = mark
909 if inactive and mark == repo._bookmarkcurrent:
913 if inactive and mark == repo._bookmarkcurrent:
910 bookmarks.unsetcurrent(repo)
914 bookmarks.unsetcurrent(repo)
911 return
915 return
912 tgt = cur
916 tgt = cur
913 if rev:
917 if rev:
914 tgt = scmutil.revsingle(repo, rev).node()
918 tgt = scmutil.revsingle(repo, rev).node()
915 checkconflict(repo, mark, cur, force, tgt)
919 checkconflict(repo, mark, cur, force, tgt)
916 marks[mark] = tgt
920 marks[mark] = tgt
917 if not inactive and cur == marks[newact] and not rev:
921 if not inactive and cur == marks[newact] and not rev:
918 bookmarks.setcurrent(repo, newact)
922 bookmarks.setcurrent(repo, newact)
919 elif cur != tgt and newact == repo._bookmarkcurrent:
923 elif cur != tgt and newact == repo._bookmarkcurrent:
920 bookmarks.unsetcurrent(repo)
924 bookmarks.unsetcurrent(repo)
921 marks.write()
925 marks.write()
922
926
923 elif inactive:
927 elif inactive:
924 if len(marks) == 0:
928 if len(marks) == 0:
925 ui.status(_("no bookmarks set\n"))
929 ui.status(_("no bookmarks set\n"))
926 elif not repo._bookmarkcurrent:
930 elif not repo._bookmarkcurrent:
927 ui.status(_("no active bookmark\n"))
931 ui.status(_("no active bookmark\n"))
928 else:
932 else:
929 bookmarks.unsetcurrent(repo)
933 bookmarks.unsetcurrent(repo)
930 finally:
934 finally:
931 wlock.release()
935 wlock.release()
932 else: # show bookmarks
936 else: # show bookmarks
933 hexfn = ui.debugflag and hex or short
937 hexfn = ui.debugflag and hex or short
934 marks = repo._bookmarks
938 marks = repo._bookmarks
935 if len(marks) == 0:
939 if len(marks) == 0:
936 ui.status(_("no bookmarks set\n"))
940 ui.status(_("no bookmarks set\n"))
937 else:
941 else:
938 for bmark, n in sorted(marks.iteritems()):
942 for bmark, n in sorted(marks.iteritems()):
939 current = repo._bookmarkcurrent
943 current = repo._bookmarkcurrent
940 if bmark == current:
944 if bmark == current:
941 prefix, label = '*', 'bookmarks.current'
945 prefix, label = '*', 'bookmarks.current'
942 else:
946 else:
943 prefix, label = ' ', ''
947 prefix, label = ' ', ''
944
948
945 if ui.quiet:
949 if ui.quiet:
946 ui.write("%s\n" % bmark, label=label)
950 ui.write("%s\n" % bmark, label=label)
947 else:
951 else:
948 ui.write(" %s %-25s %d:%s\n" % (
952 ui.write(" %s %-25s %d:%s\n" % (
949 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
953 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
950 label=label)
954 label=label)
951
955
952 @command('branch',
956 @command('branch',
953 [('f', 'force', None,
957 [('f', 'force', None,
954 _('set branch name even if it shadows an existing branch')),
958 _('set branch name even if it shadows an existing branch')),
955 ('C', 'clean', None, _('reset branch name to parent branch name'))],
959 ('C', 'clean', None, _('reset branch name to parent branch name'))],
956 _('[-fC] [NAME]'))
960 _('[-fC] [NAME]'))
957 def branch(ui, repo, label=None, **opts):
961 def branch(ui, repo, label=None, **opts):
958 """set or show the current branch name
962 """set or show the current branch name
959
963
960 .. note::
964 .. note::
961
965
962 Branch names are permanent and global. Use :hg:`bookmark` to create a
966 Branch names are permanent and global. Use :hg:`bookmark` to create a
963 light-weight bookmark instead. See :hg:`help glossary` for more
967 light-weight bookmark instead. See :hg:`help glossary` for more
964 information about named branches and bookmarks.
968 information about named branches and bookmarks.
965
969
966 With no argument, show the current branch name. With one argument,
970 With no argument, show the current branch name. With one argument,
967 set the working directory branch name (the branch will not exist
971 set the working directory branch name (the branch will not exist
968 in the repository until the next commit). Standard practice
972 in the repository until the next commit). Standard practice
969 recommends that primary development take place on the 'default'
973 recommends that primary development take place on the 'default'
970 branch.
974 branch.
971
975
972 Unless -f/--force is specified, branch will not let you set a
976 Unless -f/--force is specified, branch will not let you set a
973 branch name that already exists, even if it's inactive.
977 branch name that already exists, even if it's inactive.
974
978
975 Use -C/--clean to reset the working directory branch to that of
979 Use -C/--clean to reset the working directory branch to that of
976 the parent of the working directory, negating a previous branch
980 the parent of the working directory, negating a previous branch
977 change.
981 change.
978
982
979 Use the command :hg:`update` to switch to an existing branch. Use
983 Use the command :hg:`update` to switch to an existing branch. Use
980 :hg:`commit --close-branch` to mark this branch as closed.
984 :hg:`commit --close-branch` to mark this branch as closed.
981
985
982 Returns 0 on success.
986 Returns 0 on success.
983 """
987 """
984 if label:
988 if label:
985 label = label.strip()
989 label = label.strip()
986
990
987 if not opts.get('clean') and not label:
991 if not opts.get('clean') and not label:
988 ui.write("%s\n" % repo.dirstate.branch())
992 ui.write("%s\n" % repo.dirstate.branch())
989 return
993 return
990
994
991 wlock = repo.wlock()
995 wlock = repo.wlock()
992 try:
996 try:
993 if opts.get('clean'):
997 if opts.get('clean'):
994 label = repo[None].p1().branch()
998 label = repo[None].p1().branch()
995 repo.dirstate.setbranch(label)
999 repo.dirstate.setbranch(label)
996 ui.status(_('reset working directory to branch %s\n') % label)
1000 ui.status(_('reset working directory to branch %s\n') % label)
997 elif label:
1001 elif label:
998 if not opts.get('force') and label in repo.branchmap():
1002 if not opts.get('force') and label in repo.branchmap():
999 if label not in [p.branch() for p in repo.parents()]:
1003 if label not in [p.branch() for p in repo.parents()]:
1000 raise util.Abort(_('a branch of the same name already'
1004 raise util.Abort(_('a branch of the same name already'
1001 ' exists'),
1005 ' exists'),
1002 # i18n: "it" refers to an existing branch
1006 # i18n: "it" refers to an existing branch
1003 hint=_("use 'hg update' to switch to it"))
1007 hint=_("use 'hg update' to switch to it"))
1004 scmutil.checknewlabel(repo, label, 'branch')
1008 scmutil.checknewlabel(repo, label, 'branch')
1005 repo.dirstate.setbranch(label)
1009 repo.dirstate.setbranch(label)
1006 ui.status(_('marked working directory as branch %s\n') % label)
1010 ui.status(_('marked working directory as branch %s\n') % label)
1007 ui.status(_('(branches are permanent and global, '
1011 ui.status(_('(branches are permanent and global, '
1008 'did you want a bookmark?)\n'))
1012 'did you want a bookmark?)\n'))
1009 finally:
1013 finally:
1010 wlock.release()
1014 wlock.release()
1011
1015
1012 @command('branches',
1016 @command('branches',
1013 [('a', 'active', False, _('show only branches that have unmerged heads')),
1017 [('a', 'active', False, _('show only branches that have unmerged heads')),
1014 ('c', 'closed', False, _('show normal and closed branches'))],
1018 ('c', 'closed', False, _('show normal and closed branches'))],
1015 _('[-ac]'))
1019 _('[-ac]'))
1016 def branches(ui, repo, active=False, closed=False):
1020 def branches(ui, repo, active=False, closed=False):
1017 """list repository named branches
1021 """list repository named branches
1018
1022
1019 List the repository's named branches, indicating which ones are
1023 List the repository's named branches, indicating which ones are
1020 inactive. If -c/--closed is specified, also list branches which have
1024 inactive. If -c/--closed is specified, also list branches which have
1021 been marked closed (see :hg:`commit --close-branch`).
1025 been marked closed (see :hg:`commit --close-branch`).
1022
1026
1023 If -a/--active is specified, only show active branches. A branch
1027 If -a/--active is specified, only show active branches. A branch
1024 is considered active if it contains repository heads.
1028 is considered active if it contains repository heads.
1025
1029
1026 Use the command :hg:`update` to switch to an existing branch.
1030 Use the command :hg:`update` to switch to an existing branch.
1027
1031
1028 Returns 0.
1032 Returns 0.
1029 """
1033 """
1030
1034
1031 hexfunc = ui.debugflag and hex or short
1035 hexfunc = ui.debugflag and hex or short
1032
1036
1033 allheads = set(repo.heads())
1037 allheads = set(repo.heads())
1034 branches = []
1038 branches = []
1035 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1039 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1036 isactive = not isclosed and bool(set(heads) & allheads)
1040 isactive = not isclosed and bool(set(heads) & allheads)
1037 branches.append((tag, repo[tip], isactive, not isclosed))
1041 branches.append((tag, repo[tip], isactive, not isclosed))
1038 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1042 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1039 reverse=True)
1043 reverse=True)
1040
1044
1041 for tag, ctx, isactive, isopen in branches:
1045 for tag, ctx, isactive, isopen in branches:
1042 if (not active) or isactive:
1046 if (not active) or isactive:
1043 if isactive:
1047 if isactive:
1044 label = 'branches.active'
1048 label = 'branches.active'
1045 notice = ''
1049 notice = ''
1046 elif not isopen:
1050 elif not isopen:
1047 if not closed:
1051 if not closed:
1048 continue
1052 continue
1049 label = 'branches.closed'
1053 label = 'branches.closed'
1050 notice = _(' (closed)')
1054 notice = _(' (closed)')
1051 else:
1055 else:
1052 label = 'branches.inactive'
1056 label = 'branches.inactive'
1053 notice = _(' (inactive)')
1057 notice = _(' (inactive)')
1054 if tag == repo.dirstate.branch():
1058 if tag == repo.dirstate.branch():
1055 label = 'branches.current'
1059 label = 'branches.current'
1056 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1060 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1057 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1061 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1058 'log.changeset changeset.%s' % ctx.phasestr())
1062 'log.changeset changeset.%s' % ctx.phasestr())
1059 labeledtag = ui.label(tag, label)
1063 labeledtag = ui.label(tag, label)
1060 if ui.quiet:
1064 if ui.quiet:
1061 ui.write("%s\n" % labeledtag)
1065 ui.write("%s\n" % labeledtag)
1062 else:
1066 else:
1063 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1067 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1064
1068
1065 @command('bundle',
1069 @command('bundle',
1066 [('f', 'force', None, _('run even when the destination is unrelated')),
1070 [('f', 'force', None, _('run even when the destination is unrelated')),
1067 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1071 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1068 _('REV')),
1072 _('REV')),
1069 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1073 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1070 _('BRANCH')),
1074 _('BRANCH')),
1071 ('', 'base', [],
1075 ('', 'base', [],
1072 _('a base changeset assumed to be available at the destination'),
1076 _('a base changeset assumed to be available at the destination'),
1073 _('REV')),
1077 _('REV')),
1074 ('a', 'all', None, _('bundle all changesets in the repository')),
1078 ('a', 'all', None, _('bundle all changesets in the repository')),
1075 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1079 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1076 ] + remoteopts,
1080 ] + remoteopts,
1077 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1081 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1078 def bundle(ui, repo, fname, dest=None, **opts):
1082 def bundle(ui, repo, fname, dest=None, **opts):
1079 """create a changegroup file
1083 """create a changegroup file
1080
1084
1081 Generate a compressed changegroup file collecting changesets not
1085 Generate a compressed changegroup file collecting changesets not
1082 known to be in another repository.
1086 known to be in another repository.
1083
1087
1084 If you omit the destination repository, then hg assumes the
1088 If you omit the destination repository, then hg assumes the
1085 destination will have all the nodes you specify with --base
1089 destination will have all the nodes you specify with --base
1086 parameters. To create a bundle containing all changesets, use
1090 parameters. To create a bundle containing all changesets, use
1087 -a/--all (or --base null).
1091 -a/--all (or --base null).
1088
1092
1089 You can change compression method with the -t/--type option.
1093 You can change compression method with the -t/--type option.
1090 The available compression methods are: none, bzip2, and
1094 The available compression methods are: none, bzip2, and
1091 gzip (by default, bundles are compressed using bzip2).
1095 gzip (by default, bundles are compressed using bzip2).
1092
1096
1093 The bundle file can then be transferred using conventional means
1097 The bundle file can then be transferred using conventional means
1094 and applied to another repository with the unbundle or pull
1098 and applied to another repository with the unbundle or pull
1095 command. This is useful when direct push and pull are not
1099 command. This is useful when direct push and pull are not
1096 available or when exporting an entire repository is undesirable.
1100 available or when exporting an entire repository is undesirable.
1097
1101
1098 Applying bundles preserves all changeset contents including
1102 Applying bundles preserves all changeset contents including
1099 permissions, copy/rename information, and revision history.
1103 permissions, copy/rename information, and revision history.
1100
1104
1101 Returns 0 on success, 1 if no changes found.
1105 Returns 0 on success, 1 if no changes found.
1102 """
1106 """
1103 revs = None
1107 revs = None
1104 if 'rev' in opts:
1108 if 'rev' in opts:
1105 revs = scmutil.revrange(repo, opts['rev'])
1109 revs = scmutil.revrange(repo, opts['rev'])
1106
1110
1107 bundletype = opts.get('type', 'bzip2').lower()
1111 bundletype = opts.get('type', 'bzip2').lower()
1108 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1112 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1109 bundletype = btypes.get(bundletype)
1113 bundletype = btypes.get(bundletype)
1110 if bundletype not in changegroup.bundletypes:
1114 if bundletype not in changegroup.bundletypes:
1111 raise util.Abort(_('unknown bundle type specified with --type'))
1115 raise util.Abort(_('unknown bundle type specified with --type'))
1112
1116
1113 if opts.get('all'):
1117 if opts.get('all'):
1114 base = ['null']
1118 base = ['null']
1115 else:
1119 else:
1116 base = scmutil.revrange(repo, opts.get('base'))
1120 base = scmutil.revrange(repo, opts.get('base'))
1117 # TODO: get desired bundlecaps from command line.
1121 # TODO: get desired bundlecaps from command line.
1118 bundlecaps = None
1122 bundlecaps = None
1119 if base:
1123 if base:
1120 if dest:
1124 if dest:
1121 raise util.Abort(_("--base is incompatible with specifying "
1125 raise util.Abort(_("--base is incompatible with specifying "
1122 "a destination"))
1126 "a destination"))
1123 common = [repo.lookup(rev) for rev in base]
1127 common = [repo.lookup(rev) for rev in base]
1124 heads = revs and map(repo.lookup, revs) or revs
1128 heads = revs and map(repo.lookup, revs) or revs
1125 cg = repo.getbundle('bundle', heads=heads, common=common,
1129 cg = repo.getbundle('bundle', heads=heads, common=common,
1126 bundlecaps=bundlecaps)
1130 bundlecaps=bundlecaps)
1127 outgoing = None
1131 outgoing = None
1128 else:
1132 else:
1129 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1133 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1130 dest, branches = hg.parseurl(dest, opts.get('branch'))
1134 dest, branches = hg.parseurl(dest, opts.get('branch'))
1131 other = hg.peer(repo, opts, dest)
1135 other = hg.peer(repo, opts, dest)
1132 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1136 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1133 heads = revs and map(repo.lookup, revs) or revs
1137 heads = revs and map(repo.lookup, revs) or revs
1134 outgoing = discovery.findcommonoutgoing(repo, other,
1138 outgoing = discovery.findcommonoutgoing(repo, other,
1135 onlyheads=heads,
1139 onlyheads=heads,
1136 force=opts.get('force'),
1140 force=opts.get('force'),
1137 portable=True)
1141 portable=True)
1138 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1142 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1139 if not cg:
1143 if not cg:
1140 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1144 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1141 return 1
1145 return 1
1142
1146
1143 changegroup.writebundle(cg, fname, bundletype)
1147 changegroup.writebundle(cg, fname, bundletype)
1144
1148
1145 @command('cat',
1149 @command('cat',
1146 [('o', 'output', '',
1150 [('o', 'output', '',
1147 _('print output to file with formatted name'), _('FORMAT')),
1151 _('print output to file with formatted name'), _('FORMAT')),
1148 ('r', 'rev', '', _('print the given revision'), _('REV')),
1152 ('r', 'rev', '', _('print the given revision'), _('REV')),
1149 ('', 'decode', None, _('apply any matching decode filter')),
1153 ('', 'decode', None, _('apply any matching decode filter')),
1150 ] + walkopts,
1154 ] + walkopts,
1151 _('[OPTION]... FILE...'))
1155 _('[OPTION]... FILE...'))
1152 def cat(ui, repo, file1, *pats, **opts):
1156 def cat(ui, repo, file1, *pats, **opts):
1153 """output the current or given revision of files
1157 """output the current or given revision of files
1154
1158
1155 Print the specified files as they were at the given revision. If
1159 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.
1160 no revision is given, the parent of the working directory is used.
1157
1161
1158 Output may be to a file, in which case the name of the file is
1162 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
1163 given using a format string. The formatting rules are the same as
1160 for the export command, with the following additions:
1164 for the export command, with the following additions:
1161
1165
1162 :``%s``: basename of file being printed
1166 :``%s``: basename of file being printed
1163 :``%d``: dirname of file being printed, or '.' if in repository root
1167 :``%d``: dirname of file being printed, or '.' if in repository root
1164 :``%p``: root-relative path name of file being printed
1168 :``%p``: root-relative path name of file being printed
1165
1169
1166 Returns 0 on success.
1170 Returns 0 on success.
1167 """
1171 """
1168 ctx = scmutil.revsingle(repo, opts.get('rev'))
1172 ctx = scmutil.revsingle(repo, opts.get('rev'))
1169 err = 1
1173 err = 1
1170 m = scmutil.match(ctx, (file1,) + pats, opts)
1174 m = scmutil.match(ctx, (file1,) + pats, opts)
1171
1175
1172 def write(path):
1176 def write(path):
1173 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1177 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1174 pathname=path)
1178 pathname=path)
1175 data = ctx[path].data()
1179 data = ctx[path].data()
1176 if opts.get('decode'):
1180 if opts.get('decode'):
1177 data = repo.wwritedata(path, data)
1181 data = repo.wwritedata(path, data)
1178 fp.write(data)
1182 fp.write(data)
1179 fp.close()
1183 fp.close()
1180
1184
1181 # Automation often uses hg cat on single files, so special case it
1185 # Automation often uses hg cat on single files, so special case it
1182 # for performance to avoid the cost of parsing the manifest.
1186 # for performance to avoid the cost of parsing the manifest.
1183 if len(m.files()) == 1 and not m.anypats():
1187 if len(m.files()) == 1 and not m.anypats():
1184 file = m.files()[0]
1188 file = m.files()[0]
1185 mf = repo.manifest
1189 mf = repo.manifest
1186 mfnode = ctx._changeset[0]
1190 mfnode = ctx._changeset[0]
1187 if mf.find(mfnode, file)[0]:
1191 if mf.find(mfnode, file)[0]:
1188 write(file)
1192 write(file)
1189 return 0
1193 return 0
1190
1194
1191 for abs in ctx.walk(m):
1195 for abs in ctx.walk(m):
1192 write(abs)
1196 write(abs)
1193 err = 0
1197 err = 0
1194 return err
1198 return err
1195
1199
1196 @command('^clone',
1200 @command('^clone',
1197 [('U', 'noupdate', None,
1201 [('U', 'noupdate', None,
1198 _('the clone will include an empty working copy (only a repository)')),
1202 _('the clone will include an empty working copy (only a repository)')),
1199 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1203 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1200 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1204 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1201 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1205 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1202 ('', 'pull', None, _('use pull protocol to copy metadata')),
1206 ('', 'pull', None, _('use pull protocol to copy metadata')),
1203 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1207 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1204 ] + remoteopts,
1208 ] + remoteopts,
1205 _('[OPTION]... SOURCE [DEST]'))
1209 _('[OPTION]... SOURCE [DEST]'))
1206 def clone(ui, source, dest=None, **opts):
1210 def clone(ui, source, dest=None, **opts):
1207 """make a copy of an existing repository
1211 """make a copy of an existing repository
1208
1212
1209 Create a copy of an existing repository in a new directory.
1213 Create a copy of an existing repository in a new directory.
1210
1214
1211 If no destination directory name is specified, it defaults to the
1215 If no destination directory name is specified, it defaults to the
1212 basename of the source.
1216 basename of the source.
1213
1217
1214 The location of the source is added to the new repository's
1218 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.
1219 ``.hg/hgrc`` file, as the default to be used for future pulls.
1216
1220
1217 Only local paths and ``ssh://`` URLs are supported as
1221 Only local paths and ``ssh://`` URLs are supported as
1218 destinations. For ``ssh://`` destinations, no working directory or
1222 destinations. For ``ssh://`` destinations, no working directory or
1219 ``.hg/hgrc`` will be created on the remote side.
1223 ``.hg/hgrc`` will be created on the remote side.
1220
1224
1221 To pull only a subset of changesets, specify one or more revisions
1225 To pull only a subset of changesets, specify one or more revisions
1222 identifiers with -r/--rev or branches with -b/--branch. The
1226 identifiers with -r/--rev or branches with -b/--branch. The
1223 resulting clone will contain only the specified changesets and
1227 resulting clone will contain only the specified changesets and
1224 their ancestors. These options (or 'clone src#rev dest') imply
1228 their ancestors. These options (or 'clone src#rev dest') imply
1225 --pull, even for local source repositories. Note that specifying a
1229 --pull, even for local source repositories. Note that specifying a
1226 tag will include the tagged changeset but not the changeset
1230 tag will include the tagged changeset but not the changeset
1227 containing the tag.
1231 containing the tag.
1228
1232
1229 If the source repository has a bookmark called '@' set, that
1233 If the source repository has a bookmark called '@' set, that
1230 revision will be checked out in the new repository by default.
1234 revision will be checked out in the new repository by default.
1231
1235
1232 To check out a particular version, use -u/--update, or
1236 To check out a particular version, use -u/--update, or
1233 -U/--noupdate to create a clone with no working directory.
1237 -U/--noupdate to create a clone with no working directory.
1234
1238
1235 .. container:: verbose
1239 .. container:: verbose
1236
1240
1237 For efficiency, hardlinks are used for cloning whenever the
1241 For efficiency, hardlinks are used for cloning whenever the
1238 source and destination are on the same filesystem (note this
1242 source and destination are on the same filesystem (note this
1239 applies only to the repository data, not to the working
1243 applies only to the repository data, not to the working
1240 directory). Some filesystems, such as AFS, implement hardlinking
1244 directory). Some filesystems, such as AFS, implement hardlinking
1241 incorrectly, but do not report errors. In these cases, use the
1245 incorrectly, but do not report errors. In these cases, use the
1242 --pull option to avoid hardlinking.
1246 --pull option to avoid hardlinking.
1243
1247
1244 In some cases, you can clone repositories and the working
1248 In some cases, you can clone repositories and the working
1245 directory using full hardlinks with ::
1249 directory using full hardlinks with ::
1246
1250
1247 $ cp -al REPO REPOCLONE
1251 $ cp -al REPO REPOCLONE
1248
1252
1249 This is the fastest way to clone, but it is not always safe. The
1253 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
1254 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
1255 the operation is up to you) and you have to make sure your
1252 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1256 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1253 so). Also, this is not compatible with certain extensions that
1257 so). Also, this is not compatible with certain extensions that
1254 place their metadata under the .hg directory, such as mq.
1258 place their metadata under the .hg directory, such as mq.
1255
1259
1256 Mercurial will update the working directory to the first applicable
1260 Mercurial will update the working directory to the first applicable
1257 revision from this list:
1261 revision from this list:
1258
1262
1259 a) null if -U or the source repository has no changesets
1263 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
1264 b) if -u . and the source repository is local, the first parent of
1261 the source repository's working directory
1265 the source repository's working directory
1262 c) the changeset specified with -u (if a branch name, this means the
1266 c) the changeset specified with -u (if a branch name, this means the
1263 latest head of that branch)
1267 latest head of that branch)
1264 d) the changeset specified with -r
1268 d) the changeset specified with -r
1265 e) the tipmost head specified with -b
1269 e) the tipmost head specified with -b
1266 f) the tipmost head specified with the url#branch source syntax
1270 f) the tipmost head specified with the url#branch source syntax
1267 g) the revision marked with the '@' bookmark, if present
1271 g) the revision marked with the '@' bookmark, if present
1268 h) the tipmost head of the default branch
1272 h) the tipmost head of the default branch
1269 i) tip
1273 i) tip
1270
1274
1271 Examples:
1275 Examples:
1272
1276
1273 - clone a remote repository to a new directory named hg/::
1277 - clone a remote repository to a new directory named hg/::
1274
1278
1275 hg clone http://selenic.com/hg
1279 hg clone http://selenic.com/hg
1276
1280
1277 - create a lightweight local clone::
1281 - create a lightweight local clone::
1278
1282
1279 hg clone project/ project-feature/
1283 hg clone project/ project-feature/
1280
1284
1281 - clone from an absolute path on an ssh server (note double-slash)::
1285 - clone from an absolute path on an ssh server (note double-slash)::
1282
1286
1283 hg clone ssh://user@server//home/projects/alpha/
1287 hg clone ssh://user@server//home/projects/alpha/
1284
1288
1285 - do a high-speed clone over a LAN while checking out a
1289 - do a high-speed clone over a LAN while checking out a
1286 specified version::
1290 specified version::
1287
1291
1288 hg clone --uncompressed http://server/repo -u 1.5
1292 hg clone --uncompressed http://server/repo -u 1.5
1289
1293
1290 - create a repository without changesets after a particular revision::
1294 - create a repository without changesets after a particular revision::
1291
1295
1292 hg clone -r 04e544 experimental/ good/
1296 hg clone -r 04e544 experimental/ good/
1293
1297
1294 - clone (and track) a particular named branch::
1298 - clone (and track) a particular named branch::
1295
1299
1296 hg clone http://selenic.com/hg#stable
1300 hg clone http://selenic.com/hg#stable
1297
1301
1298 See :hg:`help urls` for details on specifying URLs.
1302 See :hg:`help urls` for details on specifying URLs.
1299
1303
1300 Returns 0 on success.
1304 Returns 0 on success.
1301 """
1305 """
1302 if opts.get('noupdate') and opts.get('updaterev'):
1306 if opts.get('noupdate') and opts.get('updaterev'):
1303 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1307 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1304
1308
1305 r = hg.clone(ui, opts, source, dest,
1309 r = hg.clone(ui, opts, source, dest,
1306 pull=opts.get('pull'),
1310 pull=opts.get('pull'),
1307 stream=opts.get('uncompressed'),
1311 stream=opts.get('uncompressed'),
1308 rev=opts.get('rev'),
1312 rev=opts.get('rev'),
1309 update=opts.get('updaterev') or not opts.get('noupdate'),
1313 update=opts.get('updaterev') or not opts.get('noupdate'),
1310 branch=opts.get('branch'))
1314 branch=opts.get('branch'))
1311
1315
1312 return r is None
1316 return r is None
1313
1317
1314 @command('^commit|ci',
1318 @command('^commit|ci',
1315 [('A', 'addremove', None,
1319 [('A', 'addremove', None,
1316 _('mark new/missing files as added/removed before committing')),
1320 _('mark new/missing files as added/removed before committing')),
1317 ('', 'close-branch', None,
1321 ('', 'close-branch', None,
1318 _('mark a branch as closed, hiding it from the branch list')),
1322 _('mark a branch as closed, hiding it from the branch list')),
1319 ('', 'amend', None, _('amend the parent of the working dir')),
1323 ('', 'amend', None, _('amend the parent of the working dir')),
1320 ('s', 'secret', None, _('use the secret phase for committing')),
1324 ('s', 'secret', None, _('use the secret phase for committing')),
1321 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1325 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1322 _('[OPTION]... [FILE]...'))
1326 _('[OPTION]... [FILE]...'))
1323 def commit(ui, repo, *pats, **opts):
1327 def commit(ui, repo, *pats, **opts):
1324 """commit the specified files or all outstanding changes
1328 """commit the specified files or all outstanding changes
1325
1329
1326 Commit changes to the given files into the repository. Unlike a
1330 Commit changes to the given files into the repository. Unlike a
1327 centralized SCM, this operation is a local operation. See
1331 centralized SCM, this operation is a local operation. See
1328 :hg:`push` for a way to actively distribute your changes.
1332 :hg:`push` for a way to actively distribute your changes.
1329
1333
1330 If a list of files is omitted, all changes reported by :hg:`status`
1334 If a list of files is omitted, all changes reported by :hg:`status`
1331 will be committed.
1335 will be committed.
1332
1336
1333 If you are committing the result of a merge, do not provide any
1337 If you are committing the result of a merge, do not provide any
1334 filenames or -I/-X filters.
1338 filenames or -I/-X filters.
1335
1339
1336 If no commit message is specified, Mercurial starts your
1340 If no commit message is specified, Mercurial starts your
1337 configured editor where you can enter a message. In case your
1341 configured editor where you can enter a message. In case your
1338 commit fails, you will find a backup of your message in
1342 commit fails, you will find a backup of your message in
1339 ``.hg/last-message.txt``.
1343 ``.hg/last-message.txt``.
1340
1344
1341 The --amend flag can be used to amend the parent of the
1345 The --amend flag can be used to amend the parent of the
1342 working directory with a new commit that contains the changes
1346 working directory with a new commit that contains the changes
1343 in the parent in addition to those currently reported by :hg:`status`,
1347 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
1348 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`
1349 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1346 on how to restore it).
1350 on how to restore it).
1347
1351
1348 Message, user and date are taken from the amended commit unless
1352 Message, user and date are taken from the amended commit unless
1349 specified. When a message isn't specified on the command line,
1353 specified. When a message isn't specified on the command line,
1350 the editor will open with the message of the amended commit.
1354 the editor will open with the message of the amended commit.
1351
1355
1352 It is not possible to amend public changesets (see :hg:`help phases`)
1356 It is not possible to amend public changesets (see :hg:`help phases`)
1353 or changesets that have children.
1357 or changesets that have children.
1354
1358
1355 See :hg:`help dates` for a list of formats valid for -d/--date.
1359 See :hg:`help dates` for a list of formats valid for -d/--date.
1356
1360
1357 Returns 0 on success, 1 if nothing changed.
1361 Returns 0 on success, 1 if nothing changed.
1358 """
1362 """
1359 if opts.get('subrepos'):
1363 if opts.get('subrepos'):
1360 if opts.get('amend'):
1364 if opts.get('amend'):
1361 raise util.Abort(_('cannot amend with --subrepos'))
1365 raise util.Abort(_('cannot amend with --subrepos'))
1362 # Let --subrepos on the command line override config setting.
1366 # Let --subrepos on the command line override config setting.
1363 ui.setconfig('ui', 'commitsubrepos', True)
1367 ui.setconfig('ui', 'commitsubrepos', True)
1364
1368
1365 # Save this for restoring it later
1369 # Save this for restoring it later
1366 oldcommitphase = ui.config('phases', 'new-commit')
1370 oldcommitphase = ui.config('phases', 'new-commit')
1367
1371
1368 cmdutil.checkunfinished(repo, commit=True)
1372 cmdutil.checkunfinished(repo, commit=True)
1369
1373
1370 branch = repo[None].branch()
1374 branch = repo[None].branch()
1371 bheads = repo.branchheads(branch)
1375 bheads = repo.branchheads(branch)
1372
1376
1373 extra = {}
1377 extra = {}
1374 if opts.get('close_branch'):
1378 if opts.get('close_branch'):
1375 extra['close'] = 1
1379 extra['close'] = 1
1376
1380
1377 if not bheads:
1381 if not bheads:
1378 raise util.Abort(_('can only close branch heads'))
1382 raise util.Abort(_('can only close branch heads'))
1379 elif opts.get('amend'):
1383 elif opts.get('amend'):
1380 if repo.parents()[0].p1().branch() != branch and \
1384 if repo.parents()[0].p1().branch() != branch and \
1381 repo.parents()[0].p2().branch() != branch:
1385 repo.parents()[0].p2().branch() != branch:
1382 raise util.Abort(_('can only close branch heads'))
1386 raise util.Abort(_('can only close branch heads'))
1383
1387
1384 if opts.get('amend'):
1388 if opts.get('amend'):
1385 if ui.configbool('ui', 'commitsubrepos'):
1389 if ui.configbool('ui', 'commitsubrepos'):
1386 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1390 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1387
1391
1388 old = repo['.']
1392 old = repo['.']
1389 if old.phase() == phases.public:
1393 if old.phase() == phases.public:
1390 raise util.Abort(_('cannot amend public changesets'))
1394 raise util.Abort(_('cannot amend public changesets'))
1391 if len(repo[None].parents()) > 1:
1395 if len(repo[None].parents()) > 1:
1392 raise util.Abort(_('cannot amend while merging'))
1396 raise util.Abort(_('cannot amend while merging'))
1393 if (not obsolete._enabled) and old.children():
1397 if (not obsolete._enabled) and old.children():
1394 raise util.Abort(_('cannot amend changeset with children'))
1398 raise util.Abort(_('cannot amend changeset with children'))
1395
1399
1396 e = cmdutil.commiteditor
1400 e = cmdutil.commiteditor
1397 if opts.get('force_editor'):
1401 if opts.get('force_editor'):
1398 e = cmdutil.commitforceeditor
1402 e = cmdutil.commitforceeditor
1399
1403
1400 # commitfunc is used only for temporary amend commit by cmdutil.amend
1404 # commitfunc is used only for temporary amend commit by cmdutil.amend
1401 def commitfunc(ui, repo, message, match, opts):
1405 def commitfunc(ui, repo, message, match, opts):
1402 editor = e
1406 editor = e
1403 # message contains text from -m or -l, if it's empty,
1407 # message contains text from -m or -l, if it's empty,
1404 # open the editor with the old message
1408 # open the editor with the old message
1405 if not message:
1409 if not message:
1406 message = old.description()
1410 message = old.description()
1407 editor = cmdutil.commitforceeditor
1411 editor = cmdutil.commitforceeditor
1408 return repo.commit(message,
1412 return repo.commit(message,
1409 opts.get('user') or old.user(),
1413 opts.get('user') or old.user(),
1410 opts.get('date') or old.date(),
1414 opts.get('date') or old.date(),
1411 match,
1415 match,
1412 editor=editor,
1416 editor=editor,
1413 extra=extra)
1417 extra=extra)
1414
1418
1415 current = repo._bookmarkcurrent
1419 current = repo._bookmarkcurrent
1416 marks = old.bookmarks()
1420 marks = old.bookmarks()
1417 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1421 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1418 if node == old.node():
1422 if node == old.node():
1419 ui.status(_("nothing changed\n"))
1423 ui.status(_("nothing changed\n"))
1420 return 1
1424 return 1
1421 elif marks:
1425 elif marks:
1422 ui.debug('moving bookmarks %r from %s to %s\n' %
1426 ui.debug('moving bookmarks %r from %s to %s\n' %
1423 (marks, old.hex(), hex(node)))
1427 (marks, old.hex(), hex(node)))
1424 newmarks = repo._bookmarks
1428 newmarks = repo._bookmarks
1425 for bm in marks:
1429 for bm in marks:
1426 newmarks[bm] = node
1430 newmarks[bm] = node
1427 if bm == current:
1431 if bm == current:
1428 bookmarks.setcurrent(repo, bm)
1432 bookmarks.setcurrent(repo, bm)
1429 newmarks.write()
1433 newmarks.write()
1430 else:
1434 else:
1431 e = cmdutil.commiteditor
1435 e = cmdutil.commiteditor
1432 if opts.get('force_editor'):
1436 if opts.get('force_editor'):
1433 e = cmdutil.commitforceeditor
1437 e = cmdutil.commitforceeditor
1434
1438
1435 def commitfunc(ui, repo, message, match, opts):
1439 def commitfunc(ui, repo, message, match, opts):
1436 try:
1440 try:
1437 if opts.get('secret'):
1441 if opts.get('secret'):
1438 ui.setconfig('phases', 'new-commit', 'secret')
1442 ui.setconfig('phases', 'new-commit', 'secret')
1439 # Propagate to subrepos
1443 # Propagate to subrepos
1440 repo.baseui.setconfig('phases', 'new-commit', 'secret')
1444 repo.baseui.setconfig('phases', 'new-commit', 'secret')
1441
1445
1442 return repo.commit(message, opts.get('user'), opts.get('date'),
1446 return repo.commit(message, opts.get('user'), opts.get('date'),
1443 match, editor=e, extra=extra)
1447 match, editor=e, extra=extra)
1444 finally:
1448 finally:
1445 ui.setconfig('phases', 'new-commit', oldcommitphase)
1449 ui.setconfig('phases', 'new-commit', oldcommitphase)
1446 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase)
1450 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase)
1447
1451
1448
1452
1449 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1453 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1450
1454
1451 if not node:
1455 if not node:
1452 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1456 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1453 if stat[3]:
1457 if stat[3]:
1454 ui.status(_("nothing changed (%d missing files, see "
1458 ui.status(_("nothing changed (%d missing files, see "
1455 "'hg status')\n") % len(stat[3]))
1459 "'hg status')\n") % len(stat[3]))
1456 else:
1460 else:
1457 ui.status(_("nothing changed\n"))
1461 ui.status(_("nothing changed\n"))
1458 return 1
1462 return 1
1459
1463
1460 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1464 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1461
1465
1462 @command('copy|cp',
1466 @command('copy|cp',
1463 [('A', 'after', None, _('record a copy that has already occurred')),
1467 [('A', 'after', None, _('record a copy that has already occurred')),
1464 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1468 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1465 ] + walkopts + dryrunopts,
1469 ] + walkopts + dryrunopts,
1466 _('[OPTION]... [SOURCE]... DEST'))
1470 _('[OPTION]... [SOURCE]... DEST'))
1467 def copy(ui, repo, *pats, **opts):
1471 def copy(ui, repo, *pats, **opts):
1468 """mark files as copied for the next commit
1472 """mark files as copied for the next commit
1469
1473
1470 Mark dest as having copies of source files. If dest is a
1474 Mark dest as having copies of source files. If dest is a
1471 directory, copies are put in that directory. If dest is a file,
1475 directory, copies are put in that directory. If dest is a file,
1472 the source must be a single file.
1476 the source must be a single file.
1473
1477
1474 By default, this command copies the contents of files as they
1478 By default, this command copies the contents of files as they
1475 exist in the working directory. If invoked with -A/--after, the
1479 exist in the working directory. If invoked with -A/--after, the
1476 operation is recorded, but no copying is performed.
1480 operation is recorded, but no copying is performed.
1477
1481
1478 This command takes effect with the next commit. To undo a copy
1482 This command takes effect with the next commit. To undo a copy
1479 before that, see :hg:`revert`.
1483 before that, see :hg:`revert`.
1480
1484
1481 Returns 0 on success, 1 if errors are encountered.
1485 Returns 0 on success, 1 if errors are encountered.
1482 """
1486 """
1483 wlock = repo.wlock(False)
1487 wlock = repo.wlock(False)
1484 try:
1488 try:
1485 return cmdutil.copy(ui, repo, pats, opts)
1489 return cmdutil.copy(ui, repo, pats, opts)
1486 finally:
1490 finally:
1487 wlock.release()
1491 wlock.release()
1488
1492
1489 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1493 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1490 def debugancestor(ui, repo, *args):
1494 def debugancestor(ui, repo, *args):
1491 """find the ancestor revision of two revisions in a given index"""
1495 """find the ancestor revision of two revisions in a given index"""
1492 if len(args) == 3:
1496 if len(args) == 3:
1493 index, rev1, rev2 = args
1497 index, rev1, rev2 = args
1494 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1498 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1495 lookup = r.lookup
1499 lookup = r.lookup
1496 elif len(args) == 2:
1500 elif len(args) == 2:
1497 if not repo:
1501 if not repo:
1498 raise util.Abort(_("there is no Mercurial repository here "
1502 raise util.Abort(_("there is no Mercurial repository here "
1499 "(.hg not found)"))
1503 "(.hg not found)"))
1500 rev1, rev2 = args
1504 rev1, rev2 = args
1501 r = repo.changelog
1505 r = repo.changelog
1502 lookup = repo.lookup
1506 lookup = repo.lookup
1503 else:
1507 else:
1504 raise util.Abort(_('either two or three arguments required'))
1508 raise util.Abort(_('either two or three arguments required'))
1505 a = r.ancestor(lookup(rev1), lookup(rev2))
1509 a = r.ancestor(lookup(rev1), lookup(rev2))
1506 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1510 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1507
1511
1508 @command('debugbuilddag',
1512 @command('debugbuilddag',
1509 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1513 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1510 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1514 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1511 ('n', 'new-file', None, _('add new file at each rev'))],
1515 ('n', 'new-file', None, _('add new file at each rev'))],
1512 _('[OPTION]... [TEXT]'))
1516 _('[OPTION]... [TEXT]'))
1513 def debugbuilddag(ui, repo, text=None,
1517 def debugbuilddag(ui, repo, text=None,
1514 mergeable_file=False,
1518 mergeable_file=False,
1515 overwritten_file=False,
1519 overwritten_file=False,
1516 new_file=False):
1520 new_file=False):
1517 """builds a repo with a given DAG from scratch in the current empty repo
1521 """builds a repo with a given DAG from scratch in the current empty repo
1518
1522
1519 The description of the DAG is read from stdin if not given on the
1523 The description of the DAG is read from stdin if not given on the
1520 command line.
1524 command line.
1521
1525
1522 Elements:
1526 Elements:
1523
1527
1524 - "+n" is a linear run of n nodes based on the current default parent
1528 - "+n" is a linear run of n nodes based on the current default parent
1525 - "." is a single node based on the current default parent
1529 - "." is a single node based on the current default parent
1526 - "$" resets the default parent to null (implied at the start);
1530 - "$" resets the default parent to null (implied at the start);
1527 otherwise the default parent is always the last node created
1531 otherwise the default parent is always the last node created
1528 - "<p" sets the default parent to the backref p
1532 - "<p" sets the default parent to the backref p
1529 - "*p" is a fork at parent p, which is a backref
1533 - "*p" is a fork at parent p, which is a backref
1530 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1534 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1531 - "/p2" is a merge of the preceding node and p2
1535 - "/p2" is a merge of the preceding node and p2
1532 - ":tag" defines a local tag for the preceding node
1536 - ":tag" defines a local tag for the preceding node
1533 - "@branch" sets the named branch for subsequent nodes
1537 - "@branch" sets the named branch for subsequent nodes
1534 - "#...\\n" is a comment up to the end of the line
1538 - "#...\\n" is a comment up to the end of the line
1535
1539
1536 Whitespace between the above elements is ignored.
1540 Whitespace between the above elements is ignored.
1537
1541
1538 A backref is either
1542 A backref is either
1539
1543
1540 - a number n, which references the node curr-n, where curr is the current
1544 - a number n, which references the node curr-n, where curr is the current
1541 node, or
1545 node, or
1542 - the name of a local tag you placed earlier using ":tag", or
1546 - the name of a local tag you placed earlier using ":tag", or
1543 - empty to denote the default parent.
1547 - empty to denote the default parent.
1544
1548
1545 All string valued-elements are either strictly alphanumeric, or must
1549 All string valued-elements are either strictly alphanumeric, or must
1546 be enclosed in double quotes ("..."), with "\\" as escape character.
1550 be enclosed in double quotes ("..."), with "\\" as escape character.
1547 """
1551 """
1548
1552
1549 if text is None:
1553 if text is None:
1550 ui.status(_("reading DAG from stdin\n"))
1554 ui.status(_("reading DAG from stdin\n"))
1551 text = ui.fin.read()
1555 text = ui.fin.read()
1552
1556
1553 cl = repo.changelog
1557 cl = repo.changelog
1554 if len(cl) > 0:
1558 if len(cl) > 0:
1555 raise util.Abort(_('repository is not empty'))
1559 raise util.Abort(_('repository is not empty'))
1556
1560
1557 # determine number of revs in DAG
1561 # determine number of revs in DAG
1558 total = 0
1562 total = 0
1559 for type, data in dagparser.parsedag(text):
1563 for type, data in dagparser.parsedag(text):
1560 if type == 'n':
1564 if type == 'n':
1561 total += 1
1565 total += 1
1562
1566
1563 if mergeable_file:
1567 if mergeable_file:
1564 linesperrev = 2
1568 linesperrev = 2
1565 # make a file with k lines per rev
1569 # make a file with k lines per rev
1566 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1570 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1567 initialmergedlines.append("")
1571 initialmergedlines.append("")
1568
1572
1569 tags = []
1573 tags = []
1570
1574
1571 lock = tr = None
1575 lock = tr = None
1572 try:
1576 try:
1573 lock = repo.lock()
1577 lock = repo.lock()
1574 tr = repo.transaction("builddag")
1578 tr = repo.transaction("builddag")
1575
1579
1576 at = -1
1580 at = -1
1577 atbranch = 'default'
1581 atbranch = 'default'
1578 nodeids = []
1582 nodeids = []
1579 id = 0
1583 id = 0
1580 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1584 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1581 for type, data in dagparser.parsedag(text):
1585 for type, data in dagparser.parsedag(text):
1582 if type == 'n':
1586 if type == 'n':
1583 ui.note(('node %s\n' % str(data)))
1587 ui.note(('node %s\n' % str(data)))
1584 id, ps = data
1588 id, ps = data
1585
1589
1586 files = []
1590 files = []
1587 fctxs = {}
1591 fctxs = {}
1588
1592
1589 p2 = None
1593 p2 = None
1590 if mergeable_file:
1594 if mergeable_file:
1591 fn = "mf"
1595 fn = "mf"
1592 p1 = repo[ps[0]]
1596 p1 = repo[ps[0]]
1593 if len(ps) > 1:
1597 if len(ps) > 1:
1594 p2 = repo[ps[1]]
1598 p2 = repo[ps[1]]
1595 pa = p1.ancestor(p2)
1599 pa = p1.ancestor(p2)
1596 base, local, other = [x[fn].data() for x in (pa, p1,
1600 base, local, other = [x[fn].data() for x in (pa, p1,
1597 p2)]
1601 p2)]
1598 m3 = simplemerge.Merge3Text(base, local, other)
1602 m3 = simplemerge.Merge3Text(base, local, other)
1599 ml = [l.strip() for l in m3.merge_lines()]
1603 ml = [l.strip() for l in m3.merge_lines()]
1600 ml.append("")
1604 ml.append("")
1601 elif at > 0:
1605 elif at > 0:
1602 ml = p1[fn].data().split("\n")
1606 ml = p1[fn].data().split("\n")
1603 else:
1607 else:
1604 ml = initialmergedlines
1608 ml = initialmergedlines
1605 ml[id * linesperrev] += " r%i" % id
1609 ml[id * linesperrev] += " r%i" % id
1606 mergedtext = "\n".join(ml)
1610 mergedtext = "\n".join(ml)
1607 files.append(fn)
1611 files.append(fn)
1608 fctxs[fn] = context.memfilectx(fn, mergedtext)
1612 fctxs[fn] = context.memfilectx(fn, mergedtext)
1609
1613
1610 if overwritten_file:
1614 if overwritten_file:
1611 fn = "of"
1615 fn = "of"
1612 files.append(fn)
1616 files.append(fn)
1613 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1617 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1614
1618
1615 if new_file:
1619 if new_file:
1616 fn = "nf%i" % id
1620 fn = "nf%i" % id
1617 files.append(fn)
1621 files.append(fn)
1618 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1622 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1619 if len(ps) > 1:
1623 if len(ps) > 1:
1620 if not p2:
1624 if not p2:
1621 p2 = repo[ps[1]]
1625 p2 = repo[ps[1]]
1622 for fn in p2:
1626 for fn in p2:
1623 if fn.startswith("nf"):
1627 if fn.startswith("nf"):
1624 files.append(fn)
1628 files.append(fn)
1625 fctxs[fn] = p2[fn]
1629 fctxs[fn] = p2[fn]
1626
1630
1627 def fctxfn(repo, cx, path):
1631 def fctxfn(repo, cx, path):
1628 return fctxs.get(path)
1632 return fctxs.get(path)
1629
1633
1630 if len(ps) == 0 or ps[0] < 0:
1634 if len(ps) == 0 or ps[0] < 0:
1631 pars = [None, None]
1635 pars = [None, None]
1632 elif len(ps) == 1:
1636 elif len(ps) == 1:
1633 pars = [nodeids[ps[0]], None]
1637 pars = [nodeids[ps[0]], None]
1634 else:
1638 else:
1635 pars = [nodeids[p] for p in ps]
1639 pars = [nodeids[p] for p in ps]
1636 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1640 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1637 date=(id, 0),
1641 date=(id, 0),
1638 user="debugbuilddag",
1642 user="debugbuilddag",
1639 extra={'branch': atbranch})
1643 extra={'branch': atbranch})
1640 nodeid = repo.commitctx(cx)
1644 nodeid = repo.commitctx(cx)
1641 nodeids.append(nodeid)
1645 nodeids.append(nodeid)
1642 at = id
1646 at = id
1643 elif type == 'l':
1647 elif type == 'l':
1644 id, name = data
1648 id, name = data
1645 ui.note(('tag %s\n' % name))
1649 ui.note(('tag %s\n' % name))
1646 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1650 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1647 elif type == 'a':
1651 elif type == 'a':
1648 ui.note(('branch %s\n' % data))
1652 ui.note(('branch %s\n' % data))
1649 atbranch = data
1653 atbranch = data
1650 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1654 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1651 tr.close()
1655 tr.close()
1652
1656
1653 if tags:
1657 if tags:
1654 repo.opener.write("localtags", "".join(tags))
1658 repo.opener.write("localtags", "".join(tags))
1655 finally:
1659 finally:
1656 ui.progress(_('building'), None)
1660 ui.progress(_('building'), None)
1657 release(tr, lock)
1661 release(tr, lock)
1658
1662
1659 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1663 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1660 def debugbundle(ui, bundlepath, all=None, **opts):
1664 def debugbundle(ui, bundlepath, all=None, **opts):
1661 """lists the contents of a bundle"""
1665 """lists the contents of a bundle"""
1662 f = hg.openpath(ui, bundlepath)
1666 f = hg.openpath(ui, bundlepath)
1663 try:
1667 try:
1664 gen = changegroup.readbundle(f, bundlepath)
1668 gen = changegroup.readbundle(f, bundlepath)
1665 if all:
1669 if all:
1666 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1670 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1667
1671
1668 def showchunks(named):
1672 def showchunks(named):
1669 ui.write("\n%s\n" % named)
1673 ui.write("\n%s\n" % named)
1670 chain = None
1674 chain = None
1671 while True:
1675 while True:
1672 chunkdata = gen.deltachunk(chain)
1676 chunkdata = gen.deltachunk(chain)
1673 if not chunkdata:
1677 if not chunkdata:
1674 break
1678 break
1675 node = chunkdata['node']
1679 node = chunkdata['node']
1676 p1 = chunkdata['p1']
1680 p1 = chunkdata['p1']
1677 p2 = chunkdata['p2']
1681 p2 = chunkdata['p2']
1678 cs = chunkdata['cs']
1682 cs = chunkdata['cs']
1679 deltabase = chunkdata['deltabase']
1683 deltabase = chunkdata['deltabase']
1680 delta = chunkdata['delta']
1684 delta = chunkdata['delta']
1681 ui.write("%s %s %s %s %s %s\n" %
1685 ui.write("%s %s %s %s %s %s\n" %
1682 (hex(node), hex(p1), hex(p2),
1686 (hex(node), hex(p1), hex(p2),
1683 hex(cs), hex(deltabase), len(delta)))
1687 hex(cs), hex(deltabase), len(delta)))
1684 chain = node
1688 chain = node
1685
1689
1686 chunkdata = gen.changelogheader()
1690 chunkdata = gen.changelogheader()
1687 showchunks("changelog")
1691 showchunks("changelog")
1688 chunkdata = gen.manifestheader()
1692 chunkdata = gen.manifestheader()
1689 showchunks("manifest")
1693 showchunks("manifest")
1690 while True:
1694 while True:
1691 chunkdata = gen.filelogheader()
1695 chunkdata = gen.filelogheader()
1692 if not chunkdata:
1696 if not chunkdata:
1693 break
1697 break
1694 fname = chunkdata['filename']
1698 fname = chunkdata['filename']
1695 showchunks(fname)
1699 showchunks(fname)
1696 else:
1700 else:
1697 chunkdata = gen.changelogheader()
1701 chunkdata = gen.changelogheader()
1698 chain = None
1702 chain = None
1699 while True:
1703 while True:
1700 chunkdata = gen.deltachunk(chain)
1704 chunkdata = gen.deltachunk(chain)
1701 if not chunkdata:
1705 if not chunkdata:
1702 break
1706 break
1703 node = chunkdata['node']
1707 node = chunkdata['node']
1704 ui.write("%s\n" % hex(node))
1708 ui.write("%s\n" % hex(node))
1705 chain = node
1709 chain = node
1706 finally:
1710 finally:
1707 f.close()
1711 f.close()
1708
1712
1709 @command('debugcheckstate', [], '')
1713 @command('debugcheckstate', [], '')
1710 def debugcheckstate(ui, repo):
1714 def debugcheckstate(ui, repo):
1711 """validate the correctness of the current dirstate"""
1715 """validate the correctness of the current dirstate"""
1712 parent1, parent2 = repo.dirstate.parents()
1716 parent1, parent2 = repo.dirstate.parents()
1713 m1 = repo[parent1].manifest()
1717 m1 = repo[parent1].manifest()
1714 m2 = repo[parent2].manifest()
1718 m2 = repo[parent2].manifest()
1715 errors = 0
1719 errors = 0
1716 for f in repo.dirstate:
1720 for f in repo.dirstate:
1717 state = repo.dirstate[f]
1721 state = repo.dirstate[f]
1718 if state in "nr" and f not in m1:
1722 if state in "nr" and f not in m1:
1719 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1723 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1720 errors += 1
1724 errors += 1
1721 if state in "a" and f in m1:
1725 if state in "a" and f in m1:
1722 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1726 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1723 errors += 1
1727 errors += 1
1724 if state in "m" and f not in m1 and f not in m2:
1728 if state in "m" and f not in m1 and f not in m2:
1725 ui.warn(_("%s in state %s, but not in either manifest\n") %
1729 ui.warn(_("%s in state %s, but not in either manifest\n") %
1726 (f, state))
1730 (f, state))
1727 errors += 1
1731 errors += 1
1728 for f in m1:
1732 for f in m1:
1729 state = repo.dirstate[f]
1733 state = repo.dirstate[f]
1730 if state not in "nrm":
1734 if state not in "nrm":
1731 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1735 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1732 errors += 1
1736 errors += 1
1733 if errors:
1737 if errors:
1734 error = _(".hg/dirstate inconsistent with current parent's manifest")
1738 error = _(".hg/dirstate inconsistent with current parent's manifest")
1735 raise util.Abort(error)
1739 raise util.Abort(error)
1736
1740
1737 @command('debugcommands', [], _('[COMMAND]'))
1741 @command('debugcommands', [], _('[COMMAND]'))
1738 def debugcommands(ui, cmd='', *args):
1742 def debugcommands(ui, cmd='', *args):
1739 """list all available commands and options"""
1743 """list all available commands and options"""
1740 for cmd, vals in sorted(table.iteritems()):
1744 for cmd, vals in sorted(table.iteritems()):
1741 cmd = cmd.split('|')[0].strip('^')
1745 cmd = cmd.split('|')[0].strip('^')
1742 opts = ', '.join([i[1] for i in vals[1]])
1746 opts = ', '.join([i[1] for i in vals[1]])
1743 ui.write('%s: %s\n' % (cmd, opts))
1747 ui.write('%s: %s\n' % (cmd, opts))
1744
1748
1745 @command('debugcomplete',
1749 @command('debugcomplete',
1746 [('o', 'options', None, _('show the command options'))],
1750 [('o', 'options', None, _('show the command options'))],
1747 _('[-o] CMD'))
1751 _('[-o] CMD'))
1748 def debugcomplete(ui, cmd='', **opts):
1752 def debugcomplete(ui, cmd='', **opts):
1749 """returns the completion list associated with the given command"""
1753 """returns the completion list associated with the given command"""
1750
1754
1751 if opts.get('options'):
1755 if opts.get('options'):
1752 options = []
1756 options = []
1753 otables = [globalopts]
1757 otables = [globalopts]
1754 if cmd:
1758 if cmd:
1755 aliases, entry = cmdutil.findcmd(cmd, table, False)
1759 aliases, entry = cmdutil.findcmd(cmd, table, False)
1756 otables.append(entry[1])
1760 otables.append(entry[1])
1757 for t in otables:
1761 for t in otables:
1758 for o in t:
1762 for o in t:
1759 if "(DEPRECATED)" in o[3]:
1763 if "(DEPRECATED)" in o[3]:
1760 continue
1764 continue
1761 if o[0]:
1765 if o[0]:
1762 options.append('-%s' % o[0])
1766 options.append('-%s' % o[0])
1763 options.append('--%s' % o[1])
1767 options.append('--%s' % o[1])
1764 ui.write("%s\n" % "\n".join(options))
1768 ui.write("%s\n" % "\n".join(options))
1765 return
1769 return
1766
1770
1767 cmdlist = cmdutil.findpossible(cmd, table)
1771 cmdlist = cmdutil.findpossible(cmd, table)
1768 if ui.verbose:
1772 if ui.verbose:
1769 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1773 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1770 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1774 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1771
1775
1772 @command('debugdag',
1776 @command('debugdag',
1773 [('t', 'tags', None, _('use tags as labels')),
1777 [('t', 'tags', None, _('use tags as labels')),
1774 ('b', 'branches', None, _('annotate with branch names')),
1778 ('b', 'branches', None, _('annotate with branch names')),
1775 ('', 'dots', None, _('use dots for runs')),
1779 ('', 'dots', None, _('use dots for runs')),
1776 ('s', 'spaces', None, _('separate elements by spaces'))],
1780 ('s', 'spaces', None, _('separate elements by spaces'))],
1777 _('[OPTION]... [FILE [REV]...]'))
1781 _('[OPTION]... [FILE [REV]...]'))
1778 def debugdag(ui, repo, file_=None, *revs, **opts):
1782 def debugdag(ui, repo, file_=None, *revs, **opts):
1779 """format the changelog or an index DAG as a concise textual description
1783 """format the changelog or an index DAG as a concise textual description
1780
1784
1781 If you pass a revlog index, the revlog's DAG is emitted. If you list
1785 If you pass a revlog index, the revlog's DAG is emitted. If you list
1782 revision numbers, they get labeled in the output as rN.
1786 revision numbers, they get labeled in the output as rN.
1783
1787
1784 Otherwise, the changelog DAG of the current repo is emitted.
1788 Otherwise, the changelog DAG of the current repo is emitted.
1785 """
1789 """
1786 spaces = opts.get('spaces')
1790 spaces = opts.get('spaces')
1787 dots = opts.get('dots')
1791 dots = opts.get('dots')
1788 if file_:
1792 if file_:
1789 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1793 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1790 revs = set((int(r) for r in revs))
1794 revs = set((int(r) for r in revs))
1791 def events():
1795 def events():
1792 for r in rlog:
1796 for r in rlog:
1793 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1797 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1794 if p != -1)))
1798 if p != -1)))
1795 if r in revs:
1799 if r in revs:
1796 yield 'l', (r, "r%i" % r)
1800 yield 'l', (r, "r%i" % r)
1797 elif repo:
1801 elif repo:
1798 cl = repo.changelog
1802 cl = repo.changelog
1799 tags = opts.get('tags')
1803 tags = opts.get('tags')
1800 branches = opts.get('branches')
1804 branches = opts.get('branches')
1801 if tags:
1805 if tags:
1802 labels = {}
1806 labels = {}
1803 for l, n in repo.tags().items():
1807 for l, n in repo.tags().items():
1804 labels.setdefault(cl.rev(n), []).append(l)
1808 labels.setdefault(cl.rev(n), []).append(l)
1805 def events():
1809 def events():
1806 b = "default"
1810 b = "default"
1807 for r in cl:
1811 for r in cl:
1808 if branches:
1812 if branches:
1809 newb = cl.read(cl.node(r))[5]['branch']
1813 newb = cl.read(cl.node(r))[5]['branch']
1810 if newb != b:
1814 if newb != b:
1811 yield 'a', newb
1815 yield 'a', newb
1812 b = newb
1816 b = newb
1813 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1817 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1814 if p != -1)))
1818 if p != -1)))
1815 if tags:
1819 if tags:
1816 ls = labels.get(r)
1820 ls = labels.get(r)
1817 if ls:
1821 if ls:
1818 for l in ls:
1822 for l in ls:
1819 yield 'l', (r, l)
1823 yield 'l', (r, l)
1820 else:
1824 else:
1821 raise util.Abort(_('need repo for changelog dag'))
1825 raise util.Abort(_('need repo for changelog dag'))
1822
1826
1823 for line in dagparser.dagtextlines(events(),
1827 for line in dagparser.dagtextlines(events(),
1824 addspaces=spaces,
1828 addspaces=spaces,
1825 wraplabels=True,
1829 wraplabels=True,
1826 wrapannotations=True,
1830 wrapannotations=True,
1827 wrapnonlinear=dots,
1831 wrapnonlinear=dots,
1828 usedots=dots,
1832 usedots=dots,
1829 maxlinewidth=70):
1833 maxlinewidth=70):
1830 ui.write(line)
1834 ui.write(line)
1831 ui.write("\n")
1835 ui.write("\n")
1832
1836
1833 @command('debugdata',
1837 @command('debugdata',
1834 [('c', 'changelog', False, _('open changelog')),
1838 [('c', 'changelog', False, _('open changelog')),
1835 ('m', 'manifest', False, _('open manifest'))],
1839 ('m', 'manifest', False, _('open manifest'))],
1836 _('-c|-m|FILE REV'))
1840 _('-c|-m|FILE REV'))
1837 def debugdata(ui, repo, file_, rev=None, **opts):
1841 def debugdata(ui, repo, file_, rev=None, **opts):
1838 """dump the contents of a data file revision"""
1842 """dump the contents of a data file revision"""
1839 if opts.get('changelog') or opts.get('manifest'):
1843 if opts.get('changelog') or opts.get('manifest'):
1840 file_, rev = None, file_
1844 file_, rev = None, file_
1841 elif rev is None:
1845 elif rev is None:
1842 raise error.CommandError('debugdata', _('invalid arguments'))
1846 raise error.CommandError('debugdata', _('invalid arguments'))
1843 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1847 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1844 try:
1848 try:
1845 ui.write(r.revision(r.lookup(rev)))
1849 ui.write(r.revision(r.lookup(rev)))
1846 except KeyError:
1850 except KeyError:
1847 raise util.Abort(_('invalid revision identifier %s') % rev)
1851 raise util.Abort(_('invalid revision identifier %s') % rev)
1848
1852
1849 @command('debugdate',
1853 @command('debugdate',
1850 [('e', 'extended', None, _('try extended date formats'))],
1854 [('e', 'extended', None, _('try extended date formats'))],
1851 _('[-e] DATE [RANGE]'))
1855 _('[-e] DATE [RANGE]'))
1852 def debugdate(ui, date, range=None, **opts):
1856 def debugdate(ui, date, range=None, **opts):
1853 """parse and display a date"""
1857 """parse and display a date"""
1854 if opts["extended"]:
1858 if opts["extended"]:
1855 d = util.parsedate(date, util.extendeddateformats)
1859 d = util.parsedate(date, util.extendeddateformats)
1856 else:
1860 else:
1857 d = util.parsedate(date)
1861 d = util.parsedate(date)
1858 ui.write(("internal: %s %s\n") % d)
1862 ui.write(("internal: %s %s\n") % d)
1859 ui.write(("standard: %s\n") % util.datestr(d))
1863 ui.write(("standard: %s\n") % util.datestr(d))
1860 if range:
1864 if range:
1861 m = util.matchdate(range)
1865 m = util.matchdate(range)
1862 ui.write(("match: %s\n") % m(d[0]))
1866 ui.write(("match: %s\n") % m(d[0]))
1863
1867
1864 @command('debugdiscovery',
1868 @command('debugdiscovery',
1865 [('', 'old', None, _('use old-style discovery')),
1869 [('', 'old', None, _('use old-style discovery')),
1866 ('', 'nonheads', None,
1870 ('', 'nonheads', None,
1867 _('use old-style discovery with non-heads included')),
1871 _('use old-style discovery with non-heads included')),
1868 ] + remoteopts,
1872 ] + remoteopts,
1869 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1873 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1870 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1874 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1871 """runs the changeset discovery protocol in isolation"""
1875 """runs the changeset discovery protocol in isolation"""
1872 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1876 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1873 opts.get('branch'))
1877 opts.get('branch'))
1874 remote = hg.peer(repo, opts, remoteurl)
1878 remote = hg.peer(repo, opts, remoteurl)
1875 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1879 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1876
1880
1877 # make sure tests are repeatable
1881 # make sure tests are repeatable
1878 random.seed(12323)
1882 random.seed(12323)
1879
1883
1880 def doit(localheads, remoteheads, remote=remote):
1884 def doit(localheads, remoteheads, remote=remote):
1881 if opts.get('old'):
1885 if opts.get('old'):
1882 if localheads:
1886 if localheads:
1883 raise util.Abort('cannot use localheads with old style '
1887 raise util.Abort('cannot use localheads with old style '
1884 'discovery')
1888 'discovery')
1885 if not util.safehasattr(remote, 'branches'):
1889 if not util.safehasattr(remote, 'branches'):
1886 # enable in-client legacy support
1890 # enable in-client legacy support
1887 remote = localrepo.locallegacypeer(remote.local())
1891 remote = localrepo.locallegacypeer(remote.local())
1888 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1892 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1889 force=True)
1893 force=True)
1890 common = set(common)
1894 common = set(common)
1891 if not opts.get('nonheads'):
1895 if not opts.get('nonheads'):
1892 ui.write(("unpruned common: %s\n") %
1896 ui.write(("unpruned common: %s\n") %
1893 " ".join(sorted(short(n) for n in common)))
1897 " ".join(sorted(short(n) for n in common)))
1894 dag = dagutil.revlogdag(repo.changelog)
1898 dag = dagutil.revlogdag(repo.changelog)
1895 all = dag.ancestorset(dag.internalizeall(common))
1899 all = dag.ancestorset(dag.internalizeall(common))
1896 common = dag.externalizeall(dag.headsetofconnecteds(all))
1900 common = dag.externalizeall(dag.headsetofconnecteds(all))
1897 else:
1901 else:
1898 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1902 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1899 common = set(common)
1903 common = set(common)
1900 rheads = set(hds)
1904 rheads = set(hds)
1901 lheads = set(repo.heads())
1905 lheads = set(repo.heads())
1902 ui.write(("common heads: %s\n") %
1906 ui.write(("common heads: %s\n") %
1903 " ".join(sorted(short(n) for n in common)))
1907 " ".join(sorted(short(n) for n in common)))
1904 if lheads <= common:
1908 if lheads <= common:
1905 ui.write(("local is subset\n"))
1909 ui.write(("local is subset\n"))
1906 elif rheads <= common:
1910 elif rheads <= common:
1907 ui.write(("remote is subset\n"))
1911 ui.write(("remote is subset\n"))
1908
1912
1909 serverlogs = opts.get('serverlog')
1913 serverlogs = opts.get('serverlog')
1910 if serverlogs:
1914 if serverlogs:
1911 for filename in serverlogs:
1915 for filename in serverlogs:
1912 logfile = open(filename, 'r')
1916 logfile = open(filename, 'r')
1913 try:
1917 try:
1914 line = logfile.readline()
1918 line = logfile.readline()
1915 while line:
1919 while line:
1916 parts = line.strip().split(';')
1920 parts = line.strip().split(';')
1917 op = parts[1]
1921 op = parts[1]
1918 if op == 'cg':
1922 if op == 'cg':
1919 pass
1923 pass
1920 elif op == 'cgss':
1924 elif op == 'cgss':
1921 doit(parts[2].split(' '), parts[3].split(' '))
1925 doit(parts[2].split(' '), parts[3].split(' '))
1922 elif op == 'unb':
1926 elif op == 'unb':
1923 doit(parts[3].split(' '), parts[2].split(' '))
1927 doit(parts[3].split(' '), parts[2].split(' '))
1924 line = logfile.readline()
1928 line = logfile.readline()
1925 finally:
1929 finally:
1926 logfile.close()
1930 logfile.close()
1927
1931
1928 else:
1932 else:
1929 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1933 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1930 opts.get('remote_head'))
1934 opts.get('remote_head'))
1931 localrevs = opts.get('local_head')
1935 localrevs = opts.get('local_head')
1932 doit(localrevs, remoterevs)
1936 doit(localrevs, remoterevs)
1933
1937
1934 @command('debugfileset',
1938 @command('debugfileset',
1935 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1939 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1936 _('[-r REV] FILESPEC'))
1940 _('[-r REV] FILESPEC'))
1937 def debugfileset(ui, repo, expr, **opts):
1941 def debugfileset(ui, repo, expr, **opts):
1938 '''parse and apply a fileset specification'''
1942 '''parse and apply a fileset specification'''
1939 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1943 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1940 if ui.verbose:
1944 if ui.verbose:
1941 tree = fileset.parse(expr)[0]
1945 tree = fileset.parse(expr)[0]
1942 ui.note(tree, "\n")
1946 ui.note(tree, "\n")
1943
1947
1944 for f in fileset.getfileset(ctx, expr):
1948 for f in fileset.getfileset(ctx, expr):
1945 ui.write("%s\n" % f)
1949 ui.write("%s\n" % f)
1946
1950
1947 @command('debugfsinfo', [], _('[PATH]'))
1951 @command('debugfsinfo', [], _('[PATH]'))
1948 def debugfsinfo(ui, path="."):
1952 def debugfsinfo(ui, path="."):
1949 """show information detected about current filesystem"""
1953 """show information detected about current filesystem"""
1950 util.writefile('.debugfsinfo', '')
1954 util.writefile('.debugfsinfo', '')
1951 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1955 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1952 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1956 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1953 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1957 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1954 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1958 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1955 and 'yes' or 'no'))
1959 and 'yes' or 'no'))
1956 os.unlink('.debugfsinfo')
1960 os.unlink('.debugfsinfo')
1957
1961
1958 @command('debuggetbundle',
1962 @command('debuggetbundle',
1959 [('H', 'head', [], _('id of head node'), _('ID')),
1963 [('H', 'head', [], _('id of head node'), _('ID')),
1960 ('C', 'common', [], _('id of common node'), _('ID')),
1964 ('C', 'common', [], _('id of common node'), _('ID')),
1961 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1965 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1962 _('REPO FILE [-H|-C ID]...'))
1966 _('REPO FILE [-H|-C ID]...'))
1963 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1967 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1964 """retrieves a bundle from a repo
1968 """retrieves a bundle from a repo
1965
1969
1966 Every ID must be a full-length hex node id string. Saves the bundle to the
1970 Every ID must be a full-length hex node id string. Saves the bundle to the
1967 given file.
1971 given file.
1968 """
1972 """
1969 repo = hg.peer(ui, opts, repopath)
1973 repo = hg.peer(ui, opts, repopath)
1970 if not repo.capable('getbundle'):
1974 if not repo.capable('getbundle'):
1971 raise util.Abort("getbundle() not supported by target repository")
1975 raise util.Abort("getbundle() not supported by target repository")
1972 args = {}
1976 args = {}
1973 if common:
1977 if common:
1974 args['common'] = [bin(s) for s in common]
1978 args['common'] = [bin(s) for s in common]
1975 if head:
1979 if head:
1976 args['heads'] = [bin(s) for s in head]
1980 args['heads'] = [bin(s) for s in head]
1977 # TODO: get desired bundlecaps from command line.
1981 # TODO: get desired bundlecaps from command line.
1978 args['bundlecaps'] = None
1982 args['bundlecaps'] = None
1979 bundle = repo.getbundle('debug', **args)
1983 bundle = repo.getbundle('debug', **args)
1980
1984
1981 bundletype = opts.get('type', 'bzip2').lower()
1985 bundletype = opts.get('type', 'bzip2').lower()
1982 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1986 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1983 bundletype = btypes.get(bundletype)
1987 bundletype = btypes.get(bundletype)
1984 if bundletype not in changegroup.bundletypes:
1988 if bundletype not in changegroup.bundletypes:
1985 raise util.Abort(_('unknown bundle type specified with --type'))
1989 raise util.Abort(_('unknown bundle type specified with --type'))
1986 changegroup.writebundle(bundle, bundlepath, bundletype)
1990 changegroup.writebundle(bundle, bundlepath, bundletype)
1987
1991
1988 @command('debugignore', [], '')
1992 @command('debugignore', [], '')
1989 def debugignore(ui, repo, *values, **opts):
1993 def debugignore(ui, repo, *values, **opts):
1990 """display the combined ignore pattern"""
1994 """display the combined ignore pattern"""
1991 ignore = repo.dirstate._ignore
1995 ignore = repo.dirstate._ignore
1992 includepat = getattr(ignore, 'includepat', None)
1996 includepat = getattr(ignore, 'includepat', None)
1993 if includepat is not None:
1997 if includepat is not None:
1994 ui.write("%s\n" % includepat)
1998 ui.write("%s\n" % includepat)
1995 else:
1999 else:
1996 raise util.Abort(_("no ignore patterns found"))
2000 raise util.Abort(_("no ignore patterns found"))
1997
2001
1998 @command('debugindex',
2002 @command('debugindex',
1999 [('c', 'changelog', False, _('open changelog')),
2003 [('c', 'changelog', False, _('open changelog')),
2000 ('m', 'manifest', False, _('open manifest')),
2004 ('m', 'manifest', False, _('open manifest')),
2001 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2005 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2002 _('[-f FORMAT] -c|-m|FILE'))
2006 _('[-f FORMAT] -c|-m|FILE'))
2003 def debugindex(ui, repo, file_=None, **opts):
2007 def debugindex(ui, repo, file_=None, **opts):
2004 """dump the contents of an index file"""
2008 """dump the contents of an index file"""
2005 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2009 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2006 format = opts.get('format', 0)
2010 format = opts.get('format', 0)
2007 if format not in (0, 1):
2011 if format not in (0, 1):
2008 raise util.Abort(_("unknown format %d") % format)
2012 raise util.Abort(_("unknown format %d") % format)
2009
2013
2010 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2014 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2011 if generaldelta:
2015 if generaldelta:
2012 basehdr = ' delta'
2016 basehdr = ' delta'
2013 else:
2017 else:
2014 basehdr = ' base'
2018 basehdr = ' base'
2015
2019
2016 if format == 0:
2020 if format == 0:
2017 ui.write(" rev offset length " + basehdr + " linkrev"
2021 ui.write(" rev offset length " + basehdr + " linkrev"
2018 " nodeid p1 p2\n")
2022 " nodeid p1 p2\n")
2019 elif format == 1:
2023 elif format == 1:
2020 ui.write(" rev flag offset length"
2024 ui.write(" rev flag offset length"
2021 " size " + basehdr + " link p1 p2"
2025 " size " + basehdr + " link p1 p2"
2022 " nodeid\n")
2026 " nodeid\n")
2023
2027
2024 for i in r:
2028 for i in r:
2025 node = r.node(i)
2029 node = r.node(i)
2026 if generaldelta:
2030 if generaldelta:
2027 base = r.deltaparent(i)
2031 base = r.deltaparent(i)
2028 else:
2032 else:
2029 base = r.chainbase(i)
2033 base = r.chainbase(i)
2030 if format == 0:
2034 if format == 0:
2031 try:
2035 try:
2032 pp = r.parents(node)
2036 pp = r.parents(node)
2033 except Exception:
2037 except Exception:
2034 pp = [nullid, nullid]
2038 pp = [nullid, nullid]
2035 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2039 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2036 i, r.start(i), r.length(i), base, r.linkrev(i),
2040 i, r.start(i), r.length(i), base, r.linkrev(i),
2037 short(node), short(pp[0]), short(pp[1])))
2041 short(node), short(pp[0]), short(pp[1])))
2038 elif format == 1:
2042 elif format == 1:
2039 pr = r.parentrevs(i)
2043 pr = r.parentrevs(i)
2040 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2044 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2041 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2045 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2042 base, r.linkrev(i), pr[0], pr[1], short(node)))
2046 base, r.linkrev(i), pr[0], pr[1], short(node)))
2043
2047
2044 @command('debugindexdot', [], _('FILE'))
2048 @command('debugindexdot', [], _('FILE'))
2045 def debugindexdot(ui, repo, file_):
2049 def debugindexdot(ui, repo, file_):
2046 """dump an index DAG as a graphviz dot file"""
2050 """dump an index DAG as a graphviz dot file"""
2047 r = None
2051 r = None
2048 if repo:
2052 if repo:
2049 filelog = repo.file(file_)
2053 filelog = repo.file(file_)
2050 if len(filelog):
2054 if len(filelog):
2051 r = filelog
2055 r = filelog
2052 if not r:
2056 if not r:
2053 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2057 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2054 ui.write(("digraph G {\n"))
2058 ui.write(("digraph G {\n"))
2055 for i in r:
2059 for i in r:
2056 node = r.node(i)
2060 node = r.node(i)
2057 pp = r.parents(node)
2061 pp = r.parents(node)
2058 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2062 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2059 if pp[1] != nullid:
2063 if pp[1] != nullid:
2060 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2064 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2061 ui.write("}\n")
2065 ui.write("}\n")
2062
2066
2063 @command('debuginstall', [], '')
2067 @command('debuginstall', [], '')
2064 def debuginstall(ui):
2068 def debuginstall(ui):
2065 '''test Mercurial installation
2069 '''test Mercurial installation
2066
2070
2067 Returns 0 on success.
2071 Returns 0 on success.
2068 '''
2072 '''
2069
2073
2070 def writetemp(contents):
2074 def writetemp(contents):
2071 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2075 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2072 f = os.fdopen(fd, "wb")
2076 f = os.fdopen(fd, "wb")
2073 f.write(contents)
2077 f.write(contents)
2074 f.close()
2078 f.close()
2075 return name
2079 return name
2076
2080
2077 problems = 0
2081 problems = 0
2078
2082
2079 # encoding
2083 # encoding
2080 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2084 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2081 try:
2085 try:
2082 encoding.fromlocal("test")
2086 encoding.fromlocal("test")
2083 except util.Abort, inst:
2087 except util.Abort, inst:
2084 ui.write(" %s\n" % inst)
2088 ui.write(" %s\n" % inst)
2085 ui.write(_(" (check that your locale is properly set)\n"))
2089 ui.write(_(" (check that your locale is properly set)\n"))
2086 problems += 1
2090 problems += 1
2087
2091
2088 # Python lib
2092 # Python lib
2089 ui.status(_("checking Python lib (%s)...\n")
2093 ui.status(_("checking Python lib (%s)...\n")
2090 % os.path.dirname(os.__file__))
2094 % os.path.dirname(os.__file__))
2091
2095
2092 # compiled modules
2096 # compiled modules
2093 ui.status(_("checking installed modules (%s)...\n")
2097 ui.status(_("checking installed modules (%s)...\n")
2094 % os.path.dirname(__file__))
2098 % os.path.dirname(__file__))
2095 try:
2099 try:
2096 import bdiff, mpatch, base85, osutil
2100 import bdiff, mpatch, base85, osutil
2097 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2101 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2098 except Exception, inst:
2102 except Exception, inst:
2099 ui.write(" %s\n" % inst)
2103 ui.write(" %s\n" % inst)
2100 ui.write(_(" One or more extensions could not be found"))
2104 ui.write(_(" One or more extensions could not be found"))
2101 ui.write(_(" (check that you compiled the extensions)\n"))
2105 ui.write(_(" (check that you compiled the extensions)\n"))
2102 problems += 1
2106 problems += 1
2103
2107
2104 # templates
2108 # templates
2105 import templater
2109 import templater
2106 p = templater.templatepath()
2110 p = templater.templatepath()
2107 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2111 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2108 try:
2112 try:
2109 templater.templater(templater.templatepath("map-cmdline.default"))
2113 templater.templater(templater.templatepath("map-cmdline.default"))
2110 except Exception, inst:
2114 except Exception, inst:
2111 ui.write(" %s\n" % inst)
2115 ui.write(" %s\n" % inst)
2112 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2116 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2113 problems += 1
2117 problems += 1
2114
2118
2115 # editor
2119 # editor
2116 ui.status(_("checking commit editor...\n"))
2120 ui.status(_("checking commit editor...\n"))
2117 editor = ui.geteditor()
2121 editor = ui.geteditor()
2118 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2122 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2119 if not cmdpath:
2123 if not cmdpath:
2120 if editor == 'vi':
2124 if editor == 'vi':
2121 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2125 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2122 ui.write(_(" (specify a commit editor in your configuration"
2126 ui.write(_(" (specify a commit editor in your configuration"
2123 " file)\n"))
2127 " file)\n"))
2124 else:
2128 else:
2125 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2129 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2126 ui.write(_(" (specify a commit editor in your configuration"
2130 ui.write(_(" (specify a commit editor in your configuration"
2127 " file)\n"))
2131 " file)\n"))
2128 problems += 1
2132 problems += 1
2129
2133
2130 # check username
2134 # check username
2131 ui.status(_("checking username...\n"))
2135 ui.status(_("checking username...\n"))
2132 try:
2136 try:
2133 ui.username()
2137 ui.username()
2134 except util.Abort, e:
2138 except util.Abort, e:
2135 ui.write(" %s\n" % e)
2139 ui.write(" %s\n" % e)
2136 ui.write(_(" (specify a username in your configuration file)\n"))
2140 ui.write(_(" (specify a username in your configuration file)\n"))
2137 problems += 1
2141 problems += 1
2138
2142
2139 if not problems:
2143 if not problems:
2140 ui.status(_("no problems detected\n"))
2144 ui.status(_("no problems detected\n"))
2141 else:
2145 else:
2142 ui.write(_("%s problems detected,"
2146 ui.write(_("%s problems detected,"
2143 " please check your install!\n") % problems)
2147 " please check your install!\n") % problems)
2144
2148
2145 return problems
2149 return problems
2146
2150
2147 @command('debugknown', [], _('REPO ID...'))
2151 @command('debugknown', [], _('REPO ID...'))
2148 def debugknown(ui, repopath, *ids, **opts):
2152 def debugknown(ui, repopath, *ids, **opts):
2149 """test whether node ids are known to a repo
2153 """test whether node ids are known to a repo
2150
2154
2151 Every ID must be a full-length hex node id string. Returns a list of 0s
2155 Every ID must be a full-length hex node id string. Returns a list of 0s
2152 and 1s indicating unknown/known.
2156 and 1s indicating unknown/known.
2153 """
2157 """
2154 repo = hg.peer(ui, opts, repopath)
2158 repo = hg.peer(ui, opts, repopath)
2155 if not repo.capable('known'):
2159 if not repo.capable('known'):
2156 raise util.Abort("known() not supported by target repository")
2160 raise util.Abort("known() not supported by target repository")
2157 flags = repo.known([bin(s) for s in ids])
2161 flags = repo.known([bin(s) for s in ids])
2158 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2162 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2159
2163
2160 @command('debuglabelcomplete', [], _('LABEL...'))
2164 @command('debuglabelcomplete', [], _('LABEL...'))
2161 def debuglabelcomplete(ui, repo, *args):
2165 def debuglabelcomplete(ui, repo, *args):
2162 '''complete "labels" - tags, open branch names, bookmark names'''
2166 '''complete "labels" - tags, open branch names, bookmark names'''
2163
2167
2164 labels = set()
2168 labels = set()
2165 labels.update(t[0] for t in repo.tagslist())
2169 labels.update(t[0] for t in repo.tagslist())
2166 labels.update(repo._bookmarks.keys())
2170 labels.update(repo._bookmarks.keys())
2167 labels.update(tag for (tag, heads, tip, closed)
2171 labels.update(tag for (tag, heads, tip, closed)
2168 in repo.branchmap().iterbranches() if not closed)
2172 in repo.branchmap().iterbranches() if not closed)
2169 completions = set()
2173 completions = set()
2170 if not args:
2174 if not args:
2171 args = ['']
2175 args = ['']
2172 for a in args:
2176 for a in args:
2173 completions.update(l for l in labels if l.startswith(a))
2177 completions.update(l for l in labels if l.startswith(a))
2174 ui.write('\n'.join(sorted(completions)))
2178 ui.write('\n'.join(sorted(completions)))
2175 ui.write('\n')
2179 ui.write('\n')
2176
2180
2177 @command('debugobsolete',
2181 @command('debugobsolete',
2178 [('', 'flags', 0, _('markers flag')),
2182 [('', 'flags', 0, _('markers flag')),
2179 ] + commitopts2,
2183 ] + commitopts2,
2180 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2184 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2181 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2185 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2182 """create arbitrary obsolete marker
2186 """create arbitrary obsolete marker
2183
2187
2184 With no arguments, displays the list of obsolescence markers."""
2188 With no arguments, displays the list of obsolescence markers."""
2185 def parsenodeid(s):
2189 def parsenodeid(s):
2186 try:
2190 try:
2187 # We do not use revsingle/revrange functions here to accept
2191 # We do not use revsingle/revrange functions here to accept
2188 # arbitrary node identifiers, possibly not present in the
2192 # arbitrary node identifiers, possibly not present in the
2189 # local repository.
2193 # local repository.
2190 n = bin(s)
2194 n = bin(s)
2191 if len(n) != len(nullid):
2195 if len(n) != len(nullid):
2192 raise TypeError()
2196 raise TypeError()
2193 return n
2197 return n
2194 except TypeError:
2198 except TypeError:
2195 raise util.Abort('changeset references must be full hexadecimal '
2199 raise util.Abort('changeset references must be full hexadecimal '
2196 'node identifiers')
2200 'node identifiers')
2197
2201
2198 if precursor is not None:
2202 if precursor is not None:
2199 metadata = {}
2203 metadata = {}
2200 if 'date' in opts:
2204 if 'date' in opts:
2201 metadata['date'] = opts['date']
2205 metadata['date'] = opts['date']
2202 metadata['user'] = opts['user'] or ui.username()
2206 metadata['user'] = opts['user'] or ui.username()
2203 succs = tuple(parsenodeid(succ) for succ in successors)
2207 succs = tuple(parsenodeid(succ) for succ in successors)
2204 l = repo.lock()
2208 l = repo.lock()
2205 try:
2209 try:
2206 tr = repo.transaction('debugobsolete')
2210 tr = repo.transaction('debugobsolete')
2207 try:
2211 try:
2208 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2212 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2209 opts['flags'], metadata)
2213 opts['flags'], metadata)
2210 tr.close()
2214 tr.close()
2211 finally:
2215 finally:
2212 tr.release()
2216 tr.release()
2213 finally:
2217 finally:
2214 l.release()
2218 l.release()
2215 else:
2219 else:
2216 for m in obsolete.allmarkers(repo):
2220 for m in obsolete.allmarkers(repo):
2217 ui.write(hex(m.precnode()))
2221 ui.write(hex(m.precnode()))
2218 for repl in m.succnodes():
2222 for repl in m.succnodes():
2219 ui.write(' ')
2223 ui.write(' ')
2220 ui.write(hex(repl))
2224 ui.write(hex(repl))
2221 ui.write(' %X ' % m._data[2])
2225 ui.write(' %X ' % m._data[2])
2222 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2226 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2223 sorted(m.metadata().items()))))
2227 sorted(m.metadata().items()))))
2224 ui.write('\n')
2228 ui.write('\n')
2225
2229
2226 @command('debugpathcomplete',
2230 @command('debugpathcomplete',
2227 [('f', 'full', None, _('complete an entire path')),
2231 [('f', 'full', None, _('complete an entire path')),
2228 ('n', 'normal', None, _('show only normal files')),
2232 ('n', 'normal', None, _('show only normal files')),
2229 ('a', 'added', None, _('show only added files')),
2233 ('a', 'added', None, _('show only added files')),
2230 ('r', 'removed', None, _('show only removed files'))],
2234 ('r', 'removed', None, _('show only removed files'))],
2231 _('FILESPEC...'))
2235 _('FILESPEC...'))
2232 def debugpathcomplete(ui, repo, *specs, **opts):
2236 def debugpathcomplete(ui, repo, *specs, **opts):
2233 '''complete part or all of a tracked path
2237 '''complete part or all of a tracked path
2234
2238
2235 This command supports shells that offer path name completion. It
2239 This command supports shells that offer path name completion. It
2236 currently completes only files already known to the dirstate.
2240 currently completes only files already known to the dirstate.
2237
2241
2238 Completion extends only to the next path segment unless
2242 Completion extends only to the next path segment unless
2239 --full is specified, in which case entire paths are used.'''
2243 --full is specified, in which case entire paths are used.'''
2240
2244
2241 def complete(path, acceptable):
2245 def complete(path, acceptable):
2242 dirstate = repo.dirstate
2246 dirstate = repo.dirstate
2243 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2247 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2244 rootdir = repo.root + os.sep
2248 rootdir = repo.root + os.sep
2245 if spec != repo.root and not spec.startswith(rootdir):
2249 if spec != repo.root and not spec.startswith(rootdir):
2246 return [], []
2250 return [], []
2247 if os.path.isdir(spec):
2251 if os.path.isdir(spec):
2248 spec += '/'
2252 spec += '/'
2249 spec = spec[len(rootdir):]
2253 spec = spec[len(rootdir):]
2250 fixpaths = os.sep != '/'
2254 fixpaths = os.sep != '/'
2251 if fixpaths:
2255 if fixpaths:
2252 spec = spec.replace(os.sep, '/')
2256 spec = spec.replace(os.sep, '/')
2253 speclen = len(spec)
2257 speclen = len(spec)
2254 fullpaths = opts['full']
2258 fullpaths = opts['full']
2255 files, dirs = set(), set()
2259 files, dirs = set(), set()
2256 adddir, addfile = dirs.add, files.add
2260 adddir, addfile = dirs.add, files.add
2257 for f, st in dirstate.iteritems():
2261 for f, st in dirstate.iteritems():
2258 if f.startswith(spec) and st[0] in acceptable:
2262 if f.startswith(spec) and st[0] in acceptable:
2259 if fixpaths:
2263 if fixpaths:
2260 f = f.replace('/', os.sep)
2264 f = f.replace('/', os.sep)
2261 if fullpaths:
2265 if fullpaths:
2262 addfile(f)
2266 addfile(f)
2263 continue
2267 continue
2264 s = f.find(os.sep, speclen)
2268 s = f.find(os.sep, speclen)
2265 if s >= 0:
2269 if s >= 0:
2266 adddir(f[:s])
2270 adddir(f[:s])
2267 else:
2271 else:
2268 addfile(f)
2272 addfile(f)
2269 return files, dirs
2273 return files, dirs
2270
2274
2271 acceptable = ''
2275 acceptable = ''
2272 if opts['normal']:
2276 if opts['normal']:
2273 acceptable += 'nm'
2277 acceptable += 'nm'
2274 if opts['added']:
2278 if opts['added']:
2275 acceptable += 'a'
2279 acceptable += 'a'
2276 if opts['removed']:
2280 if opts['removed']:
2277 acceptable += 'r'
2281 acceptable += 'r'
2278 cwd = repo.getcwd()
2282 cwd = repo.getcwd()
2279 if not specs:
2283 if not specs:
2280 specs = ['.']
2284 specs = ['.']
2281
2285
2282 files, dirs = set(), set()
2286 files, dirs = set(), set()
2283 for spec in specs:
2287 for spec in specs:
2284 f, d = complete(spec, acceptable or 'nmar')
2288 f, d = complete(spec, acceptable or 'nmar')
2285 files.update(f)
2289 files.update(f)
2286 dirs.update(d)
2290 dirs.update(d)
2287 files.update(dirs)
2291 files.update(dirs)
2288 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2292 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2289 ui.write('\n')
2293 ui.write('\n')
2290
2294
2291 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2295 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2292 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2296 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2293 '''access the pushkey key/value protocol
2297 '''access the pushkey key/value protocol
2294
2298
2295 With two args, list the keys in the given namespace.
2299 With two args, list the keys in the given namespace.
2296
2300
2297 With five args, set a key to new if it currently is set to old.
2301 With five args, set a key to new if it currently is set to old.
2298 Reports success or failure.
2302 Reports success or failure.
2299 '''
2303 '''
2300
2304
2301 target = hg.peer(ui, {}, repopath)
2305 target = hg.peer(ui, {}, repopath)
2302 if keyinfo:
2306 if keyinfo:
2303 key, old, new = keyinfo
2307 key, old, new = keyinfo
2304 r = target.pushkey(namespace, key, old, new)
2308 r = target.pushkey(namespace, key, old, new)
2305 ui.status(str(r) + '\n')
2309 ui.status(str(r) + '\n')
2306 return not r
2310 return not r
2307 else:
2311 else:
2308 for k, v in sorted(target.listkeys(namespace).iteritems()):
2312 for k, v in sorted(target.listkeys(namespace).iteritems()):
2309 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2313 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2310 v.encode('string-escape')))
2314 v.encode('string-escape')))
2311
2315
2312 @command('debugpvec', [], _('A B'))
2316 @command('debugpvec', [], _('A B'))
2313 def debugpvec(ui, repo, a, b=None):
2317 def debugpvec(ui, repo, a, b=None):
2314 ca = scmutil.revsingle(repo, a)
2318 ca = scmutil.revsingle(repo, a)
2315 cb = scmutil.revsingle(repo, b)
2319 cb = scmutil.revsingle(repo, b)
2316 pa = pvec.ctxpvec(ca)
2320 pa = pvec.ctxpvec(ca)
2317 pb = pvec.ctxpvec(cb)
2321 pb = pvec.ctxpvec(cb)
2318 if pa == pb:
2322 if pa == pb:
2319 rel = "="
2323 rel = "="
2320 elif pa > pb:
2324 elif pa > pb:
2321 rel = ">"
2325 rel = ">"
2322 elif pa < pb:
2326 elif pa < pb:
2323 rel = "<"
2327 rel = "<"
2324 elif pa | pb:
2328 elif pa | pb:
2325 rel = "|"
2329 rel = "|"
2326 ui.write(_("a: %s\n") % pa)
2330 ui.write(_("a: %s\n") % pa)
2327 ui.write(_("b: %s\n") % pb)
2331 ui.write(_("b: %s\n") % pb)
2328 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2332 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2329 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2333 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2330 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2334 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2331 pa.distance(pb), rel))
2335 pa.distance(pb), rel))
2332
2336
2333 @command('debugrebuilddirstate|debugrebuildstate',
2337 @command('debugrebuilddirstate|debugrebuildstate',
2334 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2338 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2335 _('[-r REV]'))
2339 _('[-r REV]'))
2336 def debugrebuilddirstate(ui, repo, rev):
2340 def debugrebuilddirstate(ui, repo, rev):
2337 """rebuild the dirstate as it would look like for the given revision
2341 """rebuild the dirstate as it would look like for the given revision
2338
2342
2339 If no revision is specified the first current parent will be used.
2343 If no revision is specified the first current parent will be used.
2340
2344
2341 The dirstate will be set to the files of the given revision.
2345 The dirstate will be set to the files of the given revision.
2342 The actual working directory content or existing dirstate
2346 The actual working directory content or existing dirstate
2343 information such as adds or removes is not considered.
2347 information such as adds or removes is not considered.
2344
2348
2345 One use of this command is to make the next :hg:`status` invocation
2349 One use of this command is to make the next :hg:`status` invocation
2346 check the actual file content.
2350 check the actual file content.
2347 """
2351 """
2348 ctx = scmutil.revsingle(repo, rev)
2352 ctx = scmutil.revsingle(repo, rev)
2349 wlock = repo.wlock()
2353 wlock = repo.wlock()
2350 try:
2354 try:
2351 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2355 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2352 finally:
2356 finally:
2353 wlock.release()
2357 wlock.release()
2354
2358
2355 @command('debugrename',
2359 @command('debugrename',
2356 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2360 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2357 _('[-r REV] FILE'))
2361 _('[-r REV] FILE'))
2358 def debugrename(ui, repo, file1, *pats, **opts):
2362 def debugrename(ui, repo, file1, *pats, **opts):
2359 """dump rename information"""
2363 """dump rename information"""
2360
2364
2361 ctx = scmutil.revsingle(repo, opts.get('rev'))
2365 ctx = scmutil.revsingle(repo, opts.get('rev'))
2362 m = scmutil.match(ctx, (file1,) + pats, opts)
2366 m = scmutil.match(ctx, (file1,) + pats, opts)
2363 for abs in ctx.walk(m):
2367 for abs in ctx.walk(m):
2364 fctx = ctx[abs]
2368 fctx = ctx[abs]
2365 o = fctx.filelog().renamed(fctx.filenode())
2369 o = fctx.filelog().renamed(fctx.filenode())
2366 rel = m.rel(abs)
2370 rel = m.rel(abs)
2367 if o:
2371 if o:
2368 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2372 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2369 else:
2373 else:
2370 ui.write(_("%s not renamed\n") % rel)
2374 ui.write(_("%s not renamed\n") % rel)
2371
2375
2372 @command('debugrevlog',
2376 @command('debugrevlog',
2373 [('c', 'changelog', False, _('open changelog')),
2377 [('c', 'changelog', False, _('open changelog')),
2374 ('m', 'manifest', False, _('open manifest')),
2378 ('m', 'manifest', False, _('open manifest')),
2375 ('d', 'dump', False, _('dump index data'))],
2379 ('d', 'dump', False, _('dump index data'))],
2376 _('-c|-m|FILE'))
2380 _('-c|-m|FILE'))
2377 def debugrevlog(ui, repo, file_=None, **opts):
2381 def debugrevlog(ui, repo, file_=None, **opts):
2378 """show data and statistics about a revlog"""
2382 """show data and statistics about a revlog"""
2379 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2383 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2380
2384
2381 if opts.get("dump"):
2385 if opts.get("dump"):
2382 numrevs = len(r)
2386 numrevs = len(r)
2383 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2387 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2384 " rawsize totalsize compression heads\n")
2388 " rawsize totalsize compression heads\n")
2385 ts = 0
2389 ts = 0
2386 heads = set()
2390 heads = set()
2387 for rev in xrange(numrevs):
2391 for rev in xrange(numrevs):
2388 dbase = r.deltaparent(rev)
2392 dbase = r.deltaparent(rev)
2389 if dbase == -1:
2393 if dbase == -1:
2390 dbase = rev
2394 dbase = rev
2391 cbase = r.chainbase(rev)
2395 cbase = r.chainbase(rev)
2392 p1, p2 = r.parentrevs(rev)
2396 p1, p2 = r.parentrevs(rev)
2393 rs = r.rawsize(rev)
2397 rs = r.rawsize(rev)
2394 ts = ts + rs
2398 ts = ts + rs
2395 heads -= set(r.parentrevs(rev))
2399 heads -= set(r.parentrevs(rev))
2396 heads.add(rev)
2400 heads.add(rev)
2397 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2401 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2398 (rev, p1, p2, r.start(rev), r.end(rev),
2402 (rev, p1, p2, r.start(rev), r.end(rev),
2399 r.start(dbase), r.start(cbase),
2403 r.start(dbase), r.start(cbase),
2400 r.start(p1), r.start(p2),
2404 r.start(p1), r.start(p2),
2401 rs, ts, ts / r.end(rev), len(heads)))
2405 rs, ts, ts / r.end(rev), len(heads)))
2402 return 0
2406 return 0
2403
2407
2404 v = r.version
2408 v = r.version
2405 format = v & 0xFFFF
2409 format = v & 0xFFFF
2406 flags = []
2410 flags = []
2407 gdelta = False
2411 gdelta = False
2408 if v & revlog.REVLOGNGINLINEDATA:
2412 if v & revlog.REVLOGNGINLINEDATA:
2409 flags.append('inline')
2413 flags.append('inline')
2410 if v & revlog.REVLOGGENERALDELTA:
2414 if v & revlog.REVLOGGENERALDELTA:
2411 gdelta = True
2415 gdelta = True
2412 flags.append('generaldelta')
2416 flags.append('generaldelta')
2413 if not flags:
2417 if not flags:
2414 flags = ['(none)']
2418 flags = ['(none)']
2415
2419
2416 nummerges = 0
2420 nummerges = 0
2417 numfull = 0
2421 numfull = 0
2418 numprev = 0
2422 numprev = 0
2419 nump1 = 0
2423 nump1 = 0
2420 nump2 = 0
2424 nump2 = 0
2421 numother = 0
2425 numother = 0
2422 nump1prev = 0
2426 nump1prev = 0
2423 nump2prev = 0
2427 nump2prev = 0
2424 chainlengths = []
2428 chainlengths = []
2425
2429
2426 datasize = [None, 0, 0L]
2430 datasize = [None, 0, 0L]
2427 fullsize = [None, 0, 0L]
2431 fullsize = [None, 0, 0L]
2428 deltasize = [None, 0, 0L]
2432 deltasize = [None, 0, 0L]
2429
2433
2430 def addsize(size, l):
2434 def addsize(size, l):
2431 if l[0] is None or size < l[0]:
2435 if l[0] is None or size < l[0]:
2432 l[0] = size
2436 l[0] = size
2433 if size > l[1]:
2437 if size > l[1]:
2434 l[1] = size
2438 l[1] = size
2435 l[2] += size
2439 l[2] += size
2436
2440
2437 numrevs = len(r)
2441 numrevs = len(r)
2438 for rev in xrange(numrevs):
2442 for rev in xrange(numrevs):
2439 p1, p2 = r.parentrevs(rev)
2443 p1, p2 = r.parentrevs(rev)
2440 delta = r.deltaparent(rev)
2444 delta = r.deltaparent(rev)
2441 if format > 0:
2445 if format > 0:
2442 addsize(r.rawsize(rev), datasize)
2446 addsize(r.rawsize(rev), datasize)
2443 if p2 != nullrev:
2447 if p2 != nullrev:
2444 nummerges += 1
2448 nummerges += 1
2445 size = r.length(rev)
2449 size = r.length(rev)
2446 if delta == nullrev:
2450 if delta == nullrev:
2447 chainlengths.append(0)
2451 chainlengths.append(0)
2448 numfull += 1
2452 numfull += 1
2449 addsize(size, fullsize)
2453 addsize(size, fullsize)
2450 else:
2454 else:
2451 chainlengths.append(chainlengths[delta] + 1)
2455 chainlengths.append(chainlengths[delta] + 1)
2452 addsize(size, deltasize)
2456 addsize(size, deltasize)
2453 if delta == rev - 1:
2457 if delta == rev - 1:
2454 numprev += 1
2458 numprev += 1
2455 if delta == p1:
2459 if delta == p1:
2456 nump1prev += 1
2460 nump1prev += 1
2457 elif delta == p2:
2461 elif delta == p2:
2458 nump2prev += 1
2462 nump2prev += 1
2459 elif delta == p1:
2463 elif delta == p1:
2460 nump1 += 1
2464 nump1 += 1
2461 elif delta == p2:
2465 elif delta == p2:
2462 nump2 += 1
2466 nump2 += 1
2463 elif delta != nullrev:
2467 elif delta != nullrev:
2464 numother += 1
2468 numother += 1
2465
2469
2466 # Adjust size min value for empty cases
2470 # Adjust size min value for empty cases
2467 for size in (datasize, fullsize, deltasize):
2471 for size in (datasize, fullsize, deltasize):
2468 if size[0] is None:
2472 if size[0] is None:
2469 size[0] = 0
2473 size[0] = 0
2470
2474
2471 numdeltas = numrevs - numfull
2475 numdeltas = numrevs - numfull
2472 numoprev = numprev - nump1prev - nump2prev
2476 numoprev = numprev - nump1prev - nump2prev
2473 totalrawsize = datasize[2]
2477 totalrawsize = datasize[2]
2474 datasize[2] /= numrevs
2478 datasize[2] /= numrevs
2475 fulltotal = fullsize[2]
2479 fulltotal = fullsize[2]
2476 fullsize[2] /= numfull
2480 fullsize[2] /= numfull
2477 deltatotal = deltasize[2]
2481 deltatotal = deltasize[2]
2478 if numrevs - numfull > 0:
2482 if numrevs - numfull > 0:
2479 deltasize[2] /= numrevs - numfull
2483 deltasize[2] /= numrevs - numfull
2480 totalsize = fulltotal + deltatotal
2484 totalsize = fulltotal + deltatotal
2481 avgchainlen = sum(chainlengths) / numrevs
2485 avgchainlen = sum(chainlengths) / numrevs
2482 compratio = totalrawsize / totalsize
2486 compratio = totalrawsize / totalsize
2483
2487
2484 basedfmtstr = '%%%dd\n'
2488 basedfmtstr = '%%%dd\n'
2485 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2489 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2486
2490
2487 def dfmtstr(max):
2491 def dfmtstr(max):
2488 return basedfmtstr % len(str(max))
2492 return basedfmtstr % len(str(max))
2489 def pcfmtstr(max, padding=0):
2493 def pcfmtstr(max, padding=0):
2490 return basepcfmtstr % (len(str(max)), ' ' * padding)
2494 return basepcfmtstr % (len(str(max)), ' ' * padding)
2491
2495
2492 def pcfmt(value, total):
2496 def pcfmt(value, total):
2493 return (value, 100 * float(value) / total)
2497 return (value, 100 * float(value) / total)
2494
2498
2495 ui.write(('format : %d\n') % format)
2499 ui.write(('format : %d\n') % format)
2496 ui.write(('flags : %s\n') % ', '.join(flags))
2500 ui.write(('flags : %s\n') % ', '.join(flags))
2497
2501
2498 ui.write('\n')
2502 ui.write('\n')
2499 fmt = pcfmtstr(totalsize)
2503 fmt = pcfmtstr(totalsize)
2500 fmt2 = dfmtstr(totalsize)
2504 fmt2 = dfmtstr(totalsize)
2501 ui.write(('revisions : ') + fmt2 % numrevs)
2505 ui.write(('revisions : ') + fmt2 % numrevs)
2502 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2506 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2503 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2507 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2504 ui.write(('revisions : ') + fmt2 % numrevs)
2508 ui.write(('revisions : ') + fmt2 % numrevs)
2505 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2509 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2506 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2510 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2507 ui.write(('revision size : ') + fmt2 % totalsize)
2511 ui.write(('revision size : ') + fmt2 % totalsize)
2508 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2512 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2509 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2513 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2510
2514
2511 ui.write('\n')
2515 ui.write('\n')
2512 fmt = dfmtstr(max(avgchainlen, compratio))
2516 fmt = dfmtstr(max(avgchainlen, compratio))
2513 ui.write(('avg chain length : ') + fmt % avgchainlen)
2517 ui.write(('avg chain length : ') + fmt % avgchainlen)
2514 ui.write(('compression ratio : ') + fmt % compratio)
2518 ui.write(('compression ratio : ') + fmt % compratio)
2515
2519
2516 if format > 0:
2520 if format > 0:
2517 ui.write('\n')
2521 ui.write('\n')
2518 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2522 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2519 % tuple(datasize))
2523 % tuple(datasize))
2520 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2524 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2521 % tuple(fullsize))
2525 % tuple(fullsize))
2522 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2526 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2523 % tuple(deltasize))
2527 % tuple(deltasize))
2524
2528
2525 if numdeltas > 0:
2529 if numdeltas > 0:
2526 ui.write('\n')
2530 ui.write('\n')
2527 fmt = pcfmtstr(numdeltas)
2531 fmt = pcfmtstr(numdeltas)
2528 fmt2 = pcfmtstr(numdeltas, 4)
2532 fmt2 = pcfmtstr(numdeltas, 4)
2529 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2533 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2530 if numprev > 0:
2534 if numprev > 0:
2531 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2535 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2532 numprev))
2536 numprev))
2533 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2537 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2534 numprev))
2538 numprev))
2535 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2539 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2536 numprev))
2540 numprev))
2537 if gdelta:
2541 if gdelta:
2538 ui.write(('deltas against p1 : ')
2542 ui.write(('deltas against p1 : ')
2539 + fmt % pcfmt(nump1, numdeltas))
2543 + fmt % pcfmt(nump1, numdeltas))
2540 ui.write(('deltas against p2 : ')
2544 ui.write(('deltas against p2 : ')
2541 + fmt % pcfmt(nump2, numdeltas))
2545 + fmt % pcfmt(nump2, numdeltas))
2542 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2546 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2543 numdeltas))
2547 numdeltas))
2544
2548
2545 @command('debugrevspec', [], ('REVSPEC'))
2549 @command('debugrevspec', [], ('REVSPEC'))
2546 def debugrevspec(ui, repo, expr):
2550 def debugrevspec(ui, repo, expr):
2547 """parse and apply a revision specification
2551 """parse and apply a revision specification
2548
2552
2549 Use --verbose to print the parsed tree before and after aliases
2553 Use --verbose to print the parsed tree before and after aliases
2550 expansion.
2554 expansion.
2551 """
2555 """
2552 if ui.verbose:
2556 if ui.verbose:
2553 tree = revset.parse(expr)[0]
2557 tree = revset.parse(expr)[0]
2554 ui.note(revset.prettyformat(tree), "\n")
2558 ui.note(revset.prettyformat(tree), "\n")
2555 newtree = revset.findaliases(ui, tree)
2559 newtree = revset.findaliases(ui, tree)
2556 if newtree != tree:
2560 if newtree != tree:
2557 ui.note(revset.prettyformat(newtree), "\n")
2561 ui.note(revset.prettyformat(newtree), "\n")
2558 func = revset.match(ui, expr)
2562 func = revset.match(ui, expr)
2559 for c in func(repo, range(len(repo))):
2563 for c in func(repo, range(len(repo))):
2560 ui.write("%s\n" % c)
2564 ui.write("%s\n" % c)
2561
2565
2562 @command('debugsetparents', [], _('REV1 [REV2]'))
2566 @command('debugsetparents', [], _('REV1 [REV2]'))
2563 def debugsetparents(ui, repo, rev1, rev2=None):
2567 def debugsetparents(ui, repo, rev1, rev2=None):
2564 """manually set the parents of the current working directory
2568 """manually set the parents of the current working directory
2565
2569
2566 This is useful for writing repository conversion tools, but should
2570 This is useful for writing repository conversion tools, but should
2567 be used with care.
2571 be used with care.
2568
2572
2569 Returns 0 on success.
2573 Returns 0 on success.
2570 """
2574 """
2571
2575
2572 r1 = scmutil.revsingle(repo, rev1).node()
2576 r1 = scmutil.revsingle(repo, rev1).node()
2573 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2577 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2574
2578
2575 wlock = repo.wlock()
2579 wlock = repo.wlock()
2576 try:
2580 try:
2577 repo.setparents(r1, r2)
2581 repo.setparents(r1, r2)
2578 finally:
2582 finally:
2579 wlock.release()
2583 wlock.release()
2580
2584
2581 @command('debugdirstate|debugstate',
2585 @command('debugdirstate|debugstate',
2582 [('', 'nodates', None, _('do not display the saved mtime')),
2586 [('', 'nodates', None, _('do not display the saved mtime')),
2583 ('', 'datesort', None, _('sort by saved mtime'))],
2587 ('', 'datesort', None, _('sort by saved mtime'))],
2584 _('[OPTION]...'))
2588 _('[OPTION]...'))
2585 def debugstate(ui, repo, nodates=None, datesort=None):
2589 def debugstate(ui, repo, nodates=None, datesort=None):
2586 """show the contents of the current dirstate"""
2590 """show the contents of the current dirstate"""
2587 timestr = ""
2591 timestr = ""
2588 showdate = not nodates
2592 showdate = not nodates
2589 if datesort:
2593 if datesort:
2590 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2594 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2591 else:
2595 else:
2592 keyfunc = None # sort by filename
2596 keyfunc = None # sort by filename
2593 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2597 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2594 if showdate:
2598 if showdate:
2595 if ent[3] == -1:
2599 if ent[3] == -1:
2596 # Pad or slice to locale representation
2600 # Pad or slice to locale representation
2597 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2601 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2598 time.localtime(0)))
2602 time.localtime(0)))
2599 timestr = 'unset'
2603 timestr = 'unset'
2600 timestr = (timestr[:locale_len] +
2604 timestr = (timestr[:locale_len] +
2601 ' ' * (locale_len - len(timestr)))
2605 ' ' * (locale_len - len(timestr)))
2602 else:
2606 else:
2603 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2607 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2604 time.localtime(ent[3]))
2608 time.localtime(ent[3]))
2605 if ent[1] & 020000:
2609 if ent[1] & 020000:
2606 mode = 'lnk'
2610 mode = 'lnk'
2607 else:
2611 else:
2608 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2612 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2609 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2613 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2610 for f in repo.dirstate.copies():
2614 for f in repo.dirstate.copies():
2611 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2615 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2612
2616
2613 @command('debugsub',
2617 @command('debugsub',
2614 [('r', 'rev', '',
2618 [('r', 'rev', '',
2615 _('revision to check'), _('REV'))],
2619 _('revision to check'), _('REV'))],
2616 _('[-r REV] [REV]'))
2620 _('[-r REV] [REV]'))
2617 def debugsub(ui, repo, rev=None):
2621 def debugsub(ui, repo, rev=None):
2618 ctx = scmutil.revsingle(repo, rev, None)
2622 ctx = scmutil.revsingle(repo, rev, None)
2619 for k, v in sorted(ctx.substate.items()):
2623 for k, v in sorted(ctx.substate.items()):
2620 ui.write(('path %s\n') % k)
2624 ui.write(('path %s\n') % k)
2621 ui.write((' source %s\n') % v[0])
2625 ui.write((' source %s\n') % v[0])
2622 ui.write((' revision %s\n') % v[1])
2626 ui.write((' revision %s\n') % v[1])
2623
2627
2624 @command('debugsuccessorssets',
2628 @command('debugsuccessorssets',
2625 [],
2629 [],
2626 _('[REV]'))
2630 _('[REV]'))
2627 def debugsuccessorssets(ui, repo, *revs):
2631 def debugsuccessorssets(ui, repo, *revs):
2628 """show set of successors for revision
2632 """show set of successors for revision
2629
2633
2630 A successors set of changeset A is a consistent group of revisions that
2634 A successors set of changeset A is a consistent group of revisions that
2631 succeed A. It contains non-obsolete changesets only.
2635 succeed A. It contains non-obsolete changesets only.
2632
2636
2633 In most cases a changeset A has a single successors set containing a single
2637 In most cases a changeset A has a single successors set containing a single
2634 successor (changeset A replaced by A').
2638 successor (changeset A replaced by A').
2635
2639
2636 A changeset that is made obsolete with no successors are called "pruned".
2640 A changeset that is made obsolete with no successors are called "pruned".
2637 Such changesets have no successors sets at all.
2641 Such changesets have no successors sets at all.
2638
2642
2639 A changeset that has been "split" will have a successors set containing
2643 A changeset that has been "split" will have a successors set containing
2640 more than one successor.
2644 more than one successor.
2641
2645
2642 A changeset that has been rewritten in multiple different ways is called
2646 A changeset that has been rewritten in multiple different ways is called
2643 "divergent". Such changesets have multiple successor sets (each of which
2647 "divergent". Such changesets have multiple successor sets (each of which
2644 may also be split, i.e. have multiple successors).
2648 may also be split, i.e. have multiple successors).
2645
2649
2646 Results are displayed as follows::
2650 Results are displayed as follows::
2647
2651
2648 <rev1>
2652 <rev1>
2649 <successors-1A>
2653 <successors-1A>
2650 <rev2>
2654 <rev2>
2651 <successors-2A>
2655 <successors-2A>
2652 <successors-2B1> <successors-2B2> <successors-2B3>
2656 <successors-2B1> <successors-2B2> <successors-2B3>
2653
2657
2654 Here rev2 has two possible (i.e. divergent) successors sets. The first
2658 Here rev2 has two possible (i.e. divergent) successors sets. The first
2655 holds one element, whereas the second holds three (i.e. the changeset has
2659 holds one element, whereas the second holds three (i.e. the changeset has
2656 been split).
2660 been split).
2657 """
2661 """
2658 # passed to successorssets caching computation from one call to another
2662 # passed to successorssets caching computation from one call to another
2659 cache = {}
2663 cache = {}
2660 ctx2str = str
2664 ctx2str = str
2661 node2str = short
2665 node2str = short
2662 if ui.debug():
2666 if ui.debug():
2663 def ctx2str(ctx):
2667 def ctx2str(ctx):
2664 return ctx.hex()
2668 return ctx.hex()
2665 node2str = hex
2669 node2str = hex
2666 for rev in scmutil.revrange(repo, revs):
2670 for rev in scmutil.revrange(repo, revs):
2667 ctx = repo[rev]
2671 ctx = repo[rev]
2668 ui.write('%s\n'% ctx2str(ctx))
2672 ui.write('%s\n'% ctx2str(ctx))
2669 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2673 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2670 if succsset:
2674 if succsset:
2671 ui.write(' ')
2675 ui.write(' ')
2672 ui.write(node2str(succsset[0]))
2676 ui.write(node2str(succsset[0]))
2673 for node in succsset[1:]:
2677 for node in succsset[1:]:
2674 ui.write(' ')
2678 ui.write(' ')
2675 ui.write(node2str(node))
2679 ui.write(node2str(node))
2676 ui.write('\n')
2680 ui.write('\n')
2677
2681
2678 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2682 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2679 def debugwalk(ui, repo, *pats, **opts):
2683 def debugwalk(ui, repo, *pats, **opts):
2680 """show how files match on given patterns"""
2684 """show how files match on given patterns"""
2681 m = scmutil.match(repo[None], pats, opts)
2685 m = scmutil.match(repo[None], pats, opts)
2682 items = list(repo.walk(m))
2686 items = list(repo.walk(m))
2683 if not items:
2687 if not items:
2684 return
2688 return
2685 f = lambda fn: fn
2689 f = lambda fn: fn
2686 if ui.configbool('ui', 'slash') and os.sep != '/':
2690 if ui.configbool('ui', 'slash') and os.sep != '/':
2687 f = lambda fn: util.normpath(fn)
2691 f = lambda fn: util.normpath(fn)
2688 fmt = 'f %%-%ds %%-%ds %%s' % (
2692 fmt = 'f %%-%ds %%-%ds %%s' % (
2689 max([len(abs) for abs in items]),
2693 max([len(abs) for abs in items]),
2690 max([len(m.rel(abs)) for abs in items]))
2694 max([len(m.rel(abs)) for abs in items]))
2691 for abs in items:
2695 for abs in items:
2692 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2696 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2693 ui.write("%s\n" % line.rstrip())
2697 ui.write("%s\n" % line.rstrip())
2694
2698
2695 @command('debugwireargs',
2699 @command('debugwireargs',
2696 [('', 'three', '', 'three'),
2700 [('', 'three', '', 'three'),
2697 ('', 'four', '', 'four'),
2701 ('', 'four', '', 'four'),
2698 ('', 'five', '', 'five'),
2702 ('', 'five', '', 'five'),
2699 ] + remoteopts,
2703 ] + remoteopts,
2700 _('REPO [OPTIONS]... [ONE [TWO]]'))
2704 _('REPO [OPTIONS]... [ONE [TWO]]'))
2701 def debugwireargs(ui, repopath, *vals, **opts):
2705 def debugwireargs(ui, repopath, *vals, **opts):
2702 repo = hg.peer(ui, opts, repopath)
2706 repo = hg.peer(ui, opts, repopath)
2703 for opt in remoteopts:
2707 for opt in remoteopts:
2704 del opts[opt[1]]
2708 del opts[opt[1]]
2705 args = {}
2709 args = {}
2706 for k, v in opts.iteritems():
2710 for k, v in opts.iteritems():
2707 if v:
2711 if v:
2708 args[k] = v
2712 args[k] = v
2709 # run twice to check that we don't mess up the stream for the next command
2713 # run twice to check that we don't mess up the stream for the next command
2710 res1 = repo.debugwireargs(*vals, **args)
2714 res1 = repo.debugwireargs(*vals, **args)
2711 res2 = repo.debugwireargs(*vals, **args)
2715 res2 = repo.debugwireargs(*vals, **args)
2712 ui.write("%s\n" % res1)
2716 ui.write("%s\n" % res1)
2713 if res1 != res2:
2717 if res1 != res2:
2714 ui.warn("%s\n" % res2)
2718 ui.warn("%s\n" % res2)
2715
2719
2716 @command('^diff',
2720 @command('^diff',
2717 [('r', 'rev', [], _('revision'), _('REV')),
2721 [('r', 'rev', [], _('revision'), _('REV')),
2718 ('c', 'change', '', _('change made by revision'), _('REV'))
2722 ('c', 'change', '', _('change made by revision'), _('REV'))
2719 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2723 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2720 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2724 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2721 def diff(ui, repo, *pats, **opts):
2725 def diff(ui, repo, *pats, **opts):
2722 """diff repository (or selected files)
2726 """diff repository (or selected files)
2723
2727
2724 Show differences between revisions for the specified files.
2728 Show differences between revisions for the specified files.
2725
2729
2726 Differences between files are shown using the unified diff format.
2730 Differences between files are shown using the unified diff format.
2727
2731
2728 .. note::
2732 .. note::
2729
2733
2730 diff may generate unexpected results for merges, as it will
2734 diff may generate unexpected results for merges, as it will
2731 default to comparing against the working directory's first
2735 default to comparing against the working directory's first
2732 parent changeset if no revisions are specified.
2736 parent changeset if no revisions are specified.
2733
2737
2734 When two revision arguments are given, then changes are shown
2738 When two revision arguments are given, then changes are shown
2735 between those revisions. If only one revision is specified then
2739 between those revisions. If only one revision is specified then
2736 that revision is compared to the working directory, and, when no
2740 that revision is compared to the working directory, and, when no
2737 revisions are specified, the working directory files are compared
2741 revisions are specified, the working directory files are compared
2738 to its parent.
2742 to its parent.
2739
2743
2740 Alternatively you can specify -c/--change with a revision to see
2744 Alternatively you can specify -c/--change with a revision to see
2741 the changes in that changeset relative to its first parent.
2745 the changes in that changeset relative to its first parent.
2742
2746
2743 Without the -a/--text option, diff will avoid generating diffs of
2747 Without the -a/--text option, diff will avoid generating diffs of
2744 files it detects as binary. With -a, diff will generate a diff
2748 files it detects as binary. With -a, diff will generate a diff
2745 anyway, probably with undesirable results.
2749 anyway, probably with undesirable results.
2746
2750
2747 Use the -g/--git option to generate diffs in the git extended diff
2751 Use the -g/--git option to generate diffs in the git extended diff
2748 format. For more information, read :hg:`help diffs`.
2752 format. For more information, read :hg:`help diffs`.
2749
2753
2750 .. container:: verbose
2754 .. container:: verbose
2751
2755
2752 Examples:
2756 Examples:
2753
2757
2754 - compare a file in the current working directory to its parent::
2758 - compare a file in the current working directory to its parent::
2755
2759
2756 hg diff foo.c
2760 hg diff foo.c
2757
2761
2758 - compare two historical versions of a directory, with rename info::
2762 - compare two historical versions of a directory, with rename info::
2759
2763
2760 hg diff --git -r 1.0:1.2 lib/
2764 hg diff --git -r 1.0:1.2 lib/
2761
2765
2762 - get change stats relative to the last change on some date::
2766 - get change stats relative to the last change on some date::
2763
2767
2764 hg diff --stat -r "date('may 2')"
2768 hg diff --stat -r "date('may 2')"
2765
2769
2766 - diff all newly-added files that contain a keyword::
2770 - diff all newly-added files that contain a keyword::
2767
2771
2768 hg diff "set:added() and grep(GNU)"
2772 hg diff "set:added() and grep(GNU)"
2769
2773
2770 - compare a revision and its parents::
2774 - compare a revision and its parents::
2771
2775
2772 hg diff -c 9353 # compare against first parent
2776 hg diff -c 9353 # compare against first parent
2773 hg diff -r 9353^:9353 # same using revset syntax
2777 hg diff -r 9353^:9353 # same using revset syntax
2774 hg diff -r 9353^2:9353 # compare against the second parent
2778 hg diff -r 9353^2:9353 # compare against the second parent
2775
2779
2776 Returns 0 on success.
2780 Returns 0 on success.
2777 """
2781 """
2778
2782
2779 revs = opts.get('rev')
2783 revs = opts.get('rev')
2780 change = opts.get('change')
2784 change = opts.get('change')
2781 stat = opts.get('stat')
2785 stat = opts.get('stat')
2782 reverse = opts.get('reverse')
2786 reverse = opts.get('reverse')
2783
2787
2784 if revs and change:
2788 if revs and change:
2785 msg = _('cannot specify --rev and --change at the same time')
2789 msg = _('cannot specify --rev and --change at the same time')
2786 raise util.Abort(msg)
2790 raise util.Abort(msg)
2787 elif change:
2791 elif change:
2788 node2 = scmutil.revsingle(repo, change, None).node()
2792 node2 = scmutil.revsingle(repo, change, None).node()
2789 node1 = repo[node2].p1().node()
2793 node1 = repo[node2].p1().node()
2790 else:
2794 else:
2791 node1, node2 = scmutil.revpair(repo, revs)
2795 node1, node2 = scmutil.revpair(repo, revs)
2792
2796
2793 if reverse:
2797 if reverse:
2794 node1, node2 = node2, node1
2798 node1, node2 = node2, node1
2795
2799
2796 diffopts = patch.diffopts(ui, opts)
2800 diffopts = patch.diffopts(ui, opts)
2797 m = scmutil.match(repo[node2], pats, opts)
2801 m = scmutil.match(repo[node2], pats, opts)
2798 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2802 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2799 listsubrepos=opts.get('subrepos'))
2803 listsubrepos=opts.get('subrepos'))
2800
2804
2801 @command('^export',
2805 @command('^export',
2802 [('o', 'output', '',
2806 [('o', 'output', '',
2803 _('print output to file with formatted name'), _('FORMAT')),
2807 _('print output to file with formatted name'), _('FORMAT')),
2804 ('', 'switch-parent', None, _('diff against the second parent')),
2808 ('', 'switch-parent', None, _('diff against the second parent')),
2805 ('r', 'rev', [], _('revisions to export'), _('REV')),
2809 ('r', 'rev', [], _('revisions to export'), _('REV')),
2806 ] + diffopts,
2810 ] + diffopts,
2807 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2811 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2808 def export(ui, repo, *changesets, **opts):
2812 def export(ui, repo, *changesets, **opts):
2809 """dump the header and diffs for one or more changesets
2813 """dump the header and diffs for one or more changesets
2810
2814
2811 Print the changeset header and diffs for one or more revisions.
2815 Print the changeset header and diffs for one or more revisions.
2812 If no revision is given, the parent of the working directory is used.
2816 If no revision is given, the parent of the working directory is used.
2813
2817
2814 The information shown in the changeset header is: author, date,
2818 The information shown in the changeset header is: author, date,
2815 branch name (if non-default), changeset hash, parent(s) and commit
2819 branch name (if non-default), changeset hash, parent(s) and commit
2816 comment.
2820 comment.
2817
2821
2818 .. note::
2822 .. note::
2819
2823
2820 export may generate unexpected diff output for merge
2824 export may generate unexpected diff output for merge
2821 changesets, as it will compare the merge changeset against its
2825 changesets, as it will compare the merge changeset against its
2822 first parent only.
2826 first parent only.
2823
2827
2824 Output may be to a file, in which case the name of the file is
2828 Output may be to a file, in which case the name of the file is
2825 given using a format string. The formatting rules are as follows:
2829 given using a format string. The formatting rules are as follows:
2826
2830
2827 :``%%``: literal "%" character
2831 :``%%``: literal "%" character
2828 :``%H``: changeset hash (40 hexadecimal digits)
2832 :``%H``: changeset hash (40 hexadecimal digits)
2829 :``%N``: number of patches being generated
2833 :``%N``: number of patches being generated
2830 :``%R``: changeset revision number
2834 :``%R``: changeset revision number
2831 :``%b``: basename of the exporting repository
2835 :``%b``: basename of the exporting repository
2832 :``%h``: short-form changeset hash (12 hexadecimal digits)
2836 :``%h``: short-form changeset hash (12 hexadecimal digits)
2833 :``%m``: first line of the commit message (only alphanumeric characters)
2837 :``%m``: first line of the commit message (only alphanumeric characters)
2834 :``%n``: zero-padded sequence number, starting at 1
2838 :``%n``: zero-padded sequence number, starting at 1
2835 :``%r``: zero-padded changeset revision number
2839 :``%r``: zero-padded changeset revision number
2836
2840
2837 Without the -a/--text option, export will avoid generating diffs
2841 Without the -a/--text option, export will avoid generating diffs
2838 of files it detects as binary. With -a, export will generate a
2842 of files it detects as binary. With -a, export will generate a
2839 diff anyway, probably with undesirable results.
2843 diff anyway, probably with undesirable results.
2840
2844
2841 Use the -g/--git option to generate diffs in the git extended diff
2845 Use the -g/--git option to generate diffs in the git extended diff
2842 format. See :hg:`help diffs` for more information.
2846 format. See :hg:`help diffs` for more information.
2843
2847
2844 With the --switch-parent option, the diff will be against the
2848 With the --switch-parent option, the diff will be against the
2845 second parent. It can be useful to review a merge.
2849 second parent. It can be useful to review a merge.
2846
2850
2847 .. container:: verbose
2851 .. container:: verbose
2848
2852
2849 Examples:
2853 Examples:
2850
2854
2851 - use export and import to transplant a bugfix to the current
2855 - use export and import to transplant a bugfix to the current
2852 branch::
2856 branch::
2853
2857
2854 hg export -r 9353 | hg import -
2858 hg export -r 9353 | hg import -
2855
2859
2856 - export all the changesets between two revisions to a file with
2860 - export all the changesets between two revisions to a file with
2857 rename information::
2861 rename information::
2858
2862
2859 hg export --git -r 123:150 > changes.txt
2863 hg export --git -r 123:150 > changes.txt
2860
2864
2861 - split outgoing changes into a series of patches with
2865 - split outgoing changes into a series of patches with
2862 descriptive names::
2866 descriptive names::
2863
2867
2864 hg export -r "outgoing()" -o "%n-%m.patch"
2868 hg export -r "outgoing()" -o "%n-%m.patch"
2865
2869
2866 Returns 0 on success.
2870 Returns 0 on success.
2867 """
2871 """
2868 changesets += tuple(opts.get('rev', []))
2872 changesets += tuple(opts.get('rev', []))
2869 if not changesets:
2873 if not changesets:
2870 changesets = ['.']
2874 changesets = ['.']
2871 revs = scmutil.revrange(repo, changesets)
2875 revs = scmutil.revrange(repo, changesets)
2872 if not revs:
2876 if not revs:
2873 raise util.Abort(_("export requires at least one changeset"))
2877 raise util.Abort(_("export requires at least one changeset"))
2874 if len(revs) > 1:
2878 if len(revs) > 1:
2875 ui.note(_('exporting patches:\n'))
2879 ui.note(_('exporting patches:\n'))
2876 else:
2880 else:
2877 ui.note(_('exporting patch:\n'))
2881 ui.note(_('exporting patch:\n'))
2878 cmdutil.export(repo, revs, template=opts.get('output'),
2882 cmdutil.export(repo, revs, template=opts.get('output'),
2879 switch_parent=opts.get('switch_parent'),
2883 switch_parent=opts.get('switch_parent'),
2880 opts=patch.diffopts(ui, opts))
2884 opts=patch.diffopts(ui, opts))
2881
2885
2882 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2886 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2883 def forget(ui, repo, *pats, **opts):
2887 def forget(ui, repo, *pats, **opts):
2884 """forget the specified files on the next commit
2888 """forget the specified files on the next commit
2885
2889
2886 Mark the specified files so they will no longer be tracked
2890 Mark the specified files so they will no longer be tracked
2887 after the next commit.
2891 after the next commit.
2888
2892
2889 This only removes files from the current branch, not from the
2893 This only removes files from the current branch, not from the
2890 entire project history, and it does not delete them from the
2894 entire project history, and it does not delete them from the
2891 working directory.
2895 working directory.
2892
2896
2893 To undo a forget before the next commit, see :hg:`add`.
2897 To undo a forget before the next commit, see :hg:`add`.
2894
2898
2895 .. container:: verbose
2899 .. container:: verbose
2896
2900
2897 Examples:
2901 Examples:
2898
2902
2899 - forget newly-added binary files::
2903 - forget newly-added binary files::
2900
2904
2901 hg forget "set:added() and binary()"
2905 hg forget "set:added() and binary()"
2902
2906
2903 - forget files that would be excluded by .hgignore::
2907 - forget files that would be excluded by .hgignore::
2904
2908
2905 hg forget "set:hgignore()"
2909 hg forget "set:hgignore()"
2906
2910
2907 Returns 0 on success.
2911 Returns 0 on success.
2908 """
2912 """
2909
2913
2910 if not pats:
2914 if not pats:
2911 raise util.Abort(_('no files specified'))
2915 raise util.Abort(_('no files specified'))
2912
2916
2913 m = scmutil.match(repo[None], pats, opts)
2917 m = scmutil.match(repo[None], pats, opts)
2914 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2918 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2915 return rejected and 1 or 0
2919 return rejected and 1 or 0
2916
2920
2917 @command(
2921 @command(
2918 'graft',
2922 'graft',
2919 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2923 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2920 ('c', 'continue', False, _('resume interrupted graft')),
2924 ('c', 'continue', False, _('resume interrupted graft')),
2921 ('e', 'edit', False, _('invoke editor on commit messages')),
2925 ('e', 'edit', False, _('invoke editor on commit messages')),
2922 ('', 'log', None, _('append graft info to log message')),
2926 ('', 'log', None, _('append graft info to log message')),
2923 ('D', 'currentdate', False,
2927 ('D', 'currentdate', False,
2924 _('record the current date as commit date')),
2928 _('record the current date as commit date')),
2925 ('U', 'currentuser', False,
2929 ('U', 'currentuser', False,
2926 _('record the current user as committer'), _('DATE'))]
2930 _('record the current user as committer'), _('DATE'))]
2927 + commitopts2 + mergetoolopts + dryrunopts,
2931 + commitopts2 + mergetoolopts + dryrunopts,
2928 _('[OPTION]... [-r] REV...'))
2932 _('[OPTION]... [-r] REV...'))
2929 def graft(ui, repo, *revs, **opts):
2933 def graft(ui, repo, *revs, **opts):
2930 '''copy changes from other branches onto the current branch
2934 '''copy changes from other branches onto the current branch
2931
2935
2932 This command uses Mercurial's merge logic to copy individual
2936 This command uses Mercurial's merge logic to copy individual
2933 changes from other branches without merging branches in the
2937 changes from other branches without merging branches in the
2934 history graph. This is sometimes known as 'backporting' or
2938 history graph. This is sometimes known as 'backporting' or
2935 'cherry-picking'. By default, graft will copy user, date, and
2939 'cherry-picking'. By default, graft will copy user, date, and
2936 description from the source changesets.
2940 description from the source changesets.
2937
2941
2938 Changesets that are ancestors of the current revision, that have
2942 Changesets that are ancestors of the current revision, that have
2939 already been grafted, or that are merges will be skipped.
2943 already been grafted, or that are merges will be skipped.
2940
2944
2941 If --log is specified, log messages will have a comment appended
2945 If --log is specified, log messages will have a comment appended
2942 of the form::
2946 of the form::
2943
2947
2944 (grafted from CHANGESETHASH)
2948 (grafted from CHANGESETHASH)
2945
2949
2946 If a graft merge results in conflicts, the graft process is
2950 If a graft merge results in conflicts, the graft process is
2947 interrupted so that the current merge can be manually resolved.
2951 interrupted so that the current merge can be manually resolved.
2948 Once all conflicts are addressed, the graft process can be
2952 Once all conflicts are addressed, the graft process can be
2949 continued with the -c/--continue option.
2953 continued with the -c/--continue option.
2950
2954
2951 .. note::
2955 .. note::
2952
2956
2953 The -c/--continue option does not reapply earlier options.
2957 The -c/--continue option does not reapply earlier options.
2954
2958
2955 .. container:: verbose
2959 .. container:: verbose
2956
2960
2957 Examples:
2961 Examples:
2958
2962
2959 - copy a single change to the stable branch and edit its description::
2963 - copy a single change to the stable branch and edit its description::
2960
2964
2961 hg update stable
2965 hg update stable
2962 hg graft --edit 9393
2966 hg graft --edit 9393
2963
2967
2964 - graft a range of changesets with one exception, updating dates::
2968 - graft a range of changesets with one exception, updating dates::
2965
2969
2966 hg graft -D "2085::2093 and not 2091"
2970 hg graft -D "2085::2093 and not 2091"
2967
2971
2968 - continue a graft after resolving conflicts::
2972 - continue a graft after resolving conflicts::
2969
2973
2970 hg graft -c
2974 hg graft -c
2971
2975
2972 - show the source of a grafted changeset::
2976 - show the source of a grafted changeset::
2973
2977
2974 hg log --debug -r .
2978 hg log --debug -r .
2975
2979
2976 Returns 0 on successful completion.
2980 Returns 0 on successful completion.
2977 '''
2981 '''
2978
2982
2979 revs = list(revs)
2983 revs = list(revs)
2980 revs.extend(opts['rev'])
2984 revs.extend(opts['rev'])
2981
2985
2982 if not opts.get('user') and opts.get('currentuser'):
2986 if not opts.get('user') and opts.get('currentuser'):
2983 opts['user'] = ui.username()
2987 opts['user'] = ui.username()
2984 if not opts.get('date') and opts.get('currentdate'):
2988 if not opts.get('date') and opts.get('currentdate'):
2985 opts['date'] = "%d %d" % util.makedate()
2989 opts['date'] = "%d %d" % util.makedate()
2986
2990
2987 editor = None
2991 editor = None
2988 if opts.get('edit'):
2992 if opts.get('edit'):
2989 editor = cmdutil.commitforceeditor
2993 editor = cmdutil.commitforceeditor
2990
2994
2991 cont = False
2995 cont = False
2992 if opts['continue']:
2996 if opts['continue']:
2993 cont = True
2997 cont = True
2994 if revs:
2998 if revs:
2995 raise util.Abort(_("can't specify --continue and revisions"))
2999 raise util.Abort(_("can't specify --continue and revisions"))
2996 # read in unfinished revisions
3000 # read in unfinished revisions
2997 try:
3001 try:
2998 nodes = repo.opener.read('graftstate').splitlines()
3002 nodes = repo.opener.read('graftstate').splitlines()
2999 revs = [repo[node].rev() for node in nodes]
3003 revs = [repo[node].rev() for node in nodes]
3000 except IOError, inst:
3004 except IOError, inst:
3001 if inst.errno != errno.ENOENT:
3005 if inst.errno != errno.ENOENT:
3002 raise
3006 raise
3003 raise util.Abort(_("no graft state found, can't continue"))
3007 raise util.Abort(_("no graft state found, can't continue"))
3004 else:
3008 else:
3005 cmdutil.checkunfinished(repo)
3009 cmdutil.checkunfinished(repo)
3006 cmdutil.bailifchanged(repo)
3010 cmdutil.bailifchanged(repo)
3007 if not revs:
3011 if not revs:
3008 raise util.Abort(_('no revisions specified'))
3012 raise util.Abort(_('no revisions specified'))
3009 revs = scmutil.revrange(repo, revs)
3013 revs = scmutil.revrange(repo, revs)
3010
3014
3011 # check for merges
3015 # check for merges
3012 for rev in repo.revs('%ld and merge()', revs):
3016 for rev in repo.revs('%ld and merge()', revs):
3013 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3017 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3014 revs.remove(rev)
3018 revs.remove(rev)
3015 if not revs:
3019 if not revs:
3016 return -1
3020 return -1
3017
3021
3018 # check for ancestors of dest branch
3022 # check for ancestors of dest branch
3019 crev = repo['.'].rev()
3023 crev = repo['.'].rev()
3020 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3024 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3021 # don't mutate while iterating, create a copy
3025 # don't mutate while iterating, create a copy
3022 for rev in list(revs):
3026 for rev in list(revs):
3023 if rev in ancestors:
3027 if rev in ancestors:
3024 ui.warn(_('skipping ancestor revision %s\n') % rev)
3028 ui.warn(_('skipping ancestor revision %s\n') % rev)
3025 revs.remove(rev)
3029 revs.remove(rev)
3026 if not revs:
3030 if not revs:
3027 return -1
3031 return -1
3028
3032
3029 # analyze revs for earlier grafts
3033 # analyze revs for earlier grafts
3030 ids = {}
3034 ids = {}
3031 for ctx in repo.set("%ld", revs):
3035 for ctx in repo.set("%ld", revs):
3032 ids[ctx.hex()] = ctx.rev()
3036 ids[ctx.hex()] = ctx.rev()
3033 n = ctx.extra().get('source')
3037 n = ctx.extra().get('source')
3034 if n:
3038 if n:
3035 ids[n] = ctx.rev()
3039 ids[n] = ctx.rev()
3036
3040
3037 # check ancestors for earlier grafts
3041 # check ancestors for earlier grafts
3038 ui.debug('scanning for duplicate grafts\n')
3042 ui.debug('scanning for duplicate grafts\n')
3039
3043
3040 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3044 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3041 ctx = repo[rev]
3045 ctx = repo[rev]
3042 n = ctx.extra().get('source')
3046 n = ctx.extra().get('source')
3043 if n in ids:
3047 if n in ids:
3044 r = repo[n].rev()
3048 r = repo[n].rev()
3045 if r in revs:
3049 if r in revs:
3046 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3050 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3047 % (r, rev))
3051 % (r, rev))
3048 revs.remove(r)
3052 revs.remove(r)
3049 elif ids[n] in revs:
3053 elif ids[n] in revs:
3050 ui.warn(_('skipping already grafted revision %s '
3054 ui.warn(_('skipping already grafted revision %s '
3051 '(%s also has origin %d)\n') % (ids[n], rev, r))
3055 '(%s also has origin %d)\n') % (ids[n], rev, r))
3052 revs.remove(ids[n])
3056 revs.remove(ids[n])
3053 elif ctx.hex() in ids:
3057 elif ctx.hex() in ids:
3054 r = ids[ctx.hex()]
3058 r = ids[ctx.hex()]
3055 ui.warn(_('skipping already grafted revision %s '
3059 ui.warn(_('skipping already grafted revision %s '
3056 '(was grafted from %d)\n') % (r, rev))
3060 '(was grafted from %d)\n') % (r, rev))
3057 revs.remove(r)
3061 revs.remove(r)
3058 if not revs:
3062 if not revs:
3059 return -1
3063 return -1
3060
3064
3061 wlock = repo.wlock()
3065 wlock = repo.wlock()
3062 try:
3066 try:
3063 current = repo['.']
3067 current = repo['.']
3064 for pos, ctx in enumerate(repo.set("%ld", revs)):
3068 for pos, ctx in enumerate(repo.set("%ld", revs)):
3065
3069
3066 ui.status(_('grafting revision %s\n') % ctx.rev())
3070 ui.status(_('grafting revision %s\n') % ctx.rev())
3067 if opts.get('dry_run'):
3071 if opts.get('dry_run'):
3068 continue
3072 continue
3069
3073
3070 source = ctx.extra().get('source')
3074 source = ctx.extra().get('source')
3071 if not source:
3075 if not source:
3072 source = ctx.hex()
3076 source = ctx.hex()
3073 extra = {'source': source}
3077 extra = {'source': source}
3074 user = ctx.user()
3078 user = ctx.user()
3075 if opts.get('user'):
3079 if opts.get('user'):
3076 user = opts['user']
3080 user = opts['user']
3077 date = ctx.date()
3081 date = ctx.date()
3078 if opts.get('date'):
3082 if opts.get('date'):
3079 date = opts['date']
3083 date = opts['date']
3080 message = ctx.description()
3084 message = ctx.description()
3081 if opts.get('log'):
3085 if opts.get('log'):
3082 message += '\n(grafted from %s)' % ctx.hex()
3086 message += '\n(grafted from %s)' % ctx.hex()
3083
3087
3084 # we don't merge the first commit when continuing
3088 # we don't merge the first commit when continuing
3085 if not cont:
3089 if not cont:
3086 # perform the graft merge with p1(rev) as 'ancestor'
3090 # perform the graft merge with p1(rev) as 'ancestor'
3087 try:
3091 try:
3088 # ui.forcemerge is an internal variable, do not document
3092 # ui.forcemerge is an internal variable, do not document
3089 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3093 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3090 stats = mergemod.update(repo, ctx.node(), True, True, False,
3094 stats = mergemod.update(repo, ctx.node(), True, True, False,
3091 ctx.p1().node())
3095 ctx.p1().node())
3092 finally:
3096 finally:
3093 repo.ui.setconfig('ui', 'forcemerge', '')
3097 repo.ui.setconfig('ui', 'forcemerge', '')
3094 # report any conflicts
3098 # report any conflicts
3095 if stats and stats[3] > 0:
3099 if stats and stats[3] > 0:
3096 # write out state for --continue
3100 # write out state for --continue
3097 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3101 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3098 repo.opener.write('graftstate', ''.join(nodelines))
3102 repo.opener.write('graftstate', ''.join(nodelines))
3099 raise util.Abort(
3103 raise util.Abort(
3100 _("unresolved conflicts, can't continue"),
3104 _("unresolved conflicts, can't continue"),
3101 hint=_('use hg resolve and hg graft --continue'))
3105 hint=_('use hg resolve and hg graft --continue'))
3102 else:
3106 else:
3103 cont = False
3107 cont = False
3104
3108
3105 # drop the second merge parent
3109 # drop the second merge parent
3106 repo.setparents(current.node(), nullid)
3110 repo.setparents(current.node(), nullid)
3107 repo.dirstate.write()
3111 repo.dirstate.write()
3108 # fix up dirstate for copies and renames
3112 # fix up dirstate for copies and renames
3109 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3113 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3110
3114
3111 # commit
3115 # commit
3112 node = repo.commit(text=message, user=user,
3116 node = repo.commit(text=message, user=user,
3113 date=date, extra=extra, editor=editor)
3117 date=date, extra=extra, editor=editor)
3114 if node is None:
3118 if node is None:
3115 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3119 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3116 else:
3120 else:
3117 current = repo[node]
3121 current = repo[node]
3118 finally:
3122 finally:
3119 wlock.release()
3123 wlock.release()
3120
3124
3121 # remove state when we complete successfully
3125 # remove state when we complete successfully
3122 if not opts.get('dry_run'):
3126 if not opts.get('dry_run'):
3123 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3127 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3124
3128
3125 return 0
3129 return 0
3126
3130
3127 @command('grep',
3131 @command('grep',
3128 [('0', 'print0', None, _('end fields with NUL')),
3132 [('0', 'print0', None, _('end fields with NUL')),
3129 ('', 'all', None, _('print all revisions that match')),
3133 ('', 'all', None, _('print all revisions that match')),
3130 ('a', 'text', None, _('treat all files as text')),
3134 ('a', 'text', None, _('treat all files as text')),
3131 ('f', 'follow', None,
3135 ('f', 'follow', None,
3132 _('follow changeset history,'
3136 _('follow changeset history,'
3133 ' or file history across copies and renames')),
3137 ' or file history across copies and renames')),
3134 ('i', 'ignore-case', None, _('ignore case when matching')),
3138 ('i', 'ignore-case', None, _('ignore case when matching')),
3135 ('l', 'files-with-matches', None,
3139 ('l', 'files-with-matches', None,
3136 _('print only filenames and revisions that match')),
3140 _('print only filenames and revisions that match')),
3137 ('n', 'line-number', None, _('print matching line numbers')),
3141 ('n', 'line-number', None, _('print matching line numbers')),
3138 ('r', 'rev', [],
3142 ('r', 'rev', [],
3139 _('only search files changed within revision range'), _('REV')),
3143 _('only search files changed within revision range'), _('REV')),
3140 ('u', 'user', None, _('list the author (long with -v)')),
3144 ('u', 'user', None, _('list the author (long with -v)')),
3141 ('d', 'date', None, _('list the date (short with -q)')),
3145 ('d', 'date', None, _('list the date (short with -q)')),
3142 ] + walkopts,
3146 ] + walkopts,
3143 _('[OPTION]... PATTERN [FILE]...'))
3147 _('[OPTION]... PATTERN [FILE]...'))
3144 def grep(ui, repo, pattern, *pats, **opts):
3148 def grep(ui, repo, pattern, *pats, **opts):
3145 """search for a pattern in specified files and revisions
3149 """search for a pattern in specified files and revisions
3146
3150
3147 Search revisions of files for a regular expression.
3151 Search revisions of files for a regular expression.
3148
3152
3149 This command behaves differently than Unix grep. It only accepts
3153 This command behaves differently than Unix grep. It only accepts
3150 Python/Perl regexps. It searches repository history, not the
3154 Python/Perl regexps. It searches repository history, not the
3151 working directory. It always prints the revision number in which a
3155 working directory. It always prints the revision number in which a
3152 match appears.
3156 match appears.
3153
3157
3154 By default, grep only prints output for the first revision of a
3158 By default, grep only prints output for the first revision of a
3155 file in which it finds a match. To get it to print every revision
3159 file in which it finds a match. To get it to print every revision
3156 that contains a change in match status ("-" for a match that
3160 that contains a change in match status ("-" for a match that
3157 becomes a non-match, or "+" for a non-match that becomes a match),
3161 becomes a non-match, or "+" for a non-match that becomes a match),
3158 use the --all flag.
3162 use the --all flag.
3159
3163
3160 Returns 0 if a match is found, 1 otherwise.
3164 Returns 0 if a match is found, 1 otherwise.
3161 """
3165 """
3162 reflags = re.M
3166 reflags = re.M
3163 if opts.get('ignore_case'):
3167 if opts.get('ignore_case'):
3164 reflags |= re.I
3168 reflags |= re.I
3165 try:
3169 try:
3166 regexp = util.compilere(pattern, reflags)
3170 regexp = util.compilere(pattern, reflags)
3167 except re.error, inst:
3171 except re.error, inst:
3168 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3172 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3169 return 1
3173 return 1
3170 sep, eol = ':', '\n'
3174 sep, eol = ':', '\n'
3171 if opts.get('print0'):
3175 if opts.get('print0'):
3172 sep = eol = '\0'
3176 sep = eol = '\0'
3173
3177
3174 getfile = util.lrucachefunc(repo.file)
3178 getfile = util.lrucachefunc(repo.file)
3175
3179
3176 def matchlines(body):
3180 def matchlines(body):
3177 begin = 0
3181 begin = 0
3178 linenum = 0
3182 linenum = 0
3179 while begin < len(body):
3183 while begin < len(body):
3180 match = regexp.search(body, begin)
3184 match = regexp.search(body, begin)
3181 if not match:
3185 if not match:
3182 break
3186 break
3183 mstart, mend = match.span()
3187 mstart, mend = match.span()
3184 linenum += body.count('\n', begin, mstart) + 1
3188 linenum += body.count('\n', begin, mstart) + 1
3185 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3189 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3186 begin = body.find('\n', mend) + 1 or len(body) + 1
3190 begin = body.find('\n', mend) + 1 or len(body) + 1
3187 lend = begin - 1
3191 lend = begin - 1
3188 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3192 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3189
3193
3190 class linestate(object):
3194 class linestate(object):
3191 def __init__(self, line, linenum, colstart, colend):
3195 def __init__(self, line, linenum, colstart, colend):
3192 self.line = line
3196 self.line = line
3193 self.linenum = linenum
3197 self.linenum = linenum
3194 self.colstart = colstart
3198 self.colstart = colstart
3195 self.colend = colend
3199 self.colend = colend
3196
3200
3197 def __hash__(self):
3201 def __hash__(self):
3198 return hash((self.linenum, self.line))
3202 return hash((self.linenum, self.line))
3199
3203
3200 def __eq__(self, other):
3204 def __eq__(self, other):
3201 return self.line == other.line
3205 return self.line == other.line
3202
3206
3203 matches = {}
3207 matches = {}
3204 copies = {}
3208 copies = {}
3205 def grepbody(fn, rev, body):
3209 def grepbody(fn, rev, body):
3206 matches[rev].setdefault(fn, [])
3210 matches[rev].setdefault(fn, [])
3207 m = matches[rev][fn]
3211 m = matches[rev][fn]
3208 for lnum, cstart, cend, line in matchlines(body):
3212 for lnum, cstart, cend, line in matchlines(body):
3209 s = linestate(line, lnum, cstart, cend)
3213 s = linestate(line, lnum, cstart, cend)
3210 m.append(s)
3214 m.append(s)
3211
3215
3212 def difflinestates(a, b):
3216 def difflinestates(a, b):
3213 sm = difflib.SequenceMatcher(None, a, b)
3217 sm = difflib.SequenceMatcher(None, a, b)
3214 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3218 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3215 if tag == 'insert':
3219 if tag == 'insert':
3216 for i in xrange(blo, bhi):
3220 for i in xrange(blo, bhi):
3217 yield ('+', b[i])
3221 yield ('+', b[i])
3218 elif tag == 'delete':
3222 elif tag == 'delete':
3219 for i in xrange(alo, ahi):
3223 for i in xrange(alo, ahi):
3220 yield ('-', a[i])
3224 yield ('-', a[i])
3221 elif tag == 'replace':
3225 elif tag == 'replace':
3222 for i in xrange(alo, ahi):
3226 for i in xrange(alo, ahi):
3223 yield ('-', a[i])
3227 yield ('-', a[i])
3224 for i in xrange(blo, bhi):
3228 for i in xrange(blo, bhi):
3225 yield ('+', b[i])
3229 yield ('+', b[i])
3226
3230
3227 def display(fn, ctx, pstates, states):
3231 def display(fn, ctx, pstates, states):
3228 rev = ctx.rev()
3232 rev = ctx.rev()
3229 datefunc = ui.quiet and util.shortdate or util.datestr
3233 datefunc = ui.quiet and util.shortdate or util.datestr
3230 found = False
3234 found = False
3231 filerevmatches = {}
3235 filerevmatches = {}
3232 def binary():
3236 def binary():
3233 flog = getfile(fn)
3237 flog = getfile(fn)
3234 return util.binary(flog.read(ctx.filenode(fn)))
3238 return util.binary(flog.read(ctx.filenode(fn)))
3235
3239
3236 if opts.get('all'):
3240 if opts.get('all'):
3237 iter = difflinestates(pstates, states)
3241 iter = difflinestates(pstates, states)
3238 else:
3242 else:
3239 iter = [('', l) for l in states]
3243 iter = [('', l) for l in states]
3240 for change, l in iter:
3244 for change, l in iter:
3241 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3245 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3242 before, match, after = None, None, None
3246 before, match, after = None, None, None
3243
3247
3244 if opts.get('line_number'):
3248 if opts.get('line_number'):
3245 cols.append((str(l.linenum), 'grep.linenumber'))
3249 cols.append((str(l.linenum), 'grep.linenumber'))
3246 if opts.get('all'):
3250 if opts.get('all'):
3247 cols.append((change, 'grep.change'))
3251 cols.append((change, 'grep.change'))
3248 if opts.get('user'):
3252 if opts.get('user'):
3249 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3253 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3250 if opts.get('date'):
3254 if opts.get('date'):
3251 cols.append((datefunc(ctx.date()), 'grep.date'))
3255 cols.append((datefunc(ctx.date()), 'grep.date'))
3252 if opts.get('files_with_matches'):
3256 if opts.get('files_with_matches'):
3253 c = (fn, rev)
3257 c = (fn, rev)
3254 if c in filerevmatches:
3258 if c in filerevmatches:
3255 continue
3259 continue
3256 filerevmatches[c] = 1
3260 filerevmatches[c] = 1
3257 else:
3261 else:
3258 before = l.line[:l.colstart]
3262 before = l.line[:l.colstart]
3259 match = l.line[l.colstart:l.colend]
3263 match = l.line[l.colstart:l.colend]
3260 after = l.line[l.colend:]
3264 after = l.line[l.colend:]
3261 for col, label in cols[:-1]:
3265 for col, label in cols[:-1]:
3262 ui.write(col, label=label)
3266 ui.write(col, label=label)
3263 ui.write(sep, label='grep.sep')
3267 ui.write(sep, label='grep.sep')
3264 ui.write(cols[-1][0], label=cols[-1][1])
3268 ui.write(cols[-1][0], label=cols[-1][1])
3265 if before is not None:
3269 if before is not None:
3266 ui.write(sep, label='grep.sep')
3270 ui.write(sep, label='grep.sep')
3267 if not opts.get('text') and binary():
3271 if not opts.get('text') and binary():
3268 ui.write(" Binary file matches")
3272 ui.write(" Binary file matches")
3269 else:
3273 else:
3270 ui.write(before)
3274 ui.write(before)
3271 ui.write(match, label='grep.match')
3275 ui.write(match, label='grep.match')
3272 ui.write(after)
3276 ui.write(after)
3273 ui.write(eol)
3277 ui.write(eol)
3274 found = True
3278 found = True
3275 return found
3279 return found
3276
3280
3277 skip = {}
3281 skip = {}
3278 revfiles = {}
3282 revfiles = {}
3279 matchfn = scmutil.match(repo[None], pats, opts)
3283 matchfn = scmutil.match(repo[None], pats, opts)
3280 found = False
3284 found = False
3281 follow = opts.get('follow')
3285 follow = opts.get('follow')
3282
3286
3283 def prep(ctx, fns):
3287 def prep(ctx, fns):
3284 rev = ctx.rev()
3288 rev = ctx.rev()
3285 pctx = ctx.p1()
3289 pctx = ctx.p1()
3286 parent = pctx.rev()
3290 parent = pctx.rev()
3287 matches.setdefault(rev, {})
3291 matches.setdefault(rev, {})
3288 matches.setdefault(parent, {})
3292 matches.setdefault(parent, {})
3289 files = revfiles.setdefault(rev, [])
3293 files = revfiles.setdefault(rev, [])
3290 for fn in fns:
3294 for fn in fns:
3291 flog = getfile(fn)
3295 flog = getfile(fn)
3292 try:
3296 try:
3293 fnode = ctx.filenode(fn)
3297 fnode = ctx.filenode(fn)
3294 except error.LookupError:
3298 except error.LookupError:
3295 continue
3299 continue
3296
3300
3297 copied = flog.renamed(fnode)
3301 copied = flog.renamed(fnode)
3298 copy = follow and copied and copied[0]
3302 copy = follow and copied and copied[0]
3299 if copy:
3303 if copy:
3300 copies.setdefault(rev, {})[fn] = copy
3304 copies.setdefault(rev, {})[fn] = copy
3301 if fn in skip:
3305 if fn in skip:
3302 if copy:
3306 if copy:
3303 skip[copy] = True
3307 skip[copy] = True
3304 continue
3308 continue
3305 files.append(fn)
3309 files.append(fn)
3306
3310
3307 if fn not in matches[rev]:
3311 if fn not in matches[rev]:
3308 grepbody(fn, rev, flog.read(fnode))
3312 grepbody(fn, rev, flog.read(fnode))
3309
3313
3310 pfn = copy or fn
3314 pfn = copy or fn
3311 if pfn not in matches[parent]:
3315 if pfn not in matches[parent]:
3312 try:
3316 try:
3313 fnode = pctx.filenode(pfn)
3317 fnode = pctx.filenode(pfn)
3314 grepbody(pfn, parent, flog.read(fnode))
3318 grepbody(pfn, parent, flog.read(fnode))
3315 except error.LookupError:
3319 except error.LookupError:
3316 pass
3320 pass
3317
3321
3318 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3322 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3319 rev = ctx.rev()
3323 rev = ctx.rev()
3320 parent = ctx.p1().rev()
3324 parent = ctx.p1().rev()
3321 for fn in sorted(revfiles.get(rev, [])):
3325 for fn in sorted(revfiles.get(rev, [])):
3322 states = matches[rev][fn]
3326 states = matches[rev][fn]
3323 copy = copies.get(rev, {}).get(fn)
3327 copy = copies.get(rev, {}).get(fn)
3324 if fn in skip:
3328 if fn in skip:
3325 if copy:
3329 if copy:
3326 skip[copy] = True
3330 skip[copy] = True
3327 continue
3331 continue
3328 pstates = matches.get(parent, {}).get(copy or fn, [])
3332 pstates = matches.get(parent, {}).get(copy or fn, [])
3329 if pstates or states:
3333 if pstates or states:
3330 r = display(fn, ctx, pstates, states)
3334 r = display(fn, ctx, pstates, states)
3331 found = found or r
3335 found = found or r
3332 if r and not opts.get('all'):
3336 if r and not opts.get('all'):
3333 skip[fn] = True
3337 skip[fn] = True
3334 if copy:
3338 if copy:
3335 skip[copy] = True
3339 skip[copy] = True
3336 del matches[rev]
3340 del matches[rev]
3337 del revfiles[rev]
3341 del revfiles[rev]
3338
3342
3339 return not found
3343 return not found
3340
3344
3341 @command('heads',
3345 @command('heads',
3342 [('r', 'rev', '',
3346 [('r', 'rev', '',
3343 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3347 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3344 ('t', 'topo', False, _('show topological heads only')),
3348 ('t', 'topo', False, _('show topological heads only')),
3345 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3349 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3346 ('c', 'closed', False, _('show normal and closed branch heads')),
3350 ('c', 'closed', False, _('show normal and closed branch heads')),
3347 ] + templateopts,
3351 ] + templateopts,
3348 _('[-ct] [-r STARTREV] [REV]...'))
3352 _('[-ct] [-r STARTREV] [REV]...'))
3349 def heads(ui, repo, *branchrevs, **opts):
3353 def heads(ui, repo, *branchrevs, **opts):
3350 """show branch heads
3354 """show branch heads
3351
3355
3352 With no arguments, show all open branch heads in the repository.
3356 With no arguments, show all open branch heads in the repository.
3353 Branch heads are changesets that have no descendants on the
3357 Branch heads are changesets that have no descendants on the
3354 same branch. They are where development generally takes place and
3358 same branch. They are where development generally takes place and
3355 are the usual targets for update and merge operations.
3359 are the usual targets for update and merge operations.
3356
3360
3357 If one or more REVs are given, only open branch heads on the
3361 If one or more REVs are given, only open branch heads on the
3358 branches associated with the specified changesets are shown. This
3362 branches associated with the specified changesets are shown. This
3359 means that you can use :hg:`heads .` to see the heads on the
3363 means that you can use :hg:`heads .` to see the heads on the
3360 currently checked-out branch.
3364 currently checked-out branch.
3361
3365
3362 If -c/--closed is specified, also show branch heads marked closed
3366 If -c/--closed is specified, also show branch heads marked closed
3363 (see :hg:`commit --close-branch`).
3367 (see :hg:`commit --close-branch`).
3364
3368
3365 If STARTREV is specified, only those heads that are descendants of
3369 If STARTREV is specified, only those heads that are descendants of
3366 STARTREV will be displayed.
3370 STARTREV will be displayed.
3367
3371
3368 If -t/--topo is specified, named branch mechanics will be ignored and only
3372 If -t/--topo is specified, named branch mechanics will be ignored and only
3369 topological heads (changesets with no children) will be shown.
3373 topological heads (changesets with no children) will be shown.
3370
3374
3371 Returns 0 if matching heads are found, 1 if not.
3375 Returns 0 if matching heads are found, 1 if not.
3372 """
3376 """
3373
3377
3374 start = None
3378 start = None
3375 if 'rev' in opts:
3379 if 'rev' in opts:
3376 start = scmutil.revsingle(repo, opts['rev'], None).node()
3380 start = scmutil.revsingle(repo, opts['rev'], None).node()
3377
3381
3378 if opts.get('topo'):
3382 if opts.get('topo'):
3379 heads = [repo[h] for h in repo.heads(start)]
3383 heads = [repo[h] for h in repo.heads(start)]
3380 else:
3384 else:
3381 heads = []
3385 heads = []
3382 for branch in repo.branchmap():
3386 for branch in repo.branchmap():
3383 heads += repo.branchheads(branch, start, opts.get('closed'))
3387 heads += repo.branchheads(branch, start, opts.get('closed'))
3384 heads = [repo[h] for h in heads]
3388 heads = [repo[h] for h in heads]
3385
3389
3386 if branchrevs:
3390 if branchrevs:
3387 branches = set(repo[br].branch() for br in branchrevs)
3391 branches = set(repo[br].branch() for br in branchrevs)
3388 heads = [h for h in heads if h.branch() in branches]
3392 heads = [h for h in heads if h.branch() in branches]
3389
3393
3390 if opts.get('active') and branchrevs:
3394 if opts.get('active') and branchrevs:
3391 dagheads = repo.heads(start)
3395 dagheads = repo.heads(start)
3392 heads = [h for h in heads if h.node() in dagheads]
3396 heads = [h for h in heads if h.node() in dagheads]
3393
3397
3394 if branchrevs:
3398 if branchrevs:
3395 haveheads = set(h.branch() for h in heads)
3399 haveheads = set(h.branch() for h in heads)
3396 if branches - haveheads:
3400 if branches - haveheads:
3397 headless = ', '.join(b for b in branches - haveheads)
3401 headless = ', '.join(b for b in branches - haveheads)
3398 msg = _('no open branch heads found on branches %s')
3402 msg = _('no open branch heads found on branches %s')
3399 if opts.get('rev'):
3403 if opts.get('rev'):
3400 msg += _(' (started at %s)') % opts['rev']
3404 msg += _(' (started at %s)') % opts['rev']
3401 ui.warn((msg + '\n') % headless)
3405 ui.warn((msg + '\n') % headless)
3402
3406
3403 if not heads:
3407 if not heads:
3404 return 1
3408 return 1
3405
3409
3406 heads = sorted(heads, key=lambda x: -x.rev())
3410 heads = sorted(heads, key=lambda x: -x.rev())
3407 displayer = cmdutil.show_changeset(ui, repo, opts)
3411 displayer = cmdutil.show_changeset(ui, repo, opts)
3408 for ctx in heads:
3412 for ctx in heads:
3409 displayer.show(ctx)
3413 displayer.show(ctx)
3410 displayer.close()
3414 displayer.close()
3411
3415
3412 @command('help',
3416 @command('help',
3413 [('e', 'extension', None, _('show only help for extensions')),
3417 [('e', 'extension', None, _('show only help for extensions')),
3414 ('c', 'command', None, _('show only help for commands')),
3418 ('c', 'command', None, _('show only help for commands')),
3415 ('k', 'keyword', '', _('show topics matching keyword')),
3419 ('k', 'keyword', '', _('show topics matching keyword')),
3416 ],
3420 ],
3417 _('[-ec] [TOPIC]'))
3421 _('[-ec] [TOPIC]'))
3418 def help_(ui, name=None, **opts):
3422 def help_(ui, name=None, **opts):
3419 """show help for a given topic or a help overview
3423 """show help for a given topic or a help overview
3420
3424
3421 With no arguments, print a list of commands with short help messages.
3425 With no arguments, print a list of commands with short help messages.
3422
3426
3423 Given a topic, extension, or command name, print help for that
3427 Given a topic, extension, or command name, print help for that
3424 topic.
3428 topic.
3425
3429
3426 Returns 0 if successful.
3430 Returns 0 if successful.
3427 """
3431 """
3428
3432
3429 textwidth = min(ui.termwidth(), 80) - 2
3433 textwidth = min(ui.termwidth(), 80) - 2
3430
3434
3431 keep = ui.verbose and ['verbose'] or []
3435 keep = ui.verbose and ['verbose'] or []
3432 text = help.help_(ui, name, **opts)
3436 text = help.help_(ui, name, **opts)
3433
3437
3434 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3438 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3435 if 'verbose' in pruned:
3439 if 'verbose' in pruned:
3436 keep.append('omitted')
3440 keep.append('omitted')
3437 else:
3441 else:
3438 keep.append('notomitted')
3442 keep.append('notomitted')
3439 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3443 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3440 ui.write(formatted)
3444 ui.write(formatted)
3441
3445
3442
3446
3443 @command('identify|id',
3447 @command('identify|id',
3444 [('r', 'rev', '',
3448 [('r', 'rev', '',
3445 _('identify the specified revision'), _('REV')),
3449 _('identify the specified revision'), _('REV')),
3446 ('n', 'num', None, _('show local revision number')),
3450 ('n', 'num', None, _('show local revision number')),
3447 ('i', 'id', None, _('show global revision id')),
3451 ('i', 'id', None, _('show global revision id')),
3448 ('b', 'branch', None, _('show branch')),
3452 ('b', 'branch', None, _('show branch')),
3449 ('t', 'tags', None, _('show tags')),
3453 ('t', 'tags', None, _('show tags')),
3450 ('B', 'bookmarks', None, _('show bookmarks')),
3454 ('B', 'bookmarks', None, _('show bookmarks')),
3451 ] + remoteopts,
3455 ] + remoteopts,
3452 _('[-nibtB] [-r REV] [SOURCE]'))
3456 _('[-nibtB] [-r REV] [SOURCE]'))
3453 def identify(ui, repo, source=None, rev=None,
3457 def identify(ui, repo, source=None, rev=None,
3454 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3458 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3455 """identify the working copy or specified revision
3459 """identify the working copy or specified revision
3456
3460
3457 Print a summary identifying the repository state at REV using one or
3461 Print a summary identifying the repository state at REV using one or
3458 two parent hash identifiers, followed by a "+" if the working
3462 two parent hash identifiers, followed by a "+" if the working
3459 directory has uncommitted changes, the branch name (if not default),
3463 directory has uncommitted changes, the branch name (if not default),
3460 a list of tags, and a list of bookmarks.
3464 a list of tags, and a list of bookmarks.
3461
3465
3462 When REV is not given, print a summary of the current state of the
3466 When REV is not given, print a summary of the current state of the
3463 repository.
3467 repository.
3464
3468
3465 Specifying a path to a repository root or Mercurial bundle will
3469 Specifying a path to a repository root or Mercurial bundle will
3466 cause lookup to operate on that repository/bundle.
3470 cause lookup to operate on that repository/bundle.
3467
3471
3468 .. container:: verbose
3472 .. container:: verbose
3469
3473
3470 Examples:
3474 Examples:
3471
3475
3472 - generate a build identifier for the working directory::
3476 - generate a build identifier for the working directory::
3473
3477
3474 hg id --id > build-id.dat
3478 hg id --id > build-id.dat
3475
3479
3476 - find the revision corresponding to a tag::
3480 - find the revision corresponding to a tag::
3477
3481
3478 hg id -n -r 1.3
3482 hg id -n -r 1.3
3479
3483
3480 - check the most recent revision of a remote repository::
3484 - check the most recent revision of a remote repository::
3481
3485
3482 hg id -r tip http://selenic.com/hg/
3486 hg id -r tip http://selenic.com/hg/
3483
3487
3484 Returns 0 if successful.
3488 Returns 0 if successful.
3485 """
3489 """
3486
3490
3487 if not repo and not source:
3491 if not repo and not source:
3488 raise util.Abort(_("there is no Mercurial repository here "
3492 raise util.Abort(_("there is no Mercurial repository here "
3489 "(.hg not found)"))
3493 "(.hg not found)"))
3490
3494
3491 hexfunc = ui.debugflag and hex or short
3495 hexfunc = ui.debugflag and hex or short
3492 default = not (num or id or branch or tags or bookmarks)
3496 default = not (num or id or branch or tags or bookmarks)
3493 output = []
3497 output = []
3494 revs = []
3498 revs = []
3495
3499
3496 if source:
3500 if source:
3497 source, branches = hg.parseurl(ui.expandpath(source))
3501 source, branches = hg.parseurl(ui.expandpath(source))
3498 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3502 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3499 repo = peer.local()
3503 repo = peer.local()
3500 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3504 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3501
3505
3502 if not repo:
3506 if not repo:
3503 if num or branch or tags:
3507 if num or branch or tags:
3504 raise util.Abort(
3508 raise util.Abort(
3505 _("can't query remote revision number, branch, or tags"))
3509 _("can't query remote revision number, branch, or tags"))
3506 if not rev and revs:
3510 if not rev and revs:
3507 rev = revs[0]
3511 rev = revs[0]
3508 if not rev:
3512 if not rev:
3509 rev = "tip"
3513 rev = "tip"
3510
3514
3511 remoterev = peer.lookup(rev)
3515 remoterev = peer.lookup(rev)
3512 if default or id:
3516 if default or id:
3513 output = [hexfunc(remoterev)]
3517 output = [hexfunc(remoterev)]
3514
3518
3515 def getbms():
3519 def getbms():
3516 bms = []
3520 bms = []
3517
3521
3518 if 'bookmarks' in peer.listkeys('namespaces'):
3522 if 'bookmarks' in peer.listkeys('namespaces'):
3519 hexremoterev = hex(remoterev)
3523 hexremoterev = hex(remoterev)
3520 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3524 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3521 if bmr == hexremoterev]
3525 if bmr == hexremoterev]
3522
3526
3523 return sorted(bms)
3527 return sorted(bms)
3524
3528
3525 if bookmarks:
3529 if bookmarks:
3526 output.extend(getbms())
3530 output.extend(getbms())
3527 elif default and not ui.quiet:
3531 elif default and not ui.quiet:
3528 # multiple bookmarks for a single parent separated by '/'
3532 # multiple bookmarks for a single parent separated by '/'
3529 bm = '/'.join(getbms())
3533 bm = '/'.join(getbms())
3530 if bm:
3534 if bm:
3531 output.append(bm)
3535 output.append(bm)
3532 else:
3536 else:
3533 if not rev:
3537 if not rev:
3534 ctx = repo[None]
3538 ctx = repo[None]
3535 parents = ctx.parents()
3539 parents = ctx.parents()
3536 changed = ""
3540 changed = ""
3537 if default or id or num:
3541 if default or id or num:
3538 if (util.any(repo.status())
3542 if (util.any(repo.status())
3539 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3543 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3540 changed = '+'
3544 changed = '+'
3541 if default or id:
3545 if default or id:
3542 output = ["%s%s" %
3546 output = ["%s%s" %
3543 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3547 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3544 if num:
3548 if num:
3545 output.append("%s%s" %
3549 output.append("%s%s" %
3546 ('+'.join([str(p.rev()) for p in parents]), changed))
3550 ('+'.join([str(p.rev()) for p in parents]), changed))
3547 else:
3551 else:
3548 ctx = scmutil.revsingle(repo, rev)
3552 ctx = scmutil.revsingle(repo, rev)
3549 if default or id:
3553 if default or id:
3550 output = [hexfunc(ctx.node())]
3554 output = [hexfunc(ctx.node())]
3551 if num:
3555 if num:
3552 output.append(str(ctx.rev()))
3556 output.append(str(ctx.rev()))
3553
3557
3554 if default and not ui.quiet:
3558 if default and not ui.quiet:
3555 b = ctx.branch()
3559 b = ctx.branch()
3556 if b != 'default':
3560 if b != 'default':
3557 output.append("(%s)" % b)
3561 output.append("(%s)" % b)
3558
3562
3559 # multiple tags for a single parent separated by '/'
3563 # multiple tags for a single parent separated by '/'
3560 t = '/'.join(ctx.tags())
3564 t = '/'.join(ctx.tags())
3561 if t:
3565 if t:
3562 output.append(t)
3566 output.append(t)
3563
3567
3564 # multiple bookmarks for a single parent separated by '/'
3568 # multiple bookmarks for a single parent separated by '/'
3565 bm = '/'.join(ctx.bookmarks())
3569 bm = '/'.join(ctx.bookmarks())
3566 if bm:
3570 if bm:
3567 output.append(bm)
3571 output.append(bm)
3568 else:
3572 else:
3569 if branch:
3573 if branch:
3570 output.append(ctx.branch())
3574 output.append(ctx.branch())
3571
3575
3572 if tags:
3576 if tags:
3573 output.extend(ctx.tags())
3577 output.extend(ctx.tags())
3574
3578
3575 if bookmarks:
3579 if bookmarks:
3576 output.extend(ctx.bookmarks())
3580 output.extend(ctx.bookmarks())
3577
3581
3578 ui.write("%s\n" % ' '.join(output))
3582 ui.write("%s\n" % ' '.join(output))
3579
3583
3580 @command('import|patch',
3584 @command('import|patch',
3581 [('p', 'strip', 1,
3585 [('p', 'strip', 1,
3582 _('directory strip option for patch. This has the same '
3586 _('directory strip option for patch. This has the same '
3583 'meaning as the corresponding patch option'), _('NUM')),
3587 'meaning as the corresponding patch option'), _('NUM')),
3584 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3588 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3585 ('e', 'edit', False, _('invoke editor on commit messages')),
3589 ('e', 'edit', False, _('invoke editor on commit messages')),
3586 ('f', 'force', None,
3590 ('f', 'force', None,
3587 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3591 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3588 ('', 'no-commit', None,
3592 ('', 'no-commit', None,
3589 _("don't commit, just update the working directory")),
3593 _("don't commit, just update the working directory")),
3590 ('', 'bypass', None,
3594 ('', 'bypass', None,
3591 _("apply patch without touching the working directory")),
3595 _("apply patch without touching the working directory")),
3592 ('', 'exact', None,
3596 ('', 'exact', None,
3593 _('apply patch to the nodes from which it was generated')),
3597 _('apply patch to the nodes from which it was generated')),
3594 ('', 'import-branch', None,
3598 ('', 'import-branch', None,
3595 _('use any branch information in patch (implied by --exact)'))] +
3599 _('use any branch information in patch (implied by --exact)'))] +
3596 commitopts + commitopts2 + similarityopts,
3600 commitopts + commitopts2 + similarityopts,
3597 _('[OPTION]... PATCH...'))
3601 _('[OPTION]... PATCH...'))
3598 def import_(ui, repo, patch1=None, *patches, **opts):
3602 def import_(ui, repo, patch1=None, *patches, **opts):
3599 """import an ordered set of patches
3603 """import an ordered set of patches
3600
3604
3601 Import a list of patches and commit them individually (unless
3605 Import a list of patches and commit them individually (unless
3602 --no-commit is specified).
3606 --no-commit is specified).
3603
3607
3604 Because import first applies changes to the working directory,
3608 Because import first applies changes to the working directory,
3605 import will abort if there are outstanding changes.
3609 import will abort if there are outstanding changes.
3606
3610
3607 You can import a patch straight from a mail message. Even patches
3611 You can import a patch straight from a mail message. Even patches
3608 as attachments work (to use the body part, it must have type
3612 as attachments work (to use the body part, it must have type
3609 text/plain or text/x-patch). From and Subject headers of email
3613 text/plain or text/x-patch). From and Subject headers of email
3610 message are used as default committer and commit message. All
3614 message are used as default committer and commit message. All
3611 text/plain body parts before first diff are added to commit
3615 text/plain body parts before first diff are added to commit
3612 message.
3616 message.
3613
3617
3614 If the imported patch was generated by :hg:`export`, user and
3618 If the imported patch was generated by :hg:`export`, user and
3615 description from patch override values from message headers and
3619 description from patch override values from message headers and
3616 body. Values given on command line with -m/--message and -u/--user
3620 body. Values given on command line with -m/--message and -u/--user
3617 override these.
3621 override these.
3618
3622
3619 If --exact is specified, import will set the working directory to
3623 If --exact is specified, import will set the working directory to
3620 the parent of each patch before applying it, and will abort if the
3624 the parent of each patch before applying it, and will abort if the
3621 resulting changeset has a different ID than the one recorded in
3625 resulting changeset has a different ID than the one recorded in
3622 the patch. This may happen due to character set problems or other
3626 the patch. This may happen due to character set problems or other
3623 deficiencies in the text patch format.
3627 deficiencies in the text patch format.
3624
3628
3625 Use --bypass to apply and commit patches directly to the
3629 Use --bypass to apply and commit patches directly to the
3626 repository, not touching the working directory. Without --exact,
3630 repository, not touching the working directory. Without --exact,
3627 patches will be applied on top of the working directory parent
3631 patches will be applied on top of the working directory parent
3628 revision.
3632 revision.
3629
3633
3630 With -s/--similarity, hg will attempt to discover renames and
3634 With -s/--similarity, hg will attempt to discover renames and
3631 copies in the patch in the same way as :hg:`addremove`.
3635 copies in the patch in the same way as :hg:`addremove`.
3632
3636
3633 To read a patch from standard input, use "-" as the patch name. If
3637 To read a patch from standard input, use "-" as the patch name. If
3634 a URL is specified, the patch will be downloaded from it.
3638 a URL is specified, the patch will be downloaded from it.
3635 See :hg:`help dates` for a list of formats valid for -d/--date.
3639 See :hg:`help dates` for a list of formats valid for -d/--date.
3636
3640
3637 .. container:: verbose
3641 .. container:: verbose
3638
3642
3639 Examples:
3643 Examples:
3640
3644
3641 - import a traditional patch from a website and detect renames::
3645 - import a traditional patch from a website and detect renames::
3642
3646
3643 hg import -s 80 http://example.com/bugfix.patch
3647 hg import -s 80 http://example.com/bugfix.patch
3644
3648
3645 - import a changeset from an hgweb server::
3649 - import a changeset from an hgweb server::
3646
3650
3647 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3651 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3648
3652
3649 - import all the patches in an Unix-style mbox::
3653 - import all the patches in an Unix-style mbox::
3650
3654
3651 hg import incoming-patches.mbox
3655 hg import incoming-patches.mbox
3652
3656
3653 - attempt to exactly restore an exported changeset (not always
3657 - attempt to exactly restore an exported changeset (not always
3654 possible)::
3658 possible)::
3655
3659
3656 hg import --exact proposed-fix.patch
3660 hg import --exact proposed-fix.patch
3657
3661
3658 Returns 0 on success.
3662 Returns 0 on success.
3659 """
3663 """
3660
3664
3661 if not patch1:
3665 if not patch1:
3662 raise util.Abort(_('need at least one patch to import'))
3666 raise util.Abort(_('need at least one patch to import'))
3663
3667
3664 patches = (patch1,) + patches
3668 patches = (patch1,) + patches
3665
3669
3666 date = opts.get('date')
3670 date = opts.get('date')
3667 if date:
3671 if date:
3668 opts['date'] = util.parsedate(date)
3672 opts['date'] = util.parsedate(date)
3669
3673
3670 editor = cmdutil.commiteditor
3674 editor = cmdutil.commiteditor
3671 if opts.get('edit'):
3675 if opts.get('edit'):
3672 editor = cmdutil.commitforceeditor
3676 editor = cmdutil.commitforceeditor
3673
3677
3674 update = not opts.get('bypass')
3678 update = not opts.get('bypass')
3675 if not update and opts.get('no_commit'):
3679 if not update and opts.get('no_commit'):
3676 raise util.Abort(_('cannot use --no-commit with --bypass'))
3680 raise util.Abort(_('cannot use --no-commit with --bypass'))
3677 try:
3681 try:
3678 sim = float(opts.get('similarity') or 0)
3682 sim = float(opts.get('similarity') or 0)
3679 except ValueError:
3683 except ValueError:
3680 raise util.Abort(_('similarity must be a number'))
3684 raise util.Abort(_('similarity must be a number'))
3681 if sim < 0 or sim > 100:
3685 if sim < 0 or sim > 100:
3682 raise util.Abort(_('similarity must be between 0 and 100'))
3686 raise util.Abort(_('similarity must be between 0 and 100'))
3683 if sim and not update:
3687 if sim and not update:
3684 raise util.Abort(_('cannot use --similarity with --bypass'))
3688 raise util.Abort(_('cannot use --similarity with --bypass'))
3685
3689
3686 if update:
3690 if update:
3687 cmdutil.checkunfinished(repo)
3691 cmdutil.checkunfinished(repo)
3688 if (opts.get('exact') or not opts.get('force')) and update:
3692 if (opts.get('exact') or not opts.get('force')) and update:
3689 cmdutil.bailifchanged(repo)
3693 cmdutil.bailifchanged(repo)
3690
3694
3691 base = opts["base"]
3695 base = opts["base"]
3692 strip = opts["strip"]
3696 strip = opts["strip"]
3693 wlock = lock = tr = None
3697 wlock = lock = tr = None
3694 msgs = []
3698 msgs = []
3695
3699
3696 def tryone(ui, hunk, parents):
3700 def tryone(ui, hunk, parents):
3697 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3701 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3698 patch.extract(ui, hunk)
3702 patch.extract(ui, hunk)
3699
3703
3700 if not tmpname:
3704 if not tmpname:
3701 return (None, None)
3705 return (None, None)
3702 msg = _('applied to working directory')
3706 msg = _('applied to working directory')
3703
3707
3704 try:
3708 try:
3705 cmdline_message = cmdutil.logmessage(ui, opts)
3709 cmdline_message = cmdutil.logmessage(ui, opts)
3706 if cmdline_message:
3710 if cmdline_message:
3707 # pickup the cmdline msg
3711 # pickup the cmdline msg
3708 message = cmdline_message
3712 message = cmdline_message
3709 elif message:
3713 elif message:
3710 # pickup the patch msg
3714 # pickup the patch msg
3711 message = message.strip()
3715 message = message.strip()
3712 else:
3716 else:
3713 # launch the editor
3717 # launch the editor
3714 message = None
3718 message = None
3715 ui.debug('message:\n%s\n' % message)
3719 ui.debug('message:\n%s\n' % message)
3716
3720
3717 if len(parents) == 1:
3721 if len(parents) == 1:
3718 parents.append(repo[nullid])
3722 parents.append(repo[nullid])
3719 if opts.get('exact'):
3723 if opts.get('exact'):
3720 if not nodeid or not p1:
3724 if not nodeid or not p1:
3721 raise util.Abort(_('not a Mercurial patch'))
3725 raise util.Abort(_('not a Mercurial patch'))
3722 p1 = repo[p1]
3726 p1 = repo[p1]
3723 p2 = repo[p2 or nullid]
3727 p2 = repo[p2 or nullid]
3724 elif p2:
3728 elif p2:
3725 try:
3729 try:
3726 p1 = repo[p1]
3730 p1 = repo[p1]
3727 p2 = repo[p2]
3731 p2 = repo[p2]
3728 # Without any options, consider p2 only if the
3732 # Without any options, consider p2 only if the
3729 # patch is being applied on top of the recorded
3733 # patch is being applied on top of the recorded
3730 # first parent.
3734 # first parent.
3731 if p1 != parents[0]:
3735 if p1 != parents[0]:
3732 p1 = parents[0]
3736 p1 = parents[0]
3733 p2 = repo[nullid]
3737 p2 = repo[nullid]
3734 except error.RepoError:
3738 except error.RepoError:
3735 p1, p2 = parents
3739 p1, p2 = parents
3736 else:
3740 else:
3737 p1, p2 = parents
3741 p1, p2 = parents
3738
3742
3739 n = None
3743 n = None
3740 if update:
3744 if update:
3741 if p1 != parents[0]:
3745 if p1 != parents[0]:
3742 hg.clean(repo, p1.node())
3746 hg.clean(repo, p1.node())
3743 if p2 != parents[1]:
3747 if p2 != parents[1]:
3744 repo.setparents(p1.node(), p2.node())
3748 repo.setparents(p1.node(), p2.node())
3745
3749
3746 if opts.get('exact') or opts.get('import_branch'):
3750 if opts.get('exact') or opts.get('import_branch'):
3747 repo.dirstate.setbranch(branch or 'default')
3751 repo.dirstate.setbranch(branch or 'default')
3748
3752
3749 files = set()
3753 files = set()
3750 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3754 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3751 eolmode=None, similarity=sim / 100.0)
3755 eolmode=None, similarity=sim / 100.0)
3752 files = list(files)
3756 files = list(files)
3753 if opts.get('no_commit'):
3757 if opts.get('no_commit'):
3754 if message:
3758 if message:
3755 msgs.append(message)
3759 msgs.append(message)
3756 else:
3760 else:
3757 if opts.get('exact') or p2:
3761 if opts.get('exact') or p2:
3758 # If you got here, you either use --force and know what
3762 # If you got here, you either use --force and know what
3759 # you are doing or used --exact or a merge patch while
3763 # you are doing or used --exact or a merge patch while
3760 # being updated to its first parent.
3764 # being updated to its first parent.
3761 m = None
3765 m = None
3762 else:
3766 else:
3763 m = scmutil.matchfiles(repo, files or [])
3767 m = scmutil.matchfiles(repo, files or [])
3764 n = repo.commit(message, opts.get('user') or user,
3768 n = repo.commit(message, opts.get('user') or user,
3765 opts.get('date') or date, match=m,
3769 opts.get('date') or date, match=m,
3766 editor=editor)
3770 editor=editor)
3767 else:
3771 else:
3768 if opts.get('exact') or opts.get('import_branch'):
3772 if opts.get('exact') or opts.get('import_branch'):
3769 branch = branch or 'default'
3773 branch = branch or 'default'
3770 else:
3774 else:
3771 branch = p1.branch()
3775 branch = p1.branch()
3772 store = patch.filestore()
3776 store = patch.filestore()
3773 try:
3777 try:
3774 files = set()
3778 files = set()
3775 try:
3779 try:
3776 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3780 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3777 files, eolmode=None)
3781 files, eolmode=None)
3778 except patch.PatchError, e:
3782 except patch.PatchError, e:
3779 raise util.Abort(str(e))
3783 raise util.Abort(str(e))
3780 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3784 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3781 message,
3785 message,
3782 opts.get('user') or user,
3786 opts.get('user') or user,
3783 opts.get('date') or date,
3787 opts.get('date') or date,
3784 branch, files, store,
3788 branch, files, store,
3785 editor=cmdutil.commiteditor)
3789 editor=cmdutil.commiteditor)
3786 repo.savecommitmessage(memctx.description())
3790 repo.savecommitmessage(memctx.description())
3787 n = memctx.commit()
3791 n = memctx.commit()
3788 finally:
3792 finally:
3789 store.close()
3793 store.close()
3790 if opts.get('exact') and hex(n) != nodeid:
3794 if opts.get('exact') and hex(n) != nodeid:
3791 raise util.Abort(_('patch is damaged or loses information'))
3795 raise util.Abort(_('patch is damaged or loses information'))
3792 if n:
3796 if n:
3793 # i18n: refers to a short changeset id
3797 # i18n: refers to a short changeset id
3794 msg = _('created %s') % short(n)
3798 msg = _('created %s') % short(n)
3795 return (msg, n)
3799 return (msg, n)
3796 finally:
3800 finally:
3797 os.unlink(tmpname)
3801 os.unlink(tmpname)
3798
3802
3799 try:
3803 try:
3800 try:
3804 try:
3801 wlock = repo.wlock()
3805 wlock = repo.wlock()
3802 if not opts.get('no_commit'):
3806 if not opts.get('no_commit'):
3803 lock = repo.lock()
3807 lock = repo.lock()
3804 tr = repo.transaction('import')
3808 tr = repo.transaction('import')
3805 parents = repo.parents()
3809 parents = repo.parents()
3806 for patchurl in patches:
3810 for patchurl in patches:
3807 if patchurl == '-':
3811 if patchurl == '-':
3808 ui.status(_('applying patch from stdin\n'))
3812 ui.status(_('applying patch from stdin\n'))
3809 patchfile = ui.fin
3813 patchfile = ui.fin
3810 patchurl = 'stdin' # for error message
3814 patchurl = 'stdin' # for error message
3811 else:
3815 else:
3812 patchurl = os.path.join(base, patchurl)
3816 patchurl = os.path.join(base, patchurl)
3813 ui.status(_('applying %s\n') % patchurl)
3817 ui.status(_('applying %s\n') % patchurl)
3814 patchfile = hg.openpath(ui, patchurl)
3818 patchfile = hg.openpath(ui, patchurl)
3815
3819
3816 haspatch = False
3820 haspatch = False
3817 for hunk in patch.split(patchfile):
3821 for hunk in patch.split(patchfile):
3818 (msg, node) = tryone(ui, hunk, parents)
3822 (msg, node) = tryone(ui, hunk, parents)
3819 if msg:
3823 if msg:
3820 haspatch = True
3824 haspatch = True
3821 ui.note(msg + '\n')
3825 ui.note(msg + '\n')
3822 if update or opts.get('exact'):
3826 if update or opts.get('exact'):
3823 parents = repo.parents()
3827 parents = repo.parents()
3824 else:
3828 else:
3825 parents = [repo[node]]
3829 parents = [repo[node]]
3826
3830
3827 if not haspatch:
3831 if not haspatch:
3828 raise util.Abort(_('%s: no diffs found') % patchurl)
3832 raise util.Abort(_('%s: no diffs found') % patchurl)
3829
3833
3830 if tr:
3834 if tr:
3831 tr.close()
3835 tr.close()
3832 if msgs:
3836 if msgs:
3833 repo.savecommitmessage('\n* * *\n'.join(msgs))
3837 repo.savecommitmessage('\n* * *\n'.join(msgs))
3834 except: # re-raises
3838 except: # re-raises
3835 # wlock.release() indirectly calls dirstate.write(): since
3839 # wlock.release() indirectly calls dirstate.write(): since
3836 # we're crashing, we do not want to change the working dir
3840 # we're crashing, we do not want to change the working dir
3837 # parent after all, so make sure it writes nothing
3841 # parent after all, so make sure it writes nothing
3838 repo.dirstate.invalidate()
3842 repo.dirstate.invalidate()
3839 raise
3843 raise
3840 finally:
3844 finally:
3841 if tr:
3845 if tr:
3842 tr.release()
3846 tr.release()
3843 release(lock, wlock)
3847 release(lock, wlock)
3844
3848
3845 @command('incoming|in',
3849 @command('incoming|in',
3846 [('f', 'force', None,
3850 [('f', 'force', None,
3847 _('run even if remote repository is unrelated')),
3851 _('run even if remote repository is unrelated')),
3848 ('n', 'newest-first', None, _('show newest record first')),
3852 ('n', 'newest-first', None, _('show newest record first')),
3849 ('', 'bundle', '',
3853 ('', 'bundle', '',
3850 _('file to store the bundles into'), _('FILE')),
3854 _('file to store the bundles into'), _('FILE')),
3851 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3855 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3852 ('B', 'bookmarks', False, _("compare bookmarks")),
3856 ('B', 'bookmarks', False, _("compare bookmarks")),
3853 ('b', 'branch', [],
3857 ('b', 'branch', [],
3854 _('a specific branch you would like to pull'), _('BRANCH')),
3858 _('a specific branch you would like to pull'), _('BRANCH')),
3855 ] + logopts + remoteopts + subrepoopts,
3859 ] + logopts + remoteopts + subrepoopts,
3856 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3860 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3857 def incoming(ui, repo, source="default", **opts):
3861 def incoming(ui, repo, source="default", **opts):
3858 """show new changesets found in source
3862 """show new changesets found in source
3859
3863
3860 Show new changesets found in the specified path/URL or the default
3864 Show new changesets found in the specified path/URL or the default
3861 pull location. These are the changesets that would have been pulled
3865 pull location. These are the changesets that would have been pulled
3862 if a pull at the time you issued this command.
3866 if a pull at the time you issued this command.
3863
3867
3864 For remote repository, using --bundle avoids downloading the
3868 For remote repository, using --bundle avoids downloading the
3865 changesets twice if the incoming is followed by a pull.
3869 changesets twice if the incoming is followed by a pull.
3866
3870
3867 See pull for valid source format details.
3871 See pull for valid source format details.
3868
3872
3869 Returns 0 if there are incoming changes, 1 otherwise.
3873 Returns 0 if there are incoming changes, 1 otherwise.
3870 """
3874 """
3871 if opts.get('graph'):
3875 if opts.get('graph'):
3872 cmdutil.checkunsupportedgraphflags([], opts)
3876 cmdutil.checkunsupportedgraphflags([], opts)
3873 def display(other, chlist, displayer):
3877 def display(other, chlist, displayer):
3874 revdag = cmdutil.graphrevs(other, chlist, opts)
3878 revdag = cmdutil.graphrevs(other, chlist, opts)
3875 showparents = [ctx.node() for ctx in repo[None].parents()]
3879 showparents = [ctx.node() for ctx in repo[None].parents()]
3876 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3880 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3877 graphmod.asciiedges)
3881 graphmod.asciiedges)
3878
3882
3879 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3883 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3880 return 0
3884 return 0
3881
3885
3882 if opts.get('bundle') and opts.get('subrepos'):
3886 if opts.get('bundle') and opts.get('subrepos'):
3883 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3887 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3884
3888
3885 if opts.get('bookmarks'):
3889 if opts.get('bookmarks'):
3886 source, branches = hg.parseurl(ui.expandpath(source),
3890 source, branches = hg.parseurl(ui.expandpath(source),
3887 opts.get('branch'))
3891 opts.get('branch'))
3888 other = hg.peer(repo, opts, source)
3892 other = hg.peer(repo, opts, source)
3889 if 'bookmarks' not in other.listkeys('namespaces'):
3893 if 'bookmarks' not in other.listkeys('namespaces'):
3890 ui.warn(_("remote doesn't support bookmarks\n"))
3894 ui.warn(_("remote doesn't support bookmarks\n"))
3891 return 0
3895 return 0
3892 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3896 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3893 return bookmarks.diff(ui, repo, other)
3897 return bookmarks.diff(ui, repo, other)
3894
3898
3895 repo._subtoppath = ui.expandpath(source)
3899 repo._subtoppath = ui.expandpath(source)
3896 try:
3900 try:
3897 return hg.incoming(ui, repo, source, opts)
3901 return hg.incoming(ui, repo, source, opts)
3898 finally:
3902 finally:
3899 del repo._subtoppath
3903 del repo._subtoppath
3900
3904
3901
3905
3902 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3906 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3903 def init(ui, dest=".", **opts):
3907 def init(ui, dest=".", **opts):
3904 """create a new repository in the given directory
3908 """create a new repository in the given directory
3905
3909
3906 Initialize a new repository in the given directory. If the given
3910 Initialize a new repository in the given directory. If the given
3907 directory does not exist, it will be created.
3911 directory does not exist, it will be created.
3908
3912
3909 If no directory is given, the current directory is used.
3913 If no directory is given, the current directory is used.
3910
3914
3911 It is possible to specify an ``ssh://`` URL as the destination.
3915 It is possible to specify an ``ssh://`` URL as the destination.
3912 See :hg:`help urls` for more information.
3916 See :hg:`help urls` for more information.
3913
3917
3914 Returns 0 on success.
3918 Returns 0 on success.
3915 """
3919 """
3916 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3920 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3917
3921
3918 @command('locate',
3922 @command('locate',
3919 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3923 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3920 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3924 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3921 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3925 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3922 ] + walkopts,
3926 ] + walkopts,
3923 _('[OPTION]... [PATTERN]...'))
3927 _('[OPTION]... [PATTERN]...'))
3924 def locate(ui, repo, *pats, **opts):
3928 def locate(ui, repo, *pats, **opts):
3925 """locate files matching specific patterns
3929 """locate files matching specific patterns
3926
3930
3927 Print files under Mercurial control in the working directory whose
3931 Print files under Mercurial control in the working directory whose
3928 names match the given patterns.
3932 names match the given patterns.
3929
3933
3930 By default, this command searches all directories in the working
3934 By default, this command searches all directories in the working
3931 directory. To search just the current directory and its
3935 directory. To search just the current directory and its
3932 subdirectories, use "--include .".
3936 subdirectories, use "--include .".
3933
3937
3934 If no patterns are given to match, this command prints the names
3938 If no patterns are given to match, this command prints the names
3935 of all files under Mercurial control in the working directory.
3939 of all files under Mercurial control in the working directory.
3936
3940
3937 If you want to feed the output of this command into the "xargs"
3941 If you want to feed the output of this command into the "xargs"
3938 command, use the -0 option to both this command and "xargs". This
3942 command, use the -0 option to both this command and "xargs". This
3939 will avoid the problem of "xargs" treating single filenames that
3943 will avoid the problem of "xargs" treating single filenames that
3940 contain whitespace as multiple filenames.
3944 contain whitespace as multiple filenames.
3941
3945
3942 Returns 0 if a match is found, 1 otherwise.
3946 Returns 0 if a match is found, 1 otherwise.
3943 """
3947 """
3944 end = opts.get('print0') and '\0' or '\n'
3948 end = opts.get('print0') and '\0' or '\n'
3945 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3949 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3946
3950
3947 ret = 1
3951 ret = 1
3948 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3952 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3949 m.bad = lambda x, y: False
3953 m.bad = lambda x, y: False
3950 for abs in repo[rev].walk(m):
3954 for abs in repo[rev].walk(m):
3951 if not rev and abs not in repo.dirstate:
3955 if not rev and abs not in repo.dirstate:
3952 continue
3956 continue
3953 if opts.get('fullpath'):
3957 if opts.get('fullpath'):
3954 ui.write(repo.wjoin(abs), end)
3958 ui.write(repo.wjoin(abs), end)
3955 else:
3959 else:
3956 ui.write(((pats and m.rel(abs)) or abs), end)
3960 ui.write(((pats and m.rel(abs)) or abs), end)
3957 ret = 0
3961 ret = 0
3958
3962
3959 return ret
3963 return ret
3960
3964
3961 @command('^log|history',
3965 @command('^log|history',
3962 [('f', 'follow', None,
3966 [('f', 'follow', None,
3963 _('follow changeset history, or file history across copies and renames')),
3967 _('follow changeset history, or file history across copies and renames')),
3964 ('', 'follow-first', None,
3968 ('', 'follow-first', None,
3965 _('only follow the first parent of merge changesets (DEPRECATED)')),
3969 _('only follow the first parent of merge changesets (DEPRECATED)')),
3966 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3970 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3967 ('C', 'copies', None, _('show copied files')),
3971 ('C', 'copies', None, _('show copied files')),
3968 ('k', 'keyword', [],
3972 ('k', 'keyword', [],
3969 _('do case-insensitive search for a given text'), _('TEXT')),
3973 _('do case-insensitive search for a given text'), _('TEXT')),
3970 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3974 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3971 ('', 'removed', None, _('include revisions where files were removed')),
3975 ('', 'removed', None, _('include revisions where files were removed')),
3972 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3976 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3973 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3977 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3974 ('', 'only-branch', [],
3978 ('', 'only-branch', [],
3975 _('show only changesets within the given named branch (DEPRECATED)'),
3979 _('show only changesets within the given named branch (DEPRECATED)'),
3976 _('BRANCH')),
3980 _('BRANCH')),
3977 ('b', 'branch', [],
3981 ('b', 'branch', [],
3978 _('show changesets within the given named branch'), _('BRANCH')),
3982 _('show changesets within the given named branch'), _('BRANCH')),
3979 ('P', 'prune', [],
3983 ('P', 'prune', [],
3980 _('do not display revision or any of its ancestors'), _('REV')),
3984 _('do not display revision or any of its ancestors'), _('REV')),
3981 ] + logopts + walkopts,
3985 ] + logopts + walkopts,
3982 _('[OPTION]... [FILE]'))
3986 _('[OPTION]... [FILE]'))
3983 def log(ui, repo, *pats, **opts):
3987 def log(ui, repo, *pats, **opts):
3984 """show revision history of entire repository or files
3988 """show revision history of entire repository or files
3985
3989
3986 Print the revision history of the specified files or the entire
3990 Print the revision history of the specified files or the entire
3987 project.
3991 project.
3988
3992
3989 If no revision range is specified, the default is ``tip:0`` unless
3993 If no revision range is specified, the default is ``tip:0`` unless
3990 --follow is set, in which case the working directory parent is
3994 --follow is set, in which case the working directory parent is
3991 used as the starting revision.
3995 used as the starting revision.
3992
3996
3993 File history is shown without following rename or copy history of
3997 File history is shown without following rename or copy history of
3994 files. Use -f/--follow with a filename to follow history across
3998 files. Use -f/--follow with a filename to follow history across
3995 renames and copies. --follow without a filename will only show
3999 renames and copies. --follow without a filename will only show
3996 ancestors or descendants of the starting revision.
4000 ancestors or descendants of the starting revision.
3997
4001
3998 By default this command prints revision number and changeset id,
4002 By default this command prints revision number and changeset id,
3999 tags, non-trivial parents, user, date and time, and a summary for
4003 tags, non-trivial parents, user, date and time, and a summary for
4000 each commit. When the -v/--verbose switch is used, the list of
4004 each commit. When the -v/--verbose switch is used, the list of
4001 changed files and full commit message are shown.
4005 changed files and full commit message are shown.
4002
4006
4003 .. note::
4007 .. note::
4004
4008
4005 log -p/--patch may generate unexpected diff output for merge
4009 log -p/--patch may generate unexpected diff output for merge
4006 changesets, as it will only compare the merge changeset against
4010 changesets, as it will only compare the merge changeset against
4007 its first parent. Also, only files different from BOTH parents
4011 its first parent. Also, only files different from BOTH parents
4008 will appear in files:.
4012 will appear in files:.
4009
4013
4010 .. note::
4014 .. note::
4011
4015
4012 for performance reasons, log FILE may omit duplicate changes
4016 for performance reasons, log FILE may omit duplicate changes
4013 made on branches and will not show deletions. To see all
4017 made on branches and will not show deletions. To see all
4014 changes including duplicates and deletions, use the --removed
4018 changes including duplicates and deletions, use the --removed
4015 switch.
4019 switch.
4016
4020
4017 .. container:: verbose
4021 .. container:: verbose
4018
4022
4019 Some examples:
4023 Some examples:
4020
4024
4021 - changesets with full descriptions and file lists::
4025 - changesets with full descriptions and file lists::
4022
4026
4023 hg log -v
4027 hg log -v
4024
4028
4025 - changesets ancestral to the working directory::
4029 - changesets ancestral to the working directory::
4026
4030
4027 hg log -f
4031 hg log -f
4028
4032
4029 - last 10 commits on the current branch::
4033 - last 10 commits on the current branch::
4030
4034
4031 hg log -l 10 -b .
4035 hg log -l 10 -b .
4032
4036
4033 - changesets showing all modifications of a file, including removals::
4037 - changesets showing all modifications of a file, including removals::
4034
4038
4035 hg log --removed file.c
4039 hg log --removed file.c
4036
4040
4037 - all changesets that touch a directory, with diffs, excluding merges::
4041 - all changesets that touch a directory, with diffs, excluding merges::
4038
4042
4039 hg log -Mp lib/
4043 hg log -Mp lib/
4040
4044
4041 - all revision numbers that match a keyword::
4045 - all revision numbers that match a keyword::
4042
4046
4043 hg log -k bug --template "{rev}\\n"
4047 hg log -k bug --template "{rev}\\n"
4044
4048
4045 - check if a given changeset is included is a tagged release::
4049 - check if a given changeset is included is a tagged release::
4046
4050
4047 hg log -r "a21ccf and ancestor(1.9)"
4051 hg log -r "a21ccf and ancestor(1.9)"
4048
4052
4049 - find all changesets by some user in a date range::
4053 - find all changesets by some user in a date range::
4050
4054
4051 hg log -k alice -d "may 2008 to jul 2008"
4055 hg log -k alice -d "may 2008 to jul 2008"
4052
4056
4053 - summary of all changesets after the last tag::
4057 - summary of all changesets after the last tag::
4054
4058
4055 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4059 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4056
4060
4057 See :hg:`help dates` for a list of formats valid for -d/--date.
4061 See :hg:`help dates` for a list of formats valid for -d/--date.
4058
4062
4059 See :hg:`help revisions` and :hg:`help revsets` for more about
4063 See :hg:`help revisions` and :hg:`help revsets` for more about
4060 specifying revisions.
4064 specifying revisions.
4061
4065
4062 See :hg:`help templates` for more about pre-packaged styles and
4066 See :hg:`help templates` for more about pre-packaged styles and
4063 specifying custom templates.
4067 specifying custom templates.
4064
4068
4065 Returns 0 on success.
4069 Returns 0 on success.
4066 """
4070 """
4067 if opts.get('graph'):
4071 if opts.get('graph'):
4068 return cmdutil.graphlog(ui, repo, *pats, **opts)
4072 return cmdutil.graphlog(ui, repo, *pats, **opts)
4069
4073
4070 matchfn = scmutil.match(repo[None], pats, opts)
4074 matchfn = scmutil.match(repo[None], pats, opts)
4071 limit = cmdutil.loglimit(opts)
4075 limit = cmdutil.loglimit(opts)
4072 count = 0
4076 count = 0
4073
4077
4074 getrenamed, endrev = None, None
4078 getrenamed, endrev = None, None
4075 if opts.get('copies'):
4079 if opts.get('copies'):
4076 if opts.get('rev'):
4080 if opts.get('rev'):
4077 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4081 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4078 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4082 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4079
4083
4080 df = False
4084 df = False
4081 if opts.get("date"):
4085 if opts.get("date"):
4082 df = util.matchdate(opts["date"])
4086 df = util.matchdate(opts["date"])
4083
4087
4084 branches = opts.get('branch', []) + opts.get('only_branch', [])
4088 branches = opts.get('branch', []) + opts.get('only_branch', [])
4085 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4089 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4086
4090
4087 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4091 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4088 def prep(ctx, fns):
4092 def prep(ctx, fns):
4089 rev = ctx.rev()
4093 rev = ctx.rev()
4090 parents = [p for p in repo.changelog.parentrevs(rev)
4094 parents = [p for p in repo.changelog.parentrevs(rev)
4091 if p != nullrev]
4095 if p != nullrev]
4092 if opts.get('no_merges') and len(parents) == 2:
4096 if opts.get('no_merges') and len(parents) == 2:
4093 return
4097 return
4094 if opts.get('only_merges') and len(parents) != 2:
4098 if opts.get('only_merges') and len(parents) != 2:
4095 return
4099 return
4096 if opts.get('branch') and ctx.branch() not in opts['branch']:
4100 if opts.get('branch') and ctx.branch() not in opts['branch']:
4097 return
4101 return
4098 if df and not df(ctx.date()[0]):
4102 if df and not df(ctx.date()[0]):
4099 return
4103 return
4100
4104
4101 lower = encoding.lower
4105 lower = encoding.lower
4102 if opts.get('user'):
4106 if opts.get('user'):
4103 luser = lower(ctx.user())
4107 luser = lower(ctx.user())
4104 for k in [lower(x) for x in opts['user']]:
4108 for k in [lower(x) for x in opts['user']]:
4105 if (k in luser):
4109 if (k in luser):
4106 break
4110 break
4107 else:
4111 else:
4108 return
4112 return
4109 if opts.get('keyword'):
4113 if opts.get('keyword'):
4110 luser = lower(ctx.user())
4114 luser = lower(ctx.user())
4111 ldesc = lower(ctx.description())
4115 ldesc = lower(ctx.description())
4112 lfiles = lower(" ".join(ctx.files()))
4116 lfiles = lower(" ".join(ctx.files()))
4113 for k in [lower(x) for x in opts['keyword']]:
4117 for k in [lower(x) for x in opts['keyword']]:
4114 if (k in luser or k in ldesc or k in lfiles):
4118 if (k in luser or k in ldesc or k in lfiles):
4115 break
4119 break
4116 else:
4120 else:
4117 return
4121 return
4118
4122
4119 copies = None
4123 copies = None
4120 if getrenamed is not None and rev:
4124 if getrenamed is not None and rev:
4121 copies = []
4125 copies = []
4122 for fn in ctx.files():
4126 for fn in ctx.files():
4123 rename = getrenamed(fn, rev)
4127 rename = getrenamed(fn, rev)
4124 if rename:
4128 if rename:
4125 copies.append((fn, rename[0]))
4129 copies.append((fn, rename[0]))
4126
4130
4127 revmatchfn = None
4131 revmatchfn = None
4128 if opts.get('patch') or opts.get('stat'):
4132 if opts.get('patch') or opts.get('stat'):
4129 if opts.get('follow') or opts.get('follow_first'):
4133 if opts.get('follow') or opts.get('follow_first'):
4130 # note: this might be wrong when following through merges
4134 # note: this might be wrong when following through merges
4131 revmatchfn = scmutil.match(repo[None], fns, default='path')
4135 revmatchfn = scmutil.match(repo[None], fns, default='path')
4132 else:
4136 else:
4133 revmatchfn = matchfn
4137 revmatchfn = matchfn
4134
4138
4135 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4139 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4136
4140
4137 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4141 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4138 if displayer.flush(ctx.rev()):
4142 if displayer.flush(ctx.rev()):
4139 count += 1
4143 count += 1
4140 if count == limit:
4144 if count == limit:
4141 break
4145 break
4142 displayer.close()
4146 displayer.close()
4143
4147
4144 @command('manifest',
4148 @command('manifest',
4145 [('r', 'rev', '', _('revision to display'), _('REV')),
4149 [('r', 'rev', '', _('revision to display'), _('REV')),
4146 ('', 'all', False, _("list files from all revisions"))],
4150 ('', 'all', False, _("list files from all revisions"))],
4147 _('[-r REV]'))
4151 _('[-r REV]'))
4148 def manifest(ui, repo, node=None, rev=None, **opts):
4152 def manifest(ui, repo, node=None, rev=None, **opts):
4149 """output the current or given revision of the project manifest
4153 """output the current or given revision of the project manifest
4150
4154
4151 Print a list of version controlled files for the given revision.
4155 Print a list of version controlled files for the given revision.
4152 If no revision is given, the first parent of the working directory
4156 If no revision is given, the first parent of the working directory
4153 is used, or the null revision if no revision is checked out.
4157 is used, or the null revision if no revision is checked out.
4154
4158
4155 With -v, print file permissions, symlink and executable bits.
4159 With -v, print file permissions, symlink and executable bits.
4156 With --debug, print file revision hashes.
4160 With --debug, print file revision hashes.
4157
4161
4158 If option --all is specified, the list of all files from all revisions
4162 If option --all is specified, the list of all files from all revisions
4159 is printed. This includes deleted and renamed files.
4163 is printed. This includes deleted and renamed files.
4160
4164
4161 Returns 0 on success.
4165 Returns 0 on success.
4162 """
4166 """
4163
4167
4164 fm = ui.formatter('manifest', opts)
4168 fm = ui.formatter('manifest', opts)
4165
4169
4166 if opts.get('all'):
4170 if opts.get('all'):
4167 if rev or node:
4171 if rev or node:
4168 raise util.Abort(_("can't specify a revision with --all"))
4172 raise util.Abort(_("can't specify a revision with --all"))
4169
4173
4170 res = []
4174 res = []
4171 prefix = "data/"
4175 prefix = "data/"
4172 suffix = ".i"
4176 suffix = ".i"
4173 plen = len(prefix)
4177 plen = len(prefix)
4174 slen = len(suffix)
4178 slen = len(suffix)
4175 lock = repo.lock()
4179 lock = repo.lock()
4176 try:
4180 try:
4177 for fn, b, size in repo.store.datafiles():
4181 for fn, b, size in repo.store.datafiles():
4178 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4182 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4179 res.append(fn[plen:-slen])
4183 res.append(fn[plen:-slen])
4180 finally:
4184 finally:
4181 lock.release()
4185 lock.release()
4182 for f in res:
4186 for f in res:
4183 fm.startitem()
4187 fm.startitem()
4184 fm.write("path", '%s\n', f)
4188 fm.write("path", '%s\n', f)
4185 fm.end()
4189 fm.end()
4186 return
4190 return
4187
4191
4188 if rev and node:
4192 if rev and node:
4189 raise util.Abort(_("please specify just one revision"))
4193 raise util.Abort(_("please specify just one revision"))
4190
4194
4191 if not node:
4195 if not node:
4192 node = rev
4196 node = rev
4193
4197
4194 char = {'l': '@', 'x': '*', '': ''}
4198 char = {'l': '@', 'x': '*', '': ''}
4195 mode = {'l': '644', 'x': '755', '': '644'}
4199 mode = {'l': '644', 'x': '755', '': '644'}
4196 ctx = scmutil.revsingle(repo, node)
4200 ctx = scmutil.revsingle(repo, node)
4197 mf = ctx.manifest()
4201 mf = ctx.manifest()
4198 for f in ctx:
4202 for f in ctx:
4199 fm.startitem()
4203 fm.startitem()
4200 fl = ctx[f].flags()
4204 fl = ctx[f].flags()
4201 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4205 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4202 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4206 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4203 fm.write('path', '%s\n', f)
4207 fm.write('path', '%s\n', f)
4204 fm.end()
4208 fm.end()
4205
4209
4206 @command('^merge',
4210 @command('^merge',
4207 [('f', 'force', None,
4211 [('f', 'force', None,
4208 _('force a merge including outstanding changes (DEPRECATED)')),
4212 _('force a merge including outstanding changes (DEPRECATED)')),
4209 ('r', 'rev', '', _('revision to merge'), _('REV')),
4213 ('r', 'rev', '', _('revision to merge'), _('REV')),
4210 ('P', 'preview', None,
4214 ('P', 'preview', None,
4211 _('review revisions to merge (no merge is performed)'))
4215 _('review revisions to merge (no merge is performed)'))
4212 ] + mergetoolopts,
4216 ] + mergetoolopts,
4213 _('[-P] [-f] [[-r] REV]'))
4217 _('[-P] [-f] [[-r] REV]'))
4214 def merge(ui, repo, node=None, **opts):
4218 def merge(ui, repo, node=None, **opts):
4215 """merge working directory with another revision
4219 """merge working directory with another revision
4216
4220
4217 The current working directory is updated with all changes made in
4221 The current working directory is updated with all changes made in
4218 the requested revision since the last common predecessor revision.
4222 the requested revision since the last common predecessor revision.
4219
4223
4220 Files that changed between either parent are marked as changed for
4224 Files that changed between either parent are marked as changed for
4221 the next commit and a commit must be performed before any further
4225 the next commit and a commit must be performed before any further
4222 updates to the repository are allowed. The next commit will have
4226 updates to the repository are allowed. The next commit will have
4223 two parents.
4227 two parents.
4224
4228
4225 ``--tool`` can be used to specify the merge tool used for file
4229 ``--tool`` can be used to specify the merge tool used for file
4226 merges. It overrides the HGMERGE environment variable and your
4230 merges. It overrides the HGMERGE environment variable and your
4227 configuration files. See :hg:`help merge-tools` for options.
4231 configuration files. See :hg:`help merge-tools` for options.
4228
4232
4229 If no revision is specified, the working directory's parent is a
4233 If no revision is specified, the working directory's parent is a
4230 head revision, and the current branch contains exactly one other
4234 head revision, and the current branch contains exactly one other
4231 head, the other head is merged with by default. Otherwise, an
4235 head, the other head is merged with by default. Otherwise, an
4232 explicit revision with which to merge with must be provided.
4236 explicit revision with which to merge with must be provided.
4233
4237
4234 :hg:`resolve` must be used to resolve unresolved files.
4238 :hg:`resolve` must be used to resolve unresolved files.
4235
4239
4236 To undo an uncommitted merge, use :hg:`update --clean .` which
4240 To undo an uncommitted merge, use :hg:`update --clean .` which
4237 will check out a clean copy of the original merge parent, losing
4241 will check out a clean copy of the original merge parent, losing
4238 all changes.
4242 all changes.
4239
4243
4240 Returns 0 on success, 1 if there are unresolved files.
4244 Returns 0 on success, 1 if there are unresolved files.
4241 """
4245 """
4242
4246
4243 if opts.get('rev') and node:
4247 if opts.get('rev') and node:
4244 raise util.Abort(_("please specify just one revision"))
4248 raise util.Abort(_("please specify just one revision"))
4245 if not node:
4249 if not node:
4246 node = opts.get('rev')
4250 node = opts.get('rev')
4247
4251
4248 if node:
4252 if node:
4249 node = scmutil.revsingle(repo, node).node()
4253 node = scmutil.revsingle(repo, node).node()
4250
4254
4251 if not node and repo._bookmarkcurrent:
4255 if not node and repo._bookmarkcurrent:
4252 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4256 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4253 curhead = repo[repo._bookmarkcurrent].node()
4257 curhead = repo[repo._bookmarkcurrent].node()
4254 if len(bmheads) == 2:
4258 if len(bmheads) == 2:
4255 if curhead == bmheads[0]:
4259 if curhead == bmheads[0]:
4256 node = bmheads[1]
4260 node = bmheads[1]
4257 else:
4261 else:
4258 node = bmheads[0]
4262 node = bmheads[0]
4259 elif len(bmheads) > 2:
4263 elif len(bmheads) > 2:
4260 raise util.Abort(_("multiple matching bookmarks to merge - "
4264 raise util.Abort(_("multiple matching bookmarks to merge - "
4261 "please merge with an explicit rev or bookmark"),
4265 "please merge with an explicit rev or bookmark"),
4262 hint=_("run 'hg heads' to see all heads"))
4266 hint=_("run 'hg heads' to see all heads"))
4263 elif len(bmheads) <= 1:
4267 elif len(bmheads) <= 1:
4264 raise util.Abort(_("no matching bookmark to merge - "
4268 raise util.Abort(_("no matching bookmark to merge - "
4265 "please merge with an explicit rev or bookmark"),
4269 "please merge with an explicit rev or bookmark"),
4266 hint=_("run 'hg heads' to see all heads"))
4270 hint=_("run 'hg heads' to see all heads"))
4267
4271
4268 if not node and not repo._bookmarkcurrent:
4272 if not node and not repo._bookmarkcurrent:
4269 branch = repo[None].branch()
4273 branch = repo[None].branch()
4270 bheads = repo.branchheads(branch)
4274 bheads = repo.branchheads(branch)
4271 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4275 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4272
4276
4273 if len(nbhs) > 2:
4277 if len(nbhs) > 2:
4274 raise util.Abort(_("branch '%s' has %d heads - "
4278 raise util.Abort(_("branch '%s' has %d heads - "
4275 "please merge with an explicit rev")
4279 "please merge with an explicit rev")
4276 % (branch, len(bheads)),
4280 % (branch, len(bheads)),
4277 hint=_("run 'hg heads .' to see heads"))
4281 hint=_("run 'hg heads .' to see heads"))
4278
4282
4279 parent = repo.dirstate.p1()
4283 parent = repo.dirstate.p1()
4280 if len(nbhs) <= 1:
4284 if len(nbhs) <= 1:
4281 if len(bheads) > 1:
4285 if len(bheads) > 1:
4282 raise util.Abort(_("heads are bookmarked - "
4286 raise util.Abort(_("heads are bookmarked - "
4283 "please merge with an explicit rev"),
4287 "please merge with an explicit rev"),
4284 hint=_("run 'hg heads' to see all heads"))
4288 hint=_("run 'hg heads' to see all heads"))
4285 if len(repo.heads()) > 1:
4289 if len(repo.heads()) > 1:
4286 raise util.Abort(_("branch '%s' has one head - "
4290 raise util.Abort(_("branch '%s' has one head - "
4287 "please merge with an explicit rev")
4291 "please merge with an explicit rev")
4288 % branch,
4292 % branch,
4289 hint=_("run 'hg heads' to see all heads"))
4293 hint=_("run 'hg heads' to see all heads"))
4290 msg, hint = _('nothing to merge'), None
4294 msg, hint = _('nothing to merge'), None
4291 if parent != repo.lookup(branch):
4295 if parent != repo.lookup(branch):
4292 hint = _("use 'hg update' instead")
4296 hint = _("use 'hg update' instead")
4293 raise util.Abort(msg, hint=hint)
4297 raise util.Abort(msg, hint=hint)
4294
4298
4295 if parent not in bheads:
4299 if parent not in bheads:
4296 raise util.Abort(_('working directory not at a head revision'),
4300 raise util.Abort(_('working directory not at a head revision'),
4297 hint=_("use 'hg update' or merge with an "
4301 hint=_("use 'hg update' or merge with an "
4298 "explicit revision"))
4302 "explicit revision"))
4299 if parent == nbhs[0]:
4303 if parent == nbhs[0]:
4300 node = nbhs[-1]
4304 node = nbhs[-1]
4301 else:
4305 else:
4302 node = nbhs[0]
4306 node = nbhs[0]
4303
4307
4304 if opts.get('preview'):
4308 if opts.get('preview'):
4305 # find nodes that are ancestors of p2 but not of p1
4309 # find nodes that are ancestors of p2 but not of p1
4306 p1 = repo.lookup('.')
4310 p1 = repo.lookup('.')
4307 p2 = repo.lookup(node)
4311 p2 = repo.lookup(node)
4308 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4312 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4309
4313
4310 displayer = cmdutil.show_changeset(ui, repo, opts)
4314 displayer = cmdutil.show_changeset(ui, repo, opts)
4311 for node in nodes:
4315 for node in nodes:
4312 displayer.show(repo[node])
4316 displayer.show(repo[node])
4313 displayer.close()
4317 displayer.close()
4314 return 0
4318 return 0
4315
4319
4316 try:
4320 try:
4317 # ui.forcemerge is an internal variable, do not document
4321 # ui.forcemerge is an internal variable, do not document
4318 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4322 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4319 return hg.merge(repo, node, force=opts.get('force'))
4323 return hg.merge(repo, node, force=opts.get('force'))
4320 finally:
4324 finally:
4321 ui.setconfig('ui', 'forcemerge', '')
4325 ui.setconfig('ui', 'forcemerge', '')
4322
4326
4323 @command('outgoing|out',
4327 @command('outgoing|out',
4324 [('f', 'force', None, _('run even when the destination is unrelated')),
4328 [('f', 'force', None, _('run even when the destination is unrelated')),
4325 ('r', 'rev', [],
4329 ('r', 'rev', [],
4326 _('a changeset intended to be included in the destination'), _('REV')),
4330 _('a changeset intended to be included in the destination'), _('REV')),
4327 ('n', 'newest-first', None, _('show newest record first')),
4331 ('n', 'newest-first', None, _('show newest record first')),
4328 ('B', 'bookmarks', False, _('compare bookmarks')),
4332 ('B', 'bookmarks', False, _('compare bookmarks')),
4329 ('b', 'branch', [], _('a specific branch you would like to push'),
4333 ('b', 'branch', [], _('a specific branch you would like to push'),
4330 _('BRANCH')),
4334 _('BRANCH')),
4331 ] + logopts + remoteopts + subrepoopts,
4335 ] + logopts + remoteopts + subrepoopts,
4332 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4336 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4333 def outgoing(ui, repo, dest=None, **opts):
4337 def outgoing(ui, repo, dest=None, **opts):
4334 """show changesets not found in the destination
4338 """show changesets not found in the destination
4335
4339
4336 Show changesets not found in the specified destination repository
4340 Show changesets not found in the specified destination repository
4337 or the default push location. These are the changesets that would
4341 or the default push location. These are the changesets that would
4338 be pushed if a push was requested.
4342 be pushed if a push was requested.
4339
4343
4340 See pull for details of valid destination formats.
4344 See pull for details of valid destination formats.
4341
4345
4342 Returns 0 if there are outgoing changes, 1 otherwise.
4346 Returns 0 if there are outgoing changes, 1 otherwise.
4343 """
4347 """
4344 if opts.get('graph'):
4348 if opts.get('graph'):
4345 cmdutil.checkunsupportedgraphflags([], opts)
4349 cmdutil.checkunsupportedgraphflags([], opts)
4346 o = hg._outgoing(ui, repo, dest, opts)
4350 o = hg._outgoing(ui, repo, dest, opts)
4347 if o is None:
4351 if o is None:
4348 return
4352 return
4349
4353
4350 revdag = cmdutil.graphrevs(repo, o, opts)
4354 revdag = cmdutil.graphrevs(repo, o, opts)
4351 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4355 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4352 showparents = [ctx.node() for ctx in repo[None].parents()]
4356 showparents = [ctx.node() for ctx in repo[None].parents()]
4353 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4357 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4354 graphmod.asciiedges)
4358 graphmod.asciiedges)
4355 return 0
4359 return 0
4356
4360
4357 if opts.get('bookmarks'):
4361 if opts.get('bookmarks'):
4358 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4362 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4359 dest, branches = hg.parseurl(dest, opts.get('branch'))
4363 dest, branches = hg.parseurl(dest, opts.get('branch'))
4360 other = hg.peer(repo, opts, dest)
4364 other = hg.peer(repo, opts, dest)
4361 if 'bookmarks' not in other.listkeys('namespaces'):
4365 if 'bookmarks' not in other.listkeys('namespaces'):
4362 ui.warn(_("remote doesn't support bookmarks\n"))
4366 ui.warn(_("remote doesn't support bookmarks\n"))
4363 return 0
4367 return 0
4364 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4368 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4365 return bookmarks.diff(ui, other, repo)
4369 return bookmarks.diff(ui, other, repo)
4366
4370
4367 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4371 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4368 try:
4372 try:
4369 return hg.outgoing(ui, repo, dest, opts)
4373 return hg.outgoing(ui, repo, dest, opts)
4370 finally:
4374 finally:
4371 del repo._subtoppath
4375 del repo._subtoppath
4372
4376
4373 @command('parents',
4377 @command('parents',
4374 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4378 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4375 ] + templateopts,
4379 ] + templateopts,
4376 _('[-r REV] [FILE]'))
4380 _('[-r REV] [FILE]'))
4377 def parents(ui, repo, file_=None, **opts):
4381 def parents(ui, repo, file_=None, **opts):
4378 """show the parents of the working directory or revision
4382 """show the parents of the working directory or revision
4379
4383
4380 Print the working directory's parent revisions. If a revision is
4384 Print the working directory's parent revisions. If a revision is
4381 given via -r/--rev, the parent of that revision will be printed.
4385 given via -r/--rev, the parent of that revision will be printed.
4382 If a file argument is given, the revision in which the file was
4386 If a file argument is given, the revision in which the file was
4383 last changed (before the working directory revision or the
4387 last changed (before the working directory revision or the
4384 argument to --rev if given) is printed.
4388 argument to --rev if given) is printed.
4385
4389
4386 Returns 0 on success.
4390 Returns 0 on success.
4387 """
4391 """
4388
4392
4389 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4393 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4390
4394
4391 if file_:
4395 if file_:
4392 m = scmutil.match(ctx, (file_,), opts)
4396 m = scmutil.match(ctx, (file_,), opts)
4393 if m.anypats() or len(m.files()) != 1:
4397 if m.anypats() or len(m.files()) != 1:
4394 raise util.Abort(_('can only specify an explicit filename'))
4398 raise util.Abort(_('can only specify an explicit filename'))
4395 file_ = m.files()[0]
4399 file_ = m.files()[0]
4396 filenodes = []
4400 filenodes = []
4397 for cp in ctx.parents():
4401 for cp in ctx.parents():
4398 if not cp:
4402 if not cp:
4399 continue
4403 continue
4400 try:
4404 try:
4401 filenodes.append(cp.filenode(file_))
4405 filenodes.append(cp.filenode(file_))
4402 except error.LookupError:
4406 except error.LookupError:
4403 pass
4407 pass
4404 if not filenodes:
4408 if not filenodes:
4405 raise util.Abort(_("'%s' not found in manifest!") % file_)
4409 raise util.Abort(_("'%s' not found in manifest!") % file_)
4406 p = []
4410 p = []
4407 for fn in filenodes:
4411 for fn in filenodes:
4408 fctx = repo.filectx(file_, fileid=fn)
4412 fctx = repo.filectx(file_, fileid=fn)
4409 p.append(fctx.node())
4413 p.append(fctx.node())
4410 else:
4414 else:
4411 p = [cp.node() for cp in ctx.parents()]
4415 p = [cp.node() for cp in ctx.parents()]
4412
4416
4413 displayer = cmdutil.show_changeset(ui, repo, opts)
4417 displayer = cmdutil.show_changeset(ui, repo, opts)
4414 for n in p:
4418 for n in p:
4415 if n != nullid:
4419 if n != nullid:
4416 displayer.show(repo[n])
4420 displayer.show(repo[n])
4417 displayer.close()
4421 displayer.close()
4418
4422
4419 @command('paths', [], _('[NAME]'))
4423 @command('paths', [], _('[NAME]'))
4420 def paths(ui, repo, search=None):
4424 def paths(ui, repo, search=None):
4421 """show aliases for remote repositories
4425 """show aliases for remote repositories
4422
4426
4423 Show definition of symbolic path name NAME. If no name is given,
4427 Show definition of symbolic path name NAME. If no name is given,
4424 show definition of all available names.
4428 show definition of all available names.
4425
4429
4426 Option -q/--quiet suppresses all output when searching for NAME
4430 Option -q/--quiet suppresses all output when searching for NAME
4427 and shows only the path names when listing all definitions.
4431 and shows only the path names when listing all definitions.
4428
4432
4429 Path names are defined in the [paths] section of your
4433 Path names are defined in the [paths] section of your
4430 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4434 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4431 repository, ``.hg/hgrc`` is used, too.
4435 repository, ``.hg/hgrc`` is used, too.
4432
4436
4433 The path names ``default`` and ``default-push`` have a special
4437 The path names ``default`` and ``default-push`` have a special
4434 meaning. When performing a push or pull operation, they are used
4438 meaning. When performing a push or pull operation, they are used
4435 as fallbacks if no location is specified on the command-line.
4439 as fallbacks if no location is specified on the command-line.
4436 When ``default-push`` is set, it will be used for push and
4440 When ``default-push`` is set, it will be used for push and
4437 ``default`` will be used for pull; otherwise ``default`` is used
4441 ``default`` will be used for pull; otherwise ``default`` is used
4438 as the fallback for both. When cloning a repository, the clone
4442 as the fallback for both. When cloning a repository, the clone
4439 source is written as ``default`` in ``.hg/hgrc``. Note that
4443 source is written as ``default`` in ``.hg/hgrc``. Note that
4440 ``default`` and ``default-push`` apply to all inbound (e.g.
4444 ``default`` and ``default-push`` apply to all inbound (e.g.
4441 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4445 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4442 :hg:`bundle`) operations.
4446 :hg:`bundle`) operations.
4443
4447
4444 See :hg:`help urls` for more information.
4448 See :hg:`help urls` for more information.
4445
4449
4446 Returns 0 on success.
4450 Returns 0 on success.
4447 """
4451 """
4448 if search:
4452 if search:
4449 for name, path in ui.configitems("paths"):
4453 for name, path in ui.configitems("paths"):
4450 if name == search:
4454 if name == search:
4451 ui.status("%s\n" % util.hidepassword(path))
4455 ui.status("%s\n" % util.hidepassword(path))
4452 return
4456 return
4453 if not ui.quiet:
4457 if not ui.quiet:
4454 ui.warn(_("not found!\n"))
4458 ui.warn(_("not found!\n"))
4455 return 1
4459 return 1
4456 else:
4460 else:
4457 for name, path in ui.configitems("paths"):
4461 for name, path in ui.configitems("paths"):
4458 if ui.quiet:
4462 if ui.quiet:
4459 ui.write("%s\n" % name)
4463 ui.write("%s\n" % name)
4460 else:
4464 else:
4461 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4465 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4462
4466
4463 @command('phase',
4467 @command('phase',
4464 [('p', 'public', False, _('set changeset phase to public')),
4468 [('p', 'public', False, _('set changeset phase to public')),
4465 ('d', 'draft', False, _('set changeset phase to draft')),
4469 ('d', 'draft', False, _('set changeset phase to draft')),
4466 ('s', 'secret', False, _('set changeset phase to secret')),
4470 ('s', 'secret', False, _('set changeset phase to secret')),
4467 ('f', 'force', False, _('allow to move boundary backward')),
4471 ('f', 'force', False, _('allow to move boundary backward')),
4468 ('r', 'rev', [], _('target revision'), _('REV')),
4472 ('r', 'rev', [], _('target revision'), _('REV')),
4469 ],
4473 ],
4470 _('[-p|-d|-s] [-f] [-r] REV...'))
4474 _('[-p|-d|-s] [-f] [-r] REV...'))
4471 def phase(ui, repo, *revs, **opts):
4475 def phase(ui, repo, *revs, **opts):
4472 """set or show the current phase name
4476 """set or show the current phase name
4473
4477
4474 With no argument, show the phase name of specified revisions.
4478 With no argument, show the phase name of specified revisions.
4475
4479
4476 With one of -p/--public, -d/--draft or -s/--secret, change the
4480 With one of -p/--public, -d/--draft or -s/--secret, change the
4477 phase value of the specified revisions.
4481 phase value of the specified revisions.
4478
4482
4479 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4483 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4480 lower phase to an higher phase. Phases are ordered as follows::
4484 lower phase to an higher phase. Phases are ordered as follows::
4481
4485
4482 public < draft < secret
4486 public < draft < secret
4483
4487
4484 Returns 0 on success, 1 if no phases were changed or some could not
4488 Returns 0 on success, 1 if no phases were changed or some could not
4485 be changed.
4489 be changed.
4486 """
4490 """
4487 # search for a unique phase argument
4491 # search for a unique phase argument
4488 targetphase = None
4492 targetphase = None
4489 for idx, name in enumerate(phases.phasenames):
4493 for idx, name in enumerate(phases.phasenames):
4490 if opts[name]:
4494 if opts[name]:
4491 if targetphase is not None:
4495 if targetphase is not None:
4492 raise util.Abort(_('only one phase can be specified'))
4496 raise util.Abort(_('only one phase can be specified'))
4493 targetphase = idx
4497 targetphase = idx
4494
4498
4495 # look for specified revision
4499 # look for specified revision
4496 revs = list(revs)
4500 revs = list(revs)
4497 revs.extend(opts['rev'])
4501 revs.extend(opts['rev'])
4498 if not revs:
4502 if not revs:
4499 raise util.Abort(_('no revisions specified'))
4503 raise util.Abort(_('no revisions specified'))
4500
4504
4501 revs = scmutil.revrange(repo, revs)
4505 revs = scmutil.revrange(repo, revs)
4502
4506
4503 lock = None
4507 lock = None
4504 ret = 0
4508 ret = 0
4505 if targetphase is None:
4509 if targetphase is None:
4506 # display
4510 # display
4507 for r in revs:
4511 for r in revs:
4508 ctx = repo[r]
4512 ctx = repo[r]
4509 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4513 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4510 else:
4514 else:
4511 lock = repo.lock()
4515 lock = repo.lock()
4512 try:
4516 try:
4513 # set phase
4517 # set phase
4514 if not revs:
4518 if not revs:
4515 raise util.Abort(_('empty revision set'))
4519 raise util.Abort(_('empty revision set'))
4516 nodes = [repo[r].node() for r in revs]
4520 nodes = [repo[r].node() for r in revs]
4517 olddata = repo._phasecache.getphaserevs(repo)[:]
4521 olddata = repo._phasecache.getphaserevs(repo)[:]
4518 phases.advanceboundary(repo, targetphase, nodes)
4522 phases.advanceboundary(repo, targetphase, nodes)
4519 if opts['force']:
4523 if opts['force']:
4520 phases.retractboundary(repo, targetphase, nodes)
4524 phases.retractboundary(repo, targetphase, nodes)
4521 finally:
4525 finally:
4522 lock.release()
4526 lock.release()
4523 # moving revision from public to draft may hide them
4527 # moving revision from public to draft may hide them
4524 # We have to check result on an unfiltered repository
4528 # We have to check result on an unfiltered repository
4525 unfi = repo.unfiltered()
4529 unfi = repo.unfiltered()
4526 newdata = repo._phasecache.getphaserevs(unfi)
4530 newdata = repo._phasecache.getphaserevs(unfi)
4527 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4531 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4528 cl = unfi.changelog
4532 cl = unfi.changelog
4529 rejected = [n for n in nodes
4533 rejected = [n for n in nodes
4530 if newdata[cl.rev(n)] < targetphase]
4534 if newdata[cl.rev(n)] < targetphase]
4531 if rejected:
4535 if rejected:
4532 ui.warn(_('cannot move %i changesets to a higher '
4536 ui.warn(_('cannot move %i changesets to a higher '
4533 'phase, use --force\n') % len(rejected))
4537 'phase, use --force\n') % len(rejected))
4534 ret = 1
4538 ret = 1
4535 if changes:
4539 if changes:
4536 msg = _('phase changed for %i changesets\n') % changes
4540 msg = _('phase changed for %i changesets\n') % changes
4537 if ret:
4541 if ret:
4538 ui.status(msg)
4542 ui.status(msg)
4539 else:
4543 else:
4540 ui.note(msg)
4544 ui.note(msg)
4541 else:
4545 else:
4542 ui.warn(_('no phases changed\n'))
4546 ui.warn(_('no phases changed\n'))
4543 ret = 1
4547 ret = 1
4544 return ret
4548 return ret
4545
4549
4546 def postincoming(ui, repo, modheads, optupdate, checkout):
4550 def postincoming(ui, repo, modheads, optupdate, checkout):
4547 if modheads == 0:
4551 if modheads == 0:
4548 return
4552 return
4549 if optupdate:
4553 if optupdate:
4550 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4554 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4551 try:
4555 try:
4552 ret = hg.update(repo, checkout)
4556 ret = hg.update(repo, checkout)
4553 except util.Abort, inst:
4557 except util.Abort, inst:
4554 ui.warn(_("not updating: %s\n") % str(inst))
4558 ui.warn(_("not updating: %s\n") % str(inst))
4555 if inst.hint:
4559 if inst.hint:
4556 ui.warn(_("(%s)\n") % inst.hint)
4560 ui.warn(_("(%s)\n") % inst.hint)
4557 return 0
4561 return 0
4558 if not ret and not checkout:
4562 if not ret and not checkout:
4559 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4563 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4560 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4564 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4561 return ret
4565 return ret
4562 if modheads > 1:
4566 if modheads > 1:
4563 currentbranchheads = len(repo.branchheads())
4567 currentbranchheads = len(repo.branchheads())
4564 if currentbranchheads == modheads:
4568 if currentbranchheads == modheads:
4565 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4569 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4566 elif currentbranchheads > 1:
4570 elif currentbranchheads > 1:
4567 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4571 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4568 "merge)\n"))
4572 "merge)\n"))
4569 else:
4573 else:
4570 ui.status(_("(run 'hg heads' to see heads)\n"))
4574 ui.status(_("(run 'hg heads' to see heads)\n"))
4571 else:
4575 else:
4572 ui.status(_("(run 'hg update' to get a working copy)\n"))
4576 ui.status(_("(run 'hg update' to get a working copy)\n"))
4573
4577
4574 @command('^pull',
4578 @command('^pull',
4575 [('u', 'update', None,
4579 [('u', 'update', None,
4576 _('update to new branch head if changesets were pulled')),
4580 _('update to new branch head if changesets were pulled')),
4577 ('f', 'force', None, _('run even when remote repository is unrelated')),
4581 ('f', 'force', None, _('run even when remote repository is unrelated')),
4578 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4582 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4579 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4583 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4580 ('b', 'branch', [], _('a specific branch you would like to pull'),
4584 ('b', 'branch', [], _('a specific branch you would like to pull'),
4581 _('BRANCH')),
4585 _('BRANCH')),
4582 ] + remoteopts,
4586 ] + remoteopts,
4583 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4587 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4584 def pull(ui, repo, source="default", **opts):
4588 def pull(ui, repo, source="default", **opts):
4585 """pull changes from the specified source
4589 """pull changes from the specified source
4586
4590
4587 Pull changes from a remote repository to a local one.
4591 Pull changes from a remote repository to a local one.
4588
4592
4589 This finds all changes from the repository at the specified path
4593 This finds all changes from the repository at the specified path
4590 or URL and adds them to a local repository (the current one unless
4594 or URL and adds them to a local repository (the current one unless
4591 -R is specified). By default, this does not update the copy of the
4595 -R is specified). By default, this does not update the copy of the
4592 project in the working directory.
4596 project in the working directory.
4593
4597
4594 Use :hg:`incoming` if you want to see what would have been added
4598 Use :hg:`incoming` if you want to see what would have been added
4595 by a pull at the time you issued this command. If you then decide
4599 by a pull at the time you issued this command. If you then decide
4596 to add those changes to the repository, you should use :hg:`pull
4600 to add those changes to the repository, you should use :hg:`pull
4597 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4601 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4598
4602
4599 If SOURCE is omitted, the 'default' path will be used.
4603 If SOURCE is omitted, the 'default' path will be used.
4600 See :hg:`help urls` for more information.
4604 See :hg:`help urls` for more information.
4601
4605
4602 Returns 0 on success, 1 if an update had unresolved files.
4606 Returns 0 on success, 1 if an update had unresolved files.
4603 """
4607 """
4604 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4608 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4605 other = hg.peer(repo, opts, source)
4609 other = hg.peer(repo, opts, source)
4606 try:
4610 try:
4607 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4611 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4608 revs, checkout = hg.addbranchrevs(repo, other, branches,
4612 revs, checkout = hg.addbranchrevs(repo, other, branches,
4609 opts.get('rev'))
4613 opts.get('rev'))
4610
4614
4611 remotebookmarks = other.listkeys('bookmarks')
4615 remotebookmarks = other.listkeys('bookmarks')
4612
4616
4613 if opts.get('bookmark'):
4617 if opts.get('bookmark'):
4614 if not revs:
4618 if not revs:
4615 revs = []
4619 revs = []
4616 for b in opts['bookmark']:
4620 for b in opts['bookmark']:
4617 if b not in remotebookmarks:
4621 if b not in remotebookmarks:
4618 raise util.Abort(_('remote bookmark %s not found!') % b)
4622 raise util.Abort(_('remote bookmark %s not found!') % b)
4619 revs.append(remotebookmarks[b])
4623 revs.append(remotebookmarks[b])
4620
4624
4621 if revs:
4625 if revs:
4622 try:
4626 try:
4623 revs = [other.lookup(rev) for rev in revs]
4627 revs = [other.lookup(rev) for rev in revs]
4624 except error.CapabilityError:
4628 except error.CapabilityError:
4625 err = _("other repository doesn't support revision lookup, "
4629 err = _("other repository doesn't support revision lookup, "
4626 "so a rev cannot be specified.")
4630 "so a rev cannot be specified.")
4627 raise util.Abort(err)
4631 raise util.Abort(err)
4628
4632
4629 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4633 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4630 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4634 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4631 if checkout:
4635 if checkout:
4632 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4636 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4633 repo._subtoppath = source
4637 repo._subtoppath = source
4634 try:
4638 try:
4635 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4639 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4636
4640
4637 finally:
4641 finally:
4638 del repo._subtoppath
4642 del repo._subtoppath
4639
4643
4640 # update specified bookmarks
4644 # update specified bookmarks
4641 if opts.get('bookmark'):
4645 if opts.get('bookmark'):
4642 marks = repo._bookmarks
4646 marks = repo._bookmarks
4643 for b in opts['bookmark']:
4647 for b in opts['bookmark']:
4644 # explicit pull overrides local bookmark if any
4648 # explicit pull overrides local bookmark if any
4645 ui.status(_("importing bookmark %s\n") % b)
4649 ui.status(_("importing bookmark %s\n") % b)
4646 marks[b] = repo[remotebookmarks[b]].node()
4650 marks[b] = repo[remotebookmarks[b]].node()
4647 marks.write()
4651 marks.write()
4648 finally:
4652 finally:
4649 other.close()
4653 other.close()
4650 return ret
4654 return ret
4651
4655
4652 @command('^push',
4656 @command('^push',
4653 [('f', 'force', None, _('force push')),
4657 [('f', 'force', None, _('force push')),
4654 ('r', 'rev', [],
4658 ('r', 'rev', [],
4655 _('a changeset intended to be included in the destination'),
4659 _('a changeset intended to be included in the destination'),
4656 _('REV')),
4660 _('REV')),
4657 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4661 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4658 ('b', 'branch', [],
4662 ('b', 'branch', [],
4659 _('a specific branch you would like to push'), _('BRANCH')),
4663 _('a specific branch you would like to push'), _('BRANCH')),
4660 ('', 'new-branch', False, _('allow pushing a new branch')),
4664 ('', 'new-branch', False, _('allow pushing a new branch')),
4661 ] + remoteopts,
4665 ] + remoteopts,
4662 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4666 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4663 def push(ui, repo, dest=None, **opts):
4667 def push(ui, repo, dest=None, **opts):
4664 """push changes to the specified destination
4668 """push changes to the specified destination
4665
4669
4666 Push changesets from the local repository to the specified
4670 Push changesets from the local repository to the specified
4667 destination.
4671 destination.
4668
4672
4669 This operation is symmetrical to pull: it is identical to a pull
4673 This operation is symmetrical to pull: it is identical to a pull
4670 in the destination repository from the current one.
4674 in the destination repository from the current one.
4671
4675
4672 By default, push will not allow creation of new heads at the
4676 By default, push will not allow creation of new heads at the
4673 destination, since multiple heads would make it unclear which head
4677 destination, since multiple heads would make it unclear which head
4674 to use. In this situation, it is recommended to pull and merge
4678 to use. In this situation, it is recommended to pull and merge
4675 before pushing.
4679 before pushing.
4676
4680
4677 Use --new-branch if you want to allow push to create a new named
4681 Use --new-branch if you want to allow push to create a new named
4678 branch that is not present at the destination. This allows you to
4682 branch that is not present at the destination. This allows you to
4679 only create a new branch without forcing other changes.
4683 only create a new branch without forcing other changes.
4680
4684
4681 .. note::
4685 .. note::
4682
4686
4683 Extra care should be taken with the -f/--force option,
4687 Extra care should be taken with the -f/--force option,
4684 which will push all new heads on all branches, an action which will
4688 which will push all new heads on all branches, an action which will
4685 almost always cause confusion for collaborators.
4689 almost always cause confusion for collaborators.
4686
4690
4687 If -r/--rev is used, the specified revision and all its ancestors
4691 If -r/--rev is used, the specified revision and all its ancestors
4688 will be pushed to the remote repository.
4692 will be pushed to the remote repository.
4689
4693
4690 If -B/--bookmark is used, the specified bookmarked revision, its
4694 If -B/--bookmark is used, the specified bookmarked revision, its
4691 ancestors, and the bookmark will be pushed to the remote
4695 ancestors, and the bookmark will be pushed to the remote
4692 repository.
4696 repository.
4693
4697
4694 Please see :hg:`help urls` for important details about ``ssh://``
4698 Please see :hg:`help urls` for important details about ``ssh://``
4695 URLs. If DESTINATION is omitted, a default path will be used.
4699 URLs. If DESTINATION is omitted, a default path will be used.
4696
4700
4697 Returns 0 if push was successful, 1 if nothing to push.
4701 Returns 0 if push was successful, 1 if nothing to push.
4698 """
4702 """
4699
4703
4700 if opts.get('bookmark'):
4704 if opts.get('bookmark'):
4701 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4705 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4702 for b in opts['bookmark']:
4706 for b in opts['bookmark']:
4703 # translate -B options to -r so changesets get pushed
4707 # translate -B options to -r so changesets get pushed
4704 if b in repo._bookmarks:
4708 if b in repo._bookmarks:
4705 opts.setdefault('rev', []).append(b)
4709 opts.setdefault('rev', []).append(b)
4706 else:
4710 else:
4707 # if we try to push a deleted bookmark, translate it to null
4711 # if we try to push a deleted bookmark, translate it to null
4708 # this lets simultaneous -r, -b options continue working
4712 # this lets simultaneous -r, -b options continue working
4709 opts.setdefault('rev', []).append("null")
4713 opts.setdefault('rev', []).append("null")
4710
4714
4711 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4715 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4712 dest, branches = hg.parseurl(dest, opts.get('branch'))
4716 dest, branches = hg.parseurl(dest, opts.get('branch'))
4713 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4717 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4714 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4718 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4715 other = hg.peer(repo, opts, dest)
4719 other = hg.peer(repo, opts, dest)
4716 if revs:
4720 if revs:
4717 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4721 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4718
4722
4719 repo._subtoppath = dest
4723 repo._subtoppath = dest
4720 try:
4724 try:
4721 # push subrepos depth-first for coherent ordering
4725 # push subrepos depth-first for coherent ordering
4722 c = repo['']
4726 c = repo['']
4723 subs = c.substate # only repos that are committed
4727 subs = c.substate # only repos that are committed
4724 for s in sorted(subs):
4728 for s in sorted(subs):
4725 if c.sub(s).push(opts) == 0:
4729 if c.sub(s).push(opts) == 0:
4726 return False
4730 return False
4727 finally:
4731 finally:
4728 del repo._subtoppath
4732 del repo._subtoppath
4729 result = repo.push(other, opts.get('force'), revs=revs,
4733 result = repo.push(other, opts.get('force'), revs=revs,
4730 newbranch=opts.get('new_branch'))
4734 newbranch=opts.get('new_branch'))
4731
4735
4732 result = not result
4736 result = not result
4733
4737
4734 if opts.get('bookmark'):
4738 if opts.get('bookmark'):
4735 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4739 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4736 if bresult == 2:
4740 if bresult == 2:
4737 return 2
4741 return 2
4738 if not result and bresult:
4742 if not result and bresult:
4739 result = 2
4743 result = 2
4740
4744
4741 return result
4745 return result
4742
4746
4743 @command('recover', [])
4747 @command('recover', [])
4744 def recover(ui, repo):
4748 def recover(ui, repo):
4745 """roll back an interrupted transaction
4749 """roll back an interrupted transaction
4746
4750
4747 Recover from an interrupted commit or pull.
4751 Recover from an interrupted commit or pull.
4748
4752
4749 This command tries to fix the repository status after an
4753 This command tries to fix the repository status after an
4750 interrupted operation. It should only be necessary when Mercurial
4754 interrupted operation. It should only be necessary when Mercurial
4751 suggests it.
4755 suggests it.
4752
4756
4753 Returns 0 if successful, 1 if nothing to recover or verify fails.
4757 Returns 0 if successful, 1 if nothing to recover or verify fails.
4754 """
4758 """
4755 if repo.recover():
4759 if repo.recover():
4756 return hg.verify(repo)
4760 return hg.verify(repo)
4757 return 1
4761 return 1
4758
4762
4759 @command('^remove|rm',
4763 @command('^remove|rm',
4760 [('A', 'after', None, _('record delete for missing files')),
4764 [('A', 'after', None, _('record delete for missing files')),
4761 ('f', 'force', None,
4765 ('f', 'force', None,
4762 _('remove (and delete) file even if added or modified')),
4766 _('remove (and delete) file even if added or modified')),
4763 ] + walkopts,
4767 ] + walkopts,
4764 _('[OPTION]... FILE...'))
4768 _('[OPTION]... FILE...'))
4765 def remove(ui, repo, *pats, **opts):
4769 def remove(ui, repo, *pats, **opts):
4766 """remove the specified files on the next commit
4770 """remove the specified files on the next commit
4767
4771
4768 Schedule the indicated files for removal from the current branch.
4772 Schedule the indicated files for removal from the current branch.
4769
4773
4770 This command schedules the files to be removed at the next commit.
4774 This command schedules the files to be removed at the next commit.
4771 To undo a remove before that, see :hg:`revert`. To undo added
4775 To undo a remove before that, see :hg:`revert`. To undo added
4772 files, see :hg:`forget`.
4776 files, see :hg:`forget`.
4773
4777
4774 .. container:: verbose
4778 .. container:: verbose
4775
4779
4776 -A/--after can be used to remove only files that have already
4780 -A/--after can be used to remove only files that have already
4777 been deleted, -f/--force can be used to force deletion, and -Af
4781 been deleted, -f/--force can be used to force deletion, and -Af
4778 can be used to remove files from the next revision without
4782 can be used to remove files from the next revision without
4779 deleting them from the working directory.
4783 deleting them from the working directory.
4780
4784
4781 The following table details the behavior of remove for different
4785 The following table details the behavior of remove for different
4782 file states (columns) and option combinations (rows). The file
4786 file states (columns) and option combinations (rows). The file
4783 states are Added [A], Clean [C], Modified [M] and Missing [!]
4787 states are Added [A], Clean [C], Modified [M] and Missing [!]
4784 (as reported by :hg:`status`). The actions are Warn, Remove
4788 (as reported by :hg:`status`). The actions are Warn, Remove
4785 (from branch) and Delete (from disk):
4789 (from branch) and Delete (from disk):
4786
4790
4787 ========= == == == ==
4791 ========= == == == ==
4788 opt/state A C M !
4792 opt/state A C M !
4789 ========= == == == ==
4793 ========= == == == ==
4790 none W RD W R
4794 none W RD W R
4791 -f R RD RD R
4795 -f R RD RD R
4792 -A W W W R
4796 -A W W W R
4793 -Af R R R R
4797 -Af R R R R
4794 ========= == == == ==
4798 ========= == == == ==
4795
4799
4796 Note that remove never deletes files in Added [A] state from the
4800 Note that remove never deletes files in Added [A] state from the
4797 working directory, not even if option --force is specified.
4801 working directory, not even if option --force is specified.
4798
4802
4799 Returns 0 on success, 1 if any warnings encountered.
4803 Returns 0 on success, 1 if any warnings encountered.
4800 """
4804 """
4801
4805
4802 ret = 0
4806 ret = 0
4803 after, force = opts.get('after'), opts.get('force')
4807 after, force = opts.get('after'), opts.get('force')
4804 if not pats and not after:
4808 if not pats and not after:
4805 raise util.Abort(_('no files specified'))
4809 raise util.Abort(_('no files specified'))
4806
4810
4807 m = scmutil.match(repo[None], pats, opts)
4811 m = scmutil.match(repo[None], pats, opts)
4808 s = repo.status(match=m, clean=True)
4812 s = repo.status(match=m, clean=True)
4809 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4813 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4810
4814
4811 # warn about failure to delete explicit files/dirs
4815 # warn about failure to delete explicit files/dirs
4812 wctx = repo[None]
4816 wctx = repo[None]
4813 for f in m.files():
4817 for f in m.files():
4814 if f in repo.dirstate or f in wctx.dirs():
4818 if f in repo.dirstate or f in wctx.dirs():
4815 continue
4819 continue
4816 if os.path.exists(m.rel(f)):
4820 if os.path.exists(m.rel(f)):
4817 if os.path.isdir(m.rel(f)):
4821 if os.path.isdir(m.rel(f)):
4818 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4822 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4819 else:
4823 else:
4820 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4824 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4821 # missing files will generate a warning elsewhere
4825 # missing files will generate a warning elsewhere
4822 ret = 1
4826 ret = 1
4823
4827
4824 if force:
4828 if force:
4825 list = modified + deleted + clean + added
4829 list = modified + deleted + clean + added
4826 elif after:
4830 elif after:
4827 list = deleted
4831 list = deleted
4828 for f in modified + added + clean:
4832 for f in modified + added + clean:
4829 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4833 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4830 ret = 1
4834 ret = 1
4831 else:
4835 else:
4832 list = deleted + clean
4836 list = deleted + clean
4833 for f in modified:
4837 for f in modified:
4834 ui.warn(_('not removing %s: file is modified (use -f'
4838 ui.warn(_('not removing %s: file is modified (use -f'
4835 ' to force removal)\n') % m.rel(f))
4839 ' to force removal)\n') % m.rel(f))
4836 ret = 1
4840 ret = 1
4837 for f in added:
4841 for f in added:
4838 ui.warn(_('not removing %s: file has been marked for add'
4842 ui.warn(_('not removing %s: file has been marked for add'
4839 ' (use forget to undo)\n') % m.rel(f))
4843 ' (use forget to undo)\n') % m.rel(f))
4840 ret = 1
4844 ret = 1
4841
4845
4842 for f in sorted(list):
4846 for f in sorted(list):
4843 if ui.verbose or not m.exact(f):
4847 if ui.verbose or not m.exact(f):
4844 ui.status(_('removing %s\n') % m.rel(f))
4848 ui.status(_('removing %s\n') % m.rel(f))
4845
4849
4846 wlock = repo.wlock()
4850 wlock = repo.wlock()
4847 try:
4851 try:
4848 if not after:
4852 if not after:
4849 for f in list:
4853 for f in list:
4850 if f in added:
4854 if f in added:
4851 continue # we never unlink added files on remove
4855 continue # we never unlink added files on remove
4852 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4856 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4853 repo[None].forget(list)
4857 repo[None].forget(list)
4854 finally:
4858 finally:
4855 wlock.release()
4859 wlock.release()
4856
4860
4857 return ret
4861 return ret
4858
4862
4859 @command('rename|move|mv',
4863 @command('rename|move|mv',
4860 [('A', 'after', None, _('record a rename that has already occurred')),
4864 [('A', 'after', None, _('record a rename that has already occurred')),
4861 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4865 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4862 ] + walkopts + dryrunopts,
4866 ] + walkopts + dryrunopts,
4863 _('[OPTION]... SOURCE... DEST'))
4867 _('[OPTION]... SOURCE... DEST'))
4864 def rename(ui, repo, *pats, **opts):
4868 def rename(ui, repo, *pats, **opts):
4865 """rename files; equivalent of copy + remove
4869 """rename files; equivalent of copy + remove
4866
4870
4867 Mark dest as copies of sources; mark sources for deletion. If dest
4871 Mark dest as copies of sources; mark sources for deletion. If dest
4868 is a directory, copies are put in that directory. If dest is a
4872 is a directory, copies are put in that directory. If dest is a
4869 file, there can only be one source.
4873 file, there can only be one source.
4870
4874
4871 By default, this command copies the contents of files as they
4875 By default, this command copies the contents of files as they
4872 exist in the working directory. If invoked with -A/--after, the
4876 exist in the working directory. If invoked with -A/--after, the
4873 operation is recorded, but no copying is performed.
4877 operation is recorded, but no copying is performed.
4874
4878
4875 This command takes effect at the next commit. To undo a rename
4879 This command takes effect at the next commit. To undo a rename
4876 before that, see :hg:`revert`.
4880 before that, see :hg:`revert`.
4877
4881
4878 Returns 0 on success, 1 if errors are encountered.
4882 Returns 0 on success, 1 if errors are encountered.
4879 """
4883 """
4880 wlock = repo.wlock(False)
4884 wlock = repo.wlock(False)
4881 try:
4885 try:
4882 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4886 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4883 finally:
4887 finally:
4884 wlock.release()
4888 wlock.release()
4885
4889
4886 @command('resolve',
4890 @command('resolve',
4887 [('a', 'all', None, _('select all unresolved files')),
4891 [('a', 'all', None, _('select all unresolved files')),
4888 ('l', 'list', None, _('list state of files needing merge')),
4892 ('l', 'list', None, _('list state of files needing merge')),
4889 ('m', 'mark', None, _('mark files as resolved')),
4893 ('m', 'mark', None, _('mark files as resolved')),
4890 ('u', 'unmark', None, _('mark files as unresolved')),
4894 ('u', 'unmark', None, _('mark files as unresolved')),
4891 ('n', 'no-status', None, _('hide status prefix'))]
4895 ('n', 'no-status', None, _('hide status prefix'))]
4892 + mergetoolopts + walkopts,
4896 + mergetoolopts + walkopts,
4893 _('[OPTION]... [FILE]...'))
4897 _('[OPTION]... [FILE]...'))
4894 def resolve(ui, repo, *pats, **opts):
4898 def resolve(ui, repo, *pats, **opts):
4895 """redo merges or set/view the merge status of files
4899 """redo merges or set/view the merge status of files
4896
4900
4897 Merges with unresolved conflicts are often the result of
4901 Merges with unresolved conflicts are often the result of
4898 non-interactive merging using the ``internal:merge`` configuration
4902 non-interactive merging using the ``internal:merge`` configuration
4899 setting, or a command-line merge tool like ``diff3``. The resolve
4903 setting, or a command-line merge tool like ``diff3``. The resolve
4900 command is used to manage the files involved in a merge, after
4904 command is used to manage the files involved in a merge, after
4901 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4905 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4902 working directory must have two parents). See :hg:`help
4906 working directory must have two parents). See :hg:`help
4903 merge-tools` for information on configuring merge tools.
4907 merge-tools` for information on configuring merge tools.
4904
4908
4905 The resolve command can be used in the following ways:
4909 The resolve command can be used in the following ways:
4906
4910
4907 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4911 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4908 files, discarding any previous merge attempts. Re-merging is not
4912 files, discarding any previous merge attempts. Re-merging is not
4909 performed for files already marked as resolved. Use ``--all/-a``
4913 performed for files already marked as resolved. Use ``--all/-a``
4910 to select all unresolved files. ``--tool`` can be used to specify
4914 to select all unresolved files. ``--tool`` can be used to specify
4911 the merge tool used for the given files. It overrides the HGMERGE
4915 the merge tool used for the given files. It overrides the HGMERGE
4912 environment variable and your configuration files. Previous file
4916 environment variable and your configuration files. Previous file
4913 contents are saved with a ``.orig`` suffix.
4917 contents are saved with a ``.orig`` suffix.
4914
4918
4915 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4919 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4916 (e.g. after having manually fixed-up the files). The default is
4920 (e.g. after having manually fixed-up the files). The default is
4917 to mark all unresolved files.
4921 to mark all unresolved files.
4918
4922
4919 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4923 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4920 default is to mark all resolved files.
4924 default is to mark all resolved files.
4921
4925
4922 - :hg:`resolve -l`: list files which had or still have conflicts.
4926 - :hg:`resolve -l`: list files which had or still have conflicts.
4923 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4927 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4924
4928
4925 Note that Mercurial will not let you commit files with unresolved
4929 Note that Mercurial will not let you commit files with unresolved
4926 merge conflicts. You must use :hg:`resolve -m ...` before you can
4930 merge conflicts. You must use :hg:`resolve -m ...` before you can
4927 commit after a conflicting merge.
4931 commit after a conflicting merge.
4928
4932
4929 Returns 0 on success, 1 if any files fail a resolve attempt.
4933 Returns 0 on success, 1 if any files fail a resolve attempt.
4930 """
4934 """
4931
4935
4932 all, mark, unmark, show, nostatus = \
4936 all, mark, unmark, show, nostatus = \
4933 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4937 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4934
4938
4935 if (show and (mark or unmark)) or (mark and unmark):
4939 if (show and (mark or unmark)) or (mark and unmark):
4936 raise util.Abort(_("too many options specified"))
4940 raise util.Abort(_("too many options specified"))
4937 if pats and all:
4941 if pats and all:
4938 raise util.Abort(_("can't specify --all and patterns"))
4942 raise util.Abort(_("can't specify --all and patterns"))
4939 if not (all or pats or show or mark or unmark):
4943 if not (all or pats or show or mark or unmark):
4940 raise util.Abort(_('no files or directories specified; '
4944 raise util.Abort(_('no files or directories specified; '
4941 'use --all to remerge all files'))
4945 'use --all to remerge all files'))
4942
4946
4943 ms = mergemod.mergestate(repo)
4947 ms = mergemod.mergestate(repo)
4944 m = scmutil.match(repo[None], pats, opts)
4948 m = scmutil.match(repo[None], pats, opts)
4945 ret = 0
4949 ret = 0
4946
4950
4947 for f in ms:
4951 for f in ms:
4948 if m(f):
4952 if m(f):
4949 if show:
4953 if show:
4950 if nostatus:
4954 if nostatus:
4951 ui.write("%s\n" % f)
4955 ui.write("%s\n" % f)
4952 else:
4956 else:
4953 ui.write("%s %s\n" % (ms[f].upper(), f),
4957 ui.write("%s %s\n" % (ms[f].upper(), f),
4954 label='resolve.' +
4958 label='resolve.' +
4955 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4959 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4956 elif mark:
4960 elif mark:
4957 ms.mark(f, "r")
4961 ms.mark(f, "r")
4958 elif unmark:
4962 elif unmark:
4959 ms.mark(f, "u")
4963 ms.mark(f, "u")
4960 else:
4964 else:
4961 wctx = repo[None]
4965 wctx = repo[None]
4962
4966
4963 # backup pre-resolve (merge uses .orig for its own purposes)
4967 # backup pre-resolve (merge uses .orig for its own purposes)
4964 a = repo.wjoin(f)
4968 a = repo.wjoin(f)
4965 util.copyfile(a, a + ".resolve")
4969 util.copyfile(a, a + ".resolve")
4966
4970
4967 try:
4971 try:
4968 # resolve file
4972 # resolve file
4969 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4973 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4970 if ms.resolve(f, wctx):
4974 if ms.resolve(f, wctx):
4971 ret = 1
4975 ret = 1
4972 finally:
4976 finally:
4973 ui.setconfig('ui', 'forcemerge', '')
4977 ui.setconfig('ui', 'forcemerge', '')
4974 ms.commit()
4978 ms.commit()
4975
4979
4976 # replace filemerge's .orig file with our resolve file
4980 # replace filemerge's .orig file with our resolve file
4977 util.rename(a + ".resolve", a + ".orig")
4981 util.rename(a + ".resolve", a + ".orig")
4978
4982
4979 ms.commit()
4983 ms.commit()
4980 return ret
4984 return ret
4981
4985
4982 @command('revert',
4986 @command('revert',
4983 [('a', 'all', None, _('revert all changes when no arguments given')),
4987 [('a', 'all', None, _('revert all changes when no arguments given')),
4984 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4988 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4985 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4989 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4986 ('C', 'no-backup', None, _('do not save backup copies of files')),
4990 ('C', 'no-backup', None, _('do not save backup copies of files')),
4987 ] + walkopts + dryrunopts,
4991 ] + walkopts + dryrunopts,
4988 _('[OPTION]... [-r REV] [NAME]...'))
4992 _('[OPTION]... [-r REV] [NAME]...'))
4989 def revert(ui, repo, *pats, **opts):
4993 def revert(ui, repo, *pats, **opts):
4990 """restore files to their checkout state
4994 """restore files to their checkout state
4991
4995
4992 .. note::
4996 .. note::
4993
4997
4994 To check out earlier revisions, you should use :hg:`update REV`.
4998 To check out earlier revisions, you should use :hg:`update REV`.
4995 To cancel an uncommitted merge (and lose your changes),
4999 To cancel an uncommitted merge (and lose your changes),
4996 use :hg:`update --clean .`.
5000 use :hg:`update --clean .`.
4997
5001
4998 With no revision specified, revert the specified files or directories
5002 With no revision specified, revert the specified files or directories
4999 to the contents they had in the parent of the working directory.
5003 to the contents they had in the parent of the working directory.
5000 This restores the contents of files to an unmodified
5004 This restores the contents of files to an unmodified
5001 state and unschedules adds, removes, copies, and renames. If the
5005 state and unschedules adds, removes, copies, and renames. If the
5002 working directory has two parents, you must explicitly specify a
5006 working directory has two parents, you must explicitly specify a
5003 revision.
5007 revision.
5004
5008
5005 Using the -r/--rev or -d/--date options, revert the given files or
5009 Using the -r/--rev or -d/--date options, revert the given files or
5006 directories to their states as of a specific revision. Because
5010 directories to their states as of a specific revision. Because
5007 revert does not change the working directory parents, this will
5011 revert does not change the working directory parents, this will
5008 cause these files to appear modified. This can be helpful to "back
5012 cause these files to appear modified. This can be helpful to "back
5009 out" some or all of an earlier change. See :hg:`backout` for a
5013 out" some or all of an earlier change. See :hg:`backout` for a
5010 related method.
5014 related method.
5011
5015
5012 Modified files are saved with a .orig suffix before reverting.
5016 Modified files are saved with a .orig suffix before reverting.
5013 To disable these backups, use --no-backup.
5017 To disable these backups, use --no-backup.
5014
5018
5015 See :hg:`help dates` for a list of formats valid for -d/--date.
5019 See :hg:`help dates` for a list of formats valid for -d/--date.
5016
5020
5017 Returns 0 on success.
5021 Returns 0 on success.
5018 """
5022 """
5019
5023
5020 if opts.get("date"):
5024 if opts.get("date"):
5021 if opts.get("rev"):
5025 if opts.get("rev"):
5022 raise util.Abort(_("you can't specify a revision and a date"))
5026 raise util.Abort(_("you can't specify a revision and a date"))
5023 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5027 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5024
5028
5025 parent, p2 = repo.dirstate.parents()
5029 parent, p2 = repo.dirstate.parents()
5026 if not opts.get('rev') and p2 != nullid:
5030 if not opts.get('rev') and p2 != nullid:
5027 # revert after merge is a trap for new users (issue2915)
5031 # revert after merge is a trap for new users (issue2915)
5028 raise util.Abort(_('uncommitted merge with no revision specified'),
5032 raise util.Abort(_('uncommitted merge with no revision specified'),
5029 hint=_('use "hg update" or see "hg help revert"'))
5033 hint=_('use "hg update" or see "hg help revert"'))
5030
5034
5031 ctx = scmutil.revsingle(repo, opts.get('rev'))
5035 ctx = scmutil.revsingle(repo, opts.get('rev'))
5032
5036
5033 if not pats and not opts.get('all'):
5037 if not pats and not opts.get('all'):
5034 msg = _("no files or directories specified")
5038 msg = _("no files or directories specified")
5035 if p2 != nullid:
5039 if p2 != nullid:
5036 hint = _("uncommitted merge, use --all to discard all changes,"
5040 hint = _("uncommitted merge, use --all to discard all changes,"
5037 " or 'hg update -C .' to abort the merge")
5041 " or 'hg update -C .' to abort the merge")
5038 raise util.Abort(msg, hint=hint)
5042 raise util.Abort(msg, hint=hint)
5039 dirty = util.any(repo.status())
5043 dirty = util.any(repo.status())
5040 node = ctx.node()
5044 node = ctx.node()
5041 if node != parent:
5045 if node != parent:
5042 if dirty:
5046 if dirty:
5043 hint = _("uncommitted changes, use --all to discard all"
5047 hint = _("uncommitted changes, use --all to discard all"
5044 " changes, or 'hg update %s' to update") % ctx.rev()
5048 " changes, or 'hg update %s' to update") % ctx.rev()
5045 else:
5049 else:
5046 hint = _("use --all to revert all files,"
5050 hint = _("use --all to revert all files,"
5047 " or 'hg update %s' to update") % ctx.rev()
5051 " or 'hg update %s' to update") % ctx.rev()
5048 elif dirty:
5052 elif dirty:
5049 hint = _("uncommitted changes, use --all to discard all changes")
5053 hint = _("uncommitted changes, use --all to discard all changes")
5050 else:
5054 else:
5051 hint = _("use --all to revert all files")
5055 hint = _("use --all to revert all files")
5052 raise util.Abort(msg, hint=hint)
5056 raise util.Abort(msg, hint=hint)
5053
5057
5054 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5058 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5055
5059
5056 @command('rollback', dryrunopts +
5060 @command('rollback', dryrunopts +
5057 [('f', 'force', False, _('ignore safety measures'))])
5061 [('f', 'force', False, _('ignore safety measures'))])
5058 def rollback(ui, repo, **opts):
5062 def rollback(ui, repo, **opts):
5059 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5063 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5060
5064
5061 Please use :hg:`commit --amend` instead of rollback to correct
5065 Please use :hg:`commit --amend` instead of rollback to correct
5062 mistakes in the last commit.
5066 mistakes in the last commit.
5063
5067
5064 This command should be used with care. There is only one level of
5068 This command should be used with care. There is only one level of
5065 rollback, and there is no way to undo a rollback. It will also
5069 rollback, and there is no way to undo a rollback. It will also
5066 restore the dirstate at the time of the last transaction, losing
5070 restore the dirstate at the time of the last transaction, losing
5067 any dirstate changes since that time. This command does not alter
5071 any dirstate changes since that time. This command does not alter
5068 the working directory.
5072 the working directory.
5069
5073
5070 Transactions are used to encapsulate the effects of all commands
5074 Transactions are used to encapsulate the effects of all commands
5071 that create new changesets or propagate existing changesets into a
5075 that create new changesets or propagate existing changesets into a
5072 repository.
5076 repository.
5073
5077
5074 .. container:: verbose
5078 .. container:: verbose
5075
5079
5076 For example, the following commands are transactional, and their
5080 For example, the following commands are transactional, and their
5077 effects can be rolled back:
5081 effects can be rolled back:
5078
5082
5079 - commit
5083 - commit
5080 - import
5084 - import
5081 - pull
5085 - pull
5082 - push (with this repository as the destination)
5086 - push (with this repository as the destination)
5083 - unbundle
5087 - unbundle
5084
5088
5085 To avoid permanent data loss, rollback will refuse to rollback a
5089 To avoid permanent data loss, rollback will refuse to rollback a
5086 commit transaction if it isn't checked out. Use --force to
5090 commit transaction if it isn't checked out. Use --force to
5087 override this protection.
5091 override this protection.
5088
5092
5089 This command is not intended for use on public repositories. Once
5093 This command is not intended for use on public repositories. Once
5090 changes are visible for pull by other users, rolling a transaction
5094 changes are visible for pull by other users, rolling a transaction
5091 back locally is ineffective (someone else may already have pulled
5095 back locally is ineffective (someone else may already have pulled
5092 the changes). Furthermore, a race is possible with readers of the
5096 the changes). Furthermore, a race is possible with readers of the
5093 repository; for example an in-progress pull from the repository
5097 repository; for example an in-progress pull from the repository
5094 may fail if a rollback is performed.
5098 may fail if a rollback is performed.
5095
5099
5096 Returns 0 on success, 1 if no rollback data is available.
5100 Returns 0 on success, 1 if no rollback data is available.
5097 """
5101 """
5098 return repo.rollback(dryrun=opts.get('dry_run'),
5102 return repo.rollback(dryrun=opts.get('dry_run'),
5099 force=opts.get('force'))
5103 force=opts.get('force'))
5100
5104
5101 @command('root', [])
5105 @command('root', [])
5102 def root(ui, repo):
5106 def root(ui, repo):
5103 """print the root (top) of the current working directory
5107 """print the root (top) of the current working directory
5104
5108
5105 Print the root directory of the current repository.
5109 Print the root directory of the current repository.
5106
5110
5107 Returns 0 on success.
5111 Returns 0 on success.
5108 """
5112 """
5109 ui.write(repo.root + "\n")
5113 ui.write(repo.root + "\n")
5110
5114
5111 @command('^serve',
5115 @command('^serve',
5112 [('A', 'accesslog', '', _('name of access log file to write to'),
5116 [('A', 'accesslog', '', _('name of access log file to write to'),
5113 _('FILE')),
5117 _('FILE')),
5114 ('d', 'daemon', None, _('run server in background')),
5118 ('d', 'daemon', None, _('run server in background')),
5115 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5119 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5116 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5120 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5117 # use string type, then we can check if something was passed
5121 # use string type, then we can check if something was passed
5118 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5122 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5119 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5123 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5120 _('ADDR')),
5124 _('ADDR')),
5121 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5125 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5122 _('PREFIX')),
5126 _('PREFIX')),
5123 ('n', 'name', '',
5127 ('n', 'name', '',
5124 _('name to show in web pages (default: working directory)'), _('NAME')),
5128 _('name to show in web pages (default: working directory)'), _('NAME')),
5125 ('', 'web-conf', '',
5129 ('', 'web-conf', '',
5126 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5130 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5127 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5131 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5128 _('FILE')),
5132 _('FILE')),
5129 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5133 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5130 ('', 'stdio', None, _('for remote clients')),
5134 ('', 'stdio', None, _('for remote clients')),
5131 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5135 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5132 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5136 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5133 ('', 'style', '', _('template style to use'), _('STYLE')),
5137 ('', 'style', '', _('template style to use'), _('STYLE')),
5134 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5138 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5135 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5139 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5136 _('[OPTION]...'))
5140 _('[OPTION]...'))
5137 def serve(ui, repo, **opts):
5141 def serve(ui, repo, **opts):
5138 """start stand-alone webserver
5142 """start stand-alone webserver
5139
5143
5140 Start a local HTTP repository browser and pull server. You can use
5144 Start a local HTTP repository browser and pull server. You can use
5141 this for ad-hoc sharing and browsing of repositories. It is
5145 this for ad-hoc sharing and browsing of repositories. It is
5142 recommended to use a real web server to serve a repository for
5146 recommended to use a real web server to serve a repository for
5143 longer periods of time.
5147 longer periods of time.
5144
5148
5145 Please note that the server does not implement access control.
5149 Please note that the server does not implement access control.
5146 This means that, by default, anybody can read from the server and
5150 This means that, by default, anybody can read from the server and
5147 nobody can write to it by default. Set the ``web.allow_push``
5151 nobody can write to it by default. Set the ``web.allow_push``
5148 option to ``*`` to allow everybody to push to the server. You
5152 option to ``*`` to allow everybody to push to the server. You
5149 should use a real web server if you need to authenticate users.
5153 should use a real web server if you need to authenticate users.
5150
5154
5151 By default, the server logs accesses to stdout and errors to
5155 By default, the server logs accesses to stdout and errors to
5152 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5156 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5153 files.
5157 files.
5154
5158
5155 To have the server choose a free port number to listen on, specify
5159 To have the server choose a free port number to listen on, specify
5156 a port number of 0; in this case, the server will print the port
5160 a port number of 0; in this case, the server will print the port
5157 number it uses.
5161 number it uses.
5158
5162
5159 Returns 0 on success.
5163 Returns 0 on success.
5160 """
5164 """
5161
5165
5162 if opts["stdio"] and opts["cmdserver"]:
5166 if opts["stdio"] and opts["cmdserver"]:
5163 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5167 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5164
5168
5165 def checkrepo():
5169 def checkrepo():
5166 if repo is None:
5170 if repo is None:
5167 raise error.RepoError(_("there is no Mercurial repository here"
5171 raise error.RepoError(_("there is no Mercurial repository here"
5168 " (.hg not found)"))
5172 " (.hg not found)"))
5169
5173
5170 if opts["stdio"]:
5174 if opts["stdio"]:
5171 checkrepo()
5175 checkrepo()
5172 s = sshserver.sshserver(ui, repo)
5176 s = sshserver.sshserver(ui, repo)
5173 s.serve_forever()
5177 s.serve_forever()
5174
5178
5175 if opts["cmdserver"]:
5179 if opts["cmdserver"]:
5176 checkrepo()
5180 checkrepo()
5177 s = commandserver.server(ui, repo, opts["cmdserver"])
5181 s = commandserver.server(ui, repo, opts["cmdserver"])
5178 return s.serve()
5182 return s.serve()
5179
5183
5180 # this way we can check if something was given in the command-line
5184 # this way we can check if something was given in the command-line
5181 if opts.get('port'):
5185 if opts.get('port'):
5182 opts['port'] = util.getport(opts.get('port'))
5186 opts['port'] = util.getport(opts.get('port'))
5183
5187
5184 baseui = repo and repo.baseui or ui
5188 baseui = repo and repo.baseui or ui
5185 optlist = ("name templates style address port prefix ipv6"
5189 optlist = ("name templates style address port prefix ipv6"
5186 " accesslog errorlog certificate encoding")
5190 " accesslog errorlog certificate encoding")
5187 for o in optlist.split():
5191 for o in optlist.split():
5188 val = opts.get(o, '')
5192 val = opts.get(o, '')
5189 if val in (None, ''): # should check against default options instead
5193 if val in (None, ''): # should check against default options instead
5190 continue
5194 continue
5191 baseui.setconfig("web", o, val)
5195 baseui.setconfig("web", o, val)
5192 if repo and repo.ui != baseui:
5196 if repo and repo.ui != baseui:
5193 repo.ui.setconfig("web", o, val)
5197 repo.ui.setconfig("web", o, val)
5194
5198
5195 o = opts.get('web_conf') or opts.get('webdir_conf')
5199 o = opts.get('web_conf') or opts.get('webdir_conf')
5196 if not o:
5200 if not o:
5197 if not repo:
5201 if not repo:
5198 raise error.RepoError(_("there is no Mercurial repository"
5202 raise error.RepoError(_("there is no Mercurial repository"
5199 " here (.hg not found)"))
5203 " here (.hg not found)"))
5200 o = repo
5204 o = repo
5201
5205
5202 app = hgweb.hgweb(o, baseui=baseui)
5206 app = hgweb.hgweb(o, baseui=baseui)
5203 service = httpservice(ui, app, opts)
5207 service = httpservice(ui, app, opts)
5204 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5208 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5205
5209
5206 class httpservice(object):
5210 class httpservice(object):
5207 def __init__(self, ui, app, opts):
5211 def __init__(self, ui, app, opts):
5208 self.ui = ui
5212 self.ui = ui
5209 self.app = app
5213 self.app = app
5210 self.opts = opts
5214 self.opts = opts
5211
5215
5212 def init(self):
5216 def init(self):
5213 util.setsignalhandler()
5217 util.setsignalhandler()
5214 self.httpd = hgweb_server.create_server(self.ui, self.app)
5218 self.httpd = hgweb_server.create_server(self.ui, self.app)
5215
5219
5216 if self.opts['port'] and not self.ui.verbose:
5220 if self.opts['port'] and not self.ui.verbose:
5217 return
5221 return
5218
5222
5219 if self.httpd.prefix:
5223 if self.httpd.prefix:
5220 prefix = self.httpd.prefix.strip('/') + '/'
5224 prefix = self.httpd.prefix.strip('/') + '/'
5221 else:
5225 else:
5222 prefix = ''
5226 prefix = ''
5223
5227
5224 port = ':%d' % self.httpd.port
5228 port = ':%d' % self.httpd.port
5225 if port == ':80':
5229 if port == ':80':
5226 port = ''
5230 port = ''
5227
5231
5228 bindaddr = self.httpd.addr
5232 bindaddr = self.httpd.addr
5229 if bindaddr == '0.0.0.0':
5233 if bindaddr == '0.0.0.0':
5230 bindaddr = '*'
5234 bindaddr = '*'
5231 elif ':' in bindaddr: # IPv6
5235 elif ':' in bindaddr: # IPv6
5232 bindaddr = '[%s]' % bindaddr
5236 bindaddr = '[%s]' % bindaddr
5233
5237
5234 fqaddr = self.httpd.fqaddr
5238 fqaddr = self.httpd.fqaddr
5235 if ':' in fqaddr:
5239 if ':' in fqaddr:
5236 fqaddr = '[%s]' % fqaddr
5240 fqaddr = '[%s]' % fqaddr
5237 if self.opts['port']:
5241 if self.opts['port']:
5238 write = self.ui.status
5242 write = self.ui.status
5239 else:
5243 else:
5240 write = self.ui.write
5244 write = self.ui.write
5241 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5245 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5242 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5246 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5243
5247
5244 def run(self):
5248 def run(self):
5245 self.httpd.serve_forever()
5249 self.httpd.serve_forever()
5246
5250
5247
5251
5248 @command('showconfig|debugconfig',
5252 @command('showconfig|debugconfig',
5249 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5253 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5250 _('[-u] [NAME]...'))
5254 _('[-u] [NAME]...'))
5251 def showconfig(ui, repo, *values, **opts):
5255 def showconfig(ui, repo, *values, **opts):
5252 """show combined config settings from all hgrc files
5256 """show combined config settings from all hgrc files
5253
5257
5254 With no arguments, print names and values of all config items.
5258 With no arguments, print names and values of all config items.
5255
5259
5256 With one argument of the form section.name, print just the value
5260 With one argument of the form section.name, print just the value
5257 of that config item.
5261 of that config item.
5258
5262
5259 With multiple arguments, print names and values of all config
5263 With multiple arguments, print names and values of all config
5260 items with matching section names.
5264 items with matching section names.
5261
5265
5262 With --debug, the source (filename and line number) is printed
5266 With --debug, the source (filename and line number) is printed
5263 for each config item.
5267 for each config item.
5264
5268
5265 Returns 0 on success.
5269 Returns 0 on success.
5266 """
5270 """
5267
5271
5268 for f in scmutil.rcpath():
5272 for f in scmutil.rcpath():
5269 ui.debug('read config from: %s\n' % f)
5273 ui.debug('read config from: %s\n' % f)
5270 untrusted = bool(opts.get('untrusted'))
5274 untrusted = bool(opts.get('untrusted'))
5271 if values:
5275 if values:
5272 sections = [v for v in values if '.' not in v]
5276 sections = [v for v in values if '.' not in v]
5273 items = [v for v in values if '.' in v]
5277 items = [v for v in values if '.' in v]
5274 if len(items) > 1 or items and sections:
5278 if len(items) > 1 or items and sections:
5275 raise util.Abort(_('only one config item permitted'))
5279 raise util.Abort(_('only one config item permitted'))
5276 for section, name, value in ui.walkconfig(untrusted=untrusted):
5280 for section, name, value in ui.walkconfig(untrusted=untrusted):
5277 value = str(value).replace('\n', '\\n')
5281 value = str(value).replace('\n', '\\n')
5278 sectname = section + '.' + name
5282 sectname = section + '.' + name
5279 if values:
5283 if values:
5280 for v in values:
5284 for v in values:
5281 if v == section:
5285 if v == section:
5282 ui.debug('%s: ' %
5286 ui.debug('%s: ' %
5283 ui.configsource(section, name, untrusted))
5287 ui.configsource(section, name, untrusted))
5284 ui.write('%s=%s\n' % (sectname, value))
5288 ui.write('%s=%s\n' % (sectname, value))
5285 elif v == sectname:
5289 elif v == sectname:
5286 ui.debug('%s: ' %
5290 ui.debug('%s: ' %
5287 ui.configsource(section, name, untrusted))
5291 ui.configsource(section, name, untrusted))
5288 ui.write(value, '\n')
5292 ui.write(value, '\n')
5289 else:
5293 else:
5290 ui.debug('%s: ' %
5294 ui.debug('%s: ' %
5291 ui.configsource(section, name, untrusted))
5295 ui.configsource(section, name, untrusted))
5292 ui.write('%s=%s\n' % (sectname, value))
5296 ui.write('%s=%s\n' % (sectname, value))
5293
5297
5294 @command('^status|st',
5298 @command('^status|st',
5295 [('A', 'all', None, _('show status of all files')),
5299 [('A', 'all', None, _('show status of all files')),
5296 ('m', 'modified', None, _('show only modified files')),
5300 ('m', 'modified', None, _('show only modified files')),
5297 ('a', 'added', None, _('show only added files')),
5301 ('a', 'added', None, _('show only added files')),
5298 ('r', 'removed', None, _('show only removed files')),
5302 ('r', 'removed', None, _('show only removed files')),
5299 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5303 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5300 ('c', 'clean', None, _('show only files without changes')),
5304 ('c', 'clean', None, _('show only files without changes')),
5301 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5305 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5302 ('i', 'ignored', None, _('show only ignored files')),
5306 ('i', 'ignored', None, _('show only ignored files')),
5303 ('n', 'no-status', None, _('hide status prefix')),
5307 ('n', 'no-status', None, _('hide status prefix')),
5304 ('C', 'copies', None, _('show source of copied files')),
5308 ('C', 'copies', None, _('show source of copied files')),
5305 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5309 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5306 ('', 'rev', [], _('show difference from revision'), _('REV')),
5310 ('', 'rev', [], _('show difference from revision'), _('REV')),
5307 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5311 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5308 ] + walkopts + subrepoopts,
5312 ] + walkopts + subrepoopts,
5309 _('[OPTION]... [FILE]...'))
5313 _('[OPTION]... [FILE]...'))
5310 def status(ui, repo, *pats, **opts):
5314 def status(ui, repo, *pats, **opts):
5311 """show changed files in the working directory
5315 """show changed files in the working directory
5312
5316
5313 Show status of files in the repository. If names are given, only
5317 Show status of files in the repository. If names are given, only
5314 files that match are shown. Files that are clean or ignored or
5318 files that match are shown. Files that are clean or ignored or
5315 the source of a copy/move operation, are not listed unless
5319 the source of a copy/move operation, are not listed unless
5316 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5320 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5317 Unless options described with "show only ..." are given, the
5321 Unless options described with "show only ..." are given, the
5318 options -mardu are used.
5322 options -mardu are used.
5319
5323
5320 Option -q/--quiet hides untracked (unknown and ignored) files
5324 Option -q/--quiet hides untracked (unknown and ignored) files
5321 unless explicitly requested with -u/--unknown or -i/--ignored.
5325 unless explicitly requested with -u/--unknown or -i/--ignored.
5322
5326
5323 .. note::
5327 .. note::
5324
5328
5325 status may appear to disagree with diff if permissions have
5329 status may appear to disagree with diff if permissions have
5326 changed or a merge has occurred. The standard diff format does
5330 changed or a merge has occurred. The standard diff format does
5327 not report permission changes and diff only reports changes
5331 not report permission changes and diff only reports changes
5328 relative to one merge parent.
5332 relative to one merge parent.
5329
5333
5330 If one revision is given, it is used as the base revision.
5334 If one revision is given, it is used as the base revision.
5331 If two revisions are given, the differences between them are
5335 If two revisions are given, the differences between them are
5332 shown. The --change option can also be used as a shortcut to list
5336 shown. The --change option can also be used as a shortcut to list
5333 the changed files of a revision from its first parent.
5337 the changed files of a revision from its first parent.
5334
5338
5335 The codes used to show the status of files are::
5339 The codes used to show the status of files are::
5336
5340
5337 M = modified
5341 M = modified
5338 A = added
5342 A = added
5339 R = removed
5343 R = removed
5340 C = clean
5344 C = clean
5341 ! = missing (deleted by non-hg command, but still tracked)
5345 ! = missing (deleted by non-hg command, but still tracked)
5342 ? = not tracked
5346 ? = not tracked
5343 I = ignored
5347 I = ignored
5344 = origin of the previous file listed as A (added)
5348 = origin of the previous file listed as A (added)
5345
5349
5346 .. container:: verbose
5350 .. container:: verbose
5347
5351
5348 Examples:
5352 Examples:
5349
5353
5350 - show changes in the working directory relative to a
5354 - show changes in the working directory relative to a
5351 changeset::
5355 changeset::
5352
5356
5353 hg status --rev 9353
5357 hg status --rev 9353
5354
5358
5355 - show all changes including copies in an existing changeset::
5359 - show all changes including copies in an existing changeset::
5356
5360
5357 hg status --copies --change 9353
5361 hg status --copies --change 9353
5358
5362
5359 - get a NUL separated list of added files, suitable for xargs::
5363 - get a NUL separated list of added files, suitable for xargs::
5360
5364
5361 hg status -an0
5365 hg status -an0
5362
5366
5363 Returns 0 on success.
5367 Returns 0 on success.
5364 """
5368 """
5365
5369
5366 revs = opts.get('rev')
5370 revs = opts.get('rev')
5367 change = opts.get('change')
5371 change = opts.get('change')
5368
5372
5369 if revs and change:
5373 if revs and change:
5370 msg = _('cannot specify --rev and --change at the same time')
5374 msg = _('cannot specify --rev and --change at the same time')
5371 raise util.Abort(msg)
5375 raise util.Abort(msg)
5372 elif change:
5376 elif change:
5373 node2 = scmutil.revsingle(repo, change, None).node()
5377 node2 = scmutil.revsingle(repo, change, None).node()
5374 node1 = repo[node2].p1().node()
5378 node1 = repo[node2].p1().node()
5375 else:
5379 else:
5376 node1, node2 = scmutil.revpair(repo, revs)
5380 node1, node2 = scmutil.revpair(repo, revs)
5377
5381
5378 cwd = (pats and repo.getcwd()) or ''
5382 cwd = (pats and repo.getcwd()) or ''
5379 end = opts.get('print0') and '\0' or '\n'
5383 end = opts.get('print0') and '\0' or '\n'
5380 copy = {}
5384 copy = {}
5381 states = 'modified added removed deleted unknown ignored clean'.split()
5385 states = 'modified added removed deleted unknown ignored clean'.split()
5382 show = [k for k in states if opts.get(k)]
5386 show = [k for k in states if opts.get(k)]
5383 if opts.get('all'):
5387 if opts.get('all'):
5384 show += ui.quiet and (states[:4] + ['clean']) or states
5388 show += ui.quiet and (states[:4] + ['clean']) or states
5385 if not show:
5389 if not show:
5386 show = ui.quiet and states[:4] or states[:5]
5390 show = ui.quiet and states[:4] or states[:5]
5387
5391
5388 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5392 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5389 'ignored' in show, 'clean' in show, 'unknown' in show,
5393 'ignored' in show, 'clean' in show, 'unknown' in show,
5390 opts.get('subrepos'))
5394 opts.get('subrepos'))
5391 changestates = zip(states, 'MAR!?IC', stat)
5395 changestates = zip(states, 'MAR!?IC', stat)
5392
5396
5393 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5397 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5394 copy = copies.pathcopies(repo[node1], repo[node2])
5398 copy = copies.pathcopies(repo[node1], repo[node2])
5395
5399
5396 fm = ui.formatter('status', opts)
5400 fm = ui.formatter('status', opts)
5397 fmt = '%s' + end
5401 fmt = '%s' + end
5398 showchar = not opts.get('no_status')
5402 showchar = not opts.get('no_status')
5399
5403
5400 for state, char, files in changestates:
5404 for state, char, files in changestates:
5401 if state in show:
5405 if state in show:
5402 label = 'status.' + state
5406 label = 'status.' + state
5403 for f in files:
5407 for f in files:
5404 fm.startitem()
5408 fm.startitem()
5405 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5409 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5406 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5410 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5407 if f in copy:
5411 if f in copy:
5408 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5412 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5409 label='status.copied')
5413 label='status.copied')
5410 fm.end()
5414 fm.end()
5411
5415
5412 @command('^summary|sum',
5416 @command('^summary|sum',
5413 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5417 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5414 def summary(ui, repo, **opts):
5418 def summary(ui, repo, **opts):
5415 """summarize working directory state
5419 """summarize working directory state
5416
5420
5417 This generates a brief summary of the working directory state,
5421 This generates a brief summary of the working directory state,
5418 including parents, branch, commit status, and available updates.
5422 including parents, branch, commit status, and available updates.
5419
5423
5420 With the --remote option, this will check the default paths for
5424 With the --remote option, this will check the default paths for
5421 incoming and outgoing changes. This can be time-consuming.
5425 incoming and outgoing changes. This can be time-consuming.
5422
5426
5423 Returns 0 on success.
5427 Returns 0 on success.
5424 """
5428 """
5425
5429
5426 ctx = repo[None]
5430 ctx = repo[None]
5427 parents = ctx.parents()
5431 parents = ctx.parents()
5428 pnode = parents[0].node()
5432 pnode = parents[0].node()
5429 marks = []
5433 marks = []
5430
5434
5431 for p in parents:
5435 for p in parents:
5432 # label with log.changeset (instead of log.parent) since this
5436 # label with log.changeset (instead of log.parent) since this
5433 # shows a working directory parent *changeset*:
5437 # shows a working directory parent *changeset*:
5434 # i18n: column positioning for "hg summary"
5438 # i18n: column positioning for "hg summary"
5435 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5439 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5436 label='log.changeset changeset.%s' % p.phasestr())
5440 label='log.changeset changeset.%s' % p.phasestr())
5437 ui.write(' '.join(p.tags()), label='log.tag')
5441 ui.write(' '.join(p.tags()), label='log.tag')
5438 if p.bookmarks():
5442 if p.bookmarks():
5439 marks.extend(p.bookmarks())
5443 marks.extend(p.bookmarks())
5440 if p.rev() == -1:
5444 if p.rev() == -1:
5441 if not len(repo):
5445 if not len(repo):
5442 ui.write(_(' (empty repository)'))
5446 ui.write(_(' (empty repository)'))
5443 else:
5447 else:
5444 ui.write(_(' (no revision checked out)'))
5448 ui.write(_(' (no revision checked out)'))
5445 ui.write('\n')
5449 ui.write('\n')
5446 if p.description():
5450 if p.description():
5447 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5451 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5448 label='log.summary')
5452 label='log.summary')
5449
5453
5450 branch = ctx.branch()
5454 branch = ctx.branch()
5451 bheads = repo.branchheads(branch)
5455 bheads = repo.branchheads(branch)
5452 # i18n: column positioning for "hg summary"
5456 # i18n: column positioning for "hg summary"
5453 m = _('branch: %s\n') % branch
5457 m = _('branch: %s\n') % branch
5454 if branch != 'default':
5458 if branch != 'default':
5455 ui.write(m, label='log.branch')
5459 ui.write(m, label='log.branch')
5456 else:
5460 else:
5457 ui.status(m, label='log.branch')
5461 ui.status(m, label='log.branch')
5458
5462
5459 if marks:
5463 if marks:
5460 current = repo._bookmarkcurrent
5464 current = repo._bookmarkcurrent
5461 # i18n: column positioning for "hg summary"
5465 # i18n: column positioning for "hg summary"
5462 ui.write(_('bookmarks:'), label='log.bookmark')
5466 ui.write(_('bookmarks:'), label='log.bookmark')
5463 if current is not None:
5467 if current is not None:
5464 if current in marks:
5468 if current in marks:
5465 ui.write(' *' + current, label='bookmarks.current')
5469 ui.write(' *' + current, label='bookmarks.current')
5466 marks.remove(current)
5470 marks.remove(current)
5467 else:
5471 else:
5468 ui.write(' [%s]' % current, label='bookmarks.current')
5472 ui.write(' [%s]' % current, label='bookmarks.current')
5469 for m in marks:
5473 for m in marks:
5470 ui.write(' ' + m, label='log.bookmark')
5474 ui.write(' ' + m, label='log.bookmark')
5471 ui.write('\n', label='log.bookmark')
5475 ui.write('\n', label='log.bookmark')
5472
5476
5473 st = list(repo.status(unknown=True))[:6]
5477 st = list(repo.status(unknown=True))[:6]
5474
5478
5475 c = repo.dirstate.copies()
5479 c = repo.dirstate.copies()
5476 copied, renamed = [], []
5480 copied, renamed = [], []
5477 for d, s in c.iteritems():
5481 for d, s in c.iteritems():
5478 if s in st[2]:
5482 if s in st[2]:
5479 st[2].remove(s)
5483 st[2].remove(s)
5480 renamed.append(d)
5484 renamed.append(d)
5481 else:
5485 else:
5482 copied.append(d)
5486 copied.append(d)
5483 if d in st[1]:
5487 if d in st[1]:
5484 st[1].remove(d)
5488 st[1].remove(d)
5485 st.insert(3, renamed)
5489 st.insert(3, renamed)
5486 st.insert(4, copied)
5490 st.insert(4, copied)
5487
5491
5488 ms = mergemod.mergestate(repo)
5492 ms = mergemod.mergestate(repo)
5489 st.append([f for f in ms if ms[f] == 'u'])
5493 st.append([f for f in ms if ms[f] == 'u'])
5490
5494
5491 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5495 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5492 st.append(subs)
5496 st.append(subs)
5493
5497
5494 labels = [ui.label(_('%d modified'), 'status.modified'),
5498 labels = [ui.label(_('%d modified'), 'status.modified'),
5495 ui.label(_('%d added'), 'status.added'),
5499 ui.label(_('%d added'), 'status.added'),
5496 ui.label(_('%d removed'), 'status.removed'),
5500 ui.label(_('%d removed'), 'status.removed'),
5497 ui.label(_('%d renamed'), 'status.copied'),
5501 ui.label(_('%d renamed'), 'status.copied'),
5498 ui.label(_('%d copied'), 'status.copied'),
5502 ui.label(_('%d copied'), 'status.copied'),
5499 ui.label(_('%d deleted'), 'status.deleted'),
5503 ui.label(_('%d deleted'), 'status.deleted'),
5500 ui.label(_('%d unknown'), 'status.unknown'),
5504 ui.label(_('%d unknown'), 'status.unknown'),
5501 ui.label(_('%d ignored'), 'status.ignored'),
5505 ui.label(_('%d ignored'), 'status.ignored'),
5502 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5506 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5503 ui.label(_('%d subrepos'), 'status.modified')]
5507 ui.label(_('%d subrepos'), 'status.modified')]
5504 t = []
5508 t = []
5505 for s, l in zip(st, labels):
5509 for s, l in zip(st, labels):
5506 if s:
5510 if s:
5507 t.append(l % len(s))
5511 t.append(l % len(s))
5508
5512
5509 t = ', '.join(t)
5513 t = ', '.join(t)
5510 cleanworkdir = False
5514 cleanworkdir = False
5511
5515
5512 if repo.vfs.exists('updatestate'):
5516 if repo.vfs.exists('updatestate'):
5513 t += _(' (interrupted update)')
5517 t += _(' (interrupted update)')
5514 elif len(parents) > 1:
5518 elif len(parents) > 1:
5515 t += _(' (merge)')
5519 t += _(' (merge)')
5516 elif branch != parents[0].branch():
5520 elif branch != parents[0].branch():
5517 t += _(' (new branch)')
5521 t += _(' (new branch)')
5518 elif (parents[0].closesbranch() and
5522 elif (parents[0].closesbranch() and
5519 pnode in repo.branchheads(branch, closed=True)):
5523 pnode in repo.branchheads(branch, closed=True)):
5520 t += _(' (head closed)')
5524 t += _(' (head closed)')
5521 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5525 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5522 t += _(' (clean)')
5526 t += _(' (clean)')
5523 cleanworkdir = True
5527 cleanworkdir = True
5524 elif pnode not in bheads:
5528 elif pnode not in bheads:
5525 t += _(' (new branch head)')
5529 t += _(' (new branch head)')
5526
5530
5527 if cleanworkdir:
5531 if cleanworkdir:
5528 # i18n: column positioning for "hg summary"
5532 # i18n: column positioning for "hg summary"
5529 ui.status(_('commit: %s\n') % t.strip())
5533 ui.status(_('commit: %s\n') % t.strip())
5530 else:
5534 else:
5531 # i18n: column positioning for "hg summary"
5535 # i18n: column positioning for "hg summary"
5532 ui.write(_('commit: %s\n') % t.strip())
5536 ui.write(_('commit: %s\n') % t.strip())
5533
5537
5534 # all ancestors of branch heads - all ancestors of parent = new csets
5538 # all ancestors of branch heads - all ancestors of parent = new csets
5535 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5539 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5536 bheads))
5540 bheads))
5537
5541
5538 if new == 0:
5542 if new == 0:
5539 # i18n: column positioning for "hg summary"
5543 # i18n: column positioning for "hg summary"
5540 ui.status(_('update: (current)\n'))
5544 ui.status(_('update: (current)\n'))
5541 elif pnode not in bheads:
5545 elif pnode not in bheads:
5542 # i18n: column positioning for "hg summary"
5546 # i18n: column positioning for "hg summary"
5543 ui.write(_('update: %d new changesets (update)\n') % new)
5547 ui.write(_('update: %d new changesets (update)\n') % new)
5544 else:
5548 else:
5545 # i18n: column positioning for "hg summary"
5549 # i18n: column positioning for "hg summary"
5546 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5550 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5547 (new, len(bheads)))
5551 (new, len(bheads)))
5548
5552
5549 cmdutil.summaryhooks(ui, repo)
5553 cmdutil.summaryhooks(ui, repo)
5550
5554
5551 if opts.get('remote'):
5555 if opts.get('remote'):
5552 t = []
5556 t = []
5553 source, branches = hg.parseurl(ui.expandpath('default'))
5557 source, branches = hg.parseurl(ui.expandpath('default'))
5554 sbranch = branches[0]
5558 sbranch = branches[0]
5555 other = hg.peer(repo, {}, source)
5559 other = hg.peer(repo, {}, source)
5556 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5560 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5557 if revs:
5561 if revs:
5558 revs = [other.lookup(rev) for rev in revs]
5562 revs = [other.lookup(rev) for rev in revs]
5559 ui.debug('comparing with %s\n' % util.hidepassword(source))
5563 ui.debug('comparing with %s\n' % util.hidepassword(source))
5560 repo.ui.pushbuffer()
5564 repo.ui.pushbuffer()
5561 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5565 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5562 _common, incoming, _rheads = commoninc
5566 _common, incoming, _rheads = commoninc
5563 repo.ui.popbuffer()
5567 repo.ui.popbuffer()
5564 if incoming:
5568 if incoming:
5565 t.append(_('1 or more incoming'))
5569 t.append(_('1 or more incoming'))
5566
5570
5567 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5571 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5568 dbranch = branches[0]
5572 dbranch = branches[0]
5569 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5573 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5570 if source != dest:
5574 if source != dest:
5571 other = hg.peer(repo, {}, dest)
5575 other = hg.peer(repo, {}, dest)
5572 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5576 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5573 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5577 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5574 commoninc = None
5578 commoninc = None
5575 if revs:
5579 if revs:
5576 revs = [repo.lookup(rev) for rev in revs]
5580 revs = [repo.lookup(rev) for rev in revs]
5577 repo.ui.pushbuffer()
5581 repo.ui.pushbuffer()
5578 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5582 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5579 commoninc=commoninc)
5583 commoninc=commoninc)
5580 repo.ui.popbuffer()
5584 repo.ui.popbuffer()
5581 o = outgoing.missing
5585 o = outgoing.missing
5582 if o:
5586 if o:
5583 t.append(_('%d outgoing') % len(o))
5587 t.append(_('%d outgoing') % len(o))
5584 if 'bookmarks' in other.listkeys('namespaces'):
5588 if 'bookmarks' in other.listkeys('namespaces'):
5585 lmarks = repo.listkeys('bookmarks')
5589 lmarks = repo.listkeys('bookmarks')
5586 rmarks = other.listkeys('bookmarks')
5590 rmarks = other.listkeys('bookmarks')
5587 diff = set(rmarks) - set(lmarks)
5591 diff = set(rmarks) - set(lmarks)
5588 if len(diff) > 0:
5592 if len(diff) > 0:
5589 t.append(_('%d incoming bookmarks') % len(diff))
5593 t.append(_('%d incoming bookmarks') % len(diff))
5590 diff = set(lmarks) - set(rmarks)
5594 diff = set(lmarks) - set(rmarks)
5591 if len(diff) > 0:
5595 if len(diff) > 0:
5592 t.append(_('%d outgoing bookmarks') % len(diff))
5596 t.append(_('%d outgoing bookmarks') % len(diff))
5593
5597
5594 if t:
5598 if t:
5595 # i18n: column positioning for "hg summary"
5599 # i18n: column positioning for "hg summary"
5596 ui.write(_('remote: %s\n') % (', '.join(t)))
5600 ui.write(_('remote: %s\n') % (', '.join(t)))
5597 else:
5601 else:
5598 # i18n: column positioning for "hg summary"
5602 # i18n: column positioning for "hg summary"
5599 ui.status(_('remote: (synced)\n'))
5603 ui.status(_('remote: (synced)\n'))
5600
5604
5601 @command('tag',
5605 @command('tag',
5602 [('f', 'force', None, _('force tag')),
5606 [('f', 'force', None, _('force tag')),
5603 ('l', 'local', None, _('make the tag local')),
5607 ('l', 'local', None, _('make the tag local')),
5604 ('r', 'rev', '', _('revision to tag'), _('REV')),
5608 ('r', 'rev', '', _('revision to tag'), _('REV')),
5605 ('', 'remove', None, _('remove a tag')),
5609 ('', 'remove', None, _('remove a tag')),
5606 # -l/--local is already there, commitopts cannot be used
5610 # -l/--local is already there, commitopts cannot be used
5607 ('e', 'edit', None, _('edit commit message')),
5611 ('e', 'edit', None, _('edit commit message')),
5608 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5612 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5609 ] + commitopts2,
5613 ] + commitopts2,
5610 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5614 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5611 def tag(ui, repo, name1, *names, **opts):
5615 def tag(ui, repo, name1, *names, **opts):
5612 """add one or more tags for the current or given revision
5616 """add one or more tags for the current or given revision
5613
5617
5614 Name a particular revision using <name>.
5618 Name a particular revision using <name>.
5615
5619
5616 Tags are used to name particular revisions of the repository and are
5620 Tags are used to name particular revisions of the repository and are
5617 very useful to compare different revisions, to go back to significant
5621 very useful to compare different revisions, to go back to significant
5618 earlier versions or to mark branch points as releases, etc. Changing
5622 earlier versions or to mark branch points as releases, etc. Changing
5619 an existing tag is normally disallowed; use -f/--force to override.
5623 an existing tag is normally disallowed; use -f/--force to override.
5620
5624
5621 If no revision is given, the parent of the working directory is
5625 If no revision is given, the parent of the working directory is
5622 used.
5626 used.
5623
5627
5624 To facilitate version control, distribution, and merging of tags,
5628 To facilitate version control, distribution, and merging of tags,
5625 they are stored as a file named ".hgtags" which is managed similarly
5629 they are stored as a file named ".hgtags" which is managed similarly
5626 to other project files and can be hand-edited if necessary. This
5630 to other project files and can be hand-edited if necessary. This
5627 also means that tagging creates a new commit. The file
5631 also means that tagging creates a new commit. The file
5628 ".hg/localtags" is used for local tags (not shared among
5632 ".hg/localtags" is used for local tags (not shared among
5629 repositories).
5633 repositories).
5630
5634
5631 Tag commits are usually made at the head of a branch. If the parent
5635 Tag commits are usually made at the head of a branch. If the parent
5632 of the working directory is not a branch head, :hg:`tag` aborts; use
5636 of the working directory is not a branch head, :hg:`tag` aborts; use
5633 -f/--force to force the tag commit to be based on a non-head
5637 -f/--force to force the tag commit to be based on a non-head
5634 changeset.
5638 changeset.
5635
5639
5636 See :hg:`help dates` for a list of formats valid for -d/--date.
5640 See :hg:`help dates` for a list of formats valid for -d/--date.
5637
5641
5638 Since tag names have priority over branch names during revision
5642 Since tag names have priority over branch names during revision
5639 lookup, using an existing branch name as a tag name is discouraged.
5643 lookup, using an existing branch name as a tag name is discouraged.
5640
5644
5641 Returns 0 on success.
5645 Returns 0 on success.
5642 """
5646 """
5643 wlock = lock = None
5647 wlock = lock = None
5644 try:
5648 try:
5645 wlock = repo.wlock()
5649 wlock = repo.wlock()
5646 lock = repo.lock()
5650 lock = repo.lock()
5647 rev_ = "."
5651 rev_ = "."
5648 names = [t.strip() for t in (name1,) + names]
5652 names = [t.strip() for t in (name1,) + names]
5649 if len(names) != len(set(names)):
5653 if len(names) != len(set(names)):
5650 raise util.Abort(_('tag names must be unique'))
5654 raise util.Abort(_('tag names must be unique'))
5651 for n in names:
5655 for n in names:
5652 scmutil.checknewlabel(repo, n, 'tag')
5656 scmutil.checknewlabel(repo, n, 'tag')
5653 if not n:
5657 if not n:
5654 raise util.Abort(_('tag names cannot consist entirely of '
5658 raise util.Abort(_('tag names cannot consist entirely of '
5655 'whitespace'))
5659 'whitespace'))
5656 if opts.get('rev') and opts.get('remove'):
5660 if opts.get('rev') and opts.get('remove'):
5657 raise util.Abort(_("--rev and --remove are incompatible"))
5661 raise util.Abort(_("--rev and --remove are incompatible"))
5658 if opts.get('rev'):
5662 if opts.get('rev'):
5659 rev_ = opts['rev']
5663 rev_ = opts['rev']
5660 message = opts.get('message')
5664 message = opts.get('message')
5661 if opts.get('remove'):
5665 if opts.get('remove'):
5662 expectedtype = opts.get('local') and 'local' or 'global'
5666 expectedtype = opts.get('local') and 'local' or 'global'
5663 for n in names:
5667 for n in names:
5664 if not repo.tagtype(n):
5668 if not repo.tagtype(n):
5665 raise util.Abort(_("tag '%s' does not exist") % n)
5669 raise util.Abort(_("tag '%s' does not exist") % n)
5666 if repo.tagtype(n) != expectedtype:
5670 if repo.tagtype(n) != expectedtype:
5667 if expectedtype == 'global':
5671 if expectedtype == 'global':
5668 raise util.Abort(_("tag '%s' is not a global tag") % n)
5672 raise util.Abort(_("tag '%s' is not a global tag") % n)
5669 else:
5673 else:
5670 raise util.Abort(_("tag '%s' is not a local tag") % n)
5674 raise util.Abort(_("tag '%s' is not a local tag") % n)
5671 rev_ = nullid
5675 rev_ = nullid
5672 if not message:
5676 if not message:
5673 # we don't translate commit messages
5677 # we don't translate commit messages
5674 message = 'Removed tag %s' % ', '.join(names)
5678 message = 'Removed tag %s' % ', '.join(names)
5675 elif not opts.get('force'):
5679 elif not opts.get('force'):
5676 for n in names:
5680 for n in names:
5677 if n in repo.tags():
5681 if n in repo.tags():
5678 raise util.Abort(_("tag '%s' already exists "
5682 raise util.Abort(_("tag '%s' already exists "
5679 "(use -f to force)") % n)
5683 "(use -f to force)") % n)
5680 if not opts.get('local'):
5684 if not opts.get('local'):
5681 p1, p2 = repo.dirstate.parents()
5685 p1, p2 = repo.dirstate.parents()
5682 if p2 != nullid:
5686 if p2 != nullid:
5683 raise util.Abort(_('uncommitted merge'))
5687 raise util.Abort(_('uncommitted merge'))
5684 bheads = repo.branchheads()
5688 bheads = repo.branchheads()
5685 if not opts.get('force') and bheads and p1 not in bheads:
5689 if not opts.get('force') and bheads and p1 not in bheads:
5686 raise util.Abort(_('not at a branch head (use -f to force)'))
5690 raise util.Abort(_('not at a branch head (use -f to force)'))
5687 r = scmutil.revsingle(repo, rev_).node()
5691 r = scmutil.revsingle(repo, rev_).node()
5688
5692
5689 if not message:
5693 if not message:
5690 # we don't translate commit messages
5694 # we don't translate commit messages
5691 message = ('Added tag %s for changeset %s' %
5695 message = ('Added tag %s for changeset %s' %
5692 (', '.join(names), short(r)))
5696 (', '.join(names), short(r)))
5693
5697
5694 date = opts.get('date')
5698 date = opts.get('date')
5695 if date:
5699 if date:
5696 date = util.parsedate(date)
5700 date = util.parsedate(date)
5697
5701
5698 if opts.get('edit'):
5702 if opts.get('edit'):
5699 message = ui.edit(message, ui.username())
5703 message = ui.edit(message, ui.username())
5700 repo.savecommitmessage(message)
5704 repo.savecommitmessage(message)
5701
5705
5702 # don't allow tagging the null rev
5706 # don't allow tagging the null rev
5703 if (not opts.get('remove') and
5707 if (not opts.get('remove') and
5704 scmutil.revsingle(repo, rev_).rev() == nullrev):
5708 scmutil.revsingle(repo, rev_).rev() == nullrev):
5705 raise util.Abort(_("cannot tag null revision"))
5709 raise util.Abort(_("cannot tag null revision"))
5706
5710
5707 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5711 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5708 finally:
5712 finally:
5709 release(lock, wlock)
5713 release(lock, wlock)
5710
5714
5711 @command('tags', [], '')
5715 @command('tags', [], '')
5712 def tags(ui, repo, **opts):
5716 def tags(ui, repo, **opts):
5713 """list repository tags
5717 """list repository tags
5714
5718
5715 This lists both regular and local tags. When the -v/--verbose
5719 This lists both regular and local tags. When the -v/--verbose
5716 switch is used, a third column "local" is printed for local tags.
5720 switch is used, a third column "local" is printed for local tags.
5717
5721
5718 Returns 0 on success.
5722 Returns 0 on success.
5719 """
5723 """
5720
5724
5721 fm = ui.formatter('tags', opts)
5725 fm = ui.formatter('tags', opts)
5722 hexfunc = ui.debugflag and hex or short
5726 hexfunc = ui.debugflag and hex or short
5723 tagtype = ""
5727 tagtype = ""
5724
5728
5725 for t, n in reversed(repo.tagslist()):
5729 for t, n in reversed(repo.tagslist()):
5726 hn = hexfunc(n)
5730 hn = hexfunc(n)
5727 label = 'tags.normal'
5731 label = 'tags.normal'
5728 tagtype = ''
5732 tagtype = ''
5729 if repo.tagtype(t) == 'local':
5733 if repo.tagtype(t) == 'local':
5730 label = 'tags.local'
5734 label = 'tags.local'
5731 tagtype = 'local'
5735 tagtype = 'local'
5732
5736
5733 fm.startitem()
5737 fm.startitem()
5734 fm.write('tag', '%s', t, label=label)
5738 fm.write('tag', '%s', t, label=label)
5735 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5739 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5736 fm.condwrite(not ui.quiet, 'rev id', fmt,
5740 fm.condwrite(not ui.quiet, 'rev id', fmt,
5737 repo.changelog.rev(n), hn, label=label)
5741 repo.changelog.rev(n), hn, label=label)
5738 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5742 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5739 tagtype, label=label)
5743 tagtype, label=label)
5740 fm.plain('\n')
5744 fm.plain('\n')
5741 fm.end()
5745 fm.end()
5742
5746
5743 @command('tip',
5747 @command('tip',
5744 [('p', 'patch', None, _('show patch')),
5748 [('p', 'patch', None, _('show patch')),
5745 ('g', 'git', None, _('use git extended diff format')),
5749 ('g', 'git', None, _('use git extended diff format')),
5746 ] + templateopts,
5750 ] + templateopts,
5747 _('[-p] [-g]'))
5751 _('[-p] [-g]'))
5748 def tip(ui, repo, **opts):
5752 def tip(ui, repo, **opts):
5749 """show the tip revision (DEPRECATED)
5753 """show the tip revision (DEPRECATED)
5750
5754
5751 The tip revision (usually just called the tip) is the changeset
5755 The tip revision (usually just called the tip) is the changeset
5752 most recently added to the repository (and therefore the most
5756 most recently added to the repository (and therefore the most
5753 recently changed head).
5757 recently changed head).
5754
5758
5755 If you have just made a commit, that commit will be the tip. If
5759 If you have just made a commit, that commit will be the tip. If
5756 you have just pulled changes from another repository, the tip of
5760 you have just pulled changes from another repository, the tip of
5757 that repository becomes the current tip. The "tip" tag is special
5761 that repository becomes the current tip. The "tip" tag is special
5758 and cannot be renamed or assigned to a different changeset.
5762 and cannot be renamed or assigned to a different changeset.
5759
5763
5760 This command is deprecated, please use :hg:`heads` instead.
5764 This command is deprecated, please use :hg:`heads` instead.
5761
5765
5762 Returns 0 on success.
5766 Returns 0 on success.
5763 """
5767 """
5764 displayer = cmdutil.show_changeset(ui, repo, opts)
5768 displayer = cmdutil.show_changeset(ui, repo, opts)
5765 displayer.show(repo['tip'])
5769 displayer.show(repo['tip'])
5766 displayer.close()
5770 displayer.close()
5767
5771
5768 @command('unbundle',
5772 @command('unbundle',
5769 [('u', 'update', None,
5773 [('u', 'update', None,
5770 _('update to new branch head if changesets were unbundled'))],
5774 _('update to new branch head if changesets were unbundled'))],
5771 _('[-u] FILE...'))
5775 _('[-u] FILE...'))
5772 def unbundle(ui, repo, fname1, *fnames, **opts):
5776 def unbundle(ui, repo, fname1, *fnames, **opts):
5773 """apply one or more changegroup files
5777 """apply one or more changegroup files
5774
5778
5775 Apply one or more compressed changegroup files generated by the
5779 Apply one or more compressed changegroup files generated by the
5776 bundle command.
5780 bundle command.
5777
5781
5778 Returns 0 on success, 1 if an update has unresolved files.
5782 Returns 0 on success, 1 if an update has unresolved files.
5779 """
5783 """
5780 fnames = (fname1,) + fnames
5784 fnames = (fname1,) + fnames
5781
5785
5782 lock = repo.lock()
5786 lock = repo.lock()
5783 wc = repo['.']
5787 wc = repo['.']
5784 try:
5788 try:
5785 for fname in fnames:
5789 for fname in fnames:
5786 f = hg.openpath(ui, fname)
5790 f = hg.openpath(ui, fname)
5787 gen = changegroup.readbundle(f, fname)
5791 gen = changegroup.readbundle(f, fname)
5788 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5792 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5789 finally:
5793 finally:
5790 lock.release()
5794 lock.release()
5791 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5795 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5792 return postincoming(ui, repo, modheads, opts.get('update'), None)
5796 return postincoming(ui, repo, modheads, opts.get('update'), None)
5793
5797
5794 @command('^update|up|checkout|co',
5798 @command('^update|up|checkout|co',
5795 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5799 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5796 ('c', 'check', None,
5800 ('c', 'check', None,
5797 _('update across branches if no uncommitted changes')),
5801 _('update across branches if no uncommitted changes')),
5798 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5802 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5799 ('r', 'rev', '', _('revision'), _('REV'))],
5803 ('r', 'rev', '', _('revision'), _('REV'))],
5800 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5804 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5801 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5805 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5802 """update working directory (or switch revisions)
5806 """update working directory (or switch revisions)
5803
5807
5804 Update the repository's working directory to the specified
5808 Update the repository's working directory to the specified
5805 changeset. If no changeset is specified, update to the tip of the
5809 changeset. If no changeset is specified, update to the tip of the
5806 current named branch and move the current bookmark (see :hg:`help
5810 current named branch and move the current bookmark (see :hg:`help
5807 bookmarks`).
5811 bookmarks`).
5808
5812
5809 Update sets the working directory's parent revision to the specified
5813 Update sets the working directory's parent revision to the specified
5810 changeset (see :hg:`help parents`).
5814 changeset (see :hg:`help parents`).
5811
5815
5812 If the changeset is not a descendant or ancestor of the working
5816 If the changeset is not a descendant or ancestor of the working
5813 directory's parent, the update is aborted. With the -c/--check
5817 directory's parent, the update is aborted. With the -c/--check
5814 option, the working directory is checked for uncommitted changes; if
5818 option, the working directory is checked for uncommitted changes; if
5815 none are found, the working directory is updated to the specified
5819 none are found, the working directory is updated to the specified
5816 changeset.
5820 changeset.
5817
5821
5818 .. container:: verbose
5822 .. container:: verbose
5819
5823
5820 The following rules apply when the working directory contains
5824 The following rules apply when the working directory contains
5821 uncommitted changes:
5825 uncommitted changes:
5822
5826
5823 1. If neither -c/--check nor -C/--clean is specified, and if
5827 1. If neither -c/--check nor -C/--clean is specified, and if
5824 the requested changeset is an ancestor or descendant of
5828 the requested changeset is an ancestor or descendant of
5825 the working directory's parent, the uncommitted changes
5829 the working directory's parent, the uncommitted changes
5826 are merged into the requested changeset and the merged
5830 are merged into the requested changeset and the merged
5827 result is left uncommitted. If the requested changeset is
5831 result is left uncommitted. If the requested changeset is
5828 not an ancestor or descendant (that is, it is on another
5832 not an ancestor or descendant (that is, it is on another
5829 branch), the update is aborted and the uncommitted changes
5833 branch), the update is aborted and the uncommitted changes
5830 are preserved.
5834 are preserved.
5831
5835
5832 2. With the -c/--check option, the update is aborted and the
5836 2. With the -c/--check option, the update is aborted and the
5833 uncommitted changes are preserved.
5837 uncommitted changes are preserved.
5834
5838
5835 3. With the -C/--clean option, uncommitted changes are discarded and
5839 3. With the -C/--clean option, uncommitted changes are discarded and
5836 the working directory is updated to the requested changeset.
5840 the working directory is updated to the requested changeset.
5837
5841
5838 To cancel an uncommitted merge (and lose your changes), use
5842 To cancel an uncommitted merge (and lose your changes), use
5839 :hg:`update --clean .`.
5843 :hg:`update --clean .`.
5840
5844
5841 Use null as the changeset to remove the working directory (like
5845 Use null as the changeset to remove the working directory (like
5842 :hg:`clone -U`).
5846 :hg:`clone -U`).
5843
5847
5844 If you want to revert just one file to an older revision, use
5848 If you want to revert just one file to an older revision, use
5845 :hg:`revert [-r REV] NAME`.
5849 :hg:`revert [-r REV] NAME`.
5846
5850
5847 See :hg:`help dates` for a list of formats valid for -d/--date.
5851 See :hg:`help dates` for a list of formats valid for -d/--date.
5848
5852
5849 Returns 0 on success, 1 if there are unresolved files.
5853 Returns 0 on success, 1 if there are unresolved files.
5850 """
5854 """
5851 if rev and node:
5855 if rev and node:
5852 raise util.Abort(_("please specify just one revision"))
5856 raise util.Abort(_("please specify just one revision"))
5853
5857
5854 if rev is None or rev == '':
5858 if rev is None or rev == '':
5855 rev = node
5859 rev = node
5856
5860
5857 cmdutil.clearunfinished(repo)
5861 cmdutil.clearunfinished(repo)
5858
5862
5859 # with no argument, we also move the current bookmark, if any
5863 # with no argument, we also move the current bookmark, if any
5860 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5864 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5861
5865
5862 # if we defined a bookmark, we have to remember the original bookmark name
5866 # if we defined a bookmark, we have to remember the original bookmark name
5863 brev = rev
5867 brev = rev
5864 rev = scmutil.revsingle(repo, rev, rev).rev()
5868 rev = scmutil.revsingle(repo, rev, rev).rev()
5865
5869
5866 if check and clean:
5870 if check and clean:
5867 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5871 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5868
5872
5869 if date:
5873 if date:
5870 if rev is not None:
5874 if rev is not None:
5871 raise util.Abort(_("you can't specify a revision and a date"))
5875 raise util.Abort(_("you can't specify a revision and a date"))
5872 rev = cmdutil.finddate(ui, repo, date)
5876 rev = cmdutil.finddate(ui, repo, date)
5873
5877
5874 if check:
5878 if check:
5875 c = repo[None]
5879 c = repo[None]
5876 if c.dirty(merge=False, branch=False, missing=True):
5880 if c.dirty(merge=False, branch=False, missing=True):
5877 raise util.Abort(_("uncommitted changes"))
5881 raise util.Abort(_("uncommitted changes"))
5878 if rev is None:
5882 if rev is None:
5879 rev = repo[repo[None].branch()].rev()
5883 rev = repo[repo[None].branch()].rev()
5880 mergemod._checkunknown(repo, repo[None], repo[rev])
5884 mergemod._checkunknown(repo, repo[None], repo[rev])
5881
5885
5882 if clean:
5886 if clean:
5883 ret = hg.clean(repo, rev)
5887 ret = hg.clean(repo, rev)
5884 else:
5888 else:
5885 ret = hg.update(repo, rev)
5889 ret = hg.update(repo, rev)
5886
5890
5887 if not ret and movemarkfrom:
5891 if not ret and movemarkfrom:
5888 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5892 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5889 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5893 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5890 elif brev in repo._bookmarks:
5894 elif brev in repo._bookmarks:
5891 bookmarks.setcurrent(repo, brev)
5895 bookmarks.setcurrent(repo, brev)
5892 elif brev:
5896 elif brev:
5893 bookmarks.unsetcurrent(repo)
5897 bookmarks.unsetcurrent(repo)
5894
5898
5895 return ret
5899 return ret
5896
5900
5897 @command('verify', [])
5901 @command('verify', [])
5898 def verify(ui, repo):
5902 def verify(ui, repo):
5899 """verify the integrity of the repository
5903 """verify the integrity of the repository
5900
5904
5901 Verify the integrity of the current repository.
5905 Verify the integrity of the current repository.
5902
5906
5903 This will perform an extensive check of the repository's
5907 This will perform an extensive check of the repository's
5904 integrity, validating the hashes and checksums of each entry in
5908 integrity, validating the hashes and checksums of each entry in
5905 the changelog, manifest, and tracked files, as well as the
5909 the changelog, manifest, and tracked files, as well as the
5906 integrity of their crosslinks and indices.
5910 integrity of their crosslinks and indices.
5907
5911
5908 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5912 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5909 for more information about recovery from corruption of the
5913 for more information about recovery from corruption of the
5910 repository.
5914 repository.
5911
5915
5912 Returns 0 on success, 1 if errors are encountered.
5916 Returns 0 on success, 1 if errors are encountered.
5913 """
5917 """
5914 return hg.verify(repo)
5918 return hg.verify(repo)
5915
5919
5916 @command('version', [])
5920 @command('version', [])
5917 def version_(ui):
5921 def version_(ui):
5918 """output version and copyright information"""
5922 """output version and copyright information"""
5919 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5923 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5920 % util.version())
5924 % util.version())
5921 ui.status(_(
5925 ui.status(_(
5922 "(see http://mercurial.selenic.com for more information)\n"
5926 "(see http://mercurial.selenic.com for more information)\n"
5923 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5927 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5924 "This is free software; see the source for copying conditions. "
5928 "This is free software; see the source for copying conditions. "
5925 "There is NO\nwarranty; "
5929 "There is NO\nwarranty; "
5926 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5930 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5927 ))
5931 ))
5928
5932
5929 norepo = ("clone init version help debugcommands debugcomplete"
5933 norepo = ("clone init version help debugcommands debugcomplete"
5930 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5934 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5931 " debugknown debuggetbundle debugbundle")
5935 " debugknown debuggetbundle debugbundle")
5932 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5936 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5933 " debugdata debugindex debugindexdot debugrevlog")
5937 " debugdata debugindex debugindexdot debugrevlog")
5934 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5938 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5935 " remove resolve status debugwalk")
5939 " remove resolve status debugwalk")
@@ -1,500 +1,516 b''
1 $ hg init basic
1 $ hg init basic
2 $ cd basic
2 $ cd basic
3
3
4 should complain
4 should complain
5
5
6 $ hg backout
6 $ hg backout
7 abort: please specify a revision to backout
7 abort: please specify a revision to backout
8 [255]
8 [255]
9 $ hg backout -r 0 0
9 $ hg backout -r 0 0
10 abort: please specify just one revision
10 abort: please specify just one revision
11 [255]
11 [255]
12
12
13 basic operation
13 basic operation
14
14
15 $ echo a > a
15 $ echo a > a
16 $ hg commit -d '0 0' -A -m a
16 $ hg commit -d '0 0' -A -m a
17 adding a
17 adding a
18 $ echo b >> a
18 $ echo b >> a
19 $ hg commit -d '1 0' -m b
19 $ hg commit -d '1 0' -m b
20
20
21 $ hg backout -d '2 0' tip --tool=true
21 $ hg backout -d '2 0' tip --tool=true
22 reverting a
22 reverting a
23 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
23 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
24 $ cat a
24 $ cat a
25 a
25 a
26 $ hg summary
26 $ hg summary
27 parent: 2:2929462c3dff tip
27 parent: 2:2929462c3dff tip
28 Backed out changeset a820f4f40a57
28 Backed out changeset a820f4f40a57
29 branch: default
29 branch: default
30 commit: (clean)
30 commit: (clean)
31 update: (current)
31 update: (current)
32
32
33 file that was removed is recreated
33 file that was removed is recreated
34
34
35 $ cd ..
35 $ cd ..
36 $ hg init remove
36 $ hg init remove
37 $ cd remove
37 $ cd remove
38
38
39 $ echo content > a
39 $ echo content > a
40 $ hg commit -d '0 0' -A -m a
40 $ hg commit -d '0 0' -A -m a
41 adding a
41 adding a
42
42
43 $ hg rm a
43 $ hg rm a
44 $ hg commit -d '1 0' -m b
44 $ hg commit -d '1 0' -m b
45
45
46 $ hg backout -d '2 0' tip --tool=true
46 $ hg backout -d '2 0' tip --tool=true
47 adding a
47 adding a
48 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
48 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
49 $ cat a
49 $ cat a
50 content
50 content
51 $ hg summary
51 $ hg summary
52 parent: 2:de31bdc76c0d tip
52 parent: 2:de31bdc76c0d tip
53 Backed out changeset 76862dcce372
53 Backed out changeset 76862dcce372
54 branch: default
54 branch: default
55 commit: (clean)
55 commit: (clean)
56 update: (current)
56 update: (current)
57
57
58 backout of backout is as if nothing happened
58 backout of backout is as if nothing happened
59
59
60 $ hg backout -d '3 0' --merge tip --tool=true
60 $ hg backout -d '3 0' --merge tip --tool=true
61 removing a
61 removing a
62 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
62 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
63 $ test -f a
63 $ test -f a
64 [1]
64 [1]
65 $ hg summary
65 $ hg summary
66 parent: 3:7f6d0f120113 tip
66 parent: 3:7f6d0f120113 tip
67 Backed out changeset de31bdc76c0d
67 Backed out changeset de31bdc76c0d
68 branch: default
68 branch: default
69 commit: (clean)
69 commit: (clean)
70 update: (current)
70 update: (current)
71
71
72 across branch
72 across branch
73
73
74 $ cd ..
74 $ cd ..
75 $ hg init branch
75 $ hg init branch
76 $ cd branch
76 $ cd branch
77 $ echo a > a
77 $ echo a > a
78 $ hg ci -Am0
78 $ hg ci -Am0
79 adding a
79 adding a
80 $ echo b > b
80 $ echo b > b
81 $ hg ci -Am1
81 $ hg ci -Am1
82 adding b
82 adding b
83 $ hg co -C 0
83 $ hg co -C 0
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
85 $ hg summary
85 $ hg summary
86 parent: 0:f7b1eb17ad24
86 parent: 0:f7b1eb17ad24
87 0
87 0
88 branch: default
88 branch: default
89 commit: (clean)
89 commit: (clean)
90 update: 1 new changesets (update)
90 update: 1 new changesets (update)
91
91
92 should fail
92 should fail
93
93
94 $ hg backout 1
94 $ hg backout 1
95 abort: cannot backout change on a different branch
95 abort: cannot backout change on a different branch
96 [255]
96 [255]
97 $ echo c > c
97 $ echo c > c
98 $ hg ci -Am2
98 $ hg ci -Am2
99 adding c
99 adding c
100 created new head
100 created new head
101 $ hg summary
101 $ hg summary
102 parent: 2:db815d6d32e6 tip
102 parent: 2:db815d6d32e6 tip
103 2
103 2
104 branch: default
104 branch: default
105 commit: (clean)
105 commit: (clean)
106 update: 1 new changesets, 2 branch heads (merge)
106 update: 1 new changesets, 2 branch heads (merge)
107
107
108 should fail
108 should fail
109
109
110 $ hg backout 1
110 $ hg backout 1
111 abort: cannot backout change on a different branch
111 abort: cannot backout change on a different branch
112 [255]
112 [255]
113 $ hg summary
113 $ hg summary
114 parent: 2:db815d6d32e6 tip
114 parent: 2:db815d6d32e6 tip
115 2
115 2
116 branch: default
116 branch: default
117 commit: (clean)
117 commit: (clean)
118 update: 1 new changesets, 2 branch heads (merge)
118 update: 1 new changesets, 2 branch heads (merge)
119
119
120 backout with merge
120 backout with merge
121
121
122 $ cd ..
122 $ cd ..
123 $ hg init merge
123 $ hg init merge
124 $ cd merge
124 $ cd merge
125
125
126 $ echo line 1 > a
126 $ echo line 1 > a
127 $ echo line 2 >> a
127 $ echo line 2 >> a
128 $ hg commit -d '0 0' -A -m a
128 $ hg commit -d '0 0' -A -m a
129 adding a
129 adding a
130 $ hg summary
130 $ hg summary
131 parent: 0:59395513a13a tip
131 parent: 0:59395513a13a tip
132 a
132 a
133 branch: default
133 branch: default
134 commit: (clean)
134 commit: (clean)
135 update: (current)
135 update: (current)
136
136
137 remove line 1
137 remove line 1
138
138
139 $ echo line 2 > a
139 $ echo line 2 > a
140 $ hg commit -d '1 0' -m b
140 $ hg commit -d '1 0' -m b
141
141
142 $ echo line 3 >> a
142 $ echo line 3 >> a
143 $ hg commit -d '2 0' -m c
143 $ hg commit -d '2 0' -m c
144
144
145 $ hg backout --merge -d '3 0' 1 --tool=true
145 $ hg backout --merge -d '3 0' 1 --tool=true
146 reverting a
146 reverting a
147 created new head
147 created new head
148 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
148 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
149 merging with changeset 3:26b8ccb9ad91
149 merging with changeset 3:26b8ccb9ad91
150 merging a
150 merging a
151 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
151 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
152 (branch merge, don't forget to commit)
152 (branch merge, don't forget to commit)
153 $ hg commit -d '4 0' -m d
153 $ hg commit -d '4 0' -m d
154 $ hg summary
154 $ hg summary
155 parent: 4:c7df5e0b9c09 tip
155 parent: 4:c7df5e0b9c09 tip
156 d
156 d
157 branch: default
157 branch: default
158 commit: (clean)
158 commit: (clean)
159 update: (current)
159 update: (current)
160
160
161 check line 1 is back
161 check line 1 is back
162
162
163 $ cat a
163 $ cat a
164 line 1
164 line 1
165 line 2
165 line 2
166 line 3
166 line 3
167
167
168 $ cd ..
168 $ cd ..
169
169
170 backout should not back out subsequent changesets
170 backout should not back out subsequent changesets
171
171
172 $ hg init onecs
172 $ hg init onecs
173 $ cd onecs
173 $ cd onecs
174 $ echo 1 > a
174 $ echo 1 > a
175 $ hg commit -d '0 0' -A -m a
175 $ hg commit -d '0 0' -A -m a
176 adding a
176 adding a
177 $ echo 2 >> a
177 $ echo 2 >> a
178 $ hg commit -d '1 0' -m b
178 $ hg commit -d '1 0' -m b
179 $ echo 1 > b
179 $ echo 1 > b
180 $ hg commit -d '2 0' -A -m c
180 $ hg commit -d '2 0' -A -m c
181 adding b
181 adding b
182 $ hg summary
182 $ hg summary
183 parent: 2:882396649954 tip
183 parent: 2:882396649954 tip
184 c
184 c
185 branch: default
185 branch: default
186 commit: (clean)
186 commit: (clean)
187 update: (current)
187 update: (current)
188
188
189 without --merge
189 without --merge
190 $ hg backout -d '3 0' 1 --tool=true
190 $ hg backout -d '3 0' 1 --tool=true
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 changeset 22bca4c721e5 backed out, don't forget to commit.
192 changeset 22bca4c721e5 backed out, don't forget to commit.
193 $ hg locate b
193 $ hg locate b
194 b
194 b
195 $ hg update -C tip
195 $ hg update -C tip
196 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
196 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 $ hg locate b
197 $ hg locate b
198 b
198 b
199 $ hg summary
199 $ hg summary
200 parent: 2:882396649954 tip
200 parent: 2:882396649954 tip
201 c
201 c
202 branch: default
202 branch: default
203 commit: (clean)
203 commit: (clean)
204 update: (current)
204 update: (current)
205
205
206 with --merge
206 with --merge
207 $ hg backout --merge -d '3 0' 1 --tool=true
207 $ hg backout --merge -d '3 0' 1 --tool=true
208 reverting a
208 reverting a
209 created new head
209 created new head
210 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
210 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
211 merging with changeset 3:3202beb76721
211 merging with changeset 3:3202beb76721
212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 (branch merge, don't forget to commit)
213 (branch merge, don't forget to commit)
214 $ hg locate b
214 $ hg locate b
215 b
215 b
216 $ hg update -C tip
216 $ hg update -C tip
217 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
217 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
218 $ hg locate b
218 $ hg locate b
219 [1]
219 [1]
220
220
221 $ cd ..
221 $ cd ..
222 $ hg init m
222 $ hg init m
223 $ cd m
223 $ cd m
224 $ echo a > a
224 $ echo a > a
225 $ hg commit -d '0 0' -A -m a
225 $ hg commit -d '0 0' -A -m a
226 adding a
226 adding a
227 $ echo b > b
227 $ echo b > b
228 $ hg commit -d '1 0' -A -m b
228 $ hg commit -d '1 0' -A -m b
229 adding b
229 adding b
230 $ echo c > c
230 $ echo c > c
231 $ hg commit -d '2 0' -A -m b
231 $ hg commit -d '2 0' -A -m b
232 adding c
232 adding c
233 $ hg update 1
233 $ hg update 1
234 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
234 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
235 $ echo d > d
235 $ echo d > d
236 $ hg commit -d '3 0' -A -m c
236 $ hg commit -d '3 0' -A -m c
237 adding d
237 adding d
238 created new head
238 created new head
239 $ hg merge 2
239 $ hg merge 2
240 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
240 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
241 (branch merge, don't forget to commit)
241 (branch merge, don't forget to commit)
242 $ hg commit -d '4 0' -A -m d
242 $ hg commit -d '4 0' -A -m d
243 $ hg summary
243 $ hg summary
244 parent: 4:b2f3bb92043e tip
244 parent: 4:b2f3bb92043e tip
245 d
245 d
246 branch: default
246 branch: default
247 commit: (clean)
247 commit: (clean)
248 update: (current)
248 update: (current)
249
249
250 backout of merge should fail
250 backout of merge should fail
251
251
252 $ hg backout 4
252 $ hg backout 4
253 abort: cannot backout a merge changeset
253 abort: cannot backout a merge changeset
254 [255]
254 [255]
255
255
256 backout of merge with bad parent should fail
256 backout of merge with bad parent should fail
257
257
258 $ hg backout --parent 0 4
258 $ hg backout --parent 0 4
259 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
259 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
260 [255]
260 [255]
261
261
262 backout of non-merge with parent should fail
262 backout of non-merge with parent should fail
263
263
264 $ hg backout --parent 0 3
264 $ hg backout --parent 0 3
265 abort: cannot use --parent on non-merge changeset
265 abort: cannot use --parent on non-merge changeset
266 [255]
266 [255]
267
267
268 backout with valid parent should be ok
268 backout with valid parent should be ok
269
269
270 $ hg backout -d '5 0' --parent 2 4 --tool=true
270 $ hg backout -d '5 0' --parent 2 4 --tool=true
271 removing d
271 removing d
272 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
272 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
273 $ hg summary
273 $ hg summary
274 parent: 5:10e5328c8435 tip
274 parent: 5:10e5328c8435 tip
275 Backed out changeset b2f3bb92043e
275 Backed out changeset b2f3bb92043e
276 branch: default
276 branch: default
277 commit: (clean)
277 commit: (clean)
278 update: (current)
278 update: (current)
279
279
280 $ hg rollback
280 $ hg rollback
281 repository tip rolled back to revision 4 (undo commit)
281 repository tip rolled back to revision 4 (undo commit)
282 working directory now based on revision 4
282 working directory now based on revision 4
283 $ hg update -C
283 $ hg update -C
284 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 $ hg summary
285 $ hg summary
286 parent: 4:b2f3bb92043e tip
286 parent: 4:b2f3bb92043e tip
287 d
287 d
288 branch: default
288 branch: default
289 commit: (clean)
289 commit: (clean)
290 update: (current)
290 update: (current)
291
291
292 $ hg backout -d '6 0' --parent 3 4 --tool=true
292 $ hg backout -d '6 0' --parent 3 4 --tool=true
293 removing c
293 removing c
294 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
294 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
295 $ hg summary
295 $ hg summary
296 parent: 5:033590168430 tip
296 parent: 5:033590168430 tip
297 Backed out changeset b2f3bb92043e
297 Backed out changeset b2f3bb92043e
298 branch: default
298 branch: default
299 commit: (clean)
299 commit: (clean)
300 update: (current)
300 update: (current)
301
301
302 $ cd ..
302 $ cd ..
303
303
304 named branches
304 named branches
305
305
306 $ hg init named_branches
306 $ hg init named_branches
307 $ cd named_branches
307 $ cd named_branches
308
308
309 $ echo default > default
309 $ echo default > default
310 $ hg ci -d '0 0' -Am default
310 $ hg ci -d '0 0' -Am default
311 adding default
311 adding default
312 $ hg branch branch1
312 $ hg branch branch1
313 marked working directory as branch branch1
313 marked working directory as branch branch1
314 (branches are permanent and global, did you want a bookmark?)
314 (branches are permanent and global, did you want a bookmark?)
315 $ echo branch1 > file1
315 $ echo branch1 > file1
316 $ hg ci -d '1 0' -Am file1
316 $ hg ci -d '1 0' -Am file1
317 adding file1
317 adding file1
318 $ hg branch branch2
318 $ hg branch branch2
319 marked working directory as branch branch2
319 marked working directory as branch branch2
320 (branches are permanent and global, did you want a bookmark?)
320 (branches are permanent and global, did you want a bookmark?)
321 $ echo branch2 > file2
321 $ echo branch2 > file2
322 $ hg ci -d '2 0' -Am file2
322 $ hg ci -d '2 0' -Am file2
323 adding file2
323 adding file2
324
324
325 without --merge
325 without --merge
326 $ hg backout -r 1 --tool=true
326 $ hg backout -r 1 --tool=true
327 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
327 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
328 changeset bf1602f437f3 backed out, don't forget to commit.
328 changeset bf1602f437f3 backed out, don't forget to commit.
329 $ hg branch
329 $ hg branch
330 branch2
330 branch2
331 $ hg status -A
331 $ hg status -A
332 R file1
332 R file1
333 C default
333 C default
334 C file2
334 C file2
335 $ hg summary
335 $ hg summary
336 parent: 2:45bbcd363bf0 tip
336 parent: 2:45bbcd363bf0 tip
337 file2
337 file2
338 branch: branch2
338 branch: branch2
339 commit: 1 removed
339 commit: 1 removed
340 update: (current)
340 update: (current)
341
341
342 with --merge
342 with --merge
343 $ hg update -qC
343 $ hg update -qC
344 $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true
344 $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true
345 removing file1
345 removing file1
346 created new head
346 created new head
347 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
347 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
348 merging with changeset 3:d4e8f6db59fb
348 merging with changeset 3:d4e8f6db59fb
349 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
349 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
350 (branch merge, don't forget to commit)
350 (branch merge, don't forget to commit)
351 $ hg summary
351 $ hg summary
352 parent: 2:45bbcd363bf0
352 parent: 2:45bbcd363bf0
353 file2
353 file2
354 parent: 3:d4e8f6db59fb tip
354 parent: 3:d4e8f6db59fb tip
355 backout on branch1
355 backout on branch1
356 branch: branch2
356 branch: branch2
357 commit: 1 removed (merge)
357 commit: 1 removed (merge)
358 update: (current)
358 update: (current)
359 $ hg update -q -C 2
359 $ hg update -q -C 2
360
360
361 on branch2 with branch1 not merged, so file1 should still exist:
361 on branch2 with branch1 not merged, so file1 should still exist:
362
362
363 $ hg id
363 $ hg id
364 45bbcd363bf0 (branch2)
364 45bbcd363bf0 (branch2)
365 $ hg st -A
365 $ hg st -A
366 C default
366 C default
367 C file1
367 C file1
368 C file2
368 C file2
369 $ hg summary
369 $ hg summary
370 parent: 2:45bbcd363bf0
370 parent: 2:45bbcd363bf0
371 file2
371 file2
372 branch: branch2
372 branch: branch2
373 commit: (clean)
373 commit: (clean)
374 update: 1 new changesets, 2 branch heads (merge)
374 update: 1 new changesets, 2 branch heads (merge)
375
375
376 on branch2 with branch1 merged, so file1 should be gone:
376 on branch2 with branch1 merged, so file1 should be gone:
377
377
378 $ hg merge
378 $ hg merge
379 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
379 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
380 (branch merge, don't forget to commit)
380 (branch merge, don't forget to commit)
381 $ hg ci -d '4 0' -m 'merge backout of branch1'
381 $ hg ci -d '4 0' -m 'merge backout of branch1'
382 $ hg id
382 $ hg id
383 22149cdde76d (branch2) tip
383 22149cdde76d (branch2) tip
384 $ hg st -A
384 $ hg st -A
385 C default
385 C default
386 C file2
386 C file2
387 $ hg summary
387 $ hg summary
388 parent: 4:22149cdde76d tip
388 parent: 4:22149cdde76d tip
389 merge backout of branch1
389 merge backout of branch1
390 branch: branch2
390 branch: branch2
391 commit: (clean)
391 commit: (clean)
392 update: (current)
392 update: (current)
393
393
394 on branch1, so no file1 and file2:
394 on branch1, so no file1 and file2:
395
395
396 $ hg co -C branch1
396 $ hg co -C branch1
397 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
397 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
398 $ hg id
398 $ hg id
399 bf1602f437f3 (branch1)
399 bf1602f437f3 (branch1)
400 $ hg st -A
400 $ hg st -A
401 C default
401 C default
402 C file1
402 C file1
403 $ hg summary
403 $ hg summary
404 parent: 1:bf1602f437f3
404 parent: 1:bf1602f437f3
405 file1
405 file1
406 branch: branch1
406 branch: branch1
407 commit: (clean)
407 commit: (clean)
408 update: (current)
408 update: (current)
409
409
410 $ cd ..
410 $ cd ..
411
411
412 backout of empty changeset (issue4190)
413
414 $ hg init emptycommit
415 $ cd emptycommit
416
417 $ touch file1
418 $ hg ci -Aqm file1
419 $ hg branch -q branch1
420 $ hg ci -qm branch1
421 $ hg backout -v 1
422 resolving manifests
423 nothing changed
424 [1]
425
426 $ cd ..
427
412
428
413 Test usage of `hg resolve` in case of conflict
429 Test usage of `hg resolve` in case of conflict
414 (issue4163)
430 (issue4163)
415
431
416 $ hg init issue4163
432 $ hg init issue4163
417 $ cd issue4163
433 $ cd issue4163
418 $ touch foo
434 $ touch foo
419 $ hg add foo
435 $ hg add foo
420 $ cat > foo << EOF
436 $ cat > foo << EOF
421 > one
437 > one
422 > two
438 > two
423 > three
439 > three
424 > four
440 > four
425 > five
441 > five
426 > six
442 > six
427 > seven
443 > seven
428 > height
444 > height
429 > nine
445 > nine
430 > ten
446 > ten
431 > EOF
447 > EOF
432 $ hg ci -m 'initial'
448 $ hg ci -m 'initial'
433 $ cat > foo << EOF
449 $ cat > foo << EOF
434 > one
450 > one
435 > two
451 > two
436 > THREE
452 > THREE
437 > four
453 > four
438 > five
454 > five
439 > six
455 > six
440 > seven
456 > seven
441 > height
457 > height
442 > nine
458 > nine
443 > ten
459 > ten
444 > EOF
460 > EOF
445 $ hg ci -m 'capital three'
461 $ hg ci -m 'capital three'
446 $ cat > foo << EOF
462 $ cat > foo << EOF
447 > one
463 > one
448 > two
464 > two
449 > THREE
465 > THREE
450 > four
466 > four
451 > five
467 > five
452 > six
468 > six
453 > seven
469 > seven
454 > height
470 > height
455 > nine
471 > nine
456 > TEN
472 > TEN
457 > EOF
473 > EOF
458 $ hg ci -m 'capital ten'
474 $ hg ci -m 'capital ten'
459 $ hg backout -r 'desc("capital three")' --tool internal:fail
475 $ hg backout -r 'desc("capital three")' --tool internal:fail
460 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
476 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
461 use 'hg resolve' to retry unresolved file merges
477 use 'hg resolve' to retry unresolved file merges
462 [1]
478 [1]
463 $ hg status
479 $ hg status
464 $ hg resolve -l # still unresolved
480 $ hg resolve -l # still unresolved
465 U foo
481 U foo
466 $ hg summary
482 $ hg summary
467 parent: 2:b71750c4b0fd tip
483 parent: 2:b71750c4b0fd tip
468 capital ten
484 capital ten
469 branch: default
485 branch: default
470 commit: 1 unresolved (clean)
486 commit: 1 unresolved (clean)
471 update: (current)
487 update: (current)
472 $ hg resolve --all --debug
488 $ hg resolve --all --debug
473 picked tool 'internal:merge' for foo (binary False symlink False)
489 picked tool 'internal:merge' for foo (binary False symlink False)
474 merging foo
490 merging foo
475 my foo@b71750c4b0fd+ other foo@a30dd8addae3 ancestor foo@913609522437
491 my foo@b71750c4b0fd+ other foo@a30dd8addae3 ancestor foo@913609522437
476 premerge successful
492 premerge successful
477 $ hg status
493 $ hg status
478 M foo
494 M foo
479 ? foo.orig
495 ? foo.orig
480 $ hg resolve -l
496 $ hg resolve -l
481 R foo
497 R foo
482 $ hg summary
498 $ hg summary
483 parent: 2:b71750c4b0fd tip
499 parent: 2:b71750c4b0fd tip
484 capital ten
500 capital ten
485 branch: default
501 branch: default
486 commit: 1 modified, 1 unknown
502 commit: 1 modified, 1 unknown
487 update: (current)
503 update: (current)
488 $ cat foo
504 $ cat foo
489 one
505 one
490 two
506 two
491 three
507 three
492 four
508 four
493 five
509 five
494 six
510 six
495 seven
511 seven
496 height
512 height
497 nine
513 nine
498 TEN
514 TEN
499
515
500
516
General Comments 0
You need to be logged in to leave comments. Login now