##// END OF EJS Templates
graft: make skip messages more helpful...
Mads Kiilerich -
r19893:dc4edca3 default
parent child Browse files
Show More
@@ -1,5911 +1,5912
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, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
21 import phases, obsolete
21 import phases, obsolete
22
22
23 table = {}
23 table = {}
24
24
25 command = cmdutil.command(table)
25 command = cmdutil.command(table)
26
26
27 # common command options
27 # common command options
28
28
29 globalopts = [
29 globalopts = [
30 ('R', 'repository', '',
30 ('R', 'repository', '',
31 _('repository root directory or name of overlay bundle file'),
31 _('repository root directory or name of overlay bundle file'),
32 _('REPO')),
32 _('REPO')),
33 ('', 'cwd', '',
33 ('', 'cwd', '',
34 _('change working directory'), _('DIR')),
34 _('change working directory'), _('DIR')),
35 ('y', 'noninteractive', None,
35 ('y', 'noninteractive', None,
36 _('do not prompt, automatically pick the first choice for all prompts')),
36 _('do not prompt, automatically pick the first choice for all prompts')),
37 ('q', 'quiet', None, _('suppress output')),
37 ('q', 'quiet', None, _('suppress output')),
38 ('v', 'verbose', None, _('enable additional output')),
38 ('v', 'verbose', None, _('enable additional output')),
39 ('', 'config', [],
39 ('', 'config', [],
40 _('set/override config option (use \'section.name=value\')'),
40 _('set/override config option (use \'section.name=value\')'),
41 _('CONFIG')),
41 _('CONFIG')),
42 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debugger', None, _('start debugger')),
43 ('', 'debugger', None, _('start debugger')),
44 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 _('ENCODE')),
45 _('ENCODE')),
46 ('', 'encodingmode', encoding.encodingmode,
46 ('', 'encodingmode', encoding.encodingmode,
47 _('set the charset encoding mode'), _('MODE')),
47 _('set the charset encoding mode'), _('MODE')),
48 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'time', None, _('time how long the command takes')),
49 ('', 'time', None, _('time how long the command takes')),
50 ('', 'profile', None, _('print command execution profile')),
50 ('', 'profile', None, _('print command execution profile')),
51 ('', 'version', None, _('output version information and exit')),
51 ('', 'version', None, _('output version information and exit')),
52 ('h', 'help', None, _('display help and exit')),
52 ('h', 'help', None, _('display help and exit')),
53 ('', 'hidden', False, _('consider hidden changesets')),
53 ('', 'hidden', False, _('consider hidden changesets')),
54 ]
54 ]
55
55
56 dryrunopts = [('n', 'dry-run', None,
56 dryrunopts = [('n', 'dry-run', None,
57 _('do not perform actions, just print output'))]
57 _('do not perform actions, just print output'))]
58
58
59 remoteopts = [
59 remoteopts = [
60 ('e', 'ssh', '',
60 ('e', 'ssh', '',
61 _('specify ssh command to use'), _('CMD')),
61 _('specify ssh command to use'), _('CMD')),
62 ('', 'remotecmd', '',
62 ('', 'remotecmd', '',
63 _('specify hg command to run on the remote side'), _('CMD')),
63 _('specify hg command to run on the remote side'), _('CMD')),
64 ('', 'insecure', None,
64 ('', 'insecure', None,
65 _('do not verify server certificate (ignoring web.cacerts config)')),
65 _('do not verify server certificate (ignoring web.cacerts config)')),
66 ]
66 ]
67
67
68 walkopts = [
68 walkopts = [
69 ('I', 'include', [],
69 ('I', 'include', [],
70 _('include names matching the given patterns'), _('PATTERN')),
70 _('include names matching the given patterns'), _('PATTERN')),
71 ('X', 'exclude', [],
71 ('X', 'exclude', [],
72 _('exclude names matching the given patterns'), _('PATTERN')),
72 _('exclude names matching the given patterns'), _('PATTERN')),
73 ]
73 ]
74
74
75 commitopts = [
75 commitopts = [
76 ('m', 'message', '',
76 ('m', 'message', '',
77 _('use text as commit message'), _('TEXT')),
77 _('use text as commit message'), _('TEXT')),
78 ('l', 'logfile', '',
78 ('l', 'logfile', '',
79 _('read commit message from file'), _('FILE')),
79 _('read commit message from file'), _('FILE')),
80 ]
80 ]
81
81
82 commitopts2 = [
82 commitopts2 = [
83 ('d', 'date', '',
83 ('d', 'date', '',
84 _('record the specified date as commit date'), _('DATE')),
84 _('record the specified date as commit date'), _('DATE')),
85 ('u', 'user', '',
85 ('u', 'user', '',
86 _('record the specified user as committer'), _('USER')),
86 _('record the specified user as committer'), _('USER')),
87 ]
87 ]
88
88
89 templateopts = [
89 templateopts = [
90 ('', 'style', '',
90 ('', 'style', '',
91 _('display using template map file'), _('STYLE')),
91 _('display using template map file'), _('STYLE')),
92 ('', 'template', '',
92 ('', 'template', '',
93 _('display with template'), _('TEMPLATE')),
93 _('display with template'), _('TEMPLATE')),
94 ]
94 ]
95
95
96 logopts = [
96 logopts = [
97 ('p', 'patch', None, _('show patch')),
97 ('p', 'patch', None, _('show patch')),
98 ('g', 'git', None, _('use git extended diff format')),
98 ('g', 'git', None, _('use git extended diff format')),
99 ('l', 'limit', '',
99 ('l', 'limit', '',
100 _('limit number of changes displayed'), _('NUM')),
100 _('limit number of changes displayed'), _('NUM')),
101 ('M', 'no-merges', None, _('do not show merges')),
101 ('M', 'no-merges', None, _('do not show merges')),
102 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('', 'stat', None, _('output diffstat-style summary of changes')),
103 ('G', 'graph', None, _("show the revision DAG")),
103 ('G', 'graph', None, _("show the revision DAG")),
104 ] + templateopts
104 ] + templateopts
105
105
106 diffopts = [
106 diffopts = [
107 ('a', 'text', None, _('treat all files as text')),
107 ('a', 'text', None, _('treat all files as text')),
108 ('g', 'git', None, _('use git extended diff format')),
108 ('g', 'git', None, _('use git extended diff format')),
109 ('', 'nodates', None, _('omit dates from diff headers'))
109 ('', 'nodates', None, _('omit dates from diff headers'))
110 ]
110 ]
111
111
112 diffwsopts = [
112 diffwsopts = [
113 ('w', 'ignore-all-space', None,
113 ('w', 'ignore-all-space', None,
114 _('ignore white space when comparing lines')),
114 _('ignore white space when comparing lines')),
115 ('b', 'ignore-space-change', None,
115 ('b', 'ignore-space-change', None,
116 _('ignore changes in the amount of white space')),
116 _('ignore changes in the amount of white space')),
117 ('B', 'ignore-blank-lines', None,
117 ('B', 'ignore-blank-lines', None,
118 _('ignore changes whose lines are all blank')),
118 _('ignore changes whose lines are all blank')),
119 ]
119 ]
120
120
121 diffopts2 = [
121 diffopts2 = [
122 ('p', 'show-function', None, _('show which function each change is in')),
122 ('p', 'show-function', None, _('show which function each change is in')),
123 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ('', 'reverse', None, _('produce a diff that undoes the changes')),
124 ] + diffwsopts + [
124 ] + diffwsopts + [
125 ('U', 'unified', '',
125 ('U', 'unified', '',
126 _('number of lines of context to show'), _('NUM')),
126 _('number of lines of context to show'), _('NUM')),
127 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ('', 'stat', None, _('output diffstat-style summary of changes')),
128 ]
128 ]
129
129
130 mergetoolopts = [
130 mergetoolopts = [
131 ('t', 'tool', '', _('specify merge tool')),
131 ('t', 'tool', '', _('specify merge tool')),
132 ]
132 ]
133
133
134 similarityopts = [
134 similarityopts = [
135 ('s', 'similarity', '',
135 ('s', 'similarity', '',
136 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
137 ]
137 ]
138
138
139 subrepoopts = [
139 subrepoopts = [
140 ('S', 'subrepos', None,
140 ('S', 'subrepos', None,
141 _('recurse into subrepositories'))
141 _('recurse into subrepositories'))
142 ]
142 ]
143
143
144 # Commands start here, listed alphabetically
144 # Commands start here, listed alphabetically
145
145
146 @command('^add',
146 @command('^add',
147 walkopts + subrepoopts + dryrunopts,
147 walkopts + subrepoopts + dryrunopts,
148 _('[OPTION]... [FILE]...'))
148 _('[OPTION]... [FILE]...'))
149 def add(ui, repo, *pats, **opts):
149 def add(ui, repo, *pats, **opts):
150 """add the specified files on the next commit
150 """add the specified files on the next commit
151
151
152 Schedule files to be version controlled and added to the
152 Schedule files to be version controlled and added to the
153 repository.
153 repository.
154
154
155 The files will be added to the repository at the next commit. To
155 The files will be added to the repository at the next commit. To
156 undo an add before that, see :hg:`forget`.
156 undo an add before that, see :hg:`forget`.
157
157
158 If no names are given, add all files to the repository.
158 If no names are given, add all files to the repository.
159
159
160 .. container:: verbose
160 .. container:: verbose
161
161
162 An example showing how new (unknown) files are added
162 An example showing how new (unknown) files are added
163 automatically by :hg:`add`::
163 automatically by :hg:`add`::
164
164
165 $ ls
165 $ ls
166 foo.c
166 foo.c
167 $ hg status
167 $ hg status
168 ? foo.c
168 ? foo.c
169 $ hg add
169 $ hg add
170 adding foo.c
170 adding foo.c
171 $ hg status
171 $ hg status
172 A foo.c
172 A foo.c
173
173
174 Returns 0 if all files are successfully added.
174 Returns 0 if all files are successfully added.
175 """
175 """
176
176
177 m = scmutil.match(repo[None], pats, opts)
177 m = scmutil.match(repo[None], pats, opts)
178 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
179 opts.get('subrepos'), prefix="", explicitonly=False)
179 opts.get('subrepos'), prefix="", explicitonly=False)
180 return rejected and 1 or 0
180 return rejected and 1 or 0
181
181
182 @command('addremove',
182 @command('addremove',
183 similarityopts + walkopts + dryrunopts,
183 similarityopts + walkopts + dryrunopts,
184 _('[OPTION]... [FILE]...'))
184 _('[OPTION]... [FILE]...'))
185 def addremove(ui, repo, *pats, **opts):
185 def addremove(ui, repo, *pats, **opts):
186 """add all new files, delete all missing files
186 """add all new files, delete all missing files
187
187
188 Add all new files and remove all missing files from the
188 Add all new files and remove all missing files from the
189 repository.
189 repository.
190
190
191 New files are ignored if they match any of the patterns in
191 New files are ignored if they match any of the patterns in
192 ``.hgignore``. As with add, these changes take effect at the next
192 ``.hgignore``. As with add, these changes take effect at the next
193 commit.
193 commit.
194
194
195 Use the -s/--similarity option to detect renamed files. This
195 Use the -s/--similarity option to detect renamed files. This
196 option takes a percentage between 0 (disabled) and 100 (files must
196 option takes a percentage between 0 (disabled) and 100 (files must
197 be identical) as its parameter. With a parameter greater than 0,
197 be identical) as its parameter. With a parameter greater than 0,
198 this compares every removed file with every added file and records
198 this compares every removed file with every added file and records
199 those similar enough as renames. Detecting renamed files this way
199 those similar enough as renames. Detecting renamed files this way
200 can be expensive. After using this option, :hg:`status -C` can be
200 can be expensive. After using this option, :hg:`status -C` can be
201 used to check which files were identified as moved or renamed. If
201 used to check which files were identified as moved or renamed. If
202 not specified, -s/--similarity defaults to 100 and only renames of
202 not specified, -s/--similarity defaults to 100 and only renames of
203 identical files are detected.
203 identical files are detected.
204
204
205 Returns 0 if all files are successfully added.
205 Returns 0 if all files are successfully added.
206 """
206 """
207 try:
207 try:
208 sim = float(opts.get('similarity') or 100)
208 sim = float(opts.get('similarity') or 100)
209 except ValueError:
209 except ValueError:
210 raise util.Abort(_('similarity must be a number'))
210 raise util.Abort(_('similarity must be a number'))
211 if sim < 0 or sim > 100:
211 if sim < 0 or sim > 100:
212 raise util.Abort(_('similarity must be between 0 and 100'))
212 raise util.Abort(_('similarity must be between 0 and 100'))
213 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
214
214
215 @command('^annotate|blame',
215 @command('^annotate|blame',
216 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
217 ('', 'follow', None,
217 ('', 'follow', None,
218 _('follow copies/renames and list the filename (DEPRECATED)')),
218 _('follow copies/renames and list the filename (DEPRECATED)')),
219 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('', 'no-follow', None, _("don't follow copies and renames")),
220 ('a', 'text', None, _('treat all files as text')),
220 ('a', 'text', None, _('treat all files as text')),
221 ('u', 'user', None, _('list the author (long with -v)')),
221 ('u', 'user', None, _('list the author (long with -v)')),
222 ('f', 'file', None, _('list the filename')),
222 ('f', 'file', None, _('list the filename')),
223 ('d', 'date', None, _('list the date (short with -q)')),
223 ('d', 'date', None, _('list the date (short with -q)')),
224 ('n', 'number', None, _('list the revision number (default)')),
224 ('n', 'number', None, _('list the revision number (default)')),
225 ('c', 'changeset', None, _('list the changeset')),
225 ('c', 'changeset', None, _('list the changeset')),
226 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ('l', 'line-number', None, _('show line number at the first appearance'))
227 ] + diffwsopts + walkopts,
227 ] + diffwsopts + walkopts,
228 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
229 def annotate(ui, repo, *pats, **opts):
229 def annotate(ui, repo, *pats, **opts):
230 """show changeset information by line for each file
230 """show changeset information by line for each file
231
231
232 List changes in files, showing the revision id responsible for
232 List changes in files, showing the revision id responsible for
233 each line
233 each line
234
234
235 This command is useful for discovering when a change was made and
235 This command is useful for discovering when a change was made and
236 by whom.
236 by whom.
237
237
238 Without the -a/--text option, annotate will avoid processing files
238 Without the -a/--text option, annotate will avoid processing files
239 it detects as binary. With -a, annotate will annotate the file
239 it detects as binary. With -a, annotate will annotate the file
240 anyway, although the results will probably be neither useful
240 anyway, although the results will probably be neither useful
241 nor desirable.
241 nor desirable.
242
242
243 Returns 0 on success.
243 Returns 0 on success.
244 """
244 """
245 if opts.get('follow'):
245 if opts.get('follow'):
246 # --follow is deprecated and now just an alias for -f/--file
246 # --follow is deprecated and now just an alias for -f/--file
247 # to mimic the behavior of Mercurial before version 1.5
247 # to mimic the behavior of Mercurial before version 1.5
248 opts['file'] = True
248 opts['file'] = True
249
249
250 datefunc = ui.quiet and util.shortdate or util.datestr
250 datefunc = ui.quiet and util.shortdate or util.datestr
251 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
252
252
253 if not pats:
253 if not pats:
254 raise util.Abort(_('at least one filename or pattern is required'))
254 raise util.Abort(_('at least one filename or pattern is required'))
255
255
256 hexfn = ui.debugflag and hex or short
256 hexfn = ui.debugflag and hex or short
257
257
258 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
259 ('number', ' ', lambda x: str(x[0].rev())),
259 ('number', ' ', lambda x: str(x[0].rev())),
260 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('changeset', ' ', lambda x: hexfn(x[0].node())),
261 ('date', ' ', getdate),
261 ('date', ' ', getdate),
262 ('file', ' ', lambda x: x[0].path()),
262 ('file', ' ', lambda x: x[0].path()),
263 ('line_number', ':', lambda x: str(x[1])),
263 ('line_number', ':', lambda x: str(x[1])),
264 ]
264 ]
265
265
266 if (not opts.get('user') and not opts.get('changeset')
266 if (not opts.get('user') and not opts.get('changeset')
267 and not opts.get('date') and not opts.get('file')):
267 and not opts.get('date') and not opts.get('file')):
268 opts['number'] = True
268 opts['number'] = True
269
269
270 linenumber = opts.get('line_number') is not None
270 linenumber = opts.get('line_number') is not None
271 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
272 raise util.Abort(_('at least one of -n/-c is required for -l'))
272 raise util.Abort(_('at least one of -n/-c is required for -l'))
273
273
274 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
275 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
276
276
277 def bad(x, y):
277 def bad(x, y):
278 raise util.Abort("%s: %s" % (x, y))
278 raise util.Abort("%s: %s" % (x, y))
279
279
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
281 m = scmutil.match(ctx, pats, opts)
281 m = scmutil.match(ctx, pats, opts)
282 m.bad = bad
282 m.bad = bad
283 follow = not opts.get('no_follow')
283 follow = not opts.get('no_follow')
284 diffopts = patch.diffopts(ui, opts, section='annotate')
284 diffopts = patch.diffopts(ui, opts, section='annotate')
285 for abs in ctx.walk(m):
285 for abs in ctx.walk(m):
286 fctx = ctx[abs]
286 fctx = ctx[abs]
287 if not opts.get('text') and util.binary(fctx.data()):
287 if not opts.get('text') and util.binary(fctx.data()):
288 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
289 continue
289 continue
290
290
291 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 lines = fctx.annotate(follow=follow, linenumber=linenumber,
292 diffopts=diffopts)
292 diffopts=diffopts)
293 pieces = []
293 pieces = []
294
294
295 for f, sep in funcmap:
295 for f, sep in funcmap:
296 l = [f(n) for n, dummy in lines]
296 l = [f(n) for n, dummy in lines]
297 if l:
297 if l:
298 sized = [(x, encoding.colwidth(x)) for x in l]
298 sized = [(x, encoding.colwidth(x)) for x in l]
299 ml = max([w for x, w in sized])
299 ml = max([w for x, w in sized])
300 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
301 for x, w in sized])
301 for x, w in sized])
302
302
303 if pieces:
303 if pieces:
304 for p, l in zip(zip(*pieces), lines):
304 for p, l in zip(zip(*pieces), lines):
305 ui.write("%s: %s" % ("".join(p), l[1]))
305 ui.write("%s: %s" % ("".join(p), l[1]))
306
306
307 if lines and not lines[-1][1].endswith('\n'):
307 if lines and not lines[-1][1].endswith('\n'):
308 ui.write('\n')
308 ui.write('\n')
309
309
310 @command('archive',
310 @command('archive',
311 [('', 'no-decode', None, _('do not pass files through decoders')),
311 [('', 'no-decode', None, _('do not pass files through decoders')),
312 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 ('p', 'prefix', '', _('directory prefix for files in archive'),
313 _('PREFIX')),
313 _('PREFIX')),
314 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('r', 'rev', '', _('revision to distribute'), _('REV')),
315 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
316 ] + subrepoopts + walkopts,
316 ] + subrepoopts + walkopts,
317 _('[OPTION]... DEST'))
317 _('[OPTION]... DEST'))
318 def archive(ui, repo, dest, **opts):
318 def archive(ui, repo, dest, **opts):
319 '''create an unversioned archive of a repository revision
319 '''create an unversioned archive of a repository revision
320
320
321 By default, the revision used is the parent of the working
321 By default, the revision used is the parent of the working
322 directory; use -r/--rev to specify a different revision.
322 directory; use -r/--rev to specify a different revision.
323
323
324 The archive type is automatically detected based on file
324 The archive type is automatically detected based on file
325 extension (or override using -t/--type).
325 extension (or override using -t/--type).
326
326
327 .. container:: verbose
327 .. container:: verbose
328
328
329 Examples:
329 Examples:
330
330
331 - create a zip file containing the 1.0 release::
331 - create a zip file containing the 1.0 release::
332
332
333 hg archive -r 1.0 project-1.0.zip
333 hg archive -r 1.0 project-1.0.zip
334
334
335 - create a tarball excluding .hg files::
335 - create a tarball excluding .hg files::
336
336
337 hg archive project.tar.gz -X ".hg*"
337 hg archive project.tar.gz -X ".hg*"
338
338
339 Valid types are:
339 Valid types are:
340
340
341 :``files``: a directory full of files (default)
341 :``files``: a directory full of files (default)
342 :``tar``: tar archive, uncompressed
342 :``tar``: tar archive, uncompressed
343 :``tbz2``: tar archive, compressed using bzip2
343 :``tbz2``: tar archive, compressed using bzip2
344 :``tgz``: tar archive, compressed using gzip
344 :``tgz``: tar archive, compressed using gzip
345 :``uzip``: zip archive, uncompressed
345 :``uzip``: zip archive, uncompressed
346 :``zip``: zip archive, compressed using deflate
346 :``zip``: zip archive, compressed using deflate
347
347
348 The exact name of the destination archive or directory is given
348 The exact name of the destination archive or directory is given
349 using a format string; see :hg:`help export` for details.
349 using a format string; see :hg:`help export` for details.
350
350
351 Each member added to an archive file has a directory prefix
351 Each member added to an archive file has a directory prefix
352 prepended. Use -p/--prefix to specify a format string for the
352 prepended. Use -p/--prefix to specify a format string for the
353 prefix. The default is the basename of the archive, with suffixes
353 prefix. The default is the basename of the archive, with suffixes
354 removed.
354 removed.
355
355
356 Returns 0 on success.
356 Returns 0 on success.
357 '''
357 '''
358
358
359 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 ctx = scmutil.revsingle(repo, opts.get('rev'))
360 if not ctx:
360 if not ctx:
361 raise util.Abort(_('no working directory: please specify a revision'))
361 raise util.Abort(_('no working directory: please specify a revision'))
362 node = ctx.node()
362 node = ctx.node()
363 dest = cmdutil.makefilename(repo, dest, node)
363 dest = cmdutil.makefilename(repo, dest, node)
364 if os.path.realpath(dest) == repo.root:
364 if os.path.realpath(dest) == repo.root:
365 raise util.Abort(_('repository root cannot be destination'))
365 raise util.Abort(_('repository root cannot be destination'))
366
366
367 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 kind = opts.get('type') or archival.guesskind(dest) or 'files'
368 prefix = opts.get('prefix')
368 prefix = opts.get('prefix')
369
369
370 if dest == '-':
370 if dest == '-':
371 if kind == 'files':
371 if kind == 'files':
372 raise util.Abort(_('cannot archive plain files to stdout'))
372 raise util.Abort(_('cannot archive plain files to stdout'))
373 dest = cmdutil.makefileobj(repo, dest)
373 dest = cmdutil.makefileobj(repo, dest)
374 if not prefix:
374 if not prefix:
375 prefix = os.path.basename(repo.root) + '-%h'
375 prefix = os.path.basename(repo.root) + '-%h'
376
376
377 prefix = cmdutil.makefilename(repo, prefix, node)
377 prefix = cmdutil.makefilename(repo, prefix, node)
378 matchfn = scmutil.match(ctx, [], opts)
378 matchfn = scmutil.match(ctx, [], opts)
379 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
380 matchfn, prefix, subrepos=opts.get('subrepos'))
380 matchfn, prefix, subrepos=opts.get('subrepos'))
381
381
382 @command('backout',
382 @command('backout',
383 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 [('', 'merge', None, _('merge with old dirstate parent after backout')),
384 ('', 'parent', '',
384 ('', 'parent', '',
385 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
386 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ('r', 'rev', '', _('revision to backout'), _('REV')),
387 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 ] + mergetoolopts + walkopts + commitopts + commitopts2,
388 _('[OPTION]... [-r] REV'))
388 _('[OPTION]... [-r] REV'))
389 def backout(ui, repo, node=None, rev=None, **opts):
389 def backout(ui, repo, node=None, rev=None, **opts):
390 '''reverse effect of earlier changeset
390 '''reverse effect of earlier changeset
391
391
392 Prepare a new changeset with the effect of REV undone in the
392 Prepare a new changeset with the effect of REV undone in the
393 current working directory.
393 current working directory.
394
394
395 If REV is the parent of the working directory, then this new changeset
395 If REV is the parent of the working directory, then this new changeset
396 is committed automatically. Otherwise, hg needs to merge the
396 is committed automatically. Otherwise, hg needs to merge the
397 changes and the merged result is left uncommitted.
397 changes and the merged result is left uncommitted.
398
398
399 .. note::
399 .. note::
400 backout cannot be used to fix either an unwanted or
400 backout cannot be used to fix either an unwanted or
401 incorrect merge.
401 incorrect merge.
402
402
403 .. container:: verbose
403 .. container:: verbose
404
404
405 By default, the pending changeset will have one parent,
405 By default, the pending changeset will have one parent,
406 maintaining a linear history. With --merge, the pending
406 maintaining a linear history. With --merge, the pending
407 changeset will instead have two parents: the old parent of the
407 changeset will instead have two parents: the old parent of the
408 working directory and a new child of REV that simply undoes REV.
408 working directory and a new child of REV that simply undoes REV.
409
409
410 Before version 1.7, the behavior without --merge was equivalent
410 Before version 1.7, the behavior without --merge was equivalent
411 to specifying --merge followed by :hg:`update --clean .` to
411 to specifying --merge followed by :hg:`update --clean .` to
412 cancel the merge and leave the child of REV as a head to be
412 cancel the merge and leave the child of REV as a head to be
413 merged separately.
413 merged separately.
414
414
415 See :hg:`help dates` for a list of formats valid for -d/--date.
415 See :hg:`help dates` for a list of formats valid for -d/--date.
416
416
417 Returns 0 on success.
417 Returns 0 on success.
418 '''
418 '''
419 if rev and node:
419 if rev and node:
420 raise util.Abort(_("please specify just one revision"))
420 raise util.Abort(_("please specify just one revision"))
421
421
422 if not rev:
422 if not rev:
423 rev = node
423 rev = node
424
424
425 if not rev:
425 if not rev:
426 raise util.Abort(_("please specify a revision to backout"))
426 raise util.Abort(_("please specify a revision to backout"))
427
427
428 date = opts.get('date')
428 date = opts.get('date')
429 if date:
429 if date:
430 opts['date'] = util.parsedate(date)
430 opts['date'] = util.parsedate(date)
431
431
432 cmdutil.checkunfinished(repo)
432 cmdutil.checkunfinished(repo)
433 cmdutil.bailifchanged(repo)
433 cmdutil.bailifchanged(repo)
434 node = scmutil.revsingle(repo, rev).node()
434 node = scmutil.revsingle(repo, rev).node()
435
435
436 op1, op2 = repo.dirstate.parents()
436 op1, op2 = repo.dirstate.parents()
437 a = repo.changelog.ancestor(op1, node)
437 a = repo.changelog.ancestor(op1, node)
438 if a != node:
438 if a != node:
439 raise util.Abort(_('cannot backout change on a different branch'))
439 raise util.Abort(_('cannot backout change on a different branch'))
440
440
441 p1, p2 = repo.changelog.parents(node)
441 p1, p2 = repo.changelog.parents(node)
442 if p1 == nullid:
442 if p1 == nullid:
443 raise util.Abort(_('cannot backout a change with no parents'))
443 raise util.Abort(_('cannot backout a change with no parents'))
444 if p2 != nullid:
444 if p2 != nullid:
445 if not opts.get('parent'):
445 if not opts.get('parent'):
446 raise util.Abort(_('cannot backout a merge changeset'))
446 raise util.Abort(_('cannot backout a merge changeset'))
447 p = repo.lookup(opts['parent'])
447 p = repo.lookup(opts['parent'])
448 if p not in (p1, p2):
448 if p not in (p1, p2):
449 raise util.Abort(_('%s is not a parent of %s') %
449 raise util.Abort(_('%s is not a parent of %s') %
450 (short(p), short(node)))
450 (short(p), short(node)))
451 parent = p
451 parent = p
452 else:
452 else:
453 if opts.get('parent'):
453 if opts.get('parent'):
454 raise util.Abort(_('cannot use --parent on non-merge changeset'))
454 raise util.Abort(_('cannot use --parent on non-merge changeset'))
455 parent = p1
455 parent = p1
456
456
457 # the backout should appear on the same branch
457 # the backout should appear on the same branch
458 wlock = repo.wlock()
458 wlock = repo.wlock()
459 try:
459 try:
460 branch = repo.dirstate.branch()
460 branch = repo.dirstate.branch()
461 bheads = repo.branchheads(branch)
461 bheads = repo.branchheads(branch)
462 hg.clean(repo, node, show_stats=False)
462 hg.clean(repo, node, show_stats=False)
463 repo.dirstate.setbranch(branch)
463 repo.dirstate.setbranch(branch)
464 rctx = scmutil.revsingle(repo, hex(parent))
464 rctx = scmutil.revsingle(repo, hex(parent))
465 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
465 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 return hg.update(repo, op1)
469 return hg.update(repo, op1)
470 finally:
470 finally:
471 ui.setconfig('ui', 'forcemerge', '')
471 ui.setconfig('ui', 'forcemerge', '')
472
472
473 e = cmdutil.commiteditor
473 e = cmdutil.commiteditor
474 if not opts['message'] and not opts['logfile']:
474 if not opts['message'] and not opts['logfile']:
475 # we don't translate commit messages
475 # we don't translate commit messages
476 opts['message'] = "Backed out changeset %s" % short(node)
476 opts['message'] = "Backed out changeset %s" % short(node)
477 e = cmdutil.commitforceeditor
477 e = cmdutil.commitforceeditor
478
478
479 def commitfunc(ui, repo, message, match, opts):
479 def commitfunc(ui, repo, message, match, opts):
480 return repo.commit(message, opts.get('user'), opts.get('date'),
480 return repo.commit(message, opts.get('user'), opts.get('date'),
481 match, editor=e)
481 match, editor=e)
482 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
482 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
483 cmdutil.commitstatus(repo, newnode, branch, bheads)
483 cmdutil.commitstatus(repo, newnode, branch, bheads)
484
484
485 def nice(node):
485 def nice(node):
486 return '%d:%s' % (repo.changelog.rev(node), short(node))
486 return '%d:%s' % (repo.changelog.rev(node), short(node))
487 ui.status(_('changeset %s backs out changeset %s\n') %
487 ui.status(_('changeset %s backs out changeset %s\n') %
488 (nice(repo.changelog.tip()), nice(node)))
488 (nice(repo.changelog.tip()), nice(node)))
489 if opts.get('merge') and op1 != node:
489 if opts.get('merge') and op1 != node:
490 hg.clean(repo, op1, show_stats=False)
490 hg.clean(repo, op1, show_stats=False)
491 ui.status(_('merging with changeset %s\n')
491 ui.status(_('merging with changeset %s\n')
492 % nice(repo.changelog.tip()))
492 % nice(repo.changelog.tip()))
493 try:
493 try:
494 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
494 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
495 return hg.merge(repo, hex(repo.changelog.tip()))
495 return hg.merge(repo, hex(repo.changelog.tip()))
496 finally:
496 finally:
497 ui.setconfig('ui', 'forcemerge', '')
497 ui.setconfig('ui', 'forcemerge', '')
498 finally:
498 finally:
499 wlock.release()
499 wlock.release()
500 return 0
500 return 0
501
501
502 @command('bisect',
502 @command('bisect',
503 [('r', 'reset', False, _('reset bisect state')),
503 [('r', 'reset', False, _('reset bisect state')),
504 ('g', 'good', False, _('mark changeset good')),
504 ('g', 'good', False, _('mark changeset good')),
505 ('b', 'bad', False, _('mark changeset bad')),
505 ('b', 'bad', False, _('mark changeset bad')),
506 ('s', 'skip', False, _('skip testing changeset')),
506 ('s', 'skip', False, _('skip testing changeset')),
507 ('e', 'extend', False, _('extend the bisect range')),
507 ('e', 'extend', False, _('extend the bisect range')),
508 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
508 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
509 ('U', 'noupdate', False, _('do not update to target'))],
509 ('U', 'noupdate', False, _('do not update to target'))],
510 _("[-gbsr] [-U] [-c CMD] [REV]"))
510 _("[-gbsr] [-U] [-c CMD] [REV]"))
511 def bisect(ui, repo, rev=None, extra=None, command=None,
511 def bisect(ui, repo, rev=None, extra=None, command=None,
512 reset=None, good=None, bad=None, skip=None, extend=None,
512 reset=None, good=None, bad=None, skip=None, extend=None,
513 noupdate=None):
513 noupdate=None):
514 """subdivision search of changesets
514 """subdivision search of changesets
515
515
516 This command helps to find changesets which introduce problems. To
516 This command helps to find changesets which introduce problems. To
517 use, mark the earliest changeset you know exhibits the problem as
517 use, mark the earliest changeset you know exhibits the problem as
518 bad, then mark the latest changeset which is free from the problem
518 bad, then mark the latest changeset which is free from the problem
519 as good. Bisect will update your working directory to a revision
519 as good. Bisect will update your working directory to a revision
520 for testing (unless the -U/--noupdate option is specified). Once
520 for testing (unless the -U/--noupdate option is specified). Once
521 you have performed tests, mark the working directory as good or
521 you have performed tests, mark the working directory as good or
522 bad, and bisect will either update to another candidate changeset
522 bad, and bisect will either update to another candidate changeset
523 or announce that it has found the bad revision.
523 or announce that it has found the bad revision.
524
524
525 As a shortcut, you can also use the revision argument to mark a
525 As a shortcut, you can also use the revision argument to mark a
526 revision as good or bad without checking it out first.
526 revision as good or bad without checking it out first.
527
527
528 If you supply a command, it will be used for automatic bisection.
528 If you supply a command, it will be used for automatic bisection.
529 The environment variable HG_NODE will contain the ID of the
529 The environment variable HG_NODE will contain the ID of the
530 changeset being tested. The exit status of the command will be
530 changeset being tested. The exit status of the command will be
531 used to mark revisions as good or bad: status 0 means good, 125
531 used to mark revisions as good or bad: status 0 means good, 125
532 means to skip the revision, 127 (command not found) will abort the
532 means to skip the revision, 127 (command not found) will abort the
533 bisection, and any other non-zero exit status means the revision
533 bisection, and any other non-zero exit status means the revision
534 is bad.
534 is bad.
535
535
536 .. container:: verbose
536 .. container:: verbose
537
537
538 Some examples:
538 Some examples:
539
539
540 - start a bisection with known bad revision 12, and good revision 34::
540 - start a bisection with known bad revision 12, and good revision 34::
541
541
542 hg bisect --bad 34
542 hg bisect --bad 34
543 hg bisect --good 12
543 hg bisect --good 12
544
544
545 - advance the current bisection by marking current revision as good or
545 - advance the current bisection by marking current revision as good or
546 bad::
546 bad::
547
547
548 hg bisect --good
548 hg bisect --good
549 hg bisect --bad
549 hg bisect --bad
550
550
551 - mark the current revision, or a known revision, to be skipped (e.g. if
551 - mark the current revision, or a known revision, to be skipped (e.g. if
552 that revision is not usable because of another issue)::
552 that revision is not usable because of another issue)::
553
553
554 hg bisect --skip
554 hg bisect --skip
555 hg bisect --skip 23
555 hg bisect --skip 23
556
556
557 - skip all revisions that do not touch directories ``foo`` or ``bar``
557 - skip all revisions that do not touch directories ``foo`` or ``bar``
558
558
559 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
559 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
560
560
561 - forget the current bisection::
561 - forget the current bisection::
562
562
563 hg bisect --reset
563 hg bisect --reset
564
564
565 - use 'make && make tests' to automatically find the first broken
565 - use 'make && make tests' to automatically find the first broken
566 revision::
566 revision::
567
567
568 hg bisect --reset
568 hg bisect --reset
569 hg bisect --bad 34
569 hg bisect --bad 34
570 hg bisect --good 12
570 hg bisect --good 12
571 hg bisect --command 'make && make tests'
571 hg bisect --command 'make && make tests'
572
572
573 - see all changesets whose states are already known in the current
573 - see all changesets whose states are already known in the current
574 bisection::
574 bisection::
575
575
576 hg log -r "bisect(pruned)"
576 hg log -r "bisect(pruned)"
577
577
578 - see the changeset currently being bisected (especially useful
578 - see the changeset currently being bisected (especially useful
579 if running with -U/--noupdate)::
579 if running with -U/--noupdate)::
580
580
581 hg log -r "bisect(current)"
581 hg log -r "bisect(current)"
582
582
583 - see all changesets that took part in the current bisection::
583 - see all changesets that took part in the current bisection::
584
584
585 hg log -r "bisect(range)"
585 hg log -r "bisect(range)"
586
586
587 - with the graphlog extension, you can even get a nice graph::
587 - with the graphlog extension, you can even get a nice graph::
588
588
589 hg log --graph -r "bisect(range)"
589 hg log --graph -r "bisect(range)"
590
590
591 See :hg:`help revsets` for more about the `bisect()` keyword.
591 See :hg:`help revsets` for more about the `bisect()` keyword.
592
592
593 Returns 0 on success.
593 Returns 0 on success.
594 """
594 """
595 def extendbisectrange(nodes, good):
595 def extendbisectrange(nodes, good):
596 # bisect is incomplete when it ends on a merge node and
596 # bisect is incomplete when it ends on a merge node and
597 # one of the parent was not checked.
597 # one of the parent was not checked.
598 parents = repo[nodes[0]].parents()
598 parents = repo[nodes[0]].parents()
599 if len(parents) > 1:
599 if len(parents) > 1:
600 side = good and state['bad'] or state['good']
600 side = good and state['bad'] or state['good']
601 num = len(set(i.node() for i in parents) & set(side))
601 num = len(set(i.node() for i in parents) & set(side))
602 if num == 1:
602 if num == 1:
603 return parents[0].ancestor(parents[1])
603 return parents[0].ancestor(parents[1])
604 return None
604 return None
605
605
606 def print_result(nodes, good):
606 def print_result(nodes, good):
607 displayer = cmdutil.show_changeset(ui, repo, {})
607 displayer = cmdutil.show_changeset(ui, repo, {})
608 if len(nodes) == 1:
608 if len(nodes) == 1:
609 # narrowed it down to a single revision
609 # narrowed it down to a single revision
610 if good:
610 if good:
611 ui.write(_("The first good revision is:\n"))
611 ui.write(_("The first good revision is:\n"))
612 else:
612 else:
613 ui.write(_("The first bad revision is:\n"))
613 ui.write(_("The first bad revision is:\n"))
614 displayer.show(repo[nodes[0]])
614 displayer.show(repo[nodes[0]])
615 extendnode = extendbisectrange(nodes, good)
615 extendnode = extendbisectrange(nodes, good)
616 if extendnode is not None:
616 if extendnode is not None:
617 ui.write(_('Not all ancestors of this changeset have been'
617 ui.write(_('Not all ancestors of this changeset have been'
618 ' checked.\nUse bisect --extend to continue the '
618 ' checked.\nUse bisect --extend to continue the '
619 'bisection from\nthe common ancestor, %s.\n')
619 'bisection from\nthe common ancestor, %s.\n')
620 % extendnode)
620 % extendnode)
621 else:
621 else:
622 # multiple possible revisions
622 # multiple possible revisions
623 if good:
623 if good:
624 ui.write(_("Due to skipped revisions, the first "
624 ui.write(_("Due to skipped revisions, the first "
625 "good revision could be any of:\n"))
625 "good revision could be any of:\n"))
626 else:
626 else:
627 ui.write(_("Due to skipped revisions, the first "
627 ui.write(_("Due to skipped revisions, the first "
628 "bad revision could be any of:\n"))
628 "bad revision could be any of:\n"))
629 for n in nodes:
629 for n in nodes:
630 displayer.show(repo[n])
630 displayer.show(repo[n])
631 displayer.close()
631 displayer.close()
632
632
633 def check_state(state, interactive=True):
633 def check_state(state, interactive=True):
634 if not state['good'] or not state['bad']:
634 if not state['good'] or not state['bad']:
635 if (good or bad or skip or reset) and interactive:
635 if (good or bad or skip or reset) and interactive:
636 return
636 return
637 if not state['good']:
637 if not state['good']:
638 raise util.Abort(_('cannot bisect (no known good revisions)'))
638 raise util.Abort(_('cannot bisect (no known good revisions)'))
639 else:
639 else:
640 raise util.Abort(_('cannot bisect (no known bad revisions)'))
640 raise util.Abort(_('cannot bisect (no known bad revisions)'))
641 return True
641 return True
642
642
643 # backward compatibility
643 # backward compatibility
644 if rev in "good bad reset init".split():
644 if rev in "good bad reset init".split():
645 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
645 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
646 cmd, rev, extra = rev, extra, None
646 cmd, rev, extra = rev, extra, None
647 if cmd == "good":
647 if cmd == "good":
648 good = True
648 good = True
649 elif cmd == "bad":
649 elif cmd == "bad":
650 bad = True
650 bad = True
651 else:
651 else:
652 reset = True
652 reset = True
653 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
653 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
654 raise util.Abort(_('incompatible arguments'))
654 raise util.Abort(_('incompatible arguments'))
655
655
656 cmdutil.checkunfinished(repo)
656 cmdutil.checkunfinished(repo)
657
657
658 if reset:
658 if reset:
659 p = repo.join("bisect.state")
659 p = repo.join("bisect.state")
660 if os.path.exists(p):
660 if os.path.exists(p):
661 os.unlink(p)
661 os.unlink(p)
662 return
662 return
663
663
664 state = hbisect.load_state(repo)
664 state = hbisect.load_state(repo)
665
665
666 if command:
666 if command:
667 changesets = 1
667 changesets = 1
668 try:
668 try:
669 node = state['current'][0]
669 node = state['current'][0]
670 except LookupError:
670 except LookupError:
671 if noupdate:
671 if noupdate:
672 raise util.Abort(_('current bisect revision is unknown - '
672 raise util.Abort(_('current bisect revision is unknown - '
673 'start a new bisect to fix'))
673 'start a new bisect to fix'))
674 node, p2 = repo.dirstate.parents()
674 node, p2 = repo.dirstate.parents()
675 if p2 != nullid:
675 if p2 != nullid:
676 raise util.Abort(_('current bisect revision is a merge'))
676 raise util.Abort(_('current bisect revision is a merge'))
677 try:
677 try:
678 while changesets:
678 while changesets:
679 # update state
679 # update state
680 state['current'] = [node]
680 state['current'] = [node]
681 hbisect.save_state(repo, state)
681 hbisect.save_state(repo, state)
682 status = util.system(command,
682 status = util.system(command,
683 environ={'HG_NODE': hex(node)},
683 environ={'HG_NODE': hex(node)},
684 out=ui.fout)
684 out=ui.fout)
685 if status == 125:
685 if status == 125:
686 transition = "skip"
686 transition = "skip"
687 elif status == 0:
687 elif status == 0:
688 transition = "good"
688 transition = "good"
689 # status < 0 means process was killed
689 # status < 0 means process was killed
690 elif status == 127:
690 elif status == 127:
691 raise util.Abort(_("failed to execute %s") % command)
691 raise util.Abort(_("failed to execute %s") % command)
692 elif status < 0:
692 elif status < 0:
693 raise util.Abort(_("%s killed") % command)
693 raise util.Abort(_("%s killed") % command)
694 else:
694 else:
695 transition = "bad"
695 transition = "bad"
696 ctx = scmutil.revsingle(repo, rev, node)
696 ctx = scmutil.revsingle(repo, rev, node)
697 rev = None # clear for future iterations
697 rev = None # clear for future iterations
698 state[transition].append(ctx.node())
698 state[transition].append(ctx.node())
699 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
699 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
700 check_state(state, interactive=False)
700 check_state(state, interactive=False)
701 # bisect
701 # bisect
702 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
702 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
703 # update to next check
703 # update to next check
704 node = nodes[0]
704 node = nodes[0]
705 if not noupdate:
705 if not noupdate:
706 cmdutil.bailifchanged(repo)
706 cmdutil.bailifchanged(repo)
707 hg.clean(repo, node, show_stats=False)
707 hg.clean(repo, node, show_stats=False)
708 finally:
708 finally:
709 state['current'] = [node]
709 state['current'] = [node]
710 hbisect.save_state(repo, state)
710 hbisect.save_state(repo, state)
711 print_result(nodes, good)
711 print_result(nodes, good)
712 return
712 return
713
713
714 # update state
714 # update state
715
715
716 if rev:
716 if rev:
717 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
717 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
718 else:
718 else:
719 nodes = [repo.lookup('.')]
719 nodes = [repo.lookup('.')]
720
720
721 if good or bad or skip:
721 if good or bad or skip:
722 if good:
722 if good:
723 state['good'] += nodes
723 state['good'] += nodes
724 elif bad:
724 elif bad:
725 state['bad'] += nodes
725 state['bad'] += nodes
726 elif skip:
726 elif skip:
727 state['skip'] += nodes
727 state['skip'] += nodes
728 hbisect.save_state(repo, state)
728 hbisect.save_state(repo, state)
729
729
730 if not check_state(state):
730 if not check_state(state):
731 return
731 return
732
732
733 # actually bisect
733 # actually bisect
734 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
734 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
735 if extend:
735 if extend:
736 if not changesets:
736 if not changesets:
737 extendnode = extendbisectrange(nodes, good)
737 extendnode = extendbisectrange(nodes, good)
738 if extendnode is not None:
738 if extendnode is not None:
739 ui.write(_("Extending search to changeset %d:%s\n"
739 ui.write(_("Extending search to changeset %d:%s\n"
740 % (extendnode.rev(), extendnode)))
740 % (extendnode.rev(), extendnode)))
741 state['current'] = [extendnode.node()]
741 state['current'] = [extendnode.node()]
742 hbisect.save_state(repo, state)
742 hbisect.save_state(repo, state)
743 if noupdate:
743 if noupdate:
744 return
744 return
745 cmdutil.bailifchanged(repo)
745 cmdutil.bailifchanged(repo)
746 return hg.clean(repo, extendnode.node())
746 return hg.clean(repo, extendnode.node())
747 raise util.Abort(_("nothing to extend"))
747 raise util.Abort(_("nothing to extend"))
748
748
749 if changesets == 0:
749 if changesets == 0:
750 print_result(nodes, good)
750 print_result(nodes, good)
751 else:
751 else:
752 assert len(nodes) == 1 # only a single node can be tested next
752 assert len(nodes) == 1 # only a single node can be tested next
753 node = nodes[0]
753 node = nodes[0]
754 # compute the approximate number of remaining tests
754 # compute the approximate number of remaining tests
755 tests, size = 0, 2
755 tests, size = 0, 2
756 while size <= changesets:
756 while size <= changesets:
757 tests, size = tests + 1, size * 2
757 tests, size = tests + 1, size * 2
758 rev = repo.changelog.rev(node)
758 rev = repo.changelog.rev(node)
759 ui.write(_("Testing changeset %d:%s "
759 ui.write(_("Testing changeset %d:%s "
760 "(%d changesets remaining, ~%d tests)\n")
760 "(%d changesets remaining, ~%d tests)\n")
761 % (rev, short(node), changesets, tests))
761 % (rev, short(node), changesets, tests))
762 state['current'] = [node]
762 state['current'] = [node]
763 hbisect.save_state(repo, state)
763 hbisect.save_state(repo, state)
764 if not noupdate:
764 if not noupdate:
765 cmdutil.bailifchanged(repo)
765 cmdutil.bailifchanged(repo)
766 return hg.clean(repo, node)
766 return hg.clean(repo, node)
767
767
768 @command('bookmarks|bookmark',
768 @command('bookmarks|bookmark',
769 [('f', 'force', False, _('force')),
769 [('f', 'force', False, _('force')),
770 ('r', 'rev', '', _('revision'), _('REV')),
770 ('r', 'rev', '', _('revision'), _('REV')),
771 ('d', 'delete', False, _('delete a given bookmark')),
771 ('d', 'delete', False, _('delete a given bookmark')),
772 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
772 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
773 ('i', 'inactive', False, _('mark a bookmark inactive'))],
773 ('i', 'inactive', False, _('mark a bookmark inactive'))],
774 _('hg bookmarks [OPTIONS]... [NAME]...'))
774 _('hg bookmarks [OPTIONS]... [NAME]...'))
775 def bookmark(ui, repo, *names, **opts):
775 def bookmark(ui, repo, *names, **opts):
776 '''track a line of development with movable markers
776 '''track a line of development with movable markers
777
777
778 Bookmarks are pointers to certain commits that move when committing.
778 Bookmarks are pointers to certain commits that move when committing.
779 Bookmarks are local. They can be renamed, copied and deleted. It is
779 Bookmarks are local. They can be renamed, copied and deleted. It is
780 possible to use :hg:`merge NAME` to merge from a given bookmark, and
780 possible to use :hg:`merge NAME` to merge from a given bookmark, and
781 :hg:`update NAME` to update to a given bookmark.
781 :hg:`update NAME` to update to a given bookmark.
782
782
783 You can use :hg:`bookmark NAME` to set a bookmark on the working
783 You can use :hg:`bookmark NAME` to set a bookmark on the working
784 directory's parent revision with the given name. If you specify
784 directory's parent revision with the given name. If you specify
785 a revision using -r REV (where REV may be an existing bookmark),
785 a revision using -r REV (where REV may be an existing bookmark),
786 the bookmark is assigned to that revision.
786 the bookmark is assigned to that revision.
787
787
788 Bookmarks can be pushed and pulled between repositories (see :hg:`help
788 Bookmarks can be pushed and pulled between repositories (see :hg:`help
789 push` and :hg:`help pull`). This requires both the local and remote
789 push` and :hg:`help pull`). This requires both the local and remote
790 repositories to support bookmarks. For versions prior to 1.8, this means
790 repositories to support bookmarks. For versions prior to 1.8, this means
791 the bookmarks extension must be enabled.
791 the bookmarks extension must be enabled.
792
792
793 If you set a bookmark called '@', new clones of the repository will
793 If you set a bookmark called '@', new clones of the repository will
794 have that revision checked out (and the bookmark made active) by
794 have that revision checked out (and the bookmark made active) by
795 default.
795 default.
796
796
797 With -i/--inactive, the new bookmark will not be made the active
797 With -i/--inactive, the new bookmark will not be made the active
798 bookmark. If -r/--rev is given, the new bookmark will not be made
798 bookmark. If -r/--rev is given, the new bookmark will not be made
799 active even if -i/--inactive is not given. If no NAME is given, the
799 active even if -i/--inactive is not given. If no NAME is given, the
800 current active bookmark will be marked inactive.
800 current active bookmark will be marked inactive.
801 '''
801 '''
802 force = opts.get('force')
802 force = opts.get('force')
803 rev = opts.get('rev')
803 rev = opts.get('rev')
804 delete = opts.get('delete')
804 delete = opts.get('delete')
805 rename = opts.get('rename')
805 rename = opts.get('rename')
806 inactive = opts.get('inactive')
806 inactive = opts.get('inactive')
807
807
808 hexfn = ui.debugflag and hex or short
808 hexfn = ui.debugflag and hex or short
809 marks = repo._bookmarks
809 marks = repo._bookmarks
810 cur = repo.changectx('.').node()
810 cur = repo.changectx('.').node()
811
811
812 def checkformat(mark):
812 def checkformat(mark):
813 mark = mark.strip()
813 mark = mark.strip()
814 if not mark:
814 if not mark:
815 raise util.Abort(_("bookmark names cannot consist entirely of "
815 raise util.Abort(_("bookmark names cannot consist entirely of "
816 "whitespace"))
816 "whitespace"))
817 scmutil.checknewlabel(repo, mark, 'bookmark')
817 scmutil.checknewlabel(repo, mark, 'bookmark')
818 return mark
818 return mark
819
819
820 def checkconflict(repo, mark, force=False, target=None):
820 def checkconflict(repo, mark, force=False, target=None):
821 if mark in marks and not force:
821 if mark in marks and not force:
822 if target:
822 if target:
823 if marks[mark] == target and target == cur:
823 if marks[mark] == target and target == cur:
824 # re-activating a bookmark
824 # re-activating a bookmark
825 return
825 return
826 anc = repo.changelog.ancestors([repo[target].rev()])
826 anc = repo.changelog.ancestors([repo[target].rev()])
827 bmctx = repo[marks[mark]]
827 bmctx = repo[marks[mark]]
828 divs = [repo[b].node() for b in marks
828 divs = [repo[b].node() for b in marks
829 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
829 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
830
830
831 # allow resolving a single divergent bookmark even if moving
831 # allow resolving a single divergent bookmark even if moving
832 # the bookmark across branches when a revision is specified
832 # the bookmark across branches when a revision is specified
833 # that contains a divergent bookmark
833 # that contains a divergent bookmark
834 if bmctx.rev() not in anc and target in divs:
834 if bmctx.rev() not in anc and target in divs:
835 bookmarks.deletedivergent(repo, [target], mark)
835 bookmarks.deletedivergent(repo, [target], mark)
836 return
836 return
837
837
838 deletefrom = [b for b in divs
838 deletefrom = [b for b in divs
839 if repo[b].rev() in anc or b == target]
839 if repo[b].rev() in anc or b == target]
840 bookmarks.deletedivergent(repo, deletefrom, mark)
840 bookmarks.deletedivergent(repo, deletefrom, mark)
841 if bmctx.rev() in anc:
841 if bmctx.rev() in anc:
842 ui.status(_("moving bookmark '%s' forward from %s\n") %
842 ui.status(_("moving bookmark '%s' forward from %s\n") %
843 (mark, short(bmctx.node())))
843 (mark, short(bmctx.node())))
844 return
844 return
845 raise util.Abort(_("bookmark '%s' already exists "
845 raise util.Abort(_("bookmark '%s' already exists "
846 "(use -f to force)") % mark)
846 "(use -f to force)") % mark)
847 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
847 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
848 and not force):
848 and not force):
849 raise util.Abort(
849 raise util.Abort(
850 _("a bookmark cannot have the name of an existing branch"))
850 _("a bookmark cannot have the name of an existing branch"))
851
851
852 if delete and rename:
852 if delete and rename:
853 raise util.Abort(_("--delete and --rename are incompatible"))
853 raise util.Abort(_("--delete and --rename are incompatible"))
854 if delete and rev:
854 if delete and rev:
855 raise util.Abort(_("--rev is incompatible with --delete"))
855 raise util.Abort(_("--rev is incompatible with --delete"))
856 if rename and rev:
856 if rename and rev:
857 raise util.Abort(_("--rev is incompatible with --rename"))
857 raise util.Abort(_("--rev is incompatible with --rename"))
858 if not names and (delete or rev):
858 if not names and (delete or rev):
859 raise util.Abort(_("bookmark name required"))
859 raise util.Abort(_("bookmark name required"))
860
860
861 if delete:
861 if delete:
862 for mark in names:
862 for mark in names:
863 if mark not in marks:
863 if mark not in marks:
864 raise util.Abort(_("bookmark '%s' does not exist") % mark)
864 raise util.Abort(_("bookmark '%s' does not exist") % mark)
865 if mark == repo._bookmarkcurrent:
865 if mark == repo._bookmarkcurrent:
866 bookmarks.setcurrent(repo, None)
866 bookmarks.setcurrent(repo, None)
867 del marks[mark]
867 del marks[mark]
868 marks.write()
868 marks.write()
869
869
870 elif rename:
870 elif rename:
871 if not names:
871 if not names:
872 raise util.Abort(_("new bookmark name required"))
872 raise util.Abort(_("new bookmark name required"))
873 elif len(names) > 1:
873 elif len(names) > 1:
874 raise util.Abort(_("only one new bookmark name allowed"))
874 raise util.Abort(_("only one new bookmark name allowed"))
875 mark = checkformat(names[0])
875 mark = checkformat(names[0])
876 if rename not in marks:
876 if rename not in marks:
877 raise util.Abort(_("bookmark '%s' does not exist") % rename)
877 raise util.Abort(_("bookmark '%s' does not exist") % rename)
878 checkconflict(repo, mark, force)
878 checkconflict(repo, mark, force)
879 marks[mark] = marks[rename]
879 marks[mark] = marks[rename]
880 if repo._bookmarkcurrent == rename and not inactive:
880 if repo._bookmarkcurrent == rename and not inactive:
881 bookmarks.setcurrent(repo, mark)
881 bookmarks.setcurrent(repo, mark)
882 del marks[rename]
882 del marks[rename]
883 marks.write()
883 marks.write()
884
884
885 elif names:
885 elif names:
886 newact = None
886 newact = None
887 for mark in names:
887 for mark in names:
888 mark = checkformat(mark)
888 mark = checkformat(mark)
889 if newact is None:
889 if newact is None:
890 newact = mark
890 newact = mark
891 if inactive and mark == repo._bookmarkcurrent:
891 if inactive and mark == repo._bookmarkcurrent:
892 bookmarks.setcurrent(repo, None)
892 bookmarks.setcurrent(repo, None)
893 return
893 return
894 tgt = cur
894 tgt = cur
895 if rev:
895 if rev:
896 tgt = scmutil.revsingle(repo, rev).node()
896 tgt = scmutil.revsingle(repo, rev).node()
897 checkconflict(repo, mark, force, tgt)
897 checkconflict(repo, mark, force, tgt)
898 marks[mark] = tgt
898 marks[mark] = tgt
899 if not inactive and cur == marks[newact] and not rev:
899 if not inactive and cur == marks[newact] and not rev:
900 bookmarks.setcurrent(repo, newact)
900 bookmarks.setcurrent(repo, newact)
901 elif cur != tgt and newact == repo._bookmarkcurrent:
901 elif cur != tgt and newact == repo._bookmarkcurrent:
902 bookmarks.setcurrent(repo, None)
902 bookmarks.setcurrent(repo, None)
903 marks.write()
903 marks.write()
904
904
905 # Same message whether trying to deactivate the current bookmark (-i
905 # Same message whether trying to deactivate the current bookmark (-i
906 # with no NAME) or listing bookmarks
906 # with no NAME) or listing bookmarks
907 elif len(marks) == 0:
907 elif len(marks) == 0:
908 ui.status(_("no bookmarks set\n"))
908 ui.status(_("no bookmarks set\n"))
909
909
910 elif inactive:
910 elif inactive:
911 if not repo._bookmarkcurrent:
911 if not repo._bookmarkcurrent:
912 ui.status(_("no active bookmark\n"))
912 ui.status(_("no active bookmark\n"))
913 else:
913 else:
914 bookmarks.setcurrent(repo, None)
914 bookmarks.setcurrent(repo, None)
915
915
916 else: # show bookmarks
916 else: # show bookmarks
917 for bmark, n in sorted(marks.iteritems()):
917 for bmark, n in sorted(marks.iteritems()):
918 current = repo._bookmarkcurrent
918 current = repo._bookmarkcurrent
919 if bmark == current:
919 if bmark == current:
920 prefix, label = '*', 'bookmarks.current'
920 prefix, label = '*', 'bookmarks.current'
921 else:
921 else:
922 prefix, label = ' ', ''
922 prefix, label = ' ', ''
923
923
924 if ui.quiet:
924 if ui.quiet:
925 ui.write("%s\n" % bmark, label=label)
925 ui.write("%s\n" % bmark, label=label)
926 else:
926 else:
927 ui.write(" %s %-25s %d:%s\n" % (
927 ui.write(" %s %-25s %d:%s\n" % (
928 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
928 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
929 label=label)
929 label=label)
930
930
931 @command('branch',
931 @command('branch',
932 [('f', 'force', None,
932 [('f', 'force', None,
933 _('set branch name even if it shadows an existing branch')),
933 _('set branch name even if it shadows an existing branch')),
934 ('C', 'clean', None, _('reset branch name to parent branch name'))],
934 ('C', 'clean', None, _('reset branch name to parent branch name'))],
935 _('[-fC] [NAME]'))
935 _('[-fC] [NAME]'))
936 def branch(ui, repo, label=None, **opts):
936 def branch(ui, repo, label=None, **opts):
937 """set or show the current branch name
937 """set or show the current branch name
938
938
939 .. note::
939 .. note::
940 Branch names are permanent and global. Use :hg:`bookmark` to create a
940 Branch names are permanent and global. Use :hg:`bookmark` to create a
941 light-weight bookmark instead. See :hg:`help glossary` for more
941 light-weight bookmark instead. See :hg:`help glossary` for more
942 information about named branches and bookmarks.
942 information about named branches and bookmarks.
943
943
944 With no argument, show the current branch name. With one argument,
944 With no argument, show the current branch name. With one argument,
945 set the working directory branch name (the branch will not exist
945 set the working directory branch name (the branch will not exist
946 in the repository until the next commit). Standard practice
946 in the repository until the next commit). Standard practice
947 recommends that primary development take place on the 'default'
947 recommends that primary development take place on the 'default'
948 branch.
948 branch.
949
949
950 Unless -f/--force is specified, branch will not let you set a
950 Unless -f/--force is specified, branch will not let you set a
951 branch name that already exists, even if it's inactive.
951 branch name that already exists, even if it's inactive.
952
952
953 Use -C/--clean to reset the working directory branch to that of
953 Use -C/--clean to reset the working directory branch to that of
954 the parent of the working directory, negating a previous branch
954 the parent of the working directory, negating a previous branch
955 change.
955 change.
956
956
957 Use the command :hg:`update` to switch to an existing branch. Use
957 Use the command :hg:`update` to switch to an existing branch. Use
958 :hg:`commit --close-branch` to mark this branch as closed.
958 :hg:`commit --close-branch` to mark this branch as closed.
959
959
960 Returns 0 on success.
960 Returns 0 on success.
961 """
961 """
962 if label:
962 if label:
963 label = label.strip()
963 label = label.strip()
964
964
965 if not opts.get('clean') and not label:
965 if not opts.get('clean') and not label:
966 ui.write("%s\n" % repo.dirstate.branch())
966 ui.write("%s\n" % repo.dirstate.branch())
967 return
967 return
968
968
969 wlock = repo.wlock()
969 wlock = repo.wlock()
970 try:
970 try:
971 if opts.get('clean'):
971 if opts.get('clean'):
972 label = repo[None].p1().branch()
972 label = repo[None].p1().branch()
973 repo.dirstate.setbranch(label)
973 repo.dirstate.setbranch(label)
974 ui.status(_('reset working directory to branch %s\n') % label)
974 ui.status(_('reset working directory to branch %s\n') % label)
975 elif label:
975 elif label:
976 if not opts.get('force') and label in repo.branchmap():
976 if not opts.get('force') and label in repo.branchmap():
977 if label not in [p.branch() for p in repo.parents()]:
977 if label not in [p.branch() for p in repo.parents()]:
978 raise util.Abort(_('a branch of the same name already'
978 raise util.Abort(_('a branch of the same name already'
979 ' exists'),
979 ' exists'),
980 # i18n: "it" refers to an existing branch
980 # i18n: "it" refers to an existing branch
981 hint=_("use 'hg update' to switch to it"))
981 hint=_("use 'hg update' to switch to it"))
982 scmutil.checknewlabel(repo, label, 'branch')
982 scmutil.checknewlabel(repo, label, 'branch')
983 repo.dirstate.setbranch(label)
983 repo.dirstate.setbranch(label)
984 ui.status(_('marked working directory as branch %s\n') % label)
984 ui.status(_('marked working directory as branch %s\n') % label)
985 ui.status(_('(branches are permanent and global, '
985 ui.status(_('(branches are permanent and global, '
986 'did you want a bookmark?)\n'))
986 'did you want a bookmark?)\n'))
987 finally:
987 finally:
988 wlock.release()
988 wlock.release()
989
989
990 @command('branches',
990 @command('branches',
991 [('a', 'active', False, _('show only branches that have unmerged heads')),
991 [('a', 'active', False, _('show only branches that have unmerged heads')),
992 ('c', 'closed', False, _('show normal and closed branches'))],
992 ('c', 'closed', False, _('show normal and closed branches'))],
993 _('[-ac]'))
993 _('[-ac]'))
994 def branches(ui, repo, active=False, closed=False):
994 def branches(ui, repo, active=False, closed=False):
995 """list repository named branches
995 """list repository named branches
996
996
997 List the repository's named branches, indicating which ones are
997 List the repository's named branches, indicating which ones are
998 inactive. If -c/--closed is specified, also list branches which have
998 inactive. If -c/--closed is specified, also list branches which have
999 been marked closed (see :hg:`commit --close-branch`).
999 been marked closed (see :hg:`commit --close-branch`).
1000
1000
1001 If -a/--active is specified, only show active branches. A branch
1001 If -a/--active is specified, only show active branches. A branch
1002 is considered active if it contains repository heads.
1002 is considered active if it contains repository heads.
1003
1003
1004 Use the command :hg:`update` to switch to an existing branch.
1004 Use the command :hg:`update` to switch to an existing branch.
1005
1005
1006 Returns 0.
1006 Returns 0.
1007 """
1007 """
1008
1008
1009 hexfunc = ui.debugflag and hex or short
1009 hexfunc = ui.debugflag and hex or short
1010
1010
1011 activebranches = set([repo[n].branch() for n in repo.heads()])
1011 activebranches = set([repo[n].branch() for n in repo.heads()])
1012 branches = []
1012 branches = []
1013 for tag, heads in repo.branchmap().iteritems():
1013 for tag, heads in repo.branchmap().iteritems():
1014 for h in reversed(heads):
1014 for h in reversed(heads):
1015 ctx = repo[h]
1015 ctx = repo[h]
1016 isopen = not ctx.closesbranch()
1016 isopen = not ctx.closesbranch()
1017 if isopen:
1017 if isopen:
1018 tip = ctx
1018 tip = ctx
1019 break
1019 break
1020 else:
1020 else:
1021 tip = repo[heads[-1]]
1021 tip = repo[heads[-1]]
1022 isactive = tag in activebranches and isopen
1022 isactive = tag in activebranches and isopen
1023 branches.append((tip, isactive, isopen))
1023 branches.append((tip, isactive, isopen))
1024 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1024 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1025 reverse=True)
1025 reverse=True)
1026
1026
1027 for ctx, isactive, isopen in branches:
1027 for ctx, isactive, isopen in branches:
1028 if (not active) or isactive:
1028 if (not active) or isactive:
1029 if isactive:
1029 if isactive:
1030 label = 'branches.active'
1030 label = 'branches.active'
1031 notice = ''
1031 notice = ''
1032 elif not isopen:
1032 elif not isopen:
1033 if not closed:
1033 if not closed:
1034 continue
1034 continue
1035 label = 'branches.closed'
1035 label = 'branches.closed'
1036 notice = _(' (closed)')
1036 notice = _(' (closed)')
1037 else:
1037 else:
1038 label = 'branches.inactive'
1038 label = 'branches.inactive'
1039 notice = _(' (inactive)')
1039 notice = _(' (inactive)')
1040 if ctx.branch() == repo.dirstate.branch():
1040 if ctx.branch() == repo.dirstate.branch():
1041 label = 'branches.current'
1041 label = 'branches.current'
1042 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1042 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1043 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1043 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1044 'log.changeset changeset.%s' % ctx.phasestr())
1044 'log.changeset changeset.%s' % ctx.phasestr())
1045 tag = ui.label(ctx.branch(), label)
1045 tag = ui.label(ctx.branch(), label)
1046 if ui.quiet:
1046 if ui.quiet:
1047 ui.write("%s\n" % tag)
1047 ui.write("%s\n" % tag)
1048 else:
1048 else:
1049 ui.write("%s %s%s\n" % (tag, rev, notice))
1049 ui.write("%s %s%s\n" % (tag, rev, notice))
1050
1050
1051 @command('bundle',
1051 @command('bundle',
1052 [('f', 'force', None, _('run even when the destination is unrelated')),
1052 [('f', 'force', None, _('run even when the destination is unrelated')),
1053 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1053 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1054 _('REV')),
1054 _('REV')),
1055 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1055 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1056 _('BRANCH')),
1056 _('BRANCH')),
1057 ('', 'base', [],
1057 ('', 'base', [],
1058 _('a base changeset assumed to be available at the destination'),
1058 _('a base changeset assumed to be available at the destination'),
1059 _('REV')),
1059 _('REV')),
1060 ('a', 'all', None, _('bundle all changesets in the repository')),
1060 ('a', 'all', None, _('bundle all changesets in the repository')),
1061 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1061 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1062 ] + remoteopts,
1062 ] + remoteopts,
1063 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1063 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1064 def bundle(ui, repo, fname, dest=None, **opts):
1064 def bundle(ui, repo, fname, dest=None, **opts):
1065 """create a changegroup file
1065 """create a changegroup file
1066
1066
1067 Generate a compressed changegroup file collecting changesets not
1067 Generate a compressed changegroup file collecting changesets not
1068 known to be in another repository.
1068 known to be in another repository.
1069
1069
1070 If you omit the destination repository, then hg assumes the
1070 If you omit the destination repository, then hg assumes the
1071 destination will have all the nodes you specify with --base
1071 destination will have all the nodes you specify with --base
1072 parameters. To create a bundle containing all changesets, use
1072 parameters. To create a bundle containing all changesets, use
1073 -a/--all (or --base null).
1073 -a/--all (or --base null).
1074
1074
1075 You can change compression method with the -t/--type option.
1075 You can change compression method with the -t/--type option.
1076 The available compression methods are: none, bzip2, and
1076 The available compression methods are: none, bzip2, and
1077 gzip (by default, bundles are compressed using bzip2).
1077 gzip (by default, bundles are compressed using bzip2).
1078
1078
1079 The bundle file can then be transferred using conventional means
1079 The bundle file can then be transferred using conventional means
1080 and applied to another repository with the unbundle or pull
1080 and applied to another repository with the unbundle or pull
1081 command. This is useful when direct push and pull are not
1081 command. This is useful when direct push and pull are not
1082 available or when exporting an entire repository is undesirable.
1082 available or when exporting an entire repository is undesirable.
1083
1083
1084 Applying bundles preserves all changeset contents including
1084 Applying bundles preserves all changeset contents including
1085 permissions, copy/rename information, and revision history.
1085 permissions, copy/rename information, and revision history.
1086
1086
1087 Returns 0 on success, 1 if no changes found.
1087 Returns 0 on success, 1 if no changes found.
1088 """
1088 """
1089 revs = None
1089 revs = None
1090 if 'rev' in opts:
1090 if 'rev' in opts:
1091 revs = scmutil.revrange(repo, opts['rev'])
1091 revs = scmutil.revrange(repo, opts['rev'])
1092
1092
1093 bundletype = opts.get('type', 'bzip2').lower()
1093 bundletype = opts.get('type', 'bzip2').lower()
1094 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1094 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1095 bundletype = btypes.get(bundletype)
1095 bundletype = btypes.get(bundletype)
1096 if bundletype not in changegroup.bundletypes:
1096 if bundletype not in changegroup.bundletypes:
1097 raise util.Abort(_('unknown bundle type specified with --type'))
1097 raise util.Abort(_('unknown bundle type specified with --type'))
1098
1098
1099 if opts.get('all'):
1099 if opts.get('all'):
1100 base = ['null']
1100 base = ['null']
1101 else:
1101 else:
1102 base = scmutil.revrange(repo, opts.get('base'))
1102 base = scmutil.revrange(repo, opts.get('base'))
1103 # TODO: get desired bundlecaps from command line.
1103 # TODO: get desired bundlecaps from command line.
1104 bundlecaps = None
1104 bundlecaps = None
1105 if base:
1105 if base:
1106 if dest:
1106 if dest:
1107 raise util.Abort(_("--base is incompatible with specifying "
1107 raise util.Abort(_("--base is incompatible with specifying "
1108 "a destination"))
1108 "a destination"))
1109 common = [repo.lookup(rev) for rev in base]
1109 common = [repo.lookup(rev) for rev in base]
1110 heads = revs and map(repo.lookup, revs) or revs
1110 heads = revs and map(repo.lookup, revs) or revs
1111 cg = repo.getbundle('bundle', heads=heads, common=common,
1111 cg = repo.getbundle('bundle', heads=heads, common=common,
1112 bundlecaps=bundlecaps)
1112 bundlecaps=bundlecaps)
1113 outgoing = None
1113 outgoing = None
1114 else:
1114 else:
1115 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1115 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1116 dest, branches = hg.parseurl(dest, opts.get('branch'))
1116 dest, branches = hg.parseurl(dest, opts.get('branch'))
1117 other = hg.peer(repo, opts, dest)
1117 other = hg.peer(repo, opts, dest)
1118 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1118 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1119 heads = revs and map(repo.lookup, revs) or revs
1119 heads = revs and map(repo.lookup, revs) or revs
1120 outgoing = discovery.findcommonoutgoing(repo, other,
1120 outgoing = discovery.findcommonoutgoing(repo, other,
1121 onlyheads=heads,
1121 onlyheads=heads,
1122 force=opts.get('force'),
1122 force=opts.get('force'),
1123 portable=True)
1123 portable=True)
1124 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1124 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1125 if not cg:
1125 if not cg:
1126 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1126 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1127 return 1
1127 return 1
1128
1128
1129 changegroup.writebundle(cg, fname, bundletype)
1129 changegroup.writebundle(cg, fname, bundletype)
1130
1130
1131 @command('cat',
1131 @command('cat',
1132 [('o', 'output', '',
1132 [('o', 'output', '',
1133 _('print output to file with formatted name'), _('FORMAT')),
1133 _('print output to file with formatted name'), _('FORMAT')),
1134 ('r', 'rev', '', _('print the given revision'), _('REV')),
1134 ('r', 'rev', '', _('print the given revision'), _('REV')),
1135 ('', 'decode', None, _('apply any matching decode filter')),
1135 ('', 'decode', None, _('apply any matching decode filter')),
1136 ] + walkopts,
1136 ] + walkopts,
1137 _('[OPTION]... FILE...'))
1137 _('[OPTION]... FILE...'))
1138 def cat(ui, repo, file1, *pats, **opts):
1138 def cat(ui, repo, file1, *pats, **opts):
1139 """output the current or given revision of files
1139 """output the current or given revision of files
1140
1140
1141 Print the specified files as they were at the given revision. If
1141 Print the specified files as they were at the given revision. If
1142 no revision is given, the parent of the working directory is used.
1142 no revision is given, the parent of the working directory is used.
1143
1143
1144 Output may be to a file, in which case the name of the file is
1144 Output may be to a file, in which case the name of the file is
1145 given using a format string. The formatting rules are the same as
1145 given using a format string. The formatting rules are the same as
1146 for the export command, with the following additions:
1146 for the export command, with the following additions:
1147
1147
1148 :``%s``: basename of file being printed
1148 :``%s``: basename of file being printed
1149 :``%d``: dirname of file being printed, or '.' if in repository root
1149 :``%d``: dirname of file being printed, or '.' if in repository root
1150 :``%p``: root-relative path name of file being printed
1150 :``%p``: root-relative path name of file being printed
1151
1151
1152 Returns 0 on success.
1152 Returns 0 on success.
1153 """
1153 """
1154 ctx = scmutil.revsingle(repo, opts.get('rev'))
1154 ctx = scmutil.revsingle(repo, opts.get('rev'))
1155 err = 1
1155 err = 1
1156 m = scmutil.match(ctx, (file1,) + pats, opts)
1156 m = scmutil.match(ctx, (file1,) + pats, opts)
1157 for abs in ctx.walk(m):
1157 for abs in ctx.walk(m):
1158 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1158 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1159 pathname=abs)
1159 pathname=abs)
1160 data = ctx[abs].data()
1160 data = ctx[abs].data()
1161 if opts.get('decode'):
1161 if opts.get('decode'):
1162 data = repo.wwritedata(abs, data)
1162 data = repo.wwritedata(abs, data)
1163 fp.write(data)
1163 fp.write(data)
1164 fp.close()
1164 fp.close()
1165 err = 0
1165 err = 0
1166 return err
1166 return err
1167
1167
1168 @command('^clone',
1168 @command('^clone',
1169 [('U', 'noupdate', None,
1169 [('U', 'noupdate', None,
1170 _('the clone will include an empty working copy (only a repository)')),
1170 _('the clone will include an empty working copy (only a repository)')),
1171 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1171 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1172 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1172 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1173 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1173 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1174 ('', 'pull', None, _('use pull protocol to copy metadata')),
1174 ('', 'pull', None, _('use pull protocol to copy metadata')),
1175 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1175 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1176 ] + remoteopts,
1176 ] + remoteopts,
1177 _('[OPTION]... SOURCE [DEST]'))
1177 _('[OPTION]... SOURCE [DEST]'))
1178 def clone(ui, source, dest=None, **opts):
1178 def clone(ui, source, dest=None, **opts):
1179 """make a copy of an existing repository
1179 """make a copy of an existing repository
1180
1180
1181 Create a copy of an existing repository in a new directory.
1181 Create a copy of an existing repository in a new directory.
1182
1182
1183 If no destination directory name is specified, it defaults to the
1183 If no destination directory name is specified, it defaults to the
1184 basename of the source.
1184 basename of the source.
1185
1185
1186 The location of the source is added to the new repository's
1186 The location of the source is added to the new repository's
1187 ``.hg/hgrc`` file, as the default to be used for future pulls.
1187 ``.hg/hgrc`` file, as the default to be used for future pulls.
1188
1188
1189 Only local paths and ``ssh://`` URLs are supported as
1189 Only local paths and ``ssh://`` URLs are supported as
1190 destinations. For ``ssh://`` destinations, no working directory or
1190 destinations. For ``ssh://`` destinations, no working directory or
1191 ``.hg/hgrc`` will be created on the remote side.
1191 ``.hg/hgrc`` will be created on the remote side.
1192
1192
1193 To pull only a subset of changesets, specify one or more revisions
1193 To pull only a subset of changesets, specify one or more revisions
1194 identifiers with -r/--rev or branches with -b/--branch. The
1194 identifiers with -r/--rev or branches with -b/--branch. The
1195 resulting clone will contain only the specified changesets and
1195 resulting clone will contain only the specified changesets and
1196 their ancestors. These options (or 'clone src#rev dest') imply
1196 their ancestors. These options (or 'clone src#rev dest') imply
1197 --pull, even for local source repositories. Note that specifying a
1197 --pull, even for local source repositories. Note that specifying a
1198 tag will include the tagged changeset but not the changeset
1198 tag will include the tagged changeset but not the changeset
1199 containing the tag.
1199 containing the tag.
1200
1200
1201 If the source repository has a bookmark called '@' set, that
1201 If the source repository has a bookmark called '@' set, that
1202 revision will be checked out in the new repository by default.
1202 revision will be checked out in the new repository by default.
1203
1203
1204 To check out a particular version, use -u/--update, or
1204 To check out a particular version, use -u/--update, or
1205 -U/--noupdate to create a clone with no working directory.
1205 -U/--noupdate to create a clone with no working directory.
1206
1206
1207 .. container:: verbose
1207 .. container:: verbose
1208
1208
1209 For efficiency, hardlinks are used for cloning whenever the
1209 For efficiency, hardlinks are used for cloning whenever the
1210 source and destination are on the same filesystem (note this
1210 source and destination are on the same filesystem (note this
1211 applies only to the repository data, not to the working
1211 applies only to the repository data, not to the working
1212 directory). Some filesystems, such as AFS, implement hardlinking
1212 directory). Some filesystems, such as AFS, implement hardlinking
1213 incorrectly, but do not report errors. In these cases, use the
1213 incorrectly, but do not report errors. In these cases, use the
1214 --pull option to avoid hardlinking.
1214 --pull option to avoid hardlinking.
1215
1215
1216 In some cases, you can clone repositories and the working
1216 In some cases, you can clone repositories and the working
1217 directory using full hardlinks with ::
1217 directory using full hardlinks with ::
1218
1218
1219 $ cp -al REPO REPOCLONE
1219 $ cp -al REPO REPOCLONE
1220
1220
1221 This is the fastest way to clone, but it is not always safe. The
1221 This is the fastest way to clone, but it is not always safe. The
1222 operation is not atomic (making sure REPO is not modified during
1222 operation is not atomic (making sure REPO is not modified during
1223 the operation is up to you) and you have to make sure your
1223 the operation is up to you) and you have to make sure your
1224 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1224 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1225 so). Also, this is not compatible with certain extensions that
1225 so). Also, this is not compatible with certain extensions that
1226 place their metadata under the .hg directory, such as mq.
1226 place their metadata under the .hg directory, such as mq.
1227
1227
1228 Mercurial will update the working directory to the first applicable
1228 Mercurial will update the working directory to the first applicable
1229 revision from this list:
1229 revision from this list:
1230
1230
1231 a) null if -U or the source repository has no changesets
1231 a) null if -U or the source repository has no changesets
1232 b) if -u . and the source repository is local, the first parent of
1232 b) if -u . and the source repository is local, the first parent of
1233 the source repository's working directory
1233 the source repository's working directory
1234 c) the changeset specified with -u (if a branch name, this means the
1234 c) the changeset specified with -u (if a branch name, this means the
1235 latest head of that branch)
1235 latest head of that branch)
1236 d) the changeset specified with -r
1236 d) the changeset specified with -r
1237 e) the tipmost head specified with -b
1237 e) the tipmost head specified with -b
1238 f) the tipmost head specified with the url#branch source syntax
1238 f) the tipmost head specified with the url#branch source syntax
1239 g) the revision marked with the '@' bookmark, if present
1239 g) the revision marked with the '@' bookmark, if present
1240 h) the tipmost head of the default branch
1240 h) the tipmost head of the default branch
1241 i) tip
1241 i) tip
1242
1242
1243 Examples:
1243 Examples:
1244
1244
1245 - clone a remote repository to a new directory named hg/::
1245 - clone a remote repository to a new directory named hg/::
1246
1246
1247 hg clone http://selenic.com/hg
1247 hg clone http://selenic.com/hg
1248
1248
1249 - create a lightweight local clone::
1249 - create a lightweight local clone::
1250
1250
1251 hg clone project/ project-feature/
1251 hg clone project/ project-feature/
1252
1252
1253 - clone from an absolute path on an ssh server (note double-slash)::
1253 - clone from an absolute path on an ssh server (note double-slash)::
1254
1254
1255 hg clone ssh://user@server//home/projects/alpha/
1255 hg clone ssh://user@server//home/projects/alpha/
1256
1256
1257 - do a high-speed clone over a LAN while checking out a
1257 - do a high-speed clone over a LAN while checking out a
1258 specified version::
1258 specified version::
1259
1259
1260 hg clone --uncompressed http://server/repo -u 1.5
1260 hg clone --uncompressed http://server/repo -u 1.5
1261
1261
1262 - create a repository without changesets after a particular revision::
1262 - create a repository without changesets after a particular revision::
1263
1263
1264 hg clone -r 04e544 experimental/ good/
1264 hg clone -r 04e544 experimental/ good/
1265
1265
1266 - clone (and track) a particular named branch::
1266 - clone (and track) a particular named branch::
1267
1267
1268 hg clone http://selenic.com/hg#stable
1268 hg clone http://selenic.com/hg#stable
1269
1269
1270 See :hg:`help urls` for details on specifying URLs.
1270 See :hg:`help urls` for details on specifying URLs.
1271
1271
1272 Returns 0 on success.
1272 Returns 0 on success.
1273 """
1273 """
1274 if opts.get('noupdate') and opts.get('updaterev'):
1274 if opts.get('noupdate') and opts.get('updaterev'):
1275 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1275 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1276
1276
1277 r = hg.clone(ui, opts, source, dest,
1277 r = hg.clone(ui, opts, source, dest,
1278 pull=opts.get('pull'),
1278 pull=opts.get('pull'),
1279 stream=opts.get('uncompressed'),
1279 stream=opts.get('uncompressed'),
1280 rev=opts.get('rev'),
1280 rev=opts.get('rev'),
1281 update=opts.get('updaterev') or not opts.get('noupdate'),
1281 update=opts.get('updaterev') or not opts.get('noupdate'),
1282 branch=opts.get('branch'))
1282 branch=opts.get('branch'))
1283
1283
1284 return r is None
1284 return r is None
1285
1285
1286 @command('^commit|ci',
1286 @command('^commit|ci',
1287 [('A', 'addremove', None,
1287 [('A', 'addremove', None,
1288 _('mark new/missing files as added/removed before committing')),
1288 _('mark new/missing files as added/removed before committing')),
1289 ('', 'close-branch', None,
1289 ('', 'close-branch', None,
1290 _('mark a branch as closed, hiding it from the branch list')),
1290 _('mark a branch as closed, hiding it from the branch list')),
1291 ('', 'amend', None, _('amend the parent of the working dir')),
1291 ('', 'amend', None, _('amend the parent of the working dir')),
1292 ('s', 'secret', None, _('use the secret phase for committing')),
1292 ('s', 'secret', None, _('use the secret phase for committing')),
1293 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1293 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1294 _('[OPTION]... [FILE]...'))
1294 _('[OPTION]... [FILE]...'))
1295 def commit(ui, repo, *pats, **opts):
1295 def commit(ui, repo, *pats, **opts):
1296 """commit the specified files or all outstanding changes
1296 """commit the specified files or all outstanding changes
1297
1297
1298 Commit changes to the given files into the repository. Unlike a
1298 Commit changes to the given files into the repository. Unlike a
1299 centralized SCM, this operation is a local operation. See
1299 centralized SCM, this operation is a local operation. See
1300 :hg:`push` for a way to actively distribute your changes.
1300 :hg:`push` for a way to actively distribute your changes.
1301
1301
1302 If a list of files is omitted, all changes reported by :hg:`status`
1302 If a list of files is omitted, all changes reported by :hg:`status`
1303 will be committed.
1303 will be committed.
1304
1304
1305 If you are committing the result of a merge, do not provide any
1305 If you are committing the result of a merge, do not provide any
1306 filenames or -I/-X filters.
1306 filenames or -I/-X filters.
1307
1307
1308 If no commit message is specified, Mercurial starts your
1308 If no commit message is specified, Mercurial starts your
1309 configured editor where you can enter a message. In case your
1309 configured editor where you can enter a message. In case your
1310 commit fails, you will find a backup of your message in
1310 commit fails, you will find a backup of your message in
1311 ``.hg/last-message.txt``.
1311 ``.hg/last-message.txt``.
1312
1312
1313 The --amend flag can be used to amend the parent of the
1313 The --amend flag can be used to amend the parent of the
1314 working directory with a new commit that contains the changes
1314 working directory with a new commit that contains the changes
1315 in the parent in addition to those currently reported by :hg:`status`,
1315 in the parent in addition to those currently reported by :hg:`status`,
1316 if there are any. The old commit is stored in a backup bundle in
1316 if there are any. The old commit is stored in a backup bundle in
1317 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1317 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1318 on how to restore it).
1318 on how to restore it).
1319
1319
1320 Message, user and date are taken from the amended commit unless
1320 Message, user and date are taken from the amended commit unless
1321 specified. When a message isn't specified on the command line,
1321 specified. When a message isn't specified on the command line,
1322 the editor will open with the message of the amended commit.
1322 the editor will open with the message of the amended commit.
1323
1323
1324 It is not possible to amend public changesets (see :hg:`help phases`)
1324 It is not possible to amend public changesets (see :hg:`help phases`)
1325 or changesets that have children.
1325 or changesets that have children.
1326
1326
1327 See :hg:`help dates` for a list of formats valid for -d/--date.
1327 See :hg:`help dates` for a list of formats valid for -d/--date.
1328
1328
1329 Returns 0 on success, 1 if nothing changed.
1329 Returns 0 on success, 1 if nothing changed.
1330 """
1330 """
1331 if opts.get('subrepos'):
1331 if opts.get('subrepos'):
1332 if opts.get('amend'):
1332 if opts.get('amend'):
1333 raise util.Abort(_('cannot amend with --subrepos'))
1333 raise util.Abort(_('cannot amend with --subrepos'))
1334 # Let --subrepos on the command line override config setting.
1334 # Let --subrepos on the command line override config setting.
1335 ui.setconfig('ui', 'commitsubrepos', True)
1335 ui.setconfig('ui', 'commitsubrepos', True)
1336
1336
1337 # Save this for restoring it later
1337 # Save this for restoring it later
1338 oldcommitphase = ui.config('phases', 'new-commit')
1338 oldcommitphase = ui.config('phases', 'new-commit')
1339
1339
1340 cmdutil.checkunfinished(repo, commit=True)
1340 cmdutil.checkunfinished(repo, commit=True)
1341
1341
1342 branch = repo[None].branch()
1342 branch = repo[None].branch()
1343 bheads = repo.branchheads(branch)
1343 bheads = repo.branchheads(branch)
1344
1344
1345 extra = {}
1345 extra = {}
1346 if opts.get('close_branch'):
1346 if opts.get('close_branch'):
1347 extra['close'] = 1
1347 extra['close'] = 1
1348
1348
1349 if not bheads:
1349 if not bheads:
1350 raise util.Abort(_('can only close branch heads'))
1350 raise util.Abort(_('can only close branch heads'))
1351 elif opts.get('amend'):
1351 elif opts.get('amend'):
1352 if repo.parents()[0].p1().branch() != branch and \
1352 if repo.parents()[0].p1().branch() != branch and \
1353 repo.parents()[0].p2().branch() != branch:
1353 repo.parents()[0].p2().branch() != branch:
1354 raise util.Abort(_('can only close branch heads'))
1354 raise util.Abort(_('can only close branch heads'))
1355
1355
1356 if opts.get('amend'):
1356 if opts.get('amend'):
1357 if ui.configbool('ui', 'commitsubrepos'):
1357 if ui.configbool('ui', 'commitsubrepos'):
1358 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1358 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1359
1359
1360 old = repo['.']
1360 old = repo['.']
1361 if old.phase() == phases.public:
1361 if old.phase() == phases.public:
1362 raise util.Abort(_('cannot amend public changesets'))
1362 raise util.Abort(_('cannot amend public changesets'))
1363 if len(repo[None].parents()) > 1:
1363 if len(repo[None].parents()) > 1:
1364 raise util.Abort(_('cannot amend while merging'))
1364 raise util.Abort(_('cannot amend while merging'))
1365 if (not obsolete._enabled) and old.children():
1365 if (not obsolete._enabled) and old.children():
1366 raise util.Abort(_('cannot amend changeset with children'))
1366 raise util.Abort(_('cannot amend changeset with children'))
1367
1367
1368 e = cmdutil.commiteditor
1368 e = cmdutil.commiteditor
1369 if opts.get('force_editor'):
1369 if opts.get('force_editor'):
1370 e = cmdutil.commitforceeditor
1370 e = cmdutil.commitforceeditor
1371
1371
1372 def commitfunc(ui, repo, message, match, opts):
1372 def commitfunc(ui, repo, message, match, opts):
1373 editor = e
1373 editor = e
1374 # message contains text from -m or -l, if it's empty,
1374 # message contains text from -m or -l, if it's empty,
1375 # open the editor with the old message
1375 # open the editor with the old message
1376 if not message:
1376 if not message:
1377 message = old.description()
1377 message = old.description()
1378 editor = cmdutil.commitforceeditor
1378 editor = cmdutil.commitforceeditor
1379 try:
1379 try:
1380 if opts.get('secret'):
1380 if opts.get('secret'):
1381 ui.setconfig('phases', 'new-commit', 'secret')
1381 ui.setconfig('phases', 'new-commit', 'secret')
1382
1382
1383 return repo.commit(message,
1383 return repo.commit(message,
1384 opts.get('user') or old.user(),
1384 opts.get('user') or old.user(),
1385 opts.get('date') or old.date(),
1385 opts.get('date') or old.date(),
1386 match,
1386 match,
1387 editor=editor,
1387 editor=editor,
1388 extra=extra)
1388 extra=extra)
1389 finally:
1389 finally:
1390 ui.setconfig('phases', 'new-commit', oldcommitphase)
1390 ui.setconfig('phases', 'new-commit', oldcommitphase)
1391
1391
1392 current = repo._bookmarkcurrent
1392 current = repo._bookmarkcurrent
1393 marks = old.bookmarks()
1393 marks = old.bookmarks()
1394 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1394 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1395 if node == old.node():
1395 if node == old.node():
1396 ui.status(_("nothing changed\n"))
1396 ui.status(_("nothing changed\n"))
1397 return 1
1397 return 1
1398 elif marks:
1398 elif marks:
1399 ui.debug('moving bookmarks %r from %s to %s\n' %
1399 ui.debug('moving bookmarks %r from %s to %s\n' %
1400 (marks, old.hex(), hex(node)))
1400 (marks, old.hex(), hex(node)))
1401 newmarks = repo._bookmarks
1401 newmarks = repo._bookmarks
1402 for bm in marks:
1402 for bm in marks:
1403 newmarks[bm] = node
1403 newmarks[bm] = node
1404 if bm == current:
1404 if bm == current:
1405 bookmarks.setcurrent(repo, bm)
1405 bookmarks.setcurrent(repo, bm)
1406 newmarks.write()
1406 newmarks.write()
1407 else:
1407 else:
1408 e = cmdutil.commiteditor
1408 e = cmdutil.commiteditor
1409 if opts.get('force_editor'):
1409 if opts.get('force_editor'):
1410 e = cmdutil.commitforceeditor
1410 e = cmdutil.commitforceeditor
1411
1411
1412 def commitfunc(ui, repo, message, match, opts):
1412 def commitfunc(ui, repo, message, match, opts):
1413 try:
1413 try:
1414 if opts.get('secret'):
1414 if opts.get('secret'):
1415 ui.setconfig('phases', 'new-commit', 'secret')
1415 ui.setconfig('phases', 'new-commit', 'secret')
1416
1416
1417 return repo.commit(message, opts.get('user'), opts.get('date'),
1417 return repo.commit(message, opts.get('user'), opts.get('date'),
1418 match, editor=e, extra=extra)
1418 match, editor=e, extra=extra)
1419 finally:
1419 finally:
1420 ui.setconfig('phases', 'new-commit', oldcommitphase)
1420 ui.setconfig('phases', 'new-commit', oldcommitphase)
1421
1421
1422
1422
1423 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1423 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1424
1424
1425 if not node:
1425 if not node:
1426 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1426 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1427 if stat[3]:
1427 if stat[3]:
1428 ui.status(_("nothing changed (%d missing files, see "
1428 ui.status(_("nothing changed (%d missing files, see "
1429 "'hg status')\n") % len(stat[3]))
1429 "'hg status')\n") % len(stat[3]))
1430 else:
1430 else:
1431 ui.status(_("nothing changed\n"))
1431 ui.status(_("nothing changed\n"))
1432 return 1
1432 return 1
1433
1433
1434 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1434 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1435
1435
1436 @command('copy|cp',
1436 @command('copy|cp',
1437 [('A', 'after', None, _('record a copy that has already occurred')),
1437 [('A', 'after', None, _('record a copy that has already occurred')),
1438 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1438 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1439 ] + walkopts + dryrunopts,
1439 ] + walkopts + dryrunopts,
1440 _('[OPTION]... [SOURCE]... DEST'))
1440 _('[OPTION]... [SOURCE]... DEST'))
1441 def copy(ui, repo, *pats, **opts):
1441 def copy(ui, repo, *pats, **opts):
1442 """mark files as copied for the next commit
1442 """mark files as copied for the next commit
1443
1443
1444 Mark dest as having copies of source files. If dest is a
1444 Mark dest as having copies of source files. If dest is a
1445 directory, copies are put in that directory. If dest is a file,
1445 directory, copies are put in that directory. If dest is a file,
1446 the source must be a single file.
1446 the source must be a single file.
1447
1447
1448 By default, this command copies the contents of files as they
1448 By default, this command copies the contents of files as they
1449 exist in the working directory. If invoked with -A/--after, the
1449 exist in the working directory. If invoked with -A/--after, the
1450 operation is recorded, but no copying is performed.
1450 operation is recorded, but no copying is performed.
1451
1451
1452 This command takes effect with the next commit. To undo a copy
1452 This command takes effect with the next commit. To undo a copy
1453 before that, see :hg:`revert`.
1453 before that, see :hg:`revert`.
1454
1454
1455 Returns 0 on success, 1 if errors are encountered.
1455 Returns 0 on success, 1 if errors are encountered.
1456 """
1456 """
1457 wlock = repo.wlock(False)
1457 wlock = repo.wlock(False)
1458 try:
1458 try:
1459 return cmdutil.copy(ui, repo, pats, opts)
1459 return cmdutil.copy(ui, repo, pats, opts)
1460 finally:
1460 finally:
1461 wlock.release()
1461 wlock.release()
1462
1462
1463 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1463 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1464 def debugancestor(ui, repo, *args):
1464 def debugancestor(ui, repo, *args):
1465 """find the ancestor revision of two revisions in a given index"""
1465 """find the ancestor revision of two revisions in a given index"""
1466 if len(args) == 3:
1466 if len(args) == 3:
1467 index, rev1, rev2 = args
1467 index, rev1, rev2 = args
1468 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1468 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1469 lookup = r.lookup
1469 lookup = r.lookup
1470 elif len(args) == 2:
1470 elif len(args) == 2:
1471 if not repo:
1471 if not repo:
1472 raise util.Abort(_("there is no Mercurial repository here "
1472 raise util.Abort(_("there is no Mercurial repository here "
1473 "(.hg not found)"))
1473 "(.hg not found)"))
1474 rev1, rev2 = args
1474 rev1, rev2 = args
1475 r = repo.changelog
1475 r = repo.changelog
1476 lookup = repo.lookup
1476 lookup = repo.lookup
1477 else:
1477 else:
1478 raise util.Abort(_('either two or three arguments required'))
1478 raise util.Abort(_('either two or three arguments required'))
1479 a = r.ancestor(lookup(rev1), lookup(rev2))
1479 a = r.ancestor(lookup(rev1), lookup(rev2))
1480 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1480 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1481
1481
1482 @command('debugbuilddag',
1482 @command('debugbuilddag',
1483 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1483 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1484 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1484 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1485 ('n', 'new-file', None, _('add new file at each rev'))],
1485 ('n', 'new-file', None, _('add new file at each rev'))],
1486 _('[OPTION]... [TEXT]'))
1486 _('[OPTION]... [TEXT]'))
1487 def debugbuilddag(ui, repo, text=None,
1487 def debugbuilddag(ui, repo, text=None,
1488 mergeable_file=False,
1488 mergeable_file=False,
1489 overwritten_file=False,
1489 overwritten_file=False,
1490 new_file=False):
1490 new_file=False):
1491 """builds a repo with a given DAG from scratch in the current empty repo
1491 """builds a repo with a given DAG from scratch in the current empty repo
1492
1492
1493 The description of the DAG is read from stdin if not given on the
1493 The description of the DAG is read from stdin if not given on the
1494 command line.
1494 command line.
1495
1495
1496 Elements:
1496 Elements:
1497
1497
1498 - "+n" is a linear run of n nodes based on the current default parent
1498 - "+n" is a linear run of n nodes based on the current default parent
1499 - "." is a single node based on the current default parent
1499 - "." is a single node based on the current default parent
1500 - "$" resets the default parent to null (implied at the start);
1500 - "$" resets the default parent to null (implied at the start);
1501 otherwise the default parent is always the last node created
1501 otherwise the default parent is always the last node created
1502 - "<p" sets the default parent to the backref p
1502 - "<p" sets the default parent to the backref p
1503 - "*p" is a fork at parent p, which is a backref
1503 - "*p" is a fork at parent p, which is a backref
1504 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1504 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1505 - "/p2" is a merge of the preceding node and p2
1505 - "/p2" is a merge of the preceding node and p2
1506 - ":tag" defines a local tag for the preceding node
1506 - ":tag" defines a local tag for the preceding node
1507 - "@branch" sets the named branch for subsequent nodes
1507 - "@branch" sets the named branch for subsequent nodes
1508 - "#...\\n" is a comment up to the end of the line
1508 - "#...\\n" is a comment up to the end of the line
1509
1509
1510 Whitespace between the above elements is ignored.
1510 Whitespace between the above elements is ignored.
1511
1511
1512 A backref is either
1512 A backref is either
1513
1513
1514 - a number n, which references the node curr-n, where curr is the current
1514 - a number n, which references the node curr-n, where curr is the current
1515 node, or
1515 node, or
1516 - the name of a local tag you placed earlier using ":tag", or
1516 - the name of a local tag you placed earlier using ":tag", or
1517 - empty to denote the default parent.
1517 - empty to denote the default parent.
1518
1518
1519 All string valued-elements are either strictly alphanumeric, or must
1519 All string valued-elements are either strictly alphanumeric, or must
1520 be enclosed in double quotes ("..."), with "\\" as escape character.
1520 be enclosed in double quotes ("..."), with "\\" as escape character.
1521 """
1521 """
1522
1522
1523 if text is None:
1523 if text is None:
1524 ui.status(_("reading DAG from stdin\n"))
1524 ui.status(_("reading DAG from stdin\n"))
1525 text = ui.fin.read()
1525 text = ui.fin.read()
1526
1526
1527 cl = repo.changelog
1527 cl = repo.changelog
1528 if len(cl) > 0:
1528 if len(cl) > 0:
1529 raise util.Abort(_('repository is not empty'))
1529 raise util.Abort(_('repository is not empty'))
1530
1530
1531 # determine number of revs in DAG
1531 # determine number of revs in DAG
1532 total = 0
1532 total = 0
1533 for type, data in dagparser.parsedag(text):
1533 for type, data in dagparser.parsedag(text):
1534 if type == 'n':
1534 if type == 'n':
1535 total += 1
1535 total += 1
1536
1536
1537 if mergeable_file:
1537 if mergeable_file:
1538 linesperrev = 2
1538 linesperrev = 2
1539 # make a file with k lines per rev
1539 # make a file with k lines per rev
1540 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1540 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1541 initialmergedlines.append("")
1541 initialmergedlines.append("")
1542
1542
1543 tags = []
1543 tags = []
1544
1544
1545 lock = tr = None
1545 lock = tr = None
1546 try:
1546 try:
1547 lock = repo.lock()
1547 lock = repo.lock()
1548 tr = repo.transaction("builddag")
1548 tr = repo.transaction("builddag")
1549
1549
1550 at = -1
1550 at = -1
1551 atbranch = 'default'
1551 atbranch = 'default'
1552 nodeids = []
1552 nodeids = []
1553 id = 0
1553 id = 0
1554 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1554 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1555 for type, data in dagparser.parsedag(text):
1555 for type, data in dagparser.parsedag(text):
1556 if type == 'n':
1556 if type == 'n':
1557 ui.note(('node %s\n' % str(data)))
1557 ui.note(('node %s\n' % str(data)))
1558 id, ps = data
1558 id, ps = data
1559
1559
1560 files = []
1560 files = []
1561 fctxs = {}
1561 fctxs = {}
1562
1562
1563 p2 = None
1563 p2 = None
1564 if mergeable_file:
1564 if mergeable_file:
1565 fn = "mf"
1565 fn = "mf"
1566 p1 = repo[ps[0]]
1566 p1 = repo[ps[0]]
1567 if len(ps) > 1:
1567 if len(ps) > 1:
1568 p2 = repo[ps[1]]
1568 p2 = repo[ps[1]]
1569 pa = p1.ancestor(p2)
1569 pa = p1.ancestor(p2)
1570 base, local, other = [x[fn].data() for x in (pa, p1,
1570 base, local, other = [x[fn].data() for x in (pa, p1,
1571 p2)]
1571 p2)]
1572 m3 = simplemerge.Merge3Text(base, local, other)
1572 m3 = simplemerge.Merge3Text(base, local, other)
1573 ml = [l.strip() for l in m3.merge_lines()]
1573 ml = [l.strip() for l in m3.merge_lines()]
1574 ml.append("")
1574 ml.append("")
1575 elif at > 0:
1575 elif at > 0:
1576 ml = p1[fn].data().split("\n")
1576 ml = p1[fn].data().split("\n")
1577 else:
1577 else:
1578 ml = initialmergedlines
1578 ml = initialmergedlines
1579 ml[id * linesperrev] += " r%i" % id
1579 ml[id * linesperrev] += " r%i" % id
1580 mergedtext = "\n".join(ml)
1580 mergedtext = "\n".join(ml)
1581 files.append(fn)
1581 files.append(fn)
1582 fctxs[fn] = context.memfilectx(fn, mergedtext)
1582 fctxs[fn] = context.memfilectx(fn, mergedtext)
1583
1583
1584 if overwritten_file:
1584 if overwritten_file:
1585 fn = "of"
1585 fn = "of"
1586 files.append(fn)
1586 files.append(fn)
1587 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1587 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1588
1588
1589 if new_file:
1589 if new_file:
1590 fn = "nf%i" % id
1590 fn = "nf%i" % id
1591 files.append(fn)
1591 files.append(fn)
1592 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1592 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1593 if len(ps) > 1:
1593 if len(ps) > 1:
1594 if not p2:
1594 if not p2:
1595 p2 = repo[ps[1]]
1595 p2 = repo[ps[1]]
1596 for fn in p2:
1596 for fn in p2:
1597 if fn.startswith("nf"):
1597 if fn.startswith("nf"):
1598 files.append(fn)
1598 files.append(fn)
1599 fctxs[fn] = p2[fn]
1599 fctxs[fn] = p2[fn]
1600
1600
1601 def fctxfn(repo, cx, path):
1601 def fctxfn(repo, cx, path):
1602 return fctxs.get(path)
1602 return fctxs.get(path)
1603
1603
1604 if len(ps) == 0 or ps[0] < 0:
1604 if len(ps) == 0 or ps[0] < 0:
1605 pars = [None, None]
1605 pars = [None, None]
1606 elif len(ps) == 1:
1606 elif len(ps) == 1:
1607 pars = [nodeids[ps[0]], None]
1607 pars = [nodeids[ps[0]], None]
1608 else:
1608 else:
1609 pars = [nodeids[p] for p in ps]
1609 pars = [nodeids[p] for p in ps]
1610 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1610 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1611 date=(id, 0),
1611 date=(id, 0),
1612 user="debugbuilddag",
1612 user="debugbuilddag",
1613 extra={'branch': atbranch})
1613 extra={'branch': atbranch})
1614 nodeid = repo.commitctx(cx)
1614 nodeid = repo.commitctx(cx)
1615 nodeids.append(nodeid)
1615 nodeids.append(nodeid)
1616 at = id
1616 at = id
1617 elif type == 'l':
1617 elif type == 'l':
1618 id, name = data
1618 id, name = data
1619 ui.note(('tag %s\n' % name))
1619 ui.note(('tag %s\n' % name))
1620 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1620 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1621 elif type == 'a':
1621 elif type == 'a':
1622 ui.note(('branch %s\n' % data))
1622 ui.note(('branch %s\n' % data))
1623 atbranch = data
1623 atbranch = data
1624 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1624 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1625 tr.close()
1625 tr.close()
1626
1626
1627 if tags:
1627 if tags:
1628 repo.opener.write("localtags", "".join(tags))
1628 repo.opener.write("localtags", "".join(tags))
1629 finally:
1629 finally:
1630 ui.progress(_('building'), None)
1630 ui.progress(_('building'), None)
1631 release(tr, lock)
1631 release(tr, lock)
1632
1632
1633 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1633 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1634 def debugbundle(ui, bundlepath, all=None, **opts):
1634 def debugbundle(ui, bundlepath, all=None, **opts):
1635 """lists the contents of a bundle"""
1635 """lists the contents of a bundle"""
1636 f = hg.openpath(ui, bundlepath)
1636 f = hg.openpath(ui, bundlepath)
1637 try:
1637 try:
1638 gen = changegroup.readbundle(f, bundlepath)
1638 gen = changegroup.readbundle(f, bundlepath)
1639 if all:
1639 if all:
1640 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1640 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1641
1641
1642 def showchunks(named):
1642 def showchunks(named):
1643 ui.write("\n%s\n" % named)
1643 ui.write("\n%s\n" % named)
1644 chain = None
1644 chain = None
1645 while True:
1645 while True:
1646 chunkdata = gen.deltachunk(chain)
1646 chunkdata = gen.deltachunk(chain)
1647 if not chunkdata:
1647 if not chunkdata:
1648 break
1648 break
1649 node = chunkdata['node']
1649 node = chunkdata['node']
1650 p1 = chunkdata['p1']
1650 p1 = chunkdata['p1']
1651 p2 = chunkdata['p2']
1651 p2 = chunkdata['p2']
1652 cs = chunkdata['cs']
1652 cs = chunkdata['cs']
1653 deltabase = chunkdata['deltabase']
1653 deltabase = chunkdata['deltabase']
1654 delta = chunkdata['delta']
1654 delta = chunkdata['delta']
1655 ui.write("%s %s %s %s %s %s\n" %
1655 ui.write("%s %s %s %s %s %s\n" %
1656 (hex(node), hex(p1), hex(p2),
1656 (hex(node), hex(p1), hex(p2),
1657 hex(cs), hex(deltabase), len(delta)))
1657 hex(cs), hex(deltabase), len(delta)))
1658 chain = node
1658 chain = node
1659
1659
1660 chunkdata = gen.changelogheader()
1660 chunkdata = gen.changelogheader()
1661 showchunks("changelog")
1661 showchunks("changelog")
1662 chunkdata = gen.manifestheader()
1662 chunkdata = gen.manifestheader()
1663 showchunks("manifest")
1663 showchunks("manifest")
1664 while True:
1664 while True:
1665 chunkdata = gen.filelogheader()
1665 chunkdata = gen.filelogheader()
1666 if not chunkdata:
1666 if not chunkdata:
1667 break
1667 break
1668 fname = chunkdata['filename']
1668 fname = chunkdata['filename']
1669 showchunks(fname)
1669 showchunks(fname)
1670 else:
1670 else:
1671 chunkdata = gen.changelogheader()
1671 chunkdata = gen.changelogheader()
1672 chain = None
1672 chain = None
1673 while True:
1673 while True:
1674 chunkdata = gen.deltachunk(chain)
1674 chunkdata = gen.deltachunk(chain)
1675 if not chunkdata:
1675 if not chunkdata:
1676 break
1676 break
1677 node = chunkdata['node']
1677 node = chunkdata['node']
1678 ui.write("%s\n" % hex(node))
1678 ui.write("%s\n" % hex(node))
1679 chain = node
1679 chain = node
1680 finally:
1680 finally:
1681 f.close()
1681 f.close()
1682
1682
1683 @command('debugcheckstate', [], '')
1683 @command('debugcheckstate', [], '')
1684 def debugcheckstate(ui, repo):
1684 def debugcheckstate(ui, repo):
1685 """validate the correctness of the current dirstate"""
1685 """validate the correctness of the current dirstate"""
1686 parent1, parent2 = repo.dirstate.parents()
1686 parent1, parent2 = repo.dirstate.parents()
1687 m1 = repo[parent1].manifest()
1687 m1 = repo[parent1].manifest()
1688 m2 = repo[parent2].manifest()
1688 m2 = repo[parent2].manifest()
1689 errors = 0
1689 errors = 0
1690 for f in repo.dirstate:
1690 for f in repo.dirstate:
1691 state = repo.dirstate[f]
1691 state = repo.dirstate[f]
1692 if state in "nr" and f not in m1:
1692 if state in "nr" and f not in m1:
1693 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1693 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1694 errors += 1
1694 errors += 1
1695 if state in "a" and f in m1:
1695 if state in "a" and f in m1:
1696 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1696 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1697 errors += 1
1697 errors += 1
1698 if state in "m" and f not in m1 and f not in m2:
1698 if state in "m" and f not in m1 and f not in m2:
1699 ui.warn(_("%s in state %s, but not in either manifest\n") %
1699 ui.warn(_("%s in state %s, but not in either manifest\n") %
1700 (f, state))
1700 (f, state))
1701 errors += 1
1701 errors += 1
1702 for f in m1:
1702 for f in m1:
1703 state = repo.dirstate[f]
1703 state = repo.dirstate[f]
1704 if state not in "nrm":
1704 if state not in "nrm":
1705 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1705 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1706 errors += 1
1706 errors += 1
1707 if errors:
1707 if errors:
1708 error = _(".hg/dirstate inconsistent with current parent's manifest")
1708 error = _(".hg/dirstate inconsistent with current parent's manifest")
1709 raise util.Abort(error)
1709 raise util.Abort(error)
1710
1710
1711 @command('debugcommands', [], _('[COMMAND]'))
1711 @command('debugcommands', [], _('[COMMAND]'))
1712 def debugcommands(ui, cmd='', *args):
1712 def debugcommands(ui, cmd='', *args):
1713 """list all available commands and options"""
1713 """list all available commands and options"""
1714 for cmd, vals in sorted(table.iteritems()):
1714 for cmd, vals in sorted(table.iteritems()):
1715 cmd = cmd.split('|')[0].strip('^')
1715 cmd = cmd.split('|')[0].strip('^')
1716 opts = ', '.join([i[1] for i in vals[1]])
1716 opts = ', '.join([i[1] for i in vals[1]])
1717 ui.write('%s: %s\n' % (cmd, opts))
1717 ui.write('%s: %s\n' % (cmd, opts))
1718
1718
1719 @command('debugcomplete',
1719 @command('debugcomplete',
1720 [('o', 'options', None, _('show the command options'))],
1720 [('o', 'options', None, _('show the command options'))],
1721 _('[-o] CMD'))
1721 _('[-o] CMD'))
1722 def debugcomplete(ui, cmd='', **opts):
1722 def debugcomplete(ui, cmd='', **opts):
1723 """returns the completion list associated with the given command"""
1723 """returns the completion list associated with the given command"""
1724
1724
1725 if opts.get('options'):
1725 if opts.get('options'):
1726 options = []
1726 options = []
1727 otables = [globalopts]
1727 otables = [globalopts]
1728 if cmd:
1728 if cmd:
1729 aliases, entry = cmdutil.findcmd(cmd, table, False)
1729 aliases, entry = cmdutil.findcmd(cmd, table, False)
1730 otables.append(entry[1])
1730 otables.append(entry[1])
1731 for t in otables:
1731 for t in otables:
1732 for o in t:
1732 for o in t:
1733 if "(DEPRECATED)" in o[3]:
1733 if "(DEPRECATED)" in o[3]:
1734 continue
1734 continue
1735 if o[0]:
1735 if o[0]:
1736 options.append('-%s' % o[0])
1736 options.append('-%s' % o[0])
1737 options.append('--%s' % o[1])
1737 options.append('--%s' % o[1])
1738 ui.write("%s\n" % "\n".join(options))
1738 ui.write("%s\n" % "\n".join(options))
1739 return
1739 return
1740
1740
1741 cmdlist = cmdutil.findpossible(cmd, table)
1741 cmdlist = cmdutil.findpossible(cmd, table)
1742 if ui.verbose:
1742 if ui.verbose:
1743 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1743 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1744 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1744 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1745
1745
1746 @command('debugdag',
1746 @command('debugdag',
1747 [('t', 'tags', None, _('use tags as labels')),
1747 [('t', 'tags', None, _('use tags as labels')),
1748 ('b', 'branches', None, _('annotate with branch names')),
1748 ('b', 'branches', None, _('annotate with branch names')),
1749 ('', 'dots', None, _('use dots for runs')),
1749 ('', 'dots', None, _('use dots for runs')),
1750 ('s', 'spaces', None, _('separate elements by spaces'))],
1750 ('s', 'spaces', None, _('separate elements by spaces'))],
1751 _('[OPTION]... [FILE [REV]...]'))
1751 _('[OPTION]... [FILE [REV]...]'))
1752 def debugdag(ui, repo, file_=None, *revs, **opts):
1752 def debugdag(ui, repo, file_=None, *revs, **opts):
1753 """format the changelog or an index DAG as a concise textual description
1753 """format the changelog or an index DAG as a concise textual description
1754
1754
1755 If you pass a revlog index, the revlog's DAG is emitted. If you list
1755 If you pass a revlog index, the revlog's DAG is emitted. If you list
1756 revision numbers, they get labeled in the output as rN.
1756 revision numbers, they get labeled in the output as rN.
1757
1757
1758 Otherwise, the changelog DAG of the current repo is emitted.
1758 Otherwise, the changelog DAG of the current repo is emitted.
1759 """
1759 """
1760 spaces = opts.get('spaces')
1760 spaces = opts.get('spaces')
1761 dots = opts.get('dots')
1761 dots = opts.get('dots')
1762 if file_:
1762 if file_:
1763 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1763 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1764 revs = set((int(r) for r in revs))
1764 revs = set((int(r) for r in revs))
1765 def events():
1765 def events():
1766 for r in rlog:
1766 for r in rlog:
1767 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1767 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1768 if p != -1)))
1768 if p != -1)))
1769 if r in revs:
1769 if r in revs:
1770 yield 'l', (r, "r%i" % r)
1770 yield 'l', (r, "r%i" % r)
1771 elif repo:
1771 elif repo:
1772 cl = repo.changelog
1772 cl = repo.changelog
1773 tags = opts.get('tags')
1773 tags = opts.get('tags')
1774 branches = opts.get('branches')
1774 branches = opts.get('branches')
1775 if tags:
1775 if tags:
1776 labels = {}
1776 labels = {}
1777 for l, n in repo.tags().items():
1777 for l, n in repo.tags().items():
1778 labels.setdefault(cl.rev(n), []).append(l)
1778 labels.setdefault(cl.rev(n), []).append(l)
1779 def events():
1779 def events():
1780 b = "default"
1780 b = "default"
1781 for r in cl:
1781 for r in cl:
1782 if branches:
1782 if branches:
1783 newb = cl.read(cl.node(r))[5]['branch']
1783 newb = cl.read(cl.node(r))[5]['branch']
1784 if newb != b:
1784 if newb != b:
1785 yield 'a', newb
1785 yield 'a', newb
1786 b = newb
1786 b = newb
1787 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1787 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1788 if p != -1)))
1788 if p != -1)))
1789 if tags:
1789 if tags:
1790 ls = labels.get(r)
1790 ls = labels.get(r)
1791 if ls:
1791 if ls:
1792 for l in ls:
1792 for l in ls:
1793 yield 'l', (r, l)
1793 yield 'l', (r, l)
1794 else:
1794 else:
1795 raise util.Abort(_('need repo for changelog dag'))
1795 raise util.Abort(_('need repo for changelog dag'))
1796
1796
1797 for line in dagparser.dagtextlines(events(),
1797 for line in dagparser.dagtextlines(events(),
1798 addspaces=spaces,
1798 addspaces=spaces,
1799 wraplabels=True,
1799 wraplabels=True,
1800 wrapannotations=True,
1800 wrapannotations=True,
1801 wrapnonlinear=dots,
1801 wrapnonlinear=dots,
1802 usedots=dots,
1802 usedots=dots,
1803 maxlinewidth=70):
1803 maxlinewidth=70):
1804 ui.write(line)
1804 ui.write(line)
1805 ui.write("\n")
1805 ui.write("\n")
1806
1806
1807 @command('debugdata',
1807 @command('debugdata',
1808 [('c', 'changelog', False, _('open changelog')),
1808 [('c', 'changelog', False, _('open changelog')),
1809 ('m', 'manifest', False, _('open manifest'))],
1809 ('m', 'manifest', False, _('open manifest'))],
1810 _('-c|-m|FILE REV'))
1810 _('-c|-m|FILE REV'))
1811 def debugdata(ui, repo, file_, rev=None, **opts):
1811 def debugdata(ui, repo, file_, rev=None, **opts):
1812 """dump the contents of a data file revision"""
1812 """dump the contents of a data file revision"""
1813 if opts.get('changelog') or opts.get('manifest'):
1813 if opts.get('changelog') or opts.get('manifest'):
1814 file_, rev = None, file_
1814 file_, rev = None, file_
1815 elif rev is None:
1815 elif rev is None:
1816 raise error.CommandError('debugdata', _('invalid arguments'))
1816 raise error.CommandError('debugdata', _('invalid arguments'))
1817 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1817 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1818 try:
1818 try:
1819 ui.write(r.revision(r.lookup(rev)))
1819 ui.write(r.revision(r.lookup(rev)))
1820 except KeyError:
1820 except KeyError:
1821 raise util.Abort(_('invalid revision identifier %s') % rev)
1821 raise util.Abort(_('invalid revision identifier %s') % rev)
1822
1822
1823 @command('debugdate',
1823 @command('debugdate',
1824 [('e', 'extended', None, _('try extended date formats'))],
1824 [('e', 'extended', None, _('try extended date formats'))],
1825 _('[-e] DATE [RANGE]'))
1825 _('[-e] DATE [RANGE]'))
1826 def debugdate(ui, date, range=None, **opts):
1826 def debugdate(ui, date, range=None, **opts):
1827 """parse and display a date"""
1827 """parse and display a date"""
1828 if opts["extended"]:
1828 if opts["extended"]:
1829 d = util.parsedate(date, util.extendeddateformats)
1829 d = util.parsedate(date, util.extendeddateformats)
1830 else:
1830 else:
1831 d = util.parsedate(date)
1831 d = util.parsedate(date)
1832 ui.write(("internal: %s %s\n") % d)
1832 ui.write(("internal: %s %s\n") % d)
1833 ui.write(("standard: %s\n") % util.datestr(d))
1833 ui.write(("standard: %s\n") % util.datestr(d))
1834 if range:
1834 if range:
1835 m = util.matchdate(range)
1835 m = util.matchdate(range)
1836 ui.write(("match: %s\n") % m(d[0]))
1836 ui.write(("match: %s\n") % m(d[0]))
1837
1837
1838 @command('debugdiscovery',
1838 @command('debugdiscovery',
1839 [('', 'old', None, _('use old-style discovery')),
1839 [('', 'old', None, _('use old-style discovery')),
1840 ('', 'nonheads', None,
1840 ('', 'nonheads', None,
1841 _('use old-style discovery with non-heads included')),
1841 _('use old-style discovery with non-heads included')),
1842 ] + remoteopts,
1842 ] + remoteopts,
1843 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1843 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1844 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1844 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1845 """runs the changeset discovery protocol in isolation"""
1845 """runs the changeset discovery protocol in isolation"""
1846 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1846 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1847 opts.get('branch'))
1847 opts.get('branch'))
1848 remote = hg.peer(repo, opts, remoteurl)
1848 remote = hg.peer(repo, opts, remoteurl)
1849 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1849 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1850
1850
1851 # make sure tests are repeatable
1851 # make sure tests are repeatable
1852 random.seed(12323)
1852 random.seed(12323)
1853
1853
1854 def doit(localheads, remoteheads, remote=remote):
1854 def doit(localheads, remoteheads, remote=remote):
1855 if opts.get('old'):
1855 if opts.get('old'):
1856 if localheads:
1856 if localheads:
1857 raise util.Abort('cannot use localheads with old style '
1857 raise util.Abort('cannot use localheads with old style '
1858 'discovery')
1858 'discovery')
1859 if not util.safehasattr(remote, 'branches'):
1859 if not util.safehasattr(remote, 'branches'):
1860 # enable in-client legacy support
1860 # enable in-client legacy support
1861 remote = localrepo.locallegacypeer(remote.local())
1861 remote = localrepo.locallegacypeer(remote.local())
1862 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1862 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1863 force=True)
1863 force=True)
1864 common = set(common)
1864 common = set(common)
1865 if not opts.get('nonheads'):
1865 if not opts.get('nonheads'):
1866 ui.write(("unpruned common: %s\n") %
1866 ui.write(("unpruned common: %s\n") %
1867 " ".join(sorted(short(n) for n in common)))
1867 " ".join(sorted(short(n) for n in common)))
1868 dag = dagutil.revlogdag(repo.changelog)
1868 dag = dagutil.revlogdag(repo.changelog)
1869 all = dag.ancestorset(dag.internalizeall(common))
1869 all = dag.ancestorset(dag.internalizeall(common))
1870 common = dag.externalizeall(dag.headsetofconnecteds(all))
1870 common = dag.externalizeall(dag.headsetofconnecteds(all))
1871 else:
1871 else:
1872 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1872 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1873 common = set(common)
1873 common = set(common)
1874 rheads = set(hds)
1874 rheads = set(hds)
1875 lheads = set(repo.heads())
1875 lheads = set(repo.heads())
1876 ui.write(("common heads: %s\n") %
1876 ui.write(("common heads: %s\n") %
1877 " ".join(sorted(short(n) for n in common)))
1877 " ".join(sorted(short(n) for n in common)))
1878 if lheads <= common:
1878 if lheads <= common:
1879 ui.write(("local is subset\n"))
1879 ui.write(("local is subset\n"))
1880 elif rheads <= common:
1880 elif rheads <= common:
1881 ui.write(("remote is subset\n"))
1881 ui.write(("remote is subset\n"))
1882
1882
1883 serverlogs = opts.get('serverlog')
1883 serverlogs = opts.get('serverlog')
1884 if serverlogs:
1884 if serverlogs:
1885 for filename in serverlogs:
1885 for filename in serverlogs:
1886 logfile = open(filename, 'r')
1886 logfile = open(filename, 'r')
1887 try:
1887 try:
1888 line = logfile.readline()
1888 line = logfile.readline()
1889 while line:
1889 while line:
1890 parts = line.strip().split(';')
1890 parts = line.strip().split(';')
1891 op = parts[1]
1891 op = parts[1]
1892 if op == 'cg':
1892 if op == 'cg':
1893 pass
1893 pass
1894 elif op == 'cgss':
1894 elif op == 'cgss':
1895 doit(parts[2].split(' '), parts[3].split(' '))
1895 doit(parts[2].split(' '), parts[3].split(' '))
1896 elif op == 'unb':
1896 elif op == 'unb':
1897 doit(parts[3].split(' '), parts[2].split(' '))
1897 doit(parts[3].split(' '), parts[2].split(' '))
1898 line = logfile.readline()
1898 line = logfile.readline()
1899 finally:
1899 finally:
1900 logfile.close()
1900 logfile.close()
1901
1901
1902 else:
1902 else:
1903 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1903 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1904 opts.get('remote_head'))
1904 opts.get('remote_head'))
1905 localrevs = opts.get('local_head')
1905 localrevs = opts.get('local_head')
1906 doit(localrevs, remoterevs)
1906 doit(localrevs, remoterevs)
1907
1907
1908 @command('debugfileset',
1908 @command('debugfileset',
1909 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1909 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1910 _('[-r REV] FILESPEC'))
1910 _('[-r REV] FILESPEC'))
1911 def debugfileset(ui, repo, expr, **opts):
1911 def debugfileset(ui, repo, expr, **opts):
1912 '''parse and apply a fileset specification'''
1912 '''parse and apply a fileset specification'''
1913 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1913 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1914 if ui.verbose:
1914 if ui.verbose:
1915 tree = fileset.parse(expr)[0]
1915 tree = fileset.parse(expr)[0]
1916 ui.note(tree, "\n")
1916 ui.note(tree, "\n")
1917
1917
1918 for f in fileset.getfileset(ctx, expr):
1918 for f in fileset.getfileset(ctx, expr):
1919 ui.write("%s\n" % f)
1919 ui.write("%s\n" % f)
1920
1920
1921 @command('debugfsinfo', [], _('[PATH]'))
1921 @command('debugfsinfo', [], _('[PATH]'))
1922 def debugfsinfo(ui, path="."):
1922 def debugfsinfo(ui, path="."):
1923 """show information detected about current filesystem"""
1923 """show information detected about current filesystem"""
1924 util.writefile('.debugfsinfo', '')
1924 util.writefile('.debugfsinfo', '')
1925 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1925 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1926 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1926 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1927 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1927 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1928 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1928 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1929 and 'yes' or 'no'))
1929 and 'yes' or 'no'))
1930 os.unlink('.debugfsinfo')
1930 os.unlink('.debugfsinfo')
1931
1931
1932 @command('debuggetbundle',
1932 @command('debuggetbundle',
1933 [('H', 'head', [], _('id of head node'), _('ID')),
1933 [('H', 'head', [], _('id of head node'), _('ID')),
1934 ('C', 'common', [], _('id of common node'), _('ID')),
1934 ('C', 'common', [], _('id of common node'), _('ID')),
1935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1936 _('REPO FILE [-H|-C ID]...'))
1936 _('REPO FILE [-H|-C ID]...'))
1937 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1937 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1938 """retrieves a bundle from a repo
1938 """retrieves a bundle from a repo
1939
1939
1940 Every ID must be a full-length hex node id string. Saves the bundle to the
1940 Every ID must be a full-length hex node id string. Saves the bundle to the
1941 given file.
1941 given file.
1942 """
1942 """
1943 repo = hg.peer(ui, opts, repopath)
1943 repo = hg.peer(ui, opts, repopath)
1944 if not repo.capable('getbundle'):
1944 if not repo.capable('getbundle'):
1945 raise util.Abort("getbundle() not supported by target repository")
1945 raise util.Abort("getbundle() not supported by target repository")
1946 args = {}
1946 args = {}
1947 if common:
1947 if common:
1948 args['common'] = [bin(s) for s in common]
1948 args['common'] = [bin(s) for s in common]
1949 if head:
1949 if head:
1950 args['heads'] = [bin(s) for s in head]
1950 args['heads'] = [bin(s) for s in head]
1951 # TODO: get desired bundlecaps from command line.
1951 # TODO: get desired bundlecaps from command line.
1952 args['bundlecaps'] = None
1952 args['bundlecaps'] = None
1953 bundle = repo.getbundle('debug', **args)
1953 bundle = repo.getbundle('debug', **args)
1954
1954
1955 bundletype = opts.get('type', 'bzip2').lower()
1955 bundletype = opts.get('type', 'bzip2').lower()
1956 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1956 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1957 bundletype = btypes.get(bundletype)
1957 bundletype = btypes.get(bundletype)
1958 if bundletype not in changegroup.bundletypes:
1958 if bundletype not in changegroup.bundletypes:
1959 raise util.Abort(_('unknown bundle type specified with --type'))
1959 raise util.Abort(_('unknown bundle type specified with --type'))
1960 changegroup.writebundle(bundle, bundlepath, bundletype)
1960 changegroup.writebundle(bundle, bundlepath, bundletype)
1961
1961
1962 @command('debugignore', [], '')
1962 @command('debugignore', [], '')
1963 def debugignore(ui, repo, *values, **opts):
1963 def debugignore(ui, repo, *values, **opts):
1964 """display the combined ignore pattern"""
1964 """display the combined ignore pattern"""
1965 ignore = repo.dirstate._ignore
1965 ignore = repo.dirstate._ignore
1966 includepat = getattr(ignore, 'includepat', None)
1966 includepat = getattr(ignore, 'includepat', None)
1967 if includepat is not None:
1967 if includepat is not None:
1968 ui.write("%s\n" % includepat)
1968 ui.write("%s\n" % includepat)
1969 else:
1969 else:
1970 raise util.Abort(_("no ignore patterns found"))
1970 raise util.Abort(_("no ignore patterns found"))
1971
1971
1972 @command('debugindex',
1972 @command('debugindex',
1973 [('c', 'changelog', False, _('open changelog')),
1973 [('c', 'changelog', False, _('open changelog')),
1974 ('m', 'manifest', False, _('open manifest')),
1974 ('m', 'manifest', False, _('open manifest')),
1975 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1975 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1976 _('[-f FORMAT] -c|-m|FILE'))
1976 _('[-f FORMAT] -c|-m|FILE'))
1977 def debugindex(ui, repo, file_=None, **opts):
1977 def debugindex(ui, repo, file_=None, **opts):
1978 """dump the contents of an index file"""
1978 """dump the contents of an index file"""
1979 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1979 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1980 format = opts.get('format', 0)
1980 format = opts.get('format', 0)
1981 if format not in (0, 1):
1981 if format not in (0, 1):
1982 raise util.Abort(_("unknown format %d") % format)
1982 raise util.Abort(_("unknown format %d") % format)
1983
1983
1984 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1984 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1985 if generaldelta:
1985 if generaldelta:
1986 basehdr = ' delta'
1986 basehdr = ' delta'
1987 else:
1987 else:
1988 basehdr = ' base'
1988 basehdr = ' base'
1989
1989
1990 if format == 0:
1990 if format == 0:
1991 ui.write(" rev offset length " + basehdr + " linkrev"
1991 ui.write(" rev offset length " + basehdr + " linkrev"
1992 " nodeid p1 p2\n")
1992 " nodeid p1 p2\n")
1993 elif format == 1:
1993 elif format == 1:
1994 ui.write(" rev flag offset length"
1994 ui.write(" rev flag offset length"
1995 " size " + basehdr + " link p1 p2"
1995 " size " + basehdr + " link p1 p2"
1996 " nodeid\n")
1996 " nodeid\n")
1997
1997
1998 for i in r:
1998 for i in r:
1999 node = r.node(i)
1999 node = r.node(i)
2000 if generaldelta:
2000 if generaldelta:
2001 base = r.deltaparent(i)
2001 base = r.deltaparent(i)
2002 else:
2002 else:
2003 base = r.chainbase(i)
2003 base = r.chainbase(i)
2004 if format == 0:
2004 if format == 0:
2005 try:
2005 try:
2006 pp = r.parents(node)
2006 pp = r.parents(node)
2007 except Exception:
2007 except Exception:
2008 pp = [nullid, nullid]
2008 pp = [nullid, nullid]
2009 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2009 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2010 i, r.start(i), r.length(i), base, r.linkrev(i),
2010 i, r.start(i), r.length(i), base, r.linkrev(i),
2011 short(node), short(pp[0]), short(pp[1])))
2011 short(node), short(pp[0]), short(pp[1])))
2012 elif format == 1:
2012 elif format == 1:
2013 pr = r.parentrevs(i)
2013 pr = r.parentrevs(i)
2014 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2014 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2015 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2015 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2016 base, r.linkrev(i), pr[0], pr[1], short(node)))
2016 base, r.linkrev(i), pr[0], pr[1], short(node)))
2017
2017
2018 @command('debugindexdot', [], _('FILE'))
2018 @command('debugindexdot', [], _('FILE'))
2019 def debugindexdot(ui, repo, file_):
2019 def debugindexdot(ui, repo, file_):
2020 """dump an index DAG as a graphviz dot file"""
2020 """dump an index DAG as a graphviz dot file"""
2021 r = None
2021 r = None
2022 if repo:
2022 if repo:
2023 filelog = repo.file(file_)
2023 filelog = repo.file(file_)
2024 if len(filelog):
2024 if len(filelog):
2025 r = filelog
2025 r = filelog
2026 if not r:
2026 if not r:
2027 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2027 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2028 ui.write(("digraph G {\n"))
2028 ui.write(("digraph G {\n"))
2029 for i in r:
2029 for i in r:
2030 node = r.node(i)
2030 node = r.node(i)
2031 pp = r.parents(node)
2031 pp = r.parents(node)
2032 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2032 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2033 if pp[1] != nullid:
2033 if pp[1] != nullid:
2034 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2034 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2035 ui.write("}\n")
2035 ui.write("}\n")
2036
2036
2037 @command('debuginstall', [], '')
2037 @command('debuginstall', [], '')
2038 def debuginstall(ui):
2038 def debuginstall(ui):
2039 '''test Mercurial installation
2039 '''test Mercurial installation
2040
2040
2041 Returns 0 on success.
2041 Returns 0 on success.
2042 '''
2042 '''
2043
2043
2044 def writetemp(contents):
2044 def writetemp(contents):
2045 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2045 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2046 f = os.fdopen(fd, "wb")
2046 f = os.fdopen(fd, "wb")
2047 f.write(contents)
2047 f.write(contents)
2048 f.close()
2048 f.close()
2049 return name
2049 return name
2050
2050
2051 problems = 0
2051 problems = 0
2052
2052
2053 # encoding
2053 # encoding
2054 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2054 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2055 try:
2055 try:
2056 encoding.fromlocal("test")
2056 encoding.fromlocal("test")
2057 except util.Abort, inst:
2057 except util.Abort, inst:
2058 ui.write(" %s\n" % inst)
2058 ui.write(" %s\n" % inst)
2059 ui.write(_(" (check that your locale is properly set)\n"))
2059 ui.write(_(" (check that your locale is properly set)\n"))
2060 problems += 1
2060 problems += 1
2061
2061
2062 # Python lib
2062 # Python lib
2063 ui.status(_("checking Python lib (%s)...\n")
2063 ui.status(_("checking Python lib (%s)...\n")
2064 % os.path.dirname(os.__file__))
2064 % os.path.dirname(os.__file__))
2065
2065
2066 # compiled modules
2066 # compiled modules
2067 ui.status(_("checking installed modules (%s)...\n")
2067 ui.status(_("checking installed modules (%s)...\n")
2068 % os.path.dirname(__file__))
2068 % os.path.dirname(__file__))
2069 try:
2069 try:
2070 import bdiff, mpatch, base85, osutil
2070 import bdiff, mpatch, base85, osutil
2071 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2071 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2072 except Exception, inst:
2072 except Exception, inst:
2073 ui.write(" %s\n" % inst)
2073 ui.write(" %s\n" % inst)
2074 ui.write(_(" One or more extensions could not be found"))
2074 ui.write(_(" One or more extensions could not be found"))
2075 ui.write(_(" (check that you compiled the extensions)\n"))
2075 ui.write(_(" (check that you compiled the extensions)\n"))
2076 problems += 1
2076 problems += 1
2077
2077
2078 # templates
2078 # templates
2079 import templater
2079 import templater
2080 p = templater.templatepath()
2080 p = templater.templatepath()
2081 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2081 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2082 try:
2082 try:
2083 templater.templater(templater.templatepath("map-cmdline.default"))
2083 templater.templater(templater.templatepath("map-cmdline.default"))
2084 except Exception, inst:
2084 except Exception, inst:
2085 ui.write(" %s\n" % inst)
2085 ui.write(" %s\n" % inst)
2086 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2086 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2087 problems += 1
2087 problems += 1
2088
2088
2089 # editor
2089 # editor
2090 ui.status(_("checking commit editor...\n"))
2090 ui.status(_("checking commit editor...\n"))
2091 editor = ui.geteditor()
2091 editor = ui.geteditor()
2092 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2092 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2093 if not cmdpath:
2093 if not cmdpath:
2094 if editor == 'vi':
2094 if editor == 'vi':
2095 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2095 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2096 ui.write(_(" (specify a commit editor in your configuration"
2096 ui.write(_(" (specify a commit editor in your configuration"
2097 " file)\n"))
2097 " file)\n"))
2098 else:
2098 else:
2099 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2099 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2100 ui.write(_(" (specify a commit editor in your configuration"
2100 ui.write(_(" (specify a commit editor in your configuration"
2101 " file)\n"))
2101 " file)\n"))
2102 problems += 1
2102 problems += 1
2103
2103
2104 # check username
2104 # check username
2105 ui.status(_("checking username...\n"))
2105 ui.status(_("checking username...\n"))
2106 try:
2106 try:
2107 ui.username()
2107 ui.username()
2108 except util.Abort, e:
2108 except util.Abort, e:
2109 ui.write(" %s\n" % e)
2109 ui.write(" %s\n" % e)
2110 ui.write(_(" (specify a username in your configuration file)\n"))
2110 ui.write(_(" (specify a username in your configuration file)\n"))
2111 problems += 1
2111 problems += 1
2112
2112
2113 if not problems:
2113 if not problems:
2114 ui.status(_("no problems detected\n"))
2114 ui.status(_("no problems detected\n"))
2115 else:
2115 else:
2116 ui.write(_("%s problems detected,"
2116 ui.write(_("%s problems detected,"
2117 " please check your install!\n") % problems)
2117 " please check your install!\n") % problems)
2118
2118
2119 return problems
2119 return problems
2120
2120
2121 @command('debugknown', [], _('REPO ID...'))
2121 @command('debugknown', [], _('REPO ID...'))
2122 def debugknown(ui, repopath, *ids, **opts):
2122 def debugknown(ui, repopath, *ids, **opts):
2123 """test whether node ids are known to a repo
2123 """test whether node ids are known to a repo
2124
2124
2125 Every ID must be a full-length hex node id string. Returns a list of 0s
2125 Every ID must be a full-length hex node id string. Returns a list of 0s
2126 and 1s indicating unknown/known.
2126 and 1s indicating unknown/known.
2127 """
2127 """
2128 repo = hg.peer(ui, opts, repopath)
2128 repo = hg.peer(ui, opts, repopath)
2129 if not repo.capable('known'):
2129 if not repo.capable('known'):
2130 raise util.Abort("known() not supported by target repository")
2130 raise util.Abort("known() not supported by target repository")
2131 flags = repo.known([bin(s) for s in ids])
2131 flags = repo.known([bin(s) for s in ids])
2132 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2132 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2133
2133
2134 @command('debuglabelcomplete', [], _('LABEL...'))
2134 @command('debuglabelcomplete', [], _('LABEL...'))
2135 def debuglabelcomplete(ui, repo, *args):
2135 def debuglabelcomplete(ui, repo, *args):
2136 '''complete "labels" - tags, open branch names, bookmark names'''
2136 '''complete "labels" - tags, open branch names, bookmark names'''
2137
2137
2138 labels = set()
2138 labels = set()
2139 labels.update(t[0] for t in repo.tagslist())
2139 labels.update(t[0] for t in repo.tagslist())
2140 labels.update(repo._bookmarks.keys())
2140 labels.update(repo._bookmarks.keys())
2141 for heads in repo.branchmap().itervalues():
2141 for heads in repo.branchmap().itervalues():
2142 for h in heads:
2142 for h in heads:
2143 ctx = repo[h]
2143 ctx = repo[h]
2144 if not ctx.closesbranch():
2144 if not ctx.closesbranch():
2145 labels.add(ctx.branch())
2145 labels.add(ctx.branch())
2146 completions = set()
2146 completions = set()
2147 if not args:
2147 if not args:
2148 args = ['']
2148 args = ['']
2149 for a in args:
2149 for a in args:
2150 completions.update(l for l in labels if l.startswith(a))
2150 completions.update(l for l in labels if l.startswith(a))
2151 ui.write('\n'.join(sorted(completions)))
2151 ui.write('\n'.join(sorted(completions)))
2152 ui.write('\n')
2152 ui.write('\n')
2153
2153
2154 @command('debugobsolete',
2154 @command('debugobsolete',
2155 [('', 'flags', 0, _('markers flag')),
2155 [('', 'flags', 0, _('markers flag')),
2156 ] + commitopts2,
2156 ] + commitopts2,
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2159 """create arbitrary obsolete marker
2159 """create arbitrary obsolete marker
2160
2160
2161 With no arguments, displays the list of obsolescence markers."""
2161 With no arguments, displays the list of obsolescence markers."""
2162 def parsenodeid(s):
2162 def parsenodeid(s):
2163 try:
2163 try:
2164 # We do not use revsingle/revrange functions here to accept
2164 # We do not use revsingle/revrange functions here to accept
2165 # arbitrary node identifiers, possibly not present in the
2165 # arbitrary node identifiers, possibly not present in the
2166 # local repository.
2166 # local repository.
2167 n = bin(s)
2167 n = bin(s)
2168 if len(n) != len(nullid):
2168 if len(n) != len(nullid):
2169 raise TypeError()
2169 raise TypeError()
2170 return n
2170 return n
2171 except TypeError:
2171 except TypeError:
2172 raise util.Abort('changeset references must be full hexadecimal '
2172 raise util.Abort('changeset references must be full hexadecimal '
2173 'node identifiers')
2173 'node identifiers')
2174
2174
2175 if precursor is not None:
2175 if precursor is not None:
2176 metadata = {}
2176 metadata = {}
2177 if 'date' in opts:
2177 if 'date' in opts:
2178 metadata['date'] = opts['date']
2178 metadata['date'] = opts['date']
2179 metadata['user'] = opts['user'] or ui.username()
2179 metadata['user'] = opts['user'] or ui.username()
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2181 l = repo.lock()
2181 l = repo.lock()
2182 try:
2182 try:
2183 tr = repo.transaction('debugobsolete')
2183 tr = repo.transaction('debugobsolete')
2184 try:
2184 try:
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2186 opts['flags'], metadata)
2186 opts['flags'], metadata)
2187 tr.close()
2187 tr.close()
2188 finally:
2188 finally:
2189 tr.release()
2189 tr.release()
2190 finally:
2190 finally:
2191 l.release()
2191 l.release()
2192 else:
2192 else:
2193 for m in obsolete.allmarkers(repo):
2193 for m in obsolete.allmarkers(repo):
2194 ui.write(hex(m.precnode()))
2194 ui.write(hex(m.precnode()))
2195 for repl in m.succnodes():
2195 for repl in m.succnodes():
2196 ui.write(' ')
2196 ui.write(' ')
2197 ui.write(hex(repl))
2197 ui.write(hex(repl))
2198 ui.write(' %X ' % m._data[2])
2198 ui.write(' %X ' % m._data[2])
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2200 sorted(m.metadata().items()))))
2200 sorted(m.metadata().items()))))
2201 ui.write('\n')
2201 ui.write('\n')
2202
2202
2203 @command('debugpathcomplete',
2203 @command('debugpathcomplete',
2204 [('f', 'full', None, _('complete an entire path')),
2204 [('f', 'full', None, _('complete an entire path')),
2205 ('n', 'normal', None, _('show only normal files')),
2205 ('n', 'normal', None, _('show only normal files')),
2206 ('a', 'added', None, _('show only added files')),
2206 ('a', 'added', None, _('show only added files')),
2207 ('r', 'removed', None, _('show only removed files'))],
2207 ('r', 'removed', None, _('show only removed files'))],
2208 _('FILESPEC...'))
2208 _('FILESPEC...'))
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2210 '''complete part or all of a tracked path
2210 '''complete part or all of a tracked path
2211
2211
2212 This command supports shells that offer path name completion. It
2212 This command supports shells that offer path name completion. It
2213 currently completes only files already known to the dirstate.
2213 currently completes only files already known to the dirstate.
2214
2214
2215 Completion extends only to the next path segment unless
2215 Completion extends only to the next path segment unless
2216 --full is specified, in which case entire paths are used.'''
2216 --full is specified, in which case entire paths are used.'''
2217
2217
2218 def complete(path, acceptable):
2218 def complete(path, acceptable):
2219 dirstate = repo.dirstate
2219 dirstate = repo.dirstate
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2221 rootdir = repo.root + os.sep
2221 rootdir = repo.root + os.sep
2222 if spec != repo.root and not spec.startswith(rootdir):
2222 if spec != repo.root and not spec.startswith(rootdir):
2223 return [], []
2223 return [], []
2224 if os.path.isdir(spec):
2224 if os.path.isdir(spec):
2225 spec += '/'
2225 spec += '/'
2226 spec = spec[len(rootdir):]
2226 spec = spec[len(rootdir):]
2227 fixpaths = os.sep != '/'
2227 fixpaths = os.sep != '/'
2228 if fixpaths:
2228 if fixpaths:
2229 spec = spec.replace(os.sep, '/')
2229 spec = spec.replace(os.sep, '/')
2230 speclen = len(spec)
2230 speclen = len(spec)
2231 fullpaths = opts['full']
2231 fullpaths = opts['full']
2232 files, dirs = set(), set()
2232 files, dirs = set(), set()
2233 adddir, addfile = dirs.add, files.add
2233 adddir, addfile = dirs.add, files.add
2234 for f, st in dirstate.iteritems():
2234 for f, st in dirstate.iteritems():
2235 if f.startswith(spec) and st[0] in acceptable:
2235 if f.startswith(spec) and st[0] in acceptable:
2236 if fixpaths:
2236 if fixpaths:
2237 f = f.replace('/', os.sep)
2237 f = f.replace('/', os.sep)
2238 if fullpaths:
2238 if fullpaths:
2239 addfile(f)
2239 addfile(f)
2240 continue
2240 continue
2241 s = f.find(os.sep, speclen)
2241 s = f.find(os.sep, speclen)
2242 if s >= 0:
2242 if s >= 0:
2243 adddir(f[:s + 1])
2243 adddir(f[:s + 1])
2244 else:
2244 else:
2245 addfile(f)
2245 addfile(f)
2246 return files, dirs
2246 return files, dirs
2247
2247
2248 acceptable = ''
2248 acceptable = ''
2249 if opts['normal']:
2249 if opts['normal']:
2250 acceptable += 'nm'
2250 acceptable += 'nm'
2251 if opts['added']:
2251 if opts['added']:
2252 acceptable += 'a'
2252 acceptable += 'a'
2253 if opts['removed']:
2253 if opts['removed']:
2254 acceptable += 'r'
2254 acceptable += 'r'
2255 cwd = repo.getcwd()
2255 cwd = repo.getcwd()
2256 if not specs:
2256 if not specs:
2257 specs = ['.']
2257 specs = ['.']
2258
2258
2259 files, dirs = set(), set()
2259 files, dirs = set(), set()
2260 for spec in specs:
2260 for spec in specs:
2261 f, d = complete(spec, acceptable or 'nmar')
2261 f, d = complete(spec, acceptable or 'nmar')
2262 files.update(f)
2262 files.update(f)
2263 dirs.update(d)
2263 dirs.update(d)
2264 if not files and len(dirs) == 1:
2264 if not files and len(dirs) == 1:
2265 # force the shell to consider a completion that matches one
2265 # force the shell to consider a completion that matches one
2266 # directory and zero files to be ambiguous
2266 # directory and zero files to be ambiguous
2267 dirs.add(iter(dirs).next() + '.')
2267 dirs.add(iter(dirs).next() + '.')
2268 files.update(dirs)
2268 files.update(dirs)
2269 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2269 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2270 ui.write('\n')
2270 ui.write('\n')
2271
2271
2272 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2272 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2273 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2273 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2274 '''access the pushkey key/value protocol
2274 '''access the pushkey key/value protocol
2275
2275
2276 With two args, list the keys in the given namespace.
2276 With two args, list the keys in the given namespace.
2277
2277
2278 With five args, set a key to new if it currently is set to old.
2278 With five args, set a key to new if it currently is set to old.
2279 Reports success or failure.
2279 Reports success or failure.
2280 '''
2280 '''
2281
2281
2282 target = hg.peer(ui, {}, repopath)
2282 target = hg.peer(ui, {}, repopath)
2283 if keyinfo:
2283 if keyinfo:
2284 key, old, new = keyinfo
2284 key, old, new = keyinfo
2285 r = target.pushkey(namespace, key, old, new)
2285 r = target.pushkey(namespace, key, old, new)
2286 ui.status(str(r) + '\n')
2286 ui.status(str(r) + '\n')
2287 return not r
2287 return not r
2288 else:
2288 else:
2289 for k, v in sorted(target.listkeys(namespace).iteritems()):
2289 for k, v in sorted(target.listkeys(namespace).iteritems()):
2290 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2290 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2291 v.encode('string-escape')))
2291 v.encode('string-escape')))
2292
2292
2293 @command('debugpvec', [], _('A B'))
2293 @command('debugpvec', [], _('A B'))
2294 def debugpvec(ui, repo, a, b=None):
2294 def debugpvec(ui, repo, a, b=None):
2295 ca = scmutil.revsingle(repo, a)
2295 ca = scmutil.revsingle(repo, a)
2296 cb = scmutil.revsingle(repo, b)
2296 cb = scmutil.revsingle(repo, b)
2297 pa = pvec.ctxpvec(ca)
2297 pa = pvec.ctxpvec(ca)
2298 pb = pvec.ctxpvec(cb)
2298 pb = pvec.ctxpvec(cb)
2299 if pa == pb:
2299 if pa == pb:
2300 rel = "="
2300 rel = "="
2301 elif pa > pb:
2301 elif pa > pb:
2302 rel = ">"
2302 rel = ">"
2303 elif pa < pb:
2303 elif pa < pb:
2304 rel = "<"
2304 rel = "<"
2305 elif pa | pb:
2305 elif pa | pb:
2306 rel = "|"
2306 rel = "|"
2307 ui.write(_("a: %s\n") % pa)
2307 ui.write(_("a: %s\n") % pa)
2308 ui.write(_("b: %s\n") % pb)
2308 ui.write(_("b: %s\n") % pb)
2309 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2309 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2310 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2310 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2311 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2311 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2312 pa.distance(pb), rel))
2312 pa.distance(pb), rel))
2313
2313
2314 @command('debugrebuilddirstate|debugrebuildstate',
2314 @command('debugrebuilddirstate|debugrebuildstate',
2315 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2315 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2316 _('[-r REV]'))
2316 _('[-r REV]'))
2317 def debugrebuilddirstate(ui, repo, rev):
2317 def debugrebuilddirstate(ui, repo, rev):
2318 """rebuild the dirstate as it would look like for the given revision
2318 """rebuild the dirstate as it would look like for the given revision
2319
2319
2320 If no revision is specified the first current parent will be used.
2320 If no revision is specified the first current parent will be used.
2321
2321
2322 The dirstate will be set to the files of the given revision.
2322 The dirstate will be set to the files of the given revision.
2323 The actual working directory content or existing dirstate
2323 The actual working directory content or existing dirstate
2324 information such as adds or removes is not considered.
2324 information such as adds or removes is not considered.
2325
2325
2326 One use of this command is to make the next :hg:`status` invocation
2326 One use of this command is to make the next :hg:`status` invocation
2327 check the actual file content.
2327 check the actual file content.
2328 """
2328 """
2329 ctx = scmutil.revsingle(repo, rev)
2329 ctx = scmutil.revsingle(repo, rev)
2330 wlock = repo.wlock()
2330 wlock = repo.wlock()
2331 try:
2331 try:
2332 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2332 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2333 finally:
2333 finally:
2334 wlock.release()
2334 wlock.release()
2335
2335
2336 @command('debugrename',
2336 @command('debugrename',
2337 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2337 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2338 _('[-r REV] FILE'))
2338 _('[-r REV] FILE'))
2339 def debugrename(ui, repo, file1, *pats, **opts):
2339 def debugrename(ui, repo, file1, *pats, **opts):
2340 """dump rename information"""
2340 """dump rename information"""
2341
2341
2342 ctx = scmutil.revsingle(repo, opts.get('rev'))
2342 ctx = scmutil.revsingle(repo, opts.get('rev'))
2343 m = scmutil.match(ctx, (file1,) + pats, opts)
2343 m = scmutil.match(ctx, (file1,) + pats, opts)
2344 for abs in ctx.walk(m):
2344 for abs in ctx.walk(m):
2345 fctx = ctx[abs]
2345 fctx = ctx[abs]
2346 o = fctx.filelog().renamed(fctx.filenode())
2346 o = fctx.filelog().renamed(fctx.filenode())
2347 rel = m.rel(abs)
2347 rel = m.rel(abs)
2348 if o:
2348 if o:
2349 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2349 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2350 else:
2350 else:
2351 ui.write(_("%s not renamed\n") % rel)
2351 ui.write(_("%s not renamed\n") % rel)
2352
2352
2353 @command('debugrevlog',
2353 @command('debugrevlog',
2354 [('c', 'changelog', False, _('open changelog')),
2354 [('c', 'changelog', False, _('open changelog')),
2355 ('m', 'manifest', False, _('open manifest')),
2355 ('m', 'manifest', False, _('open manifest')),
2356 ('d', 'dump', False, _('dump index data'))],
2356 ('d', 'dump', False, _('dump index data'))],
2357 _('-c|-m|FILE'))
2357 _('-c|-m|FILE'))
2358 def debugrevlog(ui, repo, file_=None, **opts):
2358 def debugrevlog(ui, repo, file_=None, **opts):
2359 """show data and statistics about a revlog"""
2359 """show data and statistics about a revlog"""
2360 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2360 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2361
2361
2362 if opts.get("dump"):
2362 if opts.get("dump"):
2363 numrevs = len(r)
2363 numrevs = len(r)
2364 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2364 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2365 " rawsize totalsize compression heads\n")
2365 " rawsize totalsize compression heads\n")
2366 ts = 0
2366 ts = 0
2367 heads = set()
2367 heads = set()
2368 for rev in xrange(numrevs):
2368 for rev in xrange(numrevs):
2369 dbase = r.deltaparent(rev)
2369 dbase = r.deltaparent(rev)
2370 if dbase == -1:
2370 if dbase == -1:
2371 dbase = rev
2371 dbase = rev
2372 cbase = r.chainbase(rev)
2372 cbase = r.chainbase(rev)
2373 p1, p2 = r.parentrevs(rev)
2373 p1, p2 = r.parentrevs(rev)
2374 rs = r.rawsize(rev)
2374 rs = r.rawsize(rev)
2375 ts = ts + rs
2375 ts = ts + rs
2376 heads -= set(r.parentrevs(rev))
2376 heads -= set(r.parentrevs(rev))
2377 heads.add(rev)
2377 heads.add(rev)
2378 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2378 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2379 (rev, p1, p2, r.start(rev), r.end(rev),
2379 (rev, p1, p2, r.start(rev), r.end(rev),
2380 r.start(dbase), r.start(cbase),
2380 r.start(dbase), r.start(cbase),
2381 r.start(p1), r.start(p2),
2381 r.start(p1), r.start(p2),
2382 rs, ts, ts / r.end(rev), len(heads)))
2382 rs, ts, ts / r.end(rev), len(heads)))
2383 return 0
2383 return 0
2384
2384
2385 v = r.version
2385 v = r.version
2386 format = v & 0xFFFF
2386 format = v & 0xFFFF
2387 flags = []
2387 flags = []
2388 gdelta = False
2388 gdelta = False
2389 if v & revlog.REVLOGNGINLINEDATA:
2389 if v & revlog.REVLOGNGINLINEDATA:
2390 flags.append('inline')
2390 flags.append('inline')
2391 if v & revlog.REVLOGGENERALDELTA:
2391 if v & revlog.REVLOGGENERALDELTA:
2392 gdelta = True
2392 gdelta = True
2393 flags.append('generaldelta')
2393 flags.append('generaldelta')
2394 if not flags:
2394 if not flags:
2395 flags = ['(none)']
2395 flags = ['(none)']
2396
2396
2397 nummerges = 0
2397 nummerges = 0
2398 numfull = 0
2398 numfull = 0
2399 numprev = 0
2399 numprev = 0
2400 nump1 = 0
2400 nump1 = 0
2401 nump2 = 0
2401 nump2 = 0
2402 numother = 0
2402 numother = 0
2403 nump1prev = 0
2403 nump1prev = 0
2404 nump2prev = 0
2404 nump2prev = 0
2405 chainlengths = []
2405 chainlengths = []
2406
2406
2407 datasize = [None, 0, 0L]
2407 datasize = [None, 0, 0L]
2408 fullsize = [None, 0, 0L]
2408 fullsize = [None, 0, 0L]
2409 deltasize = [None, 0, 0L]
2409 deltasize = [None, 0, 0L]
2410
2410
2411 def addsize(size, l):
2411 def addsize(size, l):
2412 if l[0] is None or size < l[0]:
2412 if l[0] is None or size < l[0]:
2413 l[0] = size
2413 l[0] = size
2414 if size > l[1]:
2414 if size > l[1]:
2415 l[1] = size
2415 l[1] = size
2416 l[2] += size
2416 l[2] += size
2417
2417
2418 numrevs = len(r)
2418 numrevs = len(r)
2419 for rev in xrange(numrevs):
2419 for rev in xrange(numrevs):
2420 p1, p2 = r.parentrevs(rev)
2420 p1, p2 = r.parentrevs(rev)
2421 delta = r.deltaparent(rev)
2421 delta = r.deltaparent(rev)
2422 if format > 0:
2422 if format > 0:
2423 addsize(r.rawsize(rev), datasize)
2423 addsize(r.rawsize(rev), datasize)
2424 if p2 != nullrev:
2424 if p2 != nullrev:
2425 nummerges += 1
2425 nummerges += 1
2426 size = r.length(rev)
2426 size = r.length(rev)
2427 if delta == nullrev:
2427 if delta == nullrev:
2428 chainlengths.append(0)
2428 chainlengths.append(0)
2429 numfull += 1
2429 numfull += 1
2430 addsize(size, fullsize)
2430 addsize(size, fullsize)
2431 else:
2431 else:
2432 chainlengths.append(chainlengths[delta] + 1)
2432 chainlengths.append(chainlengths[delta] + 1)
2433 addsize(size, deltasize)
2433 addsize(size, deltasize)
2434 if delta == rev - 1:
2434 if delta == rev - 1:
2435 numprev += 1
2435 numprev += 1
2436 if delta == p1:
2436 if delta == p1:
2437 nump1prev += 1
2437 nump1prev += 1
2438 elif delta == p2:
2438 elif delta == p2:
2439 nump2prev += 1
2439 nump2prev += 1
2440 elif delta == p1:
2440 elif delta == p1:
2441 nump1 += 1
2441 nump1 += 1
2442 elif delta == p2:
2442 elif delta == p2:
2443 nump2 += 1
2443 nump2 += 1
2444 elif delta != nullrev:
2444 elif delta != nullrev:
2445 numother += 1
2445 numother += 1
2446
2446
2447 # Adjust size min value for empty cases
2447 # Adjust size min value for empty cases
2448 for size in (datasize, fullsize, deltasize):
2448 for size in (datasize, fullsize, deltasize):
2449 if size[0] is None:
2449 if size[0] is None:
2450 size[0] = 0
2450 size[0] = 0
2451
2451
2452 numdeltas = numrevs - numfull
2452 numdeltas = numrevs - numfull
2453 numoprev = numprev - nump1prev - nump2prev
2453 numoprev = numprev - nump1prev - nump2prev
2454 totalrawsize = datasize[2]
2454 totalrawsize = datasize[2]
2455 datasize[2] /= numrevs
2455 datasize[2] /= numrevs
2456 fulltotal = fullsize[2]
2456 fulltotal = fullsize[2]
2457 fullsize[2] /= numfull
2457 fullsize[2] /= numfull
2458 deltatotal = deltasize[2]
2458 deltatotal = deltasize[2]
2459 if numrevs - numfull > 0:
2459 if numrevs - numfull > 0:
2460 deltasize[2] /= numrevs - numfull
2460 deltasize[2] /= numrevs - numfull
2461 totalsize = fulltotal + deltatotal
2461 totalsize = fulltotal + deltatotal
2462 avgchainlen = sum(chainlengths) / numrevs
2462 avgchainlen = sum(chainlengths) / numrevs
2463 compratio = totalrawsize / totalsize
2463 compratio = totalrawsize / totalsize
2464
2464
2465 basedfmtstr = '%%%dd\n'
2465 basedfmtstr = '%%%dd\n'
2466 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2466 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2467
2467
2468 def dfmtstr(max):
2468 def dfmtstr(max):
2469 return basedfmtstr % len(str(max))
2469 return basedfmtstr % len(str(max))
2470 def pcfmtstr(max, padding=0):
2470 def pcfmtstr(max, padding=0):
2471 return basepcfmtstr % (len(str(max)), ' ' * padding)
2471 return basepcfmtstr % (len(str(max)), ' ' * padding)
2472
2472
2473 def pcfmt(value, total):
2473 def pcfmt(value, total):
2474 return (value, 100 * float(value) / total)
2474 return (value, 100 * float(value) / total)
2475
2475
2476 ui.write(('format : %d\n') % format)
2476 ui.write(('format : %d\n') % format)
2477 ui.write(('flags : %s\n') % ', '.join(flags))
2477 ui.write(('flags : %s\n') % ', '.join(flags))
2478
2478
2479 ui.write('\n')
2479 ui.write('\n')
2480 fmt = pcfmtstr(totalsize)
2480 fmt = pcfmtstr(totalsize)
2481 fmt2 = dfmtstr(totalsize)
2481 fmt2 = dfmtstr(totalsize)
2482 ui.write(('revisions : ') + fmt2 % numrevs)
2482 ui.write(('revisions : ') + fmt2 % numrevs)
2483 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2483 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2484 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2484 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2485 ui.write(('revisions : ') + fmt2 % numrevs)
2485 ui.write(('revisions : ') + fmt2 % numrevs)
2486 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2486 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2487 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2487 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2488 ui.write(('revision size : ') + fmt2 % totalsize)
2488 ui.write(('revision size : ') + fmt2 % totalsize)
2489 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2489 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2490 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2490 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2491
2491
2492 ui.write('\n')
2492 ui.write('\n')
2493 fmt = dfmtstr(max(avgchainlen, compratio))
2493 fmt = dfmtstr(max(avgchainlen, compratio))
2494 ui.write(('avg chain length : ') + fmt % avgchainlen)
2494 ui.write(('avg chain length : ') + fmt % avgchainlen)
2495 ui.write(('compression ratio : ') + fmt % compratio)
2495 ui.write(('compression ratio : ') + fmt % compratio)
2496
2496
2497 if format > 0:
2497 if format > 0:
2498 ui.write('\n')
2498 ui.write('\n')
2499 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2499 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2500 % tuple(datasize))
2500 % tuple(datasize))
2501 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2501 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2502 % tuple(fullsize))
2502 % tuple(fullsize))
2503 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2503 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2504 % tuple(deltasize))
2504 % tuple(deltasize))
2505
2505
2506 if numdeltas > 0:
2506 if numdeltas > 0:
2507 ui.write('\n')
2507 ui.write('\n')
2508 fmt = pcfmtstr(numdeltas)
2508 fmt = pcfmtstr(numdeltas)
2509 fmt2 = pcfmtstr(numdeltas, 4)
2509 fmt2 = pcfmtstr(numdeltas, 4)
2510 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2510 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2511 if numprev > 0:
2511 if numprev > 0:
2512 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2512 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2513 numprev))
2513 numprev))
2514 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2514 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2515 numprev))
2515 numprev))
2516 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2516 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2517 numprev))
2517 numprev))
2518 if gdelta:
2518 if gdelta:
2519 ui.write(('deltas against p1 : ')
2519 ui.write(('deltas against p1 : ')
2520 + fmt % pcfmt(nump1, numdeltas))
2520 + fmt % pcfmt(nump1, numdeltas))
2521 ui.write(('deltas against p2 : ')
2521 ui.write(('deltas against p2 : ')
2522 + fmt % pcfmt(nump2, numdeltas))
2522 + fmt % pcfmt(nump2, numdeltas))
2523 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2523 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2524 numdeltas))
2524 numdeltas))
2525
2525
2526 @command('debugrevspec', [], ('REVSPEC'))
2526 @command('debugrevspec', [], ('REVSPEC'))
2527 def debugrevspec(ui, repo, expr):
2527 def debugrevspec(ui, repo, expr):
2528 """parse and apply a revision specification
2528 """parse and apply a revision specification
2529
2529
2530 Use --verbose to print the parsed tree before and after aliases
2530 Use --verbose to print the parsed tree before and after aliases
2531 expansion.
2531 expansion.
2532 """
2532 """
2533 if ui.verbose:
2533 if ui.verbose:
2534 tree = revset.parse(expr)[0]
2534 tree = revset.parse(expr)[0]
2535 ui.note(revset.prettyformat(tree), "\n")
2535 ui.note(revset.prettyformat(tree), "\n")
2536 newtree = revset.findaliases(ui, tree)
2536 newtree = revset.findaliases(ui, tree)
2537 if newtree != tree:
2537 if newtree != tree:
2538 ui.note(revset.prettyformat(newtree), "\n")
2538 ui.note(revset.prettyformat(newtree), "\n")
2539 func = revset.match(ui, expr)
2539 func = revset.match(ui, expr)
2540 for c in func(repo, range(len(repo))):
2540 for c in func(repo, range(len(repo))):
2541 ui.write("%s\n" % c)
2541 ui.write("%s\n" % c)
2542
2542
2543 @command('debugsetparents', [], _('REV1 [REV2]'))
2543 @command('debugsetparents', [], _('REV1 [REV2]'))
2544 def debugsetparents(ui, repo, rev1, rev2=None):
2544 def debugsetparents(ui, repo, rev1, rev2=None):
2545 """manually set the parents of the current working directory
2545 """manually set the parents of the current working directory
2546
2546
2547 This is useful for writing repository conversion tools, but should
2547 This is useful for writing repository conversion tools, but should
2548 be used with care.
2548 be used with care.
2549
2549
2550 Returns 0 on success.
2550 Returns 0 on success.
2551 """
2551 """
2552
2552
2553 r1 = scmutil.revsingle(repo, rev1).node()
2553 r1 = scmutil.revsingle(repo, rev1).node()
2554 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2554 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2555
2555
2556 wlock = repo.wlock()
2556 wlock = repo.wlock()
2557 try:
2557 try:
2558 repo.setparents(r1, r2)
2558 repo.setparents(r1, r2)
2559 finally:
2559 finally:
2560 wlock.release()
2560 wlock.release()
2561
2561
2562 @command('debugdirstate|debugstate',
2562 @command('debugdirstate|debugstate',
2563 [('', 'nodates', None, _('do not display the saved mtime')),
2563 [('', 'nodates', None, _('do not display the saved mtime')),
2564 ('', 'datesort', None, _('sort by saved mtime'))],
2564 ('', 'datesort', None, _('sort by saved mtime'))],
2565 _('[OPTION]...'))
2565 _('[OPTION]...'))
2566 def debugstate(ui, repo, nodates=None, datesort=None):
2566 def debugstate(ui, repo, nodates=None, datesort=None):
2567 """show the contents of the current dirstate"""
2567 """show the contents of the current dirstate"""
2568 timestr = ""
2568 timestr = ""
2569 showdate = not nodates
2569 showdate = not nodates
2570 if datesort:
2570 if datesort:
2571 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2571 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2572 else:
2572 else:
2573 keyfunc = None # sort by filename
2573 keyfunc = None # sort by filename
2574 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2574 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2575 if showdate:
2575 if showdate:
2576 if ent[3] == -1:
2576 if ent[3] == -1:
2577 # Pad or slice to locale representation
2577 # Pad or slice to locale representation
2578 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2578 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2579 time.localtime(0)))
2579 time.localtime(0)))
2580 timestr = 'unset'
2580 timestr = 'unset'
2581 timestr = (timestr[:locale_len] +
2581 timestr = (timestr[:locale_len] +
2582 ' ' * (locale_len - len(timestr)))
2582 ' ' * (locale_len - len(timestr)))
2583 else:
2583 else:
2584 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2584 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2585 time.localtime(ent[3]))
2585 time.localtime(ent[3]))
2586 if ent[1] & 020000:
2586 if ent[1] & 020000:
2587 mode = 'lnk'
2587 mode = 'lnk'
2588 else:
2588 else:
2589 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2589 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2590 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2590 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2591 for f in repo.dirstate.copies():
2591 for f in repo.dirstate.copies():
2592 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2592 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2593
2593
2594 @command('debugsub',
2594 @command('debugsub',
2595 [('r', 'rev', '',
2595 [('r', 'rev', '',
2596 _('revision to check'), _('REV'))],
2596 _('revision to check'), _('REV'))],
2597 _('[-r REV] [REV]'))
2597 _('[-r REV] [REV]'))
2598 def debugsub(ui, repo, rev=None):
2598 def debugsub(ui, repo, rev=None):
2599 ctx = scmutil.revsingle(repo, rev, None)
2599 ctx = scmutil.revsingle(repo, rev, None)
2600 for k, v in sorted(ctx.substate.items()):
2600 for k, v in sorted(ctx.substate.items()):
2601 ui.write(('path %s\n') % k)
2601 ui.write(('path %s\n') % k)
2602 ui.write((' source %s\n') % v[0])
2602 ui.write((' source %s\n') % v[0])
2603 ui.write((' revision %s\n') % v[1])
2603 ui.write((' revision %s\n') % v[1])
2604
2604
2605 @command('debugsuccessorssets',
2605 @command('debugsuccessorssets',
2606 [],
2606 [],
2607 _('[REV]'))
2607 _('[REV]'))
2608 def debugsuccessorssets(ui, repo, *revs):
2608 def debugsuccessorssets(ui, repo, *revs):
2609 """show set of successors for revision
2609 """show set of successors for revision
2610
2610
2611 A successors set of changeset A is a consistent group of revisions that
2611 A successors set of changeset A is a consistent group of revisions that
2612 succeed A. It contains non-obsolete changesets only.
2612 succeed A. It contains non-obsolete changesets only.
2613
2613
2614 In most cases a changeset A has a single successors set containing a single
2614 In most cases a changeset A has a single successors set containing a single
2615 successor (changeset A replaced by A').
2615 successor (changeset A replaced by A').
2616
2616
2617 A changeset that is made obsolete with no successors are called "pruned".
2617 A changeset that is made obsolete with no successors are called "pruned".
2618 Such changesets have no successors sets at all.
2618 Such changesets have no successors sets at all.
2619
2619
2620 A changeset that has been "split" will have a successors set containing
2620 A changeset that has been "split" will have a successors set containing
2621 more than one successor.
2621 more than one successor.
2622
2622
2623 A changeset that has been rewritten in multiple different ways is called
2623 A changeset that has been rewritten in multiple different ways is called
2624 "divergent". Such changesets have multiple successor sets (each of which
2624 "divergent". Such changesets have multiple successor sets (each of which
2625 may also be split, i.e. have multiple successors).
2625 may also be split, i.e. have multiple successors).
2626
2626
2627 Results are displayed as follows::
2627 Results are displayed as follows::
2628
2628
2629 <rev1>
2629 <rev1>
2630 <successors-1A>
2630 <successors-1A>
2631 <rev2>
2631 <rev2>
2632 <successors-2A>
2632 <successors-2A>
2633 <successors-2B1> <successors-2B2> <successors-2B3>
2633 <successors-2B1> <successors-2B2> <successors-2B3>
2634
2634
2635 Here rev2 has two possible (i.e. divergent) successors sets. The first
2635 Here rev2 has two possible (i.e. divergent) successors sets. The first
2636 holds one element, whereas the second holds three (i.e. the changeset has
2636 holds one element, whereas the second holds three (i.e. the changeset has
2637 been split).
2637 been split).
2638 """
2638 """
2639 # passed to successorssets caching computation from one call to another
2639 # passed to successorssets caching computation from one call to another
2640 cache = {}
2640 cache = {}
2641 ctx2str = str
2641 ctx2str = str
2642 node2str = short
2642 node2str = short
2643 if ui.debug():
2643 if ui.debug():
2644 def ctx2str(ctx):
2644 def ctx2str(ctx):
2645 return ctx.hex()
2645 return ctx.hex()
2646 node2str = hex
2646 node2str = hex
2647 for rev in scmutil.revrange(repo, revs):
2647 for rev in scmutil.revrange(repo, revs):
2648 ctx = repo[rev]
2648 ctx = repo[rev]
2649 ui.write('%s\n'% ctx2str(ctx))
2649 ui.write('%s\n'% ctx2str(ctx))
2650 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2650 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2651 if succsset:
2651 if succsset:
2652 ui.write(' ')
2652 ui.write(' ')
2653 ui.write(node2str(succsset[0]))
2653 ui.write(node2str(succsset[0]))
2654 for node in succsset[1:]:
2654 for node in succsset[1:]:
2655 ui.write(' ')
2655 ui.write(' ')
2656 ui.write(node2str(node))
2656 ui.write(node2str(node))
2657 ui.write('\n')
2657 ui.write('\n')
2658
2658
2659 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2659 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2660 def debugwalk(ui, repo, *pats, **opts):
2660 def debugwalk(ui, repo, *pats, **opts):
2661 """show how files match on given patterns"""
2661 """show how files match on given patterns"""
2662 m = scmutil.match(repo[None], pats, opts)
2662 m = scmutil.match(repo[None], pats, opts)
2663 items = list(repo.walk(m))
2663 items = list(repo.walk(m))
2664 if not items:
2664 if not items:
2665 return
2665 return
2666 f = lambda fn: fn
2666 f = lambda fn: fn
2667 if ui.configbool('ui', 'slash') and os.sep != '/':
2667 if ui.configbool('ui', 'slash') and os.sep != '/':
2668 f = lambda fn: util.normpath(fn)
2668 f = lambda fn: util.normpath(fn)
2669 fmt = 'f %%-%ds %%-%ds %%s' % (
2669 fmt = 'f %%-%ds %%-%ds %%s' % (
2670 max([len(abs) for abs in items]),
2670 max([len(abs) for abs in items]),
2671 max([len(m.rel(abs)) for abs in items]))
2671 max([len(m.rel(abs)) for abs in items]))
2672 for abs in items:
2672 for abs in items:
2673 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2673 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2674 ui.write("%s\n" % line.rstrip())
2674 ui.write("%s\n" % line.rstrip())
2675
2675
2676 @command('debugwireargs',
2676 @command('debugwireargs',
2677 [('', 'three', '', 'three'),
2677 [('', 'three', '', 'three'),
2678 ('', 'four', '', 'four'),
2678 ('', 'four', '', 'four'),
2679 ('', 'five', '', 'five'),
2679 ('', 'five', '', 'five'),
2680 ] + remoteopts,
2680 ] + remoteopts,
2681 _('REPO [OPTIONS]... [ONE [TWO]]'))
2681 _('REPO [OPTIONS]... [ONE [TWO]]'))
2682 def debugwireargs(ui, repopath, *vals, **opts):
2682 def debugwireargs(ui, repopath, *vals, **opts):
2683 repo = hg.peer(ui, opts, repopath)
2683 repo = hg.peer(ui, opts, repopath)
2684 for opt in remoteopts:
2684 for opt in remoteopts:
2685 del opts[opt[1]]
2685 del opts[opt[1]]
2686 args = {}
2686 args = {}
2687 for k, v in opts.iteritems():
2687 for k, v in opts.iteritems():
2688 if v:
2688 if v:
2689 args[k] = v
2689 args[k] = v
2690 # run twice to check that we don't mess up the stream for the next command
2690 # run twice to check that we don't mess up the stream for the next command
2691 res1 = repo.debugwireargs(*vals, **args)
2691 res1 = repo.debugwireargs(*vals, **args)
2692 res2 = repo.debugwireargs(*vals, **args)
2692 res2 = repo.debugwireargs(*vals, **args)
2693 ui.write("%s\n" % res1)
2693 ui.write("%s\n" % res1)
2694 if res1 != res2:
2694 if res1 != res2:
2695 ui.warn("%s\n" % res2)
2695 ui.warn("%s\n" % res2)
2696
2696
2697 @command('^diff',
2697 @command('^diff',
2698 [('r', 'rev', [], _('revision'), _('REV')),
2698 [('r', 'rev', [], _('revision'), _('REV')),
2699 ('c', 'change', '', _('change made by revision'), _('REV'))
2699 ('c', 'change', '', _('change made by revision'), _('REV'))
2700 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2700 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2701 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2701 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2702 def diff(ui, repo, *pats, **opts):
2702 def diff(ui, repo, *pats, **opts):
2703 """diff repository (or selected files)
2703 """diff repository (or selected files)
2704
2704
2705 Show differences between revisions for the specified files.
2705 Show differences between revisions for the specified files.
2706
2706
2707 Differences between files are shown using the unified diff format.
2707 Differences between files are shown using the unified diff format.
2708
2708
2709 .. note::
2709 .. note::
2710 diff may generate unexpected results for merges, as it will
2710 diff may generate unexpected results for merges, as it will
2711 default to comparing against the working directory's first
2711 default to comparing against the working directory's first
2712 parent changeset if no revisions are specified.
2712 parent changeset if no revisions are specified.
2713
2713
2714 When two revision arguments are given, then changes are shown
2714 When two revision arguments are given, then changes are shown
2715 between those revisions. If only one revision is specified then
2715 between those revisions. If only one revision is specified then
2716 that revision is compared to the working directory, and, when no
2716 that revision is compared to the working directory, and, when no
2717 revisions are specified, the working directory files are compared
2717 revisions are specified, the working directory files are compared
2718 to its parent.
2718 to its parent.
2719
2719
2720 Alternatively you can specify -c/--change with a revision to see
2720 Alternatively you can specify -c/--change with a revision to see
2721 the changes in that changeset relative to its first parent.
2721 the changes in that changeset relative to its first parent.
2722
2722
2723 Without the -a/--text option, diff will avoid generating diffs of
2723 Without the -a/--text option, diff will avoid generating diffs of
2724 files it detects as binary. With -a, diff will generate a diff
2724 files it detects as binary. With -a, diff will generate a diff
2725 anyway, probably with undesirable results.
2725 anyway, probably with undesirable results.
2726
2726
2727 Use the -g/--git option to generate diffs in the git extended diff
2727 Use the -g/--git option to generate diffs in the git extended diff
2728 format. For more information, read :hg:`help diffs`.
2728 format. For more information, read :hg:`help diffs`.
2729
2729
2730 .. container:: verbose
2730 .. container:: verbose
2731
2731
2732 Examples:
2732 Examples:
2733
2733
2734 - compare a file in the current working directory to its parent::
2734 - compare a file in the current working directory to its parent::
2735
2735
2736 hg diff foo.c
2736 hg diff foo.c
2737
2737
2738 - compare two historical versions of a directory, with rename info::
2738 - compare two historical versions of a directory, with rename info::
2739
2739
2740 hg diff --git -r 1.0:1.2 lib/
2740 hg diff --git -r 1.0:1.2 lib/
2741
2741
2742 - get change stats relative to the last change on some date::
2742 - get change stats relative to the last change on some date::
2743
2743
2744 hg diff --stat -r "date('may 2')"
2744 hg diff --stat -r "date('may 2')"
2745
2745
2746 - diff all newly-added files that contain a keyword::
2746 - diff all newly-added files that contain a keyword::
2747
2747
2748 hg diff "set:added() and grep(GNU)"
2748 hg diff "set:added() and grep(GNU)"
2749
2749
2750 - compare a revision and its parents::
2750 - compare a revision and its parents::
2751
2751
2752 hg diff -c 9353 # compare against first parent
2752 hg diff -c 9353 # compare against first parent
2753 hg diff -r 9353^:9353 # same using revset syntax
2753 hg diff -r 9353^:9353 # same using revset syntax
2754 hg diff -r 9353^2:9353 # compare against the second parent
2754 hg diff -r 9353^2:9353 # compare against the second parent
2755
2755
2756 Returns 0 on success.
2756 Returns 0 on success.
2757 """
2757 """
2758
2758
2759 revs = opts.get('rev')
2759 revs = opts.get('rev')
2760 change = opts.get('change')
2760 change = opts.get('change')
2761 stat = opts.get('stat')
2761 stat = opts.get('stat')
2762 reverse = opts.get('reverse')
2762 reverse = opts.get('reverse')
2763
2763
2764 if revs and change:
2764 if revs and change:
2765 msg = _('cannot specify --rev and --change at the same time')
2765 msg = _('cannot specify --rev and --change at the same time')
2766 raise util.Abort(msg)
2766 raise util.Abort(msg)
2767 elif change:
2767 elif change:
2768 node2 = scmutil.revsingle(repo, change, None).node()
2768 node2 = scmutil.revsingle(repo, change, None).node()
2769 node1 = repo[node2].p1().node()
2769 node1 = repo[node2].p1().node()
2770 else:
2770 else:
2771 node1, node2 = scmutil.revpair(repo, revs)
2771 node1, node2 = scmutil.revpair(repo, revs)
2772
2772
2773 if reverse:
2773 if reverse:
2774 node1, node2 = node2, node1
2774 node1, node2 = node2, node1
2775
2775
2776 diffopts = patch.diffopts(ui, opts)
2776 diffopts = patch.diffopts(ui, opts)
2777 m = scmutil.match(repo[node2], pats, opts)
2777 m = scmutil.match(repo[node2], pats, opts)
2778 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2778 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2779 listsubrepos=opts.get('subrepos'))
2779 listsubrepos=opts.get('subrepos'))
2780
2780
2781 @command('^export',
2781 @command('^export',
2782 [('o', 'output', '',
2782 [('o', 'output', '',
2783 _('print output to file with formatted name'), _('FORMAT')),
2783 _('print output to file with formatted name'), _('FORMAT')),
2784 ('', 'switch-parent', None, _('diff against the second parent')),
2784 ('', 'switch-parent', None, _('diff against the second parent')),
2785 ('r', 'rev', [], _('revisions to export'), _('REV')),
2785 ('r', 'rev', [], _('revisions to export'), _('REV')),
2786 ] + diffopts,
2786 ] + diffopts,
2787 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2787 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2788 def export(ui, repo, *changesets, **opts):
2788 def export(ui, repo, *changesets, **opts):
2789 """dump the header and diffs for one or more changesets
2789 """dump the header and diffs for one or more changesets
2790
2790
2791 Print the changeset header and diffs for one or more revisions.
2791 Print the changeset header and diffs for one or more revisions.
2792 If no revision is given, the parent of the working directory is used.
2792 If no revision is given, the parent of the working directory is used.
2793
2793
2794 The information shown in the changeset header is: author, date,
2794 The information shown in the changeset header is: author, date,
2795 branch name (if non-default), changeset hash, parent(s) and commit
2795 branch name (if non-default), changeset hash, parent(s) and commit
2796 comment.
2796 comment.
2797
2797
2798 .. note::
2798 .. note::
2799 export may generate unexpected diff output for merge
2799 export may generate unexpected diff output for merge
2800 changesets, as it will compare the merge changeset against its
2800 changesets, as it will compare the merge changeset against its
2801 first parent only.
2801 first parent only.
2802
2802
2803 Output may be to a file, in which case the name of the file is
2803 Output may be to a file, in which case the name of the file is
2804 given using a format string. The formatting rules are as follows:
2804 given using a format string. The formatting rules are as follows:
2805
2805
2806 :``%%``: literal "%" character
2806 :``%%``: literal "%" character
2807 :``%H``: changeset hash (40 hexadecimal digits)
2807 :``%H``: changeset hash (40 hexadecimal digits)
2808 :``%N``: number of patches being generated
2808 :``%N``: number of patches being generated
2809 :``%R``: changeset revision number
2809 :``%R``: changeset revision number
2810 :``%b``: basename of the exporting repository
2810 :``%b``: basename of the exporting repository
2811 :``%h``: short-form changeset hash (12 hexadecimal digits)
2811 :``%h``: short-form changeset hash (12 hexadecimal digits)
2812 :``%m``: first line of the commit message (only alphanumeric characters)
2812 :``%m``: first line of the commit message (only alphanumeric characters)
2813 :``%n``: zero-padded sequence number, starting at 1
2813 :``%n``: zero-padded sequence number, starting at 1
2814 :``%r``: zero-padded changeset revision number
2814 :``%r``: zero-padded changeset revision number
2815
2815
2816 Without the -a/--text option, export will avoid generating diffs
2816 Without the -a/--text option, export will avoid generating diffs
2817 of files it detects as binary. With -a, export will generate a
2817 of files it detects as binary. With -a, export will generate a
2818 diff anyway, probably with undesirable results.
2818 diff anyway, probably with undesirable results.
2819
2819
2820 Use the -g/--git option to generate diffs in the git extended diff
2820 Use the -g/--git option to generate diffs in the git extended diff
2821 format. See :hg:`help diffs` for more information.
2821 format. See :hg:`help diffs` for more information.
2822
2822
2823 With the --switch-parent option, the diff will be against the
2823 With the --switch-parent option, the diff will be against the
2824 second parent. It can be useful to review a merge.
2824 second parent. It can be useful to review a merge.
2825
2825
2826 .. container:: verbose
2826 .. container:: verbose
2827
2827
2828 Examples:
2828 Examples:
2829
2829
2830 - use export and import to transplant a bugfix to the current
2830 - use export and import to transplant a bugfix to the current
2831 branch::
2831 branch::
2832
2832
2833 hg export -r 9353 | hg import -
2833 hg export -r 9353 | hg import -
2834
2834
2835 - export all the changesets between two revisions to a file with
2835 - export all the changesets between two revisions to a file with
2836 rename information::
2836 rename information::
2837
2837
2838 hg export --git -r 123:150 > changes.txt
2838 hg export --git -r 123:150 > changes.txt
2839
2839
2840 - split outgoing changes into a series of patches with
2840 - split outgoing changes into a series of patches with
2841 descriptive names::
2841 descriptive names::
2842
2842
2843 hg export -r "outgoing()" -o "%n-%m.patch"
2843 hg export -r "outgoing()" -o "%n-%m.patch"
2844
2844
2845 Returns 0 on success.
2845 Returns 0 on success.
2846 """
2846 """
2847 changesets += tuple(opts.get('rev', []))
2847 changesets += tuple(opts.get('rev', []))
2848 if not changesets:
2848 if not changesets:
2849 changesets = ['.']
2849 changesets = ['.']
2850 revs = scmutil.revrange(repo, changesets)
2850 revs = scmutil.revrange(repo, changesets)
2851 if not revs:
2851 if not revs:
2852 raise util.Abort(_("export requires at least one changeset"))
2852 raise util.Abort(_("export requires at least one changeset"))
2853 if len(revs) > 1:
2853 if len(revs) > 1:
2854 ui.note(_('exporting patches:\n'))
2854 ui.note(_('exporting patches:\n'))
2855 else:
2855 else:
2856 ui.note(_('exporting patch:\n'))
2856 ui.note(_('exporting patch:\n'))
2857 cmdutil.export(repo, revs, template=opts.get('output'),
2857 cmdutil.export(repo, revs, template=opts.get('output'),
2858 switch_parent=opts.get('switch_parent'),
2858 switch_parent=opts.get('switch_parent'),
2859 opts=patch.diffopts(ui, opts))
2859 opts=patch.diffopts(ui, opts))
2860
2860
2861 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2861 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2862 def forget(ui, repo, *pats, **opts):
2862 def forget(ui, repo, *pats, **opts):
2863 """forget the specified files on the next commit
2863 """forget the specified files on the next commit
2864
2864
2865 Mark the specified files so they will no longer be tracked
2865 Mark the specified files so they will no longer be tracked
2866 after the next commit.
2866 after the next commit.
2867
2867
2868 This only removes files from the current branch, not from the
2868 This only removes files from the current branch, not from the
2869 entire project history, and it does not delete them from the
2869 entire project history, and it does not delete them from the
2870 working directory.
2870 working directory.
2871
2871
2872 To undo a forget before the next commit, see :hg:`add`.
2872 To undo a forget before the next commit, see :hg:`add`.
2873
2873
2874 .. container:: verbose
2874 .. container:: verbose
2875
2875
2876 Examples:
2876 Examples:
2877
2877
2878 - forget newly-added binary files::
2878 - forget newly-added binary files::
2879
2879
2880 hg forget "set:added() and binary()"
2880 hg forget "set:added() and binary()"
2881
2881
2882 - forget files that would be excluded by .hgignore::
2882 - forget files that would be excluded by .hgignore::
2883
2883
2884 hg forget "set:hgignore()"
2884 hg forget "set:hgignore()"
2885
2885
2886 Returns 0 on success.
2886 Returns 0 on success.
2887 """
2887 """
2888
2888
2889 if not pats:
2889 if not pats:
2890 raise util.Abort(_('no files specified'))
2890 raise util.Abort(_('no files specified'))
2891
2891
2892 m = scmutil.match(repo[None], pats, opts)
2892 m = scmutil.match(repo[None], pats, opts)
2893 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2893 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2894 return rejected and 1 or 0
2894 return rejected and 1 or 0
2895
2895
2896 @command(
2896 @command(
2897 'graft',
2897 'graft',
2898 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2898 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2899 ('c', 'continue', False, _('resume interrupted graft')),
2899 ('c', 'continue', False, _('resume interrupted graft')),
2900 ('e', 'edit', False, _('invoke editor on commit messages')),
2900 ('e', 'edit', False, _('invoke editor on commit messages')),
2901 ('', 'log', None, _('append graft info to log message')),
2901 ('', 'log', None, _('append graft info to log message')),
2902 ('D', 'currentdate', False,
2902 ('D', 'currentdate', False,
2903 _('record the current date as commit date')),
2903 _('record the current date as commit date')),
2904 ('U', 'currentuser', False,
2904 ('U', 'currentuser', False,
2905 _('record the current user as committer'), _('DATE'))]
2905 _('record the current user as committer'), _('DATE'))]
2906 + commitopts2 + mergetoolopts + dryrunopts,
2906 + commitopts2 + mergetoolopts + dryrunopts,
2907 _('[OPTION]... [-r] REV...'))
2907 _('[OPTION]... [-r] REV...'))
2908 def graft(ui, repo, *revs, **opts):
2908 def graft(ui, repo, *revs, **opts):
2909 '''copy changes from other branches onto the current branch
2909 '''copy changes from other branches onto the current branch
2910
2910
2911 This command uses Mercurial's merge logic to copy individual
2911 This command uses Mercurial's merge logic to copy individual
2912 changes from other branches without merging branches in the
2912 changes from other branches without merging branches in the
2913 history graph. This is sometimes known as 'backporting' or
2913 history graph. This is sometimes known as 'backporting' or
2914 'cherry-picking'. By default, graft will copy user, date, and
2914 'cherry-picking'. By default, graft will copy user, date, and
2915 description from the source changesets.
2915 description from the source changesets.
2916
2916
2917 Changesets that are ancestors of the current revision, that have
2917 Changesets that are ancestors of the current revision, that have
2918 already been grafted, or that are merges will be skipped.
2918 already been grafted, or that are merges will be skipped.
2919
2919
2920 If --log is specified, log messages will have a comment appended
2920 If --log is specified, log messages will have a comment appended
2921 of the form::
2921 of the form::
2922
2922
2923 (grafted from CHANGESETHASH)
2923 (grafted from CHANGESETHASH)
2924
2924
2925 If a graft merge results in conflicts, the graft process is
2925 If a graft merge results in conflicts, the graft process is
2926 interrupted so that the current merge can be manually resolved.
2926 interrupted so that the current merge can be manually resolved.
2927 Once all conflicts are addressed, the graft process can be
2927 Once all conflicts are addressed, the graft process can be
2928 continued with the -c/--continue option.
2928 continued with the -c/--continue option.
2929
2929
2930 .. note::
2930 .. note::
2931 The -c/--continue option does not reapply earlier options.
2931 The -c/--continue option does not reapply earlier options.
2932
2932
2933 .. container:: verbose
2933 .. container:: verbose
2934
2934
2935 Examples:
2935 Examples:
2936
2936
2937 - copy a single change to the stable branch and edit its description::
2937 - copy a single change to the stable branch and edit its description::
2938
2938
2939 hg update stable
2939 hg update stable
2940 hg graft --edit 9393
2940 hg graft --edit 9393
2941
2941
2942 - graft a range of changesets with one exception, updating dates::
2942 - graft a range of changesets with one exception, updating dates::
2943
2943
2944 hg graft -D "2085::2093 and not 2091"
2944 hg graft -D "2085::2093 and not 2091"
2945
2945
2946 - continue a graft after resolving conflicts::
2946 - continue a graft after resolving conflicts::
2947
2947
2948 hg graft -c
2948 hg graft -c
2949
2949
2950 - show the source of a grafted changeset::
2950 - show the source of a grafted changeset::
2951
2951
2952 hg log --debug -r .
2952 hg log --debug -r .
2953
2953
2954 Returns 0 on successful completion.
2954 Returns 0 on successful completion.
2955 '''
2955 '''
2956
2956
2957 revs = list(revs)
2957 revs = list(revs)
2958 revs.extend(opts['rev'])
2958 revs.extend(opts['rev'])
2959
2959
2960 if not opts.get('user') and opts.get('currentuser'):
2960 if not opts.get('user') and opts.get('currentuser'):
2961 opts['user'] = ui.username()
2961 opts['user'] = ui.username()
2962 if not opts.get('date') and opts.get('currentdate'):
2962 if not opts.get('date') and opts.get('currentdate'):
2963 opts['date'] = "%d %d" % util.makedate()
2963 opts['date'] = "%d %d" % util.makedate()
2964
2964
2965 editor = None
2965 editor = None
2966 if opts.get('edit'):
2966 if opts.get('edit'):
2967 editor = cmdutil.commitforceeditor
2967 editor = cmdutil.commitforceeditor
2968
2968
2969 cont = False
2969 cont = False
2970 if opts['continue']:
2970 if opts['continue']:
2971 cont = True
2971 cont = True
2972 if revs:
2972 if revs:
2973 raise util.Abort(_("can't specify --continue and revisions"))
2973 raise util.Abort(_("can't specify --continue and revisions"))
2974 # read in unfinished revisions
2974 # read in unfinished revisions
2975 try:
2975 try:
2976 nodes = repo.opener.read('graftstate').splitlines()
2976 nodes = repo.opener.read('graftstate').splitlines()
2977 revs = [repo[node].rev() for node in nodes]
2977 revs = [repo[node].rev() for node in nodes]
2978 except IOError, inst:
2978 except IOError, inst:
2979 if inst.errno != errno.ENOENT:
2979 if inst.errno != errno.ENOENT:
2980 raise
2980 raise
2981 raise util.Abort(_("no graft state found, can't continue"))
2981 raise util.Abort(_("no graft state found, can't continue"))
2982 else:
2982 else:
2983 cmdutil.checkunfinished(repo)
2983 cmdutil.checkunfinished(repo)
2984 cmdutil.bailifchanged(repo)
2984 cmdutil.bailifchanged(repo)
2985 if not revs:
2985 if not revs:
2986 raise util.Abort(_('no revisions specified'))
2986 raise util.Abort(_('no revisions specified'))
2987 revs = scmutil.revrange(repo, revs)
2987 revs = scmutil.revrange(repo, revs)
2988
2988
2989 # check for merges
2989 # check for merges
2990 for rev in repo.revs('%ld and merge()', revs):
2990 for rev in repo.revs('%ld and merge()', revs):
2991 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2991 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2992 revs.remove(rev)
2992 revs.remove(rev)
2993 if not revs:
2993 if not revs:
2994 return -1
2994 return -1
2995
2995
2996 # check for ancestors of dest branch
2996 # check for ancestors of dest branch
2997 crev = repo['.'].rev()
2997 crev = repo['.'].rev()
2998 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2998 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2999 # don't mutate while iterating, create a copy
2999 # don't mutate while iterating, create a copy
3000 for rev in list(revs):
3000 for rev in list(revs):
3001 if rev in ancestors:
3001 if rev in ancestors:
3002 ui.warn(_('skipping ancestor revision %s\n') % rev)
3002 ui.warn(_('skipping ancestor revision %s\n') % rev)
3003 revs.remove(rev)
3003 revs.remove(rev)
3004 if not revs:
3004 if not revs:
3005 return -1
3005 return -1
3006
3006
3007 # analyze revs for earlier grafts
3007 # analyze revs for earlier grafts
3008 ids = {}
3008 ids = {}
3009 for ctx in repo.set("%ld", revs):
3009 for ctx in repo.set("%ld", revs):
3010 ids[ctx.hex()] = ctx.rev()
3010 ids[ctx.hex()] = ctx.rev()
3011 n = ctx.extra().get('source')
3011 n = ctx.extra().get('source')
3012 if n:
3012 if n:
3013 ids[n] = ctx.rev()
3013 ids[n] = ctx.rev()
3014
3014
3015 # check ancestors for earlier grafts
3015 # check ancestors for earlier grafts
3016 ui.debug('scanning for duplicate grafts\n')
3016 ui.debug('scanning for duplicate grafts\n')
3017
3017
3018 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3018 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3019 ctx = repo[rev]
3019 ctx = repo[rev]
3020 n = ctx.extra().get('source')
3020 n = ctx.extra().get('source')
3021 if n in ids:
3021 if n in ids:
3022 r = repo[n].rev()
3022 r = repo[n].rev()
3023 if r in revs:
3023 if r in revs:
3024 ui.warn(_('skipping already grafted revision %s\n') % r)
3024 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3025 % (r, rev))
3025 revs.remove(r)
3026 revs.remove(r)
3026 elif ids[n] in revs:
3027 elif ids[n] in revs:
3027 ui.warn(_('skipping already grafted revision %s '
3028 ui.warn(_('skipping already grafted revision %s '
3028 '(same origin %d)\n') % (ids[n], r))
3029 '(%s also has origin %d)\n') % (ids[n], rev, r))
3029 revs.remove(ids[n])
3030 revs.remove(ids[n])
3030 elif ctx.hex() in ids:
3031 elif ctx.hex() in ids:
3031 r = ids[ctx.hex()]
3032 r = ids[ctx.hex()]
3032 ui.warn(_('skipping already grafted revision %s '
3033 ui.warn(_('skipping already grafted revision %s '
3033 '(was grafted from %d)\n') % (r, rev))
3034 '(was grafted from %d)\n') % (r, rev))
3034 revs.remove(r)
3035 revs.remove(r)
3035 if not revs:
3036 if not revs:
3036 return -1
3037 return -1
3037
3038
3038 wlock = repo.wlock()
3039 wlock = repo.wlock()
3039 try:
3040 try:
3040 current = repo['.']
3041 current = repo['.']
3041 for pos, ctx in enumerate(repo.set("%ld", revs)):
3042 for pos, ctx in enumerate(repo.set("%ld", revs)):
3042
3043
3043 ui.status(_('grafting revision %s\n') % ctx.rev())
3044 ui.status(_('grafting revision %s\n') % ctx.rev())
3044 if opts.get('dry_run'):
3045 if opts.get('dry_run'):
3045 continue
3046 continue
3046
3047
3047 source = ctx.extra().get('source')
3048 source = ctx.extra().get('source')
3048 if not source:
3049 if not source:
3049 source = ctx.hex()
3050 source = ctx.hex()
3050 extra = {'source': source}
3051 extra = {'source': source}
3051 user = ctx.user()
3052 user = ctx.user()
3052 if opts.get('user'):
3053 if opts.get('user'):
3053 user = opts['user']
3054 user = opts['user']
3054 date = ctx.date()
3055 date = ctx.date()
3055 if opts.get('date'):
3056 if opts.get('date'):
3056 date = opts['date']
3057 date = opts['date']
3057 message = ctx.description()
3058 message = ctx.description()
3058 if opts.get('log'):
3059 if opts.get('log'):
3059 message += '\n(grafted from %s)' % ctx.hex()
3060 message += '\n(grafted from %s)' % ctx.hex()
3060
3061
3061 # we don't merge the first commit when continuing
3062 # we don't merge the first commit when continuing
3062 if not cont:
3063 if not cont:
3063 # perform the graft merge with p1(rev) as 'ancestor'
3064 # perform the graft merge with p1(rev) as 'ancestor'
3064 try:
3065 try:
3065 # ui.forcemerge is an internal variable, do not document
3066 # ui.forcemerge is an internal variable, do not document
3066 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3067 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3067 stats = mergemod.update(repo, ctx.node(), True, True, False,
3068 stats = mergemod.update(repo, ctx.node(), True, True, False,
3068 ctx.p1().node())
3069 ctx.p1().node())
3069 finally:
3070 finally:
3070 repo.ui.setconfig('ui', 'forcemerge', '')
3071 repo.ui.setconfig('ui', 'forcemerge', '')
3071 # report any conflicts
3072 # report any conflicts
3072 if stats and stats[3] > 0:
3073 if stats and stats[3] > 0:
3073 # write out state for --continue
3074 # write out state for --continue
3074 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3075 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3075 repo.opener.write('graftstate', ''.join(nodelines))
3076 repo.opener.write('graftstate', ''.join(nodelines))
3076 raise util.Abort(
3077 raise util.Abort(
3077 _("unresolved conflicts, can't continue"),
3078 _("unresolved conflicts, can't continue"),
3078 hint=_('use hg resolve and hg graft --continue'))
3079 hint=_('use hg resolve and hg graft --continue'))
3079 else:
3080 else:
3080 cont = False
3081 cont = False
3081
3082
3082 # drop the second merge parent
3083 # drop the second merge parent
3083 repo.setparents(current.node(), nullid)
3084 repo.setparents(current.node(), nullid)
3084 repo.dirstate.write()
3085 repo.dirstate.write()
3085 # fix up dirstate for copies and renames
3086 # fix up dirstate for copies and renames
3086 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3087 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3087
3088
3088 # commit
3089 # commit
3089 node = repo.commit(text=message, user=user,
3090 node = repo.commit(text=message, user=user,
3090 date=date, extra=extra, editor=editor)
3091 date=date, extra=extra, editor=editor)
3091 if node is None:
3092 if node is None:
3092 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3093 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3093 else:
3094 else:
3094 current = repo[node]
3095 current = repo[node]
3095 finally:
3096 finally:
3096 wlock.release()
3097 wlock.release()
3097
3098
3098 # remove state when we complete successfully
3099 # remove state when we complete successfully
3099 if not opts.get('dry_run'):
3100 if not opts.get('dry_run'):
3100 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3101 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3101
3102
3102 return 0
3103 return 0
3103
3104
3104 @command('grep',
3105 @command('grep',
3105 [('0', 'print0', None, _('end fields with NUL')),
3106 [('0', 'print0', None, _('end fields with NUL')),
3106 ('', 'all', None, _('print all revisions that match')),
3107 ('', 'all', None, _('print all revisions that match')),
3107 ('a', 'text', None, _('treat all files as text')),
3108 ('a', 'text', None, _('treat all files as text')),
3108 ('f', 'follow', None,
3109 ('f', 'follow', None,
3109 _('follow changeset history,'
3110 _('follow changeset history,'
3110 ' or file history across copies and renames')),
3111 ' or file history across copies and renames')),
3111 ('i', 'ignore-case', None, _('ignore case when matching')),
3112 ('i', 'ignore-case', None, _('ignore case when matching')),
3112 ('l', 'files-with-matches', None,
3113 ('l', 'files-with-matches', None,
3113 _('print only filenames and revisions that match')),
3114 _('print only filenames and revisions that match')),
3114 ('n', 'line-number', None, _('print matching line numbers')),
3115 ('n', 'line-number', None, _('print matching line numbers')),
3115 ('r', 'rev', [],
3116 ('r', 'rev', [],
3116 _('only search files changed within revision range'), _('REV')),
3117 _('only search files changed within revision range'), _('REV')),
3117 ('u', 'user', None, _('list the author (long with -v)')),
3118 ('u', 'user', None, _('list the author (long with -v)')),
3118 ('d', 'date', None, _('list the date (short with -q)')),
3119 ('d', 'date', None, _('list the date (short with -q)')),
3119 ] + walkopts,
3120 ] + walkopts,
3120 _('[OPTION]... PATTERN [FILE]...'))
3121 _('[OPTION]... PATTERN [FILE]...'))
3121 def grep(ui, repo, pattern, *pats, **opts):
3122 def grep(ui, repo, pattern, *pats, **opts):
3122 """search for a pattern in specified files and revisions
3123 """search for a pattern in specified files and revisions
3123
3124
3124 Search revisions of files for a regular expression.
3125 Search revisions of files for a regular expression.
3125
3126
3126 This command behaves differently than Unix grep. It only accepts
3127 This command behaves differently than Unix grep. It only accepts
3127 Python/Perl regexps. It searches repository history, not the
3128 Python/Perl regexps. It searches repository history, not the
3128 working directory. It always prints the revision number in which a
3129 working directory. It always prints the revision number in which a
3129 match appears.
3130 match appears.
3130
3131
3131 By default, grep only prints output for the first revision of a
3132 By default, grep only prints output for the first revision of a
3132 file in which it finds a match. To get it to print every revision
3133 file in which it finds a match. To get it to print every revision
3133 that contains a change in match status ("-" for a match that
3134 that contains a change in match status ("-" for a match that
3134 becomes a non-match, or "+" for a non-match that becomes a match),
3135 becomes a non-match, or "+" for a non-match that becomes a match),
3135 use the --all flag.
3136 use the --all flag.
3136
3137
3137 Returns 0 if a match is found, 1 otherwise.
3138 Returns 0 if a match is found, 1 otherwise.
3138 """
3139 """
3139 reflags = re.M
3140 reflags = re.M
3140 if opts.get('ignore_case'):
3141 if opts.get('ignore_case'):
3141 reflags |= re.I
3142 reflags |= re.I
3142 try:
3143 try:
3143 regexp = util.compilere(pattern, reflags)
3144 regexp = util.compilere(pattern, reflags)
3144 except re.error, inst:
3145 except re.error, inst:
3145 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3146 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3146 return 1
3147 return 1
3147 sep, eol = ':', '\n'
3148 sep, eol = ':', '\n'
3148 if opts.get('print0'):
3149 if opts.get('print0'):
3149 sep = eol = '\0'
3150 sep = eol = '\0'
3150
3151
3151 getfile = util.lrucachefunc(repo.file)
3152 getfile = util.lrucachefunc(repo.file)
3152
3153
3153 def matchlines(body):
3154 def matchlines(body):
3154 begin = 0
3155 begin = 0
3155 linenum = 0
3156 linenum = 0
3156 while begin < len(body):
3157 while begin < len(body):
3157 match = regexp.search(body, begin)
3158 match = regexp.search(body, begin)
3158 if not match:
3159 if not match:
3159 break
3160 break
3160 mstart, mend = match.span()
3161 mstart, mend = match.span()
3161 linenum += body.count('\n', begin, mstart) + 1
3162 linenum += body.count('\n', begin, mstart) + 1
3162 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3163 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3163 begin = body.find('\n', mend) + 1 or len(body) + 1
3164 begin = body.find('\n', mend) + 1 or len(body) + 1
3164 lend = begin - 1
3165 lend = begin - 1
3165 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3166 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3166
3167
3167 class linestate(object):
3168 class linestate(object):
3168 def __init__(self, line, linenum, colstart, colend):
3169 def __init__(self, line, linenum, colstart, colend):
3169 self.line = line
3170 self.line = line
3170 self.linenum = linenum
3171 self.linenum = linenum
3171 self.colstart = colstart
3172 self.colstart = colstart
3172 self.colend = colend
3173 self.colend = colend
3173
3174
3174 def __hash__(self):
3175 def __hash__(self):
3175 return hash((self.linenum, self.line))
3176 return hash((self.linenum, self.line))
3176
3177
3177 def __eq__(self, other):
3178 def __eq__(self, other):
3178 return self.line == other.line
3179 return self.line == other.line
3179
3180
3180 matches = {}
3181 matches = {}
3181 copies = {}
3182 copies = {}
3182 def grepbody(fn, rev, body):
3183 def grepbody(fn, rev, body):
3183 matches[rev].setdefault(fn, [])
3184 matches[rev].setdefault(fn, [])
3184 m = matches[rev][fn]
3185 m = matches[rev][fn]
3185 for lnum, cstart, cend, line in matchlines(body):
3186 for lnum, cstart, cend, line in matchlines(body):
3186 s = linestate(line, lnum, cstart, cend)
3187 s = linestate(line, lnum, cstart, cend)
3187 m.append(s)
3188 m.append(s)
3188
3189
3189 def difflinestates(a, b):
3190 def difflinestates(a, b):
3190 sm = difflib.SequenceMatcher(None, a, b)
3191 sm = difflib.SequenceMatcher(None, a, b)
3191 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3192 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3192 if tag == 'insert':
3193 if tag == 'insert':
3193 for i in xrange(blo, bhi):
3194 for i in xrange(blo, bhi):
3194 yield ('+', b[i])
3195 yield ('+', b[i])
3195 elif tag == 'delete':
3196 elif tag == 'delete':
3196 for i in xrange(alo, ahi):
3197 for i in xrange(alo, ahi):
3197 yield ('-', a[i])
3198 yield ('-', a[i])
3198 elif tag == 'replace':
3199 elif tag == 'replace':
3199 for i in xrange(alo, ahi):
3200 for i in xrange(alo, ahi):
3200 yield ('-', a[i])
3201 yield ('-', a[i])
3201 for i in xrange(blo, bhi):
3202 for i in xrange(blo, bhi):
3202 yield ('+', b[i])
3203 yield ('+', b[i])
3203
3204
3204 def display(fn, ctx, pstates, states):
3205 def display(fn, ctx, pstates, states):
3205 rev = ctx.rev()
3206 rev = ctx.rev()
3206 datefunc = ui.quiet and util.shortdate or util.datestr
3207 datefunc = ui.quiet and util.shortdate or util.datestr
3207 found = False
3208 found = False
3208 filerevmatches = {}
3209 filerevmatches = {}
3209 def binary():
3210 def binary():
3210 flog = getfile(fn)
3211 flog = getfile(fn)
3211 return util.binary(flog.read(ctx.filenode(fn)))
3212 return util.binary(flog.read(ctx.filenode(fn)))
3212
3213
3213 if opts.get('all'):
3214 if opts.get('all'):
3214 iter = difflinestates(pstates, states)
3215 iter = difflinestates(pstates, states)
3215 else:
3216 else:
3216 iter = [('', l) for l in states]
3217 iter = [('', l) for l in states]
3217 for change, l in iter:
3218 for change, l in iter:
3218 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3219 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3219 before, match, after = None, None, None
3220 before, match, after = None, None, None
3220
3221
3221 if opts.get('line_number'):
3222 if opts.get('line_number'):
3222 cols.append((str(l.linenum), 'grep.linenumber'))
3223 cols.append((str(l.linenum), 'grep.linenumber'))
3223 if opts.get('all'):
3224 if opts.get('all'):
3224 cols.append((change, 'grep.change'))
3225 cols.append((change, 'grep.change'))
3225 if opts.get('user'):
3226 if opts.get('user'):
3226 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3227 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3227 if opts.get('date'):
3228 if opts.get('date'):
3228 cols.append((datefunc(ctx.date()), 'grep.date'))
3229 cols.append((datefunc(ctx.date()), 'grep.date'))
3229 if opts.get('files_with_matches'):
3230 if opts.get('files_with_matches'):
3230 c = (fn, rev)
3231 c = (fn, rev)
3231 if c in filerevmatches:
3232 if c in filerevmatches:
3232 continue
3233 continue
3233 filerevmatches[c] = 1
3234 filerevmatches[c] = 1
3234 else:
3235 else:
3235 before = l.line[:l.colstart]
3236 before = l.line[:l.colstart]
3236 match = l.line[l.colstart:l.colend]
3237 match = l.line[l.colstart:l.colend]
3237 after = l.line[l.colend:]
3238 after = l.line[l.colend:]
3238 for col, label in cols[:-1]:
3239 for col, label in cols[:-1]:
3239 ui.write(col, label=label)
3240 ui.write(col, label=label)
3240 ui.write(sep, label='grep.sep')
3241 ui.write(sep, label='grep.sep')
3241 ui.write(cols[-1][0], label=cols[-1][1])
3242 ui.write(cols[-1][0], label=cols[-1][1])
3242 if before is not None:
3243 if before is not None:
3243 ui.write(sep, label='grep.sep')
3244 ui.write(sep, label='grep.sep')
3244 if not opts.get('text') and binary():
3245 if not opts.get('text') and binary():
3245 ui.write(" Binary file matches")
3246 ui.write(" Binary file matches")
3246 else:
3247 else:
3247 ui.write(before)
3248 ui.write(before)
3248 ui.write(match, label='grep.match')
3249 ui.write(match, label='grep.match')
3249 ui.write(after)
3250 ui.write(after)
3250 ui.write(eol)
3251 ui.write(eol)
3251 found = True
3252 found = True
3252 return found
3253 return found
3253
3254
3254 skip = {}
3255 skip = {}
3255 revfiles = {}
3256 revfiles = {}
3256 matchfn = scmutil.match(repo[None], pats, opts)
3257 matchfn = scmutil.match(repo[None], pats, opts)
3257 found = False
3258 found = False
3258 follow = opts.get('follow')
3259 follow = opts.get('follow')
3259
3260
3260 def prep(ctx, fns):
3261 def prep(ctx, fns):
3261 rev = ctx.rev()
3262 rev = ctx.rev()
3262 pctx = ctx.p1()
3263 pctx = ctx.p1()
3263 parent = pctx.rev()
3264 parent = pctx.rev()
3264 matches.setdefault(rev, {})
3265 matches.setdefault(rev, {})
3265 matches.setdefault(parent, {})
3266 matches.setdefault(parent, {})
3266 files = revfiles.setdefault(rev, [])
3267 files = revfiles.setdefault(rev, [])
3267 for fn in fns:
3268 for fn in fns:
3268 flog = getfile(fn)
3269 flog = getfile(fn)
3269 try:
3270 try:
3270 fnode = ctx.filenode(fn)
3271 fnode = ctx.filenode(fn)
3271 except error.LookupError:
3272 except error.LookupError:
3272 continue
3273 continue
3273
3274
3274 copied = flog.renamed(fnode)
3275 copied = flog.renamed(fnode)
3275 copy = follow and copied and copied[0]
3276 copy = follow and copied and copied[0]
3276 if copy:
3277 if copy:
3277 copies.setdefault(rev, {})[fn] = copy
3278 copies.setdefault(rev, {})[fn] = copy
3278 if fn in skip:
3279 if fn in skip:
3279 if copy:
3280 if copy:
3280 skip[copy] = True
3281 skip[copy] = True
3281 continue
3282 continue
3282 files.append(fn)
3283 files.append(fn)
3283
3284
3284 if fn not in matches[rev]:
3285 if fn not in matches[rev]:
3285 grepbody(fn, rev, flog.read(fnode))
3286 grepbody(fn, rev, flog.read(fnode))
3286
3287
3287 pfn = copy or fn
3288 pfn = copy or fn
3288 if pfn not in matches[parent]:
3289 if pfn not in matches[parent]:
3289 try:
3290 try:
3290 fnode = pctx.filenode(pfn)
3291 fnode = pctx.filenode(pfn)
3291 grepbody(pfn, parent, flog.read(fnode))
3292 grepbody(pfn, parent, flog.read(fnode))
3292 except error.LookupError:
3293 except error.LookupError:
3293 pass
3294 pass
3294
3295
3295 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3296 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3296 rev = ctx.rev()
3297 rev = ctx.rev()
3297 parent = ctx.p1().rev()
3298 parent = ctx.p1().rev()
3298 for fn in sorted(revfiles.get(rev, [])):
3299 for fn in sorted(revfiles.get(rev, [])):
3299 states = matches[rev][fn]
3300 states = matches[rev][fn]
3300 copy = copies.get(rev, {}).get(fn)
3301 copy = copies.get(rev, {}).get(fn)
3301 if fn in skip:
3302 if fn in skip:
3302 if copy:
3303 if copy:
3303 skip[copy] = True
3304 skip[copy] = True
3304 continue
3305 continue
3305 pstates = matches.get(parent, {}).get(copy or fn, [])
3306 pstates = matches.get(parent, {}).get(copy or fn, [])
3306 if pstates or states:
3307 if pstates or states:
3307 r = display(fn, ctx, pstates, states)
3308 r = display(fn, ctx, pstates, states)
3308 found = found or r
3309 found = found or r
3309 if r and not opts.get('all'):
3310 if r and not opts.get('all'):
3310 skip[fn] = True
3311 skip[fn] = True
3311 if copy:
3312 if copy:
3312 skip[copy] = True
3313 skip[copy] = True
3313 del matches[rev]
3314 del matches[rev]
3314 del revfiles[rev]
3315 del revfiles[rev]
3315
3316
3316 return not found
3317 return not found
3317
3318
3318 @command('heads',
3319 @command('heads',
3319 [('r', 'rev', '',
3320 [('r', 'rev', '',
3320 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3321 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3321 ('t', 'topo', False, _('show topological heads only')),
3322 ('t', 'topo', False, _('show topological heads only')),
3322 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3323 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3323 ('c', 'closed', False, _('show normal and closed branch heads')),
3324 ('c', 'closed', False, _('show normal and closed branch heads')),
3324 ] + templateopts,
3325 ] + templateopts,
3325 _('[-ct] [-r STARTREV] [REV]...'))
3326 _('[-ct] [-r STARTREV] [REV]...'))
3326 def heads(ui, repo, *branchrevs, **opts):
3327 def heads(ui, repo, *branchrevs, **opts):
3327 """show branch heads
3328 """show branch heads
3328
3329
3329 With no arguments, show all open branch heads in the repository.
3330 With no arguments, show all open branch heads in the repository.
3330 Branch heads are changesets that have no descendants on the
3331 Branch heads are changesets that have no descendants on the
3331 same branch. They are where development generally takes place and
3332 same branch. They are where development generally takes place and
3332 are the usual targets for update and merge operations.
3333 are the usual targets for update and merge operations.
3333
3334
3334 If one or more REVs are given, only open branch heads on the
3335 If one or more REVs are given, only open branch heads on the
3335 branches associated with the specified changesets are shown. This
3336 branches associated with the specified changesets are shown. This
3336 means that you can use :hg:`heads .` to see the heads on the
3337 means that you can use :hg:`heads .` to see the heads on the
3337 currently checked-out branch.
3338 currently checked-out branch.
3338
3339
3339 If -c/--closed is specified, also show branch heads marked closed
3340 If -c/--closed is specified, also show branch heads marked closed
3340 (see :hg:`commit --close-branch`).
3341 (see :hg:`commit --close-branch`).
3341
3342
3342 If STARTREV is specified, only those heads that are descendants of
3343 If STARTREV is specified, only those heads that are descendants of
3343 STARTREV will be displayed.
3344 STARTREV will be displayed.
3344
3345
3345 If -t/--topo is specified, named branch mechanics will be ignored and only
3346 If -t/--topo is specified, named branch mechanics will be ignored and only
3346 topological heads (changesets with no children) will be shown.
3347 topological heads (changesets with no children) will be shown.
3347
3348
3348 Returns 0 if matching heads are found, 1 if not.
3349 Returns 0 if matching heads are found, 1 if not.
3349 """
3350 """
3350
3351
3351 start = None
3352 start = None
3352 if 'rev' in opts:
3353 if 'rev' in opts:
3353 start = scmutil.revsingle(repo, opts['rev'], None).node()
3354 start = scmutil.revsingle(repo, opts['rev'], None).node()
3354
3355
3355 if opts.get('topo'):
3356 if opts.get('topo'):
3356 heads = [repo[h] for h in repo.heads(start)]
3357 heads = [repo[h] for h in repo.heads(start)]
3357 else:
3358 else:
3358 heads = []
3359 heads = []
3359 for branch in repo.branchmap():
3360 for branch in repo.branchmap():
3360 heads += repo.branchheads(branch, start, opts.get('closed'))
3361 heads += repo.branchheads(branch, start, opts.get('closed'))
3361 heads = [repo[h] for h in heads]
3362 heads = [repo[h] for h in heads]
3362
3363
3363 if branchrevs:
3364 if branchrevs:
3364 branches = set(repo[br].branch() for br in branchrevs)
3365 branches = set(repo[br].branch() for br in branchrevs)
3365 heads = [h for h in heads if h.branch() in branches]
3366 heads = [h for h in heads if h.branch() in branches]
3366
3367
3367 if opts.get('active') and branchrevs:
3368 if opts.get('active') and branchrevs:
3368 dagheads = repo.heads(start)
3369 dagheads = repo.heads(start)
3369 heads = [h for h in heads if h.node() in dagheads]
3370 heads = [h for h in heads if h.node() in dagheads]
3370
3371
3371 if branchrevs:
3372 if branchrevs:
3372 haveheads = set(h.branch() for h in heads)
3373 haveheads = set(h.branch() for h in heads)
3373 if branches - haveheads:
3374 if branches - haveheads:
3374 headless = ', '.join(b for b in branches - haveheads)
3375 headless = ', '.join(b for b in branches - haveheads)
3375 msg = _('no open branch heads found on branches %s')
3376 msg = _('no open branch heads found on branches %s')
3376 if opts.get('rev'):
3377 if opts.get('rev'):
3377 msg += _(' (started at %s)') % opts['rev']
3378 msg += _(' (started at %s)') % opts['rev']
3378 ui.warn((msg + '\n') % headless)
3379 ui.warn((msg + '\n') % headless)
3379
3380
3380 if not heads:
3381 if not heads:
3381 return 1
3382 return 1
3382
3383
3383 heads = sorted(heads, key=lambda x: -x.rev())
3384 heads = sorted(heads, key=lambda x: -x.rev())
3384 displayer = cmdutil.show_changeset(ui, repo, opts)
3385 displayer = cmdutil.show_changeset(ui, repo, opts)
3385 for ctx in heads:
3386 for ctx in heads:
3386 displayer.show(ctx)
3387 displayer.show(ctx)
3387 displayer.close()
3388 displayer.close()
3388
3389
3389 @command('help',
3390 @command('help',
3390 [('e', 'extension', None, _('show only help for extensions')),
3391 [('e', 'extension', None, _('show only help for extensions')),
3391 ('c', 'command', None, _('show only help for commands')),
3392 ('c', 'command', None, _('show only help for commands')),
3392 ('k', 'keyword', '', _('show topics matching keyword')),
3393 ('k', 'keyword', '', _('show topics matching keyword')),
3393 ],
3394 ],
3394 _('[-ec] [TOPIC]'))
3395 _('[-ec] [TOPIC]'))
3395 def help_(ui, name=None, **opts):
3396 def help_(ui, name=None, **opts):
3396 """show help for a given topic or a help overview
3397 """show help for a given topic or a help overview
3397
3398
3398 With no arguments, print a list of commands with short help messages.
3399 With no arguments, print a list of commands with short help messages.
3399
3400
3400 Given a topic, extension, or command name, print help for that
3401 Given a topic, extension, or command name, print help for that
3401 topic.
3402 topic.
3402
3403
3403 Returns 0 if successful.
3404 Returns 0 if successful.
3404 """
3405 """
3405
3406
3406 textwidth = min(ui.termwidth(), 80) - 2
3407 textwidth = min(ui.termwidth(), 80) - 2
3407
3408
3408 keep = ui.verbose and ['verbose'] or []
3409 keep = ui.verbose and ['verbose'] or []
3409 text = help.help_(ui, name, **opts)
3410 text = help.help_(ui, name, **opts)
3410
3411
3411 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3412 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3412 if 'verbose' in pruned:
3413 if 'verbose' in pruned:
3413 keep.append('omitted')
3414 keep.append('omitted')
3414 else:
3415 else:
3415 keep.append('notomitted')
3416 keep.append('notomitted')
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3417 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3417 ui.write(formatted)
3418 ui.write(formatted)
3418
3419
3419
3420
3420 @command('identify|id',
3421 @command('identify|id',
3421 [('r', 'rev', '',
3422 [('r', 'rev', '',
3422 _('identify the specified revision'), _('REV')),
3423 _('identify the specified revision'), _('REV')),
3423 ('n', 'num', None, _('show local revision number')),
3424 ('n', 'num', None, _('show local revision number')),
3424 ('i', 'id', None, _('show global revision id')),
3425 ('i', 'id', None, _('show global revision id')),
3425 ('b', 'branch', None, _('show branch')),
3426 ('b', 'branch', None, _('show branch')),
3426 ('t', 'tags', None, _('show tags')),
3427 ('t', 'tags', None, _('show tags')),
3427 ('B', 'bookmarks', None, _('show bookmarks')),
3428 ('B', 'bookmarks', None, _('show bookmarks')),
3428 ] + remoteopts,
3429 ] + remoteopts,
3429 _('[-nibtB] [-r REV] [SOURCE]'))
3430 _('[-nibtB] [-r REV] [SOURCE]'))
3430 def identify(ui, repo, source=None, rev=None,
3431 def identify(ui, repo, source=None, rev=None,
3431 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3432 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3432 """identify the working copy or specified revision
3433 """identify the working copy or specified revision
3433
3434
3434 Print a summary identifying the repository state at REV using one or
3435 Print a summary identifying the repository state at REV using one or
3435 two parent hash identifiers, followed by a "+" if the working
3436 two parent hash identifiers, followed by a "+" if the working
3436 directory has uncommitted changes, the branch name (if not default),
3437 directory has uncommitted changes, the branch name (if not default),
3437 a list of tags, and a list of bookmarks.
3438 a list of tags, and a list of bookmarks.
3438
3439
3439 When REV is not given, print a summary of the current state of the
3440 When REV is not given, print a summary of the current state of the
3440 repository.
3441 repository.
3441
3442
3442 Specifying a path to a repository root or Mercurial bundle will
3443 Specifying a path to a repository root or Mercurial bundle will
3443 cause lookup to operate on that repository/bundle.
3444 cause lookup to operate on that repository/bundle.
3444
3445
3445 .. container:: verbose
3446 .. container:: verbose
3446
3447
3447 Examples:
3448 Examples:
3448
3449
3449 - generate a build identifier for the working directory::
3450 - generate a build identifier for the working directory::
3450
3451
3451 hg id --id > build-id.dat
3452 hg id --id > build-id.dat
3452
3453
3453 - find the revision corresponding to a tag::
3454 - find the revision corresponding to a tag::
3454
3455
3455 hg id -n -r 1.3
3456 hg id -n -r 1.3
3456
3457
3457 - check the most recent revision of a remote repository::
3458 - check the most recent revision of a remote repository::
3458
3459
3459 hg id -r tip http://selenic.com/hg/
3460 hg id -r tip http://selenic.com/hg/
3460
3461
3461 Returns 0 if successful.
3462 Returns 0 if successful.
3462 """
3463 """
3463
3464
3464 if not repo and not source:
3465 if not repo and not source:
3465 raise util.Abort(_("there is no Mercurial repository here "
3466 raise util.Abort(_("there is no Mercurial repository here "
3466 "(.hg not found)"))
3467 "(.hg not found)"))
3467
3468
3468 hexfunc = ui.debugflag and hex or short
3469 hexfunc = ui.debugflag and hex or short
3469 default = not (num or id or branch or tags or bookmarks)
3470 default = not (num or id or branch or tags or bookmarks)
3470 output = []
3471 output = []
3471 revs = []
3472 revs = []
3472
3473
3473 if source:
3474 if source:
3474 source, branches = hg.parseurl(ui.expandpath(source))
3475 source, branches = hg.parseurl(ui.expandpath(source))
3475 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3476 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3476 repo = peer.local()
3477 repo = peer.local()
3477 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3478 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3478
3479
3479 if not repo:
3480 if not repo:
3480 if num or branch or tags:
3481 if num or branch or tags:
3481 raise util.Abort(
3482 raise util.Abort(
3482 _("can't query remote revision number, branch, or tags"))
3483 _("can't query remote revision number, branch, or tags"))
3483 if not rev and revs:
3484 if not rev and revs:
3484 rev = revs[0]
3485 rev = revs[0]
3485 if not rev:
3486 if not rev:
3486 rev = "tip"
3487 rev = "tip"
3487
3488
3488 remoterev = peer.lookup(rev)
3489 remoterev = peer.lookup(rev)
3489 if default or id:
3490 if default or id:
3490 output = [hexfunc(remoterev)]
3491 output = [hexfunc(remoterev)]
3491
3492
3492 def getbms():
3493 def getbms():
3493 bms = []
3494 bms = []
3494
3495
3495 if 'bookmarks' in peer.listkeys('namespaces'):
3496 if 'bookmarks' in peer.listkeys('namespaces'):
3496 hexremoterev = hex(remoterev)
3497 hexremoterev = hex(remoterev)
3497 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3498 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3498 if bmr == hexremoterev]
3499 if bmr == hexremoterev]
3499
3500
3500 return sorted(bms)
3501 return sorted(bms)
3501
3502
3502 if bookmarks:
3503 if bookmarks:
3503 output.extend(getbms())
3504 output.extend(getbms())
3504 elif default and not ui.quiet:
3505 elif default and not ui.quiet:
3505 # multiple bookmarks for a single parent separated by '/'
3506 # multiple bookmarks for a single parent separated by '/'
3506 bm = '/'.join(getbms())
3507 bm = '/'.join(getbms())
3507 if bm:
3508 if bm:
3508 output.append(bm)
3509 output.append(bm)
3509 else:
3510 else:
3510 if not rev:
3511 if not rev:
3511 ctx = repo[None]
3512 ctx = repo[None]
3512 parents = ctx.parents()
3513 parents = ctx.parents()
3513 changed = ""
3514 changed = ""
3514 if default or id or num:
3515 if default or id or num:
3515 if (util.any(repo.status())
3516 if (util.any(repo.status())
3516 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3517 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3517 changed = '+'
3518 changed = '+'
3518 if default or id:
3519 if default or id:
3519 output = ["%s%s" %
3520 output = ["%s%s" %
3520 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3521 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3521 if num:
3522 if num:
3522 output.append("%s%s" %
3523 output.append("%s%s" %
3523 ('+'.join([str(p.rev()) for p in parents]), changed))
3524 ('+'.join([str(p.rev()) for p in parents]), changed))
3524 else:
3525 else:
3525 ctx = scmutil.revsingle(repo, rev)
3526 ctx = scmutil.revsingle(repo, rev)
3526 if default or id:
3527 if default or id:
3527 output = [hexfunc(ctx.node())]
3528 output = [hexfunc(ctx.node())]
3528 if num:
3529 if num:
3529 output.append(str(ctx.rev()))
3530 output.append(str(ctx.rev()))
3530
3531
3531 if default and not ui.quiet:
3532 if default and not ui.quiet:
3532 b = ctx.branch()
3533 b = ctx.branch()
3533 if b != 'default':
3534 if b != 'default':
3534 output.append("(%s)" % b)
3535 output.append("(%s)" % b)
3535
3536
3536 # multiple tags for a single parent separated by '/'
3537 # multiple tags for a single parent separated by '/'
3537 t = '/'.join(ctx.tags())
3538 t = '/'.join(ctx.tags())
3538 if t:
3539 if t:
3539 output.append(t)
3540 output.append(t)
3540
3541
3541 # multiple bookmarks for a single parent separated by '/'
3542 # multiple bookmarks for a single parent separated by '/'
3542 bm = '/'.join(ctx.bookmarks())
3543 bm = '/'.join(ctx.bookmarks())
3543 if bm:
3544 if bm:
3544 output.append(bm)
3545 output.append(bm)
3545 else:
3546 else:
3546 if branch:
3547 if branch:
3547 output.append(ctx.branch())
3548 output.append(ctx.branch())
3548
3549
3549 if tags:
3550 if tags:
3550 output.extend(ctx.tags())
3551 output.extend(ctx.tags())
3551
3552
3552 if bookmarks:
3553 if bookmarks:
3553 output.extend(ctx.bookmarks())
3554 output.extend(ctx.bookmarks())
3554
3555
3555 ui.write("%s\n" % ' '.join(output))
3556 ui.write("%s\n" % ' '.join(output))
3556
3557
3557 @command('import|patch',
3558 @command('import|patch',
3558 [('p', 'strip', 1,
3559 [('p', 'strip', 1,
3559 _('directory strip option for patch. This has the same '
3560 _('directory strip option for patch. This has the same '
3560 'meaning as the corresponding patch option'), _('NUM')),
3561 'meaning as the corresponding patch option'), _('NUM')),
3561 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3562 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3562 ('e', 'edit', False, _('invoke editor on commit messages')),
3563 ('e', 'edit', False, _('invoke editor on commit messages')),
3563 ('f', 'force', None,
3564 ('f', 'force', None,
3564 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3565 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3565 ('', 'no-commit', None,
3566 ('', 'no-commit', None,
3566 _("don't commit, just update the working directory")),
3567 _("don't commit, just update the working directory")),
3567 ('', 'bypass', None,
3568 ('', 'bypass', None,
3568 _("apply patch without touching the working directory")),
3569 _("apply patch without touching the working directory")),
3569 ('', 'exact', None,
3570 ('', 'exact', None,
3570 _('apply patch to the nodes from which it was generated')),
3571 _('apply patch to the nodes from which it was generated')),
3571 ('', 'import-branch', None,
3572 ('', 'import-branch', None,
3572 _('use any branch information in patch (implied by --exact)'))] +
3573 _('use any branch information in patch (implied by --exact)'))] +
3573 commitopts + commitopts2 + similarityopts,
3574 commitopts + commitopts2 + similarityopts,
3574 _('[OPTION]... PATCH...'))
3575 _('[OPTION]... PATCH...'))
3575 def import_(ui, repo, patch1=None, *patches, **opts):
3576 def import_(ui, repo, patch1=None, *patches, **opts):
3576 """import an ordered set of patches
3577 """import an ordered set of patches
3577
3578
3578 Import a list of patches and commit them individually (unless
3579 Import a list of patches and commit them individually (unless
3579 --no-commit is specified).
3580 --no-commit is specified).
3580
3581
3581 Because import first applies changes to the working directory,
3582 Because import first applies changes to the working directory,
3582 import will abort if there are outstanding changes.
3583 import will abort if there are outstanding changes.
3583
3584
3584 You can import a patch straight from a mail message. Even patches
3585 You can import a patch straight from a mail message. Even patches
3585 as attachments work (to use the body part, it must have type
3586 as attachments work (to use the body part, it must have type
3586 text/plain or text/x-patch). From and Subject headers of email
3587 text/plain or text/x-patch). From and Subject headers of email
3587 message are used as default committer and commit message. All
3588 message are used as default committer and commit message. All
3588 text/plain body parts before first diff are added to commit
3589 text/plain body parts before first diff are added to commit
3589 message.
3590 message.
3590
3591
3591 If the imported patch was generated by :hg:`export`, user and
3592 If the imported patch was generated by :hg:`export`, user and
3592 description from patch override values from message headers and
3593 description from patch override values from message headers and
3593 body. Values given on command line with -m/--message and -u/--user
3594 body. Values given on command line with -m/--message and -u/--user
3594 override these.
3595 override these.
3595
3596
3596 If --exact is specified, import will set the working directory to
3597 If --exact is specified, import will set the working directory to
3597 the parent of each patch before applying it, and will abort if the
3598 the parent of each patch before applying it, and will abort if the
3598 resulting changeset has a different ID than the one recorded in
3599 resulting changeset has a different ID than the one recorded in
3599 the patch. This may happen due to character set problems or other
3600 the patch. This may happen due to character set problems or other
3600 deficiencies in the text patch format.
3601 deficiencies in the text patch format.
3601
3602
3602 Use --bypass to apply and commit patches directly to the
3603 Use --bypass to apply and commit patches directly to the
3603 repository, not touching the working directory. Without --exact,
3604 repository, not touching the working directory. Without --exact,
3604 patches will be applied on top of the working directory parent
3605 patches will be applied on top of the working directory parent
3605 revision.
3606 revision.
3606
3607
3607 With -s/--similarity, hg will attempt to discover renames and
3608 With -s/--similarity, hg will attempt to discover renames and
3608 copies in the patch in the same way as :hg:`addremove`.
3609 copies in the patch in the same way as :hg:`addremove`.
3609
3610
3610 To read a patch from standard input, use "-" as the patch name. If
3611 To read a patch from standard input, use "-" as the patch name. If
3611 a URL is specified, the patch will be downloaded from it.
3612 a URL is specified, the patch will be downloaded from it.
3612 See :hg:`help dates` for a list of formats valid for -d/--date.
3613 See :hg:`help dates` for a list of formats valid for -d/--date.
3613
3614
3614 .. container:: verbose
3615 .. container:: verbose
3615
3616
3616 Examples:
3617 Examples:
3617
3618
3618 - import a traditional patch from a website and detect renames::
3619 - import a traditional patch from a website and detect renames::
3619
3620
3620 hg import -s 80 http://example.com/bugfix.patch
3621 hg import -s 80 http://example.com/bugfix.patch
3621
3622
3622 - import a changeset from an hgweb server::
3623 - import a changeset from an hgweb server::
3623
3624
3624 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3625 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3625
3626
3626 - import all the patches in an Unix-style mbox::
3627 - import all the patches in an Unix-style mbox::
3627
3628
3628 hg import incoming-patches.mbox
3629 hg import incoming-patches.mbox
3629
3630
3630 - attempt to exactly restore an exported changeset (not always
3631 - attempt to exactly restore an exported changeset (not always
3631 possible)::
3632 possible)::
3632
3633
3633 hg import --exact proposed-fix.patch
3634 hg import --exact proposed-fix.patch
3634
3635
3635 Returns 0 on success.
3636 Returns 0 on success.
3636 """
3637 """
3637
3638
3638 if not patch1:
3639 if not patch1:
3639 raise util.Abort(_('need at least one patch to import'))
3640 raise util.Abort(_('need at least one patch to import'))
3640
3641
3641 patches = (patch1,) + patches
3642 patches = (patch1,) + patches
3642
3643
3643 date = opts.get('date')
3644 date = opts.get('date')
3644 if date:
3645 if date:
3645 opts['date'] = util.parsedate(date)
3646 opts['date'] = util.parsedate(date)
3646
3647
3647 editor = cmdutil.commiteditor
3648 editor = cmdutil.commiteditor
3648 if opts.get('edit'):
3649 if opts.get('edit'):
3649 editor = cmdutil.commitforceeditor
3650 editor = cmdutil.commitforceeditor
3650
3651
3651 update = not opts.get('bypass')
3652 update = not opts.get('bypass')
3652 if not update and opts.get('no_commit'):
3653 if not update and opts.get('no_commit'):
3653 raise util.Abort(_('cannot use --no-commit with --bypass'))
3654 raise util.Abort(_('cannot use --no-commit with --bypass'))
3654 try:
3655 try:
3655 sim = float(opts.get('similarity') or 0)
3656 sim = float(opts.get('similarity') or 0)
3656 except ValueError:
3657 except ValueError:
3657 raise util.Abort(_('similarity must be a number'))
3658 raise util.Abort(_('similarity must be a number'))
3658 if sim < 0 or sim > 100:
3659 if sim < 0 or sim > 100:
3659 raise util.Abort(_('similarity must be between 0 and 100'))
3660 raise util.Abort(_('similarity must be between 0 and 100'))
3660 if sim and not update:
3661 if sim and not update:
3661 raise util.Abort(_('cannot use --similarity with --bypass'))
3662 raise util.Abort(_('cannot use --similarity with --bypass'))
3662
3663
3663 if update:
3664 if update:
3664 cmdutil.checkunfinished(repo)
3665 cmdutil.checkunfinished(repo)
3665 if (opts.get('exact') or not opts.get('force')) and update:
3666 if (opts.get('exact') or not opts.get('force')) and update:
3666 cmdutil.bailifchanged(repo)
3667 cmdutil.bailifchanged(repo)
3667
3668
3668 base = opts["base"]
3669 base = opts["base"]
3669 strip = opts["strip"]
3670 strip = opts["strip"]
3670 wlock = lock = tr = None
3671 wlock = lock = tr = None
3671 msgs = []
3672 msgs = []
3672
3673
3673 def tryone(ui, hunk, parents):
3674 def tryone(ui, hunk, parents):
3674 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3675 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3675 patch.extract(ui, hunk)
3676 patch.extract(ui, hunk)
3676
3677
3677 if not tmpname:
3678 if not tmpname:
3678 return (None, None)
3679 return (None, None)
3679 msg = _('applied to working directory')
3680 msg = _('applied to working directory')
3680
3681
3681 try:
3682 try:
3682 cmdline_message = cmdutil.logmessage(ui, opts)
3683 cmdline_message = cmdutil.logmessage(ui, opts)
3683 if cmdline_message:
3684 if cmdline_message:
3684 # pickup the cmdline msg
3685 # pickup the cmdline msg
3685 message = cmdline_message
3686 message = cmdline_message
3686 elif message:
3687 elif message:
3687 # pickup the patch msg
3688 # pickup the patch msg
3688 message = message.strip()
3689 message = message.strip()
3689 else:
3690 else:
3690 # launch the editor
3691 # launch the editor
3691 message = None
3692 message = None
3692 ui.debug('message:\n%s\n' % message)
3693 ui.debug('message:\n%s\n' % message)
3693
3694
3694 if len(parents) == 1:
3695 if len(parents) == 1:
3695 parents.append(repo[nullid])
3696 parents.append(repo[nullid])
3696 if opts.get('exact'):
3697 if opts.get('exact'):
3697 if not nodeid or not p1:
3698 if not nodeid or not p1:
3698 raise util.Abort(_('not a Mercurial patch'))
3699 raise util.Abort(_('not a Mercurial patch'))
3699 p1 = repo[p1]
3700 p1 = repo[p1]
3700 p2 = repo[p2 or nullid]
3701 p2 = repo[p2 or nullid]
3701 elif p2:
3702 elif p2:
3702 try:
3703 try:
3703 p1 = repo[p1]
3704 p1 = repo[p1]
3704 p2 = repo[p2]
3705 p2 = repo[p2]
3705 # Without any options, consider p2 only if the
3706 # Without any options, consider p2 only if the
3706 # patch is being applied on top of the recorded
3707 # patch is being applied on top of the recorded
3707 # first parent.
3708 # first parent.
3708 if p1 != parents[0]:
3709 if p1 != parents[0]:
3709 p1 = parents[0]
3710 p1 = parents[0]
3710 p2 = repo[nullid]
3711 p2 = repo[nullid]
3711 except error.RepoError:
3712 except error.RepoError:
3712 p1, p2 = parents
3713 p1, p2 = parents
3713 else:
3714 else:
3714 p1, p2 = parents
3715 p1, p2 = parents
3715
3716
3716 n = None
3717 n = None
3717 if update:
3718 if update:
3718 if p1 != parents[0]:
3719 if p1 != parents[0]:
3719 hg.clean(repo, p1.node())
3720 hg.clean(repo, p1.node())
3720 if p2 != parents[1]:
3721 if p2 != parents[1]:
3721 repo.setparents(p1.node(), p2.node())
3722 repo.setparents(p1.node(), p2.node())
3722
3723
3723 if opts.get('exact') or opts.get('import_branch'):
3724 if opts.get('exact') or opts.get('import_branch'):
3724 repo.dirstate.setbranch(branch or 'default')
3725 repo.dirstate.setbranch(branch or 'default')
3725
3726
3726 files = set()
3727 files = set()
3727 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3728 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3728 eolmode=None, similarity=sim / 100.0)
3729 eolmode=None, similarity=sim / 100.0)
3729 files = list(files)
3730 files = list(files)
3730 if opts.get('no_commit'):
3731 if opts.get('no_commit'):
3731 if message:
3732 if message:
3732 msgs.append(message)
3733 msgs.append(message)
3733 else:
3734 else:
3734 if opts.get('exact') or p2:
3735 if opts.get('exact') or p2:
3735 # If you got here, you either use --force and know what
3736 # If you got here, you either use --force and know what
3736 # you are doing or used --exact or a merge patch while
3737 # you are doing or used --exact or a merge patch while
3737 # being updated to its first parent.
3738 # being updated to its first parent.
3738 m = None
3739 m = None
3739 else:
3740 else:
3740 m = scmutil.matchfiles(repo, files or [])
3741 m = scmutil.matchfiles(repo, files or [])
3741 n = repo.commit(message, opts.get('user') or user,
3742 n = repo.commit(message, opts.get('user') or user,
3742 opts.get('date') or date, match=m,
3743 opts.get('date') or date, match=m,
3743 editor=editor)
3744 editor=editor)
3744 else:
3745 else:
3745 if opts.get('exact') or opts.get('import_branch'):
3746 if opts.get('exact') or opts.get('import_branch'):
3746 branch = branch or 'default'
3747 branch = branch or 'default'
3747 else:
3748 else:
3748 branch = p1.branch()
3749 branch = p1.branch()
3749 store = patch.filestore()
3750 store = patch.filestore()
3750 try:
3751 try:
3751 files = set()
3752 files = set()
3752 try:
3753 try:
3753 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3754 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3754 files, eolmode=None)
3755 files, eolmode=None)
3755 except patch.PatchError, e:
3756 except patch.PatchError, e:
3756 raise util.Abort(str(e))
3757 raise util.Abort(str(e))
3757 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3758 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3758 message,
3759 message,
3759 opts.get('user') or user,
3760 opts.get('user') or user,
3760 opts.get('date') or date,
3761 opts.get('date') or date,
3761 branch, files, store,
3762 branch, files, store,
3762 editor=cmdutil.commiteditor)
3763 editor=cmdutil.commiteditor)
3763 repo.savecommitmessage(memctx.description())
3764 repo.savecommitmessage(memctx.description())
3764 n = memctx.commit()
3765 n = memctx.commit()
3765 finally:
3766 finally:
3766 store.close()
3767 store.close()
3767 if opts.get('exact') and hex(n) != nodeid:
3768 if opts.get('exact') and hex(n) != nodeid:
3768 raise util.Abort(_('patch is damaged or loses information'))
3769 raise util.Abort(_('patch is damaged or loses information'))
3769 if n:
3770 if n:
3770 # i18n: refers to a short changeset id
3771 # i18n: refers to a short changeset id
3771 msg = _('created %s') % short(n)
3772 msg = _('created %s') % short(n)
3772 return (msg, n)
3773 return (msg, n)
3773 finally:
3774 finally:
3774 os.unlink(tmpname)
3775 os.unlink(tmpname)
3775
3776
3776 try:
3777 try:
3777 try:
3778 try:
3778 wlock = repo.wlock()
3779 wlock = repo.wlock()
3779 if not opts.get('no_commit'):
3780 if not opts.get('no_commit'):
3780 lock = repo.lock()
3781 lock = repo.lock()
3781 tr = repo.transaction('import')
3782 tr = repo.transaction('import')
3782 parents = repo.parents()
3783 parents = repo.parents()
3783 for patchurl in patches:
3784 for patchurl in patches:
3784 if patchurl == '-':
3785 if patchurl == '-':
3785 ui.status(_('applying patch from stdin\n'))
3786 ui.status(_('applying patch from stdin\n'))
3786 patchfile = ui.fin
3787 patchfile = ui.fin
3787 patchurl = 'stdin' # for error message
3788 patchurl = 'stdin' # for error message
3788 else:
3789 else:
3789 patchurl = os.path.join(base, patchurl)
3790 patchurl = os.path.join(base, patchurl)
3790 ui.status(_('applying %s\n') % patchurl)
3791 ui.status(_('applying %s\n') % patchurl)
3791 patchfile = hg.openpath(ui, patchurl)
3792 patchfile = hg.openpath(ui, patchurl)
3792
3793
3793 haspatch = False
3794 haspatch = False
3794 for hunk in patch.split(patchfile):
3795 for hunk in patch.split(patchfile):
3795 (msg, node) = tryone(ui, hunk, parents)
3796 (msg, node) = tryone(ui, hunk, parents)
3796 if msg:
3797 if msg:
3797 haspatch = True
3798 haspatch = True
3798 ui.note(msg + '\n')
3799 ui.note(msg + '\n')
3799 if update or opts.get('exact'):
3800 if update or opts.get('exact'):
3800 parents = repo.parents()
3801 parents = repo.parents()
3801 else:
3802 else:
3802 parents = [repo[node]]
3803 parents = [repo[node]]
3803
3804
3804 if not haspatch:
3805 if not haspatch:
3805 raise util.Abort(_('%s: no diffs found') % patchurl)
3806 raise util.Abort(_('%s: no diffs found') % patchurl)
3806
3807
3807 if tr:
3808 if tr:
3808 tr.close()
3809 tr.close()
3809 if msgs:
3810 if msgs:
3810 repo.savecommitmessage('\n* * *\n'.join(msgs))
3811 repo.savecommitmessage('\n* * *\n'.join(msgs))
3811 except: # re-raises
3812 except: # re-raises
3812 # wlock.release() indirectly calls dirstate.write(): since
3813 # wlock.release() indirectly calls dirstate.write(): since
3813 # we're crashing, we do not want to change the working dir
3814 # we're crashing, we do not want to change the working dir
3814 # parent after all, so make sure it writes nothing
3815 # parent after all, so make sure it writes nothing
3815 repo.dirstate.invalidate()
3816 repo.dirstate.invalidate()
3816 raise
3817 raise
3817 finally:
3818 finally:
3818 if tr:
3819 if tr:
3819 tr.release()
3820 tr.release()
3820 release(lock, wlock)
3821 release(lock, wlock)
3821
3822
3822 @command('incoming|in',
3823 @command('incoming|in',
3823 [('f', 'force', None,
3824 [('f', 'force', None,
3824 _('run even if remote repository is unrelated')),
3825 _('run even if remote repository is unrelated')),
3825 ('n', 'newest-first', None, _('show newest record first')),
3826 ('n', 'newest-first', None, _('show newest record first')),
3826 ('', 'bundle', '',
3827 ('', 'bundle', '',
3827 _('file to store the bundles into'), _('FILE')),
3828 _('file to store the bundles into'), _('FILE')),
3828 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3829 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3829 ('B', 'bookmarks', False, _("compare bookmarks")),
3830 ('B', 'bookmarks', False, _("compare bookmarks")),
3830 ('b', 'branch', [],
3831 ('b', 'branch', [],
3831 _('a specific branch you would like to pull'), _('BRANCH')),
3832 _('a specific branch you would like to pull'), _('BRANCH')),
3832 ] + logopts + remoteopts + subrepoopts,
3833 ] + logopts + remoteopts + subrepoopts,
3833 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3834 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3834 def incoming(ui, repo, source="default", **opts):
3835 def incoming(ui, repo, source="default", **opts):
3835 """show new changesets found in source
3836 """show new changesets found in source
3836
3837
3837 Show new changesets found in the specified path/URL or the default
3838 Show new changesets found in the specified path/URL or the default
3838 pull location. These are the changesets that would have been pulled
3839 pull location. These are the changesets that would have been pulled
3839 if a pull at the time you issued this command.
3840 if a pull at the time you issued this command.
3840
3841
3841 For remote repository, using --bundle avoids downloading the
3842 For remote repository, using --bundle avoids downloading the
3842 changesets twice if the incoming is followed by a pull.
3843 changesets twice if the incoming is followed by a pull.
3843
3844
3844 See pull for valid source format details.
3845 See pull for valid source format details.
3845
3846
3846 Returns 0 if there are incoming changes, 1 otherwise.
3847 Returns 0 if there are incoming changes, 1 otherwise.
3847 """
3848 """
3848 if opts.get('graph'):
3849 if opts.get('graph'):
3849 cmdutil.checkunsupportedgraphflags([], opts)
3850 cmdutil.checkunsupportedgraphflags([], opts)
3850 def display(other, chlist, displayer):
3851 def display(other, chlist, displayer):
3851 revdag = cmdutil.graphrevs(other, chlist, opts)
3852 revdag = cmdutil.graphrevs(other, chlist, opts)
3852 showparents = [ctx.node() for ctx in repo[None].parents()]
3853 showparents = [ctx.node() for ctx in repo[None].parents()]
3853 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3854 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3854 graphmod.asciiedges)
3855 graphmod.asciiedges)
3855
3856
3856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3857 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3857 return 0
3858 return 0
3858
3859
3859 if opts.get('bundle') and opts.get('subrepos'):
3860 if opts.get('bundle') and opts.get('subrepos'):
3860 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3861 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3861
3862
3862 if opts.get('bookmarks'):
3863 if opts.get('bookmarks'):
3863 source, branches = hg.parseurl(ui.expandpath(source),
3864 source, branches = hg.parseurl(ui.expandpath(source),
3864 opts.get('branch'))
3865 opts.get('branch'))
3865 other = hg.peer(repo, opts, source)
3866 other = hg.peer(repo, opts, source)
3866 if 'bookmarks' not in other.listkeys('namespaces'):
3867 if 'bookmarks' not in other.listkeys('namespaces'):
3867 ui.warn(_("remote doesn't support bookmarks\n"))
3868 ui.warn(_("remote doesn't support bookmarks\n"))
3868 return 0
3869 return 0
3869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3870 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3870 return bookmarks.diff(ui, repo, other)
3871 return bookmarks.diff(ui, repo, other)
3871
3872
3872 repo._subtoppath = ui.expandpath(source)
3873 repo._subtoppath = ui.expandpath(source)
3873 try:
3874 try:
3874 return hg.incoming(ui, repo, source, opts)
3875 return hg.incoming(ui, repo, source, opts)
3875 finally:
3876 finally:
3876 del repo._subtoppath
3877 del repo._subtoppath
3877
3878
3878
3879
3879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3880 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3880 def init(ui, dest=".", **opts):
3881 def init(ui, dest=".", **opts):
3881 """create a new repository in the given directory
3882 """create a new repository in the given directory
3882
3883
3883 Initialize a new repository in the given directory. If the given
3884 Initialize a new repository in the given directory. If the given
3884 directory does not exist, it will be created.
3885 directory does not exist, it will be created.
3885
3886
3886 If no directory is given, the current directory is used.
3887 If no directory is given, the current directory is used.
3887
3888
3888 It is possible to specify an ``ssh://`` URL as the destination.
3889 It is possible to specify an ``ssh://`` URL as the destination.
3889 See :hg:`help urls` for more information.
3890 See :hg:`help urls` for more information.
3890
3891
3891 Returns 0 on success.
3892 Returns 0 on success.
3892 """
3893 """
3893 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3894 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3894
3895
3895 @command('locate',
3896 @command('locate',
3896 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3897 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3897 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3898 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3898 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3899 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3899 ] + walkopts,
3900 ] + walkopts,
3900 _('[OPTION]... [PATTERN]...'))
3901 _('[OPTION]... [PATTERN]...'))
3901 def locate(ui, repo, *pats, **opts):
3902 def locate(ui, repo, *pats, **opts):
3902 """locate files matching specific patterns
3903 """locate files matching specific patterns
3903
3904
3904 Print files under Mercurial control in the working directory whose
3905 Print files under Mercurial control in the working directory whose
3905 names match the given patterns.
3906 names match the given patterns.
3906
3907
3907 By default, this command searches all directories in the working
3908 By default, this command searches all directories in the working
3908 directory. To search just the current directory and its
3909 directory. To search just the current directory and its
3909 subdirectories, use "--include .".
3910 subdirectories, use "--include .".
3910
3911
3911 If no patterns are given to match, this command prints the names
3912 If no patterns are given to match, this command prints the names
3912 of all files under Mercurial control in the working directory.
3913 of all files under Mercurial control in the working directory.
3913
3914
3914 If you want to feed the output of this command into the "xargs"
3915 If you want to feed the output of this command into the "xargs"
3915 command, use the -0 option to both this command and "xargs". This
3916 command, use the -0 option to both this command and "xargs". This
3916 will avoid the problem of "xargs" treating single filenames that
3917 will avoid the problem of "xargs" treating single filenames that
3917 contain whitespace as multiple filenames.
3918 contain whitespace as multiple filenames.
3918
3919
3919 Returns 0 if a match is found, 1 otherwise.
3920 Returns 0 if a match is found, 1 otherwise.
3920 """
3921 """
3921 end = opts.get('print0') and '\0' or '\n'
3922 end = opts.get('print0') and '\0' or '\n'
3922 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3923 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3923
3924
3924 ret = 1
3925 ret = 1
3925 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3926 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3926 m.bad = lambda x, y: False
3927 m.bad = lambda x, y: False
3927 for abs in repo[rev].walk(m):
3928 for abs in repo[rev].walk(m):
3928 if not rev and abs not in repo.dirstate:
3929 if not rev and abs not in repo.dirstate:
3929 continue
3930 continue
3930 if opts.get('fullpath'):
3931 if opts.get('fullpath'):
3931 ui.write(repo.wjoin(abs), end)
3932 ui.write(repo.wjoin(abs), end)
3932 else:
3933 else:
3933 ui.write(((pats and m.rel(abs)) or abs), end)
3934 ui.write(((pats and m.rel(abs)) or abs), end)
3934 ret = 0
3935 ret = 0
3935
3936
3936 return ret
3937 return ret
3937
3938
3938 @command('^log|history',
3939 @command('^log|history',
3939 [('f', 'follow', None,
3940 [('f', 'follow', None,
3940 _('follow changeset history, or file history across copies and renames')),
3941 _('follow changeset history, or file history across copies and renames')),
3941 ('', 'follow-first', None,
3942 ('', 'follow-first', None,
3942 _('only follow the first parent of merge changesets (DEPRECATED)')),
3943 _('only follow the first parent of merge changesets (DEPRECATED)')),
3943 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3944 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3944 ('C', 'copies', None, _('show copied files')),
3945 ('C', 'copies', None, _('show copied files')),
3945 ('k', 'keyword', [],
3946 ('k', 'keyword', [],
3946 _('do case-insensitive search for a given text'), _('TEXT')),
3947 _('do case-insensitive search for a given text'), _('TEXT')),
3947 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3948 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3948 ('', 'removed', None, _('include revisions where files were removed')),
3949 ('', 'removed', None, _('include revisions where files were removed')),
3949 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3950 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3950 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3951 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3951 ('', 'only-branch', [],
3952 ('', 'only-branch', [],
3952 _('show only changesets within the given named branch (DEPRECATED)'),
3953 _('show only changesets within the given named branch (DEPRECATED)'),
3953 _('BRANCH')),
3954 _('BRANCH')),
3954 ('b', 'branch', [],
3955 ('b', 'branch', [],
3955 _('show changesets within the given named branch'), _('BRANCH')),
3956 _('show changesets within the given named branch'), _('BRANCH')),
3956 ('P', 'prune', [],
3957 ('P', 'prune', [],
3957 _('do not display revision or any of its ancestors'), _('REV')),
3958 _('do not display revision or any of its ancestors'), _('REV')),
3958 ] + logopts + walkopts,
3959 ] + logopts + walkopts,
3959 _('[OPTION]... [FILE]'))
3960 _('[OPTION]... [FILE]'))
3960 def log(ui, repo, *pats, **opts):
3961 def log(ui, repo, *pats, **opts):
3961 """show revision history of entire repository or files
3962 """show revision history of entire repository or files
3962
3963
3963 Print the revision history of the specified files or the entire
3964 Print the revision history of the specified files or the entire
3964 project.
3965 project.
3965
3966
3966 If no revision range is specified, the default is ``tip:0`` unless
3967 If no revision range is specified, the default is ``tip:0`` unless
3967 --follow is set, in which case the working directory parent is
3968 --follow is set, in which case the working directory parent is
3968 used as the starting revision.
3969 used as the starting revision.
3969
3970
3970 File history is shown without following rename or copy history of
3971 File history is shown without following rename or copy history of
3971 files. Use -f/--follow with a filename to follow history across
3972 files. Use -f/--follow with a filename to follow history across
3972 renames and copies. --follow without a filename will only show
3973 renames and copies. --follow without a filename will only show
3973 ancestors or descendants of the starting revision.
3974 ancestors or descendants of the starting revision.
3974
3975
3975 By default this command prints revision number and changeset id,
3976 By default this command prints revision number and changeset id,
3976 tags, non-trivial parents, user, date and time, and a summary for
3977 tags, non-trivial parents, user, date and time, and a summary for
3977 each commit. When the -v/--verbose switch is used, the list of
3978 each commit. When the -v/--verbose switch is used, the list of
3978 changed files and full commit message are shown.
3979 changed files and full commit message are shown.
3979
3980
3980 .. note::
3981 .. note::
3981 log -p/--patch may generate unexpected diff output for merge
3982 log -p/--patch may generate unexpected diff output for merge
3982 changesets, as it will only compare the merge changeset against
3983 changesets, as it will only compare the merge changeset against
3983 its first parent. Also, only files different from BOTH parents
3984 its first parent. Also, only files different from BOTH parents
3984 will appear in files:.
3985 will appear in files:.
3985
3986
3986 .. note::
3987 .. note::
3987 for performance reasons, log FILE may omit duplicate changes
3988 for performance reasons, log FILE may omit duplicate changes
3988 made on branches and will not show deletions. To see all
3989 made on branches and will not show deletions. To see all
3989 changes including duplicates and deletions, use the --removed
3990 changes including duplicates and deletions, use the --removed
3990 switch.
3991 switch.
3991
3992
3992 .. container:: verbose
3993 .. container:: verbose
3993
3994
3994 Some examples:
3995 Some examples:
3995
3996
3996 - changesets with full descriptions and file lists::
3997 - changesets with full descriptions and file lists::
3997
3998
3998 hg log -v
3999 hg log -v
3999
4000
4000 - changesets ancestral to the working directory::
4001 - changesets ancestral to the working directory::
4001
4002
4002 hg log -f
4003 hg log -f
4003
4004
4004 - last 10 commits on the current branch::
4005 - last 10 commits on the current branch::
4005
4006
4006 hg log -l 10 -b .
4007 hg log -l 10 -b .
4007
4008
4008 - changesets showing all modifications of a file, including removals::
4009 - changesets showing all modifications of a file, including removals::
4009
4010
4010 hg log --removed file.c
4011 hg log --removed file.c
4011
4012
4012 - all changesets that touch a directory, with diffs, excluding merges::
4013 - all changesets that touch a directory, with diffs, excluding merges::
4013
4014
4014 hg log -Mp lib/
4015 hg log -Mp lib/
4015
4016
4016 - all revision numbers that match a keyword::
4017 - all revision numbers that match a keyword::
4017
4018
4018 hg log -k bug --template "{rev}\\n"
4019 hg log -k bug --template "{rev}\\n"
4019
4020
4020 - check if a given changeset is included is a tagged release::
4021 - check if a given changeset is included is a tagged release::
4021
4022
4022 hg log -r "a21ccf and ancestor(1.9)"
4023 hg log -r "a21ccf and ancestor(1.9)"
4023
4024
4024 - find all changesets by some user in a date range::
4025 - find all changesets by some user in a date range::
4025
4026
4026 hg log -k alice -d "may 2008 to jul 2008"
4027 hg log -k alice -d "may 2008 to jul 2008"
4027
4028
4028 - summary of all changesets after the last tag::
4029 - summary of all changesets after the last tag::
4029
4030
4030 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4031 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4031
4032
4032 See :hg:`help dates` for a list of formats valid for -d/--date.
4033 See :hg:`help dates` for a list of formats valid for -d/--date.
4033
4034
4034 See :hg:`help revisions` and :hg:`help revsets` for more about
4035 See :hg:`help revisions` and :hg:`help revsets` for more about
4035 specifying revisions.
4036 specifying revisions.
4036
4037
4037 See :hg:`help templates` for more about pre-packaged styles and
4038 See :hg:`help templates` for more about pre-packaged styles and
4038 specifying custom templates.
4039 specifying custom templates.
4039
4040
4040 Returns 0 on success.
4041 Returns 0 on success.
4041 """
4042 """
4042 if opts.get('graph'):
4043 if opts.get('graph'):
4043 return cmdutil.graphlog(ui, repo, *pats, **opts)
4044 return cmdutil.graphlog(ui, repo, *pats, **opts)
4044
4045
4045 matchfn = scmutil.match(repo[None], pats, opts)
4046 matchfn = scmutil.match(repo[None], pats, opts)
4046 limit = cmdutil.loglimit(opts)
4047 limit = cmdutil.loglimit(opts)
4047 count = 0
4048 count = 0
4048
4049
4049 getrenamed, endrev = None, None
4050 getrenamed, endrev = None, None
4050 if opts.get('copies'):
4051 if opts.get('copies'):
4051 if opts.get('rev'):
4052 if opts.get('rev'):
4052 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4053 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4053 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4054 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4054
4055
4055 df = False
4056 df = False
4056 if opts.get("date"):
4057 if opts.get("date"):
4057 df = util.matchdate(opts["date"])
4058 df = util.matchdate(opts["date"])
4058
4059
4059 branches = opts.get('branch', []) + opts.get('only_branch', [])
4060 branches = opts.get('branch', []) + opts.get('only_branch', [])
4060 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4061 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4061
4062
4062 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4063 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4063 def prep(ctx, fns):
4064 def prep(ctx, fns):
4064 rev = ctx.rev()
4065 rev = ctx.rev()
4065 parents = [p for p in repo.changelog.parentrevs(rev)
4066 parents = [p for p in repo.changelog.parentrevs(rev)
4066 if p != nullrev]
4067 if p != nullrev]
4067 if opts.get('no_merges') and len(parents) == 2:
4068 if opts.get('no_merges') and len(parents) == 2:
4068 return
4069 return
4069 if opts.get('only_merges') and len(parents) != 2:
4070 if opts.get('only_merges') and len(parents) != 2:
4070 return
4071 return
4071 if opts.get('branch') and ctx.branch() not in opts['branch']:
4072 if opts.get('branch') and ctx.branch() not in opts['branch']:
4072 return
4073 return
4073 if df and not df(ctx.date()[0]):
4074 if df and not df(ctx.date()[0]):
4074 return
4075 return
4075
4076
4076 lower = encoding.lower
4077 lower = encoding.lower
4077 if opts.get('user'):
4078 if opts.get('user'):
4078 luser = lower(ctx.user())
4079 luser = lower(ctx.user())
4079 for k in [lower(x) for x in opts['user']]:
4080 for k in [lower(x) for x in opts['user']]:
4080 if (k in luser):
4081 if (k in luser):
4081 break
4082 break
4082 else:
4083 else:
4083 return
4084 return
4084 if opts.get('keyword'):
4085 if opts.get('keyword'):
4085 luser = lower(ctx.user())
4086 luser = lower(ctx.user())
4086 ldesc = lower(ctx.description())
4087 ldesc = lower(ctx.description())
4087 lfiles = lower(" ".join(ctx.files()))
4088 lfiles = lower(" ".join(ctx.files()))
4088 for k in [lower(x) for x in opts['keyword']]:
4089 for k in [lower(x) for x in opts['keyword']]:
4089 if (k in luser or k in ldesc or k in lfiles):
4090 if (k in luser or k in ldesc or k in lfiles):
4090 break
4091 break
4091 else:
4092 else:
4092 return
4093 return
4093
4094
4094 copies = None
4095 copies = None
4095 if getrenamed is not None and rev:
4096 if getrenamed is not None and rev:
4096 copies = []
4097 copies = []
4097 for fn in ctx.files():
4098 for fn in ctx.files():
4098 rename = getrenamed(fn, rev)
4099 rename = getrenamed(fn, rev)
4099 if rename:
4100 if rename:
4100 copies.append((fn, rename[0]))
4101 copies.append((fn, rename[0]))
4101
4102
4102 revmatchfn = None
4103 revmatchfn = None
4103 if opts.get('patch') or opts.get('stat'):
4104 if opts.get('patch') or opts.get('stat'):
4104 if opts.get('follow') or opts.get('follow_first'):
4105 if opts.get('follow') or opts.get('follow_first'):
4105 # note: this might be wrong when following through merges
4106 # note: this might be wrong when following through merges
4106 revmatchfn = scmutil.match(repo[None], fns, default='path')
4107 revmatchfn = scmutil.match(repo[None], fns, default='path')
4107 else:
4108 else:
4108 revmatchfn = matchfn
4109 revmatchfn = matchfn
4109
4110
4110 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4111 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4111
4112
4112 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4113 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4113 if displayer.flush(ctx.rev()):
4114 if displayer.flush(ctx.rev()):
4114 count += 1
4115 count += 1
4115 if count == limit:
4116 if count == limit:
4116 break
4117 break
4117 displayer.close()
4118 displayer.close()
4118
4119
4119 @command('manifest',
4120 @command('manifest',
4120 [('r', 'rev', '', _('revision to display'), _('REV')),
4121 [('r', 'rev', '', _('revision to display'), _('REV')),
4121 ('', 'all', False, _("list files from all revisions"))],
4122 ('', 'all', False, _("list files from all revisions"))],
4122 _('[-r REV]'))
4123 _('[-r REV]'))
4123 def manifest(ui, repo, node=None, rev=None, **opts):
4124 def manifest(ui, repo, node=None, rev=None, **opts):
4124 """output the current or given revision of the project manifest
4125 """output the current or given revision of the project manifest
4125
4126
4126 Print a list of version controlled files for the given revision.
4127 Print a list of version controlled files for the given revision.
4127 If no revision is given, the first parent of the working directory
4128 If no revision is given, the first parent of the working directory
4128 is used, or the null revision if no revision is checked out.
4129 is used, or the null revision if no revision is checked out.
4129
4130
4130 With -v, print file permissions, symlink and executable bits.
4131 With -v, print file permissions, symlink and executable bits.
4131 With --debug, print file revision hashes.
4132 With --debug, print file revision hashes.
4132
4133
4133 If option --all is specified, the list of all files from all revisions
4134 If option --all is specified, the list of all files from all revisions
4134 is printed. This includes deleted and renamed files.
4135 is printed. This includes deleted and renamed files.
4135
4136
4136 Returns 0 on success.
4137 Returns 0 on success.
4137 """
4138 """
4138
4139
4139 fm = ui.formatter('manifest', opts)
4140 fm = ui.formatter('manifest', opts)
4140
4141
4141 if opts.get('all'):
4142 if opts.get('all'):
4142 if rev or node:
4143 if rev or node:
4143 raise util.Abort(_("can't specify a revision with --all"))
4144 raise util.Abort(_("can't specify a revision with --all"))
4144
4145
4145 res = []
4146 res = []
4146 prefix = "data/"
4147 prefix = "data/"
4147 suffix = ".i"
4148 suffix = ".i"
4148 plen = len(prefix)
4149 plen = len(prefix)
4149 slen = len(suffix)
4150 slen = len(suffix)
4150 lock = repo.lock()
4151 lock = repo.lock()
4151 try:
4152 try:
4152 for fn, b, size in repo.store.datafiles():
4153 for fn, b, size in repo.store.datafiles():
4153 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4154 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4154 res.append(fn[plen:-slen])
4155 res.append(fn[plen:-slen])
4155 finally:
4156 finally:
4156 lock.release()
4157 lock.release()
4157 for f in res:
4158 for f in res:
4158 fm.startitem()
4159 fm.startitem()
4159 fm.write("path", '%s\n', f)
4160 fm.write("path", '%s\n', f)
4160 fm.end()
4161 fm.end()
4161 return
4162 return
4162
4163
4163 if rev and node:
4164 if rev and node:
4164 raise util.Abort(_("please specify just one revision"))
4165 raise util.Abort(_("please specify just one revision"))
4165
4166
4166 if not node:
4167 if not node:
4167 node = rev
4168 node = rev
4168
4169
4169 char = {'l': '@', 'x': '*', '': ''}
4170 char = {'l': '@', 'x': '*', '': ''}
4170 mode = {'l': '644', 'x': '755', '': '644'}
4171 mode = {'l': '644', 'x': '755', '': '644'}
4171 ctx = scmutil.revsingle(repo, node)
4172 ctx = scmutil.revsingle(repo, node)
4172 mf = ctx.manifest()
4173 mf = ctx.manifest()
4173 for f in ctx:
4174 for f in ctx:
4174 fm.startitem()
4175 fm.startitem()
4175 fl = ctx[f].flags()
4176 fl = ctx[f].flags()
4176 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4177 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4177 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4178 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4178 fm.write('path', '%s\n', f)
4179 fm.write('path', '%s\n', f)
4179 fm.end()
4180 fm.end()
4180
4181
4181 @command('^merge',
4182 @command('^merge',
4182 [('f', 'force', None,
4183 [('f', 'force', None,
4183 _('force a merge including outstanding changes (DEPRECATED)')),
4184 _('force a merge including outstanding changes (DEPRECATED)')),
4184 ('r', 'rev', '', _('revision to merge'), _('REV')),
4185 ('r', 'rev', '', _('revision to merge'), _('REV')),
4185 ('P', 'preview', None,
4186 ('P', 'preview', None,
4186 _('review revisions to merge (no merge is performed)'))
4187 _('review revisions to merge (no merge is performed)'))
4187 ] + mergetoolopts,
4188 ] + mergetoolopts,
4188 _('[-P] [-f] [[-r] REV]'))
4189 _('[-P] [-f] [[-r] REV]'))
4189 def merge(ui, repo, node=None, **opts):
4190 def merge(ui, repo, node=None, **opts):
4190 """merge working directory with another revision
4191 """merge working directory with another revision
4191
4192
4192 The current working directory is updated with all changes made in
4193 The current working directory is updated with all changes made in
4193 the requested revision since the last common predecessor revision.
4194 the requested revision since the last common predecessor revision.
4194
4195
4195 Files that changed between either parent are marked as changed for
4196 Files that changed between either parent are marked as changed for
4196 the next commit and a commit must be performed before any further
4197 the next commit and a commit must be performed before any further
4197 updates to the repository are allowed. The next commit will have
4198 updates to the repository are allowed. The next commit will have
4198 two parents.
4199 two parents.
4199
4200
4200 ``--tool`` can be used to specify the merge tool used for file
4201 ``--tool`` can be used to specify the merge tool used for file
4201 merges. It overrides the HGMERGE environment variable and your
4202 merges. It overrides the HGMERGE environment variable and your
4202 configuration files. See :hg:`help merge-tools` for options.
4203 configuration files. See :hg:`help merge-tools` for options.
4203
4204
4204 If no revision is specified, the working directory's parent is a
4205 If no revision is specified, the working directory's parent is a
4205 head revision, and the current branch contains exactly one other
4206 head revision, and the current branch contains exactly one other
4206 head, the other head is merged with by default. Otherwise, an
4207 head, the other head is merged with by default. Otherwise, an
4207 explicit revision with which to merge with must be provided.
4208 explicit revision with which to merge with must be provided.
4208
4209
4209 :hg:`resolve` must be used to resolve unresolved files.
4210 :hg:`resolve` must be used to resolve unresolved files.
4210
4211
4211 To undo an uncommitted merge, use :hg:`update --clean .` which
4212 To undo an uncommitted merge, use :hg:`update --clean .` which
4212 will check out a clean copy of the original merge parent, losing
4213 will check out a clean copy of the original merge parent, losing
4213 all changes.
4214 all changes.
4214
4215
4215 Returns 0 on success, 1 if there are unresolved files.
4216 Returns 0 on success, 1 if there are unresolved files.
4216 """
4217 """
4217
4218
4218 if opts.get('rev') and node:
4219 if opts.get('rev') and node:
4219 raise util.Abort(_("please specify just one revision"))
4220 raise util.Abort(_("please specify just one revision"))
4220 if not node:
4221 if not node:
4221 node = opts.get('rev')
4222 node = opts.get('rev')
4222
4223
4223 if node:
4224 if node:
4224 node = scmutil.revsingle(repo, node).node()
4225 node = scmutil.revsingle(repo, node).node()
4225
4226
4226 if not node and repo._bookmarkcurrent:
4227 if not node and repo._bookmarkcurrent:
4227 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4228 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4228 curhead = repo[repo._bookmarkcurrent].node()
4229 curhead = repo[repo._bookmarkcurrent].node()
4229 if len(bmheads) == 2:
4230 if len(bmheads) == 2:
4230 if curhead == bmheads[0]:
4231 if curhead == bmheads[0]:
4231 node = bmheads[1]
4232 node = bmheads[1]
4232 else:
4233 else:
4233 node = bmheads[0]
4234 node = bmheads[0]
4234 elif len(bmheads) > 2:
4235 elif len(bmheads) > 2:
4235 raise util.Abort(_("multiple matching bookmarks to merge - "
4236 raise util.Abort(_("multiple matching bookmarks to merge - "
4236 "please merge with an explicit rev or bookmark"),
4237 "please merge with an explicit rev or bookmark"),
4237 hint=_("run 'hg heads' to see all heads"))
4238 hint=_("run 'hg heads' to see all heads"))
4238 elif len(bmheads) <= 1:
4239 elif len(bmheads) <= 1:
4239 raise util.Abort(_("no matching bookmark to merge - "
4240 raise util.Abort(_("no matching bookmark to merge - "
4240 "please merge with an explicit rev or bookmark"),
4241 "please merge with an explicit rev or bookmark"),
4241 hint=_("run 'hg heads' to see all heads"))
4242 hint=_("run 'hg heads' to see all heads"))
4242
4243
4243 if not node and not repo._bookmarkcurrent:
4244 if not node and not repo._bookmarkcurrent:
4244 branch = repo[None].branch()
4245 branch = repo[None].branch()
4245 bheads = repo.branchheads(branch)
4246 bheads = repo.branchheads(branch)
4246 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4247 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4247
4248
4248 if len(nbhs) > 2:
4249 if len(nbhs) > 2:
4249 raise util.Abort(_("branch '%s' has %d heads - "
4250 raise util.Abort(_("branch '%s' has %d heads - "
4250 "please merge with an explicit rev")
4251 "please merge with an explicit rev")
4251 % (branch, len(bheads)),
4252 % (branch, len(bheads)),
4252 hint=_("run 'hg heads .' to see heads"))
4253 hint=_("run 'hg heads .' to see heads"))
4253
4254
4254 parent = repo.dirstate.p1()
4255 parent = repo.dirstate.p1()
4255 if len(nbhs) <= 1:
4256 if len(nbhs) <= 1:
4256 if len(bheads) > 1:
4257 if len(bheads) > 1:
4257 raise util.Abort(_("heads are bookmarked - "
4258 raise util.Abort(_("heads are bookmarked - "
4258 "please merge with an explicit rev"),
4259 "please merge with an explicit rev"),
4259 hint=_("run 'hg heads' to see all heads"))
4260 hint=_("run 'hg heads' to see all heads"))
4260 if len(repo.heads()) > 1:
4261 if len(repo.heads()) > 1:
4261 raise util.Abort(_("branch '%s' has one head - "
4262 raise util.Abort(_("branch '%s' has one head - "
4262 "please merge with an explicit rev")
4263 "please merge with an explicit rev")
4263 % branch,
4264 % branch,
4264 hint=_("run 'hg heads' to see all heads"))
4265 hint=_("run 'hg heads' to see all heads"))
4265 msg, hint = _('nothing to merge'), None
4266 msg, hint = _('nothing to merge'), None
4266 if parent != repo.lookup(branch):
4267 if parent != repo.lookup(branch):
4267 hint = _("use 'hg update' instead")
4268 hint = _("use 'hg update' instead")
4268 raise util.Abort(msg, hint=hint)
4269 raise util.Abort(msg, hint=hint)
4269
4270
4270 if parent not in bheads:
4271 if parent not in bheads:
4271 raise util.Abort(_('working directory not at a head revision'),
4272 raise util.Abort(_('working directory not at a head revision'),
4272 hint=_("use 'hg update' or merge with an "
4273 hint=_("use 'hg update' or merge with an "
4273 "explicit revision"))
4274 "explicit revision"))
4274 if parent == nbhs[0]:
4275 if parent == nbhs[0]:
4275 node = nbhs[-1]
4276 node = nbhs[-1]
4276 else:
4277 else:
4277 node = nbhs[0]
4278 node = nbhs[0]
4278
4279
4279 if opts.get('preview'):
4280 if opts.get('preview'):
4280 # find nodes that are ancestors of p2 but not of p1
4281 # find nodes that are ancestors of p2 but not of p1
4281 p1 = repo.lookup('.')
4282 p1 = repo.lookup('.')
4282 p2 = repo.lookup(node)
4283 p2 = repo.lookup(node)
4283 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4284 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4284
4285
4285 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 for node in nodes:
4287 for node in nodes:
4287 displayer.show(repo[node])
4288 displayer.show(repo[node])
4288 displayer.close()
4289 displayer.close()
4289 return 0
4290 return 0
4290
4291
4291 try:
4292 try:
4292 # ui.forcemerge is an internal variable, do not document
4293 # ui.forcemerge is an internal variable, do not document
4293 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4294 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4294 return hg.merge(repo, node, force=opts.get('force'))
4295 return hg.merge(repo, node, force=opts.get('force'))
4295 finally:
4296 finally:
4296 ui.setconfig('ui', 'forcemerge', '')
4297 ui.setconfig('ui', 'forcemerge', '')
4297
4298
4298 @command('outgoing|out',
4299 @command('outgoing|out',
4299 [('f', 'force', None, _('run even when the destination is unrelated')),
4300 [('f', 'force', None, _('run even when the destination is unrelated')),
4300 ('r', 'rev', [],
4301 ('r', 'rev', [],
4301 _('a changeset intended to be included in the destination'), _('REV')),
4302 _('a changeset intended to be included in the destination'), _('REV')),
4302 ('n', 'newest-first', None, _('show newest record first')),
4303 ('n', 'newest-first', None, _('show newest record first')),
4303 ('B', 'bookmarks', False, _('compare bookmarks')),
4304 ('B', 'bookmarks', False, _('compare bookmarks')),
4304 ('b', 'branch', [], _('a specific branch you would like to push'),
4305 ('b', 'branch', [], _('a specific branch you would like to push'),
4305 _('BRANCH')),
4306 _('BRANCH')),
4306 ] + logopts + remoteopts + subrepoopts,
4307 ] + logopts + remoteopts + subrepoopts,
4307 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4308 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4308 def outgoing(ui, repo, dest=None, **opts):
4309 def outgoing(ui, repo, dest=None, **opts):
4309 """show changesets not found in the destination
4310 """show changesets not found in the destination
4310
4311
4311 Show changesets not found in the specified destination repository
4312 Show changesets not found in the specified destination repository
4312 or the default push location. These are the changesets that would
4313 or the default push location. These are the changesets that would
4313 be pushed if a push was requested.
4314 be pushed if a push was requested.
4314
4315
4315 See pull for details of valid destination formats.
4316 See pull for details of valid destination formats.
4316
4317
4317 Returns 0 if there are outgoing changes, 1 otherwise.
4318 Returns 0 if there are outgoing changes, 1 otherwise.
4318 """
4319 """
4319 if opts.get('graph'):
4320 if opts.get('graph'):
4320 cmdutil.checkunsupportedgraphflags([], opts)
4321 cmdutil.checkunsupportedgraphflags([], opts)
4321 o = hg._outgoing(ui, repo, dest, opts)
4322 o = hg._outgoing(ui, repo, dest, opts)
4322 if o is None:
4323 if o is None:
4323 return
4324 return
4324
4325
4325 revdag = cmdutil.graphrevs(repo, o, opts)
4326 revdag = cmdutil.graphrevs(repo, o, opts)
4326 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4327 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4328 showparents = [ctx.node() for ctx in repo[None].parents()]
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4329 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4329 graphmod.asciiedges)
4330 graphmod.asciiedges)
4330 return 0
4331 return 0
4331
4332
4332 if opts.get('bookmarks'):
4333 if opts.get('bookmarks'):
4333 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4334 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4334 dest, branches = hg.parseurl(dest, opts.get('branch'))
4335 dest, branches = hg.parseurl(dest, opts.get('branch'))
4335 other = hg.peer(repo, opts, dest)
4336 other = hg.peer(repo, opts, dest)
4336 if 'bookmarks' not in other.listkeys('namespaces'):
4337 if 'bookmarks' not in other.listkeys('namespaces'):
4337 ui.warn(_("remote doesn't support bookmarks\n"))
4338 ui.warn(_("remote doesn't support bookmarks\n"))
4338 return 0
4339 return 0
4339 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4340 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4340 return bookmarks.diff(ui, other, repo)
4341 return bookmarks.diff(ui, other, repo)
4341
4342
4342 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4343 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4343 try:
4344 try:
4344 return hg.outgoing(ui, repo, dest, opts)
4345 return hg.outgoing(ui, repo, dest, opts)
4345 finally:
4346 finally:
4346 del repo._subtoppath
4347 del repo._subtoppath
4347
4348
4348 @command('parents',
4349 @command('parents',
4349 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4350 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4350 ] + templateopts,
4351 ] + templateopts,
4351 _('[-r REV] [FILE]'))
4352 _('[-r REV] [FILE]'))
4352 def parents(ui, repo, file_=None, **opts):
4353 def parents(ui, repo, file_=None, **opts):
4353 """show the parents of the working directory or revision
4354 """show the parents of the working directory or revision
4354
4355
4355 Print the working directory's parent revisions. If a revision is
4356 Print the working directory's parent revisions. If a revision is
4356 given via -r/--rev, the parent of that revision will be printed.
4357 given via -r/--rev, the parent of that revision will be printed.
4357 If a file argument is given, the revision in which the file was
4358 If a file argument is given, the revision in which the file was
4358 last changed (before the working directory revision or the
4359 last changed (before the working directory revision or the
4359 argument to --rev if given) is printed.
4360 argument to --rev if given) is printed.
4360
4361
4361 Returns 0 on success.
4362 Returns 0 on success.
4362 """
4363 """
4363
4364
4364 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4365 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4365
4366
4366 if file_:
4367 if file_:
4367 m = scmutil.match(ctx, (file_,), opts)
4368 m = scmutil.match(ctx, (file_,), opts)
4368 if m.anypats() or len(m.files()) != 1:
4369 if m.anypats() or len(m.files()) != 1:
4369 raise util.Abort(_('can only specify an explicit filename'))
4370 raise util.Abort(_('can only specify an explicit filename'))
4370 file_ = m.files()[0]
4371 file_ = m.files()[0]
4371 filenodes = []
4372 filenodes = []
4372 for cp in ctx.parents():
4373 for cp in ctx.parents():
4373 if not cp:
4374 if not cp:
4374 continue
4375 continue
4375 try:
4376 try:
4376 filenodes.append(cp.filenode(file_))
4377 filenodes.append(cp.filenode(file_))
4377 except error.LookupError:
4378 except error.LookupError:
4378 pass
4379 pass
4379 if not filenodes:
4380 if not filenodes:
4380 raise util.Abort(_("'%s' not found in manifest!") % file_)
4381 raise util.Abort(_("'%s' not found in manifest!") % file_)
4381 p = []
4382 p = []
4382 for fn in filenodes:
4383 for fn in filenodes:
4383 fctx = repo.filectx(file_, fileid=fn)
4384 fctx = repo.filectx(file_, fileid=fn)
4384 p.append(fctx.node())
4385 p.append(fctx.node())
4385 else:
4386 else:
4386 p = [cp.node() for cp in ctx.parents()]
4387 p = [cp.node() for cp in ctx.parents()]
4387
4388
4388 displayer = cmdutil.show_changeset(ui, repo, opts)
4389 displayer = cmdutil.show_changeset(ui, repo, opts)
4389 for n in p:
4390 for n in p:
4390 if n != nullid:
4391 if n != nullid:
4391 displayer.show(repo[n])
4392 displayer.show(repo[n])
4392 displayer.close()
4393 displayer.close()
4393
4394
4394 @command('paths', [], _('[NAME]'))
4395 @command('paths', [], _('[NAME]'))
4395 def paths(ui, repo, search=None):
4396 def paths(ui, repo, search=None):
4396 """show aliases for remote repositories
4397 """show aliases for remote repositories
4397
4398
4398 Show definition of symbolic path name NAME. If no name is given,
4399 Show definition of symbolic path name NAME. If no name is given,
4399 show definition of all available names.
4400 show definition of all available names.
4400
4401
4401 Option -q/--quiet suppresses all output when searching for NAME
4402 Option -q/--quiet suppresses all output when searching for NAME
4402 and shows only the path names when listing all definitions.
4403 and shows only the path names when listing all definitions.
4403
4404
4404 Path names are defined in the [paths] section of your
4405 Path names are defined in the [paths] section of your
4405 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4406 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4406 repository, ``.hg/hgrc`` is used, too.
4407 repository, ``.hg/hgrc`` is used, too.
4407
4408
4408 The path names ``default`` and ``default-push`` have a special
4409 The path names ``default`` and ``default-push`` have a special
4409 meaning. When performing a push or pull operation, they are used
4410 meaning. When performing a push or pull operation, they are used
4410 as fallbacks if no location is specified on the command-line.
4411 as fallbacks if no location is specified on the command-line.
4411 When ``default-push`` is set, it will be used for push and
4412 When ``default-push`` is set, it will be used for push and
4412 ``default`` will be used for pull; otherwise ``default`` is used
4413 ``default`` will be used for pull; otherwise ``default`` is used
4413 as the fallback for both. When cloning a repository, the clone
4414 as the fallback for both. When cloning a repository, the clone
4414 source is written as ``default`` in ``.hg/hgrc``. Note that
4415 source is written as ``default`` in ``.hg/hgrc``. Note that
4415 ``default`` and ``default-push`` apply to all inbound (e.g.
4416 ``default`` and ``default-push`` apply to all inbound (e.g.
4416 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4417 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4417 :hg:`bundle`) operations.
4418 :hg:`bundle`) operations.
4418
4419
4419 See :hg:`help urls` for more information.
4420 See :hg:`help urls` for more information.
4420
4421
4421 Returns 0 on success.
4422 Returns 0 on success.
4422 """
4423 """
4423 if search:
4424 if search:
4424 for name, path in ui.configitems("paths"):
4425 for name, path in ui.configitems("paths"):
4425 if name == search:
4426 if name == search:
4426 ui.status("%s\n" % util.hidepassword(path))
4427 ui.status("%s\n" % util.hidepassword(path))
4427 return
4428 return
4428 if not ui.quiet:
4429 if not ui.quiet:
4429 ui.warn(_("not found!\n"))
4430 ui.warn(_("not found!\n"))
4430 return 1
4431 return 1
4431 else:
4432 else:
4432 for name, path in ui.configitems("paths"):
4433 for name, path in ui.configitems("paths"):
4433 if ui.quiet:
4434 if ui.quiet:
4434 ui.write("%s\n" % name)
4435 ui.write("%s\n" % name)
4435 else:
4436 else:
4436 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4437 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4437
4438
4438 @command('phase',
4439 @command('phase',
4439 [('p', 'public', False, _('set changeset phase to public')),
4440 [('p', 'public', False, _('set changeset phase to public')),
4440 ('d', 'draft', False, _('set changeset phase to draft')),
4441 ('d', 'draft', False, _('set changeset phase to draft')),
4441 ('s', 'secret', False, _('set changeset phase to secret')),
4442 ('s', 'secret', False, _('set changeset phase to secret')),
4442 ('f', 'force', False, _('allow to move boundary backward')),
4443 ('f', 'force', False, _('allow to move boundary backward')),
4443 ('r', 'rev', [], _('target revision'), _('REV')),
4444 ('r', 'rev', [], _('target revision'), _('REV')),
4444 ],
4445 ],
4445 _('[-p|-d|-s] [-f] [-r] REV...'))
4446 _('[-p|-d|-s] [-f] [-r] REV...'))
4446 def phase(ui, repo, *revs, **opts):
4447 def phase(ui, repo, *revs, **opts):
4447 """set or show the current phase name
4448 """set or show the current phase name
4448
4449
4449 With no argument, show the phase name of specified revisions.
4450 With no argument, show the phase name of specified revisions.
4450
4451
4451 With one of -p/--public, -d/--draft or -s/--secret, change the
4452 With one of -p/--public, -d/--draft or -s/--secret, change the
4452 phase value of the specified revisions.
4453 phase value of the specified revisions.
4453
4454
4454 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4455 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4455 lower phase to an higher phase. Phases are ordered as follows::
4456 lower phase to an higher phase. Phases are ordered as follows::
4456
4457
4457 public < draft < secret
4458 public < draft < secret
4458
4459
4459 Return 0 on success, 1 if no phases were changed or some could not
4460 Return 0 on success, 1 if no phases were changed or some could not
4460 be changed.
4461 be changed.
4461 """
4462 """
4462 # search for a unique phase argument
4463 # search for a unique phase argument
4463 targetphase = None
4464 targetphase = None
4464 for idx, name in enumerate(phases.phasenames):
4465 for idx, name in enumerate(phases.phasenames):
4465 if opts[name]:
4466 if opts[name]:
4466 if targetphase is not None:
4467 if targetphase is not None:
4467 raise util.Abort(_('only one phase can be specified'))
4468 raise util.Abort(_('only one phase can be specified'))
4468 targetphase = idx
4469 targetphase = idx
4469
4470
4470 # look for specified revision
4471 # look for specified revision
4471 revs = list(revs)
4472 revs = list(revs)
4472 revs.extend(opts['rev'])
4473 revs.extend(opts['rev'])
4473 if not revs:
4474 if not revs:
4474 raise util.Abort(_('no revisions specified'))
4475 raise util.Abort(_('no revisions specified'))
4475
4476
4476 revs = scmutil.revrange(repo, revs)
4477 revs = scmutil.revrange(repo, revs)
4477
4478
4478 lock = None
4479 lock = None
4479 ret = 0
4480 ret = 0
4480 if targetphase is None:
4481 if targetphase is None:
4481 # display
4482 # display
4482 for r in revs:
4483 for r in revs:
4483 ctx = repo[r]
4484 ctx = repo[r]
4484 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4485 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4485 else:
4486 else:
4486 lock = repo.lock()
4487 lock = repo.lock()
4487 try:
4488 try:
4488 # set phase
4489 # set phase
4489 if not revs:
4490 if not revs:
4490 raise util.Abort(_('empty revision set'))
4491 raise util.Abort(_('empty revision set'))
4491 nodes = [repo[r].node() for r in revs]
4492 nodes = [repo[r].node() for r in revs]
4492 olddata = repo._phasecache.getphaserevs(repo)[:]
4493 olddata = repo._phasecache.getphaserevs(repo)[:]
4493 phases.advanceboundary(repo, targetphase, nodes)
4494 phases.advanceboundary(repo, targetphase, nodes)
4494 if opts['force']:
4495 if opts['force']:
4495 phases.retractboundary(repo, targetphase, nodes)
4496 phases.retractboundary(repo, targetphase, nodes)
4496 finally:
4497 finally:
4497 lock.release()
4498 lock.release()
4498 # moving revision from public to draft may hide them
4499 # moving revision from public to draft may hide them
4499 # We have to check result on an unfiltered repository
4500 # We have to check result on an unfiltered repository
4500 unfi = repo.unfiltered()
4501 unfi = repo.unfiltered()
4501 newdata = repo._phasecache.getphaserevs(unfi)
4502 newdata = repo._phasecache.getphaserevs(unfi)
4502 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4503 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4503 cl = unfi.changelog
4504 cl = unfi.changelog
4504 rejected = [n for n in nodes
4505 rejected = [n for n in nodes
4505 if newdata[cl.rev(n)] < targetphase]
4506 if newdata[cl.rev(n)] < targetphase]
4506 if rejected:
4507 if rejected:
4507 ui.warn(_('cannot move %i changesets to a more permissive '
4508 ui.warn(_('cannot move %i changesets to a more permissive '
4508 'phase, use --force\n') % len(rejected))
4509 'phase, use --force\n') % len(rejected))
4509 ret = 1
4510 ret = 1
4510 if changes:
4511 if changes:
4511 msg = _('phase changed for %i changesets\n') % changes
4512 msg = _('phase changed for %i changesets\n') % changes
4512 if ret:
4513 if ret:
4513 ui.status(msg)
4514 ui.status(msg)
4514 else:
4515 else:
4515 ui.note(msg)
4516 ui.note(msg)
4516 else:
4517 else:
4517 ui.warn(_('no phases changed\n'))
4518 ui.warn(_('no phases changed\n'))
4518 ret = 1
4519 ret = 1
4519 return ret
4520 return ret
4520
4521
4521 def postincoming(ui, repo, modheads, optupdate, checkout):
4522 def postincoming(ui, repo, modheads, optupdate, checkout):
4522 if modheads == 0:
4523 if modheads == 0:
4523 return
4524 return
4524 if optupdate:
4525 if optupdate:
4525 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4526 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4526 try:
4527 try:
4527 ret = hg.update(repo, checkout)
4528 ret = hg.update(repo, checkout)
4528 except util.Abort, inst:
4529 except util.Abort, inst:
4529 ui.warn(_("not updating: %s\n") % str(inst))
4530 ui.warn(_("not updating: %s\n") % str(inst))
4530 if inst.hint:
4531 if inst.hint:
4531 ui.warn(_("(%s)\n") % inst.hint)
4532 ui.warn(_("(%s)\n") % inst.hint)
4532 return 0
4533 return 0
4533 if not ret and not checkout:
4534 if not ret and not checkout:
4534 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4535 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4535 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4536 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4536 return ret
4537 return ret
4537 if modheads > 1:
4538 if modheads > 1:
4538 currentbranchheads = len(repo.branchheads())
4539 currentbranchheads = len(repo.branchheads())
4539 if currentbranchheads == modheads:
4540 if currentbranchheads == modheads:
4540 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4541 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4541 elif currentbranchheads > 1:
4542 elif currentbranchheads > 1:
4542 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4543 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4543 "merge)\n"))
4544 "merge)\n"))
4544 else:
4545 else:
4545 ui.status(_("(run 'hg heads' to see heads)\n"))
4546 ui.status(_("(run 'hg heads' to see heads)\n"))
4546 else:
4547 else:
4547 ui.status(_("(run 'hg update' to get a working copy)\n"))
4548 ui.status(_("(run 'hg update' to get a working copy)\n"))
4548
4549
4549 @command('^pull',
4550 @command('^pull',
4550 [('u', 'update', None,
4551 [('u', 'update', None,
4551 _('update to new branch head if changesets were pulled')),
4552 _('update to new branch head if changesets were pulled')),
4552 ('f', 'force', None, _('run even when remote repository is unrelated')),
4553 ('f', 'force', None, _('run even when remote repository is unrelated')),
4553 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4554 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4554 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4555 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4555 ('b', 'branch', [], _('a specific branch you would like to pull'),
4556 ('b', 'branch', [], _('a specific branch you would like to pull'),
4556 _('BRANCH')),
4557 _('BRANCH')),
4557 ] + remoteopts,
4558 ] + remoteopts,
4558 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4559 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4559 def pull(ui, repo, source="default", **opts):
4560 def pull(ui, repo, source="default", **opts):
4560 """pull changes from the specified source
4561 """pull changes from the specified source
4561
4562
4562 Pull changes from a remote repository to a local one.
4563 Pull changes from a remote repository to a local one.
4563
4564
4564 This finds all changes from the repository at the specified path
4565 This finds all changes from the repository at the specified path
4565 or URL and adds them to a local repository (the current one unless
4566 or URL and adds them to a local repository (the current one unless
4566 -R is specified). By default, this does not update the copy of the
4567 -R is specified). By default, this does not update the copy of the
4567 project in the working directory.
4568 project in the working directory.
4568
4569
4569 Use :hg:`incoming` if you want to see what would have been added
4570 Use :hg:`incoming` if you want to see what would have been added
4570 by a pull at the time you issued this command. If you then decide
4571 by a pull at the time you issued this command. If you then decide
4571 to add those changes to the repository, you should use :hg:`pull
4572 to add those changes to the repository, you should use :hg:`pull
4572 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4573 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4573
4574
4574 If SOURCE is omitted, the 'default' path will be used.
4575 If SOURCE is omitted, the 'default' path will be used.
4575 See :hg:`help urls` for more information.
4576 See :hg:`help urls` for more information.
4576
4577
4577 Returns 0 on success, 1 if an update had unresolved files.
4578 Returns 0 on success, 1 if an update had unresolved files.
4578 """
4579 """
4579 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4580 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4580 other = hg.peer(repo, opts, source)
4581 other = hg.peer(repo, opts, source)
4581 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4582 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4582 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4583 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4583
4584
4584 remotebookmarks = other.listkeys('bookmarks')
4585 remotebookmarks = other.listkeys('bookmarks')
4585
4586
4586 if opts.get('bookmark'):
4587 if opts.get('bookmark'):
4587 if not revs:
4588 if not revs:
4588 revs = []
4589 revs = []
4589 for b in opts['bookmark']:
4590 for b in opts['bookmark']:
4590 if b not in remotebookmarks:
4591 if b not in remotebookmarks:
4591 raise util.Abort(_('remote bookmark %s not found!') % b)
4592 raise util.Abort(_('remote bookmark %s not found!') % b)
4592 revs.append(remotebookmarks[b])
4593 revs.append(remotebookmarks[b])
4593
4594
4594 if revs:
4595 if revs:
4595 try:
4596 try:
4596 revs = [other.lookup(rev) for rev in revs]
4597 revs = [other.lookup(rev) for rev in revs]
4597 except error.CapabilityError:
4598 except error.CapabilityError:
4598 err = _("other repository doesn't support revision lookup, "
4599 err = _("other repository doesn't support revision lookup, "
4599 "so a rev cannot be specified.")
4600 "so a rev cannot be specified.")
4600 raise util.Abort(err)
4601 raise util.Abort(err)
4601
4602
4602 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4603 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4603 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4604 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4604 if checkout:
4605 if checkout:
4605 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4606 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4606 repo._subtoppath = source
4607 repo._subtoppath = source
4607 try:
4608 try:
4608 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4609 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4609
4610
4610 finally:
4611 finally:
4611 del repo._subtoppath
4612 del repo._subtoppath
4612
4613
4613 # update specified bookmarks
4614 # update specified bookmarks
4614 if opts.get('bookmark'):
4615 if opts.get('bookmark'):
4615 marks = repo._bookmarks
4616 marks = repo._bookmarks
4616 for b in opts['bookmark']:
4617 for b in opts['bookmark']:
4617 # explicit pull overrides local bookmark if any
4618 # explicit pull overrides local bookmark if any
4618 ui.status(_("importing bookmark %s\n") % b)
4619 ui.status(_("importing bookmark %s\n") % b)
4619 marks[b] = repo[remotebookmarks[b]].node()
4620 marks[b] = repo[remotebookmarks[b]].node()
4620 marks.write()
4621 marks.write()
4621
4622
4622 return ret
4623 return ret
4623
4624
4624 @command('^push',
4625 @command('^push',
4625 [('f', 'force', None, _('force push')),
4626 [('f', 'force', None, _('force push')),
4626 ('r', 'rev', [],
4627 ('r', 'rev', [],
4627 _('a changeset intended to be included in the destination'),
4628 _('a changeset intended to be included in the destination'),
4628 _('REV')),
4629 _('REV')),
4629 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4630 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4630 ('b', 'branch', [],
4631 ('b', 'branch', [],
4631 _('a specific branch you would like to push'), _('BRANCH')),
4632 _('a specific branch you would like to push'), _('BRANCH')),
4632 ('', 'new-branch', False, _('allow pushing a new branch')),
4633 ('', 'new-branch', False, _('allow pushing a new branch')),
4633 ] + remoteopts,
4634 ] + remoteopts,
4634 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4635 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4635 def push(ui, repo, dest=None, **opts):
4636 def push(ui, repo, dest=None, **opts):
4636 """push changes to the specified destination
4637 """push changes to the specified destination
4637
4638
4638 Push changesets from the local repository to the specified
4639 Push changesets from the local repository to the specified
4639 destination.
4640 destination.
4640
4641
4641 This operation is symmetrical to pull: it is identical to a pull
4642 This operation is symmetrical to pull: it is identical to a pull
4642 in the destination repository from the current one.
4643 in the destination repository from the current one.
4643
4644
4644 By default, push will not allow creation of new heads at the
4645 By default, push will not allow creation of new heads at the
4645 destination, since multiple heads would make it unclear which head
4646 destination, since multiple heads would make it unclear which head
4646 to use. In this situation, it is recommended to pull and merge
4647 to use. In this situation, it is recommended to pull and merge
4647 before pushing.
4648 before pushing.
4648
4649
4649 Use --new-branch if you want to allow push to create a new named
4650 Use --new-branch if you want to allow push to create a new named
4650 branch that is not present at the destination. This allows you to
4651 branch that is not present at the destination. This allows you to
4651 only create a new branch without forcing other changes.
4652 only create a new branch without forcing other changes.
4652
4653
4653 Use -f/--force to override the default behavior and push all
4654 Use -f/--force to override the default behavior and push all
4654 changesets on all branches.
4655 changesets on all branches.
4655
4656
4656 If -r/--rev is used, the specified revision and all its ancestors
4657 If -r/--rev is used, the specified revision and all its ancestors
4657 will be pushed to the remote repository.
4658 will be pushed to the remote repository.
4658
4659
4659 If -B/--bookmark is used, the specified bookmarked revision, its
4660 If -B/--bookmark is used, the specified bookmarked revision, its
4660 ancestors, and the bookmark will be pushed to the remote
4661 ancestors, and the bookmark will be pushed to the remote
4661 repository.
4662 repository.
4662
4663
4663 Please see :hg:`help urls` for important details about ``ssh://``
4664 Please see :hg:`help urls` for important details about ``ssh://``
4664 URLs. If DESTINATION is omitted, a default path will be used.
4665 URLs. If DESTINATION is omitted, a default path will be used.
4665
4666
4666 Returns 0 if push was successful, 1 if nothing to push.
4667 Returns 0 if push was successful, 1 if nothing to push.
4667 """
4668 """
4668
4669
4669 if opts.get('bookmark'):
4670 if opts.get('bookmark'):
4670 for b in opts['bookmark']:
4671 for b in opts['bookmark']:
4671 # translate -B options to -r so changesets get pushed
4672 # translate -B options to -r so changesets get pushed
4672 if b in repo._bookmarks:
4673 if b in repo._bookmarks:
4673 opts.setdefault('rev', []).append(b)
4674 opts.setdefault('rev', []).append(b)
4674 else:
4675 else:
4675 # if we try to push a deleted bookmark, translate it to null
4676 # if we try to push a deleted bookmark, translate it to null
4676 # this lets simultaneous -r, -b options continue working
4677 # this lets simultaneous -r, -b options continue working
4677 opts.setdefault('rev', []).append("null")
4678 opts.setdefault('rev', []).append("null")
4678
4679
4679 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4680 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4680 dest, branches = hg.parseurl(dest, opts.get('branch'))
4681 dest, branches = hg.parseurl(dest, opts.get('branch'))
4681 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4682 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4682 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4683 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4683 other = hg.peer(repo, opts, dest)
4684 other = hg.peer(repo, opts, dest)
4684 if revs:
4685 if revs:
4685 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4686 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4686
4687
4687 repo._subtoppath = dest
4688 repo._subtoppath = dest
4688 try:
4689 try:
4689 # push subrepos depth-first for coherent ordering
4690 # push subrepos depth-first for coherent ordering
4690 c = repo['']
4691 c = repo['']
4691 subs = c.substate # only repos that are committed
4692 subs = c.substate # only repos that are committed
4692 for s in sorted(subs):
4693 for s in sorted(subs):
4693 if c.sub(s).push(opts) == 0:
4694 if c.sub(s).push(opts) == 0:
4694 return False
4695 return False
4695 finally:
4696 finally:
4696 del repo._subtoppath
4697 del repo._subtoppath
4697 result = repo.push(other, opts.get('force'), revs=revs,
4698 result = repo.push(other, opts.get('force'), revs=revs,
4698 newbranch=opts.get('new_branch'))
4699 newbranch=opts.get('new_branch'))
4699
4700
4700 result = not result
4701 result = not result
4701
4702
4702 if opts.get('bookmark'):
4703 if opts.get('bookmark'):
4703 rb = other.listkeys('bookmarks')
4704 rb = other.listkeys('bookmarks')
4704 for b in opts['bookmark']:
4705 for b in opts['bookmark']:
4705 # explicit push overrides remote bookmark if any
4706 # explicit push overrides remote bookmark if any
4706 if b in repo._bookmarks:
4707 if b in repo._bookmarks:
4707 ui.status(_("exporting bookmark %s\n") % b)
4708 ui.status(_("exporting bookmark %s\n") % b)
4708 new = repo[b].hex()
4709 new = repo[b].hex()
4709 elif b in rb:
4710 elif b in rb:
4710 ui.status(_("deleting remote bookmark %s\n") % b)
4711 ui.status(_("deleting remote bookmark %s\n") % b)
4711 new = '' # delete
4712 new = '' # delete
4712 else:
4713 else:
4713 ui.warn(_('bookmark %s does not exist on the local '
4714 ui.warn(_('bookmark %s does not exist on the local '
4714 'or remote repository!\n') % b)
4715 'or remote repository!\n') % b)
4715 return 2
4716 return 2
4716 old = rb.get(b, '')
4717 old = rb.get(b, '')
4717 r = other.pushkey('bookmarks', b, old, new)
4718 r = other.pushkey('bookmarks', b, old, new)
4718 if not r:
4719 if not r:
4719 ui.warn(_('updating bookmark %s failed!\n') % b)
4720 ui.warn(_('updating bookmark %s failed!\n') % b)
4720 if not result:
4721 if not result:
4721 result = 2
4722 result = 2
4722
4723
4723 return result
4724 return result
4724
4725
4725 @command('recover', [])
4726 @command('recover', [])
4726 def recover(ui, repo):
4727 def recover(ui, repo):
4727 """roll back an interrupted transaction
4728 """roll back an interrupted transaction
4728
4729
4729 Recover from an interrupted commit or pull.
4730 Recover from an interrupted commit or pull.
4730
4731
4731 This command tries to fix the repository status after an
4732 This command tries to fix the repository status after an
4732 interrupted operation. It should only be necessary when Mercurial
4733 interrupted operation. It should only be necessary when Mercurial
4733 suggests it.
4734 suggests it.
4734
4735
4735 Returns 0 if successful, 1 if nothing to recover or verify fails.
4736 Returns 0 if successful, 1 if nothing to recover or verify fails.
4736 """
4737 """
4737 if repo.recover():
4738 if repo.recover():
4738 return hg.verify(repo)
4739 return hg.verify(repo)
4739 return 1
4740 return 1
4740
4741
4741 @command('^remove|rm',
4742 @command('^remove|rm',
4742 [('A', 'after', None, _('record delete for missing files')),
4743 [('A', 'after', None, _('record delete for missing files')),
4743 ('f', 'force', None,
4744 ('f', 'force', None,
4744 _('remove (and delete) file even if added or modified')),
4745 _('remove (and delete) file even if added or modified')),
4745 ] + walkopts,
4746 ] + walkopts,
4746 _('[OPTION]... FILE...'))
4747 _('[OPTION]... FILE...'))
4747 def remove(ui, repo, *pats, **opts):
4748 def remove(ui, repo, *pats, **opts):
4748 """remove the specified files on the next commit
4749 """remove the specified files on the next commit
4749
4750
4750 Schedule the indicated files for removal from the current branch.
4751 Schedule the indicated files for removal from the current branch.
4751
4752
4752 This command schedules the files to be removed at the next commit.
4753 This command schedules the files to be removed at the next commit.
4753 To undo a remove before that, see :hg:`revert`. To undo added
4754 To undo a remove before that, see :hg:`revert`. To undo added
4754 files, see :hg:`forget`.
4755 files, see :hg:`forget`.
4755
4756
4756 .. container:: verbose
4757 .. container:: verbose
4757
4758
4758 -A/--after can be used to remove only files that have already
4759 -A/--after can be used to remove only files that have already
4759 been deleted, -f/--force can be used to force deletion, and -Af
4760 been deleted, -f/--force can be used to force deletion, and -Af
4760 can be used to remove files from the next revision without
4761 can be used to remove files from the next revision without
4761 deleting them from the working directory.
4762 deleting them from the working directory.
4762
4763
4763 The following table details the behavior of remove for different
4764 The following table details the behavior of remove for different
4764 file states (columns) and option combinations (rows). The file
4765 file states (columns) and option combinations (rows). The file
4765 states are Added [A], Clean [C], Modified [M] and Missing [!]
4766 states are Added [A], Clean [C], Modified [M] and Missing [!]
4766 (as reported by :hg:`status`). The actions are Warn, Remove
4767 (as reported by :hg:`status`). The actions are Warn, Remove
4767 (from branch) and Delete (from disk):
4768 (from branch) and Delete (from disk):
4768
4769
4769 ======= == == == ==
4770 ======= == == == ==
4770 A C M !
4771 A C M !
4771 ======= == == == ==
4772 ======= == == == ==
4772 none W RD W R
4773 none W RD W R
4773 -f R RD RD R
4774 -f R RD RD R
4774 -A W W W R
4775 -A W W W R
4775 -Af R R R R
4776 -Af R R R R
4776 ======= == == == ==
4777 ======= == == == ==
4777
4778
4778 Note that remove never deletes files in Added [A] state from the
4779 Note that remove never deletes files in Added [A] state from the
4779 working directory, not even if option --force is specified.
4780 working directory, not even if option --force is specified.
4780
4781
4781 Returns 0 on success, 1 if any warnings encountered.
4782 Returns 0 on success, 1 if any warnings encountered.
4782 """
4783 """
4783
4784
4784 ret = 0
4785 ret = 0
4785 after, force = opts.get('after'), opts.get('force')
4786 after, force = opts.get('after'), opts.get('force')
4786 if not pats and not after:
4787 if not pats and not after:
4787 raise util.Abort(_('no files specified'))
4788 raise util.Abort(_('no files specified'))
4788
4789
4789 m = scmutil.match(repo[None], pats, opts)
4790 m = scmutil.match(repo[None], pats, opts)
4790 s = repo.status(match=m, clean=True)
4791 s = repo.status(match=m, clean=True)
4791 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4792 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4792
4793
4793 # warn about failure to delete explicit files/dirs
4794 # warn about failure to delete explicit files/dirs
4794 wctx = repo[None]
4795 wctx = repo[None]
4795 for f in m.files():
4796 for f in m.files():
4796 if f in repo.dirstate or f in wctx.dirs():
4797 if f in repo.dirstate or f in wctx.dirs():
4797 continue
4798 continue
4798 if os.path.exists(m.rel(f)):
4799 if os.path.exists(m.rel(f)):
4799 if os.path.isdir(m.rel(f)):
4800 if os.path.isdir(m.rel(f)):
4800 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4801 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4801 else:
4802 else:
4802 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4803 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4803 # missing files will generate a warning elsewhere
4804 # missing files will generate a warning elsewhere
4804 ret = 1
4805 ret = 1
4805
4806
4806 if force:
4807 if force:
4807 list = modified + deleted + clean + added
4808 list = modified + deleted + clean + added
4808 elif after:
4809 elif after:
4809 list = deleted
4810 list = deleted
4810 for f in modified + added + clean:
4811 for f in modified + added + clean:
4811 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4812 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4812 ret = 1
4813 ret = 1
4813 else:
4814 else:
4814 list = deleted + clean
4815 list = deleted + clean
4815 for f in modified:
4816 for f in modified:
4816 ui.warn(_('not removing %s: file is modified (use -f'
4817 ui.warn(_('not removing %s: file is modified (use -f'
4817 ' to force removal)\n') % m.rel(f))
4818 ' to force removal)\n') % m.rel(f))
4818 ret = 1
4819 ret = 1
4819 for f in added:
4820 for f in added:
4820 ui.warn(_('not removing %s: file has been marked for add'
4821 ui.warn(_('not removing %s: file has been marked for add'
4821 ' (use forget to undo)\n') % m.rel(f))
4822 ' (use forget to undo)\n') % m.rel(f))
4822 ret = 1
4823 ret = 1
4823
4824
4824 for f in sorted(list):
4825 for f in sorted(list):
4825 if ui.verbose or not m.exact(f):
4826 if ui.verbose or not m.exact(f):
4826 ui.status(_('removing %s\n') % m.rel(f))
4827 ui.status(_('removing %s\n') % m.rel(f))
4827
4828
4828 wlock = repo.wlock()
4829 wlock = repo.wlock()
4829 try:
4830 try:
4830 if not after:
4831 if not after:
4831 for f in list:
4832 for f in list:
4832 if f in added:
4833 if f in added:
4833 continue # we never unlink added files on remove
4834 continue # we never unlink added files on remove
4834 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4835 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4835 repo[None].forget(list)
4836 repo[None].forget(list)
4836 finally:
4837 finally:
4837 wlock.release()
4838 wlock.release()
4838
4839
4839 return ret
4840 return ret
4840
4841
4841 @command('rename|move|mv',
4842 @command('rename|move|mv',
4842 [('A', 'after', None, _('record a rename that has already occurred')),
4843 [('A', 'after', None, _('record a rename that has already occurred')),
4843 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4844 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4844 ] + walkopts + dryrunopts,
4845 ] + walkopts + dryrunopts,
4845 _('[OPTION]... SOURCE... DEST'))
4846 _('[OPTION]... SOURCE... DEST'))
4846 def rename(ui, repo, *pats, **opts):
4847 def rename(ui, repo, *pats, **opts):
4847 """rename files; equivalent of copy + remove
4848 """rename files; equivalent of copy + remove
4848
4849
4849 Mark dest as copies of sources; mark sources for deletion. If dest
4850 Mark dest as copies of sources; mark sources for deletion. If dest
4850 is a directory, copies are put in that directory. If dest is a
4851 is a directory, copies are put in that directory. If dest is a
4851 file, there can only be one source.
4852 file, there can only be one source.
4852
4853
4853 By default, this command copies the contents of files as they
4854 By default, this command copies the contents of files as they
4854 exist in the working directory. If invoked with -A/--after, the
4855 exist in the working directory. If invoked with -A/--after, the
4855 operation is recorded, but no copying is performed.
4856 operation is recorded, but no copying is performed.
4856
4857
4857 This command takes effect at the next commit. To undo a rename
4858 This command takes effect at the next commit. To undo a rename
4858 before that, see :hg:`revert`.
4859 before that, see :hg:`revert`.
4859
4860
4860 Returns 0 on success, 1 if errors are encountered.
4861 Returns 0 on success, 1 if errors are encountered.
4861 """
4862 """
4862 wlock = repo.wlock(False)
4863 wlock = repo.wlock(False)
4863 try:
4864 try:
4864 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4865 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4865 finally:
4866 finally:
4866 wlock.release()
4867 wlock.release()
4867
4868
4868 @command('resolve',
4869 @command('resolve',
4869 [('a', 'all', None, _('select all unresolved files')),
4870 [('a', 'all', None, _('select all unresolved files')),
4870 ('l', 'list', None, _('list state of files needing merge')),
4871 ('l', 'list', None, _('list state of files needing merge')),
4871 ('m', 'mark', None, _('mark files as resolved')),
4872 ('m', 'mark', None, _('mark files as resolved')),
4872 ('u', 'unmark', None, _('mark files as unresolved')),
4873 ('u', 'unmark', None, _('mark files as unresolved')),
4873 ('n', 'no-status', None, _('hide status prefix'))]
4874 ('n', 'no-status', None, _('hide status prefix'))]
4874 + mergetoolopts + walkopts,
4875 + mergetoolopts + walkopts,
4875 _('[OPTION]... [FILE]...'))
4876 _('[OPTION]... [FILE]...'))
4876 def resolve(ui, repo, *pats, **opts):
4877 def resolve(ui, repo, *pats, **opts):
4877 """redo merges or set/view the merge status of files
4878 """redo merges or set/view the merge status of files
4878
4879
4879 Merges with unresolved conflicts are often the result of
4880 Merges with unresolved conflicts are often the result of
4880 non-interactive merging using the ``internal:merge`` configuration
4881 non-interactive merging using the ``internal:merge`` configuration
4881 setting, or a command-line merge tool like ``diff3``. The resolve
4882 setting, or a command-line merge tool like ``diff3``. The resolve
4882 command is used to manage the files involved in a merge, after
4883 command is used to manage the files involved in a merge, after
4883 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4884 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4884 working directory must have two parents). See :hg:`help
4885 working directory must have two parents). See :hg:`help
4885 merge-tools` for information on configuring merge tools.
4886 merge-tools` for information on configuring merge tools.
4886
4887
4887 The resolve command can be used in the following ways:
4888 The resolve command can be used in the following ways:
4888
4889
4889 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4890 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4890 files, discarding any previous merge attempts. Re-merging is not
4891 files, discarding any previous merge attempts. Re-merging is not
4891 performed for files already marked as resolved. Use ``--all/-a``
4892 performed for files already marked as resolved. Use ``--all/-a``
4892 to select all unresolved files. ``--tool`` can be used to specify
4893 to select all unresolved files. ``--tool`` can be used to specify
4893 the merge tool used for the given files. It overrides the HGMERGE
4894 the merge tool used for the given files. It overrides the HGMERGE
4894 environment variable and your configuration files. Previous file
4895 environment variable and your configuration files. Previous file
4895 contents are saved with a ``.orig`` suffix.
4896 contents are saved with a ``.orig`` suffix.
4896
4897
4897 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4898 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4898 (e.g. after having manually fixed-up the files). The default is
4899 (e.g. after having manually fixed-up the files). The default is
4899 to mark all unresolved files.
4900 to mark all unresolved files.
4900
4901
4901 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4902 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4902 default is to mark all resolved files.
4903 default is to mark all resolved files.
4903
4904
4904 - :hg:`resolve -l`: list files which had or still have conflicts.
4905 - :hg:`resolve -l`: list files which had or still have conflicts.
4905 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4906 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4906
4907
4907 Note that Mercurial will not let you commit files with unresolved
4908 Note that Mercurial will not let you commit files with unresolved
4908 merge conflicts. You must use :hg:`resolve -m ...` before you can
4909 merge conflicts. You must use :hg:`resolve -m ...` before you can
4909 commit after a conflicting merge.
4910 commit after a conflicting merge.
4910
4911
4911 Returns 0 on success, 1 if any files fail a resolve attempt.
4912 Returns 0 on success, 1 if any files fail a resolve attempt.
4912 """
4913 """
4913
4914
4914 all, mark, unmark, show, nostatus = \
4915 all, mark, unmark, show, nostatus = \
4915 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4916 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4916
4917
4917 if (show and (mark or unmark)) or (mark and unmark):
4918 if (show and (mark or unmark)) or (mark and unmark):
4918 raise util.Abort(_("too many options specified"))
4919 raise util.Abort(_("too many options specified"))
4919 if pats and all:
4920 if pats and all:
4920 raise util.Abort(_("can't specify --all and patterns"))
4921 raise util.Abort(_("can't specify --all and patterns"))
4921 if not (all or pats or show or mark or unmark):
4922 if not (all or pats or show or mark or unmark):
4922 raise util.Abort(_('no files or directories specified; '
4923 raise util.Abort(_('no files or directories specified; '
4923 'use --all to remerge all files'))
4924 'use --all to remerge all files'))
4924
4925
4925 ms = mergemod.mergestate(repo)
4926 ms = mergemod.mergestate(repo)
4926 m = scmutil.match(repo[None], pats, opts)
4927 m = scmutil.match(repo[None], pats, opts)
4927 ret = 0
4928 ret = 0
4928
4929
4929 for f in ms:
4930 for f in ms:
4930 if m(f):
4931 if m(f):
4931 if show:
4932 if show:
4932 if nostatus:
4933 if nostatus:
4933 ui.write("%s\n" % f)
4934 ui.write("%s\n" % f)
4934 else:
4935 else:
4935 ui.write("%s %s\n" % (ms[f].upper(), f),
4936 ui.write("%s %s\n" % (ms[f].upper(), f),
4936 label='resolve.' +
4937 label='resolve.' +
4937 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4938 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4938 elif mark:
4939 elif mark:
4939 ms.mark(f, "r")
4940 ms.mark(f, "r")
4940 elif unmark:
4941 elif unmark:
4941 ms.mark(f, "u")
4942 ms.mark(f, "u")
4942 else:
4943 else:
4943 wctx = repo[None]
4944 wctx = repo[None]
4944 mctx = wctx.parents()[-1]
4945 mctx = wctx.parents()[-1]
4945
4946
4946 # backup pre-resolve (merge uses .orig for its own purposes)
4947 # backup pre-resolve (merge uses .orig for its own purposes)
4947 a = repo.wjoin(f)
4948 a = repo.wjoin(f)
4948 util.copyfile(a, a + ".resolve")
4949 util.copyfile(a, a + ".resolve")
4949
4950
4950 try:
4951 try:
4951 # resolve file
4952 # resolve file
4952 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4953 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4953 if ms.resolve(f, wctx, mctx):
4954 if ms.resolve(f, wctx, mctx):
4954 ret = 1
4955 ret = 1
4955 finally:
4956 finally:
4956 ui.setconfig('ui', 'forcemerge', '')
4957 ui.setconfig('ui', 'forcemerge', '')
4957 ms.commit()
4958 ms.commit()
4958
4959
4959 # replace filemerge's .orig file with our resolve file
4960 # replace filemerge's .orig file with our resolve file
4960 util.rename(a + ".resolve", a + ".orig")
4961 util.rename(a + ".resolve", a + ".orig")
4961
4962
4962 ms.commit()
4963 ms.commit()
4963 return ret
4964 return ret
4964
4965
4965 @command('revert',
4966 @command('revert',
4966 [('a', 'all', None, _('revert all changes when no arguments given')),
4967 [('a', 'all', None, _('revert all changes when no arguments given')),
4967 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4968 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4968 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4969 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4969 ('C', 'no-backup', None, _('do not save backup copies of files')),
4970 ('C', 'no-backup', None, _('do not save backup copies of files')),
4970 ] + walkopts + dryrunopts,
4971 ] + walkopts + dryrunopts,
4971 _('[OPTION]... [-r REV] [NAME]...'))
4972 _('[OPTION]... [-r REV] [NAME]...'))
4972 def revert(ui, repo, *pats, **opts):
4973 def revert(ui, repo, *pats, **opts):
4973 """restore files to their checkout state
4974 """restore files to their checkout state
4974
4975
4975 .. note::
4976 .. note::
4976 To check out earlier revisions, you should use :hg:`update REV`.
4977 To check out earlier revisions, you should use :hg:`update REV`.
4977 To cancel an uncommitted merge (and lose your changes),
4978 To cancel an uncommitted merge (and lose your changes),
4978 use :hg:`update --clean .`.
4979 use :hg:`update --clean .`.
4979
4980
4980 With no revision specified, revert the specified files or directories
4981 With no revision specified, revert the specified files or directories
4981 to the contents they had in the parent of the working directory.
4982 to the contents they had in the parent of the working directory.
4982 This restores the contents of files to an unmodified
4983 This restores the contents of files to an unmodified
4983 state and unschedules adds, removes, copies, and renames. If the
4984 state and unschedules adds, removes, copies, and renames. If the
4984 working directory has two parents, you must explicitly specify a
4985 working directory has two parents, you must explicitly specify a
4985 revision.
4986 revision.
4986
4987
4987 Using the -r/--rev or -d/--date options, revert the given files or
4988 Using the -r/--rev or -d/--date options, revert the given files or
4988 directories to their states as of a specific revision. Because
4989 directories to their states as of a specific revision. Because
4989 revert does not change the working directory parents, this will
4990 revert does not change the working directory parents, this will
4990 cause these files to appear modified. This can be helpful to "back
4991 cause these files to appear modified. This can be helpful to "back
4991 out" some or all of an earlier change. See :hg:`backout` for a
4992 out" some or all of an earlier change. See :hg:`backout` for a
4992 related method.
4993 related method.
4993
4994
4994 Modified files are saved with a .orig suffix before reverting.
4995 Modified files are saved with a .orig suffix before reverting.
4995 To disable these backups, use --no-backup.
4996 To disable these backups, use --no-backup.
4996
4997
4997 See :hg:`help dates` for a list of formats valid for -d/--date.
4998 See :hg:`help dates` for a list of formats valid for -d/--date.
4998
4999
4999 Returns 0 on success.
5000 Returns 0 on success.
5000 """
5001 """
5001
5002
5002 if opts.get("date"):
5003 if opts.get("date"):
5003 if opts.get("rev"):
5004 if opts.get("rev"):
5004 raise util.Abort(_("you can't specify a revision and a date"))
5005 raise util.Abort(_("you can't specify a revision and a date"))
5005 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5006 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5006
5007
5007 parent, p2 = repo.dirstate.parents()
5008 parent, p2 = repo.dirstate.parents()
5008 if not opts.get('rev') and p2 != nullid:
5009 if not opts.get('rev') and p2 != nullid:
5009 # revert after merge is a trap for new users (issue2915)
5010 # revert after merge is a trap for new users (issue2915)
5010 raise util.Abort(_('uncommitted merge with no revision specified'),
5011 raise util.Abort(_('uncommitted merge with no revision specified'),
5011 hint=_('use "hg update" or see "hg help revert"'))
5012 hint=_('use "hg update" or see "hg help revert"'))
5012
5013
5013 ctx = scmutil.revsingle(repo, opts.get('rev'))
5014 ctx = scmutil.revsingle(repo, opts.get('rev'))
5014
5015
5015 if not pats and not opts.get('all'):
5016 if not pats and not opts.get('all'):
5016 msg = _("no files or directories specified")
5017 msg = _("no files or directories specified")
5017 if p2 != nullid:
5018 if p2 != nullid:
5018 hint = _("uncommitted merge, use --all to discard all changes,"
5019 hint = _("uncommitted merge, use --all to discard all changes,"
5019 " or 'hg update -C .' to abort the merge")
5020 " or 'hg update -C .' to abort the merge")
5020 raise util.Abort(msg, hint=hint)
5021 raise util.Abort(msg, hint=hint)
5021 dirty = util.any(repo.status())
5022 dirty = util.any(repo.status())
5022 node = ctx.node()
5023 node = ctx.node()
5023 if node != parent:
5024 if node != parent:
5024 if dirty:
5025 if dirty:
5025 hint = _("uncommitted changes, use --all to discard all"
5026 hint = _("uncommitted changes, use --all to discard all"
5026 " changes, or 'hg update %s' to update") % ctx.rev()
5027 " changes, or 'hg update %s' to update") % ctx.rev()
5027 else:
5028 else:
5028 hint = _("use --all to revert all files,"
5029 hint = _("use --all to revert all files,"
5029 " or 'hg update %s' to update") % ctx.rev()
5030 " or 'hg update %s' to update") % ctx.rev()
5030 elif dirty:
5031 elif dirty:
5031 hint = _("uncommitted changes, use --all to discard all changes")
5032 hint = _("uncommitted changes, use --all to discard all changes")
5032 else:
5033 else:
5033 hint = _("use --all to revert all files")
5034 hint = _("use --all to revert all files")
5034 raise util.Abort(msg, hint=hint)
5035 raise util.Abort(msg, hint=hint)
5035
5036
5036 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5037 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5037
5038
5038 @command('rollback', dryrunopts +
5039 @command('rollback', dryrunopts +
5039 [('f', 'force', False, _('ignore safety measures'))])
5040 [('f', 'force', False, _('ignore safety measures'))])
5040 def rollback(ui, repo, **opts):
5041 def rollback(ui, repo, **opts):
5041 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5042 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5042
5043
5043 Please use :hg:`commit --amend` instead of rollback to correct
5044 Please use :hg:`commit --amend` instead of rollback to correct
5044 mistakes in the last commit.
5045 mistakes in the last commit.
5045
5046
5046 This command should be used with care. There is only one level of
5047 This command should be used with care. There is only one level of
5047 rollback, and there is no way to undo a rollback. It will also
5048 rollback, and there is no way to undo a rollback. It will also
5048 restore the dirstate at the time of the last transaction, losing
5049 restore the dirstate at the time of the last transaction, losing
5049 any dirstate changes since that time. This command does not alter
5050 any dirstate changes since that time. This command does not alter
5050 the working directory.
5051 the working directory.
5051
5052
5052 Transactions are used to encapsulate the effects of all commands
5053 Transactions are used to encapsulate the effects of all commands
5053 that create new changesets or propagate existing changesets into a
5054 that create new changesets or propagate existing changesets into a
5054 repository.
5055 repository.
5055
5056
5056 .. container:: verbose
5057 .. container:: verbose
5057
5058
5058 For example, the following commands are transactional, and their
5059 For example, the following commands are transactional, and their
5059 effects can be rolled back:
5060 effects can be rolled back:
5060
5061
5061 - commit
5062 - commit
5062 - import
5063 - import
5063 - pull
5064 - pull
5064 - push (with this repository as the destination)
5065 - push (with this repository as the destination)
5065 - unbundle
5066 - unbundle
5066
5067
5067 To avoid permanent data loss, rollback will refuse to rollback a
5068 To avoid permanent data loss, rollback will refuse to rollback a
5068 commit transaction if it isn't checked out. Use --force to
5069 commit transaction if it isn't checked out. Use --force to
5069 override this protection.
5070 override this protection.
5070
5071
5071 This command is not intended for use on public repositories. Once
5072 This command is not intended for use on public repositories. Once
5072 changes are visible for pull by other users, rolling a transaction
5073 changes are visible for pull by other users, rolling a transaction
5073 back locally is ineffective (someone else may already have pulled
5074 back locally is ineffective (someone else may already have pulled
5074 the changes). Furthermore, a race is possible with readers of the
5075 the changes). Furthermore, a race is possible with readers of the
5075 repository; for example an in-progress pull from the repository
5076 repository; for example an in-progress pull from the repository
5076 may fail if a rollback is performed.
5077 may fail if a rollback is performed.
5077
5078
5078 Returns 0 on success, 1 if no rollback data is available.
5079 Returns 0 on success, 1 if no rollback data is available.
5079 """
5080 """
5080 return repo.rollback(dryrun=opts.get('dry_run'),
5081 return repo.rollback(dryrun=opts.get('dry_run'),
5081 force=opts.get('force'))
5082 force=opts.get('force'))
5082
5083
5083 @command('root', [])
5084 @command('root', [])
5084 def root(ui, repo):
5085 def root(ui, repo):
5085 """print the root (top) of the current working directory
5086 """print the root (top) of the current working directory
5086
5087
5087 Print the root directory of the current repository.
5088 Print the root directory of the current repository.
5088
5089
5089 Returns 0 on success.
5090 Returns 0 on success.
5090 """
5091 """
5091 ui.write(repo.root + "\n")
5092 ui.write(repo.root + "\n")
5092
5093
5093 @command('^serve',
5094 @command('^serve',
5094 [('A', 'accesslog', '', _('name of access log file to write to'),
5095 [('A', 'accesslog', '', _('name of access log file to write to'),
5095 _('FILE')),
5096 _('FILE')),
5096 ('d', 'daemon', None, _('run server in background')),
5097 ('d', 'daemon', None, _('run server in background')),
5097 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5098 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5098 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5099 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5099 # use string type, then we can check if something was passed
5100 # use string type, then we can check if something was passed
5100 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5101 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5101 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5102 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5102 _('ADDR')),
5103 _('ADDR')),
5103 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5104 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5104 _('PREFIX')),
5105 _('PREFIX')),
5105 ('n', 'name', '',
5106 ('n', 'name', '',
5106 _('name to show in web pages (default: working directory)'), _('NAME')),
5107 _('name to show in web pages (default: working directory)'), _('NAME')),
5107 ('', 'web-conf', '',
5108 ('', 'web-conf', '',
5108 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5109 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5109 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5110 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5110 _('FILE')),
5111 _('FILE')),
5111 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5112 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5112 ('', 'stdio', None, _('for remote clients')),
5113 ('', 'stdio', None, _('for remote clients')),
5113 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5114 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5114 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5115 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5115 ('', 'style', '', _('template style to use'), _('STYLE')),
5116 ('', 'style', '', _('template style to use'), _('STYLE')),
5116 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5117 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5117 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5118 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5118 _('[OPTION]...'))
5119 _('[OPTION]...'))
5119 def serve(ui, repo, **opts):
5120 def serve(ui, repo, **opts):
5120 """start stand-alone webserver
5121 """start stand-alone webserver
5121
5122
5122 Start a local HTTP repository browser and pull server. You can use
5123 Start a local HTTP repository browser and pull server. You can use
5123 this for ad-hoc sharing and browsing of repositories. It is
5124 this for ad-hoc sharing and browsing of repositories. It is
5124 recommended to use a real web server to serve a repository for
5125 recommended to use a real web server to serve a repository for
5125 longer periods of time.
5126 longer periods of time.
5126
5127
5127 Please note that the server does not implement access control.
5128 Please note that the server does not implement access control.
5128 This means that, by default, anybody can read from the server and
5129 This means that, by default, anybody can read from the server and
5129 nobody can write to it by default. Set the ``web.allow_push``
5130 nobody can write to it by default. Set the ``web.allow_push``
5130 option to ``*`` to allow everybody to push to the server. You
5131 option to ``*`` to allow everybody to push to the server. You
5131 should use a real web server if you need to authenticate users.
5132 should use a real web server if you need to authenticate users.
5132
5133
5133 By default, the server logs accesses to stdout and errors to
5134 By default, the server logs accesses to stdout and errors to
5134 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5135 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5135 files.
5136 files.
5136
5137
5137 To have the server choose a free port number to listen on, specify
5138 To have the server choose a free port number to listen on, specify
5138 a port number of 0; in this case, the server will print the port
5139 a port number of 0; in this case, the server will print the port
5139 number it uses.
5140 number it uses.
5140
5141
5141 Returns 0 on success.
5142 Returns 0 on success.
5142 """
5143 """
5143
5144
5144 if opts["stdio"] and opts["cmdserver"]:
5145 if opts["stdio"] and opts["cmdserver"]:
5145 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5146 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5146
5147
5147 def checkrepo():
5148 def checkrepo():
5148 if repo is None:
5149 if repo is None:
5149 raise error.RepoError(_("there is no Mercurial repository here"
5150 raise error.RepoError(_("there is no Mercurial repository here"
5150 " (.hg not found)"))
5151 " (.hg not found)"))
5151
5152
5152 if opts["stdio"]:
5153 if opts["stdio"]:
5153 checkrepo()
5154 checkrepo()
5154 s = sshserver.sshserver(ui, repo)
5155 s = sshserver.sshserver(ui, repo)
5155 s.serve_forever()
5156 s.serve_forever()
5156
5157
5157 if opts["cmdserver"]:
5158 if opts["cmdserver"]:
5158 checkrepo()
5159 checkrepo()
5159 s = commandserver.server(ui, repo, opts["cmdserver"])
5160 s = commandserver.server(ui, repo, opts["cmdserver"])
5160 return s.serve()
5161 return s.serve()
5161
5162
5162 # this way we can check if something was given in the command-line
5163 # this way we can check if something was given in the command-line
5163 if opts.get('port'):
5164 if opts.get('port'):
5164 opts['port'] = util.getport(opts.get('port'))
5165 opts['port'] = util.getport(opts.get('port'))
5165
5166
5166 baseui = repo and repo.baseui or ui
5167 baseui = repo and repo.baseui or ui
5167 optlist = ("name templates style address port prefix ipv6"
5168 optlist = ("name templates style address port prefix ipv6"
5168 " accesslog errorlog certificate encoding")
5169 " accesslog errorlog certificate encoding")
5169 for o in optlist.split():
5170 for o in optlist.split():
5170 val = opts.get(o, '')
5171 val = opts.get(o, '')
5171 if val in (None, ''): # should check against default options instead
5172 if val in (None, ''): # should check against default options instead
5172 continue
5173 continue
5173 baseui.setconfig("web", o, val)
5174 baseui.setconfig("web", o, val)
5174 if repo and repo.ui != baseui:
5175 if repo and repo.ui != baseui:
5175 repo.ui.setconfig("web", o, val)
5176 repo.ui.setconfig("web", o, val)
5176
5177
5177 o = opts.get('web_conf') or opts.get('webdir_conf')
5178 o = opts.get('web_conf') or opts.get('webdir_conf')
5178 if not o:
5179 if not o:
5179 if not repo:
5180 if not repo:
5180 raise error.RepoError(_("there is no Mercurial repository"
5181 raise error.RepoError(_("there is no Mercurial repository"
5181 " here (.hg not found)"))
5182 " here (.hg not found)"))
5182 o = repo
5183 o = repo
5183
5184
5184 app = hgweb.hgweb(o, baseui=baseui)
5185 app = hgweb.hgweb(o, baseui=baseui)
5185
5186
5186 class service(object):
5187 class service(object):
5187 def init(self):
5188 def init(self):
5188 util.setsignalhandler()
5189 util.setsignalhandler()
5189 self.httpd = hgweb_server.create_server(ui, app)
5190 self.httpd = hgweb_server.create_server(ui, app)
5190
5191
5191 if opts['port'] and not ui.verbose:
5192 if opts['port'] and not ui.verbose:
5192 return
5193 return
5193
5194
5194 if self.httpd.prefix:
5195 if self.httpd.prefix:
5195 prefix = self.httpd.prefix.strip('/') + '/'
5196 prefix = self.httpd.prefix.strip('/') + '/'
5196 else:
5197 else:
5197 prefix = ''
5198 prefix = ''
5198
5199
5199 port = ':%d' % self.httpd.port
5200 port = ':%d' % self.httpd.port
5200 if port == ':80':
5201 if port == ':80':
5201 port = ''
5202 port = ''
5202
5203
5203 bindaddr = self.httpd.addr
5204 bindaddr = self.httpd.addr
5204 if bindaddr == '0.0.0.0':
5205 if bindaddr == '0.0.0.0':
5205 bindaddr = '*'
5206 bindaddr = '*'
5206 elif ':' in bindaddr: # IPv6
5207 elif ':' in bindaddr: # IPv6
5207 bindaddr = '[%s]' % bindaddr
5208 bindaddr = '[%s]' % bindaddr
5208
5209
5209 fqaddr = self.httpd.fqaddr
5210 fqaddr = self.httpd.fqaddr
5210 if ':' in fqaddr:
5211 if ':' in fqaddr:
5211 fqaddr = '[%s]' % fqaddr
5212 fqaddr = '[%s]' % fqaddr
5212 if opts['port']:
5213 if opts['port']:
5213 write = ui.status
5214 write = ui.status
5214 else:
5215 else:
5215 write = ui.write
5216 write = ui.write
5216 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5217 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5217 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5218 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5218
5219
5219 def run(self):
5220 def run(self):
5220 self.httpd.serve_forever()
5221 self.httpd.serve_forever()
5221
5222
5222 service = service()
5223 service = service()
5223
5224
5224 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5225 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5225
5226
5226 @command('showconfig|debugconfig',
5227 @command('showconfig|debugconfig',
5227 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5228 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5228 _('[-u] [NAME]...'))
5229 _('[-u] [NAME]...'))
5229 def showconfig(ui, repo, *values, **opts):
5230 def showconfig(ui, repo, *values, **opts):
5230 """show combined config settings from all hgrc files
5231 """show combined config settings from all hgrc files
5231
5232
5232 With no arguments, print names and values of all config items.
5233 With no arguments, print names and values of all config items.
5233
5234
5234 With one argument of the form section.name, print just the value
5235 With one argument of the form section.name, print just the value
5235 of that config item.
5236 of that config item.
5236
5237
5237 With multiple arguments, print names and values of all config
5238 With multiple arguments, print names and values of all config
5238 items with matching section names.
5239 items with matching section names.
5239
5240
5240 With --debug, the source (filename and line number) is printed
5241 With --debug, the source (filename and line number) is printed
5241 for each config item.
5242 for each config item.
5242
5243
5243 Returns 0 on success.
5244 Returns 0 on success.
5244 """
5245 """
5245
5246
5246 for f in scmutil.rcpath():
5247 for f in scmutil.rcpath():
5247 ui.debug('read config from: %s\n' % f)
5248 ui.debug('read config from: %s\n' % f)
5248 untrusted = bool(opts.get('untrusted'))
5249 untrusted = bool(opts.get('untrusted'))
5249 if values:
5250 if values:
5250 sections = [v for v in values if '.' not in v]
5251 sections = [v for v in values if '.' not in v]
5251 items = [v for v in values if '.' in v]
5252 items = [v for v in values if '.' in v]
5252 if len(items) > 1 or items and sections:
5253 if len(items) > 1 or items and sections:
5253 raise util.Abort(_('only one config item permitted'))
5254 raise util.Abort(_('only one config item permitted'))
5254 for section, name, value in ui.walkconfig(untrusted=untrusted):
5255 for section, name, value in ui.walkconfig(untrusted=untrusted):
5255 value = str(value).replace('\n', '\\n')
5256 value = str(value).replace('\n', '\\n')
5256 sectname = section + '.' + name
5257 sectname = section + '.' + name
5257 if values:
5258 if values:
5258 for v in values:
5259 for v in values:
5259 if v == section:
5260 if v == section:
5260 ui.debug('%s: ' %
5261 ui.debug('%s: ' %
5261 ui.configsource(section, name, untrusted))
5262 ui.configsource(section, name, untrusted))
5262 ui.write('%s=%s\n' % (sectname, value))
5263 ui.write('%s=%s\n' % (sectname, value))
5263 elif v == sectname:
5264 elif v == sectname:
5264 ui.debug('%s: ' %
5265 ui.debug('%s: ' %
5265 ui.configsource(section, name, untrusted))
5266 ui.configsource(section, name, untrusted))
5266 ui.write(value, '\n')
5267 ui.write(value, '\n')
5267 else:
5268 else:
5268 ui.debug('%s: ' %
5269 ui.debug('%s: ' %
5269 ui.configsource(section, name, untrusted))
5270 ui.configsource(section, name, untrusted))
5270 ui.write('%s=%s\n' % (sectname, value))
5271 ui.write('%s=%s\n' % (sectname, value))
5271
5272
5272 @command('^status|st',
5273 @command('^status|st',
5273 [('A', 'all', None, _('show status of all files')),
5274 [('A', 'all', None, _('show status of all files')),
5274 ('m', 'modified', None, _('show only modified files')),
5275 ('m', 'modified', None, _('show only modified files')),
5275 ('a', 'added', None, _('show only added files')),
5276 ('a', 'added', None, _('show only added files')),
5276 ('r', 'removed', None, _('show only removed files')),
5277 ('r', 'removed', None, _('show only removed files')),
5277 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5278 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5278 ('c', 'clean', None, _('show only files without changes')),
5279 ('c', 'clean', None, _('show only files without changes')),
5279 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5280 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5280 ('i', 'ignored', None, _('show only ignored files')),
5281 ('i', 'ignored', None, _('show only ignored files')),
5281 ('n', 'no-status', None, _('hide status prefix')),
5282 ('n', 'no-status', None, _('hide status prefix')),
5282 ('C', 'copies', None, _('show source of copied files')),
5283 ('C', 'copies', None, _('show source of copied files')),
5283 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5284 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5284 ('', 'rev', [], _('show difference from revision'), _('REV')),
5285 ('', 'rev', [], _('show difference from revision'), _('REV')),
5285 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5286 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5286 ] + walkopts + subrepoopts,
5287 ] + walkopts + subrepoopts,
5287 _('[OPTION]... [FILE]...'))
5288 _('[OPTION]... [FILE]...'))
5288 def status(ui, repo, *pats, **opts):
5289 def status(ui, repo, *pats, **opts):
5289 """show changed files in the working directory
5290 """show changed files in the working directory
5290
5291
5291 Show status of files in the repository. If names are given, only
5292 Show status of files in the repository. If names are given, only
5292 files that match are shown. Files that are clean or ignored or
5293 files that match are shown. Files that are clean or ignored or
5293 the source of a copy/move operation, are not listed unless
5294 the source of a copy/move operation, are not listed unless
5294 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5295 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5295 Unless options described with "show only ..." are given, the
5296 Unless options described with "show only ..." are given, the
5296 options -mardu are used.
5297 options -mardu are used.
5297
5298
5298 Option -q/--quiet hides untracked (unknown and ignored) files
5299 Option -q/--quiet hides untracked (unknown and ignored) files
5299 unless explicitly requested with -u/--unknown or -i/--ignored.
5300 unless explicitly requested with -u/--unknown or -i/--ignored.
5300
5301
5301 .. note::
5302 .. note::
5302 status may appear to disagree with diff if permissions have
5303 status may appear to disagree with diff if permissions have
5303 changed or a merge has occurred. The standard diff format does
5304 changed or a merge has occurred. The standard diff format does
5304 not report permission changes and diff only reports changes
5305 not report permission changes and diff only reports changes
5305 relative to one merge parent.
5306 relative to one merge parent.
5306
5307
5307 If one revision is given, it is used as the base revision.
5308 If one revision is given, it is used as the base revision.
5308 If two revisions are given, the differences between them are
5309 If two revisions are given, the differences between them are
5309 shown. The --change option can also be used as a shortcut to list
5310 shown. The --change option can also be used as a shortcut to list
5310 the changed files of a revision from its first parent.
5311 the changed files of a revision from its first parent.
5311
5312
5312 The codes used to show the status of files are::
5313 The codes used to show the status of files are::
5313
5314
5314 M = modified
5315 M = modified
5315 A = added
5316 A = added
5316 R = removed
5317 R = removed
5317 C = clean
5318 C = clean
5318 ! = missing (deleted by non-hg command, but still tracked)
5319 ! = missing (deleted by non-hg command, but still tracked)
5319 ? = not tracked
5320 ? = not tracked
5320 I = ignored
5321 I = ignored
5321 = origin of the previous file listed as A (added)
5322 = origin of the previous file listed as A (added)
5322
5323
5323 .. container:: verbose
5324 .. container:: verbose
5324
5325
5325 Examples:
5326 Examples:
5326
5327
5327 - show changes in the working directory relative to a
5328 - show changes in the working directory relative to a
5328 changeset::
5329 changeset::
5329
5330
5330 hg status --rev 9353
5331 hg status --rev 9353
5331
5332
5332 - show all changes including copies in an existing changeset::
5333 - show all changes including copies in an existing changeset::
5333
5334
5334 hg status --copies --change 9353
5335 hg status --copies --change 9353
5335
5336
5336 - get a NUL separated list of added files, suitable for xargs::
5337 - get a NUL separated list of added files, suitable for xargs::
5337
5338
5338 hg status -an0
5339 hg status -an0
5339
5340
5340 Returns 0 on success.
5341 Returns 0 on success.
5341 """
5342 """
5342
5343
5343 revs = opts.get('rev')
5344 revs = opts.get('rev')
5344 change = opts.get('change')
5345 change = opts.get('change')
5345
5346
5346 if revs and change:
5347 if revs and change:
5347 msg = _('cannot specify --rev and --change at the same time')
5348 msg = _('cannot specify --rev and --change at the same time')
5348 raise util.Abort(msg)
5349 raise util.Abort(msg)
5349 elif change:
5350 elif change:
5350 node2 = scmutil.revsingle(repo, change, None).node()
5351 node2 = scmutil.revsingle(repo, change, None).node()
5351 node1 = repo[node2].p1().node()
5352 node1 = repo[node2].p1().node()
5352 else:
5353 else:
5353 node1, node2 = scmutil.revpair(repo, revs)
5354 node1, node2 = scmutil.revpair(repo, revs)
5354
5355
5355 cwd = (pats and repo.getcwd()) or ''
5356 cwd = (pats and repo.getcwd()) or ''
5356 end = opts.get('print0') and '\0' or '\n'
5357 end = opts.get('print0') and '\0' or '\n'
5357 copy = {}
5358 copy = {}
5358 states = 'modified added removed deleted unknown ignored clean'.split()
5359 states = 'modified added removed deleted unknown ignored clean'.split()
5359 show = [k for k in states if opts.get(k)]
5360 show = [k for k in states if opts.get(k)]
5360 if opts.get('all'):
5361 if opts.get('all'):
5361 show += ui.quiet and (states[:4] + ['clean']) or states
5362 show += ui.quiet and (states[:4] + ['clean']) or states
5362 if not show:
5363 if not show:
5363 show = ui.quiet and states[:4] or states[:5]
5364 show = ui.quiet and states[:4] or states[:5]
5364
5365
5365 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5366 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5366 'ignored' in show, 'clean' in show, 'unknown' in show,
5367 'ignored' in show, 'clean' in show, 'unknown' in show,
5367 opts.get('subrepos'))
5368 opts.get('subrepos'))
5368 changestates = zip(states, 'MAR!?IC', stat)
5369 changestates = zip(states, 'MAR!?IC', stat)
5369
5370
5370 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5371 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5371 copy = copies.pathcopies(repo[node1], repo[node2])
5372 copy = copies.pathcopies(repo[node1], repo[node2])
5372
5373
5373 fm = ui.formatter('status', opts)
5374 fm = ui.formatter('status', opts)
5374 fmt = '%s' + end
5375 fmt = '%s' + end
5375 showchar = not opts.get('no_status')
5376 showchar = not opts.get('no_status')
5376
5377
5377 for state, char, files in changestates:
5378 for state, char, files in changestates:
5378 if state in show:
5379 if state in show:
5379 label = 'status.' + state
5380 label = 'status.' + state
5380 for f in files:
5381 for f in files:
5381 fm.startitem()
5382 fm.startitem()
5382 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5383 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5383 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5384 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5384 if f in copy:
5385 if f in copy:
5385 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5386 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5386 label='status.copied')
5387 label='status.copied')
5387 fm.end()
5388 fm.end()
5388
5389
5389 @command('^summary|sum',
5390 @command('^summary|sum',
5390 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5391 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5391 def summary(ui, repo, **opts):
5392 def summary(ui, repo, **opts):
5392 """summarize working directory state
5393 """summarize working directory state
5393
5394
5394 This generates a brief summary of the working directory state,
5395 This generates a brief summary of the working directory state,
5395 including parents, branch, commit status, and available updates.
5396 including parents, branch, commit status, and available updates.
5396
5397
5397 With the --remote option, this will check the default paths for
5398 With the --remote option, this will check the default paths for
5398 incoming and outgoing changes. This can be time-consuming.
5399 incoming and outgoing changes. This can be time-consuming.
5399
5400
5400 Returns 0 on success.
5401 Returns 0 on success.
5401 """
5402 """
5402
5403
5403 ctx = repo[None]
5404 ctx = repo[None]
5404 parents = ctx.parents()
5405 parents = ctx.parents()
5405 pnode = parents[0].node()
5406 pnode = parents[0].node()
5406 marks = []
5407 marks = []
5407
5408
5408 for p in parents:
5409 for p in parents:
5409 # label with log.changeset (instead of log.parent) since this
5410 # label with log.changeset (instead of log.parent) since this
5410 # shows a working directory parent *changeset*:
5411 # shows a working directory parent *changeset*:
5411 # i18n: column positioning for "hg summary"
5412 # i18n: column positioning for "hg summary"
5412 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5413 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5413 label='log.changeset changeset.%s' % p.phasestr())
5414 label='log.changeset changeset.%s' % p.phasestr())
5414 ui.write(' '.join(p.tags()), label='log.tag')
5415 ui.write(' '.join(p.tags()), label='log.tag')
5415 if p.bookmarks():
5416 if p.bookmarks():
5416 marks.extend(p.bookmarks())
5417 marks.extend(p.bookmarks())
5417 if p.rev() == -1:
5418 if p.rev() == -1:
5418 if not len(repo):
5419 if not len(repo):
5419 ui.write(_(' (empty repository)'))
5420 ui.write(_(' (empty repository)'))
5420 else:
5421 else:
5421 ui.write(_(' (no revision checked out)'))
5422 ui.write(_(' (no revision checked out)'))
5422 ui.write('\n')
5423 ui.write('\n')
5423 if p.description():
5424 if p.description():
5424 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5425 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5425 label='log.summary')
5426 label='log.summary')
5426
5427
5427 branch = ctx.branch()
5428 branch = ctx.branch()
5428 bheads = repo.branchheads(branch)
5429 bheads = repo.branchheads(branch)
5429 # i18n: column positioning for "hg summary"
5430 # i18n: column positioning for "hg summary"
5430 m = _('branch: %s\n') % branch
5431 m = _('branch: %s\n') % branch
5431 if branch != 'default':
5432 if branch != 'default':
5432 ui.write(m, label='log.branch')
5433 ui.write(m, label='log.branch')
5433 else:
5434 else:
5434 ui.status(m, label='log.branch')
5435 ui.status(m, label='log.branch')
5435
5436
5436 if marks:
5437 if marks:
5437 current = repo._bookmarkcurrent
5438 current = repo._bookmarkcurrent
5438 # i18n: column positioning for "hg summary"
5439 # i18n: column positioning for "hg summary"
5439 ui.write(_('bookmarks:'), label='log.bookmark')
5440 ui.write(_('bookmarks:'), label='log.bookmark')
5440 if current is not None:
5441 if current is not None:
5441 if current in marks:
5442 if current in marks:
5442 ui.write(' *' + current, label='bookmarks.current')
5443 ui.write(' *' + current, label='bookmarks.current')
5443 marks.remove(current)
5444 marks.remove(current)
5444 else:
5445 else:
5445 ui.write(' [%s]' % current, label='bookmarks.current')
5446 ui.write(' [%s]' % current, label='bookmarks.current')
5446 for m in marks:
5447 for m in marks:
5447 ui.write(' ' + m, label='log.bookmark')
5448 ui.write(' ' + m, label='log.bookmark')
5448 ui.write('\n', label='log.bookmark')
5449 ui.write('\n', label='log.bookmark')
5449
5450
5450 st = list(repo.status(unknown=True))[:6]
5451 st = list(repo.status(unknown=True))[:6]
5451
5452
5452 c = repo.dirstate.copies()
5453 c = repo.dirstate.copies()
5453 copied, renamed = [], []
5454 copied, renamed = [], []
5454 for d, s in c.iteritems():
5455 for d, s in c.iteritems():
5455 if s in st[2]:
5456 if s in st[2]:
5456 st[2].remove(s)
5457 st[2].remove(s)
5457 renamed.append(d)
5458 renamed.append(d)
5458 else:
5459 else:
5459 copied.append(d)
5460 copied.append(d)
5460 if d in st[1]:
5461 if d in st[1]:
5461 st[1].remove(d)
5462 st[1].remove(d)
5462 st.insert(3, renamed)
5463 st.insert(3, renamed)
5463 st.insert(4, copied)
5464 st.insert(4, copied)
5464
5465
5465 ms = mergemod.mergestate(repo)
5466 ms = mergemod.mergestate(repo)
5466 st.append([f for f in ms if ms[f] == 'u'])
5467 st.append([f for f in ms if ms[f] == 'u'])
5467
5468
5468 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5469 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5469 st.append(subs)
5470 st.append(subs)
5470
5471
5471 labels = [ui.label(_('%d modified'), 'status.modified'),
5472 labels = [ui.label(_('%d modified'), 'status.modified'),
5472 ui.label(_('%d added'), 'status.added'),
5473 ui.label(_('%d added'), 'status.added'),
5473 ui.label(_('%d removed'), 'status.removed'),
5474 ui.label(_('%d removed'), 'status.removed'),
5474 ui.label(_('%d renamed'), 'status.copied'),
5475 ui.label(_('%d renamed'), 'status.copied'),
5475 ui.label(_('%d copied'), 'status.copied'),
5476 ui.label(_('%d copied'), 'status.copied'),
5476 ui.label(_('%d deleted'), 'status.deleted'),
5477 ui.label(_('%d deleted'), 'status.deleted'),
5477 ui.label(_('%d unknown'), 'status.unknown'),
5478 ui.label(_('%d unknown'), 'status.unknown'),
5478 ui.label(_('%d ignored'), 'status.ignored'),
5479 ui.label(_('%d ignored'), 'status.ignored'),
5479 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5480 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5480 ui.label(_('%d subrepos'), 'status.modified')]
5481 ui.label(_('%d subrepos'), 'status.modified')]
5481 t = []
5482 t = []
5482 for s, l in zip(st, labels):
5483 for s, l in zip(st, labels):
5483 if s:
5484 if s:
5484 t.append(l % len(s))
5485 t.append(l % len(s))
5485
5486
5486 t = ', '.join(t)
5487 t = ', '.join(t)
5487 cleanworkdir = False
5488 cleanworkdir = False
5488
5489
5489 if repo.vfs.exists('updatestate'):
5490 if repo.vfs.exists('updatestate'):
5490 t += _(' (interrupted update)')
5491 t += _(' (interrupted update)')
5491 elif len(parents) > 1:
5492 elif len(parents) > 1:
5492 t += _(' (merge)')
5493 t += _(' (merge)')
5493 elif branch != parents[0].branch():
5494 elif branch != parents[0].branch():
5494 t += _(' (new branch)')
5495 t += _(' (new branch)')
5495 elif (parents[0].closesbranch() and
5496 elif (parents[0].closesbranch() and
5496 pnode in repo.branchheads(branch, closed=True)):
5497 pnode in repo.branchheads(branch, closed=True)):
5497 t += _(' (head closed)')
5498 t += _(' (head closed)')
5498 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5499 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5499 t += _(' (clean)')
5500 t += _(' (clean)')
5500 cleanworkdir = True
5501 cleanworkdir = True
5501 elif pnode not in bheads:
5502 elif pnode not in bheads:
5502 t += _(' (new branch head)')
5503 t += _(' (new branch head)')
5503
5504
5504 if cleanworkdir:
5505 if cleanworkdir:
5505 # i18n: column positioning for "hg summary"
5506 # i18n: column positioning for "hg summary"
5506 ui.status(_('commit: %s\n') % t.strip())
5507 ui.status(_('commit: %s\n') % t.strip())
5507 else:
5508 else:
5508 # i18n: column positioning for "hg summary"
5509 # i18n: column positioning for "hg summary"
5509 ui.write(_('commit: %s\n') % t.strip())
5510 ui.write(_('commit: %s\n') % t.strip())
5510
5511
5511 # all ancestors of branch heads - all ancestors of parent = new csets
5512 # all ancestors of branch heads - all ancestors of parent = new csets
5512 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5513 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5513 bheads))
5514 bheads))
5514
5515
5515 if new == 0:
5516 if new == 0:
5516 # i18n: column positioning for "hg summary"
5517 # i18n: column positioning for "hg summary"
5517 ui.status(_('update: (current)\n'))
5518 ui.status(_('update: (current)\n'))
5518 elif pnode not in bheads:
5519 elif pnode not in bheads:
5519 # i18n: column positioning for "hg summary"
5520 # i18n: column positioning for "hg summary"
5520 ui.write(_('update: %d new changesets (update)\n') % new)
5521 ui.write(_('update: %d new changesets (update)\n') % new)
5521 else:
5522 else:
5522 # i18n: column positioning for "hg summary"
5523 # i18n: column positioning for "hg summary"
5523 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5524 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5524 (new, len(bheads)))
5525 (new, len(bheads)))
5525
5526
5526 cmdutil.summaryhooks(ui, repo)
5527 cmdutil.summaryhooks(ui, repo)
5527
5528
5528 if opts.get('remote'):
5529 if opts.get('remote'):
5529 t = []
5530 t = []
5530 source, branches = hg.parseurl(ui.expandpath('default'))
5531 source, branches = hg.parseurl(ui.expandpath('default'))
5531 sbranch = branches[0]
5532 sbranch = branches[0]
5532 other = hg.peer(repo, {}, source)
5533 other = hg.peer(repo, {}, source)
5533 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5534 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5534 if revs:
5535 if revs:
5535 revs = [other.lookup(rev) for rev in revs]
5536 revs = [other.lookup(rev) for rev in revs]
5536 ui.debug('comparing with %s\n' % util.hidepassword(source))
5537 ui.debug('comparing with %s\n' % util.hidepassword(source))
5537 repo.ui.pushbuffer()
5538 repo.ui.pushbuffer()
5538 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5539 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5539 _common, incoming, _rheads = commoninc
5540 _common, incoming, _rheads = commoninc
5540 repo.ui.popbuffer()
5541 repo.ui.popbuffer()
5541 if incoming:
5542 if incoming:
5542 t.append(_('1 or more incoming'))
5543 t.append(_('1 or more incoming'))
5543
5544
5544 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5545 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5545 dbranch = branches[0]
5546 dbranch = branches[0]
5546 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5547 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5547 if source != dest:
5548 if source != dest:
5548 other = hg.peer(repo, {}, dest)
5549 other = hg.peer(repo, {}, dest)
5549 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5550 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5550 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5551 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5551 commoninc = None
5552 commoninc = None
5552 if revs:
5553 if revs:
5553 revs = [repo.lookup(rev) for rev in revs]
5554 revs = [repo.lookup(rev) for rev in revs]
5554 repo.ui.pushbuffer()
5555 repo.ui.pushbuffer()
5555 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5556 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5556 commoninc=commoninc)
5557 commoninc=commoninc)
5557 repo.ui.popbuffer()
5558 repo.ui.popbuffer()
5558 o = outgoing.missing
5559 o = outgoing.missing
5559 if o:
5560 if o:
5560 t.append(_('%d outgoing') % len(o))
5561 t.append(_('%d outgoing') % len(o))
5561 if 'bookmarks' in other.listkeys('namespaces'):
5562 if 'bookmarks' in other.listkeys('namespaces'):
5562 lmarks = repo.listkeys('bookmarks')
5563 lmarks = repo.listkeys('bookmarks')
5563 rmarks = other.listkeys('bookmarks')
5564 rmarks = other.listkeys('bookmarks')
5564 diff = set(rmarks) - set(lmarks)
5565 diff = set(rmarks) - set(lmarks)
5565 if len(diff) > 0:
5566 if len(diff) > 0:
5566 t.append(_('%d incoming bookmarks') % len(diff))
5567 t.append(_('%d incoming bookmarks') % len(diff))
5567 diff = set(lmarks) - set(rmarks)
5568 diff = set(lmarks) - set(rmarks)
5568 if len(diff) > 0:
5569 if len(diff) > 0:
5569 t.append(_('%d outgoing bookmarks') % len(diff))
5570 t.append(_('%d outgoing bookmarks') % len(diff))
5570
5571
5571 if t:
5572 if t:
5572 # i18n: column positioning for "hg summary"
5573 # i18n: column positioning for "hg summary"
5573 ui.write(_('remote: %s\n') % (', '.join(t)))
5574 ui.write(_('remote: %s\n') % (', '.join(t)))
5574 else:
5575 else:
5575 # i18n: column positioning for "hg summary"
5576 # i18n: column positioning for "hg summary"
5576 ui.status(_('remote: (synced)\n'))
5577 ui.status(_('remote: (synced)\n'))
5577
5578
5578 @command('tag',
5579 @command('tag',
5579 [('f', 'force', None, _('force tag')),
5580 [('f', 'force', None, _('force tag')),
5580 ('l', 'local', None, _('make the tag local')),
5581 ('l', 'local', None, _('make the tag local')),
5581 ('r', 'rev', '', _('revision to tag'), _('REV')),
5582 ('r', 'rev', '', _('revision to tag'), _('REV')),
5582 ('', 'remove', None, _('remove a tag')),
5583 ('', 'remove', None, _('remove a tag')),
5583 # -l/--local is already there, commitopts cannot be used
5584 # -l/--local is already there, commitopts cannot be used
5584 ('e', 'edit', None, _('edit commit message')),
5585 ('e', 'edit', None, _('edit commit message')),
5585 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5586 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5586 ] + commitopts2,
5587 ] + commitopts2,
5587 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5588 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5588 def tag(ui, repo, name1, *names, **opts):
5589 def tag(ui, repo, name1, *names, **opts):
5589 """add one or more tags for the current or given revision
5590 """add one or more tags for the current or given revision
5590
5591
5591 Name a particular revision using <name>.
5592 Name a particular revision using <name>.
5592
5593
5593 Tags are used to name particular revisions of the repository and are
5594 Tags are used to name particular revisions of the repository and are
5594 very useful to compare different revisions, to go back to significant
5595 very useful to compare different revisions, to go back to significant
5595 earlier versions or to mark branch points as releases, etc. Changing
5596 earlier versions or to mark branch points as releases, etc. Changing
5596 an existing tag is normally disallowed; use -f/--force to override.
5597 an existing tag is normally disallowed; use -f/--force to override.
5597
5598
5598 If no revision is given, the parent of the working directory is
5599 If no revision is given, the parent of the working directory is
5599 used.
5600 used.
5600
5601
5601 To facilitate version control, distribution, and merging of tags,
5602 To facilitate version control, distribution, and merging of tags,
5602 they are stored as a file named ".hgtags" which is managed similarly
5603 they are stored as a file named ".hgtags" which is managed similarly
5603 to other project files and can be hand-edited if necessary. This
5604 to other project files and can be hand-edited if necessary. This
5604 also means that tagging creates a new commit. The file
5605 also means that tagging creates a new commit. The file
5605 ".hg/localtags" is used for local tags (not shared among
5606 ".hg/localtags" is used for local tags (not shared among
5606 repositories).
5607 repositories).
5607
5608
5608 Tag commits are usually made at the head of a branch. If the parent
5609 Tag commits are usually made at the head of a branch. If the parent
5609 of the working directory is not a branch head, :hg:`tag` aborts; use
5610 of the working directory is not a branch head, :hg:`tag` aborts; use
5610 -f/--force to force the tag commit to be based on a non-head
5611 -f/--force to force the tag commit to be based on a non-head
5611 changeset.
5612 changeset.
5612
5613
5613 See :hg:`help dates` for a list of formats valid for -d/--date.
5614 See :hg:`help dates` for a list of formats valid for -d/--date.
5614
5615
5615 Since tag names have priority over branch names during revision
5616 Since tag names have priority over branch names during revision
5616 lookup, using an existing branch name as a tag name is discouraged.
5617 lookup, using an existing branch name as a tag name is discouraged.
5617
5618
5618 Returns 0 on success.
5619 Returns 0 on success.
5619 """
5620 """
5620 wlock = lock = None
5621 wlock = lock = None
5621 try:
5622 try:
5622 wlock = repo.wlock()
5623 wlock = repo.wlock()
5623 lock = repo.lock()
5624 lock = repo.lock()
5624 rev_ = "."
5625 rev_ = "."
5625 names = [t.strip() for t in (name1,) + names]
5626 names = [t.strip() for t in (name1,) + names]
5626 if len(names) != len(set(names)):
5627 if len(names) != len(set(names)):
5627 raise util.Abort(_('tag names must be unique'))
5628 raise util.Abort(_('tag names must be unique'))
5628 for n in names:
5629 for n in names:
5629 scmutil.checknewlabel(repo, n, 'tag')
5630 scmutil.checknewlabel(repo, n, 'tag')
5630 if not n:
5631 if not n:
5631 raise util.Abort(_('tag names cannot consist entirely of '
5632 raise util.Abort(_('tag names cannot consist entirely of '
5632 'whitespace'))
5633 'whitespace'))
5633 if opts.get('rev') and opts.get('remove'):
5634 if opts.get('rev') and opts.get('remove'):
5634 raise util.Abort(_("--rev and --remove are incompatible"))
5635 raise util.Abort(_("--rev and --remove are incompatible"))
5635 if opts.get('rev'):
5636 if opts.get('rev'):
5636 rev_ = opts['rev']
5637 rev_ = opts['rev']
5637 message = opts.get('message')
5638 message = opts.get('message')
5638 if opts.get('remove'):
5639 if opts.get('remove'):
5639 expectedtype = opts.get('local') and 'local' or 'global'
5640 expectedtype = opts.get('local') and 'local' or 'global'
5640 for n in names:
5641 for n in names:
5641 if not repo.tagtype(n):
5642 if not repo.tagtype(n):
5642 raise util.Abort(_("tag '%s' does not exist") % n)
5643 raise util.Abort(_("tag '%s' does not exist") % n)
5643 if repo.tagtype(n) != expectedtype:
5644 if repo.tagtype(n) != expectedtype:
5644 if expectedtype == 'global':
5645 if expectedtype == 'global':
5645 raise util.Abort(_("tag '%s' is not a global tag") % n)
5646 raise util.Abort(_("tag '%s' is not a global tag") % n)
5646 else:
5647 else:
5647 raise util.Abort(_("tag '%s' is not a local tag") % n)
5648 raise util.Abort(_("tag '%s' is not a local tag") % n)
5648 rev_ = nullid
5649 rev_ = nullid
5649 if not message:
5650 if not message:
5650 # we don't translate commit messages
5651 # we don't translate commit messages
5651 message = 'Removed tag %s' % ', '.join(names)
5652 message = 'Removed tag %s' % ', '.join(names)
5652 elif not opts.get('force'):
5653 elif not opts.get('force'):
5653 for n in names:
5654 for n in names:
5654 if n in repo.tags():
5655 if n in repo.tags():
5655 raise util.Abort(_("tag '%s' already exists "
5656 raise util.Abort(_("tag '%s' already exists "
5656 "(use -f to force)") % n)
5657 "(use -f to force)") % n)
5657 if not opts.get('local'):
5658 if not opts.get('local'):
5658 p1, p2 = repo.dirstate.parents()
5659 p1, p2 = repo.dirstate.parents()
5659 if p2 != nullid:
5660 if p2 != nullid:
5660 raise util.Abort(_('uncommitted merge'))
5661 raise util.Abort(_('uncommitted merge'))
5661 bheads = repo.branchheads()
5662 bheads = repo.branchheads()
5662 if not opts.get('force') and bheads and p1 not in bheads:
5663 if not opts.get('force') and bheads and p1 not in bheads:
5663 raise util.Abort(_('not at a branch head (use -f to force)'))
5664 raise util.Abort(_('not at a branch head (use -f to force)'))
5664 r = scmutil.revsingle(repo, rev_).node()
5665 r = scmutil.revsingle(repo, rev_).node()
5665
5666
5666 if not message:
5667 if not message:
5667 # we don't translate commit messages
5668 # we don't translate commit messages
5668 message = ('Added tag %s for changeset %s' %
5669 message = ('Added tag %s for changeset %s' %
5669 (', '.join(names), short(r)))
5670 (', '.join(names), short(r)))
5670
5671
5671 date = opts.get('date')
5672 date = opts.get('date')
5672 if date:
5673 if date:
5673 date = util.parsedate(date)
5674 date = util.parsedate(date)
5674
5675
5675 if opts.get('edit'):
5676 if opts.get('edit'):
5676 message = ui.edit(message, ui.username())
5677 message = ui.edit(message, ui.username())
5677
5678
5678 # don't allow tagging the null rev
5679 # don't allow tagging the null rev
5679 if (not opts.get('remove') and
5680 if (not opts.get('remove') and
5680 scmutil.revsingle(repo, rev_).rev() == nullrev):
5681 scmutil.revsingle(repo, rev_).rev() == nullrev):
5681 raise util.Abort(_("cannot tag null revision"))
5682 raise util.Abort(_("cannot tag null revision"))
5682
5683
5683 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5684 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5684 finally:
5685 finally:
5685 release(lock, wlock)
5686 release(lock, wlock)
5686
5687
5687 @command('tags', [], '')
5688 @command('tags', [], '')
5688 def tags(ui, repo, **opts):
5689 def tags(ui, repo, **opts):
5689 """list repository tags
5690 """list repository tags
5690
5691
5691 This lists both regular and local tags. When the -v/--verbose
5692 This lists both regular and local tags. When the -v/--verbose
5692 switch is used, a third column "local" is printed for local tags.
5693 switch is used, a third column "local" is printed for local tags.
5693
5694
5694 Returns 0 on success.
5695 Returns 0 on success.
5695 """
5696 """
5696
5697
5697 fm = ui.formatter('tags', opts)
5698 fm = ui.formatter('tags', opts)
5698 hexfunc = ui.debugflag and hex or short
5699 hexfunc = ui.debugflag and hex or short
5699 tagtype = ""
5700 tagtype = ""
5700
5701
5701 for t, n in reversed(repo.tagslist()):
5702 for t, n in reversed(repo.tagslist()):
5702 hn = hexfunc(n)
5703 hn = hexfunc(n)
5703 label = 'tags.normal'
5704 label = 'tags.normal'
5704 tagtype = ''
5705 tagtype = ''
5705 if repo.tagtype(t) == 'local':
5706 if repo.tagtype(t) == 'local':
5706 label = 'tags.local'
5707 label = 'tags.local'
5707 tagtype = 'local'
5708 tagtype = 'local'
5708
5709
5709 fm.startitem()
5710 fm.startitem()
5710 fm.write('tag', '%s', t, label=label)
5711 fm.write('tag', '%s', t, label=label)
5711 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5712 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5712 fm.condwrite(not ui.quiet, 'rev id', fmt,
5713 fm.condwrite(not ui.quiet, 'rev id', fmt,
5713 repo.changelog.rev(n), hn, label=label)
5714 repo.changelog.rev(n), hn, label=label)
5714 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5715 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5715 tagtype, label=label)
5716 tagtype, label=label)
5716 fm.plain('\n')
5717 fm.plain('\n')
5717 fm.end()
5718 fm.end()
5718
5719
5719 @command('tip',
5720 @command('tip',
5720 [('p', 'patch', None, _('show patch')),
5721 [('p', 'patch', None, _('show patch')),
5721 ('g', 'git', None, _('use git extended diff format')),
5722 ('g', 'git', None, _('use git extended diff format')),
5722 ] + templateopts,
5723 ] + templateopts,
5723 _('[-p] [-g]'))
5724 _('[-p] [-g]'))
5724 def tip(ui, repo, **opts):
5725 def tip(ui, repo, **opts):
5725 """show the tip revision (DEPRECATED)
5726 """show the tip revision (DEPRECATED)
5726
5727
5727 The tip revision (usually just called the tip) is the changeset
5728 The tip revision (usually just called the tip) is the changeset
5728 most recently added to the repository (and therefore the most
5729 most recently added to the repository (and therefore the most
5729 recently changed head).
5730 recently changed head).
5730
5731
5731 If you have just made a commit, that commit will be the tip. If
5732 If you have just made a commit, that commit will be the tip. If
5732 you have just pulled changes from another repository, the tip of
5733 you have just pulled changes from another repository, the tip of
5733 that repository becomes the current tip. The "tip" tag is special
5734 that repository becomes the current tip. The "tip" tag is special
5734 and cannot be renamed or assigned to a different changeset.
5735 and cannot be renamed or assigned to a different changeset.
5735
5736
5736 This command is deprecated, please use :hg:`heads` instead.
5737 This command is deprecated, please use :hg:`heads` instead.
5737
5738
5738 Returns 0 on success.
5739 Returns 0 on success.
5739 """
5740 """
5740 displayer = cmdutil.show_changeset(ui, repo, opts)
5741 displayer = cmdutil.show_changeset(ui, repo, opts)
5741 displayer.show(repo['tip'])
5742 displayer.show(repo['tip'])
5742 displayer.close()
5743 displayer.close()
5743
5744
5744 @command('unbundle',
5745 @command('unbundle',
5745 [('u', 'update', None,
5746 [('u', 'update', None,
5746 _('update to new branch head if changesets were unbundled'))],
5747 _('update to new branch head if changesets were unbundled'))],
5747 _('[-u] FILE...'))
5748 _('[-u] FILE...'))
5748 def unbundle(ui, repo, fname1, *fnames, **opts):
5749 def unbundle(ui, repo, fname1, *fnames, **opts):
5749 """apply one or more changegroup files
5750 """apply one or more changegroup files
5750
5751
5751 Apply one or more compressed changegroup files generated by the
5752 Apply one or more compressed changegroup files generated by the
5752 bundle command.
5753 bundle command.
5753
5754
5754 Returns 0 on success, 1 if an update has unresolved files.
5755 Returns 0 on success, 1 if an update has unresolved files.
5755 """
5756 """
5756 fnames = (fname1,) + fnames
5757 fnames = (fname1,) + fnames
5757
5758
5758 lock = repo.lock()
5759 lock = repo.lock()
5759 wc = repo['.']
5760 wc = repo['.']
5760 try:
5761 try:
5761 for fname in fnames:
5762 for fname in fnames:
5762 f = hg.openpath(ui, fname)
5763 f = hg.openpath(ui, fname)
5763 gen = changegroup.readbundle(f, fname)
5764 gen = changegroup.readbundle(f, fname)
5764 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5765 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5765 finally:
5766 finally:
5766 lock.release()
5767 lock.release()
5767 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5768 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5768 return postincoming(ui, repo, modheads, opts.get('update'), None)
5769 return postincoming(ui, repo, modheads, opts.get('update'), None)
5769
5770
5770 @command('^update|up|checkout|co',
5771 @command('^update|up|checkout|co',
5771 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5772 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5772 ('c', 'check', None,
5773 ('c', 'check', None,
5773 _('update across branches if no uncommitted changes')),
5774 _('update across branches if no uncommitted changes')),
5774 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5775 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5775 ('r', 'rev', '', _('revision'), _('REV'))],
5776 ('r', 'rev', '', _('revision'), _('REV'))],
5776 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5777 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5777 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5778 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5778 """update working directory (or switch revisions)
5779 """update working directory (or switch revisions)
5779
5780
5780 Update the repository's working directory to the specified
5781 Update the repository's working directory to the specified
5781 changeset. If no changeset is specified, update to the tip of the
5782 changeset. If no changeset is specified, update to the tip of the
5782 current named branch and move the current bookmark (see :hg:`help
5783 current named branch and move the current bookmark (see :hg:`help
5783 bookmarks`).
5784 bookmarks`).
5784
5785
5785 Update sets the working directory's parent revision to the specified
5786 Update sets the working directory's parent revision to the specified
5786 changeset (see :hg:`help parents`).
5787 changeset (see :hg:`help parents`).
5787
5788
5788 If the changeset is not a descendant or ancestor of the working
5789 If the changeset is not a descendant or ancestor of the working
5789 directory's parent, the update is aborted. With the -c/--check
5790 directory's parent, the update is aborted. With the -c/--check
5790 option, the working directory is checked for uncommitted changes; if
5791 option, the working directory is checked for uncommitted changes; if
5791 none are found, the working directory is updated to the specified
5792 none are found, the working directory is updated to the specified
5792 changeset.
5793 changeset.
5793
5794
5794 .. container:: verbose
5795 .. container:: verbose
5795
5796
5796 The following rules apply when the working directory contains
5797 The following rules apply when the working directory contains
5797 uncommitted changes:
5798 uncommitted changes:
5798
5799
5799 1. If neither -c/--check nor -C/--clean is specified, and if
5800 1. If neither -c/--check nor -C/--clean is specified, and if
5800 the requested changeset is an ancestor or descendant of
5801 the requested changeset is an ancestor or descendant of
5801 the working directory's parent, the uncommitted changes
5802 the working directory's parent, the uncommitted changes
5802 are merged into the requested changeset and the merged
5803 are merged into the requested changeset and the merged
5803 result is left uncommitted. If the requested changeset is
5804 result is left uncommitted. If the requested changeset is
5804 not an ancestor or descendant (that is, it is on another
5805 not an ancestor or descendant (that is, it is on another
5805 branch), the update is aborted and the uncommitted changes
5806 branch), the update is aborted and the uncommitted changes
5806 are preserved.
5807 are preserved.
5807
5808
5808 2. With the -c/--check option, the update is aborted and the
5809 2. With the -c/--check option, the update is aborted and the
5809 uncommitted changes are preserved.
5810 uncommitted changes are preserved.
5810
5811
5811 3. With the -C/--clean option, uncommitted changes are discarded and
5812 3. With the -C/--clean option, uncommitted changes are discarded and
5812 the working directory is updated to the requested changeset.
5813 the working directory is updated to the requested changeset.
5813
5814
5814 To cancel an uncommitted merge (and lose your changes), use
5815 To cancel an uncommitted merge (and lose your changes), use
5815 :hg:`update --clean .`.
5816 :hg:`update --clean .`.
5816
5817
5817 Use null as the changeset to remove the working directory (like
5818 Use null as the changeset to remove the working directory (like
5818 :hg:`clone -U`).
5819 :hg:`clone -U`).
5819
5820
5820 If you want to revert just one file to an older revision, use
5821 If you want to revert just one file to an older revision, use
5821 :hg:`revert [-r REV] NAME`.
5822 :hg:`revert [-r REV] NAME`.
5822
5823
5823 See :hg:`help dates` for a list of formats valid for -d/--date.
5824 See :hg:`help dates` for a list of formats valid for -d/--date.
5824
5825
5825 Returns 0 on success, 1 if there are unresolved files.
5826 Returns 0 on success, 1 if there are unresolved files.
5826 """
5827 """
5827 if rev and node:
5828 if rev and node:
5828 raise util.Abort(_("please specify just one revision"))
5829 raise util.Abort(_("please specify just one revision"))
5829
5830
5830 if rev is None or rev == '':
5831 if rev is None or rev == '':
5831 rev = node
5832 rev = node
5832
5833
5833 cmdutil.clearunfinished(repo)
5834 cmdutil.clearunfinished(repo)
5834
5835
5835 # with no argument, we also move the current bookmark, if any
5836 # with no argument, we also move the current bookmark, if any
5836 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5837 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5837
5838
5838 # if we defined a bookmark, we have to remember the original bookmark name
5839 # if we defined a bookmark, we have to remember the original bookmark name
5839 brev = rev
5840 brev = rev
5840 rev = scmutil.revsingle(repo, rev, rev).rev()
5841 rev = scmutil.revsingle(repo, rev, rev).rev()
5841
5842
5842 if check and clean:
5843 if check and clean:
5843 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5844 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5844
5845
5845 if date:
5846 if date:
5846 if rev is not None:
5847 if rev is not None:
5847 raise util.Abort(_("you can't specify a revision and a date"))
5848 raise util.Abort(_("you can't specify a revision and a date"))
5848 rev = cmdutil.finddate(ui, repo, date)
5849 rev = cmdutil.finddate(ui, repo, date)
5849
5850
5850 if check:
5851 if check:
5851 c = repo[None]
5852 c = repo[None]
5852 if c.dirty(merge=False, branch=False, missing=True):
5853 if c.dirty(merge=False, branch=False, missing=True):
5853 raise util.Abort(_("uncommitted changes"))
5854 raise util.Abort(_("uncommitted changes"))
5854 if rev is None:
5855 if rev is None:
5855 rev = repo[repo[None].branch()].rev()
5856 rev = repo[repo[None].branch()].rev()
5856 mergemod._checkunknown(repo, repo[None], repo[rev])
5857 mergemod._checkunknown(repo, repo[None], repo[rev])
5857
5858
5858 if clean:
5859 if clean:
5859 ret = hg.clean(repo, rev)
5860 ret = hg.clean(repo, rev)
5860 else:
5861 else:
5861 ret = hg.update(repo, rev)
5862 ret = hg.update(repo, rev)
5862
5863
5863 if not ret and movemarkfrom:
5864 if not ret and movemarkfrom:
5864 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5865 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5865 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5866 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5866 elif brev in repo._bookmarks:
5867 elif brev in repo._bookmarks:
5867 bookmarks.setcurrent(repo, brev)
5868 bookmarks.setcurrent(repo, brev)
5868 elif brev:
5869 elif brev:
5869 bookmarks.unsetcurrent(repo)
5870 bookmarks.unsetcurrent(repo)
5870
5871
5871 return ret
5872 return ret
5872
5873
5873 @command('verify', [])
5874 @command('verify', [])
5874 def verify(ui, repo):
5875 def verify(ui, repo):
5875 """verify the integrity of the repository
5876 """verify the integrity of the repository
5876
5877
5877 Verify the integrity of the current repository.
5878 Verify the integrity of the current repository.
5878
5879
5879 This will perform an extensive check of the repository's
5880 This will perform an extensive check of the repository's
5880 integrity, validating the hashes and checksums of each entry in
5881 integrity, validating the hashes and checksums of each entry in
5881 the changelog, manifest, and tracked files, as well as the
5882 the changelog, manifest, and tracked files, as well as the
5882 integrity of their crosslinks and indices.
5883 integrity of their crosslinks and indices.
5883
5884
5884 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5885 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5885 for more information about recovery from corruption of the
5886 for more information about recovery from corruption of the
5886 repository.
5887 repository.
5887
5888
5888 Returns 0 on success, 1 if errors are encountered.
5889 Returns 0 on success, 1 if errors are encountered.
5889 """
5890 """
5890 return hg.verify(repo)
5891 return hg.verify(repo)
5891
5892
5892 @command('version', [])
5893 @command('version', [])
5893 def version_(ui):
5894 def version_(ui):
5894 """output version and copyright information"""
5895 """output version and copyright information"""
5895 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5896 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5896 % util.version())
5897 % util.version())
5897 ui.status(_(
5898 ui.status(_(
5898 "(see http://mercurial.selenic.com for more information)\n"
5899 "(see http://mercurial.selenic.com for more information)\n"
5899 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5900 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5900 "This is free software; see the source for copying conditions. "
5901 "This is free software; see the source for copying conditions. "
5901 "There is NO\nwarranty; "
5902 "There is NO\nwarranty; "
5902 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5903 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5903 ))
5904 ))
5904
5905
5905 norepo = ("clone init version help debugcommands debugcomplete"
5906 norepo = ("clone init version help debugcommands debugcomplete"
5906 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5907 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5907 " debugknown debuggetbundle debugbundle")
5908 " debugknown debuggetbundle debugbundle")
5908 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5909 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5909 " debugdata debugindex debugindexdot debugrevlog")
5910 " debugdata debugindex debugindexdot debugrevlog")
5910 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5911 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5911 " remove resolve status debugwalk")
5912 " remove resolve status debugwalk")
@@ -1,571 +1,571
1 Create a repo with some stuff in it:
1 Create a repo with some stuff in it:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ echo a > d
6 $ echo a > d
7 $ echo a > e
7 $ echo a > e
8 $ hg ci -qAm0
8 $ hg ci -qAm0
9 $ echo b > a
9 $ echo b > a
10 $ hg ci -m1 -u bar
10 $ hg ci -m1 -u bar
11 $ hg mv a b
11 $ hg mv a b
12 $ hg ci -m2
12 $ hg ci -m2
13 $ hg cp b c
13 $ hg cp b c
14 $ hg ci -m3 -u baz
14 $ hg ci -m3 -u baz
15 $ echo b > d
15 $ echo b > d
16 $ echo f > e
16 $ echo f > e
17 $ hg ci -m4
17 $ hg ci -m4
18 $ hg up -q 3
18 $ hg up -q 3
19 $ echo b > e
19 $ echo b > e
20 $ hg branch -q stable
20 $ hg branch -q stable
21 $ hg ci -m5
21 $ hg ci -m5
22 $ hg merge -q default --tool internal:local
22 $ hg merge -q default --tool internal:local
23 $ hg branch -q default
23 $ hg branch -q default
24 $ hg ci -m6
24 $ hg ci -m6
25 $ hg phase --public 3
25 $ hg phase --public 3
26 $ hg phase --force --secret 6
26 $ hg phase --force --secret 6
27
27
28 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
28 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
29 @ test@6.secret: 6
29 @ test@6.secret: 6
30 |\
30 |\
31 | o test@5.draft: 5
31 | o test@5.draft: 5
32 | |
32 | |
33 o | test@4.draft: 4
33 o | test@4.draft: 4
34 |/
34 |/
35 o baz@3.public: 3
35 o baz@3.public: 3
36 |
36 |
37 o test@2.public: 2
37 o test@2.public: 2
38 |
38 |
39 o bar@1.public: 1
39 o bar@1.public: 1
40 |
40 |
41 o test@0.public: 0
41 o test@0.public: 0
42
42
43
43
44 Need to specify a rev:
44 Need to specify a rev:
45
45
46 $ hg graft
46 $ hg graft
47 abort: no revisions specified
47 abort: no revisions specified
48 [255]
48 [255]
49
49
50 Can't graft ancestor:
50 Can't graft ancestor:
51
51
52 $ hg graft 1 2
52 $ hg graft 1 2
53 skipping ancestor revision 1
53 skipping ancestor revision 1
54 skipping ancestor revision 2
54 skipping ancestor revision 2
55 [255]
55 [255]
56
56
57 Specify revisions with -r:
57 Specify revisions with -r:
58
58
59 $ hg graft -r 1 -r 2
59 $ hg graft -r 1 -r 2
60 skipping ancestor revision 1
60 skipping ancestor revision 1
61 skipping ancestor revision 2
61 skipping ancestor revision 2
62 [255]
62 [255]
63
63
64 $ hg graft -r 1 2
64 $ hg graft -r 1 2
65 skipping ancestor revision 2
65 skipping ancestor revision 2
66 skipping ancestor revision 1
66 skipping ancestor revision 1
67 [255]
67 [255]
68
68
69 Can't graft with dirty wd:
69 Can't graft with dirty wd:
70
70
71 $ hg up -q 0
71 $ hg up -q 0
72 $ echo foo > a
72 $ echo foo > a
73 $ hg graft 1
73 $ hg graft 1
74 abort: uncommitted changes
74 abort: uncommitted changes
75 [255]
75 [255]
76 $ hg revert a
76 $ hg revert a
77
77
78 Graft a rename:
78 Graft a rename:
79
79
80 $ hg graft 2 -u foo
80 $ hg graft 2 -u foo
81 grafting revision 2
81 grafting revision 2
82 merging a and b to b
82 merging a and b to b
83 $ hg export tip --git
83 $ hg export tip --git
84 # HG changeset patch
84 # HG changeset patch
85 # User foo
85 # User foo
86 # Date 0 0
86 # Date 0 0
87 # Thu Jan 01 00:00:00 1970 +0000
87 # Thu Jan 01 00:00:00 1970 +0000
88 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
88 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
89 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
89 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
90 2
90 2
91
91
92 diff --git a/a b/b
92 diff --git a/a b/b
93 rename from a
93 rename from a
94 rename to b
94 rename to b
95
95
96 Look for extra:source
96 Look for extra:source
97
97
98 $ hg log --debug -r tip
98 $ hg log --debug -r tip
99 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
99 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
100 tag: tip
100 tag: tip
101 phase: draft
101 phase: draft
102 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
102 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
103 parent: -1:0000000000000000000000000000000000000000
103 parent: -1:0000000000000000000000000000000000000000
104 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
104 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
105 user: foo
105 user: foo
106 date: Thu Jan 01 00:00:00 1970 +0000
106 date: Thu Jan 01 00:00:00 1970 +0000
107 files+: b
107 files+: b
108 files-: a
108 files-: a
109 extra: branch=default
109 extra: branch=default
110 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
110 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
111 description:
111 description:
112 2
112 2
113
113
114
114
115
115
116 Graft out of order, skipping a merge and a duplicate
116 Graft out of order, skipping a merge and a duplicate
117
117
118 $ hg graft 1 5 4 3 'merge()' 2 -n
118 $ hg graft 1 5 4 3 'merge()' 2 -n
119 skipping ungraftable merge revision 6
119 skipping ungraftable merge revision 6
120 skipping already grafted revision 2
120 skipping revision 2 (already grafted to 7)
121 grafting revision 1
121 grafting revision 1
122 grafting revision 5
122 grafting revision 5
123 grafting revision 4
123 grafting revision 4
124 grafting revision 3
124 grafting revision 3
125
125
126 $ hg graft 1 5 4 3 'merge()' 2 --debug
126 $ hg graft 1 5 4 3 'merge()' 2 --debug
127 skipping ungraftable merge revision 6
127 skipping ungraftable merge revision 6
128 scanning for duplicate grafts
128 scanning for duplicate grafts
129 skipping already grafted revision 2
129 skipping revision 2 (already grafted to 7)
130 grafting revision 1
130 grafting revision 1
131 searching for copies back to rev 1
131 searching for copies back to rev 1
132 unmatched files in local:
132 unmatched files in local:
133 b
133 b
134 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
134 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
135 src: 'a' -> dst: 'b' *
135 src: 'a' -> dst: 'b' *
136 checking for directory renames
136 checking for directory renames
137 resolving manifests
137 resolving manifests
138 branchmerge: True, force: True, partial: False
138 branchmerge: True, force: True, partial: False
139 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
139 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
140 b: local copied/moved to a -> m
140 b: local copied/moved to a -> m
141 preserving b for resolve of b
141 preserving b for resolve of b
142 updating: b 1/1 files (100.00%)
142 updating: b 1/1 files (100.00%)
143 picked tool 'internal:merge' for b (binary False symlink False)
143 picked tool 'internal:merge' for b (binary False symlink False)
144 merging b and a to b
144 merging b and a to b
145 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
145 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
146 premerge successful
146 premerge successful
147 b
147 b
148 grafting revision 5
148 grafting revision 5
149 searching for copies back to rev 1
149 searching for copies back to rev 1
150 resolving manifests
150 resolving manifests
151 branchmerge: True, force: True, partial: False
151 branchmerge: True, force: True, partial: False
152 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
152 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
153 e: remote is newer -> g
153 e: remote is newer -> g
154 getting e
154 getting e
155 updating: e 1/1 files (100.00%)
155 updating: e 1/1 files (100.00%)
156 e
156 e
157 grafting revision 4
157 grafting revision 4
158 searching for copies back to rev 1
158 searching for copies back to rev 1
159 resolving manifests
159 resolving manifests
160 branchmerge: True, force: True, partial: False
160 branchmerge: True, force: True, partial: False
161 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
161 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
162 d: remote is newer -> g
162 d: remote is newer -> g
163 e: versions differ -> m
163 e: versions differ -> m
164 preserving e for resolve of e
164 preserving e for resolve of e
165 getting d
165 getting d
166 updating: d 1/2 files (50.00%)
166 updating: d 1/2 files (50.00%)
167 updating: e 2/2 files (100.00%)
167 updating: e 2/2 files (100.00%)
168 picked tool 'internal:merge' for e (binary False symlink False)
168 picked tool 'internal:merge' for e (binary False symlink False)
169 merging e
169 merging e
170 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
170 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
171 warning: conflicts during merge.
171 warning: conflicts during merge.
172 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
172 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
173 abort: unresolved conflicts, can't continue
173 abort: unresolved conflicts, can't continue
174 (use hg resolve and hg graft --continue)
174 (use hg resolve and hg graft --continue)
175 [255]
175 [255]
176
176
177 Commit while interrupted should fail:
177 Commit while interrupted should fail:
178
178
179 $ hg ci -m 'commit interrupted graft'
179 $ hg ci -m 'commit interrupted graft'
180 abort: graft in progress
180 abort: graft in progress
181 (use 'hg graft --continue' or 'hg update' to abort)
181 (use 'hg graft --continue' or 'hg update' to abort)
182 [255]
182 [255]
183
183
184 Abort the graft and try committing:
184 Abort the graft and try committing:
185
185
186 $ hg up -C .
186 $ hg up -C .
187 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
188 $ echo c >> e
188 $ echo c >> e
189 $ hg ci -mtest
189 $ hg ci -mtest
190
190
191 $ hg strip . --config extensions.mq=
191 $ hg strip . --config extensions.mq=
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
193 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
194
194
195 Graft again:
195 Graft again:
196
196
197 $ hg graft 1 5 4 3 'merge()' 2
197 $ hg graft 1 5 4 3 'merge()' 2
198 skipping ungraftable merge revision 6
198 skipping ungraftable merge revision 6
199 skipping already grafted revision 2
199 skipping revision 2 (already grafted to 7)
200 skipping already grafted revision 1
200 skipping revision 1 (already grafted to 8)
201 skipping already grafted revision 5
201 skipping revision 5 (already grafted to 9)
202 grafting revision 4
202 grafting revision 4
203 merging e
203 merging e
204 warning: conflicts during merge.
204 warning: conflicts during merge.
205 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
205 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
206 abort: unresolved conflicts, can't continue
206 abort: unresolved conflicts, can't continue
207 (use hg resolve and hg graft --continue)
207 (use hg resolve and hg graft --continue)
208 [255]
208 [255]
209
209
210 Continue without resolve should fail:
210 Continue without resolve should fail:
211
211
212 $ hg graft -c
212 $ hg graft -c
213 grafting revision 4
213 grafting revision 4
214 abort: unresolved merge conflicts (see hg help resolve)
214 abort: unresolved merge conflicts (see hg help resolve)
215 [255]
215 [255]
216
216
217 Fix up:
217 Fix up:
218
218
219 $ echo b > e
219 $ echo b > e
220 $ hg resolve -m e
220 $ hg resolve -m e
221
221
222 Continue with a revision should fail:
222 Continue with a revision should fail:
223
223
224 $ hg graft -c 6
224 $ hg graft -c 6
225 abort: can't specify --continue and revisions
225 abort: can't specify --continue and revisions
226 [255]
226 [255]
227
227
228 $ hg graft -c -r 6
228 $ hg graft -c -r 6
229 abort: can't specify --continue and revisions
229 abort: can't specify --continue and revisions
230 [255]
230 [255]
231
231
232 Continue for real, clobber usernames
232 Continue for real, clobber usernames
233
233
234 $ hg graft -c -U
234 $ hg graft -c -U
235 grafting revision 4
235 grafting revision 4
236 grafting revision 3
236 grafting revision 3
237
237
238 Compare with original:
238 Compare with original:
239
239
240 $ hg diff -r 6
240 $ hg diff -r 6
241 $ hg status --rev 0:. -C
241 $ hg status --rev 0:. -C
242 M d
242 M d
243 M e
243 M e
244 A b
244 A b
245 a
245 a
246 A c
246 A c
247 a
247 a
248 R a
248 R a
249
249
250 View graph:
250 View graph:
251
251
252 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
252 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
253 @ test@11.draft: 3
253 @ test@11.draft: 3
254 |
254 |
255 o test@10.draft: 4
255 o test@10.draft: 4
256 |
256 |
257 o test@9.draft: 5
257 o test@9.draft: 5
258 |
258 |
259 o bar@8.draft: 1
259 o bar@8.draft: 1
260 |
260 |
261 o foo@7.draft: 2
261 o foo@7.draft: 2
262 |
262 |
263 | o test@6.secret: 6
263 | o test@6.secret: 6
264 | |\
264 | |\
265 | | o test@5.draft: 5
265 | | o test@5.draft: 5
266 | | |
266 | | |
267 | o | test@4.draft: 4
267 | o | test@4.draft: 4
268 | |/
268 | |/
269 | o baz@3.public: 3
269 | o baz@3.public: 3
270 | |
270 | |
271 | o test@2.public: 2
271 | o test@2.public: 2
272 | |
272 | |
273 | o bar@1.public: 1
273 | o bar@1.public: 1
274 |/
274 |/
275 o test@0.public: 0
275 o test@0.public: 0
276
276
277 Graft again onto another branch should preserve the original source
277 Graft again onto another branch should preserve the original source
278 $ hg up -q 0
278 $ hg up -q 0
279 $ echo 'g'>g
279 $ echo 'g'>g
280 $ hg add g
280 $ hg add g
281 $ hg ci -m 7
281 $ hg ci -m 7
282 created new head
282 created new head
283 $ hg graft 7
283 $ hg graft 7
284 grafting revision 7
284 grafting revision 7
285
285
286 $ hg log -r 7 --template '{rev}:{node}\n'
286 $ hg log -r 7 --template '{rev}:{node}\n'
287 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
287 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
288 $ hg log -r 2 --template '{rev}:{node}\n'
288 $ hg log -r 2 --template '{rev}:{node}\n'
289 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
289 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
290
290
291 $ hg log --debug -r tip
291 $ hg log --debug -r tip
292 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
292 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
293 tag: tip
293 tag: tip
294 phase: draft
294 phase: draft
295 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
295 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
296 parent: -1:0000000000000000000000000000000000000000
296 parent: -1:0000000000000000000000000000000000000000
297 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
297 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
298 user: foo
298 user: foo
299 date: Thu Jan 01 00:00:00 1970 +0000
299 date: Thu Jan 01 00:00:00 1970 +0000
300 files+: b
300 files+: b
301 files-: a
301 files-: a
302 extra: branch=default
302 extra: branch=default
303 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
303 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
304 description:
304 description:
305 2
305 2
306
306
307
307
308 Disallow grafting an already grafted cset onto its original branch
308 Disallow grafting an already grafted cset onto its original branch
309 $ hg up -q 6
309 $ hg up -q 6
310 $ hg graft 7
310 $ hg graft 7
311 skipping already grafted revision 7 (was grafted from 2)
311 skipping already grafted revision 7 (was grafted from 2)
312 [255]
312 [255]
313
313
314 Disallow grafting already grafted csets with the same origin onto each other
314 Disallow grafting already grafted csets with the same origin onto each other
315 $ hg up -q 13
315 $ hg up -q 13
316 $ hg graft 2
316 $ hg graft 2
317 skipping already grafted revision 2
317 skipping revision 2 (already grafted to 13)
318 [255]
318 [255]
319 $ hg graft 7
319 $ hg graft 7
320 skipping already grafted revision 7 (same origin 2)
320 skipping already grafted revision 7 (13 also has origin 2)
321 [255]
321 [255]
322
322
323 $ hg up -q 7
323 $ hg up -q 7
324 $ hg graft 2
324 $ hg graft 2
325 skipping already grafted revision 2
325 skipping revision 2 (already grafted to 7)
326 [255]
326 [255]
327 $ hg graft tip
327 $ hg graft tip
328 skipping already grafted revision 13 (same origin 2)
328 skipping already grafted revision 13 (7 also has origin 2)
329 [255]
329 [255]
330
330
331 Graft with --log
331 Graft with --log
332
332
333 $ hg up -Cq 1
333 $ hg up -Cq 1
334 $ hg graft 3 --log -u foo
334 $ hg graft 3 --log -u foo
335 grafting revision 3
335 grafting revision 3
336 warning: can't find ancestor for 'c' copied from 'b'!
336 warning: can't find ancestor for 'c' copied from 'b'!
337 $ hg log --template '{rev} {parents} {desc}\n' -r tip
337 $ hg log --template '{rev} {parents} {desc}\n' -r tip
338 14 1:5d205f8b35b6 3
338 14 1:5d205f8b35b6 3
339 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
339 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
340
340
341 Resolve conflicted graft
341 Resolve conflicted graft
342 $ hg up -q 0
342 $ hg up -q 0
343 $ echo b > a
343 $ echo b > a
344 $ hg ci -m 8
344 $ hg ci -m 8
345 created new head
345 created new head
346 $ echo a > a
346 $ echo a > a
347 $ hg ci -m 9
347 $ hg ci -m 9
348 $ hg graft 1 --tool internal:fail
348 $ hg graft 1 --tool internal:fail
349 grafting revision 1
349 grafting revision 1
350 abort: unresolved conflicts, can't continue
350 abort: unresolved conflicts, can't continue
351 (use hg resolve and hg graft --continue)
351 (use hg resolve and hg graft --continue)
352 [255]
352 [255]
353 $ hg resolve --all
353 $ hg resolve --all
354 merging a
354 merging a
355 $ hg graft -c
355 $ hg graft -c
356 grafting revision 1
356 grafting revision 1
357 $ hg export tip --git
357 $ hg export tip --git
358 # HG changeset patch
358 # HG changeset patch
359 # User bar
359 # User bar
360 # Date 0 0
360 # Date 0 0
361 # Thu Jan 01 00:00:00 1970 +0000
361 # Thu Jan 01 00:00:00 1970 +0000
362 # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
362 # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
363 # Parent 4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
363 # Parent 4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
364 1
364 1
365
365
366 diff --git a/a b/a
366 diff --git a/a b/a
367 --- a/a
367 --- a/a
368 +++ b/a
368 +++ b/a
369 @@ -1,1 +1,1 @@
369 @@ -1,1 +1,1 @@
370 -a
370 -a
371 +b
371 +b
372
372
373 Resolve conflicted graft with rename
373 Resolve conflicted graft with rename
374 $ echo c > a
374 $ echo c > a
375 $ hg ci -m 10
375 $ hg ci -m 10
376 $ hg graft 2 --tool internal:fail
376 $ hg graft 2 --tool internal:fail
377 grafting revision 2
377 grafting revision 2
378 abort: unresolved conflicts, can't continue
378 abort: unresolved conflicts, can't continue
379 (use hg resolve and hg graft --continue)
379 (use hg resolve and hg graft --continue)
380 [255]
380 [255]
381 $ hg resolve --all
381 $ hg resolve --all
382 merging a and b to b
382 merging a and b to b
383 $ hg graft -c
383 $ hg graft -c
384 grafting revision 2
384 grafting revision 2
385 $ hg export tip --git
385 $ hg export tip --git
386 # HG changeset patch
386 # HG changeset patch
387 # User test
387 # User test
388 # Date 0 0
388 # Date 0 0
389 # Thu Jan 01 00:00:00 1970 +0000
389 # Thu Jan 01 00:00:00 1970 +0000
390 # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
390 # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
391 # Parent e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
391 # Parent e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
392 2
392 2
393
393
394 diff --git a/a b/b
394 diff --git a/a b/b
395 rename from a
395 rename from a
396 rename to b
396 rename to b
397
397
398 Test simple origin(), with and without args
398 Test simple origin(), with and without args
399 $ hg log -r 'origin()'
399 $ hg log -r 'origin()'
400 changeset: 1:5d205f8b35b6
400 changeset: 1:5d205f8b35b6
401 user: bar
401 user: bar
402 date: Thu Jan 01 00:00:00 1970 +0000
402 date: Thu Jan 01 00:00:00 1970 +0000
403 summary: 1
403 summary: 1
404
404
405 changeset: 2:5c095ad7e90f
405 changeset: 2:5c095ad7e90f
406 user: test
406 user: test
407 date: Thu Jan 01 00:00:00 1970 +0000
407 date: Thu Jan 01 00:00:00 1970 +0000
408 summary: 2
408 summary: 2
409
409
410 changeset: 3:4c60f11aa304
410 changeset: 3:4c60f11aa304
411 user: baz
411 user: baz
412 date: Thu Jan 01 00:00:00 1970 +0000
412 date: Thu Jan 01 00:00:00 1970 +0000
413 summary: 3
413 summary: 3
414
414
415 changeset: 4:9c233e8e184d
415 changeset: 4:9c233e8e184d
416 user: test
416 user: test
417 date: Thu Jan 01 00:00:00 1970 +0000
417 date: Thu Jan 01 00:00:00 1970 +0000
418 summary: 4
418 summary: 4
419
419
420 changeset: 5:97f8bfe72746
420 changeset: 5:97f8bfe72746
421 branch: stable
421 branch: stable
422 parent: 3:4c60f11aa304
422 parent: 3:4c60f11aa304
423 user: test
423 user: test
424 date: Thu Jan 01 00:00:00 1970 +0000
424 date: Thu Jan 01 00:00:00 1970 +0000
425 summary: 5
425 summary: 5
426
426
427 $ hg log -r 'origin(7)'
427 $ hg log -r 'origin(7)'
428 changeset: 2:5c095ad7e90f
428 changeset: 2:5c095ad7e90f
429 user: test
429 user: test
430 date: Thu Jan 01 00:00:00 1970 +0000
430 date: Thu Jan 01 00:00:00 1970 +0000
431 summary: 2
431 summary: 2
432
432
433 Now transplant a graft to test following through copies
433 Now transplant a graft to test following through copies
434 $ hg up -q 0
434 $ hg up -q 0
435 $ hg branch -q dev
435 $ hg branch -q dev
436 $ hg ci -qm "dev branch"
436 $ hg ci -qm "dev branch"
437 $ hg --config extensions.transplant= transplant -q 7
437 $ hg --config extensions.transplant= transplant -q 7
438 $ hg log -r 'origin(.)'
438 $ hg log -r 'origin(.)'
439 changeset: 2:5c095ad7e90f
439 changeset: 2:5c095ad7e90f
440 user: test
440 user: test
441 date: Thu Jan 01 00:00:00 1970 +0000
441 date: Thu Jan 01 00:00:00 1970 +0000
442 summary: 2
442 summary: 2
443
443
444 Test simple destination
444 Test simple destination
445 $ hg log -r 'destination()'
445 $ hg log -r 'destination()'
446 changeset: 7:ef0ef43d49e7
446 changeset: 7:ef0ef43d49e7
447 parent: 0:68795b066622
447 parent: 0:68795b066622
448 user: foo
448 user: foo
449 date: Thu Jan 01 00:00:00 1970 +0000
449 date: Thu Jan 01 00:00:00 1970 +0000
450 summary: 2
450 summary: 2
451
451
452 changeset: 8:6b9e5368ca4e
452 changeset: 8:6b9e5368ca4e
453 user: bar
453 user: bar
454 date: Thu Jan 01 00:00:00 1970 +0000
454 date: Thu Jan 01 00:00:00 1970 +0000
455 summary: 1
455 summary: 1
456
456
457 changeset: 9:1905859650ec
457 changeset: 9:1905859650ec
458 user: test
458 user: test
459 date: Thu Jan 01 00:00:00 1970 +0000
459 date: Thu Jan 01 00:00:00 1970 +0000
460 summary: 5
460 summary: 5
461
461
462 changeset: 10:52dc0b4c6907
462 changeset: 10:52dc0b4c6907
463 user: test
463 user: test
464 date: Thu Jan 01 00:00:00 1970 +0000
464 date: Thu Jan 01 00:00:00 1970 +0000
465 summary: 4
465 summary: 4
466
466
467 changeset: 11:882b35362a6b
467 changeset: 11:882b35362a6b
468 user: test
468 user: test
469 date: Thu Jan 01 00:00:00 1970 +0000
469 date: Thu Jan 01 00:00:00 1970 +0000
470 summary: 3
470 summary: 3
471
471
472 changeset: 13:9db0f28fd374
472 changeset: 13:9db0f28fd374
473 user: foo
473 user: foo
474 date: Thu Jan 01 00:00:00 1970 +0000
474 date: Thu Jan 01 00:00:00 1970 +0000
475 summary: 2
475 summary: 2
476
476
477 changeset: 14:f64defefacee
477 changeset: 14:f64defefacee
478 parent: 1:5d205f8b35b6
478 parent: 1:5d205f8b35b6
479 user: foo
479 user: foo
480 date: Thu Jan 01 00:00:00 1970 +0000
480 date: Thu Jan 01 00:00:00 1970 +0000
481 summary: 3
481 summary: 3
482
482
483 changeset: 17:64ecd9071ce8
483 changeset: 17:64ecd9071ce8
484 user: bar
484 user: bar
485 date: Thu Jan 01 00:00:00 1970 +0000
485 date: Thu Jan 01 00:00:00 1970 +0000
486 summary: 1
486 summary: 1
487
487
488 changeset: 19:2e80e1351d6e
488 changeset: 19:2e80e1351d6e
489 user: test
489 user: test
490 date: Thu Jan 01 00:00:00 1970 +0000
490 date: Thu Jan 01 00:00:00 1970 +0000
491 summary: 2
491 summary: 2
492
492
493 changeset: 21:7e61b508e709
493 changeset: 21:7e61b508e709
494 branch: dev
494 branch: dev
495 tag: tip
495 tag: tip
496 user: foo
496 user: foo
497 date: Thu Jan 01 00:00:00 1970 +0000
497 date: Thu Jan 01 00:00:00 1970 +0000
498 summary: 2
498 summary: 2
499
499
500 $ hg log -r 'destination(2)'
500 $ hg log -r 'destination(2)'
501 changeset: 7:ef0ef43d49e7
501 changeset: 7:ef0ef43d49e7
502 parent: 0:68795b066622
502 parent: 0:68795b066622
503 user: foo
503 user: foo
504 date: Thu Jan 01 00:00:00 1970 +0000
504 date: Thu Jan 01 00:00:00 1970 +0000
505 summary: 2
505 summary: 2
506
506
507 changeset: 13:9db0f28fd374
507 changeset: 13:9db0f28fd374
508 user: foo
508 user: foo
509 date: Thu Jan 01 00:00:00 1970 +0000
509 date: Thu Jan 01 00:00:00 1970 +0000
510 summary: 2
510 summary: 2
511
511
512 changeset: 19:2e80e1351d6e
512 changeset: 19:2e80e1351d6e
513 user: test
513 user: test
514 date: Thu Jan 01 00:00:00 1970 +0000
514 date: Thu Jan 01 00:00:00 1970 +0000
515 summary: 2
515 summary: 2
516
516
517 changeset: 21:7e61b508e709
517 changeset: 21:7e61b508e709
518 branch: dev
518 branch: dev
519 tag: tip
519 tag: tip
520 user: foo
520 user: foo
521 date: Thu Jan 01 00:00:00 1970 +0000
521 date: Thu Jan 01 00:00:00 1970 +0000
522 summary: 2
522 summary: 2
523
523
524 Transplants of grafts can find a destination...
524 Transplants of grafts can find a destination...
525 $ hg log -r 'destination(7)'
525 $ hg log -r 'destination(7)'
526 changeset: 21:7e61b508e709
526 changeset: 21:7e61b508e709
527 branch: dev
527 branch: dev
528 tag: tip
528 tag: tip
529 user: foo
529 user: foo
530 date: Thu Jan 01 00:00:00 1970 +0000
530 date: Thu Jan 01 00:00:00 1970 +0000
531 summary: 2
531 summary: 2
532
532
533 ... grafts of grafts unfortunately can't
533 ... grafts of grafts unfortunately can't
534 $ hg graft -q 13
534 $ hg graft -q 13
535 $ hg log -r 'destination(13)'
535 $ hg log -r 'destination(13)'
536 All copies of a cset
536 All copies of a cset
537 $ hg log -r 'origin(13) or destination(origin(13))'
537 $ hg log -r 'origin(13) or destination(origin(13))'
538 changeset: 2:5c095ad7e90f
538 changeset: 2:5c095ad7e90f
539 user: test
539 user: test
540 date: Thu Jan 01 00:00:00 1970 +0000
540 date: Thu Jan 01 00:00:00 1970 +0000
541 summary: 2
541 summary: 2
542
542
543 changeset: 7:ef0ef43d49e7
543 changeset: 7:ef0ef43d49e7
544 parent: 0:68795b066622
544 parent: 0:68795b066622
545 user: foo
545 user: foo
546 date: Thu Jan 01 00:00:00 1970 +0000
546 date: Thu Jan 01 00:00:00 1970 +0000
547 summary: 2
547 summary: 2
548
548
549 changeset: 13:9db0f28fd374
549 changeset: 13:9db0f28fd374
550 user: foo
550 user: foo
551 date: Thu Jan 01 00:00:00 1970 +0000
551 date: Thu Jan 01 00:00:00 1970 +0000
552 summary: 2
552 summary: 2
553
553
554 changeset: 19:2e80e1351d6e
554 changeset: 19:2e80e1351d6e
555 user: test
555 user: test
556 date: Thu Jan 01 00:00:00 1970 +0000
556 date: Thu Jan 01 00:00:00 1970 +0000
557 summary: 2
557 summary: 2
558
558
559 changeset: 21:7e61b508e709
559 changeset: 21:7e61b508e709
560 branch: dev
560 branch: dev
561 user: foo
561 user: foo
562 date: Thu Jan 01 00:00:00 1970 +0000
562 date: Thu Jan 01 00:00:00 1970 +0000
563 summary: 2
563 summary: 2
564
564
565 changeset: 22:1313d0a825e2
565 changeset: 22:1313d0a825e2
566 branch: dev
566 branch: dev
567 tag: tip
567 tag: tip
568 user: foo
568 user: foo
569 date: Thu Jan 01 00:00:00 1970 +0000
569 date: Thu Jan 01 00:00:00 1970 +0000
570 summary: 2
570 summary: 2
571
571
General Comments 0
You need to be logged in to leave comments. Login now