##// END OF EJS Templates
export: export working directory parent by default...
Mads Kiilerich -
r18956:1a9ad845 default
parent child Browse files
Show More
@@ -1,5831 +1,5834 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 bheads = repo.branchheads(branch)
459 bheads = repo.branchheads(branch)
460 hg.clean(repo, node, show_stats=False)
460 hg.clean(repo, node, show_stats=False)
461 repo.dirstate.setbranch(branch)
461 repo.dirstate.setbranch(branch)
462 rctx = scmutil.revsingle(repo, hex(parent))
462 rctx = scmutil.revsingle(repo, hex(parent))
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
464 if not opts.get('merge') and op1 != node:
464 if not opts.get('merge') and op1 != node:
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.update(repo, op1)
467 return hg.update(repo, op1)
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470
470
471 e = cmdutil.commiteditor
471 e = cmdutil.commiteditor
472 if not opts['message'] and not opts['logfile']:
472 if not opts['message'] and not opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 opts['message'] = "Backed out changeset %s" % short(node)
474 opts['message'] = "Backed out changeset %s" % short(node)
475 e = cmdutil.commitforceeditor
475 e = cmdutil.commitforceeditor
476
476
477 def commitfunc(ui, repo, message, match, opts):
477 def commitfunc(ui, repo, message, match, opts):
478 return repo.commit(message, opts.get('user'), opts.get('date'),
478 return repo.commit(message, opts.get('user'), opts.get('date'),
479 match, editor=e)
479 match, editor=e)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
482
482
483 def nice(node):
483 def nice(node):
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
485 ui.status(_('changeset %s backs out changeset %s\n') %
485 ui.status(_('changeset %s backs out changeset %s\n') %
486 (nice(repo.changelog.tip()), nice(node)))
486 (nice(repo.changelog.tip()), nice(node)))
487 if opts.get('merge') and op1 != node:
487 if opts.get('merge') and op1 != node:
488 hg.clean(repo, op1, show_stats=False)
488 hg.clean(repo, op1, show_stats=False)
489 ui.status(_('merging with changeset %s\n')
489 ui.status(_('merging with changeset %s\n')
490 % nice(repo.changelog.tip()))
490 % nice(repo.changelog.tip()))
491 try:
491 try:
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
493 return hg.merge(repo, hex(repo.changelog.tip()))
493 return hg.merge(repo, hex(repo.changelog.tip()))
494 finally:
494 finally:
495 ui.setconfig('ui', 'forcemerge', '')
495 ui.setconfig('ui', 'forcemerge', '')
496 finally:
496 finally:
497 wlock.release()
497 wlock.release()
498 return 0
498 return 0
499
499
500 @command('bisect',
500 @command('bisect',
501 [('r', 'reset', False, _('reset bisect state')),
501 [('r', 'reset', False, _('reset bisect state')),
502 ('g', 'good', False, _('mark changeset good')),
502 ('g', 'good', False, _('mark changeset good')),
503 ('b', 'bad', False, _('mark changeset bad')),
503 ('b', 'bad', False, _('mark changeset bad')),
504 ('s', 'skip', False, _('skip testing changeset')),
504 ('s', 'skip', False, _('skip testing changeset')),
505 ('e', 'extend', False, _('extend the bisect range')),
505 ('e', 'extend', False, _('extend the bisect range')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
507 ('U', 'noupdate', False, _('do not update to target'))],
507 ('U', 'noupdate', False, _('do not update to target'))],
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
509 def bisect(ui, repo, rev=None, extra=None, command=None,
509 def bisect(ui, repo, rev=None, extra=None, command=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
511 noupdate=None):
511 noupdate=None):
512 """subdivision search of changesets
512 """subdivision search of changesets
513
513
514 This command helps to find changesets which introduce problems. To
514 This command helps to find changesets which introduce problems. To
515 use, mark the earliest changeset you know exhibits the problem as
515 use, mark the earliest changeset you know exhibits the problem as
516 bad, then mark the latest changeset which is free from the problem
516 bad, then mark the latest changeset which is free from the problem
517 as good. Bisect will update your working directory to a revision
517 as good. Bisect will update your working directory to a revision
518 for testing (unless the -U/--noupdate option is specified). Once
518 for testing (unless the -U/--noupdate option is specified). Once
519 you have performed tests, mark the working directory as good or
519 you have performed tests, mark the working directory as good or
520 bad, and bisect will either update to another candidate changeset
520 bad, and bisect will either update to another candidate changeset
521 or announce that it has found the bad revision.
521 or announce that it has found the bad revision.
522
522
523 As a shortcut, you can also use the revision argument to mark a
523 As a shortcut, you can also use the revision argument to mark a
524 revision as good or bad without checking it out first.
524 revision as good or bad without checking it out first.
525
525
526 If you supply a command, it will be used for automatic bisection.
526 If you supply a command, it will be used for automatic bisection.
527 The environment variable HG_NODE will contain the ID of the
527 The environment variable HG_NODE will contain the ID of the
528 changeset being tested. The exit status of the command will be
528 changeset being tested. The exit status of the command will be
529 used to mark revisions as good or bad: status 0 means good, 125
529 used to mark revisions as good or bad: status 0 means good, 125
530 means to skip the revision, 127 (command not found) will abort the
530 means to skip the revision, 127 (command not found) will abort the
531 bisection, and any other non-zero exit status means the revision
531 bisection, and any other non-zero exit status means the revision
532 is bad.
532 is bad.
533
533
534 .. container:: verbose
534 .. container:: verbose
535
535
536 Some examples:
536 Some examples:
537
537
538 - start a bisection with known bad revision 12, and good revision 34::
538 - start a bisection with known bad revision 12, and good revision 34::
539
539
540 hg bisect --bad 34
540 hg bisect --bad 34
541 hg bisect --good 12
541 hg bisect --good 12
542
542
543 - advance the current bisection by marking current revision as good or
543 - advance the current bisection by marking current revision as good or
544 bad::
544 bad::
545
545
546 hg bisect --good
546 hg bisect --good
547 hg bisect --bad
547 hg bisect --bad
548
548
549 - mark the current revision, or a known revision, to be skipped (e.g. if
549 - mark the current revision, or a known revision, to be skipped (e.g. if
550 that revision is not usable because of another issue)::
550 that revision is not usable because of another issue)::
551
551
552 hg bisect --skip
552 hg bisect --skip
553 hg bisect --skip 23
553 hg bisect --skip 23
554
554
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
556
556
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
558
558
559 - forget the current bisection::
559 - forget the current bisection::
560
560
561 hg bisect --reset
561 hg bisect --reset
562
562
563 - use 'make && make tests' to automatically find the first broken
563 - use 'make && make tests' to automatically find the first broken
564 revision::
564 revision::
565
565
566 hg bisect --reset
566 hg bisect --reset
567 hg bisect --bad 34
567 hg bisect --bad 34
568 hg bisect --good 12
568 hg bisect --good 12
569 hg bisect --command 'make && make tests'
569 hg bisect --command 'make && make tests'
570
570
571 - see all changesets whose states are already known in the current
571 - see all changesets whose states are already known in the current
572 bisection::
572 bisection::
573
573
574 hg log -r "bisect(pruned)"
574 hg log -r "bisect(pruned)"
575
575
576 - see the changeset currently being bisected (especially useful
576 - see the changeset currently being bisected (especially useful
577 if running with -U/--noupdate)::
577 if running with -U/--noupdate)::
578
578
579 hg log -r "bisect(current)"
579 hg log -r "bisect(current)"
580
580
581 - see all changesets that took part in the current bisection::
581 - see all changesets that took part in the current bisection::
582
582
583 hg log -r "bisect(range)"
583 hg log -r "bisect(range)"
584
584
585 - with the graphlog extension, you can even get a nice graph::
585 - with the graphlog extension, you can even get a nice graph::
586
586
587 hg log --graph -r "bisect(range)"
587 hg log --graph -r "bisect(range)"
588
588
589 See :hg:`help revsets` for more about the `bisect()` keyword.
589 See :hg:`help revsets` for more about the `bisect()` keyword.
590
590
591 Returns 0 on success.
591 Returns 0 on success.
592 """
592 """
593 def extendbisectrange(nodes, good):
593 def extendbisectrange(nodes, good):
594 # bisect is incomplete when it ends on a merge node and
594 # bisect is incomplete when it ends on a merge node and
595 # one of the parent was not checked.
595 # one of the parent was not checked.
596 parents = repo[nodes[0]].parents()
596 parents = repo[nodes[0]].parents()
597 if len(parents) > 1:
597 if len(parents) > 1:
598 side = good and state['bad'] or state['good']
598 side = good and state['bad'] or state['good']
599 num = len(set(i.node() for i in parents) & set(side))
599 num = len(set(i.node() for i in parents) & set(side))
600 if num == 1:
600 if num == 1:
601 return parents[0].ancestor(parents[1])
601 return parents[0].ancestor(parents[1])
602 return None
602 return None
603
603
604 def print_result(nodes, good):
604 def print_result(nodes, good):
605 displayer = cmdutil.show_changeset(ui, repo, {})
605 displayer = cmdutil.show_changeset(ui, repo, {})
606 if len(nodes) == 1:
606 if len(nodes) == 1:
607 # narrowed it down to a single revision
607 # narrowed it down to a single revision
608 if good:
608 if good:
609 ui.write(_("The first good revision is:\n"))
609 ui.write(_("The first good revision is:\n"))
610 else:
610 else:
611 ui.write(_("The first bad revision is:\n"))
611 ui.write(_("The first bad revision is:\n"))
612 displayer.show(repo[nodes[0]])
612 displayer.show(repo[nodes[0]])
613 extendnode = extendbisectrange(nodes, good)
613 extendnode = extendbisectrange(nodes, good)
614 if extendnode is not None:
614 if extendnode is not None:
615 ui.write(_('Not all ancestors of this changeset have been'
615 ui.write(_('Not all ancestors of this changeset have been'
616 ' checked.\nUse bisect --extend to continue the '
616 ' checked.\nUse bisect --extend to continue the '
617 'bisection from\nthe common ancestor, %s.\n')
617 'bisection from\nthe common ancestor, %s.\n')
618 % extendnode)
618 % extendnode)
619 else:
619 else:
620 # multiple possible revisions
620 # multiple possible revisions
621 if good:
621 if good:
622 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
623 "good revision could be any of:\n"))
623 "good revision could be any of:\n"))
624 else:
624 else:
625 ui.write(_("Due to skipped revisions, the first "
625 ui.write(_("Due to skipped revisions, the first "
626 "bad revision could be any of:\n"))
626 "bad revision could be any of:\n"))
627 for n in nodes:
627 for n in nodes:
628 displayer.show(repo[n])
628 displayer.show(repo[n])
629 displayer.close()
629 displayer.close()
630
630
631 def check_state(state, interactive=True):
631 def check_state(state, interactive=True):
632 if not state['good'] or not state['bad']:
632 if not state['good'] or not state['bad']:
633 if (good or bad or skip or reset) and interactive:
633 if (good or bad or skip or reset) and interactive:
634 return
634 return
635 if not state['good']:
635 if not state['good']:
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
637 else:
637 else:
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
639 return True
639 return True
640
640
641 # backward compatibility
641 # backward compatibility
642 if rev in "good bad reset init".split():
642 if rev in "good bad reset init".split():
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
644 cmd, rev, extra = rev, extra, None
644 cmd, rev, extra = rev, extra, None
645 if cmd == "good":
645 if cmd == "good":
646 good = True
646 good = True
647 elif cmd == "bad":
647 elif cmd == "bad":
648 bad = True
648 bad = True
649 else:
649 else:
650 reset = True
650 reset = True
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
652 raise util.Abort(_('incompatible arguments'))
652 raise util.Abort(_('incompatible arguments'))
653
653
654 if reset:
654 if reset:
655 p = repo.join("bisect.state")
655 p = repo.join("bisect.state")
656 if os.path.exists(p):
656 if os.path.exists(p):
657 os.unlink(p)
657 os.unlink(p)
658 return
658 return
659
659
660 state = hbisect.load_state(repo)
660 state = hbisect.load_state(repo)
661
661
662 if command:
662 if command:
663 changesets = 1
663 changesets = 1
664 try:
664 try:
665 node = state['current'][0]
665 node = state['current'][0]
666 except LookupError:
666 except LookupError:
667 if noupdate:
667 if noupdate:
668 raise util.Abort(_('current bisect revision is unknown - '
668 raise util.Abort(_('current bisect revision is unknown - '
669 'start a new bisect to fix'))
669 'start a new bisect to fix'))
670 node, p2 = repo.dirstate.parents()
670 node, p2 = repo.dirstate.parents()
671 if p2 != nullid:
671 if p2 != nullid:
672 raise util.Abort(_('current bisect revision is a merge'))
672 raise util.Abort(_('current bisect revision is a merge'))
673 try:
673 try:
674 while changesets:
674 while changesets:
675 # update state
675 # update state
676 state['current'] = [node]
676 state['current'] = [node]
677 hbisect.save_state(repo, state)
677 hbisect.save_state(repo, state)
678 status = util.system(command,
678 status = util.system(command,
679 environ={'HG_NODE': hex(node)},
679 environ={'HG_NODE': hex(node)},
680 out=ui.fout)
680 out=ui.fout)
681 if status == 125:
681 if status == 125:
682 transition = "skip"
682 transition = "skip"
683 elif status == 0:
683 elif status == 0:
684 transition = "good"
684 transition = "good"
685 # status < 0 means process was killed
685 # status < 0 means process was killed
686 elif status == 127:
686 elif status == 127:
687 raise util.Abort(_("failed to execute %s") % command)
687 raise util.Abort(_("failed to execute %s") % command)
688 elif status < 0:
688 elif status < 0:
689 raise util.Abort(_("%s killed") % command)
689 raise util.Abort(_("%s killed") % command)
690 else:
690 else:
691 transition = "bad"
691 transition = "bad"
692 ctx = scmutil.revsingle(repo, rev, node)
692 ctx = scmutil.revsingle(repo, rev, node)
693 rev = None # clear for future iterations
693 rev = None # clear for future iterations
694 state[transition].append(ctx.node())
694 state[transition].append(ctx.node())
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
696 check_state(state, interactive=False)
696 check_state(state, interactive=False)
697 # bisect
697 # bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 # update to next check
699 # update to next check
700 node = nodes[0]
700 node = nodes[0]
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 hg.clean(repo, node, show_stats=False)
703 hg.clean(repo, node, show_stats=False)
704 finally:
704 finally:
705 state['current'] = [node]
705 state['current'] = [node]
706 hbisect.save_state(repo, state)
706 hbisect.save_state(repo, state)
707 print_result(nodes, good)
707 print_result(nodes, good)
708 return
708 return
709
709
710 # update state
710 # update state
711
711
712 if rev:
712 if rev:
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
714 else:
714 else:
715 nodes = [repo.lookup('.')]
715 nodes = [repo.lookup('.')]
716
716
717 if good or bad or skip:
717 if good or bad or skip:
718 if good:
718 if good:
719 state['good'] += nodes
719 state['good'] += nodes
720 elif bad:
720 elif bad:
721 state['bad'] += nodes
721 state['bad'] += nodes
722 elif skip:
722 elif skip:
723 state['skip'] += nodes
723 state['skip'] += nodes
724 hbisect.save_state(repo, state)
724 hbisect.save_state(repo, state)
725
725
726 if not check_state(state):
726 if not check_state(state):
727 return
727 return
728
728
729 # actually bisect
729 # actually bisect
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
731 if extend:
731 if extend:
732 if not changesets:
732 if not changesets:
733 extendnode = extendbisectrange(nodes, good)
733 extendnode = extendbisectrange(nodes, good)
734 if extendnode is not None:
734 if extendnode is not None:
735 ui.write(_("Extending search to changeset %d:%s\n"
735 ui.write(_("Extending search to changeset %d:%s\n"
736 % (extendnode.rev(), extendnode)))
736 % (extendnode.rev(), extendnode)))
737 state['current'] = [extendnode.node()]
737 state['current'] = [extendnode.node()]
738 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
739 if noupdate:
739 if noupdate:
740 return
740 return
741 cmdutil.bailifchanged(repo)
741 cmdutil.bailifchanged(repo)
742 return hg.clean(repo, extendnode.node())
742 return hg.clean(repo, extendnode.node())
743 raise util.Abort(_("nothing to extend"))
743 raise util.Abort(_("nothing to extend"))
744
744
745 if changesets == 0:
745 if changesets == 0:
746 print_result(nodes, good)
746 print_result(nodes, good)
747 else:
747 else:
748 assert len(nodes) == 1 # only a single node can be tested next
748 assert len(nodes) == 1 # only a single node can be tested next
749 node = nodes[0]
749 node = nodes[0]
750 # compute the approximate number of remaining tests
750 # compute the approximate number of remaining tests
751 tests, size = 0, 2
751 tests, size = 0, 2
752 while size <= changesets:
752 while size <= changesets:
753 tests, size = tests + 1, size * 2
753 tests, size = tests + 1, size * 2
754 rev = repo.changelog.rev(node)
754 rev = repo.changelog.rev(node)
755 ui.write(_("Testing changeset %d:%s "
755 ui.write(_("Testing changeset %d:%s "
756 "(%d changesets remaining, ~%d tests)\n")
756 "(%d changesets remaining, ~%d tests)\n")
757 % (rev, short(node), changesets, tests))
757 % (rev, short(node), changesets, tests))
758 state['current'] = [node]
758 state['current'] = [node]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if not noupdate:
760 if not noupdate:
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, node)
762 return hg.clean(repo, node)
763
763
764 @command('bookmarks|bookmark',
764 @command('bookmarks|bookmark',
765 [('f', 'force', False, _('force')),
765 [('f', 'force', False, _('force')),
766 ('r', 'rev', '', _('revision'), _('REV')),
766 ('r', 'rev', '', _('revision'), _('REV')),
767 ('d', 'delete', False, _('delete a given bookmark')),
767 ('d', 'delete', False, _('delete a given bookmark')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
772 rename=None, inactive=False):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
773 '''track a line of development with movable markers
774
774
775 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
776 Bookmarks are local. They can be renamed, copied and deleted. It is
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
778 :hg:`update NAME` to update to a given bookmark.
779
779
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
781 directory's parent revision with the given name. If you specify
781 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
782 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
783 the bookmark is assigned to that revision.
784
784
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
786 push` and :hg:`help pull`). This requires both the local and remote
787 repositories to support bookmarks. For versions prior to 1.8, this means
787 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
788 the bookmarks extension must be enabled.
789
789
790 If you set a bookmark called '@', new clones of the repository will
790 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
791 have that revision checked out (and the bookmark made active) by
792 default.
792 default.
793
793
794 With -i/--inactive, the new bookmark will not be made the active
794 With -i/--inactive, the new bookmark will not be made the active
795 bookmark. If -r/--rev is given, the new bookmark will not be made
795 bookmark. If -r/--rev is given, the new bookmark will not be made
796 active even if -i/--inactive is not given. If no NAME is given, the
796 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
797 current active bookmark will be marked inactive.
798 '''
798 '''
799 hexfn = ui.debugflag and hex or short
799 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
800 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
801 cur = repo.changectx('.').node()
802
802
803 def checkformat(mark):
803 def checkformat(mark):
804 mark = mark.strip()
804 mark = mark.strip()
805 if not mark:
805 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
806 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
807 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
808 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
809 return mark
810
810
811 def checkconflict(repo, mark, force=False, target=None):
811 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
812 if mark in marks and not force:
813 if target:
813 if target:
814 if marks[mark] == target and target == cur:
814 if marks[mark] == target and target == cur:
815 # re-activating a bookmark
815 # re-activating a bookmark
816 return
816 return
817 anc = repo.changelog.ancestors([repo[target].rev()])
817 anc = repo.changelog.ancestors([repo[target].rev()])
818 bmctx = repo[marks[mark]]
818 bmctx = repo[marks[mark]]
819 if bmctx.rev() in anc:
819 if bmctx.rev() in anc:
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
821 (mark, short(bmctx.node())))
821 (mark, short(bmctx.node())))
822 return
822 return
823 raise util.Abort(_("bookmark '%s' already exists "
823 raise util.Abort(_("bookmark '%s' already exists "
824 "(use -f to force)") % mark)
824 "(use -f to force)") % mark)
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
826 and not force):
826 and not force):
827 raise util.Abort(
827 raise util.Abort(
828 _("a bookmark cannot have the name of an existing branch"))
828 _("a bookmark cannot have the name of an existing branch"))
829
829
830 if delete and rename:
830 if delete and rename:
831 raise util.Abort(_("--delete and --rename are incompatible"))
831 raise util.Abort(_("--delete and --rename are incompatible"))
832 if delete and rev:
832 if delete and rev:
833 raise util.Abort(_("--rev is incompatible with --delete"))
833 raise util.Abort(_("--rev is incompatible with --delete"))
834 if rename and rev:
834 if rename and rev:
835 raise util.Abort(_("--rev is incompatible with --rename"))
835 raise util.Abort(_("--rev is incompatible with --rename"))
836 if mark is None and (delete or rev):
836 if mark is None and (delete or rev):
837 raise util.Abort(_("bookmark name required"))
837 raise util.Abort(_("bookmark name required"))
838
838
839 if delete:
839 if delete:
840 if mark not in marks:
840 if mark not in marks:
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
842 if mark == repo._bookmarkcurrent:
842 if mark == repo._bookmarkcurrent:
843 bookmarks.setcurrent(repo, None)
843 bookmarks.setcurrent(repo, None)
844 del marks[mark]
844 del marks[mark]
845 marks.write()
845 marks.write()
846
846
847 elif rename:
847 elif rename:
848 if mark is None:
848 if mark is None:
849 raise util.Abort(_("new bookmark name required"))
849 raise util.Abort(_("new bookmark name required"))
850 mark = checkformat(mark)
850 mark = checkformat(mark)
851 if rename not in marks:
851 if rename not in marks:
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
853 checkconflict(repo, mark, force)
853 checkconflict(repo, mark, force)
854 marks[mark] = marks[rename]
854 marks[mark] = marks[rename]
855 if repo._bookmarkcurrent == rename and not inactive:
855 if repo._bookmarkcurrent == rename and not inactive:
856 bookmarks.setcurrent(repo, mark)
856 bookmarks.setcurrent(repo, mark)
857 del marks[rename]
857 del marks[rename]
858 marks.write()
858 marks.write()
859
859
860 elif mark is not None:
860 elif mark is not None:
861 mark = checkformat(mark)
861 mark = checkformat(mark)
862 if inactive and mark == repo._bookmarkcurrent:
862 if inactive and mark == repo._bookmarkcurrent:
863 bookmarks.setcurrent(repo, None)
863 bookmarks.setcurrent(repo, None)
864 return
864 return
865 tgt = cur
865 tgt = cur
866 if rev:
866 if rev:
867 tgt = scmutil.revsingle(repo, rev).node()
867 tgt = scmutil.revsingle(repo, rev).node()
868 checkconflict(repo, mark, force, tgt)
868 checkconflict(repo, mark, force, tgt)
869 marks[mark] = tgt
869 marks[mark] = tgt
870 if not inactive and cur == marks[mark]:
870 if not inactive and cur == marks[mark]:
871 bookmarks.setcurrent(repo, mark)
871 bookmarks.setcurrent(repo, mark)
872 elif cur != tgt and mark == repo._bookmarkcurrent:
872 elif cur != tgt and mark == repo._bookmarkcurrent:
873 bookmarks.setcurrent(repo, None)
873 bookmarks.setcurrent(repo, None)
874 marks.write()
874 marks.write()
875
875
876 # Same message whether trying to deactivate the current bookmark (-i
876 # Same message whether trying to deactivate the current bookmark (-i
877 # with no NAME) or listing bookmarks
877 # with no NAME) or listing bookmarks
878 elif len(marks) == 0:
878 elif len(marks) == 0:
879 ui.status(_("no bookmarks set\n"))
879 ui.status(_("no bookmarks set\n"))
880
880
881 elif inactive:
881 elif inactive:
882 if not repo._bookmarkcurrent:
882 if not repo._bookmarkcurrent:
883 ui.status(_("no active bookmark\n"))
883 ui.status(_("no active bookmark\n"))
884 else:
884 else:
885 bookmarks.setcurrent(repo, None)
885 bookmarks.setcurrent(repo, None)
886
886
887 else: # show bookmarks
887 else: # show bookmarks
888 for bmark, n in sorted(marks.iteritems()):
888 for bmark, n in sorted(marks.iteritems()):
889 current = repo._bookmarkcurrent
889 current = repo._bookmarkcurrent
890 if bmark == current:
890 if bmark == current:
891 prefix, label = '*', 'bookmarks.current'
891 prefix, label = '*', 'bookmarks.current'
892 else:
892 else:
893 prefix, label = ' ', ''
893 prefix, label = ' ', ''
894
894
895 if ui.quiet:
895 if ui.quiet:
896 ui.write("%s\n" % bmark, label=label)
896 ui.write("%s\n" % bmark, label=label)
897 else:
897 else:
898 ui.write(" %s %-25s %d:%s\n" % (
898 ui.write(" %s %-25s %d:%s\n" % (
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
900 label=label)
900 label=label)
901
901
902 @command('branch',
902 @command('branch',
903 [('f', 'force', None,
903 [('f', 'force', None,
904 _('set branch name even if it shadows an existing branch')),
904 _('set branch name even if it shadows an existing branch')),
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
906 _('[-fC] [NAME]'))
906 _('[-fC] [NAME]'))
907 def branch(ui, repo, label=None, **opts):
907 def branch(ui, repo, label=None, **opts):
908 """set or show the current branch name
908 """set or show the current branch name
909
909
910 .. note::
910 .. note::
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
912 light-weight bookmark instead. See :hg:`help glossary` for more
912 light-weight bookmark instead. See :hg:`help glossary` for more
913 information about named branches and bookmarks.
913 information about named branches and bookmarks.
914
914
915 With no argument, show the current branch name. With one argument,
915 With no argument, show the current branch name. With one argument,
916 set the working directory branch name (the branch will not exist
916 set the working directory branch name (the branch will not exist
917 in the repository until the next commit). Standard practice
917 in the repository until the next commit). Standard practice
918 recommends that primary development take place on the 'default'
918 recommends that primary development take place on the 'default'
919 branch.
919 branch.
920
920
921 Unless -f/--force is specified, branch will not let you set a
921 Unless -f/--force is specified, branch will not let you set a
922 branch name that already exists, even if it's inactive.
922 branch name that already exists, even if it's inactive.
923
923
924 Use -C/--clean to reset the working directory branch to that of
924 Use -C/--clean to reset the working directory branch to that of
925 the parent of the working directory, negating a previous branch
925 the parent of the working directory, negating a previous branch
926 change.
926 change.
927
927
928 Use the command :hg:`update` to switch to an existing branch. Use
928 Use the command :hg:`update` to switch to an existing branch. Use
929 :hg:`commit --close-branch` to mark this branch as closed.
929 :hg:`commit --close-branch` to mark this branch as closed.
930
930
931 Returns 0 on success.
931 Returns 0 on success.
932 """
932 """
933 if not opts.get('clean') and not label:
933 if not opts.get('clean') and not label:
934 ui.write("%s\n" % repo.dirstate.branch())
934 ui.write("%s\n" % repo.dirstate.branch())
935 return
935 return
936
936
937 wlock = repo.wlock()
937 wlock = repo.wlock()
938 try:
938 try:
939 if opts.get('clean'):
939 if opts.get('clean'):
940 label = repo[None].p1().branch()
940 label = repo[None].p1().branch()
941 repo.dirstate.setbranch(label)
941 repo.dirstate.setbranch(label)
942 ui.status(_('reset working directory to branch %s\n') % label)
942 ui.status(_('reset working directory to branch %s\n') % label)
943 elif label:
943 elif label:
944 if not opts.get('force') and label in repo.branchmap():
944 if not opts.get('force') and label in repo.branchmap():
945 if label not in [p.branch() for p in repo.parents()]:
945 if label not in [p.branch() for p in repo.parents()]:
946 raise util.Abort(_('a branch of the same name already'
946 raise util.Abort(_('a branch of the same name already'
947 ' exists'),
947 ' exists'),
948 # i18n: "it" refers to an existing branch
948 # i18n: "it" refers to an existing branch
949 hint=_("use 'hg update' to switch to it"))
949 hint=_("use 'hg update' to switch to it"))
950 scmutil.checknewlabel(repo, label, 'branch')
950 scmutil.checknewlabel(repo, label, 'branch')
951 repo.dirstate.setbranch(label)
951 repo.dirstate.setbranch(label)
952 ui.status(_('marked working directory as branch %s\n') % label)
952 ui.status(_('marked working directory as branch %s\n') % label)
953 ui.status(_('(branches are permanent and global, '
953 ui.status(_('(branches are permanent and global, '
954 'did you want a bookmark?)\n'))
954 'did you want a bookmark?)\n'))
955 finally:
955 finally:
956 wlock.release()
956 wlock.release()
957
957
958 @command('branches',
958 @command('branches',
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
960 ('c', 'closed', False, _('show normal and closed branches'))],
960 ('c', 'closed', False, _('show normal and closed branches'))],
961 _('[-ac]'))
961 _('[-ac]'))
962 def branches(ui, repo, active=False, closed=False):
962 def branches(ui, repo, active=False, closed=False):
963 """list repository named branches
963 """list repository named branches
964
964
965 List the repository's named branches, indicating which ones are
965 List the repository's named branches, indicating which ones are
966 inactive. If -c/--closed is specified, also list branches which have
966 inactive. If -c/--closed is specified, also list branches which have
967 been marked closed (see :hg:`commit --close-branch`).
967 been marked closed (see :hg:`commit --close-branch`).
968
968
969 If -a/--active is specified, only show active branches. A branch
969 If -a/--active is specified, only show active branches. A branch
970 is considered active if it contains repository heads.
970 is considered active if it contains repository heads.
971
971
972 Use the command :hg:`update` to switch to an existing branch.
972 Use the command :hg:`update` to switch to an existing branch.
973
973
974 Returns 0.
974 Returns 0.
975 """
975 """
976
976
977 hexfunc = ui.debugflag and hex or short
977 hexfunc = ui.debugflag and hex or short
978
978
979 activebranches = set([repo[n].branch() for n in repo.heads()])
979 activebranches = set([repo[n].branch() for n in repo.heads()])
980 branches = []
980 branches = []
981 for tag, heads in repo.branchmap().iteritems():
981 for tag, heads in repo.branchmap().iteritems():
982 for h in reversed(heads):
982 for h in reversed(heads):
983 ctx = repo[h]
983 ctx = repo[h]
984 isopen = not ctx.closesbranch()
984 isopen = not ctx.closesbranch()
985 if isopen:
985 if isopen:
986 tip = ctx
986 tip = ctx
987 break
987 break
988 else:
988 else:
989 tip = repo[heads[-1]]
989 tip = repo[heads[-1]]
990 isactive = tag in activebranches and isopen
990 isactive = tag in activebranches and isopen
991 branches.append((tip, isactive, isopen))
991 branches.append((tip, isactive, isopen))
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
993 reverse=True)
993 reverse=True)
994
994
995 for ctx, isactive, isopen in branches:
995 for ctx, isactive, isopen in branches:
996 if (not active) or isactive:
996 if (not active) or isactive:
997 if isactive:
997 if isactive:
998 label = 'branches.active'
998 label = 'branches.active'
999 notice = ''
999 notice = ''
1000 elif not isopen:
1000 elif not isopen:
1001 if not closed:
1001 if not closed:
1002 continue
1002 continue
1003 label = 'branches.closed'
1003 label = 'branches.closed'
1004 notice = _(' (closed)')
1004 notice = _(' (closed)')
1005 else:
1005 else:
1006 label = 'branches.inactive'
1006 label = 'branches.inactive'
1007 notice = _(' (inactive)')
1007 notice = _(' (inactive)')
1008 if ctx.branch() == repo.dirstate.branch():
1008 if ctx.branch() == repo.dirstate.branch():
1009 label = 'branches.current'
1009 label = 'branches.current'
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1012 'log.changeset changeset.%s' % ctx.phasestr())
1012 'log.changeset changeset.%s' % ctx.phasestr())
1013 tag = ui.label(ctx.branch(), label)
1013 tag = ui.label(ctx.branch(), label)
1014 if ui.quiet:
1014 if ui.quiet:
1015 ui.write("%s\n" % tag)
1015 ui.write("%s\n" % tag)
1016 else:
1016 else:
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1018
1018
1019 @command('bundle',
1019 @command('bundle',
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1022 _('REV')),
1022 _('REV')),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1024 _('BRANCH')),
1024 _('BRANCH')),
1025 ('', 'base', [],
1025 ('', 'base', [],
1026 _('a base changeset assumed to be available at the destination'),
1026 _('a base changeset assumed to be available at the destination'),
1027 _('REV')),
1027 _('REV')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1030 ] + remoteopts,
1030 ] + remoteopts,
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1032 def bundle(ui, repo, fname, dest=None, **opts):
1032 def bundle(ui, repo, fname, dest=None, **opts):
1033 """create a changegroup file
1033 """create a changegroup file
1034
1034
1035 Generate a compressed changegroup file collecting changesets not
1035 Generate a compressed changegroup file collecting changesets not
1036 known to be in another repository.
1036 known to be in another repository.
1037
1037
1038 If you omit the destination repository, then hg assumes the
1038 If you omit the destination repository, then hg assumes the
1039 destination will have all the nodes you specify with --base
1039 destination will have all the nodes you specify with --base
1040 parameters. To create a bundle containing all changesets, use
1040 parameters. To create a bundle containing all changesets, use
1041 -a/--all (or --base null).
1041 -a/--all (or --base null).
1042
1042
1043 You can change compression method with the -t/--type option.
1043 You can change compression method with the -t/--type option.
1044 The available compression methods are: none, bzip2, and
1044 The available compression methods are: none, bzip2, and
1045 gzip (by default, bundles are compressed using bzip2).
1045 gzip (by default, bundles are compressed using bzip2).
1046
1046
1047 The bundle file can then be transferred using conventional means
1047 The bundle file can then be transferred using conventional means
1048 and applied to another repository with the unbundle or pull
1048 and applied to another repository with the unbundle or pull
1049 command. This is useful when direct push and pull are not
1049 command. This is useful when direct push and pull are not
1050 available or when exporting an entire repository is undesirable.
1050 available or when exporting an entire repository is undesirable.
1051
1051
1052 Applying bundles preserves all changeset contents including
1052 Applying bundles preserves all changeset contents including
1053 permissions, copy/rename information, and revision history.
1053 permissions, copy/rename information, and revision history.
1054
1054
1055 Returns 0 on success, 1 if no changes found.
1055 Returns 0 on success, 1 if no changes found.
1056 """
1056 """
1057 revs = None
1057 revs = None
1058 if 'rev' in opts:
1058 if 'rev' in opts:
1059 revs = scmutil.revrange(repo, opts['rev'])
1059 revs = scmutil.revrange(repo, opts['rev'])
1060
1060
1061 bundletype = opts.get('type', 'bzip2').lower()
1061 bundletype = opts.get('type', 'bzip2').lower()
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1063 bundletype = btypes.get(bundletype)
1063 bundletype = btypes.get(bundletype)
1064 if bundletype not in changegroup.bundletypes:
1064 if bundletype not in changegroup.bundletypes:
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1066
1066
1067 if opts.get('all'):
1067 if opts.get('all'):
1068 base = ['null']
1068 base = ['null']
1069 else:
1069 else:
1070 base = scmutil.revrange(repo, opts.get('base'))
1070 base = scmutil.revrange(repo, opts.get('base'))
1071 if base:
1071 if base:
1072 if dest:
1072 if dest:
1073 raise util.Abort(_("--base is incompatible with specifying "
1073 raise util.Abort(_("--base is incompatible with specifying "
1074 "a destination"))
1074 "a destination"))
1075 common = [repo.lookup(rev) for rev in base]
1075 common = [repo.lookup(rev) for rev in base]
1076 heads = revs and map(repo.lookup, revs) or revs
1076 heads = revs and map(repo.lookup, revs) or revs
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1078 outgoing = None
1078 outgoing = None
1079 else:
1079 else:
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1082 other = hg.peer(repo, opts, dest)
1082 other = hg.peer(repo, opts, dest)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1084 heads = revs and map(repo.lookup, revs) or revs
1084 heads = revs and map(repo.lookup, revs) or revs
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1086 onlyheads=heads,
1086 onlyheads=heads,
1087 force=opts.get('force'),
1087 force=opts.get('force'),
1088 portable=True)
1088 portable=True)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1090 if not cg:
1090 if not cg:
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1092 return 1
1092 return 1
1093
1093
1094 changegroup.writebundle(cg, fname, bundletype)
1094 changegroup.writebundle(cg, fname, bundletype)
1095
1095
1096 @command('cat',
1096 @command('cat',
1097 [('o', 'output', '',
1097 [('o', 'output', '',
1098 _('print output to file with formatted name'), _('FORMAT')),
1098 _('print output to file with formatted name'), _('FORMAT')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1101 ] + walkopts,
1101 ] + walkopts,
1102 _('[OPTION]... FILE...'))
1102 _('[OPTION]... FILE...'))
1103 def cat(ui, repo, file1, *pats, **opts):
1103 def cat(ui, repo, file1, *pats, **opts):
1104 """output the current or given revision of files
1104 """output the current or given revision of files
1105
1105
1106 Print the specified files as they were at the given revision. If
1106 Print the specified files as they were at the given revision. If
1107 no revision is given, the parent of the working directory is used,
1107 no revision is given, the parent of the working directory is used,
1108 or tip if no revision is checked out.
1108 or tip if no revision is checked out.
1109
1109
1110 Output may be to a file, in which case the name of the file is
1110 Output may be to a file, in which case the name of the file is
1111 given using a format string. The formatting rules are the same as
1111 given using a format string. The formatting rules are the same as
1112 for the export command, with the following additions:
1112 for the export command, with the following additions:
1113
1113
1114 :``%s``: basename of file being printed
1114 :``%s``: basename of file being printed
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1116 :``%p``: root-relative path name of file being printed
1116 :``%p``: root-relative path name of file being printed
1117
1117
1118 Returns 0 on success.
1118 Returns 0 on success.
1119 """
1119 """
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1121 err = 1
1121 err = 1
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1123 for abs in ctx.walk(m):
1123 for abs in ctx.walk(m):
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1125 pathname=abs)
1125 pathname=abs)
1126 data = ctx[abs].data()
1126 data = ctx[abs].data()
1127 if opts.get('decode'):
1127 if opts.get('decode'):
1128 data = repo.wwritedata(abs, data)
1128 data = repo.wwritedata(abs, data)
1129 fp.write(data)
1129 fp.write(data)
1130 fp.close()
1130 fp.close()
1131 err = 0
1131 err = 0
1132 return err
1132 return err
1133
1133
1134 @command('^clone',
1134 @command('^clone',
1135 [('U', 'noupdate', None,
1135 [('U', 'noupdate', None,
1136 _('the clone will include an empty working copy (only a repository)')),
1136 _('the clone will include an empty working copy (only a repository)')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1142 ] + remoteopts,
1142 ] + remoteopts,
1143 _('[OPTION]... SOURCE [DEST]'))
1143 _('[OPTION]... SOURCE [DEST]'))
1144 def clone(ui, source, dest=None, **opts):
1144 def clone(ui, source, dest=None, **opts):
1145 """make a copy of an existing repository
1145 """make a copy of an existing repository
1146
1146
1147 Create a copy of an existing repository in a new directory.
1147 Create a copy of an existing repository in a new directory.
1148
1148
1149 If no destination directory name is specified, it defaults to the
1149 If no destination directory name is specified, it defaults to the
1150 basename of the source.
1150 basename of the source.
1151
1151
1152 The location of the source is added to the new repository's
1152 The location of the source is added to the new repository's
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1154
1154
1155 Only local paths and ``ssh://`` URLs are supported as
1155 Only local paths and ``ssh://`` URLs are supported as
1156 destinations. For ``ssh://`` destinations, no working directory or
1156 destinations. For ``ssh://`` destinations, no working directory or
1157 ``.hg/hgrc`` will be created on the remote side.
1157 ``.hg/hgrc`` will be created on the remote side.
1158
1158
1159 To pull only a subset of changesets, specify one or more revisions
1159 To pull only a subset of changesets, specify one or more revisions
1160 identifiers with -r/--rev or branches with -b/--branch. The
1160 identifiers with -r/--rev or branches with -b/--branch. The
1161 resulting clone will contain only the specified changesets and
1161 resulting clone will contain only the specified changesets and
1162 their ancestors. These options (or 'clone src#rev dest') imply
1162 their ancestors. These options (or 'clone src#rev dest') imply
1163 --pull, even for local source repositories. Note that specifying a
1163 --pull, even for local source repositories. Note that specifying a
1164 tag will include the tagged changeset but not the changeset
1164 tag will include the tagged changeset but not the changeset
1165 containing the tag.
1165 containing the tag.
1166
1166
1167 If the source repository has a bookmark called '@' set, that
1167 If the source repository has a bookmark called '@' set, that
1168 revision will be checked out in the new repository by default.
1168 revision will be checked out in the new repository by default.
1169
1169
1170 To check out a particular version, use -u/--update, or
1170 To check out a particular version, use -u/--update, or
1171 -U/--noupdate to create a clone with no working directory.
1171 -U/--noupdate to create a clone with no working directory.
1172
1172
1173 .. container:: verbose
1173 .. container:: verbose
1174
1174
1175 For efficiency, hardlinks are used for cloning whenever the
1175 For efficiency, hardlinks are used for cloning whenever the
1176 source and destination are on the same filesystem (note this
1176 source and destination are on the same filesystem (note this
1177 applies only to the repository data, not to the working
1177 applies only to the repository data, not to the working
1178 directory). Some filesystems, such as AFS, implement hardlinking
1178 directory). Some filesystems, such as AFS, implement hardlinking
1179 incorrectly, but do not report errors. In these cases, use the
1179 incorrectly, but do not report errors. In these cases, use the
1180 --pull option to avoid hardlinking.
1180 --pull option to avoid hardlinking.
1181
1181
1182 In some cases, you can clone repositories and the working
1182 In some cases, you can clone repositories and the working
1183 directory using full hardlinks with ::
1183 directory using full hardlinks with ::
1184
1184
1185 $ cp -al REPO REPOCLONE
1185 $ cp -al REPO REPOCLONE
1186
1186
1187 This is the fastest way to clone, but it is not always safe. The
1187 This is the fastest way to clone, but it is not always safe. The
1188 operation is not atomic (making sure REPO is not modified during
1188 operation is not atomic (making sure REPO is not modified during
1189 the operation is up to you) and you have to make sure your
1189 the operation is up to you) and you have to make sure your
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1191 so). Also, this is not compatible with certain extensions that
1191 so). Also, this is not compatible with certain extensions that
1192 place their metadata under the .hg directory, such as mq.
1192 place their metadata under the .hg directory, such as mq.
1193
1193
1194 Mercurial will update the working directory to the first applicable
1194 Mercurial will update the working directory to the first applicable
1195 revision from this list:
1195 revision from this list:
1196
1196
1197 a) null if -U or the source repository has no changesets
1197 a) null if -U or the source repository has no changesets
1198 b) if -u . and the source repository is local, the first parent of
1198 b) if -u . and the source repository is local, the first parent of
1199 the source repository's working directory
1199 the source repository's working directory
1200 c) the changeset specified with -u (if a branch name, this means the
1200 c) the changeset specified with -u (if a branch name, this means the
1201 latest head of that branch)
1201 latest head of that branch)
1202 d) the changeset specified with -r
1202 d) the changeset specified with -r
1203 e) the tipmost head specified with -b
1203 e) the tipmost head specified with -b
1204 f) the tipmost head specified with the url#branch source syntax
1204 f) the tipmost head specified with the url#branch source syntax
1205 g) the revision marked with the '@' bookmark, if present
1205 g) the revision marked with the '@' bookmark, if present
1206 h) the tipmost head of the default branch
1206 h) the tipmost head of the default branch
1207 i) tip
1207 i) tip
1208
1208
1209 Examples:
1209 Examples:
1210
1210
1211 - clone a remote repository to a new directory named hg/::
1211 - clone a remote repository to a new directory named hg/::
1212
1212
1213 hg clone http://selenic.com/hg
1213 hg clone http://selenic.com/hg
1214
1214
1215 - create a lightweight local clone::
1215 - create a lightweight local clone::
1216
1216
1217 hg clone project/ project-feature/
1217 hg clone project/ project-feature/
1218
1218
1219 - clone from an absolute path on an ssh server (note double-slash)::
1219 - clone from an absolute path on an ssh server (note double-slash)::
1220
1220
1221 hg clone ssh://user@server//home/projects/alpha/
1221 hg clone ssh://user@server//home/projects/alpha/
1222
1222
1223 - do a high-speed clone over a LAN while checking out a
1223 - do a high-speed clone over a LAN while checking out a
1224 specified version::
1224 specified version::
1225
1225
1226 hg clone --uncompressed http://server/repo -u 1.5
1226 hg clone --uncompressed http://server/repo -u 1.5
1227
1227
1228 - create a repository without changesets after a particular revision::
1228 - create a repository without changesets after a particular revision::
1229
1229
1230 hg clone -r 04e544 experimental/ good/
1230 hg clone -r 04e544 experimental/ good/
1231
1231
1232 - clone (and track) a particular named branch::
1232 - clone (and track) a particular named branch::
1233
1233
1234 hg clone http://selenic.com/hg#stable
1234 hg clone http://selenic.com/hg#stable
1235
1235
1236 See :hg:`help urls` for details on specifying URLs.
1236 See :hg:`help urls` for details on specifying URLs.
1237
1237
1238 Returns 0 on success.
1238 Returns 0 on success.
1239 """
1239 """
1240 if opts.get('noupdate') and opts.get('updaterev'):
1240 if opts.get('noupdate') and opts.get('updaterev'):
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1242
1242
1243 r = hg.clone(ui, opts, source, dest,
1243 r = hg.clone(ui, opts, source, dest,
1244 pull=opts.get('pull'),
1244 pull=opts.get('pull'),
1245 stream=opts.get('uncompressed'),
1245 stream=opts.get('uncompressed'),
1246 rev=opts.get('rev'),
1246 rev=opts.get('rev'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1248 branch=opts.get('branch'))
1248 branch=opts.get('branch'))
1249
1249
1250 return r is None
1250 return r is None
1251
1251
1252 @command('^commit|ci',
1252 @command('^commit|ci',
1253 [('A', 'addremove', None,
1253 [('A', 'addremove', None,
1254 _('mark new/missing files as added/removed before committing')),
1254 _('mark new/missing files as added/removed before committing')),
1255 ('', 'close-branch', None,
1255 ('', 'close-branch', None,
1256 _('mark a branch as closed, hiding it from the branch list')),
1256 _('mark a branch as closed, hiding it from the branch list')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1259 _('[OPTION]... [FILE]...'))
1259 _('[OPTION]... [FILE]...'))
1260 def commit(ui, repo, *pats, **opts):
1260 def commit(ui, repo, *pats, **opts):
1261 """commit the specified files or all outstanding changes
1261 """commit the specified files or all outstanding changes
1262
1262
1263 Commit changes to the given files into the repository. Unlike a
1263 Commit changes to the given files into the repository. Unlike a
1264 centralized SCM, this operation is a local operation. See
1264 centralized SCM, this operation is a local operation. See
1265 :hg:`push` for a way to actively distribute your changes.
1265 :hg:`push` for a way to actively distribute your changes.
1266
1266
1267 If a list of files is omitted, all changes reported by :hg:`status`
1267 If a list of files is omitted, all changes reported by :hg:`status`
1268 will be committed.
1268 will be committed.
1269
1269
1270 If you are committing the result of a merge, do not provide any
1270 If you are committing the result of a merge, do not provide any
1271 filenames or -I/-X filters.
1271 filenames or -I/-X filters.
1272
1272
1273 If no commit message is specified, Mercurial starts your
1273 If no commit message is specified, Mercurial starts your
1274 configured editor where you can enter a message. In case your
1274 configured editor where you can enter a message. In case your
1275 commit fails, you will find a backup of your message in
1275 commit fails, you will find a backup of your message in
1276 ``.hg/last-message.txt``.
1276 ``.hg/last-message.txt``.
1277
1277
1278 The --amend flag can be used to amend the parent of the
1278 The --amend flag can be used to amend the parent of the
1279 working directory with a new commit that contains the changes
1279 working directory with a new commit that contains the changes
1280 in the parent in addition to those currently reported by :hg:`status`,
1280 in the parent in addition to those currently reported by :hg:`status`,
1281 if there are any. The old commit is stored in a backup bundle in
1281 if there are any. The old commit is stored in a backup bundle in
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1283 on how to restore it).
1283 on how to restore it).
1284
1284
1285 Message, user and date are taken from the amended commit unless
1285 Message, user and date are taken from the amended commit unless
1286 specified. When a message isn't specified on the command line,
1286 specified. When a message isn't specified on the command line,
1287 the editor will open with the message of the amended commit.
1287 the editor will open with the message of the amended commit.
1288
1288
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1290 or changesets that have children.
1290 or changesets that have children.
1291
1291
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1293
1293
1294 Returns 0 on success, 1 if nothing changed.
1294 Returns 0 on success, 1 if nothing changed.
1295 """
1295 """
1296 if opts.get('subrepos'):
1296 if opts.get('subrepos'):
1297 # Let --subrepos on the command line override config setting.
1297 # Let --subrepos on the command line override config setting.
1298 ui.setconfig('ui', 'commitsubrepos', True)
1298 ui.setconfig('ui', 'commitsubrepos', True)
1299
1299
1300 extra = {}
1300 extra = {}
1301 if opts.get('close_branch'):
1301 if opts.get('close_branch'):
1302 extra['close'] = 1
1302 extra['close'] = 1
1303
1303
1304 branch = repo[None].branch()
1304 branch = repo[None].branch()
1305 bheads = repo.branchheads(branch)
1305 bheads = repo.branchheads(branch)
1306
1306
1307 if opts.get('amend'):
1307 if opts.get('amend'):
1308 if ui.configbool('ui', 'commitsubrepos'):
1308 if ui.configbool('ui', 'commitsubrepos'):
1309 raise util.Abort(_('cannot amend recursively'))
1309 raise util.Abort(_('cannot amend recursively'))
1310
1310
1311 old = repo['.']
1311 old = repo['.']
1312 if old.phase() == phases.public:
1312 if old.phase() == phases.public:
1313 raise util.Abort(_('cannot amend public changesets'))
1313 raise util.Abort(_('cannot amend public changesets'))
1314 if len(repo[None].parents()) > 1:
1314 if len(repo[None].parents()) > 1:
1315 raise util.Abort(_('cannot amend while merging'))
1315 raise util.Abort(_('cannot amend while merging'))
1316 if (not obsolete._enabled) and old.children():
1316 if (not obsolete._enabled) and old.children():
1317 raise util.Abort(_('cannot amend changeset with children'))
1317 raise util.Abort(_('cannot amend changeset with children'))
1318
1318
1319 e = cmdutil.commiteditor
1319 e = cmdutil.commiteditor
1320 if opts.get('force_editor'):
1320 if opts.get('force_editor'):
1321 e = cmdutil.commitforceeditor
1321 e = cmdutil.commitforceeditor
1322
1322
1323 def commitfunc(ui, repo, message, match, opts):
1323 def commitfunc(ui, repo, message, match, opts):
1324 editor = e
1324 editor = e
1325 # message contains text from -m or -l, if it's empty,
1325 # message contains text from -m or -l, if it's empty,
1326 # open the editor with the old message
1326 # open the editor with the old message
1327 if not message:
1327 if not message:
1328 message = old.description()
1328 message = old.description()
1329 editor = cmdutil.commitforceeditor
1329 editor = cmdutil.commitforceeditor
1330 return repo.commit(message,
1330 return repo.commit(message,
1331 opts.get('user') or old.user(),
1331 opts.get('user') or old.user(),
1332 opts.get('date') or old.date(),
1332 opts.get('date') or old.date(),
1333 match,
1333 match,
1334 editor=editor,
1334 editor=editor,
1335 extra=extra)
1335 extra=extra)
1336
1336
1337 current = repo._bookmarkcurrent
1337 current = repo._bookmarkcurrent
1338 marks = old.bookmarks()
1338 marks = old.bookmarks()
1339 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1339 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1340 if node == old.node():
1340 if node == old.node():
1341 ui.status(_("nothing changed\n"))
1341 ui.status(_("nothing changed\n"))
1342 return 1
1342 return 1
1343 elif marks:
1343 elif marks:
1344 ui.debug('moving bookmarks %r from %s to %s\n' %
1344 ui.debug('moving bookmarks %r from %s to %s\n' %
1345 (marks, old.hex(), hex(node)))
1345 (marks, old.hex(), hex(node)))
1346 newmarks = repo._bookmarks
1346 newmarks = repo._bookmarks
1347 for bm in marks:
1347 for bm in marks:
1348 newmarks[bm] = node
1348 newmarks[bm] = node
1349 if bm == current:
1349 if bm == current:
1350 bookmarks.setcurrent(repo, bm)
1350 bookmarks.setcurrent(repo, bm)
1351 newmarks.write()
1351 newmarks.write()
1352 else:
1352 else:
1353 e = cmdutil.commiteditor
1353 e = cmdutil.commiteditor
1354 if opts.get('force_editor'):
1354 if opts.get('force_editor'):
1355 e = cmdutil.commitforceeditor
1355 e = cmdutil.commitforceeditor
1356
1356
1357 def commitfunc(ui, repo, message, match, opts):
1357 def commitfunc(ui, repo, message, match, opts):
1358 return repo.commit(message, opts.get('user'), opts.get('date'),
1358 return repo.commit(message, opts.get('user'), opts.get('date'),
1359 match, editor=e, extra=extra)
1359 match, editor=e, extra=extra)
1360
1360
1361 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1361 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1362
1362
1363 if not node:
1363 if not node:
1364 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1364 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1365 if stat[3]:
1365 if stat[3]:
1366 ui.status(_("nothing changed (%d missing files, see "
1366 ui.status(_("nothing changed (%d missing files, see "
1367 "'hg status')\n") % len(stat[3]))
1367 "'hg status')\n") % len(stat[3]))
1368 else:
1368 else:
1369 ui.status(_("nothing changed\n"))
1369 ui.status(_("nothing changed\n"))
1370 return 1
1370 return 1
1371
1371
1372 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1372 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1373
1373
1374 @command('copy|cp',
1374 @command('copy|cp',
1375 [('A', 'after', None, _('record a copy that has already occurred')),
1375 [('A', 'after', None, _('record a copy that has already occurred')),
1376 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1376 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1377 ] + walkopts + dryrunopts,
1377 ] + walkopts + dryrunopts,
1378 _('[OPTION]... [SOURCE]... DEST'))
1378 _('[OPTION]... [SOURCE]... DEST'))
1379 def copy(ui, repo, *pats, **opts):
1379 def copy(ui, repo, *pats, **opts):
1380 """mark files as copied for the next commit
1380 """mark files as copied for the next commit
1381
1381
1382 Mark dest as having copies of source files. If dest is a
1382 Mark dest as having copies of source files. If dest is a
1383 directory, copies are put in that directory. If dest is a file,
1383 directory, copies are put in that directory. If dest is a file,
1384 the source must be a single file.
1384 the source must be a single file.
1385
1385
1386 By default, this command copies the contents of files as they
1386 By default, this command copies the contents of files as they
1387 exist in the working directory. If invoked with -A/--after, the
1387 exist in the working directory. If invoked with -A/--after, the
1388 operation is recorded, but no copying is performed.
1388 operation is recorded, but no copying is performed.
1389
1389
1390 This command takes effect with the next commit. To undo a copy
1390 This command takes effect with the next commit. To undo a copy
1391 before that, see :hg:`revert`.
1391 before that, see :hg:`revert`.
1392
1392
1393 Returns 0 on success, 1 if errors are encountered.
1393 Returns 0 on success, 1 if errors are encountered.
1394 """
1394 """
1395 wlock = repo.wlock(False)
1395 wlock = repo.wlock(False)
1396 try:
1396 try:
1397 return cmdutil.copy(ui, repo, pats, opts)
1397 return cmdutil.copy(ui, repo, pats, opts)
1398 finally:
1398 finally:
1399 wlock.release()
1399 wlock.release()
1400
1400
1401 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1401 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1402 def debugancestor(ui, repo, *args):
1402 def debugancestor(ui, repo, *args):
1403 """find the ancestor revision of two revisions in a given index"""
1403 """find the ancestor revision of two revisions in a given index"""
1404 if len(args) == 3:
1404 if len(args) == 3:
1405 index, rev1, rev2 = args
1405 index, rev1, rev2 = args
1406 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1406 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1407 lookup = r.lookup
1407 lookup = r.lookup
1408 elif len(args) == 2:
1408 elif len(args) == 2:
1409 if not repo:
1409 if not repo:
1410 raise util.Abort(_("there is no Mercurial repository here "
1410 raise util.Abort(_("there is no Mercurial repository here "
1411 "(.hg not found)"))
1411 "(.hg not found)"))
1412 rev1, rev2 = args
1412 rev1, rev2 = args
1413 r = repo.changelog
1413 r = repo.changelog
1414 lookup = repo.lookup
1414 lookup = repo.lookup
1415 else:
1415 else:
1416 raise util.Abort(_('either two or three arguments required'))
1416 raise util.Abort(_('either two or three arguments required'))
1417 a = r.ancestor(lookup(rev1), lookup(rev2))
1417 a = r.ancestor(lookup(rev1), lookup(rev2))
1418 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1418 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1419
1419
1420 @command('debugbuilddag',
1420 @command('debugbuilddag',
1421 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1421 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1422 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1422 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1423 ('n', 'new-file', None, _('add new file at each rev'))],
1423 ('n', 'new-file', None, _('add new file at each rev'))],
1424 _('[OPTION]... [TEXT]'))
1424 _('[OPTION]... [TEXT]'))
1425 def debugbuilddag(ui, repo, text=None,
1425 def debugbuilddag(ui, repo, text=None,
1426 mergeable_file=False,
1426 mergeable_file=False,
1427 overwritten_file=False,
1427 overwritten_file=False,
1428 new_file=False):
1428 new_file=False):
1429 """builds a repo with a given DAG from scratch in the current empty repo
1429 """builds a repo with a given DAG from scratch in the current empty repo
1430
1430
1431 The description of the DAG is read from stdin if not given on the
1431 The description of the DAG is read from stdin if not given on the
1432 command line.
1432 command line.
1433
1433
1434 Elements:
1434 Elements:
1435
1435
1436 - "+n" is a linear run of n nodes based on the current default parent
1436 - "+n" is a linear run of n nodes based on the current default parent
1437 - "." is a single node based on the current default parent
1437 - "." is a single node based on the current default parent
1438 - "$" resets the default parent to null (implied at the start);
1438 - "$" resets the default parent to null (implied at the start);
1439 otherwise the default parent is always the last node created
1439 otherwise the default parent is always the last node created
1440 - "<p" sets the default parent to the backref p
1440 - "<p" sets the default parent to the backref p
1441 - "*p" is a fork at parent p, which is a backref
1441 - "*p" is a fork at parent p, which is a backref
1442 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1442 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1443 - "/p2" is a merge of the preceding node and p2
1443 - "/p2" is a merge of the preceding node and p2
1444 - ":tag" defines a local tag for the preceding node
1444 - ":tag" defines a local tag for the preceding node
1445 - "@branch" sets the named branch for subsequent nodes
1445 - "@branch" sets the named branch for subsequent nodes
1446 - "#...\\n" is a comment up to the end of the line
1446 - "#...\\n" is a comment up to the end of the line
1447
1447
1448 Whitespace between the above elements is ignored.
1448 Whitespace between the above elements is ignored.
1449
1449
1450 A backref is either
1450 A backref is either
1451
1451
1452 - a number n, which references the node curr-n, where curr is the current
1452 - a number n, which references the node curr-n, where curr is the current
1453 node, or
1453 node, or
1454 - the name of a local tag you placed earlier using ":tag", or
1454 - the name of a local tag you placed earlier using ":tag", or
1455 - empty to denote the default parent.
1455 - empty to denote the default parent.
1456
1456
1457 All string valued-elements are either strictly alphanumeric, or must
1457 All string valued-elements are either strictly alphanumeric, or must
1458 be enclosed in double quotes ("..."), with "\\" as escape character.
1458 be enclosed in double quotes ("..."), with "\\" as escape character.
1459 """
1459 """
1460
1460
1461 if text is None:
1461 if text is None:
1462 ui.status(_("reading DAG from stdin\n"))
1462 ui.status(_("reading DAG from stdin\n"))
1463 text = ui.fin.read()
1463 text = ui.fin.read()
1464
1464
1465 cl = repo.changelog
1465 cl = repo.changelog
1466 if len(cl) > 0:
1466 if len(cl) > 0:
1467 raise util.Abort(_('repository is not empty'))
1467 raise util.Abort(_('repository is not empty'))
1468
1468
1469 # determine number of revs in DAG
1469 # determine number of revs in DAG
1470 total = 0
1470 total = 0
1471 for type, data in dagparser.parsedag(text):
1471 for type, data in dagparser.parsedag(text):
1472 if type == 'n':
1472 if type == 'n':
1473 total += 1
1473 total += 1
1474
1474
1475 if mergeable_file:
1475 if mergeable_file:
1476 linesperrev = 2
1476 linesperrev = 2
1477 # make a file with k lines per rev
1477 # make a file with k lines per rev
1478 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1478 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1479 initialmergedlines.append("")
1479 initialmergedlines.append("")
1480
1480
1481 tags = []
1481 tags = []
1482
1482
1483 lock = tr = None
1483 lock = tr = None
1484 try:
1484 try:
1485 lock = repo.lock()
1485 lock = repo.lock()
1486 tr = repo.transaction("builddag")
1486 tr = repo.transaction("builddag")
1487
1487
1488 at = -1
1488 at = -1
1489 atbranch = 'default'
1489 atbranch = 'default'
1490 nodeids = []
1490 nodeids = []
1491 id = 0
1491 id = 0
1492 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1492 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1493 for type, data in dagparser.parsedag(text):
1493 for type, data in dagparser.parsedag(text):
1494 if type == 'n':
1494 if type == 'n':
1495 ui.note(('node %s\n' % str(data)))
1495 ui.note(('node %s\n' % str(data)))
1496 id, ps = data
1496 id, ps = data
1497
1497
1498 files = []
1498 files = []
1499 fctxs = {}
1499 fctxs = {}
1500
1500
1501 p2 = None
1501 p2 = None
1502 if mergeable_file:
1502 if mergeable_file:
1503 fn = "mf"
1503 fn = "mf"
1504 p1 = repo[ps[0]]
1504 p1 = repo[ps[0]]
1505 if len(ps) > 1:
1505 if len(ps) > 1:
1506 p2 = repo[ps[1]]
1506 p2 = repo[ps[1]]
1507 pa = p1.ancestor(p2)
1507 pa = p1.ancestor(p2)
1508 base, local, other = [x[fn].data() for x in (pa, p1,
1508 base, local, other = [x[fn].data() for x in (pa, p1,
1509 p2)]
1509 p2)]
1510 m3 = simplemerge.Merge3Text(base, local, other)
1510 m3 = simplemerge.Merge3Text(base, local, other)
1511 ml = [l.strip() for l in m3.merge_lines()]
1511 ml = [l.strip() for l in m3.merge_lines()]
1512 ml.append("")
1512 ml.append("")
1513 elif at > 0:
1513 elif at > 0:
1514 ml = p1[fn].data().split("\n")
1514 ml = p1[fn].data().split("\n")
1515 else:
1515 else:
1516 ml = initialmergedlines
1516 ml = initialmergedlines
1517 ml[id * linesperrev] += " r%i" % id
1517 ml[id * linesperrev] += " r%i" % id
1518 mergedtext = "\n".join(ml)
1518 mergedtext = "\n".join(ml)
1519 files.append(fn)
1519 files.append(fn)
1520 fctxs[fn] = context.memfilectx(fn, mergedtext)
1520 fctxs[fn] = context.memfilectx(fn, mergedtext)
1521
1521
1522 if overwritten_file:
1522 if overwritten_file:
1523 fn = "of"
1523 fn = "of"
1524 files.append(fn)
1524 files.append(fn)
1525 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1525 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1526
1526
1527 if new_file:
1527 if new_file:
1528 fn = "nf%i" % id
1528 fn = "nf%i" % id
1529 files.append(fn)
1529 files.append(fn)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531 if len(ps) > 1:
1531 if len(ps) > 1:
1532 if not p2:
1532 if not p2:
1533 p2 = repo[ps[1]]
1533 p2 = repo[ps[1]]
1534 for fn in p2:
1534 for fn in p2:
1535 if fn.startswith("nf"):
1535 if fn.startswith("nf"):
1536 files.append(fn)
1536 files.append(fn)
1537 fctxs[fn] = p2[fn]
1537 fctxs[fn] = p2[fn]
1538
1538
1539 def fctxfn(repo, cx, path):
1539 def fctxfn(repo, cx, path):
1540 return fctxs.get(path)
1540 return fctxs.get(path)
1541
1541
1542 if len(ps) == 0 or ps[0] < 0:
1542 if len(ps) == 0 or ps[0] < 0:
1543 pars = [None, None]
1543 pars = [None, None]
1544 elif len(ps) == 1:
1544 elif len(ps) == 1:
1545 pars = [nodeids[ps[0]], None]
1545 pars = [nodeids[ps[0]], None]
1546 else:
1546 else:
1547 pars = [nodeids[p] for p in ps]
1547 pars = [nodeids[p] for p in ps]
1548 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1548 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1549 date=(id, 0),
1549 date=(id, 0),
1550 user="debugbuilddag",
1550 user="debugbuilddag",
1551 extra={'branch': atbranch})
1551 extra={'branch': atbranch})
1552 nodeid = repo.commitctx(cx)
1552 nodeid = repo.commitctx(cx)
1553 nodeids.append(nodeid)
1553 nodeids.append(nodeid)
1554 at = id
1554 at = id
1555 elif type == 'l':
1555 elif type == 'l':
1556 id, name = data
1556 id, name = data
1557 ui.note(('tag %s\n' % name))
1557 ui.note(('tag %s\n' % name))
1558 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1558 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1559 elif type == 'a':
1559 elif type == 'a':
1560 ui.note(('branch %s\n' % data))
1560 ui.note(('branch %s\n' % data))
1561 atbranch = data
1561 atbranch = data
1562 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1562 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1563 tr.close()
1563 tr.close()
1564
1564
1565 if tags:
1565 if tags:
1566 repo.opener.write("localtags", "".join(tags))
1566 repo.opener.write("localtags", "".join(tags))
1567 finally:
1567 finally:
1568 ui.progress(_('building'), None)
1568 ui.progress(_('building'), None)
1569 release(tr, lock)
1569 release(tr, lock)
1570
1570
1571 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1571 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1572 def debugbundle(ui, bundlepath, all=None, **opts):
1572 def debugbundle(ui, bundlepath, all=None, **opts):
1573 """lists the contents of a bundle"""
1573 """lists the contents of a bundle"""
1574 f = hg.openpath(ui, bundlepath)
1574 f = hg.openpath(ui, bundlepath)
1575 try:
1575 try:
1576 gen = changegroup.readbundle(f, bundlepath)
1576 gen = changegroup.readbundle(f, bundlepath)
1577 if all:
1577 if all:
1578 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1578 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1579
1579
1580 def showchunks(named):
1580 def showchunks(named):
1581 ui.write("\n%s\n" % named)
1581 ui.write("\n%s\n" % named)
1582 chain = None
1582 chain = None
1583 while True:
1583 while True:
1584 chunkdata = gen.deltachunk(chain)
1584 chunkdata = gen.deltachunk(chain)
1585 if not chunkdata:
1585 if not chunkdata:
1586 break
1586 break
1587 node = chunkdata['node']
1587 node = chunkdata['node']
1588 p1 = chunkdata['p1']
1588 p1 = chunkdata['p1']
1589 p2 = chunkdata['p2']
1589 p2 = chunkdata['p2']
1590 cs = chunkdata['cs']
1590 cs = chunkdata['cs']
1591 deltabase = chunkdata['deltabase']
1591 deltabase = chunkdata['deltabase']
1592 delta = chunkdata['delta']
1592 delta = chunkdata['delta']
1593 ui.write("%s %s %s %s %s %s\n" %
1593 ui.write("%s %s %s %s %s %s\n" %
1594 (hex(node), hex(p1), hex(p2),
1594 (hex(node), hex(p1), hex(p2),
1595 hex(cs), hex(deltabase), len(delta)))
1595 hex(cs), hex(deltabase), len(delta)))
1596 chain = node
1596 chain = node
1597
1597
1598 chunkdata = gen.changelogheader()
1598 chunkdata = gen.changelogheader()
1599 showchunks("changelog")
1599 showchunks("changelog")
1600 chunkdata = gen.manifestheader()
1600 chunkdata = gen.manifestheader()
1601 showchunks("manifest")
1601 showchunks("manifest")
1602 while True:
1602 while True:
1603 chunkdata = gen.filelogheader()
1603 chunkdata = gen.filelogheader()
1604 if not chunkdata:
1604 if not chunkdata:
1605 break
1605 break
1606 fname = chunkdata['filename']
1606 fname = chunkdata['filename']
1607 showchunks(fname)
1607 showchunks(fname)
1608 else:
1608 else:
1609 chunkdata = gen.changelogheader()
1609 chunkdata = gen.changelogheader()
1610 chain = None
1610 chain = None
1611 while True:
1611 while True:
1612 chunkdata = gen.deltachunk(chain)
1612 chunkdata = gen.deltachunk(chain)
1613 if not chunkdata:
1613 if not chunkdata:
1614 break
1614 break
1615 node = chunkdata['node']
1615 node = chunkdata['node']
1616 ui.write("%s\n" % hex(node))
1616 ui.write("%s\n" % hex(node))
1617 chain = node
1617 chain = node
1618 finally:
1618 finally:
1619 f.close()
1619 f.close()
1620
1620
1621 @command('debugcheckstate', [], '')
1621 @command('debugcheckstate', [], '')
1622 def debugcheckstate(ui, repo):
1622 def debugcheckstate(ui, repo):
1623 """validate the correctness of the current dirstate"""
1623 """validate the correctness of the current dirstate"""
1624 parent1, parent2 = repo.dirstate.parents()
1624 parent1, parent2 = repo.dirstate.parents()
1625 m1 = repo[parent1].manifest()
1625 m1 = repo[parent1].manifest()
1626 m2 = repo[parent2].manifest()
1626 m2 = repo[parent2].manifest()
1627 errors = 0
1627 errors = 0
1628 for f in repo.dirstate:
1628 for f in repo.dirstate:
1629 state = repo.dirstate[f]
1629 state = repo.dirstate[f]
1630 if state in "nr" and f not in m1:
1630 if state in "nr" and f not in m1:
1631 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1631 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1632 errors += 1
1632 errors += 1
1633 if state in "a" and f in m1:
1633 if state in "a" and f in m1:
1634 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1634 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1635 errors += 1
1635 errors += 1
1636 if state in "m" and f not in m1 and f not in m2:
1636 if state in "m" and f not in m1 and f not in m2:
1637 ui.warn(_("%s in state %s, but not in either manifest\n") %
1637 ui.warn(_("%s in state %s, but not in either manifest\n") %
1638 (f, state))
1638 (f, state))
1639 errors += 1
1639 errors += 1
1640 for f in m1:
1640 for f in m1:
1641 state = repo.dirstate[f]
1641 state = repo.dirstate[f]
1642 if state not in "nrm":
1642 if state not in "nrm":
1643 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1643 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1644 errors += 1
1644 errors += 1
1645 if errors:
1645 if errors:
1646 error = _(".hg/dirstate inconsistent with current parent's manifest")
1646 error = _(".hg/dirstate inconsistent with current parent's manifest")
1647 raise util.Abort(error)
1647 raise util.Abort(error)
1648
1648
1649 @command('debugcommands', [], _('[COMMAND]'))
1649 @command('debugcommands', [], _('[COMMAND]'))
1650 def debugcommands(ui, cmd='', *args):
1650 def debugcommands(ui, cmd='', *args):
1651 """list all available commands and options"""
1651 """list all available commands and options"""
1652 for cmd, vals in sorted(table.iteritems()):
1652 for cmd, vals in sorted(table.iteritems()):
1653 cmd = cmd.split('|')[0].strip('^')
1653 cmd = cmd.split('|')[0].strip('^')
1654 opts = ', '.join([i[1] for i in vals[1]])
1654 opts = ', '.join([i[1] for i in vals[1]])
1655 ui.write('%s: %s\n' % (cmd, opts))
1655 ui.write('%s: %s\n' % (cmd, opts))
1656
1656
1657 @command('debugcomplete',
1657 @command('debugcomplete',
1658 [('o', 'options', None, _('show the command options'))],
1658 [('o', 'options', None, _('show the command options'))],
1659 _('[-o] CMD'))
1659 _('[-o] CMD'))
1660 def debugcomplete(ui, cmd='', **opts):
1660 def debugcomplete(ui, cmd='', **opts):
1661 """returns the completion list associated with the given command"""
1661 """returns the completion list associated with the given command"""
1662
1662
1663 if opts.get('options'):
1663 if opts.get('options'):
1664 options = []
1664 options = []
1665 otables = [globalopts]
1665 otables = [globalopts]
1666 if cmd:
1666 if cmd:
1667 aliases, entry = cmdutil.findcmd(cmd, table, False)
1667 aliases, entry = cmdutil.findcmd(cmd, table, False)
1668 otables.append(entry[1])
1668 otables.append(entry[1])
1669 for t in otables:
1669 for t in otables:
1670 for o in t:
1670 for o in t:
1671 if "(DEPRECATED)" in o[3]:
1671 if "(DEPRECATED)" in o[3]:
1672 continue
1672 continue
1673 if o[0]:
1673 if o[0]:
1674 options.append('-%s' % o[0])
1674 options.append('-%s' % o[0])
1675 options.append('--%s' % o[1])
1675 options.append('--%s' % o[1])
1676 ui.write("%s\n" % "\n".join(options))
1676 ui.write("%s\n" % "\n".join(options))
1677 return
1677 return
1678
1678
1679 cmdlist = cmdutil.findpossible(cmd, table)
1679 cmdlist = cmdutil.findpossible(cmd, table)
1680 if ui.verbose:
1680 if ui.verbose:
1681 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1681 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1682 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1682 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1683
1683
1684 @command('debugdag',
1684 @command('debugdag',
1685 [('t', 'tags', None, _('use tags as labels')),
1685 [('t', 'tags', None, _('use tags as labels')),
1686 ('b', 'branches', None, _('annotate with branch names')),
1686 ('b', 'branches', None, _('annotate with branch names')),
1687 ('', 'dots', None, _('use dots for runs')),
1687 ('', 'dots', None, _('use dots for runs')),
1688 ('s', 'spaces', None, _('separate elements by spaces'))],
1688 ('s', 'spaces', None, _('separate elements by spaces'))],
1689 _('[OPTION]... [FILE [REV]...]'))
1689 _('[OPTION]... [FILE [REV]...]'))
1690 def debugdag(ui, repo, file_=None, *revs, **opts):
1690 def debugdag(ui, repo, file_=None, *revs, **opts):
1691 """format the changelog or an index DAG as a concise textual description
1691 """format the changelog or an index DAG as a concise textual description
1692
1692
1693 If you pass a revlog index, the revlog's DAG is emitted. If you list
1693 If you pass a revlog index, the revlog's DAG is emitted. If you list
1694 revision numbers, they get labeled in the output as rN.
1694 revision numbers, they get labeled in the output as rN.
1695
1695
1696 Otherwise, the changelog DAG of the current repo is emitted.
1696 Otherwise, the changelog DAG of the current repo is emitted.
1697 """
1697 """
1698 spaces = opts.get('spaces')
1698 spaces = opts.get('spaces')
1699 dots = opts.get('dots')
1699 dots = opts.get('dots')
1700 if file_:
1700 if file_:
1701 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1701 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1702 revs = set((int(r) for r in revs))
1702 revs = set((int(r) for r in revs))
1703 def events():
1703 def events():
1704 for r in rlog:
1704 for r in rlog:
1705 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1705 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1706 if p != -1)))
1706 if p != -1)))
1707 if r in revs:
1707 if r in revs:
1708 yield 'l', (r, "r%i" % r)
1708 yield 'l', (r, "r%i" % r)
1709 elif repo:
1709 elif repo:
1710 cl = repo.changelog
1710 cl = repo.changelog
1711 tags = opts.get('tags')
1711 tags = opts.get('tags')
1712 branches = opts.get('branches')
1712 branches = opts.get('branches')
1713 if tags:
1713 if tags:
1714 labels = {}
1714 labels = {}
1715 for l, n in repo.tags().items():
1715 for l, n in repo.tags().items():
1716 labels.setdefault(cl.rev(n), []).append(l)
1716 labels.setdefault(cl.rev(n), []).append(l)
1717 def events():
1717 def events():
1718 b = "default"
1718 b = "default"
1719 for r in cl:
1719 for r in cl:
1720 if branches:
1720 if branches:
1721 newb = cl.read(cl.node(r))[5]['branch']
1721 newb = cl.read(cl.node(r))[5]['branch']
1722 if newb != b:
1722 if newb != b:
1723 yield 'a', newb
1723 yield 'a', newb
1724 b = newb
1724 b = newb
1725 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1725 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1726 if p != -1)))
1726 if p != -1)))
1727 if tags:
1727 if tags:
1728 ls = labels.get(r)
1728 ls = labels.get(r)
1729 if ls:
1729 if ls:
1730 for l in ls:
1730 for l in ls:
1731 yield 'l', (r, l)
1731 yield 'l', (r, l)
1732 else:
1732 else:
1733 raise util.Abort(_('need repo for changelog dag'))
1733 raise util.Abort(_('need repo for changelog dag'))
1734
1734
1735 for line in dagparser.dagtextlines(events(),
1735 for line in dagparser.dagtextlines(events(),
1736 addspaces=spaces,
1736 addspaces=spaces,
1737 wraplabels=True,
1737 wraplabels=True,
1738 wrapannotations=True,
1738 wrapannotations=True,
1739 wrapnonlinear=dots,
1739 wrapnonlinear=dots,
1740 usedots=dots,
1740 usedots=dots,
1741 maxlinewidth=70):
1741 maxlinewidth=70):
1742 ui.write(line)
1742 ui.write(line)
1743 ui.write("\n")
1743 ui.write("\n")
1744
1744
1745 @command('debugdata',
1745 @command('debugdata',
1746 [('c', 'changelog', False, _('open changelog')),
1746 [('c', 'changelog', False, _('open changelog')),
1747 ('m', 'manifest', False, _('open manifest'))],
1747 ('m', 'manifest', False, _('open manifest'))],
1748 _('-c|-m|FILE REV'))
1748 _('-c|-m|FILE REV'))
1749 def debugdata(ui, repo, file_, rev = None, **opts):
1749 def debugdata(ui, repo, file_, rev = None, **opts):
1750 """dump the contents of a data file revision"""
1750 """dump the contents of a data file revision"""
1751 if opts.get('changelog') or opts.get('manifest'):
1751 if opts.get('changelog') or opts.get('manifest'):
1752 file_, rev = None, file_
1752 file_, rev = None, file_
1753 elif rev is None:
1753 elif rev is None:
1754 raise error.CommandError('debugdata', _('invalid arguments'))
1754 raise error.CommandError('debugdata', _('invalid arguments'))
1755 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1755 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1756 try:
1756 try:
1757 ui.write(r.revision(r.lookup(rev)))
1757 ui.write(r.revision(r.lookup(rev)))
1758 except KeyError:
1758 except KeyError:
1759 raise util.Abort(_('invalid revision identifier %s') % rev)
1759 raise util.Abort(_('invalid revision identifier %s') % rev)
1760
1760
1761 @command('debugdate',
1761 @command('debugdate',
1762 [('e', 'extended', None, _('try extended date formats'))],
1762 [('e', 'extended', None, _('try extended date formats'))],
1763 _('[-e] DATE [RANGE]'))
1763 _('[-e] DATE [RANGE]'))
1764 def debugdate(ui, date, range=None, **opts):
1764 def debugdate(ui, date, range=None, **opts):
1765 """parse and display a date"""
1765 """parse and display a date"""
1766 if opts["extended"]:
1766 if opts["extended"]:
1767 d = util.parsedate(date, util.extendeddateformats)
1767 d = util.parsedate(date, util.extendeddateformats)
1768 else:
1768 else:
1769 d = util.parsedate(date)
1769 d = util.parsedate(date)
1770 ui.write(("internal: %s %s\n") % d)
1770 ui.write(("internal: %s %s\n") % d)
1771 ui.write(("standard: %s\n") % util.datestr(d))
1771 ui.write(("standard: %s\n") % util.datestr(d))
1772 if range:
1772 if range:
1773 m = util.matchdate(range)
1773 m = util.matchdate(range)
1774 ui.write(("match: %s\n") % m(d[0]))
1774 ui.write(("match: %s\n") % m(d[0]))
1775
1775
1776 @command('debugdiscovery',
1776 @command('debugdiscovery',
1777 [('', 'old', None, _('use old-style discovery')),
1777 [('', 'old', None, _('use old-style discovery')),
1778 ('', 'nonheads', None,
1778 ('', 'nonheads', None,
1779 _('use old-style discovery with non-heads included')),
1779 _('use old-style discovery with non-heads included')),
1780 ] + remoteopts,
1780 ] + remoteopts,
1781 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1781 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1782 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1782 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1783 """runs the changeset discovery protocol in isolation"""
1783 """runs the changeset discovery protocol in isolation"""
1784 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1784 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1785 opts.get('branch'))
1785 opts.get('branch'))
1786 remote = hg.peer(repo, opts, remoteurl)
1786 remote = hg.peer(repo, opts, remoteurl)
1787 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1787 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1788
1788
1789 # make sure tests are repeatable
1789 # make sure tests are repeatable
1790 random.seed(12323)
1790 random.seed(12323)
1791
1791
1792 def doit(localheads, remoteheads, remote=remote):
1792 def doit(localheads, remoteheads, remote=remote):
1793 if opts.get('old'):
1793 if opts.get('old'):
1794 if localheads:
1794 if localheads:
1795 raise util.Abort('cannot use localheads with old style '
1795 raise util.Abort('cannot use localheads with old style '
1796 'discovery')
1796 'discovery')
1797 if not util.safehasattr(remote, 'branches'):
1797 if not util.safehasattr(remote, 'branches'):
1798 # enable in-client legacy support
1798 # enable in-client legacy support
1799 remote = localrepo.locallegacypeer(remote.local())
1799 remote = localrepo.locallegacypeer(remote.local())
1800 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1800 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1801 force=True)
1801 force=True)
1802 common = set(common)
1802 common = set(common)
1803 if not opts.get('nonheads'):
1803 if not opts.get('nonheads'):
1804 ui.write(("unpruned common: %s\n") %
1804 ui.write(("unpruned common: %s\n") %
1805 " ".join(sorted(short(n) for n in common)))
1805 " ".join(sorted(short(n) for n in common)))
1806 dag = dagutil.revlogdag(repo.changelog)
1806 dag = dagutil.revlogdag(repo.changelog)
1807 all = dag.ancestorset(dag.internalizeall(common))
1807 all = dag.ancestorset(dag.internalizeall(common))
1808 common = dag.externalizeall(dag.headsetofconnecteds(all))
1808 common = dag.externalizeall(dag.headsetofconnecteds(all))
1809 else:
1809 else:
1810 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1810 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1811 common = set(common)
1811 common = set(common)
1812 rheads = set(hds)
1812 rheads = set(hds)
1813 lheads = set(repo.heads())
1813 lheads = set(repo.heads())
1814 ui.write(("common heads: %s\n") %
1814 ui.write(("common heads: %s\n") %
1815 " ".join(sorted(short(n) for n in common)))
1815 " ".join(sorted(short(n) for n in common)))
1816 if lheads <= common:
1816 if lheads <= common:
1817 ui.write(("local is subset\n"))
1817 ui.write(("local is subset\n"))
1818 elif rheads <= common:
1818 elif rheads <= common:
1819 ui.write(("remote is subset\n"))
1819 ui.write(("remote is subset\n"))
1820
1820
1821 serverlogs = opts.get('serverlog')
1821 serverlogs = opts.get('serverlog')
1822 if serverlogs:
1822 if serverlogs:
1823 for filename in serverlogs:
1823 for filename in serverlogs:
1824 logfile = open(filename, 'r')
1824 logfile = open(filename, 'r')
1825 try:
1825 try:
1826 line = logfile.readline()
1826 line = logfile.readline()
1827 while line:
1827 while line:
1828 parts = line.strip().split(';')
1828 parts = line.strip().split(';')
1829 op = parts[1]
1829 op = parts[1]
1830 if op == 'cg':
1830 if op == 'cg':
1831 pass
1831 pass
1832 elif op == 'cgss':
1832 elif op == 'cgss':
1833 doit(parts[2].split(' '), parts[3].split(' '))
1833 doit(parts[2].split(' '), parts[3].split(' '))
1834 elif op == 'unb':
1834 elif op == 'unb':
1835 doit(parts[3].split(' '), parts[2].split(' '))
1835 doit(parts[3].split(' '), parts[2].split(' '))
1836 line = logfile.readline()
1836 line = logfile.readline()
1837 finally:
1837 finally:
1838 logfile.close()
1838 logfile.close()
1839
1839
1840 else:
1840 else:
1841 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1841 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1842 opts.get('remote_head'))
1842 opts.get('remote_head'))
1843 localrevs = opts.get('local_head')
1843 localrevs = opts.get('local_head')
1844 doit(localrevs, remoterevs)
1844 doit(localrevs, remoterevs)
1845
1845
1846 @command('debugfileset',
1846 @command('debugfileset',
1847 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1847 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1848 _('[-r REV] FILESPEC'))
1848 _('[-r REV] FILESPEC'))
1849 def debugfileset(ui, repo, expr, **opts):
1849 def debugfileset(ui, repo, expr, **opts):
1850 '''parse and apply a fileset specification'''
1850 '''parse and apply a fileset specification'''
1851 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1851 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1852 if ui.verbose:
1852 if ui.verbose:
1853 tree = fileset.parse(expr)[0]
1853 tree = fileset.parse(expr)[0]
1854 ui.note(tree, "\n")
1854 ui.note(tree, "\n")
1855
1855
1856 for f in fileset.getfileset(ctx, expr):
1856 for f in fileset.getfileset(ctx, expr):
1857 ui.write("%s\n" % f)
1857 ui.write("%s\n" % f)
1858
1858
1859 @command('debugfsinfo', [], _('[PATH]'))
1859 @command('debugfsinfo', [], _('[PATH]'))
1860 def debugfsinfo(ui, path = "."):
1860 def debugfsinfo(ui, path = "."):
1861 """show information detected about current filesystem"""
1861 """show information detected about current filesystem"""
1862 util.writefile('.debugfsinfo', '')
1862 util.writefile('.debugfsinfo', '')
1863 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1863 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1864 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1864 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1865 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1865 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1866 and 'yes' or 'no'))
1866 and 'yes' or 'no'))
1867 os.unlink('.debugfsinfo')
1867 os.unlink('.debugfsinfo')
1868
1868
1869 @command('debuggetbundle',
1869 @command('debuggetbundle',
1870 [('H', 'head', [], _('id of head node'), _('ID')),
1870 [('H', 'head', [], _('id of head node'), _('ID')),
1871 ('C', 'common', [], _('id of common node'), _('ID')),
1871 ('C', 'common', [], _('id of common node'), _('ID')),
1872 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1872 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1873 _('REPO FILE [-H|-C ID]...'))
1873 _('REPO FILE [-H|-C ID]...'))
1874 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1874 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1875 """retrieves a bundle from a repo
1875 """retrieves a bundle from a repo
1876
1876
1877 Every ID must be a full-length hex node id string. Saves the bundle to the
1877 Every ID must be a full-length hex node id string. Saves the bundle to the
1878 given file.
1878 given file.
1879 """
1879 """
1880 repo = hg.peer(ui, opts, repopath)
1880 repo = hg.peer(ui, opts, repopath)
1881 if not repo.capable('getbundle'):
1881 if not repo.capable('getbundle'):
1882 raise util.Abort("getbundle() not supported by target repository")
1882 raise util.Abort("getbundle() not supported by target repository")
1883 args = {}
1883 args = {}
1884 if common:
1884 if common:
1885 args['common'] = [bin(s) for s in common]
1885 args['common'] = [bin(s) for s in common]
1886 if head:
1886 if head:
1887 args['heads'] = [bin(s) for s in head]
1887 args['heads'] = [bin(s) for s in head]
1888 bundle = repo.getbundle('debug', **args)
1888 bundle = repo.getbundle('debug', **args)
1889
1889
1890 bundletype = opts.get('type', 'bzip2').lower()
1890 bundletype = opts.get('type', 'bzip2').lower()
1891 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1891 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1892 bundletype = btypes.get(bundletype)
1892 bundletype = btypes.get(bundletype)
1893 if bundletype not in changegroup.bundletypes:
1893 if bundletype not in changegroup.bundletypes:
1894 raise util.Abort(_('unknown bundle type specified with --type'))
1894 raise util.Abort(_('unknown bundle type specified with --type'))
1895 changegroup.writebundle(bundle, bundlepath, bundletype)
1895 changegroup.writebundle(bundle, bundlepath, bundletype)
1896
1896
1897 @command('debugignore', [], '')
1897 @command('debugignore', [], '')
1898 def debugignore(ui, repo, *values, **opts):
1898 def debugignore(ui, repo, *values, **opts):
1899 """display the combined ignore pattern"""
1899 """display the combined ignore pattern"""
1900 ignore = repo.dirstate._ignore
1900 ignore = repo.dirstate._ignore
1901 includepat = getattr(ignore, 'includepat', None)
1901 includepat = getattr(ignore, 'includepat', None)
1902 if includepat is not None:
1902 if includepat is not None:
1903 ui.write("%s\n" % includepat)
1903 ui.write("%s\n" % includepat)
1904 else:
1904 else:
1905 raise util.Abort(_("no ignore patterns found"))
1905 raise util.Abort(_("no ignore patterns found"))
1906
1906
1907 @command('debugindex',
1907 @command('debugindex',
1908 [('c', 'changelog', False, _('open changelog')),
1908 [('c', 'changelog', False, _('open changelog')),
1909 ('m', 'manifest', False, _('open manifest')),
1909 ('m', 'manifest', False, _('open manifest')),
1910 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1910 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1911 _('[-f FORMAT] -c|-m|FILE'))
1911 _('[-f FORMAT] -c|-m|FILE'))
1912 def debugindex(ui, repo, file_ = None, **opts):
1912 def debugindex(ui, repo, file_ = None, **opts):
1913 """dump the contents of an index file"""
1913 """dump the contents of an index file"""
1914 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1914 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1915 format = opts.get('format', 0)
1915 format = opts.get('format', 0)
1916 if format not in (0, 1):
1916 if format not in (0, 1):
1917 raise util.Abort(_("unknown format %d") % format)
1917 raise util.Abort(_("unknown format %d") % format)
1918
1918
1919 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1919 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1920 if generaldelta:
1920 if generaldelta:
1921 basehdr = ' delta'
1921 basehdr = ' delta'
1922 else:
1922 else:
1923 basehdr = ' base'
1923 basehdr = ' base'
1924
1924
1925 if format == 0:
1925 if format == 0:
1926 ui.write(" rev offset length " + basehdr + " linkrev"
1926 ui.write(" rev offset length " + basehdr + " linkrev"
1927 " nodeid p1 p2\n")
1927 " nodeid p1 p2\n")
1928 elif format == 1:
1928 elif format == 1:
1929 ui.write(" rev flag offset length"
1929 ui.write(" rev flag offset length"
1930 " size " + basehdr + " link p1 p2"
1930 " size " + basehdr + " link p1 p2"
1931 " nodeid\n")
1931 " nodeid\n")
1932
1932
1933 for i in r:
1933 for i in r:
1934 node = r.node(i)
1934 node = r.node(i)
1935 if generaldelta:
1935 if generaldelta:
1936 base = r.deltaparent(i)
1936 base = r.deltaparent(i)
1937 else:
1937 else:
1938 base = r.chainbase(i)
1938 base = r.chainbase(i)
1939 if format == 0:
1939 if format == 0:
1940 try:
1940 try:
1941 pp = r.parents(node)
1941 pp = r.parents(node)
1942 except Exception:
1942 except Exception:
1943 pp = [nullid, nullid]
1943 pp = [nullid, nullid]
1944 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1944 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1945 i, r.start(i), r.length(i), base, r.linkrev(i),
1945 i, r.start(i), r.length(i), base, r.linkrev(i),
1946 short(node), short(pp[0]), short(pp[1])))
1946 short(node), short(pp[0]), short(pp[1])))
1947 elif format == 1:
1947 elif format == 1:
1948 pr = r.parentrevs(i)
1948 pr = r.parentrevs(i)
1949 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1949 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1950 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1950 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1951 base, r.linkrev(i), pr[0], pr[1], short(node)))
1951 base, r.linkrev(i), pr[0], pr[1], short(node)))
1952
1952
1953 @command('debugindexdot', [], _('FILE'))
1953 @command('debugindexdot', [], _('FILE'))
1954 def debugindexdot(ui, repo, file_):
1954 def debugindexdot(ui, repo, file_):
1955 """dump an index DAG as a graphviz dot file"""
1955 """dump an index DAG as a graphviz dot file"""
1956 r = None
1956 r = None
1957 if repo:
1957 if repo:
1958 filelog = repo.file(file_)
1958 filelog = repo.file(file_)
1959 if len(filelog):
1959 if len(filelog):
1960 r = filelog
1960 r = filelog
1961 if not r:
1961 if not r:
1962 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1962 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1963 ui.write(("digraph G {\n"))
1963 ui.write(("digraph G {\n"))
1964 for i in r:
1964 for i in r:
1965 node = r.node(i)
1965 node = r.node(i)
1966 pp = r.parents(node)
1966 pp = r.parents(node)
1967 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1967 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1968 if pp[1] != nullid:
1968 if pp[1] != nullid:
1969 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1969 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1970 ui.write("}\n")
1970 ui.write("}\n")
1971
1971
1972 @command('debuginstall', [], '')
1972 @command('debuginstall', [], '')
1973 def debuginstall(ui):
1973 def debuginstall(ui):
1974 '''test Mercurial installation
1974 '''test Mercurial installation
1975
1975
1976 Returns 0 on success.
1976 Returns 0 on success.
1977 '''
1977 '''
1978
1978
1979 def writetemp(contents):
1979 def writetemp(contents):
1980 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1980 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1981 f = os.fdopen(fd, "wb")
1981 f = os.fdopen(fd, "wb")
1982 f.write(contents)
1982 f.write(contents)
1983 f.close()
1983 f.close()
1984 return name
1984 return name
1985
1985
1986 problems = 0
1986 problems = 0
1987
1987
1988 # encoding
1988 # encoding
1989 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1989 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1990 try:
1990 try:
1991 encoding.fromlocal("test")
1991 encoding.fromlocal("test")
1992 except util.Abort, inst:
1992 except util.Abort, inst:
1993 ui.write(" %s\n" % inst)
1993 ui.write(" %s\n" % inst)
1994 ui.write(_(" (check that your locale is properly set)\n"))
1994 ui.write(_(" (check that your locale is properly set)\n"))
1995 problems += 1
1995 problems += 1
1996
1996
1997 # Python lib
1997 # Python lib
1998 ui.status(_("checking Python lib (%s)...\n")
1998 ui.status(_("checking Python lib (%s)...\n")
1999 % os.path.dirname(os.__file__))
1999 % os.path.dirname(os.__file__))
2000
2000
2001 # compiled modules
2001 # compiled modules
2002 ui.status(_("checking installed modules (%s)...\n")
2002 ui.status(_("checking installed modules (%s)...\n")
2003 % os.path.dirname(__file__))
2003 % os.path.dirname(__file__))
2004 try:
2004 try:
2005 import bdiff, mpatch, base85, osutil
2005 import bdiff, mpatch, base85, osutil
2006 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2006 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2007 except Exception, inst:
2007 except Exception, inst:
2008 ui.write(" %s\n" % inst)
2008 ui.write(" %s\n" % inst)
2009 ui.write(_(" One or more extensions could not be found"))
2009 ui.write(_(" One or more extensions could not be found"))
2010 ui.write(_(" (check that you compiled the extensions)\n"))
2010 ui.write(_(" (check that you compiled the extensions)\n"))
2011 problems += 1
2011 problems += 1
2012
2012
2013 # templates
2013 # templates
2014 import templater
2014 import templater
2015 p = templater.templatepath()
2015 p = templater.templatepath()
2016 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2016 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2017 try:
2017 try:
2018 templater.templater(templater.templatepath("map-cmdline.default"))
2018 templater.templater(templater.templatepath("map-cmdline.default"))
2019 except Exception, inst:
2019 except Exception, inst:
2020 ui.write(" %s\n" % inst)
2020 ui.write(" %s\n" % inst)
2021 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2021 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2022 problems += 1
2022 problems += 1
2023
2023
2024 # editor
2024 # editor
2025 ui.status(_("checking commit editor...\n"))
2025 ui.status(_("checking commit editor...\n"))
2026 editor = ui.geteditor()
2026 editor = ui.geteditor()
2027 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2027 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2028 if not cmdpath:
2028 if not cmdpath:
2029 if editor == 'vi':
2029 if editor == 'vi':
2030 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2030 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2031 ui.write(_(" (specify a commit editor in your configuration"
2031 ui.write(_(" (specify a commit editor in your configuration"
2032 " file)\n"))
2032 " file)\n"))
2033 else:
2033 else:
2034 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2034 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2035 ui.write(_(" (specify a commit editor in your configuration"
2035 ui.write(_(" (specify a commit editor in your configuration"
2036 " file)\n"))
2036 " file)\n"))
2037 problems += 1
2037 problems += 1
2038
2038
2039 # check username
2039 # check username
2040 ui.status(_("checking username...\n"))
2040 ui.status(_("checking username...\n"))
2041 try:
2041 try:
2042 ui.username()
2042 ui.username()
2043 except util.Abort, e:
2043 except util.Abort, e:
2044 ui.write(" %s\n" % e)
2044 ui.write(" %s\n" % e)
2045 ui.write(_(" (specify a username in your configuration file)\n"))
2045 ui.write(_(" (specify a username in your configuration file)\n"))
2046 problems += 1
2046 problems += 1
2047
2047
2048 if not problems:
2048 if not problems:
2049 ui.status(_("no problems detected\n"))
2049 ui.status(_("no problems detected\n"))
2050 else:
2050 else:
2051 ui.write(_("%s problems detected,"
2051 ui.write(_("%s problems detected,"
2052 " please check your install!\n") % problems)
2052 " please check your install!\n") % problems)
2053
2053
2054 return problems
2054 return problems
2055
2055
2056 @command('debugknown', [], _('REPO ID...'))
2056 @command('debugknown', [], _('REPO ID...'))
2057 def debugknown(ui, repopath, *ids, **opts):
2057 def debugknown(ui, repopath, *ids, **opts):
2058 """test whether node ids are known to a repo
2058 """test whether node ids are known to a repo
2059
2059
2060 Every ID must be a full-length hex node id string. Returns a list of 0s
2060 Every ID must be a full-length hex node id string. Returns a list of 0s
2061 and 1s indicating unknown/known.
2061 and 1s indicating unknown/known.
2062 """
2062 """
2063 repo = hg.peer(ui, opts, repopath)
2063 repo = hg.peer(ui, opts, repopath)
2064 if not repo.capable('known'):
2064 if not repo.capable('known'):
2065 raise util.Abort("known() not supported by target repository")
2065 raise util.Abort("known() not supported by target repository")
2066 flags = repo.known([bin(s) for s in ids])
2066 flags = repo.known([bin(s) for s in ids])
2067 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2067 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2068
2068
2069 @command('debuglabelcomplete', [], _('LABEL...'))
2069 @command('debuglabelcomplete', [], _('LABEL...'))
2070 def debuglabelcomplete(ui, repo, *args):
2070 def debuglabelcomplete(ui, repo, *args):
2071 '''complete "labels" - tags, open branch names, bookmark names'''
2071 '''complete "labels" - tags, open branch names, bookmark names'''
2072
2072
2073 labels = set()
2073 labels = set()
2074 labels.update(t[0] for t in repo.tagslist())
2074 labels.update(t[0] for t in repo.tagslist())
2075 labels.update(repo._bookmarks.keys())
2075 labels.update(repo._bookmarks.keys())
2076 for heads in repo.branchmap().itervalues():
2076 for heads in repo.branchmap().itervalues():
2077 for h in heads:
2077 for h in heads:
2078 ctx = repo[h]
2078 ctx = repo[h]
2079 if not ctx.closesbranch():
2079 if not ctx.closesbranch():
2080 labels.add(ctx.branch())
2080 labels.add(ctx.branch())
2081 completions = set()
2081 completions = set()
2082 if not args:
2082 if not args:
2083 args = ['']
2083 args = ['']
2084 for a in args:
2084 for a in args:
2085 completions.update(l for l in labels if l.startswith(a))
2085 completions.update(l for l in labels if l.startswith(a))
2086 ui.write('\n'.join(sorted(completions)))
2086 ui.write('\n'.join(sorted(completions)))
2087 ui.write('\n')
2087 ui.write('\n')
2088
2088
2089 @command('debugobsolete',
2089 @command('debugobsolete',
2090 [('', 'flags', 0, _('markers flag')),
2090 [('', 'flags', 0, _('markers flag')),
2091 ] + commitopts2,
2091 ] + commitopts2,
2092 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2092 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2093 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2093 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2094 """create arbitrary obsolete marker
2094 """create arbitrary obsolete marker
2095
2095
2096 With no arguments, displays the list of obsolescence markers."""
2096 With no arguments, displays the list of obsolescence markers."""
2097 def parsenodeid(s):
2097 def parsenodeid(s):
2098 try:
2098 try:
2099 # We do not use revsingle/revrange functions here to accept
2099 # We do not use revsingle/revrange functions here to accept
2100 # arbitrary node identifiers, possibly not present in the
2100 # arbitrary node identifiers, possibly not present in the
2101 # local repository.
2101 # local repository.
2102 n = bin(s)
2102 n = bin(s)
2103 if len(n) != len(nullid):
2103 if len(n) != len(nullid):
2104 raise TypeError()
2104 raise TypeError()
2105 return n
2105 return n
2106 except TypeError:
2106 except TypeError:
2107 raise util.Abort('changeset references must be full hexadecimal '
2107 raise util.Abort('changeset references must be full hexadecimal '
2108 'node identifiers')
2108 'node identifiers')
2109
2109
2110 if precursor is not None:
2110 if precursor is not None:
2111 metadata = {}
2111 metadata = {}
2112 if 'date' in opts:
2112 if 'date' in opts:
2113 metadata['date'] = opts['date']
2113 metadata['date'] = opts['date']
2114 metadata['user'] = opts['user'] or ui.username()
2114 metadata['user'] = opts['user'] or ui.username()
2115 succs = tuple(parsenodeid(succ) for succ in successors)
2115 succs = tuple(parsenodeid(succ) for succ in successors)
2116 l = repo.lock()
2116 l = repo.lock()
2117 try:
2117 try:
2118 tr = repo.transaction('debugobsolete')
2118 tr = repo.transaction('debugobsolete')
2119 try:
2119 try:
2120 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2120 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2121 opts['flags'], metadata)
2121 opts['flags'], metadata)
2122 tr.close()
2122 tr.close()
2123 finally:
2123 finally:
2124 tr.release()
2124 tr.release()
2125 finally:
2125 finally:
2126 l.release()
2126 l.release()
2127 else:
2127 else:
2128 for m in obsolete.allmarkers(repo):
2128 for m in obsolete.allmarkers(repo):
2129 ui.write(hex(m.precnode()))
2129 ui.write(hex(m.precnode()))
2130 for repl in m.succnodes():
2130 for repl in m.succnodes():
2131 ui.write(' ')
2131 ui.write(' ')
2132 ui.write(hex(repl))
2132 ui.write(hex(repl))
2133 ui.write(' %X ' % m._data[2])
2133 ui.write(' %X ' % m._data[2])
2134 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2134 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2135 sorted(m.metadata().items()))))
2135 sorted(m.metadata().items()))))
2136 ui.write('\n')
2136 ui.write('\n')
2137
2137
2138 @command('debugpathcomplete',
2138 @command('debugpathcomplete',
2139 [('f', 'full', None, _('complete an entire path')),
2139 [('f', 'full', None, _('complete an entire path')),
2140 ('n', 'normal', None, _('show only normal files')),
2140 ('n', 'normal', None, _('show only normal files')),
2141 ('a', 'added', None, _('show only added files')),
2141 ('a', 'added', None, _('show only added files')),
2142 ('r', 'removed', None, _('show only removed files'))],
2142 ('r', 'removed', None, _('show only removed files'))],
2143 _('FILESPEC...'))
2143 _('FILESPEC...'))
2144 def debugpathcomplete(ui, repo, *specs, **opts):
2144 def debugpathcomplete(ui, repo, *specs, **opts):
2145 '''complete part or all of a tracked path
2145 '''complete part or all of a tracked path
2146
2146
2147 This command supports shells that offer path name completion. It
2147 This command supports shells that offer path name completion. It
2148 currently completes only files already known to the dirstate.
2148 currently completes only files already known to the dirstate.
2149
2149
2150 Completion extends only to the next path segment unless
2150 Completion extends only to the next path segment unless
2151 --full is specified, in which case entire paths are used.'''
2151 --full is specified, in which case entire paths are used.'''
2152
2152
2153 def complete(path, acceptable):
2153 def complete(path, acceptable):
2154 dirstate = repo.dirstate
2154 dirstate = repo.dirstate
2155 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2155 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2156 rootdir = repo.root + os.sep
2156 rootdir = repo.root + os.sep
2157 if spec != repo.root and not spec.startswith(rootdir):
2157 if spec != repo.root and not spec.startswith(rootdir):
2158 return [], []
2158 return [], []
2159 if os.path.isdir(spec):
2159 if os.path.isdir(spec):
2160 spec += '/'
2160 spec += '/'
2161 spec = spec[len(rootdir):]
2161 spec = spec[len(rootdir):]
2162 fixpaths = os.sep != '/'
2162 fixpaths = os.sep != '/'
2163 if fixpaths:
2163 if fixpaths:
2164 spec = spec.replace(os.sep, '/')
2164 spec = spec.replace(os.sep, '/')
2165 speclen = len(spec)
2165 speclen = len(spec)
2166 fullpaths = opts['full']
2166 fullpaths = opts['full']
2167 files, dirs = set(), set()
2167 files, dirs = set(), set()
2168 adddir, addfile = dirs.add, files.add
2168 adddir, addfile = dirs.add, files.add
2169 for f, st in dirstate.iteritems():
2169 for f, st in dirstate.iteritems():
2170 if f.startswith(spec) and st[0] in acceptable:
2170 if f.startswith(spec) and st[0] in acceptable:
2171 if fixpaths:
2171 if fixpaths:
2172 f = f.replace('/', os.sep)
2172 f = f.replace('/', os.sep)
2173 if fullpaths:
2173 if fullpaths:
2174 addfile(f)
2174 addfile(f)
2175 continue
2175 continue
2176 s = f.find(os.sep, speclen)
2176 s = f.find(os.sep, speclen)
2177 if s >= 0:
2177 if s >= 0:
2178 adddir(f[:s + 1])
2178 adddir(f[:s + 1])
2179 else:
2179 else:
2180 addfile(f)
2180 addfile(f)
2181 return files, dirs
2181 return files, dirs
2182
2182
2183 acceptable = ''
2183 acceptable = ''
2184 if opts['normal']:
2184 if opts['normal']:
2185 acceptable += 'nm'
2185 acceptable += 'nm'
2186 if opts['added']:
2186 if opts['added']:
2187 acceptable += 'a'
2187 acceptable += 'a'
2188 if opts['removed']:
2188 if opts['removed']:
2189 acceptable += 'r'
2189 acceptable += 'r'
2190 cwd = repo.getcwd()
2190 cwd = repo.getcwd()
2191 if not specs:
2191 if not specs:
2192 specs = ['.']
2192 specs = ['.']
2193
2193
2194 files, dirs = set(), set()
2194 files, dirs = set(), set()
2195 for spec in specs:
2195 for spec in specs:
2196 f, d = complete(spec, acceptable or 'nmar')
2196 f, d = complete(spec, acceptable or 'nmar')
2197 files.update(f)
2197 files.update(f)
2198 dirs.update(d)
2198 dirs.update(d)
2199 if not files and len(dirs) == 1:
2199 if not files and len(dirs) == 1:
2200 # force the shell to consider a completion that matches one
2200 # force the shell to consider a completion that matches one
2201 # directory and zero files to be ambiguous
2201 # directory and zero files to be ambiguous
2202 dirs.add(iter(dirs).next() + '.')
2202 dirs.add(iter(dirs).next() + '.')
2203 files.update(dirs)
2203 files.update(dirs)
2204 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2204 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2205 ui.write('\n')
2205 ui.write('\n')
2206
2206
2207 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2207 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2208 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2208 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2209 '''access the pushkey key/value protocol
2209 '''access the pushkey key/value protocol
2210
2210
2211 With two args, list the keys in the given namespace.
2211 With two args, list the keys in the given namespace.
2212
2212
2213 With five args, set a key to new if it currently is set to old.
2213 With five args, set a key to new if it currently is set to old.
2214 Reports success or failure.
2214 Reports success or failure.
2215 '''
2215 '''
2216
2216
2217 target = hg.peer(ui, {}, repopath)
2217 target = hg.peer(ui, {}, repopath)
2218 if keyinfo:
2218 if keyinfo:
2219 key, old, new = keyinfo
2219 key, old, new = keyinfo
2220 r = target.pushkey(namespace, key, old, new)
2220 r = target.pushkey(namespace, key, old, new)
2221 ui.status(str(r) + '\n')
2221 ui.status(str(r) + '\n')
2222 return not r
2222 return not r
2223 else:
2223 else:
2224 for k, v in sorted(target.listkeys(namespace).iteritems()):
2224 for k, v in sorted(target.listkeys(namespace).iteritems()):
2225 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2225 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2226 v.encode('string-escape')))
2226 v.encode('string-escape')))
2227
2227
2228 @command('debugpvec', [], _('A B'))
2228 @command('debugpvec', [], _('A B'))
2229 def debugpvec(ui, repo, a, b=None):
2229 def debugpvec(ui, repo, a, b=None):
2230 ca = scmutil.revsingle(repo, a)
2230 ca = scmutil.revsingle(repo, a)
2231 cb = scmutil.revsingle(repo, b)
2231 cb = scmutil.revsingle(repo, b)
2232 pa = pvec.ctxpvec(ca)
2232 pa = pvec.ctxpvec(ca)
2233 pb = pvec.ctxpvec(cb)
2233 pb = pvec.ctxpvec(cb)
2234 if pa == pb:
2234 if pa == pb:
2235 rel = "="
2235 rel = "="
2236 elif pa > pb:
2236 elif pa > pb:
2237 rel = ">"
2237 rel = ">"
2238 elif pa < pb:
2238 elif pa < pb:
2239 rel = "<"
2239 rel = "<"
2240 elif pa | pb:
2240 elif pa | pb:
2241 rel = "|"
2241 rel = "|"
2242 ui.write(_("a: %s\n") % pa)
2242 ui.write(_("a: %s\n") % pa)
2243 ui.write(_("b: %s\n") % pb)
2243 ui.write(_("b: %s\n") % pb)
2244 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2244 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2245 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2245 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2246 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2246 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2247 pa.distance(pb), rel))
2247 pa.distance(pb), rel))
2248
2248
2249 @command('debugrebuildstate',
2249 @command('debugrebuildstate',
2250 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2250 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2251 _('[-r REV] [REV]'))
2251 _('[-r REV] [REV]'))
2252 def debugrebuildstate(ui, repo, rev="tip"):
2252 def debugrebuildstate(ui, repo, rev="tip"):
2253 """rebuild the dirstate as it would look like for the given revision"""
2253 """rebuild the dirstate as it would look like for the given revision"""
2254 ctx = scmutil.revsingle(repo, rev)
2254 ctx = scmutil.revsingle(repo, rev)
2255 wlock = repo.wlock()
2255 wlock = repo.wlock()
2256 try:
2256 try:
2257 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2257 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2258 finally:
2258 finally:
2259 wlock.release()
2259 wlock.release()
2260
2260
2261 @command('debugrename',
2261 @command('debugrename',
2262 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2262 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2263 _('[-r REV] FILE'))
2263 _('[-r REV] FILE'))
2264 def debugrename(ui, repo, file1, *pats, **opts):
2264 def debugrename(ui, repo, file1, *pats, **opts):
2265 """dump rename information"""
2265 """dump rename information"""
2266
2266
2267 ctx = scmutil.revsingle(repo, opts.get('rev'))
2267 ctx = scmutil.revsingle(repo, opts.get('rev'))
2268 m = scmutil.match(ctx, (file1,) + pats, opts)
2268 m = scmutil.match(ctx, (file1,) + pats, opts)
2269 for abs in ctx.walk(m):
2269 for abs in ctx.walk(m):
2270 fctx = ctx[abs]
2270 fctx = ctx[abs]
2271 o = fctx.filelog().renamed(fctx.filenode())
2271 o = fctx.filelog().renamed(fctx.filenode())
2272 rel = m.rel(abs)
2272 rel = m.rel(abs)
2273 if o:
2273 if o:
2274 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2274 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2275 else:
2275 else:
2276 ui.write(_("%s not renamed\n") % rel)
2276 ui.write(_("%s not renamed\n") % rel)
2277
2277
2278 @command('debugrevlog',
2278 @command('debugrevlog',
2279 [('c', 'changelog', False, _('open changelog')),
2279 [('c', 'changelog', False, _('open changelog')),
2280 ('m', 'manifest', False, _('open manifest')),
2280 ('m', 'manifest', False, _('open manifest')),
2281 ('d', 'dump', False, _('dump index data'))],
2281 ('d', 'dump', False, _('dump index data'))],
2282 _('-c|-m|FILE'))
2282 _('-c|-m|FILE'))
2283 def debugrevlog(ui, repo, file_ = None, **opts):
2283 def debugrevlog(ui, repo, file_ = None, **opts):
2284 """show data and statistics about a revlog"""
2284 """show data and statistics about a revlog"""
2285 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2285 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2286
2286
2287 if opts.get("dump"):
2287 if opts.get("dump"):
2288 numrevs = len(r)
2288 numrevs = len(r)
2289 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2289 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2290 " rawsize totalsize compression heads\n")
2290 " rawsize totalsize compression heads\n")
2291 ts = 0
2291 ts = 0
2292 heads = set()
2292 heads = set()
2293 for rev in xrange(numrevs):
2293 for rev in xrange(numrevs):
2294 dbase = r.deltaparent(rev)
2294 dbase = r.deltaparent(rev)
2295 if dbase == -1:
2295 if dbase == -1:
2296 dbase = rev
2296 dbase = rev
2297 cbase = r.chainbase(rev)
2297 cbase = r.chainbase(rev)
2298 p1, p2 = r.parentrevs(rev)
2298 p1, p2 = r.parentrevs(rev)
2299 rs = r.rawsize(rev)
2299 rs = r.rawsize(rev)
2300 ts = ts + rs
2300 ts = ts + rs
2301 heads -= set(r.parentrevs(rev))
2301 heads -= set(r.parentrevs(rev))
2302 heads.add(rev)
2302 heads.add(rev)
2303 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2303 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2304 (rev, p1, p2, r.start(rev), r.end(rev),
2304 (rev, p1, p2, r.start(rev), r.end(rev),
2305 r.start(dbase), r.start(cbase),
2305 r.start(dbase), r.start(cbase),
2306 r.start(p1), r.start(p2),
2306 r.start(p1), r.start(p2),
2307 rs, ts, ts / r.end(rev), len(heads)))
2307 rs, ts, ts / r.end(rev), len(heads)))
2308 return 0
2308 return 0
2309
2309
2310 v = r.version
2310 v = r.version
2311 format = v & 0xFFFF
2311 format = v & 0xFFFF
2312 flags = []
2312 flags = []
2313 gdelta = False
2313 gdelta = False
2314 if v & revlog.REVLOGNGINLINEDATA:
2314 if v & revlog.REVLOGNGINLINEDATA:
2315 flags.append('inline')
2315 flags.append('inline')
2316 if v & revlog.REVLOGGENERALDELTA:
2316 if v & revlog.REVLOGGENERALDELTA:
2317 gdelta = True
2317 gdelta = True
2318 flags.append('generaldelta')
2318 flags.append('generaldelta')
2319 if not flags:
2319 if not flags:
2320 flags = ['(none)']
2320 flags = ['(none)']
2321
2321
2322 nummerges = 0
2322 nummerges = 0
2323 numfull = 0
2323 numfull = 0
2324 numprev = 0
2324 numprev = 0
2325 nump1 = 0
2325 nump1 = 0
2326 nump2 = 0
2326 nump2 = 0
2327 numother = 0
2327 numother = 0
2328 nump1prev = 0
2328 nump1prev = 0
2329 nump2prev = 0
2329 nump2prev = 0
2330 chainlengths = []
2330 chainlengths = []
2331
2331
2332 datasize = [None, 0, 0L]
2332 datasize = [None, 0, 0L]
2333 fullsize = [None, 0, 0L]
2333 fullsize = [None, 0, 0L]
2334 deltasize = [None, 0, 0L]
2334 deltasize = [None, 0, 0L]
2335
2335
2336 def addsize(size, l):
2336 def addsize(size, l):
2337 if l[0] is None or size < l[0]:
2337 if l[0] is None or size < l[0]:
2338 l[0] = size
2338 l[0] = size
2339 if size > l[1]:
2339 if size > l[1]:
2340 l[1] = size
2340 l[1] = size
2341 l[2] += size
2341 l[2] += size
2342
2342
2343 numrevs = len(r)
2343 numrevs = len(r)
2344 for rev in xrange(numrevs):
2344 for rev in xrange(numrevs):
2345 p1, p2 = r.parentrevs(rev)
2345 p1, p2 = r.parentrevs(rev)
2346 delta = r.deltaparent(rev)
2346 delta = r.deltaparent(rev)
2347 if format > 0:
2347 if format > 0:
2348 addsize(r.rawsize(rev), datasize)
2348 addsize(r.rawsize(rev), datasize)
2349 if p2 != nullrev:
2349 if p2 != nullrev:
2350 nummerges += 1
2350 nummerges += 1
2351 size = r.length(rev)
2351 size = r.length(rev)
2352 if delta == nullrev:
2352 if delta == nullrev:
2353 chainlengths.append(0)
2353 chainlengths.append(0)
2354 numfull += 1
2354 numfull += 1
2355 addsize(size, fullsize)
2355 addsize(size, fullsize)
2356 else:
2356 else:
2357 chainlengths.append(chainlengths[delta] + 1)
2357 chainlengths.append(chainlengths[delta] + 1)
2358 addsize(size, deltasize)
2358 addsize(size, deltasize)
2359 if delta == rev - 1:
2359 if delta == rev - 1:
2360 numprev += 1
2360 numprev += 1
2361 if delta == p1:
2361 if delta == p1:
2362 nump1prev += 1
2362 nump1prev += 1
2363 elif delta == p2:
2363 elif delta == p2:
2364 nump2prev += 1
2364 nump2prev += 1
2365 elif delta == p1:
2365 elif delta == p1:
2366 nump1 += 1
2366 nump1 += 1
2367 elif delta == p2:
2367 elif delta == p2:
2368 nump2 += 1
2368 nump2 += 1
2369 elif delta != nullrev:
2369 elif delta != nullrev:
2370 numother += 1
2370 numother += 1
2371
2371
2372 # Adjust size min value for empty cases
2372 # Adjust size min value for empty cases
2373 for size in (datasize, fullsize, deltasize):
2373 for size in (datasize, fullsize, deltasize):
2374 if size[0] is None:
2374 if size[0] is None:
2375 size[0] = 0
2375 size[0] = 0
2376
2376
2377 numdeltas = numrevs - numfull
2377 numdeltas = numrevs - numfull
2378 numoprev = numprev - nump1prev - nump2prev
2378 numoprev = numprev - nump1prev - nump2prev
2379 totalrawsize = datasize[2]
2379 totalrawsize = datasize[2]
2380 datasize[2] /= numrevs
2380 datasize[2] /= numrevs
2381 fulltotal = fullsize[2]
2381 fulltotal = fullsize[2]
2382 fullsize[2] /= numfull
2382 fullsize[2] /= numfull
2383 deltatotal = deltasize[2]
2383 deltatotal = deltasize[2]
2384 if numrevs - numfull > 0:
2384 if numrevs - numfull > 0:
2385 deltasize[2] /= numrevs - numfull
2385 deltasize[2] /= numrevs - numfull
2386 totalsize = fulltotal + deltatotal
2386 totalsize = fulltotal + deltatotal
2387 avgchainlen = sum(chainlengths) / numrevs
2387 avgchainlen = sum(chainlengths) / numrevs
2388 compratio = totalrawsize / totalsize
2388 compratio = totalrawsize / totalsize
2389
2389
2390 basedfmtstr = '%%%dd\n'
2390 basedfmtstr = '%%%dd\n'
2391 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2391 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2392
2392
2393 def dfmtstr(max):
2393 def dfmtstr(max):
2394 return basedfmtstr % len(str(max))
2394 return basedfmtstr % len(str(max))
2395 def pcfmtstr(max, padding=0):
2395 def pcfmtstr(max, padding=0):
2396 return basepcfmtstr % (len(str(max)), ' ' * padding)
2396 return basepcfmtstr % (len(str(max)), ' ' * padding)
2397
2397
2398 def pcfmt(value, total):
2398 def pcfmt(value, total):
2399 return (value, 100 * float(value) / total)
2399 return (value, 100 * float(value) / total)
2400
2400
2401 ui.write(('format : %d\n') % format)
2401 ui.write(('format : %d\n') % format)
2402 ui.write(('flags : %s\n') % ', '.join(flags))
2402 ui.write(('flags : %s\n') % ', '.join(flags))
2403
2403
2404 ui.write('\n')
2404 ui.write('\n')
2405 fmt = pcfmtstr(totalsize)
2405 fmt = pcfmtstr(totalsize)
2406 fmt2 = dfmtstr(totalsize)
2406 fmt2 = dfmtstr(totalsize)
2407 ui.write(('revisions : ') + fmt2 % numrevs)
2407 ui.write(('revisions : ') + fmt2 % numrevs)
2408 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2408 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2409 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2409 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2410 ui.write(('revisions : ') + fmt2 % numrevs)
2410 ui.write(('revisions : ') + fmt2 % numrevs)
2411 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2411 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2412 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2412 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2413 ui.write(('revision size : ') + fmt2 % totalsize)
2413 ui.write(('revision size : ') + fmt2 % totalsize)
2414 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2414 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2415 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2415 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2416
2416
2417 ui.write('\n')
2417 ui.write('\n')
2418 fmt = dfmtstr(max(avgchainlen, compratio))
2418 fmt = dfmtstr(max(avgchainlen, compratio))
2419 ui.write(('avg chain length : ') + fmt % avgchainlen)
2419 ui.write(('avg chain length : ') + fmt % avgchainlen)
2420 ui.write(('compression ratio : ') + fmt % compratio)
2420 ui.write(('compression ratio : ') + fmt % compratio)
2421
2421
2422 if format > 0:
2422 if format > 0:
2423 ui.write('\n')
2423 ui.write('\n')
2424 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2424 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2425 % tuple(datasize))
2425 % tuple(datasize))
2426 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2426 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2427 % tuple(fullsize))
2427 % tuple(fullsize))
2428 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2428 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2429 % tuple(deltasize))
2429 % tuple(deltasize))
2430
2430
2431 if numdeltas > 0:
2431 if numdeltas > 0:
2432 ui.write('\n')
2432 ui.write('\n')
2433 fmt = pcfmtstr(numdeltas)
2433 fmt = pcfmtstr(numdeltas)
2434 fmt2 = pcfmtstr(numdeltas, 4)
2434 fmt2 = pcfmtstr(numdeltas, 4)
2435 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2435 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2436 if numprev > 0:
2436 if numprev > 0:
2437 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2437 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2438 numprev))
2438 numprev))
2439 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2439 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2440 numprev))
2440 numprev))
2441 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2441 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2442 numprev))
2442 numprev))
2443 if gdelta:
2443 if gdelta:
2444 ui.write(('deltas against p1 : ')
2444 ui.write(('deltas against p1 : ')
2445 + fmt % pcfmt(nump1, numdeltas))
2445 + fmt % pcfmt(nump1, numdeltas))
2446 ui.write(('deltas against p2 : ')
2446 ui.write(('deltas against p2 : ')
2447 + fmt % pcfmt(nump2, numdeltas))
2447 + fmt % pcfmt(nump2, numdeltas))
2448 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2448 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2449 numdeltas))
2449 numdeltas))
2450
2450
2451 @command('debugrevspec', [], ('REVSPEC'))
2451 @command('debugrevspec', [], ('REVSPEC'))
2452 def debugrevspec(ui, repo, expr):
2452 def debugrevspec(ui, repo, expr):
2453 """parse and apply a revision specification
2453 """parse and apply a revision specification
2454
2454
2455 Use --verbose to print the parsed tree before and after aliases
2455 Use --verbose to print the parsed tree before and after aliases
2456 expansion.
2456 expansion.
2457 """
2457 """
2458 if ui.verbose:
2458 if ui.verbose:
2459 tree = revset.parse(expr)[0]
2459 tree = revset.parse(expr)[0]
2460 ui.note(revset.prettyformat(tree), "\n")
2460 ui.note(revset.prettyformat(tree), "\n")
2461 newtree = revset.findaliases(ui, tree)
2461 newtree = revset.findaliases(ui, tree)
2462 if newtree != tree:
2462 if newtree != tree:
2463 ui.note(revset.prettyformat(newtree), "\n")
2463 ui.note(revset.prettyformat(newtree), "\n")
2464 func = revset.match(ui, expr)
2464 func = revset.match(ui, expr)
2465 for c in func(repo, range(len(repo))):
2465 for c in func(repo, range(len(repo))):
2466 ui.write("%s\n" % c)
2466 ui.write("%s\n" % c)
2467
2467
2468 @command('debugsetparents', [], _('REV1 [REV2]'))
2468 @command('debugsetparents', [], _('REV1 [REV2]'))
2469 def debugsetparents(ui, repo, rev1, rev2=None):
2469 def debugsetparents(ui, repo, rev1, rev2=None):
2470 """manually set the parents of the current working directory
2470 """manually set the parents of the current working directory
2471
2471
2472 This is useful for writing repository conversion tools, but should
2472 This is useful for writing repository conversion tools, but should
2473 be used with care.
2473 be used with care.
2474
2474
2475 Returns 0 on success.
2475 Returns 0 on success.
2476 """
2476 """
2477
2477
2478 r1 = scmutil.revsingle(repo, rev1).node()
2478 r1 = scmutil.revsingle(repo, rev1).node()
2479 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2479 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2480
2480
2481 wlock = repo.wlock()
2481 wlock = repo.wlock()
2482 try:
2482 try:
2483 repo.setparents(r1, r2)
2483 repo.setparents(r1, r2)
2484 finally:
2484 finally:
2485 wlock.release()
2485 wlock.release()
2486
2486
2487 @command('debugstate',
2487 @command('debugstate',
2488 [('', 'nodates', None, _('do not display the saved mtime')),
2488 [('', 'nodates', None, _('do not display the saved mtime')),
2489 ('', 'datesort', None, _('sort by saved mtime'))],
2489 ('', 'datesort', None, _('sort by saved mtime'))],
2490 _('[OPTION]...'))
2490 _('[OPTION]...'))
2491 def debugstate(ui, repo, nodates=None, datesort=None):
2491 def debugstate(ui, repo, nodates=None, datesort=None):
2492 """show the contents of the current dirstate"""
2492 """show the contents of the current dirstate"""
2493 timestr = ""
2493 timestr = ""
2494 showdate = not nodates
2494 showdate = not nodates
2495 if datesort:
2495 if datesort:
2496 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2496 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2497 else:
2497 else:
2498 keyfunc = None # sort by filename
2498 keyfunc = None # sort by filename
2499 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2499 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2500 if showdate:
2500 if showdate:
2501 if ent[3] == -1:
2501 if ent[3] == -1:
2502 # Pad or slice to locale representation
2502 # Pad or slice to locale representation
2503 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2503 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2504 time.localtime(0)))
2504 time.localtime(0)))
2505 timestr = 'unset'
2505 timestr = 'unset'
2506 timestr = (timestr[:locale_len] +
2506 timestr = (timestr[:locale_len] +
2507 ' ' * (locale_len - len(timestr)))
2507 ' ' * (locale_len - len(timestr)))
2508 else:
2508 else:
2509 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2509 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2510 time.localtime(ent[3]))
2510 time.localtime(ent[3]))
2511 if ent[1] & 020000:
2511 if ent[1] & 020000:
2512 mode = 'lnk'
2512 mode = 'lnk'
2513 else:
2513 else:
2514 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2514 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2515 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2515 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2516 for f in repo.dirstate.copies():
2516 for f in repo.dirstate.copies():
2517 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2517 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2518
2518
2519 @command('debugsub',
2519 @command('debugsub',
2520 [('r', 'rev', '',
2520 [('r', 'rev', '',
2521 _('revision to check'), _('REV'))],
2521 _('revision to check'), _('REV'))],
2522 _('[-r REV] [REV]'))
2522 _('[-r REV] [REV]'))
2523 def debugsub(ui, repo, rev=None):
2523 def debugsub(ui, repo, rev=None):
2524 ctx = scmutil.revsingle(repo, rev, None)
2524 ctx = scmutil.revsingle(repo, rev, None)
2525 for k, v in sorted(ctx.substate.items()):
2525 for k, v in sorted(ctx.substate.items()):
2526 ui.write(('path %s\n') % k)
2526 ui.write(('path %s\n') % k)
2527 ui.write((' source %s\n') % v[0])
2527 ui.write((' source %s\n') % v[0])
2528 ui.write((' revision %s\n') % v[1])
2528 ui.write((' revision %s\n') % v[1])
2529
2529
2530 @command('debugsuccessorssets',
2530 @command('debugsuccessorssets',
2531 [],
2531 [],
2532 _('[REV]'))
2532 _('[REV]'))
2533 def debugsuccessorssets(ui, repo, *revs):
2533 def debugsuccessorssets(ui, repo, *revs):
2534 """show set of successors for revision
2534 """show set of successors for revision
2535
2535
2536 A successors set of changeset A is a consistent group of revisions that
2536 A successors set of changeset A is a consistent group of revisions that
2537 succeed A. It contains non-obsolete changesets only.
2537 succeed A. It contains non-obsolete changesets only.
2538
2538
2539 In most cases a changeset A has a single successors set containing a single
2539 In most cases a changeset A has a single successors set containing a single
2540 successor (changeset A replaced by A').
2540 successor (changeset A replaced by A').
2541
2541
2542 A changeset that is made obsolete with no successors are called "pruned".
2542 A changeset that is made obsolete with no successors are called "pruned".
2543 Such changesets have no successors sets at all.
2543 Such changesets have no successors sets at all.
2544
2544
2545 A changeset that has been "split" will have a successors set containing
2545 A changeset that has been "split" will have a successors set containing
2546 more than one successor.
2546 more than one successor.
2547
2547
2548 A changeset that has been rewritten in multiple different ways is called
2548 A changeset that has been rewritten in multiple different ways is called
2549 "divergent". Such changesets have multiple successor sets (each of which
2549 "divergent". Such changesets have multiple successor sets (each of which
2550 may also be split, i.e. have multiple successors).
2550 may also be split, i.e. have multiple successors).
2551
2551
2552 Results are displayed as follows::
2552 Results are displayed as follows::
2553
2553
2554 <rev1>
2554 <rev1>
2555 <successors-1A>
2555 <successors-1A>
2556 <rev2>
2556 <rev2>
2557 <successors-2A>
2557 <successors-2A>
2558 <successors-2B1> <successors-2B2> <successors-2B3>
2558 <successors-2B1> <successors-2B2> <successors-2B3>
2559
2559
2560 Here rev2 has two possible (i.e. divergent) successors sets. The first
2560 Here rev2 has two possible (i.e. divergent) successors sets. The first
2561 holds one element, whereas the second holds three (i.e. the changeset has
2561 holds one element, whereas the second holds three (i.e. the changeset has
2562 been split).
2562 been split).
2563 """
2563 """
2564 # passed to successorssets caching computation from one call to another
2564 # passed to successorssets caching computation from one call to another
2565 cache = {}
2565 cache = {}
2566 ctx2str = str
2566 ctx2str = str
2567 node2str = short
2567 node2str = short
2568 if ui.debug():
2568 if ui.debug():
2569 def ctx2str(ctx):
2569 def ctx2str(ctx):
2570 return ctx.hex()
2570 return ctx.hex()
2571 node2str = hex
2571 node2str = hex
2572 for rev in scmutil.revrange(repo, revs):
2572 for rev in scmutil.revrange(repo, revs):
2573 ctx = repo[rev]
2573 ctx = repo[rev]
2574 ui.write('%s\n'% ctx2str(ctx))
2574 ui.write('%s\n'% ctx2str(ctx))
2575 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2575 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2576 if succsset:
2576 if succsset:
2577 ui.write(' ')
2577 ui.write(' ')
2578 ui.write(node2str(succsset[0]))
2578 ui.write(node2str(succsset[0]))
2579 for node in succsset[1:]:
2579 for node in succsset[1:]:
2580 ui.write(' ')
2580 ui.write(' ')
2581 ui.write(node2str(node))
2581 ui.write(node2str(node))
2582 ui.write('\n')
2582 ui.write('\n')
2583
2583
2584 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2584 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2585 def debugwalk(ui, repo, *pats, **opts):
2585 def debugwalk(ui, repo, *pats, **opts):
2586 """show how files match on given patterns"""
2586 """show how files match on given patterns"""
2587 m = scmutil.match(repo[None], pats, opts)
2587 m = scmutil.match(repo[None], pats, opts)
2588 items = list(repo.walk(m))
2588 items = list(repo.walk(m))
2589 if not items:
2589 if not items:
2590 return
2590 return
2591 f = lambda fn: fn
2591 f = lambda fn: fn
2592 if ui.configbool('ui', 'slash') and os.sep != '/':
2592 if ui.configbool('ui', 'slash') and os.sep != '/':
2593 f = lambda fn: util.normpath(fn)
2593 f = lambda fn: util.normpath(fn)
2594 fmt = 'f %%-%ds %%-%ds %%s' % (
2594 fmt = 'f %%-%ds %%-%ds %%s' % (
2595 max([len(abs) for abs in items]),
2595 max([len(abs) for abs in items]),
2596 max([len(m.rel(abs)) for abs in items]))
2596 max([len(m.rel(abs)) for abs in items]))
2597 for abs in items:
2597 for abs in items:
2598 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2598 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2599 ui.write("%s\n" % line.rstrip())
2599 ui.write("%s\n" % line.rstrip())
2600
2600
2601 @command('debugwireargs',
2601 @command('debugwireargs',
2602 [('', 'three', '', 'three'),
2602 [('', 'three', '', 'three'),
2603 ('', 'four', '', 'four'),
2603 ('', 'four', '', 'four'),
2604 ('', 'five', '', 'five'),
2604 ('', 'five', '', 'five'),
2605 ] + remoteopts,
2605 ] + remoteopts,
2606 _('REPO [OPTIONS]... [ONE [TWO]]'))
2606 _('REPO [OPTIONS]... [ONE [TWO]]'))
2607 def debugwireargs(ui, repopath, *vals, **opts):
2607 def debugwireargs(ui, repopath, *vals, **opts):
2608 repo = hg.peer(ui, opts, repopath)
2608 repo = hg.peer(ui, opts, repopath)
2609 for opt in remoteopts:
2609 for opt in remoteopts:
2610 del opts[opt[1]]
2610 del opts[opt[1]]
2611 args = {}
2611 args = {}
2612 for k, v in opts.iteritems():
2612 for k, v in opts.iteritems():
2613 if v:
2613 if v:
2614 args[k] = v
2614 args[k] = v
2615 # run twice to check that we don't mess up the stream for the next command
2615 # run twice to check that we don't mess up the stream for the next command
2616 res1 = repo.debugwireargs(*vals, **args)
2616 res1 = repo.debugwireargs(*vals, **args)
2617 res2 = repo.debugwireargs(*vals, **args)
2617 res2 = repo.debugwireargs(*vals, **args)
2618 ui.write("%s\n" % res1)
2618 ui.write("%s\n" % res1)
2619 if res1 != res2:
2619 if res1 != res2:
2620 ui.warn("%s\n" % res2)
2620 ui.warn("%s\n" % res2)
2621
2621
2622 @command('^diff',
2622 @command('^diff',
2623 [('r', 'rev', [], _('revision'), _('REV')),
2623 [('r', 'rev', [], _('revision'), _('REV')),
2624 ('c', 'change', '', _('change made by revision'), _('REV'))
2624 ('c', 'change', '', _('change made by revision'), _('REV'))
2625 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2625 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2626 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2626 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2627 def diff(ui, repo, *pats, **opts):
2627 def diff(ui, repo, *pats, **opts):
2628 """diff repository (or selected files)
2628 """diff repository (or selected files)
2629
2629
2630 Show differences between revisions for the specified files.
2630 Show differences between revisions for the specified files.
2631
2631
2632 Differences between files are shown using the unified diff format.
2632 Differences between files are shown using the unified diff format.
2633
2633
2634 .. note::
2634 .. note::
2635 diff may generate unexpected results for merges, as it will
2635 diff may generate unexpected results for merges, as it will
2636 default to comparing against the working directory's first
2636 default to comparing against the working directory's first
2637 parent changeset if no revisions are specified.
2637 parent changeset if no revisions are specified.
2638
2638
2639 When two revision arguments are given, then changes are shown
2639 When two revision arguments are given, then changes are shown
2640 between those revisions. If only one revision is specified then
2640 between those revisions. If only one revision is specified then
2641 that revision is compared to the working directory, and, when no
2641 that revision is compared to the working directory, and, when no
2642 revisions are specified, the working directory files are compared
2642 revisions are specified, the working directory files are compared
2643 to its parent.
2643 to its parent.
2644
2644
2645 Alternatively you can specify -c/--change with a revision to see
2645 Alternatively you can specify -c/--change with a revision to see
2646 the changes in that changeset relative to its first parent.
2646 the changes in that changeset relative to its first parent.
2647
2647
2648 Without the -a/--text option, diff will avoid generating diffs of
2648 Without the -a/--text option, diff will avoid generating diffs of
2649 files it detects as binary. With -a, diff will generate a diff
2649 files it detects as binary. With -a, diff will generate a diff
2650 anyway, probably with undesirable results.
2650 anyway, probably with undesirable results.
2651
2651
2652 Use the -g/--git option to generate diffs in the git extended diff
2652 Use the -g/--git option to generate diffs in the git extended diff
2653 format. For more information, read :hg:`help diffs`.
2653 format. For more information, read :hg:`help diffs`.
2654
2654
2655 .. container:: verbose
2655 .. container:: verbose
2656
2656
2657 Examples:
2657 Examples:
2658
2658
2659 - compare a file in the current working directory to its parent::
2659 - compare a file in the current working directory to its parent::
2660
2660
2661 hg diff foo.c
2661 hg diff foo.c
2662
2662
2663 - compare two historical versions of a directory, with rename info::
2663 - compare two historical versions of a directory, with rename info::
2664
2664
2665 hg diff --git -r 1.0:1.2 lib/
2665 hg diff --git -r 1.0:1.2 lib/
2666
2666
2667 - get change stats relative to the last change on some date::
2667 - get change stats relative to the last change on some date::
2668
2668
2669 hg diff --stat -r "date('may 2')"
2669 hg diff --stat -r "date('may 2')"
2670
2670
2671 - diff all newly-added files that contain a keyword::
2671 - diff all newly-added files that contain a keyword::
2672
2672
2673 hg diff "set:added() and grep(GNU)"
2673 hg diff "set:added() and grep(GNU)"
2674
2674
2675 - compare a revision and its parents::
2675 - compare a revision and its parents::
2676
2676
2677 hg diff -c 9353 # compare against first parent
2677 hg diff -c 9353 # compare against first parent
2678 hg diff -r 9353^:9353 # same using revset syntax
2678 hg diff -r 9353^:9353 # same using revset syntax
2679 hg diff -r 9353^2:9353 # compare against the second parent
2679 hg diff -r 9353^2:9353 # compare against the second parent
2680
2680
2681 Returns 0 on success.
2681 Returns 0 on success.
2682 """
2682 """
2683
2683
2684 revs = opts.get('rev')
2684 revs = opts.get('rev')
2685 change = opts.get('change')
2685 change = opts.get('change')
2686 stat = opts.get('stat')
2686 stat = opts.get('stat')
2687 reverse = opts.get('reverse')
2687 reverse = opts.get('reverse')
2688
2688
2689 if revs and change:
2689 if revs and change:
2690 msg = _('cannot specify --rev and --change at the same time')
2690 msg = _('cannot specify --rev and --change at the same time')
2691 raise util.Abort(msg)
2691 raise util.Abort(msg)
2692 elif change:
2692 elif change:
2693 node2 = scmutil.revsingle(repo, change, None).node()
2693 node2 = scmutil.revsingle(repo, change, None).node()
2694 node1 = repo[node2].p1().node()
2694 node1 = repo[node2].p1().node()
2695 else:
2695 else:
2696 node1, node2 = scmutil.revpair(repo, revs)
2696 node1, node2 = scmutil.revpair(repo, revs)
2697
2697
2698 if reverse:
2698 if reverse:
2699 node1, node2 = node2, node1
2699 node1, node2 = node2, node1
2700
2700
2701 diffopts = patch.diffopts(ui, opts)
2701 diffopts = patch.diffopts(ui, opts)
2702 m = scmutil.match(repo[node2], pats, opts)
2702 m = scmutil.match(repo[node2], pats, opts)
2703 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2703 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2704 listsubrepos=opts.get('subrepos'))
2704 listsubrepos=opts.get('subrepos'))
2705
2705
2706 @command('^export',
2706 @command('^export',
2707 [('o', 'output', '',
2707 [('o', 'output', '',
2708 _('print output to file with formatted name'), _('FORMAT')),
2708 _('print output to file with formatted name'), _('FORMAT')),
2709 ('', 'switch-parent', None, _('diff against the second parent')),
2709 ('', 'switch-parent', None, _('diff against the second parent')),
2710 ('r', 'rev', [], _('revisions to export'), _('REV')),
2710 ('r', 'rev', [], _('revisions to export'), _('REV')),
2711 ] + diffopts,
2711 ] + diffopts,
2712 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2712 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2713 def export(ui, repo, *changesets, **opts):
2713 def export(ui, repo, *changesets, **opts):
2714 """dump the header and diffs for one or more changesets
2714 """dump the header and diffs for one or more changesets
2715
2715
2716 Print the changeset header and diffs for one or more revisions.
2716 Print the changeset header and diffs for one or more revisions.
2717 If no revision is given, the parent of the working directory is used.
2717
2718
2718 The information shown in the changeset header is: author, date,
2719 The information shown in the changeset header is: author, date,
2719 branch name (if non-default), changeset hash, parent(s) and commit
2720 branch name (if non-default), changeset hash, parent(s) and commit
2720 comment.
2721 comment.
2721
2722
2722 .. note::
2723 .. note::
2723 export may generate unexpected diff output for merge
2724 export may generate unexpected diff output for merge
2724 changesets, as it will compare the merge changeset against its
2725 changesets, as it will compare the merge changeset against its
2725 first parent only.
2726 first parent only.
2726
2727
2727 Output may be to a file, in which case the name of the file is
2728 Output may be to a file, in which case the name of the file is
2728 given using a format string. The formatting rules are as follows:
2729 given using a format string. The formatting rules are as follows:
2729
2730
2730 :``%%``: literal "%" character
2731 :``%%``: literal "%" character
2731 :``%H``: changeset hash (40 hexadecimal digits)
2732 :``%H``: changeset hash (40 hexadecimal digits)
2732 :``%N``: number of patches being generated
2733 :``%N``: number of patches being generated
2733 :``%R``: changeset revision number
2734 :``%R``: changeset revision number
2734 :``%b``: basename of the exporting repository
2735 :``%b``: basename of the exporting repository
2735 :``%h``: short-form changeset hash (12 hexadecimal digits)
2736 :``%h``: short-form changeset hash (12 hexadecimal digits)
2736 :``%m``: first line of the commit message (only alphanumeric characters)
2737 :``%m``: first line of the commit message (only alphanumeric characters)
2737 :``%n``: zero-padded sequence number, starting at 1
2738 :``%n``: zero-padded sequence number, starting at 1
2738 :``%r``: zero-padded changeset revision number
2739 :``%r``: zero-padded changeset revision number
2739
2740
2740 Without the -a/--text option, export will avoid generating diffs
2741 Without the -a/--text option, export will avoid generating diffs
2741 of files it detects as binary. With -a, export will generate a
2742 of files it detects as binary. With -a, export will generate a
2742 diff anyway, probably with undesirable results.
2743 diff anyway, probably with undesirable results.
2743
2744
2744 Use the -g/--git option to generate diffs in the git extended diff
2745 Use the -g/--git option to generate diffs in the git extended diff
2745 format. See :hg:`help diffs` for more information.
2746 format. See :hg:`help diffs` for more information.
2746
2747
2747 With the --switch-parent option, the diff will be against the
2748 With the --switch-parent option, the diff will be against the
2748 second parent. It can be useful to review a merge.
2749 second parent. It can be useful to review a merge.
2749
2750
2750 .. container:: verbose
2751 .. container:: verbose
2751
2752
2752 Examples:
2753 Examples:
2753
2754
2754 - use export and import to transplant a bugfix to the current
2755 - use export and import to transplant a bugfix to the current
2755 branch::
2756 branch::
2756
2757
2757 hg export -r 9353 | hg import -
2758 hg export -r 9353 | hg import -
2758
2759
2759 - export all the changesets between two revisions to a file with
2760 - export all the changesets between two revisions to a file with
2760 rename information::
2761 rename information::
2761
2762
2762 hg export --git -r 123:150 > changes.txt
2763 hg export --git -r 123:150 > changes.txt
2763
2764
2764 - split outgoing changes into a series of patches with
2765 - split outgoing changes into a series of patches with
2765 descriptive names::
2766 descriptive names::
2766
2767
2767 hg export -r "outgoing()" -o "%n-%m.patch"
2768 hg export -r "outgoing()" -o "%n-%m.patch"
2768
2769
2769 Returns 0 on success.
2770 Returns 0 on success.
2770 """
2771 """
2771 changesets += tuple(opts.get('rev', []))
2772 changesets += tuple(opts.get('rev', []))
2773 if not changesets:
2774 changesets = ['.']
2772 revs = scmutil.revrange(repo, changesets)
2775 revs = scmutil.revrange(repo, changesets)
2773 if not revs:
2776 if not revs:
2774 raise util.Abort(_("export requires at least one changeset"))
2777 raise util.Abort(_("export requires at least one changeset"))
2775 if len(revs) > 1:
2778 if len(revs) > 1:
2776 ui.note(_('exporting patches:\n'))
2779 ui.note(_('exporting patches:\n'))
2777 else:
2780 else:
2778 ui.note(_('exporting patch:\n'))
2781 ui.note(_('exporting patch:\n'))
2779 cmdutil.export(repo, revs, template=opts.get('output'),
2782 cmdutil.export(repo, revs, template=opts.get('output'),
2780 switch_parent=opts.get('switch_parent'),
2783 switch_parent=opts.get('switch_parent'),
2781 opts=patch.diffopts(ui, opts))
2784 opts=patch.diffopts(ui, opts))
2782
2785
2783 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2786 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2784 def forget(ui, repo, *pats, **opts):
2787 def forget(ui, repo, *pats, **opts):
2785 """forget the specified files on the next commit
2788 """forget the specified files on the next commit
2786
2789
2787 Mark the specified files so they will no longer be tracked
2790 Mark the specified files so they will no longer be tracked
2788 after the next commit.
2791 after the next commit.
2789
2792
2790 This only removes files from the current branch, not from the
2793 This only removes files from the current branch, not from the
2791 entire project history, and it does not delete them from the
2794 entire project history, and it does not delete them from the
2792 working directory.
2795 working directory.
2793
2796
2794 To undo a forget before the next commit, see :hg:`add`.
2797 To undo a forget before the next commit, see :hg:`add`.
2795
2798
2796 .. container:: verbose
2799 .. container:: verbose
2797
2800
2798 Examples:
2801 Examples:
2799
2802
2800 - forget newly-added binary files::
2803 - forget newly-added binary files::
2801
2804
2802 hg forget "set:added() and binary()"
2805 hg forget "set:added() and binary()"
2803
2806
2804 - forget files that would be excluded by .hgignore::
2807 - forget files that would be excluded by .hgignore::
2805
2808
2806 hg forget "set:hgignore()"
2809 hg forget "set:hgignore()"
2807
2810
2808 Returns 0 on success.
2811 Returns 0 on success.
2809 """
2812 """
2810
2813
2811 if not pats:
2814 if not pats:
2812 raise util.Abort(_('no files specified'))
2815 raise util.Abort(_('no files specified'))
2813
2816
2814 m = scmutil.match(repo[None], pats, opts)
2817 m = scmutil.match(repo[None], pats, opts)
2815 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2818 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2816 return rejected and 1 or 0
2819 return rejected and 1 or 0
2817
2820
2818 @command(
2821 @command(
2819 'graft',
2822 'graft',
2820 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2823 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2821 ('c', 'continue', False, _('resume interrupted graft')),
2824 ('c', 'continue', False, _('resume interrupted graft')),
2822 ('e', 'edit', False, _('invoke editor on commit messages')),
2825 ('e', 'edit', False, _('invoke editor on commit messages')),
2823 ('', 'log', None, _('append graft info to log message')),
2826 ('', 'log', None, _('append graft info to log message')),
2824 ('D', 'currentdate', False,
2827 ('D', 'currentdate', False,
2825 _('record the current date as commit date')),
2828 _('record the current date as commit date')),
2826 ('U', 'currentuser', False,
2829 ('U', 'currentuser', False,
2827 _('record the current user as committer'), _('DATE'))]
2830 _('record the current user as committer'), _('DATE'))]
2828 + commitopts2 + mergetoolopts + dryrunopts,
2831 + commitopts2 + mergetoolopts + dryrunopts,
2829 _('[OPTION]... [-r] REV...'))
2832 _('[OPTION]... [-r] REV...'))
2830 def graft(ui, repo, *revs, **opts):
2833 def graft(ui, repo, *revs, **opts):
2831 '''copy changes from other branches onto the current branch
2834 '''copy changes from other branches onto the current branch
2832
2835
2833 This command uses Mercurial's merge logic to copy individual
2836 This command uses Mercurial's merge logic to copy individual
2834 changes from other branches without merging branches in the
2837 changes from other branches without merging branches in the
2835 history graph. This is sometimes known as 'backporting' or
2838 history graph. This is sometimes known as 'backporting' or
2836 'cherry-picking'. By default, graft will copy user, date, and
2839 'cherry-picking'. By default, graft will copy user, date, and
2837 description from the source changesets.
2840 description from the source changesets.
2838
2841
2839 Changesets that are ancestors of the current revision, that have
2842 Changesets that are ancestors of the current revision, that have
2840 already been grafted, or that are merges will be skipped.
2843 already been grafted, or that are merges will be skipped.
2841
2844
2842 If --log is specified, log messages will have a comment appended
2845 If --log is specified, log messages will have a comment appended
2843 of the form::
2846 of the form::
2844
2847
2845 (grafted from CHANGESETHASH)
2848 (grafted from CHANGESETHASH)
2846
2849
2847 If a graft merge results in conflicts, the graft process is
2850 If a graft merge results in conflicts, the graft process is
2848 interrupted so that the current merge can be manually resolved.
2851 interrupted so that the current merge can be manually resolved.
2849 Once all conflicts are addressed, the graft process can be
2852 Once all conflicts are addressed, the graft process can be
2850 continued with the -c/--continue option.
2853 continued with the -c/--continue option.
2851
2854
2852 .. note::
2855 .. note::
2853 The -c/--continue option does not reapply earlier options.
2856 The -c/--continue option does not reapply earlier options.
2854
2857
2855 .. container:: verbose
2858 .. container:: verbose
2856
2859
2857 Examples:
2860 Examples:
2858
2861
2859 - copy a single change to the stable branch and edit its description::
2862 - copy a single change to the stable branch and edit its description::
2860
2863
2861 hg update stable
2864 hg update stable
2862 hg graft --edit 9393
2865 hg graft --edit 9393
2863
2866
2864 - graft a range of changesets with one exception, updating dates::
2867 - graft a range of changesets with one exception, updating dates::
2865
2868
2866 hg graft -D "2085::2093 and not 2091"
2869 hg graft -D "2085::2093 and not 2091"
2867
2870
2868 - continue a graft after resolving conflicts::
2871 - continue a graft after resolving conflicts::
2869
2872
2870 hg graft -c
2873 hg graft -c
2871
2874
2872 - show the source of a grafted changeset::
2875 - show the source of a grafted changeset::
2873
2876
2874 hg log --debug -r tip
2877 hg log --debug -r tip
2875
2878
2876 Returns 0 on successful completion.
2879 Returns 0 on successful completion.
2877 '''
2880 '''
2878
2881
2879 revs = list(revs)
2882 revs = list(revs)
2880 revs.extend(opts['rev'])
2883 revs.extend(opts['rev'])
2881
2884
2882 if not opts.get('user') and opts.get('currentuser'):
2885 if not opts.get('user') and opts.get('currentuser'):
2883 opts['user'] = ui.username()
2886 opts['user'] = ui.username()
2884 if not opts.get('date') and opts.get('currentdate'):
2887 if not opts.get('date') and opts.get('currentdate'):
2885 opts['date'] = "%d %d" % util.makedate()
2888 opts['date'] = "%d %d" % util.makedate()
2886
2889
2887 editor = None
2890 editor = None
2888 if opts.get('edit'):
2891 if opts.get('edit'):
2889 editor = cmdutil.commitforceeditor
2892 editor = cmdutil.commitforceeditor
2890
2893
2891 cont = False
2894 cont = False
2892 if opts['continue']:
2895 if opts['continue']:
2893 cont = True
2896 cont = True
2894 if revs:
2897 if revs:
2895 raise util.Abort(_("can't specify --continue and revisions"))
2898 raise util.Abort(_("can't specify --continue and revisions"))
2896 # read in unfinished revisions
2899 # read in unfinished revisions
2897 try:
2900 try:
2898 nodes = repo.opener.read('graftstate').splitlines()
2901 nodes = repo.opener.read('graftstate').splitlines()
2899 revs = [repo[node].rev() for node in nodes]
2902 revs = [repo[node].rev() for node in nodes]
2900 except IOError, inst:
2903 except IOError, inst:
2901 if inst.errno != errno.ENOENT:
2904 if inst.errno != errno.ENOENT:
2902 raise
2905 raise
2903 raise util.Abort(_("no graft state found, can't continue"))
2906 raise util.Abort(_("no graft state found, can't continue"))
2904 else:
2907 else:
2905 cmdutil.bailifchanged(repo)
2908 cmdutil.bailifchanged(repo)
2906 if not revs:
2909 if not revs:
2907 raise util.Abort(_('no revisions specified'))
2910 raise util.Abort(_('no revisions specified'))
2908 revs = scmutil.revrange(repo, revs)
2911 revs = scmutil.revrange(repo, revs)
2909
2912
2910 # check for merges
2913 # check for merges
2911 for rev in repo.revs('%ld and merge()', revs):
2914 for rev in repo.revs('%ld and merge()', revs):
2912 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2915 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2913 revs.remove(rev)
2916 revs.remove(rev)
2914 if not revs:
2917 if not revs:
2915 return -1
2918 return -1
2916
2919
2917 # check for ancestors of dest branch
2920 # check for ancestors of dest branch
2918 crev = repo['.'].rev()
2921 crev = repo['.'].rev()
2919 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2922 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2920 # don't mutate while iterating, create a copy
2923 # don't mutate while iterating, create a copy
2921 for rev in list(revs):
2924 for rev in list(revs):
2922 if rev in ancestors:
2925 if rev in ancestors:
2923 ui.warn(_('skipping ancestor revision %s\n') % rev)
2926 ui.warn(_('skipping ancestor revision %s\n') % rev)
2924 revs.remove(rev)
2927 revs.remove(rev)
2925 if not revs:
2928 if not revs:
2926 return -1
2929 return -1
2927
2930
2928 # analyze revs for earlier grafts
2931 # analyze revs for earlier grafts
2929 ids = {}
2932 ids = {}
2930 for ctx in repo.set("%ld", revs):
2933 for ctx in repo.set("%ld", revs):
2931 ids[ctx.hex()] = ctx.rev()
2934 ids[ctx.hex()] = ctx.rev()
2932 n = ctx.extra().get('source')
2935 n = ctx.extra().get('source')
2933 if n:
2936 if n:
2934 ids[n] = ctx.rev()
2937 ids[n] = ctx.rev()
2935
2938
2936 # check ancestors for earlier grafts
2939 # check ancestors for earlier grafts
2937 ui.debug('scanning for duplicate grafts\n')
2940 ui.debug('scanning for duplicate grafts\n')
2938
2941
2939 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2942 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2940 ctx = repo[rev]
2943 ctx = repo[rev]
2941 n = ctx.extra().get('source')
2944 n = ctx.extra().get('source')
2942 if n in ids:
2945 if n in ids:
2943 r = repo[n].rev()
2946 r = repo[n].rev()
2944 if r in revs:
2947 if r in revs:
2945 ui.warn(_('skipping already grafted revision %s\n') % r)
2948 ui.warn(_('skipping already grafted revision %s\n') % r)
2946 revs.remove(r)
2949 revs.remove(r)
2947 elif ids[n] in revs:
2950 elif ids[n] in revs:
2948 ui.warn(_('skipping already grafted revision %s '
2951 ui.warn(_('skipping already grafted revision %s '
2949 '(same origin %d)\n') % (ids[n], r))
2952 '(same origin %d)\n') % (ids[n], r))
2950 revs.remove(ids[n])
2953 revs.remove(ids[n])
2951 elif ctx.hex() in ids:
2954 elif ctx.hex() in ids:
2952 r = ids[ctx.hex()]
2955 r = ids[ctx.hex()]
2953 ui.warn(_('skipping already grafted revision %s '
2956 ui.warn(_('skipping already grafted revision %s '
2954 '(was grafted from %d)\n') % (r, rev))
2957 '(was grafted from %d)\n') % (r, rev))
2955 revs.remove(r)
2958 revs.remove(r)
2956 if not revs:
2959 if not revs:
2957 return -1
2960 return -1
2958
2961
2959 wlock = repo.wlock()
2962 wlock = repo.wlock()
2960 try:
2963 try:
2961 current = repo['.']
2964 current = repo['.']
2962 for pos, ctx in enumerate(repo.set("%ld", revs)):
2965 for pos, ctx in enumerate(repo.set("%ld", revs)):
2963
2966
2964 ui.status(_('grafting revision %s\n') % ctx.rev())
2967 ui.status(_('grafting revision %s\n') % ctx.rev())
2965 if opts.get('dry_run'):
2968 if opts.get('dry_run'):
2966 continue
2969 continue
2967
2970
2968 source = ctx.extra().get('source')
2971 source = ctx.extra().get('source')
2969 if not source:
2972 if not source:
2970 source = ctx.hex()
2973 source = ctx.hex()
2971 extra = {'source': source}
2974 extra = {'source': source}
2972 user = ctx.user()
2975 user = ctx.user()
2973 if opts.get('user'):
2976 if opts.get('user'):
2974 user = opts['user']
2977 user = opts['user']
2975 date = ctx.date()
2978 date = ctx.date()
2976 if opts.get('date'):
2979 if opts.get('date'):
2977 date = opts['date']
2980 date = opts['date']
2978 message = ctx.description()
2981 message = ctx.description()
2979 if opts.get('log'):
2982 if opts.get('log'):
2980 message += '\n(grafted from %s)' % ctx.hex()
2983 message += '\n(grafted from %s)' % ctx.hex()
2981
2984
2982 # we don't merge the first commit when continuing
2985 # we don't merge the first commit when continuing
2983 if not cont:
2986 if not cont:
2984 # perform the graft merge with p1(rev) as 'ancestor'
2987 # perform the graft merge with p1(rev) as 'ancestor'
2985 try:
2988 try:
2986 # ui.forcemerge is an internal variable, do not document
2989 # ui.forcemerge is an internal variable, do not document
2987 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2990 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2988 stats = mergemod.update(repo, ctx.node(), True, True, False,
2991 stats = mergemod.update(repo, ctx.node(), True, True, False,
2989 ctx.p1().node())
2992 ctx.p1().node())
2990 finally:
2993 finally:
2991 repo.ui.setconfig('ui', 'forcemerge', '')
2994 repo.ui.setconfig('ui', 'forcemerge', '')
2992 # report any conflicts
2995 # report any conflicts
2993 if stats and stats[3] > 0:
2996 if stats and stats[3] > 0:
2994 # write out state for --continue
2997 # write out state for --continue
2995 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2998 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2996 repo.opener.write('graftstate', ''.join(nodelines))
2999 repo.opener.write('graftstate', ''.join(nodelines))
2997 raise util.Abort(
3000 raise util.Abort(
2998 _("unresolved conflicts, can't continue"),
3001 _("unresolved conflicts, can't continue"),
2999 hint=_('use hg resolve and hg graft --continue'))
3002 hint=_('use hg resolve and hg graft --continue'))
3000 else:
3003 else:
3001 cont = False
3004 cont = False
3002
3005
3003 # drop the second merge parent
3006 # drop the second merge parent
3004 repo.setparents(current.node(), nullid)
3007 repo.setparents(current.node(), nullid)
3005 repo.dirstate.write()
3008 repo.dirstate.write()
3006 # fix up dirstate for copies and renames
3009 # fix up dirstate for copies and renames
3007 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3010 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3008
3011
3009 # commit
3012 # commit
3010 node = repo.commit(text=message, user=user,
3013 node = repo.commit(text=message, user=user,
3011 date=date, extra=extra, editor=editor)
3014 date=date, extra=extra, editor=editor)
3012 if node is None:
3015 if node is None:
3013 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3016 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3014 else:
3017 else:
3015 current = repo[node]
3018 current = repo[node]
3016 finally:
3019 finally:
3017 wlock.release()
3020 wlock.release()
3018
3021
3019 # remove state when we complete successfully
3022 # remove state when we complete successfully
3020 if not opts.get('dry_run'):
3023 if not opts.get('dry_run'):
3021 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3024 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3022
3025
3023 return 0
3026 return 0
3024
3027
3025 @command('grep',
3028 @command('grep',
3026 [('0', 'print0', None, _('end fields with NUL')),
3029 [('0', 'print0', None, _('end fields with NUL')),
3027 ('', 'all', None, _('print all revisions that match')),
3030 ('', 'all', None, _('print all revisions that match')),
3028 ('a', 'text', None, _('treat all files as text')),
3031 ('a', 'text', None, _('treat all files as text')),
3029 ('f', 'follow', None,
3032 ('f', 'follow', None,
3030 _('follow changeset history,'
3033 _('follow changeset history,'
3031 ' or file history across copies and renames')),
3034 ' or file history across copies and renames')),
3032 ('i', 'ignore-case', None, _('ignore case when matching')),
3035 ('i', 'ignore-case', None, _('ignore case when matching')),
3033 ('l', 'files-with-matches', None,
3036 ('l', 'files-with-matches', None,
3034 _('print only filenames and revisions that match')),
3037 _('print only filenames and revisions that match')),
3035 ('n', 'line-number', None, _('print matching line numbers')),
3038 ('n', 'line-number', None, _('print matching line numbers')),
3036 ('r', 'rev', [],
3039 ('r', 'rev', [],
3037 _('only search files changed within revision range'), _('REV')),
3040 _('only search files changed within revision range'), _('REV')),
3038 ('u', 'user', None, _('list the author (long with -v)')),
3041 ('u', 'user', None, _('list the author (long with -v)')),
3039 ('d', 'date', None, _('list the date (short with -q)')),
3042 ('d', 'date', None, _('list the date (short with -q)')),
3040 ] + walkopts,
3043 ] + walkopts,
3041 _('[OPTION]... PATTERN [FILE]...'))
3044 _('[OPTION]... PATTERN [FILE]...'))
3042 def grep(ui, repo, pattern, *pats, **opts):
3045 def grep(ui, repo, pattern, *pats, **opts):
3043 """search for a pattern in specified files and revisions
3046 """search for a pattern in specified files and revisions
3044
3047
3045 Search revisions of files for a regular expression.
3048 Search revisions of files for a regular expression.
3046
3049
3047 This command behaves differently than Unix grep. It only accepts
3050 This command behaves differently than Unix grep. It only accepts
3048 Python/Perl regexps. It searches repository history, not the
3051 Python/Perl regexps. It searches repository history, not the
3049 working directory. It always prints the revision number in which a
3052 working directory. It always prints the revision number in which a
3050 match appears.
3053 match appears.
3051
3054
3052 By default, grep only prints output for the first revision of a
3055 By default, grep only prints output for the first revision of a
3053 file in which it finds a match. To get it to print every revision
3056 file in which it finds a match. To get it to print every revision
3054 that contains a change in match status ("-" for a match that
3057 that contains a change in match status ("-" for a match that
3055 becomes a non-match, or "+" for a non-match that becomes a match),
3058 becomes a non-match, or "+" for a non-match that becomes a match),
3056 use the --all flag.
3059 use the --all flag.
3057
3060
3058 Returns 0 if a match is found, 1 otherwise.
3061 Returns 0 if a match is found, 1 otherwise.
3059 """
3062 """
3060 reflags = re.M
3063 reflags = re.M
3061 if opts.get('ignore_case'):
3064 if opts.get('ignore_case'):
3062 reflags |= re.I
3065 reflags |= re.I
3063 try:
3066 try:
3064 regexp = util.compilere(pattern, reflags)
3067 regexp = util.compilere(pattern, reflags)
3065 except re.error, inst:
3068 except re.error, inst:
3066 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3069 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3067 return 1
3070 return 1
3068 sep, eol = ':', '\n'
3071 sep, eol = ':', '\n'
3069 if opts.get('print0'):
3072 if opts.get('print0'):
3070 sep = eol = '\0'
3073 sep = eol = '\0'
3071
3074
3072 getfile = util.lrucachefunc(repo.file)
3075 getfile = util.lrucachefunc(repo.file)
3073
3076
3074 def matchlines(body):
3077 def matchlines(body):
3075 begin = 0
3078 begin = 0
3076 linenum = 0
3079 linenum = 0
3077 while begin < len(body):
3080 while begin < len(body):
3078 match = regexp.search(body, begin)
3081 match = regexp.search(body, begin)
3079 if not match:
3082 if not match:
3080 break
3083 break
3081 mstart, mend = match.span()
3084 mstart, mend = match.span()
3082 linenum += body.count('\n', begin, mstart) + 1
3085 linenum += body.count('\n', begin, mstart) + 1
3083 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3086 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3084 begin = body.find('\n', mend) + 1 or len(body) + 1
3087 begin = body.find('\n', mend) + 1 or len(body) + 1
3085 lend = begin - 1
3088 lend = begin - 1
3086 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3089 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3087
3090
3088 class linestate(object):
3091 class linestate(object):
3089 def __init__(self, line, linenum, colstart, colend):
3092 def __init__(self, line, linenum, colstart, colend):
3090 self.line = line
3093 self.line = line
3091 self.linenum = linenum
3094 self.linenum = linenum
3092 self.colstart = colstart
3095 self.colstart = colstart
3093 self.colend = colend
3096 self.colend = colend
3094
3097
3095 def __hash__(self):
3098 def __hash__(self):
3096 return hash((self.linenum, self.line))
3099 return hash((self.linenum, self.line))
3097
3100
3098 def __eq__(self, other):
3101 def __eq__(self, other):
3099 return self.line == other.line
3102 return self.line == other.line
3100
3103
3101 matches = {}
3104 matches = {}
3102 copies = {}
3105 copies = {}
3103 def grepbody(fn, rev, body):
3106 def grepbody(fn, rev, body):
3104 matches[rev].setdefault(fn, [])
3107 matches[rev].setdefault(fn, [])
3105 m = matches[rev][fn]
3108 m = matches[rev][fn]
3106 for lnum, cstart, cend, line in matchlines(body):
3109 for lnum, cstart, cend, line in matchlines(body):
3107 s = linestate(line, lnum, cstart, cend)
3110 s = linestate(line, lnum, cstart, cend)
3108 m.append(s)
3111 m.append(s)
3109
3112
3110 def difflinestates(a, b):
3113 def difflinestates(a, b):
3111 sm = difflib.SequenceMatcher(None, a, b)
3114 sm = difflib.SequenceMatcher(None, a, b)
3112 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3115 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3113 if tag == 'insert':
3116 if tag == 'insert':
3114 for i in xrange(blo, bhi):
3117 for i in xrange(blo, bhi):
3115 yield ('+', b[i])
3118 yield ('+', b[i])
3116 elif tag == 'delete':
3119 elif tag == 'delete':
3117 for i in xrange(alo, ahi):
3120 for i in xrange(alo, ahi):
3118 yield ('-', a[i])
3121 yield ('-', a[i])
3119 elif tag == 'replace':
3122 elif tag == 'replace':
3120 for i in xrange(alo, ahi):
3123 for i in xrange(alo, ahi):
3121 yield ('-', a[i])
3124 yield ('-', a[i])
3122 for i in xrange(blo, bhi):
3125 for i in xrange(blo, bhi):
3123 yield ('+', b[i])
3126 yield ('+', b[i])
3124
3127
3125 def display(fn, ctx, pstates, states):
3128 def display(fn, ctx, pstates, states):
3126 rev = ctx.rev()
3129 rev = ctx.rev()
3127 datefunc = ui.quiet and util.shortdate or util.datestr
3130 datefunc = ui.quiet and util.shortdate or util.datestr
3128 found = False
3131 found = False
3129 filerevmatches = {}
3132 filerevmatches = {}
3130 def binary():
3133 def binary():
3131 flog = getfile(fn)
3134 flog = getfile(fn)
3132 return util.binary(flog.read(ctx.filenode(fn)))
3135 return util.binary(flog.read(ctx.filenode(fn)))
3133
3136
3134 if opts.get('all'):
3137 if opts.get('all'):
3135 iter = difflinestates(pstates, states)
3138 iter = difflinestates(pstates, states)
3136 else:
3139 else:
3137 iter = [('', l) for l in states]
3140 iter = [('', l) for l in states]
3138 for change, l in iter:
3141 for change, l in iter:
3139 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3142 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3140 before, match, after = None, None, None
3143 before, match, after = None, None, None
3141
3144
3142 if opts.get('line_number'):
3145 if opts.get('line_number'):
3143 cols.append((str(l.linenum), 'grep.linenumber'))
3146 cols.append((str(l.linenum), 'grep.linenumber'))
3144 if opts.get('all'):
3147 if opts.get('all'):
3145 cols.append((change, 'grep.change'))
3148 cols.append((change, 'grep.change'))
3146 if opts.get('user'):
3149 if opts.get('user'):
3147 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3150 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3148 if opts.get('date'):
3151 if opts.get('date'):
3149 cols.append((datefunc(ctx.date()), 'grep.date'))
3152 cols.append((datefunc(ctx.date()), 'grep.date'))
3150 if opts.get('files_with_matches'):
3153 if opts.get('files_with_matches'):
3151 c = (fn, rev)
3154 c = (fn, rev)
3152 if c in filerevmatches:
3155 if c in filerevmatches:
3153 continue
3156 continue
3154 filerevmatches[c] = 1
3157 filerevmatches[c] = 1
3155 else:
3158 else:
3156 before = l.line[:l.colstart]
3159 before = l.line[:l.colstart]
3157 match = l.line[l.colstart:l.colend]
3160 match = l.line[l.colstart:l.colend]
3158 after = l.line[l.colend:]
3161 after = l.line[l.colend:]
3159 for col, label in cols[:-1]:
3162 for col, label in cols[:-1]:
3160 ui.write(col, label=label)
3163 ui.write(col, label=label)
3161 ui.write(sep, label='grep.sep')
3164 ui.write(sep, label='grep.sep')
3162 ui.write(cols[-1][0], label=cols[-1][1])
3165 ui.write(cols[-1][0], label=cols[-1][1])
3163 if before is not None:
3166 if before is not None:
3164 ui.write(sep, label='grep.sep')
3167 ui.write(sep, label='grep.sep')
3165 if not opts.get('text') and binary():
3168 if not opts.get('text') and binary():
3166 ui.write(" Binary file matches")
3169 ui.write(" Binary file matches")
3167 else:
3170 else:
3168 ui.write(before)
3171 ui.write(before)
3169 ui.write(match, label='grep.match')
3172 ui.write(match, label='grep.match')
3170 ui.write(after)
3173 ui.write(after)
3171 ui.write(eol)
3174 ui.write(eol)
3172 found = True
3175 found = True
3173 return found
3176 return found
3174
3177
3175 skip = {}
3178 skip = {}
3176 revfiles = {}
3179 revfiles = {}
3177 matchfn = scmutil.match(repo[None], pats, opts)
3180 matchfn = scmutil.match(repo[None], pats, opts)
3178 found = False
3181 found = False
3179 follow = opts.get('follow')
3182 follow = opts.get('follow')
3180
3183
3181 def prep(ctx, fns):
3184 def prep(ctx, fns):
3182 rev = ctx.rev()
3185 rev = ctx.rev()
3183 pctx = ctx.p1()
3186 pctx = ctx.p1()
3184 parent = pctx.rev()
3187 parent = pctx.rev()
3185 matches.setdefault(rev, {})
3188 matches.setdefault(rev, {})
3186 matches.setdefault(parent, {})
3189 matches.setdefault(parent, {})
3187 files = revfiles.setdefault(rev, [])
3190 files = revfiles.setdefault(rev, [])
3188 for fn in fns:
3191 for fn in fns:
3189 flog = getfile(fn)
3192 flog = getfile(fn)
3190 try:
3193 try:
3191 fnode = ctx.filenode(fn)
3194 fnode = ctx.filenode(fn)
3192 except error.LookupError:
3195 except error.LookupError:
3193 continue
3196 continue
3194
3197
3195 copied = flog.renamed(fnode)
3198 copied = flog.renamed(fnode)
3196 copy = follow and copied and copied[0]
3199 copy = follow and copied and copied[0]
3197 if copy:
3200 if copy:
3198 copies.setdefault(rev, {})[fn] = copy
3201 copies.setdefault(rev, {})[fn] = copy
3199 if fn in skip:
3202 if fn in skip:
3200 if copy:
3203 if copy:
3201 skip[copy] = True
3204 skip[copy] = True
3202 continue
3205 continue
3203 files.append(fn)
3206 files.append(fn)
3204
3207
3205 if fn not in matches[rev]:
3208 if fn not in matches[rev]:
3206 grepbody(fn, rev, flog.read(fnode))
3209 grepbody(fn, rev, flog.read(fnode))
3207
3210
3208 pfn = copy or fn
3211 pfn = copy or fn
3209 if pfn not in matches[parent]:
3212 if pfn not in matches[parent]:
3210 try:
3213 try:
3211 fnode = pctx.filenode(pfn)
3214 fnode = pctx.filenode(pfn)
3212 grepbody(pfn, parent, flog.read(fnode))
3215 grepbody(pfn, parent, flog.read(fnode))
3213 except error.LookupError:
3216 except error.LookupError:
3214 pass
3217 pass
3215
3218
3216 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3219 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3217 rev = ctx.rev()
3220 rev = ctx.rev()
3218 parent = ctx.p1().rev()
3221 parent = ctx.p1().rev()
3219 for fn in sorted(revfiles.get(rev, [])):
3222 for fn in sorted(revfiles.get(rev, [])):
3220 states = matches[rev][fn]
3223 states = matches[rev][fn]
3221 copy = copies.get(rev, {}).get(fn)
3224 copy = copies.get(rev, {}).get(fn)
3222 if fn in skip:
3225 if fn in skip:
3223 if copy:
3226 if copy:
3224 skip[copy] = True
3227 skip[copy] = True
3225 continue
3228 continue
3226 pstates = matches.get(parent, {}).get(copy or fn, [])
3229 pstates = matches.get(parent, {}).get(copy or fn, [])
3227 if pstates or states:
3230 if pstates or states:
3228 r = display(fn, ctx, pstates, states)
3231 r = display(fn, ctx, pstates, states)
3229 found = found or r
3232 found = found or r
3230 if r and not opts.get('all'):
3233 if r and not opts.get('all'):
3231 skip[fn] = True
3234 skip[fn] = True
3232 if copy:
3235 if copy:
3233 skip[copy] = True
3236 skip[copy] = True
3234 del matches[rev]
3237 del matches[rev]
3235 del revfiles[rev]
3238 del revfiles[rev]
3236
3239
3237 return not found
3240 return not found
3238
3241
3239 @command('heads',
3242 @command('heads',
3240 [('r', 'rev', '',
3243 [('r', 'rev', '',
3241 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3244 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3242 ('t', 'topo', False, _('show topological heads only')),
3245 ('t', 'topo', False, _('show topological heads only')),
3243 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3246 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3244 ('c', 'closed', False, _('show normal and closed branch heads')),
3247 ('c', 'closed', False, _('show normal and closed branch heads')),
3245 ] + templateopts,
3248 ] + templateopts,
3246 _('[-ct] [-r STARTREV] [REV]...'))
3249 _('[-ct] [-r STARTREV] [REV]...'))
3247 def heads(ui, repo, *branchrevs, **opts):
3250 def heads(ui, repo, *branchrevs, **opts):
3248 """show current repository heads or show branch heads
3251 """show current repository heads or show branch heads
3249
3252
3250 With no arguments, show all repository branch heads.
3253 With no arguments, show all repository branch heads.
3251
3254
3252 Repository "heads" are changesets with no child changesets. They are
3255 Repository "heads" are changesets with no child changesets. They are
3253 where development generally takes place and are the usual targets
3256 where development generally takes place and are the usual targets
3254 for update and merge operations. Branch heads are changesets that have
3257 for update and merge operations. Branch heads are changesets that have
3255 no child changeset on the same branch.
3258 no child changeset on the same branch.
3256
3259
3257 If one or more REVs are given, only branch heads on the branches
3260 If one or more REVs are given, only branch heads on the branches
3258 associated with the specified changesets are shown. This means
3261 associated with the specified changesets are shown. This means
3259 that you can use :hg:`heads foo` to see the heads on a branch
3262 that you can use :hg:`heads foo` to see the heads on a branch
3260 named ``foo``.
3263 named ``foo``.
3261
3264
3262 If -c/--closed is specified, also show branch heads marked closed
3265 If -c/--closed is specified, also show branch heads marked closed
3263 (see :hg:`commit --close-branch`).
3266 (see :hg:`commit --close-branch`).
3264
3267
3265 If STARTREV is specified, only those heads that are descendants of
3268 If STARTREV is specified, only those heads that are descendants of
3266 STARTREV will be displayed.
3269 STARTREV will be displayed.
3267
3270
3268 If -t/--topo is specified, named branch mechanics will be ignored and only
3271 If -t/--topo is specified, named branch mechanics will be ignored and only
3269 changesets without children will be shown.
3272 changesets without children will be shown.
3270
3273
3271 Returns 0 if matching heads are found, 1 if not.
3274 Returns 0 if matching heads are found, 1 if not.
3272 """
3275 """
3273
3276
3274 start = None
3277 start = None
3275 if 'rev' in opts:
3278 if 'rev' in opts:
3276 start = scmutil.revsingle(repo, opts['rev'], None).node()
3279 start = scmutil.revsingle(repo, opts['rev'], None).node()
3277
3280
3278 if opts.get('topo'):
3281 if opts.get('topo'):
3279 heads = [repo[h] for h in repo.heads(start)]
3282 heads = [repo[h] for h in repo.heads(start)]
3280 else:
3283 else:
3281 heads = []
3284 heads = []
3282 for branch in repo.branchmap():
3285 for branch in repo.branchmap():
3283 heads += repo.branchheads(branch, start, opts.get('closed'))
3286 heads += repo.branchheads(branch, start, opts.get('closed'))
3284 heads = [repo[h] for h in heads]
3287 heads = [repo[h] for h in heads]
3285
3288
3286 if branchrevs:
3289 if branchrevs:
3287 branches = set(repo[br].branch() for br in branchrevs)
3290 branches = set(repo[br].branch() for br in branchrevs)
3288 heads = [h for h in heads if h.branch() in branches]
3291 heads = [h for h in heads if h.branch() in branches]
3289
3292
3290 if opts.get('active') and branchrevs:
3293 if opts.get('active') and branchrevs:
3291 dagheads = repo.heads(start)
3294 dagheads = repo.heads(start)
3292 heads = [h for h in heads if h.node() in dagheads]
3295 heads = [h for h in heads if h.node() in dagheads]
3293
3296
3294 if branchrevs:
3297 if branchrevs:
3295 haveheads = set(h.branch() for h in heads)
3298 haveheads = set(h.branch() for h in heads)
3296 if branches - haveheads:
3299 if branches - haveheads:
3297 headless = ', '.join(b for b in branches - haveheads)
3300 headless = ', '.join(b for b in branches - haveheads)
3298 msg = _('no open branch heads found on branches %s')
3301 msg = _('no open branch heads found on branches %s')
3299 if opts.get('rev'):
3302 if opts.get('rev'):
3300 msg += _(' (started at %s)') % opts['rev']
3303 msg += _(' (started at %s)') % opts['rev']
3301 ui.warn((msg + '\n') % headless)
3304 ui.warn((msg + '\n') % headless)
3302
3305
3303 if not heads:
3306 if not heads:
3304 return 1
3307 return 1
3305
3308
3306 heads = sorted(heads, key=lambda x: -x.rev())
3309 heads = sorted(heads, key=lambda x: -x.rev())
3307 displayer = cmdutil.show_changeset(ui, repo, opts)
3310 displayer = cmdutil.show_changeset(ui, repo, opts)
3308 for ctx in heads:
3311 for ctx in heads:
3309 displayer.show(ctx)
3312 displayer.show(ctx)
3310 displayer.close()
3313 displayer.close()
3311
3314
3312 @command('help',
3315 @command('help',
3313 [('e', 'extension', None, _('show only help for extensions')),
3316 [('e', 'extension', None, _('show only help for extensions')),
3314 ('c', 'command', None, _('show only help for commands')),
3317 ('c', 'command', None, _('show only help for commands')),
3315 ('k', 'keyword', '', _('show topics matching keyword')),
3318 ('k', 'keyword', '', _('show topics matching keyword')),
3316 ],
3319 ],
3317 _('[-ec] [TOPIC]'))
3320 _('[-ec] [TOPIC]'))
3318 def help_(ui, name=None, **opts):
3321 def help_(ui, name=None, **opts):
3319 """show help for a given topic or a help overview
3322 """show help for a given topic or a help overview
3320
3323
3321 With no arguments, print a list of commands with short help messages.
3324 With no arguments, print a list of commands with short help messages.
3322
3325
3323 Given a topic, extension, or command name, print help for that
3326 Given a topic, extension, or command name, print help for that
3324 topic.
3327 topic.
3325
3328
3326 Returns 0 if successful.
3329 Returns 0 if successful.
3327 """
3330 """
3328
3331
3329 textwidth = min(ui.termwidth(), 80) - 2
3332 textwidth = min(ui.termwidth(), 80) - 2
3330
3333
3331 keep = ui.verbose and ['verbose'] or []
3334 keep = ui.verbose and ['verbose'] or []
3332 text = help.help_(ui, name, **opts)
3335 text = help.help_(ui, name, **opts)
3333
3336
3334 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3337 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3335 if 'verbose' in pruned:
3338 if 'verbose' in pruned:
3336 keep.append('omitted')
3339 keep.append('omitted')
3337 else:
3340 else:
3338 keep.append('notomitted')
3341 keep.append('notomitted')
3339 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3342 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3340 ui.write(formatted)
3343 ui.write(formatted)
3341
3344
3342
3345
3343 @command('identify|id',
3346 @command('identify|id',
3344 [('r', 'rev', '',
3347 [('r', 'rev', '',
3345 _('identify the specified revision'), _('REV')),
3348 _('identify the specified revision'), _('REV')),
3346 ('n', 'num', None, _('show local revision number')),
3349 ('n', 'num', None, _('show local revision number')),
3347 ('i', 'id', None, _('show global revision id')),
3350 ('i', 'id', None, _('show global revision id')),
3348 ('b', 'branch', None, _('show branch')),
3351 ('b', 'branch', None, _('show branch')),
3349 ('t', 'tags', None, _('show tags')),
3352 ('t', 'tags', None, _('show tags')),
3350 ('B', 'bookmarks', None, _('show bookmarks')),
3353 ('B', 'bookmarks', None, _('show bookmarks')),
3351 ] + remoteopts,
3354 ] + remoteopts,
3352 _('[-nibtB] [-r REV] [SOURCE]'))
3355 _('[-nibtB] [-r REV] [SOURCE]'))
3353 def identify(ui, repo, source=None, rev=None,
3356 def identify(ui, repo, source=None, rev=None,
3354 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3357 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3355 """identify the working copy or specified revision
3358 """identify the working copy or specified revision
3356
3359
3357 Print a summary identifying the repository state at REV using one or
3360 Print a summary identifying the repository state at REV using one or
3358 two parent hash identifiers, followed by a "+" if the working
3361 two parent hash identifiers, followed by a "+" if the working
3359 directory has uncommitted changes, the branch name (if not default),
3362 directory has uncommitted changes, the branch name (if not default),
3360 a list of tags, and a list of bookmarks.
3363 a list of tags, and a list of bookmarks.
3361
3364
3362 When REV is not given, print a summary of the current state of the
3365 When REV is not given, print a summary of the current state of the
3363 repository.
3366 repository.
3364
3367
3365 Specifying a path to a repository root or Mercurial bundle will
3368 Specifying a path to a repository root or Mercurial bundle will
3366 cause lookup to operate on that repository/bundle.
3369 cause lookup to operate on that repository/bundle.
3367
3370
3368 .. container:: verbose
3371 .. container:: verbose
3369
3372
3370 Examples:
3373 Examples:
3371
3374
3372 - generate a build identifier for the working directory::
3375 - generate a build identifier for the working directory::
3373
3376
3374 hg id --id > build-id.dat
3377 hg id --id > build-id.dat
3375
3378
3376 - find the revision corresponding to a tag::
3379 - find the revision corresponding to a tag::
3377
3380
3378 hg id -n -r 1.3
3381 hg id -n -r 1.3
3379
3382
3380 - check the most recent revision of a remote repository::
3383 - check the most recent revision of a remote repository::
3381
3384
3382 hg id -r tip http://selenic.com/hg/
3385 hg id -r tip http://selenic.com/hg/
3383
3386
3384 Returns 0 if successful.
3387 Returns 0 if successful.
3385 """
3388 """
3386
3389
3387 if not repo and not source:
3390 if not repo and not source:
3388 raise util.Abort(_("there is no Mercurial repository here "
3391 raise util.Abort(_("there is no Mercurial repository here "
3389 "(.hg not found)"))
3392 "(.hg not found)"))
3390
3393
3391 hexfunc = ui.debugflag and hex or short
3394 hexfunc = ui.debugflag and hex or short
3392 default = not (num or id or branch or tags or bookmarks)
3395 default = not (num or id or branch or tags or bookmarks)
3393 output = []
3396 output = []
3394 revs = []
3397 revs = []
3395
3398
3396 if source:
3399 if source:
3397 source, branches = hg.parseurl(ui.expandpath(source))
3400 source, branches = hg.parseurl(ui.expandpath(source))
3398 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3401 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3399 repo = peer.local()
3402 repo = peer.local()
3400 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3403 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3401
3404
3402 if not repo:
3405 if not repo:
3403 if num or branch or tags:
3406 if num or branch or tags:
3404 raise util.Abort(
3407 raise util.Abort(
3405 _("can't query remote revision number, branch, or tags"))
3408 _("can't query remote revision number, branch, or tags"))
3406 if not rev and revs:
3409 if not rev and revs:
3407 rev = revs[0]
3410 rev = revs[0]
3408 if not rev:
3411 if not rev:
3409 rev = "tip"
3412 rev = "tip"
3410
3413
3411 remoterev = peer.lookup(rev)
3414 remoterev = peer.lookup(rev)
3412 if default or id:
3415 if default or id:
3413 output = [hexfunc(remoterev)]
3416 output = [hexfunc(remoterev)]
3414
3417
3415 def getbms():
3418 def getbms():
3416 bms = []
3419 bms = []
3417
3420
3418 if 'bookmarks' in peer.listkeys('namespaces'):
3421 if 'bookmarks' in peer.listkeys('namespaces'):
3419 hexremoterev = hex(remoterev)
3422 hexremoterev = hex(remoterev)
3420 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3423 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3421 if bmr == hexremoterev]
3424 if bmr == hexremoterev]
3422
3425
3423 return sorted(bms)
3426 return sorted(bms)
3424
3427
3425 if bookmarks:
3428 if bookmarks:
3426 output.extend(getbms())
3429 output.extend(getbms())
3427 elif default and not ui.quiet:
3430 elif default and not ui.quiet:
3428 # multiple bookmarks for a single parent separated by '/'
3431 # multiple bookmarks for a single parent separated by '/'
3429 bm = '/'.join(getbms())
3432 bm = '/'.join(getbms())
3430 if bm:
3433 if bm:
3431 output.append(bm)
3434 output.append(bm)
3432 else:
3435 else:
3433 if not rev:
3436 if not rev:
3434 ctx = repo[None]
3437 ctx = repo[None]
3435 parents = ctx.parents()
3438 parents = ctx.parents()
3436 changed = ""
3439 changed = ""
3437 if default or id or num:
3440 if default or id or num:
3438 if (util.any(repo.status())
3441 if (util.any(repo.status())
3439 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3442 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3440 changed = '+'
3443 changed = '+'
3441 if default or id:
3444 if default or id:
3442 output = ["%s%s" %
3445 output = ["%s%s" %
3443 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3446 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3444 if num:
3447 if num:
3445 output.append("%s%s" %
3448 output.append("%s%s" %
3446 ('+'.join([str(p.rev()) for p in parents]), changed))
3449 ('+'.join([str(p.rev()) for p in parents]), changed))
3447 else:
3450 else:
3448 ctx = scmutil.revsingle(repo, rev)
3451 ctx = scmutil.revsingle(repo, rev)
3449 if default or id:
3452 if default or id:
3450 output = [hexfunc(ctx.node())]
3453 output = [hexfunc(ctx.node())]
3451 if num:
3454 if num:
3452 output.append(str(ctx.rev()))
3455 output.append(str(ctx.rev()))
3453
3456
3454 if default and not ui.quiet:
3457 if default and not ui.quiet:
3455 b = ctx.branch()
3458 b = ctx.branch()
3456 if b != 'default':
3459 if b != 'default':
3457 output.append("(%s)" % b)
3460 output.append("(%s)" % b)
3458
3461
3459 # multiple tags for a single parent separated by '/'
3462 # multiple tags for a single parent separated by '/'
3460 t = '/'.join(ctx.tags())
3463 t = '/'.join(ctx.tags())
3461 if t:
3464 if t:
3462 output.append(t)
3465 output.append(t)
3463
3466
3464 # multiple bookmarks for a single parent separated by '/'
3467 # multiple bookmarks for a single parent separated by '/'
3465 bm = '/'.join(ctx.bookmarks())
3468 bm = '/'.join(ctx.bookmarks())
3466 if bm:
3469 if bm:
3467 output.append(bm)
3470 output.append(bm)
3468 else:
3471 else:
3469 if branch:
3472 if branch:
3470 output.append(ctx.branch())
3473 output.append(ctx.branch())
3471
3474
3472 if tags:
3475 if tags:
3473 output.extend(ctx.tags())
3476 output.extend(ctx.tags())
3474
3477
3475 if bookmarks:
3478 if bookmarks:
3476 output.extend(ctx.bookmarks())
3479 output.extend(ctx.bookmarks())
3477
3480
3478 ui.write("%s\n" % ' '.join(output))
3481 ui.write("%s\n" % ' '.join(output))
3479
3482
3480 @command('import|patch',
3483 @command('import|patch',
3481 [('p', 'strip', 1,
3484 [('p', 'strip', 1,
3482 _('directory strip option for patch. This has the same '
3485 _('directory strip option for patch. This has the same '
3483 'meaning as the corresponding patch option'), _('NUM')),
3486 'meaning as the corresponding patch option'), _('NUM')),
3484 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3487 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3485 ('e', 'edit', False, _('invoke editor on commit messages')),
3488 ('e', 'edit', False, _('invoke editor on commit messages')),
3486 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3489 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3487 ('', 'no-commit', None,
3490 ('', 'no-commit', None,
3488 _("don't commit, just update the working directory")),
3491 _("don't commit, just update the working directory")),
3489 ('', 'bypass', None,
3492 ('', 'bypass', None,
3490 _("apply patch without touching the working directory")),
3493 _("apply patch without touching the working directory")),
3491 ('', 'exact', None,
3494 ('', 'exact', None,
3492 _('apply patch to the nodes from which it was generated')),
3495 _('apply patch to the nodes from which it was generated')),
3493 ('', 'import-branch', None,
3496 ('', 'import-branch', None,
3494 _('use any branch information in patch (implied by --exact)'))] +
3497 _('use any branch information in patch (implied by --exact)'))] +
3495 commitopts + commitopts2 + similarityopts,
3498 commitopts + commitopts2 + similarityopts,
3496 _('[OPTION]... PATCH...'))
3499 _('[OPTION]... PATCH...'))
3497 def import_(ui, repo, patch1=None, *patches, **opts):
3500 def import_(ui, repo, patch1=None, *patches, **opts):
3498 """import an ordered set of patches
3501 """import an ordered set of patches
3499
3502
3500 Import a list of patches and commit them individually (unless
3503 Import a list of patches and commit them individually (unless
3501 --no-commit is specified).
3504 --no-commit is specified).
3502
3505
3503 If there are outstanding changes in the working directory, import
3506 If there are outstanding changes in the working directory, import
3504 will abort unless given the -f/--force flag.
3507 will abort unless given the -f/--force flag.
3505
3508
3506 You can import a patch straight from a mail message. Even patches
3509 You can import a patch straight from a mail message. Even patches
3507 as attachments work (to use the body part, it must have type
3510 as attachments work (to use the body part, it must have type
3508 text/plain or text/x-patch). From and Subject headers of email
3511 text/plain or text/x-patch). From and Subject headers of email
3509 message are used as default committer and commit message. All
3512 message are used as default committer and commit message. All
3510 text/plain body parts before first diff are added to commit
3513 text/plain body parts before first diff are added to commit
3511 message.
3514 message.
3512
3515
3513 If the imported patch was generated by :hg:`export`, user and
3516 If the imported patch was generated by :hg:`export`, user and
3514 description from patch override values from message headers and
3517 description from patch override values from message headers and
3515 body. Values given on command line with -m/--message and -u/--user
3518 body. Values given on command line with -m/--message and -u/--user
3516 override these.
3519 override these.
3517
3520
3518 If --exact is specified, import will set the working directory to
3521 If --exact is specified, import will set the working directory to
3519 the parent of each patch before applying it, and will abort if the
3522 the parent of each patch before applying it, and will abort if the
3520 resulting changeset has a different ID than the one recorded in
3523 resulting changeset has a different ID than the one recorded in
3521 the patch. This may happen due to character set problems or other
3524 the patch. This may happen due to character set problems or other
3522 deficiencies in the text patch format.
3525 deficiencies in the text patch format.
3523
3526
3524 Use --bypass to apply and commit patches directly to the
3527 Use --bypass to apply and commit patches directly to the
3525 repository, not touching the working directory. Without --exact,
3528 repository, not touching the working directory. Without --exact,
3526 patches will be applied on top of the working directory parent
3529 patches will be applied on top of the working directory parent
3527 revision.
3530 revision.
3528
3531
3529 With -s/--similarity, hg will attempt to discover renames and
3532 With -s/--similarity, hg will attempt to discover renames and
3530 copies in the patch in the same way as :hg:`addremove`.
3533 copies in the patch in the same way as :hg:`addremove`.
3531
3534
3532 To read a patch from standard input, use "-" as the patch name. If
3535 To read a patch from standard input, use "-" as the patch name. If
3533 a URL is specified, the patch will be downloaded from it.
3536 a URL is specified, the patch will be downloaded from it.
3534 See :hg:`help dates` for a list of formats valid for -d/--date.
3537 See :hg:`help dates` for a list of formats valid for -d/--date.
3535
3538
3536 .. container:: verbose
3539 .. container:: verbose
3537
3540
3538 Examples:
3541 Examples:
3539
3542
3540 - import a traditional patch from a website and detect renames::
3543 - import a traditional patch from a website and detect renames::
3541
3544
3542 hg import -s 80 http://example.com/bugfix.patch
3545 hg import -s 80 http://example.com/bugfix.patch
3543
3546
3544 - import a changeset from an hgweb server::
3547 - import a changeset from an hgweb server::
3545
3548
3546 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3549 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3547
3550
3548 - import all the patches in an Unix-style mbox::
3551 - import all the patches in an Unix-style mbox::
3549
3552
3550 hg import incoming-patches.mbox
3553 hg import incoming-patches.mbox
3551
3554
3552 - attempt to exactly restore an exported changeset (not always
3555 - attempt to exactly restore an exported changeset (not always
3553 possible)::
3556 possible)::
3554
3557
3555 hg import --exact proposed-fix.patch
3558 hg import --exact proposed-fix.patch
3556
3559
3557 Returns 0 on success.
3560 Returns 0 on success.
3558 """
3561 """
3559
3562
3560 if not patch1:
3563 if not patch1:
3561 raise util.Abort(_('need at least one patch to import'))
3564 raise util.Abort(_('need at least one patch to import'))
3562
3565
3563 patches = (patch1,) + patches
3566 patches = (patch1,) + patches
3564
3567
3565 date = opts.get('date')
3568 date = opts.get('date')
3566 if date:
3569 if date:
3567 opts['date'] = util.parsedate(date)
3570 opts['date'] = util.parsedate(date)
3568
3571
3569 editor = cmdutil.commiteditor
3572 editor = cmdutil.commiteditor
3570 if opts.get('edit'):
3573 if opts.get('edit'):
3571 editor = cmdutil.commitforceeditor
3574 editor = cmdutil.commitforceeditor
3572
3575
3573 update = not opts.get('bypass')
3576 update = not opts.get('bypass')
3574 if not update and opts.get('no_commit'):
3577 if not update and opts.get('no_commit'):
3575 raise util.Abort(_('cannot use --no-commit with --bypass'))
3578 raise util.Abort(_('cannot use --no-commit with --bypass'))
3576 try:
3579 try:
3577 sim = float(opts.get('similarity') or 0)
3580 sim = float(opts.get('similarity') or 0)
3578 except ValueError:
3581 except ValueError:
3579 raise util.Abort(_('similarity must be a number'))
3582 raise util.Abort(_('similarity must be a number'))
3580 if sim < 0 or sim > 100:
3583 if sim < 0 or sim > 100:
3581 raise util.Abort(_('similarity must be between 0 and 100'))
3584 raise util.Abort(_('similarity must be between 0 and 100'))
3582 if sim and not update:
3585 if sim and not update:
3583 raise util.Abort(_('cannot use --similarity with --bypass'))
3586 raise util.Abort(_('cannot use --similarity with --bypass'))
3584
3587
3585 if (opts.get('exact') or not opts.get('force')) and update:
3588 if (opts.get('exact') or not opts.get('force')) and update:
3586 cmdutil.bailifchanged(repo)
3589 cmdutil.bailifchanged(repo)
3587
3590
3588 base = opts["base"]
3591 base = opts["base"]
3589 strip = opts["strip"]
3592 strip = opts["strip"]
3590 wlock = lock = tr = None
3593 wlock = lock = tr = None
3591 msgs = []
3594 msgs = []
3592
3595
3593 def checkexact(repo, n, nodeid):
3596 def checkexact(repo, n, nodeid):
3594 if opts.get('exact') and hex(n) != nodeid:
3597 if opts.get('exact') and hex(n) != nodeid:
3595 raise util.Abort(_('patch is damaged or loses information'))
3598 raise util.Abort(_('patch is damaged or loses information'))
3596
3599
3597 def tryone(ui, hunk, parents):
3600 def tryone(ui, hunk, parents):
3598 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3601 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3599 patch.extract(ui, hunk)
3602 patch.extract(ui, hunk)
3600
3603
3601 if not tmpname:
3604 if not tmpname:
3602 return (None, None)
3605 return (None, None)
3603 msg = _('applied to working directory')
3606 msg = _('applied to working directory')
3604
3607
3605 try:
3608 try:
3606 cmdline_message = cmdutil.logmessage(ui, opts)
3609 cmdline_message = cmdutil.logmessage(ui, opts)
3607 if cmdline_message:
3610 if cmdline_message:
3608 # pickup the cmdline msg
3611 # pickup the cmdline msg
3609 message = cmdline_message
3612 message = cmdline_message
3610 elif message:
3613 elif message:
3611 # pickup the patch msg
3614 # pickup the patch msg
3612 message = message.strip()
3615 message = message.strip()
3613 else:
3616 else:
3614 # launch the editor
3617 # launch the editor
3615 message = None
3618 message = None
3616 ui.debug('message:\n%s\n' % message)
3619 ui.debug('message:\n%s\n' % message)
3617
3620
3618 if len(parents) == 1:
3621 if len(parents) == 1:
3619 parents.append(repo[nullid])
3622 parents.append(repo[nullid])
3620 if opts.get('exact'):
3623 if opts.get('exact'):
3621 if not nodeid or not p1:
3624 if not nodeid or not p1:
3622 raise util.Abort(_('not a Mercurial patch'))
3625 raise util.Abort(_('not a Mercurial patch'))
3623 p1 = repo[p1]
3626 p1 = repo[p1]
3624 p2 = repo[p2 or nullid]
3627 p2 = repo[p2 or nullid]
3625 elif p2:
3628 elif p2:
3626 try:
3629 try:
3627 p1 = repo[p1]
3630 p1 = repo[p1]
3628 p2 = repo[p2]
3631 p2 = repo[p2]
3629 # Without any options, consider p2 only if the
3632 # Without any options, consider p2 only if the
3630 # patch is being applied on top of the recorded
3633 # patch is being applied on top of the recorded
3631 # first parent.
3634 # first parent.
3632 if p1 != parents[0]:
3635 if p1 != parents[0]:
3633 p1 = parents[0]
3636 p1 = parents[0]
3634 p2 = repo[nullid]
3637 p2 = repo[nullid]
3635 except error.RepoError:
3638 except error.RepoError:
3636 p1, p2 = parents
3639 p1, p2 = parents
3637 else:
3640 else:
3638 p1, p2 = parents
3641 p1, p2 = parents
3639
3642
3640 n = None
3643 n = None
3641 if update:
3644 if update:
3642 if p1 != parents[0]:
3645 if p1 != parents[0]:
3643 hg.clean(repo, p1.node())
3646 hg.clean(repo, p1.node())
3644 if p2 != parents[1]:
3647 if p2 != parents[1]:
3645 repo.setparents(p1.node(), p2.node())
3648 repo.setparents(p1.node(), p2.node())
3646
3649
3647 if opts.get('exact') or opts.get('import_branch'):
3650 if opts.get('exact') or opts.get('import_branch'):
3648 repo.dirstate.setbranch(branch or 'default')
3651 repo.dirstate.setbranch(branch or 'default')
3649
3652
3650 files = set()
3653 files = set()
3651 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3654 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3652 eolmode=None, similarity=sim / 100.0)
3655 eolmode=None, similarity=sim / 100.0)
3653 files = list(files)
3656 files = list(files)
3654 if opts.get('no_commit'):
3657 if opts.get('no_commit'):
3655 if message:
3658 if message:
3656 msgs.append(message)
3659 msgs.append(message)
3657 else:
3660 else:
3658 if opts.get('exact') or p2:
3661 if opts.get('exact') or p2:
3659 # If you got here, you either use --force and know what
3662 # If you got here, you either use --force and know what
3660 # you are doing or used --exact or a merge patch while
3663 # you are doing or used --exact or a merge patch while
3661 # being updated to its first parent.
3664 # being updated to its first parent.
3662 m = None
3665 m = None
3663 else:
3666 else:
3664 m = scmutil.matchfiles(repo, files or [])
3667 m = scmutil.matchfiles(repo, files or [])
3665 n = repo.commit(message, opts.get('user') or user,
3668 n = repo.commit(message, opts.get('user') or user,
3666 opts.get('date') or date, match=m,
3669 opts.get('date') or date, match=m,
3667 editor=editor)
3670 editor=editor)
3668 checkexact(repo, n, nodeid)
3671 checkexact(repo, n, nodeid)
3669 else:
3672 else:
3670 if opts.get('exact') or opts.get('import_branch'):
3673 if opts.get('exact') or opts.get('import_branch'):
3671 branch = branch or 'default'
3674 branch = branch or 'default'
3672 else:
3675 else:
3673 branch = p1.branch()
3676 branch = p1.branch()
3674 store = patch.filestore()
3677 store = patch.filestore()
3675 try:
3678 try:
3676 files = set()
3679 files = set()
3677 try:
3680 try:
3678 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3681 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3679 files, eolmode=None)
3682 files, eolmode=None)
3680 except patch.PatchError, e:
3683 except patch.PatchError, e:
3681 raise util.Abort(str(e))
3684 raise util.Abort(str(e))
3682 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3685 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3683 message,
3686 message,
3684 opts.get('user') or user,
3687 opts.get('user') or user,
3685 opts.get('date') or date,
3688 opts.get('date') or date,
3686 branch, files, store,
3689 branch, files, store,
3687 editor=cmdutil.commiteditor)
3690 editor=cmdutil.commiteditor)
3688 repo.savecommitmessage(memctx.description())
3691 repo.savecommitmessage(memctx.description())
3689 n = memctx.commit()
3692 n = memctx.commit()
3690 checkexact(repo, n, nodeid)
3693 checkexact(repo, n, nodeid)
3691 finally:
3694 finally:
3692 store.close()
3695 store.close()
3693 if n:
3696 if n:
3694 # i18n: refers to a short changeset id
3697 # i18n: refers to a short changeset id
3695 msg = _('created %s') % short(n)
3698 msg = _('created %s') % short(n)
3696 return (msg, n)
3699 return (msg, n)
3697 finally:
3700 finally:
3698 os.unlink(tmpname)
3701 os.unlink(tmpname)
3699
3702
3700 try:
3703 try:
3701 try:
3704 try:
3702 wlock = repo.wlock()
3705 wlock = repo.wlock()
3703 if not opts.get('no_commit'):
3706 if not opts.get('no_commit'):
3704 lock = repo.lock()
3707 lock = repo.lock()
3705 tr = repo.transaction('import')
3708 tr = repo.transaction('import')
3706 parents = repo.parents()
3709 parents = repo.parents()
3707 for patchurl in patches:
3710 for patchurl in patches:
3708 if patchurl == '-':
3711 if patchurl == '-':
3709 ui.status(_('applying patch from stdin\n'))
3712 ui.status(_('applying patch from stdin\n'))
3710 patchfile = ui.fin
3713 patchfile = ui.fin
3711 patchurl = 'stdin' # for error message
3714 patchurl = 'stdin' # for error message
3712 else:
3715 else:
3713 patchurl = os.path.join(base, patchurl)
3716 patchurl = os.path.join(base, patchurl)
3714 ui.status(_('applying %s\n') % patchurl)
3717 ui.status(_('applying %s\n') % patchurl)
3715 patchfile = hg.openpath(ui, patchurl)
3718 patchfile = hg.openpath(ui, patchurl)
3716
3719
3717 haspatch = False
3720 haspatch = False
3718 for hunk in patch.split(patchfile):
3721 for hunk in patch.split(patchfile):
3719 (msg, node) = tryone(ui, hunk, parents)
3722 (msg, node) = tryone(ui, hunk, parents)
3720 if msg:
3723 if msg:
3721 haspatch = True
3724 haspatch = True
3722 ui.note(msg + '\n')
3725 ui.note(msg + '\n')
3723 if update or opts.get('exact'):
3726 if update or opts.get('exact'):
3724 parents = repo.parents()
3727 parents = repo.parents()
3725 else:
3728 else:
3726 parents = [repo[node]]
3729 parents = [repo[node]]
3727
3730
3728 if not haspatch:
3731 if not haspatch:
3729 raise util.Abort(_('%s: no diffs found') % patchurl)
3732 raise util.Abort(_('%s: no diffs found') % patchurl)
3730
3733
3731 if tr:
3734 if tr:
3732 tr.close()
3735 tr.close()
3733 if msgs:
3736 if msgs:
3734 repo.savecommitmessage('\n* * *\n'.join(msgs))
3737 repo.savecommitmessage('\n* * *\n'.join(msgs))
3735 except: # re-raises
3738 except: # re-raises
3736 # wlock.release() indirectly calls dirstate.write(): since
3739 # wlock.release() indirectly calls dirstate.write(): since
3737 # we're crashing, we do not want to change the working dir
3740 # we're crashing, we do not want to change the working dir
3738 # parent after all, so make sure it writes nothing
3741 # parent after all, so make sure it writes nothing
3739 repo.dirstate.invalidate()
3742 repo.dirstate.invalidate()
3740 raise
3743 raise
3741 finally:
3744 finally:
3742 if tr:
3745 if tr:
3743 tr.release()
3746 tr.release()
3744 release(lock, wlock)
3747 release(lock, wlock)
3745
3748
3746 @command('incoming|in',
3749 @command('incoming|in',
3747 [('f', 'force', None,
3750 [('f', 'force', None,
3748 _('run even if remote repository is unrelated')),
3751 _('run even if remote repository is unrelated')),
3749 ('n', 'newest-first', None, _('show newest record first')),
3752 ('n', 'newest-first', None, _('show newest record first')),
3750 ('', 'bundle', '',
3753 ('', 'bundle', '',
3751 _('file to store the bundles into'), _('FILE')),
3754 _('file to store the bundles into'), _('FILE')),
3752 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3755 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3753 ('B', 'bookmarks', False, _("compare bookmarks")),
3756 ('B', 'bookmarks', False, _("compare bookmarks")),
3754 ('b', 'branch', [],
3757 ('b', 'branch', [],
3755 _('a specific branch you would like to pull'), _('BRANCH')),
3758 _('a specific branch you would like to pull'), _('BRANCH')),
3756 ] + logopts + remoteopts + subrepoopts,
3759 ] + logopts + remoteopts + subrepoopts,
3757 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3760 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3758 def incoming(ui, repo, source="default", **opts):
3761 def incoming(ui, repo, source="default", **opts):
3759 """show new changesets found in source
3762 """show new changesets found in source
3760
3763
3761 Show new changesets found in the specified path/URL or the default
3764 Show new changesets found in the specified path/URL or the default
3762 pull location. These are the changesets that would have been pulled
3765 pull location. These are the changesets that would have been pulled
3763 if a pull at the time you issued this command.
3766 if a pull at the time you issued this command.
3764
3767
3765 For remote repository, using --bundle avoids downloading the
3768 For remote repository, using --bundle avoids downloading the
3766 changesets twice if the incoming is followed by a pull.
3769 changesets twice if the incoming is followed by a pull.
3767
3770
3768 See pull for valid source format details.
3771 See pull for valid source format details.
3769
3772
3770 Returns 0 if there are incoming changes, 1 otherwise.
3773 Returns 0 if there are incoming changes, 1 otherwise.
3771 """
3774 """
3772 if opts.get('graph'):
3775 if opts.get('graph'):
3773 cmdutil.checkunsupportedgraphflags([], opts)
3776 cmdutil.checkunsupportedgraphflags([], opts)
3774 def display(other, chlist, displayer):
3777 def display(other, chlist, displayer):
3775 revdag = cmdutil.graphrevs(other, chlist, opts)
3778 revdag = cmdutil.graphrevs(other, chlist, opts)
3776 showparents = [ctx.node() for ctx in repo[None].parents()]
3779 showparents = [ctx.node() for ctx in repo[None].parents()]
3777 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3780 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3778 graphmod.asciiedges)
3781 graphmod.asciiedges)
3779
3782
3780 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3783 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3781 return 0
3784 return 0
3782
3785
3783 if opts.get('bundle') and opts.get('subrepos'):
3786 if opts.get('bundle') and opts.get('subrepos'):
3784 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3787 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3785
3788
3786 if opts.get('bookmarks'):
3789 if opts.get('bookmarks'):
3787 source, branches = hg.parseurl(ui.expandpath(source),
3790 source, branches = hg.parseurl(ui.expandpath(source),
3788 opts.get('branch'))
3791 opts.get('branch'))
3789 other = hg.peer(repo, opts, source)
3792 other = hg.peer(repo, opts, source)
3790 if 'bookmarks' not in other.listkeys('namespaces'):
3793 if 'bookmarks' not in other.listkeys('namespaces'):
3791 ui.warn(_("remote doesn't support bookmarks\n"))
3794 ui.warn(_("remote doesn't support bookmarks\n"))
3792 return 0
3795 return 0
3793 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3796 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3794 return bookmarks.diff(ui, repo, other)
3797 return bookmarks.diff(ui, repo, other)
3795
3798
3796 repo._subtoppath = ui.expandpath(source)
3799 repo._subtoppath = ui.expandpath(source)
3797 try:
3800 try:
3798 return hg.incoming(ui, repo, source, opts)
3801 return hg.incoming(ui, repo, source, opts)
3799 finally:
3802 finally:
3800 del repo._subtoppath
3803 del repo._subtoppath
3801
3804
3802
3805
3803 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3806 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3804 def init(ui, dest=".", **opts):
3807 def init(ui, dest=".", **opts):
3805 """create a new repository in the given directory
3808 """create a new repository in the given directory
3806
3809
3807 Initialize a new repository in the given directory. If the given
3810 Initialize a new repository in the given directory. If the given
3808 directory does not exist, it will be created.
3811 directory does not exist, it will be created.
3809
3812
3810 If no directory is given, the current directory is used.
3813 If no directory is given, the current directory is used.
3811
3814
3812 It is possible to specify an ``ssh://`` URL as the destination.
3815 It is possible to specify an ``ssh://`` URL as the destination.
3813 See :hg:`help urls` for more information.
3816 See :hg:`help urls` for more information.
3814
3817
3815 Returns 0 on success.
3818 Returns 0 on success.
3816 """
3819 """
3817 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3820 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3818
3821
3819 @command('locate',
3822 @command('locate',
3820 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3823 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3821 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3824 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3822 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3825 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3823 ] + walkopts,
3826 ] + walkopts,
3824 _('[OPTION]... [PATTERN]...'))
3827 _('[OPTION]... [PATTERN]...'))
3825 def locate(ui, repo, *pats, **opts):
3828 def locate(ui, repo, *pats, **opts):
3826 """locate files matching specific patterns
3829 """locate files matching specific patterns
3827
3830
3828 Print files under Mercurial control in the working directory whose
3831 Print files under Mercurial control in the working directory whose
3829 names match the given patterns.
3832 names match the given patterns.
3830
3833
3831 By default, this command searches all directories in the working
3834 By default, this command searches all directories in the working
3832 directory. To search just the current directory and its
3835 directory. To search just the current directory and its
3833 subdirectories, use "--include .".
3836 subdirectories, use "--include .".
3834
3837
3835 If no patterns are given to match, this command prints the names
3838 If no patterns are given to match, this command prints the names
3836 of all files under Mercurial control in the working directory.
3839 of all files under Mercurial control in the working directory.
3837
3840
3838 If you want to feed the output of this command into the "xargs"
3841 If you want to feed the output of this command into the "xargs"
3839 command, use the -0 option to both this command and "xargs". This
3842 command, use the -0 option to both this command and "xargs". This
3840 will avoid the problem of "xargs" treating single filenames that
3843 will avoid the problem of "xargs" treating single filenames that
3841 contain whitespace as multiple filenames.
3844 contain whitespace as multiple filenames.
3842
3845
3843 Returns 0 if a match is found, 1 otherwise.
3846 Returns 0 if a match is found, 1 otherwise.
3844 """
3847 """
3845 end = opts.get('print0') and '\0' or '\n'
3848 end = opts.get('print0') and '\0' or '\n'
3846 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3849 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3847
3850
3848 ret = 1
3851 ret = 1
3849 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3852 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3850 m.bad = lambda x, y: False
3853 m.bad = lambda x, y: False
3851 for abs in repo[rev].walk(m):
3854 for abs in repo[rev].walk(m):
3852 if not rev and abs not in repo.dirstate:
3855 if not rev and abs not in repo.dirstate:
3853 continue
3856 continue
3854 if opts.get('fullpath'):
3857 if opts.get('fullpath'):
3855 ui.write(repo.wjoin(abs), end)
3858 ui.write(repo.wjoin(abs), end)
3856 else:
3859 else:
3857 ui.write(((pats and m.rel(abs)) or abs), end)
3860 ui.write(((pats and m.rel(abs)) or abs), end)
3858 ret = 0
3861 ret = 0
3859
3862
3860 return ret
3863 return ret
3861
3864
3862 @command('^log|history',
3865 @command('^log|history',
3863 [('f', 'follow', None,
3866 [('f', 'follow', None,
3864 _('follow changeset history, or file history across copies and renames')),
3867 _('follow changeset history, or file history across copies and renames')),
3865 ('', 'follow-first', None,
3868 ('', 'follow-first', None,
3866 _('only follow the first parent of merge changesets (DEPRECATED)')),
3869 _('only follow the first parent of merge changesets (DEPRECATED)')),
3867 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3870 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3868 ('C', 'copies', None, _('show copied files')),
3871 ('C', 'copies', None, _('show copied files')),
3869 ('k', 'keyword', [],
3872 ('k', 'keyword', [],
3870 _('do case-insensitive search for a given text'), _('TEXT')),
3873 _('do case-insensitive search for a given text'), _('TEXT')),
3871 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3874 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3872 ('', 'removed', None, _('include revisions where files were removed')),
3875 ('', 'removed', None, _('include revisions where files were removed')),
3873 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3876 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3874 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3877 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3875 ('', 'only-branch', [],
3878 ('', 'only-branch', [],
3876 _('show only changesets within the given named branch (DEPRECATED)'),
3879 _('show only changesets within the given named branch (DEPRECATED)'),
3877 _('BRANCH')),
3880 _('BRANCH')),
3878 ('b', 'branch', [],
3881 ('b', 'branch', [],
3879 _('show changesets within the given named branch'), _('BRANCH')),
3882 _('show changesets within the given named branch'), _('BRANCH')),
3880 ('P', 'prune', [],
3883 ('P', 'prune', [],
3881 _('do not display revision or any of its ancestors'), _('REV')),
3884 _('do not display revision or any of its ancestors'), _('REV')),
3882 ] + logopts + walkopts,
3885 ] + logopts + walkopts,
3883 _('[OPTION]... [FILE]'))
3886 _('[OPTION]... [FILE]'))
3884 def log(ui, repo, *pats, **opts):
3887 def log(ui, repo, *pats, **opts):
3885 """show revision history of entire repository or files
3888 """show revision history of entire repository or files
3886
3889
3887 Print the revision history of the specified files or the entire
3890 Print the revision history of the specified files or the entire
3888 project.
3891 project.
3889
3892
3890 If no revision range is specified, the default is ``tip:0`` unless
3893 If no revision range is specified, the default is ``tip:0`` unless
3891 --follow is set, in which case the working directory parent is
3894 --follow is set, in which case the working directory parent is
3892 used as the starting revision.
3895 used as the starting revision.
3893
3896
3894 File history is shown without following rename or copy history of
3897 File history is shown without following rename or copy history of
3895 files. Use -f/--follow with a filename to follow history across
3898 files. Use -f/--follow with a filename to follow history across
3896 renames and copies. --follow without a filename will only show
3899 renames and copies. --follow without a filename will only show
3897 ancestors or descendants of the starting revision.
3900 ancestors or descendants of the starting revision.
3898
3901
3899 By default this command prints revision number and changeset id,
3902 By default this command prints revision number and changeset id,
3900 tags, non-trivial parents, user, date and time, and a summary for
3903 tags, non-trivial parents, user, date and time, and a summary for
3901 each commit. When the -v/--verbose switch is used, the list of
3904 each commit. When the -v/--verbose switch is used, the list of
3902 changed files and full commit message are shown.
3905 changed files and full commit message are shown.
3903
3906
3904 .. note::
3907 .. note::
3905 log -p/--patch may generate unexpected diff output for merge
3908 log -p/--patch may generate unexpected diff output for merge
3906 changesets, as it will only compare the merge changeset against
3909 changesets, as it will only compare the merge changeset against
3907 its first parent. Also, only files different from BOTH parents
3910 its first parent. Also, only files different from BOTH parents
3908 will appear in files:.
3911 will appear in files:.
3909
3912
3910 .. note::
3913 .. note::
3911 for performance reasons, log FILE may omit duplicate changes
3914 for performance reasons, log FILE may omit duplicate changes
3912 made on branches and will not show deletions. To see all
3915 made on branches and will not show deletions. To see all
3913 changes including duplicates and deletions, use the --removed
3916 changes including duplicates and deletions, use the --removed
3914 switch.
3917 switch.
3915
3918
3916 .. container:: verbose
3919 .. container:: verbose
3917
3920
3918 Some examples:
3921 Some examples:
3919
3922
3920 - changesets with full descriptions and file lists::
3923 - changesets with full descriptions and file lists::
3921
3924
3922 hg log -v
3925 hg log -v
3923
3926
3924 - changesets ancestral to the working directory::
3927 - changesets ancestral to the working directory::
3925
3928
3926 hg log -f
3929 hg log -f
3927
3930
3928 - last 10 commits on the current branch::
3931 - last 10 commits on the current branch::
3929
3932
3930 hg log -l 10 -b .
3933 hg log -l 10 -b .
3931
3934
3932 - changesets showing all modifications of a file, including removals::
3935 - changesets showing all modifications of a file, including removals::
3933
3936
3934 hg log --removed file.c
3937 hg log --removed file.c
3935
3938
3936 - all changesets that touch a directory, with diffs, excluding merges::
3939 - all changesets that touch a directory, with diffs, excluding merges::
3937
3940
3938 hg log -Mp lib/
3941 hg log -Mp lib/
3939
3942
3940 - all revision numbers that match a keyword::
3943 - all revision numbers that match a keyword::
3941
3944
3942 hg log -k bug --template "{rev}\\n"
3945 hg log -k bug --template "{rev}\\n"
3943
3946
3944 - check if a given changeset is included is a tagged release::
3947 - check if a given changeset is included is a tagged release::
3945
3948
3946 hg log -r "a21ccf and ancestor(1.9)"
3949 hg log -r "a21ccf and ancestor(1.9)"
3947
3950
3948 - find all changesets by some user in a date range::
3951 - find all changesets by some user in a date range::
3949
3952
3950 hg log -k alice -d "may 2008 to jul 2008"
3953 hg log -k alice -d "may 2008 to jul 2008"
3951
3954
3952 - summary of all changesets after the last tag::
3955 - summary of all changesets after the last tag::
3953
3956
3954 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3957 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3955
3958
3956 See :hg:`help dates` for a list of formats valid for -d/--date.
3959 See :hg:`help dates` for a list of formats valid for -d/--date.
3957
3960
3958 See :hg:`help revisions` and :hg:`help revsets` for more about
3961 See :hg:`help revisions` and :hg:`help revsets` for more about
3959 specifying revisions.
3962 specifying revisions.
3960
3963
3961 See :hg:`help templates` for more about pre-packaged styles and
3964 See :hg:`help templates` for more about pre-packaged styles and
3962 specifying custom templates.
3965 specifying custom templates.
3963
3966
3964 Returns 0 on success.
3967 Returns 0 on success.
3965 """
3968 """
3966 if opts.get('graph'):
3969 if opts.get('graph'):
3967 return cmdutil.graphlog(ui, repo, *pats, **opts)
3970 return cmdutil.graphlog(ui, repo, *pats, **opts)
3968
3971
3969 matchfn = scmutil.match(repo[None], pats, opts)
3972 matchfn = scmutil.match(repo[None], pats, opts)
3970 limit = cmdutil.loglimit(opts)
3973 limit = cmdutil.loglimit(opts)
3971 count = 0
3974 count = 0
3972
3975
3973 getrenamed, endrev = None, None
3976 getrenamed, endrev = None, None
3974 if opts.get('copies'):
3977 if opts.get('copies'):
3975 if opts.get('rev'):
3978 if opts.get('rev'):
3976 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3979 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3977 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3980 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3978
3981
3979 df = False
3982 df = False
3980 if opts.get("date"):
3983 if opts.get("date"):
3981 df = util.matchdate(opts["date"])
3984 df = util.matchdate(opts["date"])
3982
3985
3983 branches = opts.get('branch', []) + opts.get('only_branch', [])
3986 branches = opts.get('branch', []) + opts.get('only_branch', [])
3984 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3987 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3985
3988
3986 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3989 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3987 def prep(ctx, fns):
3990 def prep(ctx, fns):
3988 rev = ctx.rev()
3991 rev = ctx.rev()
3989 parents = [p for p in repo.changelog.parentrevs(rev)
3992 parents = [p for p in repo.changelog.parentrevs(rev)
3990 if p != nullrev]
3993 if p != nullrev]
3991 if opts.get('no_merges') and len(parents) == 2:
3994 if opts.get('no_merges') and len(parents) == 2:
3992 return
3995 return
3993 if opts.get('only_merges') and len(parents) != 2:
3996 if opts.get('only_merges') and len(parents) != 2:
3994 return
3997 return
3995 if opts.get('branch') and ctx.branch() not in opts['branch']:
3998 if opts.get('branch') and ctx.branch() not in opts['branch']:
3996 return
3999 return
3997 if df and not df(ctx.date()[0]):
4000 if df and not df(ctx.date()[0]):
3998 return
4001 return
3999
4002
4000 lower = encoding.lower
4003 lower = encoding.lower
4001 if opts.get('user'):
4004 if opts.get('user'):
4002 luser = lower(ctx.user())
4005 luser = lower(ctx.user())
4003 for k in [lower(x) for x in opts['user']]:
4006 for k in [lower(x) for x in opts['user']]:
4004 if (k in luser):
4007 if (k in luser):
4005 break
4008 break
4006 else:
4009 else:
4007 return
4010 return
4008 if opts.get('keyword'):
4011 if opts.get('keyword'):
4009 luser = lower(ctx.user())
4012 luser = lower(ctx.user())
4010 ldesc = lower(ctx.description())
4013 ldesc = lower(ctx.description())
4011 lfiles = lower(" ".join(ctx.files()))
4014 lfiles = lower(" ".join(ctx.files()))
4012 for k in [lower(x) for x in opts['keyword']]:
4015 for k in [lower(x) for x in opts['keyword']]:
4013 if (k in luser or k in ldesc or k in lfiles):
4016 if (k in luser or k in ldesc or k in lfiles):
4014 break
4017 break
4015 else:
4018 else:
4016 return
4019 return
4017
4020
4018 copies = None
4021 copies = None
4019 if getrenamed is not None and rev:
4022 if getrenamed is not None and rev:
4020 copies = []
4023 copies = []
4021 for fn in ctx.files():
4024 for fn in ctx.files():
4022 rename = getrenamed(fn, rev)
4025 rename = getrenamed(fn, rev)
4023 if rename:
4026 if rename:
4024 copies.append((fn, rename[0]))
4027 copies.append((fn, rename[0]))
4025
4028
4026 revmatchfn = None
4029 revmatchfn = None
4027 if opts.get('patch') or opts.get('stat'):
4030 if opts.get('patch') or opts.get('stat'):
4028 if opts.get('follow') or opts.get('follow_first'):
4031 if opts.get('follow') or opts.get('follow_first'):
4029 # note: this might be wrong when following through merges
4032 # note: this might be wrong when following through merges
4030 revmatchfn = scmutil.match(repo[None], fns, default='path')
4033 revmatchfn = scmutil.match(repo[None], fns, default='path')
4031 else:
4034 else:
4032 revmatchfn = matchfn
4035 revmatchfn = matchfn
4033
4036
4034 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4037 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4035
4038
4036 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4039 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4037 if displayer.flush(ctx.rev()):
4040 if displayer.flush(ctx.rev()):
4038 count += 1
4041 count += 1
4039 if count == limit:
4042 if count == limit:
4040 break
4043 break
4041 displayer.close()
4044 displayer.close()
4042
4045
4043 @command('manifest',
4046 @command('manifest',
4044 [('r', 'rev', '', _('revision to display'), _('REV')),
4047 [('r', 'rev', '', _('revision to display'), _('REV')),
4045 ('', 'all', False, _("list files from all revisions"))],
4048 ('', 'all', False, _("list files from all revisions"))],
4046 _('[-r REV]'))
4049 _('[-r REV]'))
4047 def manifest(ui, repo, node=None, rev=None, **opts):
4050 def manifest(ui, repo, node=None, rev=None, **opts):
4048 """output the current or given revision of the project manifest
4051 """output the current or given revision of the project manifest
4049
4052
4050 Print a list of version controlled files for the given revision.
4053 Print a list of version controlled files for the given revision.
4051 If no revision is given, the first parent of the working directory
4054 If no revision is given, the first parent of the working directory
4052 is used, or the null revision if no revision is checked out.
4055 is used, or the null revision if no revision is checked out.
4053
4056
4054 With -v, print file permissions, symlink and executable bits.
4057 With -v, print file permissions, symlink and executable bits.
4055 With --debug, print file revision hashes.
4058 With --debug, print file revision hashes.
4056
4059
4057 If option --all is specified, the list of all files from all revisions
4060 If option --all is specified, the list of all files from all revisions
4058 is printed. This includes deleted and renamed files.
4061 is printed. This includes deleted and renamed files.
4059
4062
4060 Returns 0 on success.
4063 Returns 0 on success.
4061 """
4064 """
4062
4065
4063 fm = ui.formatter('manifest', opts)
4066 fm = ui.formatter('manifest', opts)
4064
4067
4065 if opts.get('all'):
4068 if opts.get('all'):
4066 if rev or node:
4069 if rev or node:
4067 raise util.Abort(_("can't specify a revision with --all"))
4070 raise util.Abort(_("can't specify a revision with --all"))
4068
4071
4069 res = []
4072 res = []
4070 prefix = "data/"
4073 prefix = "data/"
4071 suffix = ".i"
4074 suffix = ".i"
4072 plen = len(prefix)
4075 plen = len(prefix)
4073 slen = len(suffix)
4076 slen = len(suffix)
4074 lock = repo.lock()
4077 lock = repo.lock()
4075 try:
4078 try:
4076 for fn, b, size in repo.store.datafiles():
4079 for fn, b, size in repo.store.datafiles():
4077 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4080 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4078 res.append(fn[plen:-slen])
4081 res.append(fn[plen:-slen])
4079 finally:
4082 finally:
4080 lock.release()
4083 lock.release()
4081 for f in res:
4084 for f in res:
4082 fm.startitem()
4085 fm.startitem()
4083 fm.write("path", '%s\n', f)
4086 fm.write("path", '%s\n', f)
4084 fm.end()
4087 fm.end()
4085 return
4088 return
4086
4089
4087 if rev and node:
4090 if rev and node:
4088 raise util.Abort(_("please specify just one revision"))
4091 raise util.Abort(_("please specify just one revision"))
4089
4092
4090 if not node:
4093 if not node:
4091 node = rev
4094 node = rev
4092
4095
4093 char = {'l': '@', 'x': '*', '': ''}
4096 char = {'l': '@', 'x': '*', '': ''}
4094 mode = {'l': '644', 'x': '755', '': '644'}
4097 mode = {'l': '644', 'x': '755', '': '644'}
4095 ctx = scmutil.revsingle(repo, node)
4098 ctx = scmutil.revsingle(repo, node)
4096 mf = ctx.manifest()
4099 mf = ctx.manifest()
4097 for f in ctx:
4100 for f in ctx:
4098 fm.startitem()
4101 fm.startitem()
4099 fl = ctx[f].flags()
4102 fl = ctx[f].flags()
4100 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4103 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4101 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4104 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4102 fm.write('path', '%s\n', f)
4105 fm.write('path', '%s\n', f)
4103 fm.end()
4106 fm.end()
4104
4107
4105 @command('^merge',
4108 @command('^merge',
4106 [('f', 'force', None, _('force a merge with outstanding changes')),
4109 [('f', 'force', None, _('force a merge with outstanding changes')),
4107 ('r', 'rev', '', _('revision to merge'), _('REV')),
4110 ('r', 'rev', '', _('revision to merge'), _('REV')),
4108 ('P', 'preview', None,
4111 ('P', 'preview', None,
4109 _('review revisions to merge (no merge is performed)'))
4112 _('review revisions to merge (no merge is performed)'))
4110 ] + mergetoolopts,
4113 ] + mergetoolopts,
4111 _('[-P] [-f] [[-r] REV]'))
4114 _('[-P] [-f] [[-r] REV]'))
4112 def merge(ui, repo, node=None, **opts):
4115 def merge(ui, repo, node=None, **opts):
4113 """merge working directory with another revision
4116 """merge working directory with another revision
4114
4117
4115 The current working directory is updated with all changes made in
4118 The current working directory is updated with all changes made in
4116 the requested revision since the last common predecessor revision.
4119 the requested revision since the last common predecessor revision.
4117
4120
4118 Files that changed between either parent are marked as changed for
4121 Files that changed between either parent are marked as changed for
4119 the next commit and a commit must be performed before any further
4122 the next commit and a commit must be performed before any further
4120 updates to the repository are allowed. The next commit will have
4123 updates to the repository are allowed. The next commit will have
4121 two parents.
4124 two parents.
4122
4125
4123 ``--tool`` can be used to specify the merge tool used for file
4126 ``--tool`` can be used to specify the merge tool used for file
4124 merges. It overrides the HGMERGE environment variable and your
4127 merges. It overrides the HGMERGE environment variable and your
4125 configuration files. See :hg:`help merge-tools` for options.
4128 configuration files. See :hg:`help merge-tools` for options.
4126
4129
4127 If no revision is specified, the working directory's parent is a
4130 If no revision is specified, the working directory's parent is a
4128 head revision, and the current branch contains exactly one other
4131 head revision, and the current branch contains exactly one other
4129 head, the other head is merged with by default. Otherwise, an
4132 head, the other head is merged with by default. Otherwise, an
4130 explicit revision with which to merge with must be provided.
4133 explicit revision with which to merge with must be provided.
4131
4134
4132 :hg:`resolve` must be used to resolve unresolved files.
4135 :hg:`resolve` must be used to resolve unresolved files.
4133
4136
4134 To undo an uncommitted merge, use :hg:`update --clean .` which
4137 To undo an uncommitted merge, use :hg:`update --clean .` which
4135 will check out a clean copy of the original merge parent, losing
4138 will check out a clean copy of the original merge parent, losing
4136 all changes.
4139 all changes.
4137
4140
4138 Returns 0 on success, 1 if there are unresolved files.
4141 Returns 0 on success, 1 if there are unresolved files.
4139 """
4142 """
4140
4143
4141 if opts.get('rev') and node:
4144 if opts.get('rev') and node:
4142 raise util.Abort(_("please specify just one revision"))
4145 raise util.Abort(_("please specify just one revision"))
4143 if not node:
4146 if not node:
4144 node = opts.get('rev')
4147 node = opts.get('rev')
4145
4148
4146 if node:
4149 if node:
4147 node = scmutil.revsingle(repo, node).node()
4150 node = scmutil.revsingle(repo, node).node()
4148
4151
4149 if not node and repo._bookmarkcurrent:
4152 if not node and repo._bookmarkcurrent:
4150 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4153 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4151 curhead = repo[repo._bookmarkcurrent].node()
4154 curhead = repo[repo._bookmarkcurrent].node()
4152 if len(bmheads) == 2:
4155 if len(bmheads) == 2:
4153 if curhead == bmheads[0]:
4156 if curhead == bmheads[0]:
4154 node = bmheads[1]
4157 node = bmheads[1]
4155 else:
4158 else:
4156 node = bmheads[0]
4159 node = bmheads[0]
4157 elif len(bmheads) > 2:
4160 elif len(bmheads) > 2:
4158 raise util.Abort(_("multiple matching bookmarks to merge - "
4161 raise util.Abort(_("multiple matching bookmarks to merge - "
4159 "please merge with an explicit rev or bookmark"),
4162 "please merge with an explicit rev or bookmark"),
4160 hint=_("run 'hg heads' to see all heads"))
4163 hint=_("run 'hg heads' to see all heads"))
4161 elif len(bmheads) <= 1:
4164 elif len(bmheads) <= 1:
4162 raise util.Abort(_("no matching bookmark to merge - "
4165 raise util.Abort(_("no matching bookmark to merge - "
4163 "please merge with an explicit rev or bookmark"),
4166 "please merge with an explicit rev or bookmark"),
4164 hint=_("run 'hg heads' to see all heads"))
4167 hint=_("run 'hg heads' to see all heads"))
4165
4168
4166 if not node and not repo._bookmarkcurrent:
4169 if not node and not repo._bookmarkcurrent:
4167 branch = repo[None].branch()
4170 branch = repo[None].branch()
4168 bheads = repo.branchheads(branch)
4171 bheads = repo.branchheads(branch)
4169 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4172 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4170
4173
4171 if len(nbhs) > 2:
4174 if len(nbhs) > 2:
4172 raise util.Abort(_("branch '%s' has %d heads - "
4175 raise util.Abort(_("branch '%s' has %d heads - "
4173 "please merge with an explicit rev")
4176 "please merge with an explicit rev")
4174 % (branch, len(bheads)),
4177 % (branch, len(bheads)),
4175 hint=_("run 'hg heads .' to see heads"))
4178 hint=_("run 'hg heads .' to see heads"))
4176
4179
4177 parent = repo.dirstate.p1()
4180 parent = repo.dirstate.p1()
4178 if len(nbhs) <= 1:
4181 if len(nbhs) <= 1:
4179 if len(bheads) > 1:
4182 if len(bheads) > 1:
4180 raise util.Abort(_("heads are bookmarked - "
4183 raise util.Abort(_("heads are bookmarked - "
4181 "please merge with an explicit rev"),
4184 "please merge with an explicit rev"),
4182 hint=_("run 'hg heads' to see all heads"))
4185 hint=_("run 'hg heads' to see all heads"))
4183 if len(repo.heads()) > 1:
4186 if len(repo.heads()) > 1:
4184 raise util.Abort(_("branch '%s' has one head - "
4187 raise util.Abort(_("branch '%s' has one head - "
4185 "please merge with an explicit rev")
4188 "please merge with an explicit rev")
4186 % branch,
4189 % branch,
4187 hint=_("run 'hg heads' to see all heads"))
4190 hint=_("run 'hg heads' to see all heads"))
4188 msg, hint = _('nothing to merge'), None
4191 msg, hint = _('nothing to merge'), None
4189 if parent != repo.lookup(branch):
4192 if parent != repo.lookup(branch):
4190 hint = _("use 'hg update' instead")
4193 hint = _("use 'hg update' instead")
4191 raise util.Abort(msg, hint=hint)
4194 raise util.Abort(msg, hint=hint)
4192
4195
4193 if parent not in bheads:
4196 if parent not in bheads:
4194 raise util.Abort(_('working directory not at a head revision'),
4197 raise util.Abort(_('working directory not at a head revision'),
4195 hint=_("use 'hg update' or merge with an "
4198 hint=_("use 'hg update' or merge with an "
4196 "explicit revision"))
4199 "explicit revision"))
4197 if parent == nbhs[0]:
4200 if parent == nbhs[0]:
4198 node = nbhs[-1]
4201 node = nbhs[-1]
4199 else:
4202 else:
4200 node = nbhs[0]
4203 node = nbhs[0]
4201
4204
4202 if opts.get('preview'):
4205 if opts.get('preview'):
4203 # find nodes that are ancestors of p2 but not of p1
4206 # find nodes that are ancestors of p2 but not of p1
4204 p1 = repo.lookup('.')
4207 p1 = repo.lookup('.')
4205 p2 = repo.lookup(node)
4208 p2 = repo.lookup(node)
4206 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4209 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4207
4210
4208 displayer = cmdutil.show_changeset(ui, repo, opts)
4211 displayer = cmdutil.show_changeset(ui, repo, opts)
4209 for node in nodes:
4212 for node in nodes:
4210 displayer.show(repo[node])
4213 displayer.show(repo[node])
4211 displayer.close()
4214 displayer.close()
4212 return 0
4215 return 0
4213
4216
4214 try:
4217 try:
4215 # ui.forcemerge is an internal variable, do not document
4218 # ui.forcemerge is an internal variable, do not document
4216 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4219 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4217 return hg.merge(repo, node, force=opts.get('force'))
4220 return hg.merge(repo, node, force=opts.get('force'))
4218 finally:
4221 finally:
4219 ui.setconfig('ui', 'forcemerge', '')
4222 ui.setconfig('ui', 'forcemerge', '')
4220
4223
4221 @command('outgoing|out',
4224 @command('outgoing|out',
4222 [('f', 'force', None, _('run even when the destination is unrelated')),
4225 [('f', 'force', None, _('run even when the destination is unrelated')),
4223 ('r', 'rev', [],
4226 ('r', 'rev', [],
4224 _('a changeset intended to be included in the destination'), _('REV')),
4227 _('a changeset intended to be included in the destination'), _('REV')),
4225 ('n', 'newest-first', None, _('show newest record first')),
4228 ('n', 'newest-first', None, _('show newest record first')),
4226 ('B', 'bookmarks', False, _('compare bookmarks')),
4229 ('B', 'bookmarks', False, _('compare bookmarks')),
4227 ('b', 'branch', [], _('a specific branch you would like to push'),
4230 ('b', 'branch', [], _('a specific branch you would like to push'),
4228 _('BRANCH')),
4231 _('BRANCH')),
4229 ] + logopts + remoteopts + subrepoopts,
4232 ] + logopts + remoteopts + subrepoopts,
4230 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4233 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4231 def outgoing(ui, repo, dest=None, **opts):
4234 def outgoing(ui, repo, dest=None, **opts):
4232 """show changesets not found in the destination
4235 """show changesets not found in the destination
4233
4236
4234 Show changesets not found in the specified destination repository
4237 Show changesets not found in the specified destination repository
4235 or the default push location. These are the changesets that would
4238 or the default push location. These are the changesets that would
4236 be pushed if a push was requested.
4239 be pushed if a push was requested.
4237
4240
4238 See pull for details of valid destination formats.
4241 See pull for details of valid destination formats.
4239
4242
4240 Returns 0 if there are outgoing changes, 1 otherwise.
4243 Returns 0 if there are outgoing changes, 1 otherwise.
4241 """
4244 """
4242 if opts.get('graph'):
4245 if opts.get('graph'):
4243 cmdutil.checkunsupportedgraphflags([], opts)
4246 cmdutil.checkunsupportedgraphflags([], opts)
4244 o = hg._outgoing(ui, repo, dest, opts)
4247 o = hg._outgoing(ui, repo, dest, opts)
4245 if o is None:
4248 if o is None:
4246 return
4249 return
4247
4250
4248 revdag = cmdutil.graphrevs(repo, o, opts)
4251 revdag = cmdutil.graphrevs(repo, o, opts)
4249 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4252 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4250 showparents = [ctx.node() for ctx in repo[None].parents()]
4253 showparents = [ctx.node() for ctx in repo[None].parents()]
4251 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4254 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4252 graphmod.asciiedges)
4255 graphmod.asciiedges)
4253 return 0
4256 return 0
4254
4257
4255 if opts.get('bookmarks'):
4258 if opts.get('bookmarks'):
4256 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4259 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4257 dest, branches = hg.parseurl(dest, opts.get('branch'))
4260 dest, branches = hg.parseurl(dest, opts.get('branch'))
4258 other = hg.peer(repo, opts, dest)
4261 other = hg.peer(repo, opts, dest)
4259 if 'bookmarks' not in other.listkeys('namespaces'):
4262 if 'bookmarks' not in other.listkeys('namespaces'):
4260 ui.warn(_("remote doesn't support bookmarks\n"))
4263 ui.warn(_("remote doesn't support bookmarks\n"))
4261 return 0
4264 return 0
4262 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4265 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4263 return bookmarks.diff(ui, other, repo)
4266 return bookmarks.diff(ui, other, repo)
4264
4267
4265 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4268 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4266 try:
4269 try:
4267 return hg.outgoing(ui, repo, dest, opts)
4270 return hg.outgoing(ui, repo, dest, opts)
4268 finally:
4271 finally:
4269 del repo._subtoppath
4272 del repo._subtoppath
4270
4273
4271 @command('parents',
4274 @command('parents',
4272 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4275 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4273 ] + templateopts,
4276 ] + templateopts,
4274 _('[-r REV] [FILE]'))
4277 _('[-r REV] [FILE]'))
4275 def parents(ui, repo, file_=None, **opts):
4278 def parents(ui, repo, file_=None, **opts):
4276 """show the parents of the working directory or revision
4279 """show the parents of the working directory or revision
4277
4280
4278 Print the working directory's parent revisions. If a revision is
4281 Print the working directory's parent revisions. If a revision is
4279 given via -r/--rev, the parent of that revision will be printed.
4282 given via -r/--rev, the parent of that revision will be printed.
4280 If a file argument is given, the revision in which the file was
4283 If a file argument is given, the revision in which the file was
4281 last changed (before the working directory revision or the
4284 last changed (before the working directory revision or the
4282 argument to --rev if given) is printed.
4285 argument to --rev if given) is printed.
4283
4286
4284 Returns 0 on success.
4287 Returns 0 on success.
4285 """
4288 """
4286
4289
4287 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4290 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4288
4291
4289 if file_:
4292 if file_:
4290 m = scmutil.match(ctx, (file_,), opts)
4293 m = scmutil.match(ctx, (file_,), opts)
4291 if m.anypats() or len(m.files()) != 1:
4294 if m.anypats() or len(m.files()) != 1:
4292 raise util.Abort(_('can only specify an explicit filename'))
4295 raise util.Abort(_('can only specify an explicit filename'))
4293 file_ = m.files()[0]
4296 file_ = m.files()[0]
4294 filenodes = []
4297 filenodes = []
4295 for cp in ctx.parents():
4298 for cp in ctx.parents():
4296 if not cp:
4299 if not cp:
4297 continue
4300 continue
4298 try:
4301 try:
4299 filenodes.append(cp.filenode(file_))
4302 filenodes.append(cp.filenode(file_))
4300 except error.LookupError:
4303 except error.LookupError:
4301 pass
4304 pass
4302 if not filenodes:
4305 if not filenodes:
4303 raise util.Abort(_("'%s' not found in manifest!") % file_)
4306 raise util.Abort(_("'%s' not found in manifest!") % file_)
4304 fl = repo.file(file_)
4307 fl = repo.file(file_)
4305 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4308 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4306 else:
4309 else:
4307 p = [cp.node() for cp in ctx.parents()]
4310 p = [cp.node() for cp in ctx.parents()]
4308
4311
4309 displayer = cmdutil.show_changeset(ui, repo, opts)
4312 displayer = cmdutil.show_changeset(ui, repo, opts)
4310 for n in p:
4313 for n in p:
4311 if n != nullid:
4314 if n != nullid:
4312 displayer.show(repo[n])
4315 displayer.show(repo[n])
4313 displayer.close()
4316 displayer.close()
4314
4317
4315 @command('paths', [], _('[NAME]'))
4318 @command('paths', [], _('[NAME]'))
4316 def paths(ui, repo, search=None):
4319 def paths(ui, repo, search=None):
4317 """show aliases for remote repositories
4320 """show aliases for remote repositories
4318
4321
4319 Show definition of symbolic path name NAME. If no name is given,
4322 Show definition of symbolic path name NAME. If no name is given,
4320 show definition of all available names.
4323 show definition of all available names.
4321
4324
4322 Option -q/--quiet suppresses all output when searching for NAME
4325 Option -q/--quiet suppresses all output when searching for NAME
4323 and shows only the path names when listing all definitions.
4326 and shows only the path names when listing all definitions.
4324
4327
4325 Path names are defined in the [paths] section of your
4328 Path names are defined in the [paths] section of your
4326 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4329 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4327 repository, ``.hg/hgrc`` is used, too.
4330 repository, ``.hg/hgrc`` is used, too.
4328
4331
4329 The path names ``default`` and ``default-push`` have a special
4332 The path names ``default`` and ``default-push`` have a special
4330 meaning. When performing a push or pull operation, they are used
4333 meaning. When performing a push or pull operation, they are used
4331 as fallbacks if no location is specified on the command-line.
4334 as fallbacks if no location is specified on the command-line.
4332 When ``default-push`` is set, it will be used for push and
4335 When ``default-push`` is set, it will be used for push and
4333 ``default`` will be used for pull; otherwise ``default`` is used
4336 ``default`` will be used for pull; otherwise ``default`` is used
4334 as the fallback for both. When cloning a repository, the clone
4337 as the fallback for both. When cloning a repository, the clone
4335 source is written as ``default`` in ``.hg/hgrc``. Note that
4338 source is written as ``default`` in ``.hg/hgrc``. Note that
4336 ``default`` and ``default-push`` apply to all inbound (e.g.
4339 ``default`` and ``default-push`` apply to all inbound (e.g.
4337 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4340 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4338 :hg:`bundle`) operations.
4341 :hg:`bundle`) operations.
4339
4342
4340 See :hg:`help urls` for more information.
4343 See :hg:`help urls` for more information.
4341
4344
4342 Returns 0 on success.
4345 Returns 0 on success.
4343 """
4346 """
4344 if search:
4347 if search:
4345 for name, path in ui.configitems("paths"):
4348 for name, path in ui.configitems("paths"):
4346 if name == search:
4349 if name == search:
4347 ui.status("%s\n" % util.hidepassword(path))
4350 ui.status("%s\n" % util.hidepassword(path))
4348 return
4351 return
4349 if not ui.quiet:
4352 if not ui.quiet:
4350 ui.warn(_("not found!\n"))
4353 ui.warn(_("not found!\n"))
4351 return 1
4354 return 1
4352 else:
4355 else:
4353 for name, path in ui.configitems("paths"):
4356 for name, path in ui.configitems("paths"):
4354 if ui.quiet:
4357 if ui.quiet:
4355 ui.write("%s\n" % name)
4358 ui.write("%s\n" % name)
4356 else:
4359 else:
4357 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4360 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4358
4361
4359 @command('phase',
4362 @command('phase',
4360 [('p', 'public', False, _('set changeset phase to public')),
4363 [('p', 'public', False, _('set changeset phase to public')),
4361 ('d', 'draft', False, _('set changeset phase to draft')),
4364 ('d', 'draft', False, _('set changeset phase to draft')),
4362 ('s', 'secret', False, _('set changeset phase to secret')),
4365 ('s', 'secret', False, _('set changeset phase to secret')),
4363 ('f', 'force', False, _('allow to move boundary backward')),
4366 ('f', 'force', False, _('allow to move boundary backward')),
4364 ('r', 'rev', [], _('target revision'), _('REV')),
4367 ('r', 'rev', [], _('target revision'), _('REV')),
4365 ],
4368 ],
4366 _('[-p|-d|-s] [-f] [-r] REV...'))
4369 _('[-p|-d|-s] [-f] [-r] REV...'))
4367 def phase(ui, repo, *revs, **opts):
4370 def phase(ui, repo, *revs, **opts):
4368 """set or show the current phase name
4371 """set or show the current phase name
4369
4372
4370 With no argument, show the phase name of specified revisions.
4373 With no argument, show the phase name of specified revisions.
4371
4374
4372 With one of -p/--public, -d/--draft or -s/--secret, change the
4375 With one of -p/--public, -d/--draft or -s/--secret, change the
4373 phase value of the specified revisions.
4376 phase value of the specified revisions.
4374
4377
4375 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4378 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4376 lower phase to an higher phase. Phases are ordered as follows::
4379 lower phase to an higher phase. Phases are ordered as follows::
4377
4380
4378 public < draft < secret
4381 public < draft < secret
4379
4382
4380 Return 0 on success, 1 if no phases were changed or some could not
4383 Return 0 on success, 1 if no phases were changed or some could not
4381 be changed.
4384 be changed.
4382 """
4385 """
4383 # search for a unique phase argument
4386 # search for a unique phase argument
4384 targetphase = None
4387 targetphase = None
4385 for idx, name in enumerate(phases.phasenames):
4388 for idx, name in enumerate(phases.phasenames):
4386 if opts[name]:
4389 if opts[name]:
4387 if targetphase is not None:
4390 if targetphase is not None:
4388 raise util.Abort(_('only one phase can be specified'))
4391 raise util.Abort(_('only one phase can be specified'))
4389 targetphase = idx
4392 targetphase = idx
4390
4393
4391 # look for specified revision
4394 # look for specified revision
4392 revs = list(revs)
4395 revs = list(revs)
4393 revs.extend(opts['rev'])
4396 revs.extend(opts['rev'])
4394 if not revs:
4397 if not revs:
4395 raise util.Abort(_('no revisions specified'))
4398 raise util.Abort(_('no revisions specified'))
4396
4399
4397 revs = scmutil.revrange(repo, revs)
4400 revs = scmutil.revrange(repo, revs)
4398
4401
4399 lock = None
4402 lock = None
4400 ret = 0
4403 ret = 0
4401 if targetphase is None:
4404 if targetphase is None:
4402 # display
4405 # display
4403 for r in revs:
4406 for r in revs:
4404 ctx = repo[r]
4407 ctx = repo[r]
4405 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4408 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4406 else:
4409 else:
4407 lock = repo.lock()
4410 lock = repo.lock()
4408 try:
4411 try:
4409 # set phase
4412 # set phase
4410 if not revs:
4413 if not revs:
4411 raise util.Abort(_('empty revision set'))
4414 raise util.Abort(_('empty revision set'))
4412 nodes = [repo[r].node() for r in revs]
4415 nodes = [repo[r].node() for r in revs]
4413 olddata = repo._phasecache.getphaserevs(repo)[:]
4416 olddata = repo._phasecache.getphaserevs(repo)[:]
4414 phases.advanceboundary(repo, targetphase, nodes)
4417 phases.advanceboundary(repo, targetphase, nodes)
4415 if opts['force']:
4418 if opts['force']:
4416 phases.retractboundary(repo, targetphase, nodes)
4419 phases.retractboundary(repo, targetphase, nodes)
4417 finally:
4420 finally:
4418 lock.release()
4421 lock.release()
4419 # moving revision from public to draft may hide them
4422 # moving revision from public to draft may hide them
4420 # We have to check result on an unfiltered repository
4423 # We have to check result on an unfiltered repository
4421 unfi = repo.unfiltered()
4424 unfi = repo.unfiltered()
4422 newdata = repo._phasecache.getphaserevs(unfi)
4425 newdata = repo._phasecache.getphaserevs(unfi)
4423 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4426 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4424 cl = unfi.changelog
4427 cl = unfi.changelog
4425 rejected = [n for n in nodes
4428 rejected = [n for n in nodes
4426 if newdata[cl.rev(n)] < targetphase]
4429 if newdata[cl.rev(n)] < targetphase]
4427 if rejected:
4430 if rejected:
4428 ui.warn(_('cannot move %i changesets to a more permissive '
4431 ui.warn(_('cannot move %i changesets to a more permissive '
4429 'phase, use --force\n') % len(rejected))
4432 'phase, use --force\n') % len(rejected))
4430 ret = 1
4433 ret = 1
4431 if changes:
4434 if changes:
4432 msg = _('phase changed for %i changesets\n') % changes
4435 msg = _('phase changed for %i changesets\n') % changes
4433 if ret:
4436 if ret:
4434 ui.status(msg)
4437 ui.status(msg)
4435 else:
4438 else:
4436 ui.note(msg)
4439 ui.note(msg)
4437 else:
4440 else:
4438 ui.warn(_('no phases changed\n'))
4441 ui.warn(_('no phases changed\n'))
4439 ret = 1
4442 ret = 1
4440 return ret
4443 return ret
4441
4444
4442 def postincoming(ui, repo, modheads, optupdate, checkout):
4445 def postincoming(ui, repo, modheads, optupdate, checkout):
4443 if modheads == 0:
4446 if modheads == 0:
4444 return
4447 return
4445 if optupdate:
4448 if optupdate:
4446 movemarkfrom = repo['.'].node()
4449 movemarkfrom = repo['.'].node()
4447 try:
4450 try:
4448 ret = hg.update(repo, checkout)
4451 ret = hg.update(repo, checkout)
4449 except util.Abort, inst:
4452 except util.Abort, inst:
4450 ui.warn(_("not updating: %s\n") % str(inst))
4453 ui.warn(_("not updating: %s\n") % str(inst))
4451 return 0
4454 return 0
4452 if not ret and not checkout:
4455 if not ret and not checkout:
4453 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4456 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4454 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4457 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4455 return ret
4458 return ret
4456 if modheads > 1:
4459 if modheads > 1:
4457 currentbranchheads = len(repo.branchheads())
4460 currentbranchheads = len(repo.branchheads())
4458 if currentbranchheads == modheads:
4461 if currentbranchheads == modheads:
4459 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4462 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4460 elif currentbranchheads > 1:
4463 elif currentbranchheads > 1:
4461 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4464 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4462 "merge)\n"))
4465 "merge)\n"))
4463 else:
4466 else:
4464 ui.status(_("(run 'hg heads' to see heads)\n"))
4467 ui.status(_("(run 'hg heads' to see heads)\n"))
4465 else:
4468 else:
4466 ui.status(_("(run 'hg update' to get a working copy)\n"))
4469 ui.status(_("(run 'hg update' to get a working copy)\n"))
4467
4470
4468 @command('^pull',
4471 @command('^pull',
4469 [('u', 'update', None,
4472 [('u', 'update', None,
4470 _('update to new branch head if changesets were pulled')),
4473 _('update to new branch head if changesets were pulled')),
4471 ('f', 'force', None, _('run even when remote repository is unrelated')),
4474 ('f', 'force', None, _('run even when remote repository is unrelated')),
4472 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4475 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4473 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4476 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4474 ('b', 'branch', [], _('a specific branch you would like to pull'),
4477 ('b', 'branch', [], _('a specific branch you would like to pull'),
4475 _('BRANCH')),
4478 _('BRANCH')),
4476 ] + remoteopts,
4479 ] + remoteopts,
4477 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4480 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4478 def pull(ui, repo, source="default", **opts):
4481 def pull(ui, repo, source="default", **opts):
4479 """pull changes from the specified source
4482 """pull changes from the specified source
4480
4483
4481 Pull changes from a remote repository to a local one.
4484 Pull changes from a remote repository to a local one.
4482
4485
4483 This finds all changes from the repository at the specified path
4486 This finds all changes from the repository at the specified path
4484 or URL and adds them to a local repository (the current one unless
4487 or URL and adds them to a local repository (the current one unless
4485 -R is specified). By default, this does not update the copy of the
4488 -R is specified). By default, this does not update the copy of the
4486 project in the working directory.
4489 project in the working directory.
4487
4490
4488 Use :hg:`incoming` if you want to see what would have been added
4491 Use :hg:`incoming` if you want to see what would have been added
4489 by a pull at the time you issued this command. If you then decide
4492 by a pull at the time you issued this command. If you then decide
4490 to add those changes to the repository, you should use :hg:`pull
4493 to add those changes to the repository, you should use :hg:`pull
4491 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4494 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4492
4495
4493 If SOURCE is omitted, the 'default' path will be used.
4496 If SOURCE is omitted, the 'default' path will be used.
4494 See :hg:`help urls` for more information.
4497 See :hg:`help urls` for more information.
4495
4498
4496 Returns 0 on success, 1 if an update had unresolved files.
4499 Returns 0 on success, 1 if an update had unresolved files.
4497 """
4500 """
4498 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4501 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4499 other = hg.peer(repo, opts, source)
4502 other = hg.peer(repo, opts, source)
4500 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4503 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4501 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4504 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4502
4505
4503 remotebookmarks = other.listkeys('bookmarks')
4506 remotebookmarks = other.listkeys('bookmarks')
4504
4507
4505 if opts.get('bookmark'):
4508 if opts.get('bookmark'):
4506 if not revs:
4509 if not revs:
4507 revs = []
4510 revs = []
4508 for b in opts['bookmark']:
4511 for b in opts['bookmark']:
4509 if b not in remotebookmarks:
4512 if b not in remotebookmarks:
4510 raise util.Abort(_('remote bookmark %s not found!') % b)
4513 raise util.Abort(_('remote bookmark %s not found!') % b)
4511 revs.append(remotebookmarks[b])
4514 revs.append(remotebookmarks[b])
4512
4515
4513 if revs:
4516 if revs:
4514 try:
4517 try:
4515 revs = [other.lookup(rev) for rev in revs]
4518 revs = [other.lookup(rev) for rev in revs]
4516 except error.CapabilityError:
4519 except error.CapabilityError:
4517 err = _("other repository doesn't support revision lookup, "
4520 err = _("other repository doesn't support revision lookup, "
4518 "so a rev cannot be specified.")
4521 "so a rev cannot be specified.")
4519 raise util.Abort(err)
4522 raise util.Abort(err)
4520
4523
4521 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4524 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4522 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4525 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4523 if checkout:
4526 if checkout:
4524 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4527 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4525 repo._subtoppath = source
4528 repo._subtoppath = source
4526 try:
4529 try:
4527 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4530 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4528
4531
4529 finally:
4532 finally:
4530 del repo._subtoppath
4533 del repo._subtoppath
4531
4534
4532 # update specified bookmarks
4535 # update specified bookmarks
4533 if opts.get('bookmark'):
4536 if opts.get('bookmark'):
4534 marks = repo._bookmarks
4537 marks = repo._bookmarks
4535 for b in opts['bookmark']:
4538 for b in opts['bookmark']:
4536 # explicit pull overrides local bookmark if any
4539 # explicit pull overrides local bookmark if any
4537 ui.status(_("importing bookmark %s\n") % b)
4540 ui.status(_("importing bookmark %s\n") % b)
4538 marks[b] = repo[remotebookmarks[b]].node()
4541 marks[b] = repo[remotebookmarks[b]].node()
4539 marks.write()
4542 marks.write()
4540
4543
4541 return ret
4544 return ret
4542
4545
4543 @command('^push',
4546 @command('^push',
4544 [('f', 'force', None, _('force push')),
4547 [('f', 'force', None, _('force push')),
4545 ('r', 'rev', [],
4548 ('r', 'rev', [],
4546 _('a changeset intended to be included in the destination'),
4549 _('a changeset intended to be included in the destination'),
4547 _('REV')),
4550 _('REV')),
4548 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4551 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4549 ('b', 'branch', [],
4552 ('b', 'branch', [],
4550 _('a specific branch you would like to push'), _('BRANCH')),
4553 _('a specific branch you would like to push'), _('BRANCH')),
4551 ('', 'new-branch', False, _('allow pushing a new branch')),
4554 ('', 'new-branch', False, _('allow pushing a new branch')),
4552 ] + remoteopts,
4555 ] + remoteopts,
4553 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4556 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4554 def push(ui, repo, dest=None, **opts):
4557 def push(ui, repo, dest=None, **opts):
4555 """push changes to the specified destination
4558 """push changes to the specified destination
4556
4559
4557 Push changesets from the local repository to the specified
4560 Push changesets from the local repository to the specified
4558 destination.
4561 destination.
4559
4562
4560 This operation is symmetrical to pull: it is identical to a pull
4563 This operation is symmetrical to pull: it is identical to a pull
4561 in the destination repository from the current one.
4564 in the destination repository from the current one.
4562
4565
4563 By default, push will not allow creation of new heads at the
4566 By default, push will not allow creation of new heads at the
4564 destination, since multiple heads would make it unclear which head
4567 destination, since multiple heads would make it unclear which head
4565 to use. In this situation, it is recommended to pull and merge
4568 to use. In this situation, it is recommended to pull and merge
4566 before pushing.
4569 before pushing.
4567
4570
4568 Use --new-branch if you want to allow push to create a new named
4571 Use --new-branch if you want to allow push to create a new named
4569 branch that is not present at the destination. This allows you to
4572 branch that is not present at the destination. This allows you to
4570 only create a new branch without forcing other changes.
4573 only create a new branch without forcing other changes.
4571
4574
4572 Use -f/--force to override the default behavior and push all
4575 Use -f/--force to override the default behavior and push all
4573 changesets on all branches.
4576 changesets on all branches.
4574
4577
4575 If -r/--rev is used, the specified revision and all its ancestors
4578 If -r/--rev is used, the specified revision and all its ancestors
4576 will be pushed to the remote repository.
4579 will be pushed to the remote repository.
4577
4580
4578 If -B/--bookmark is used, the specified bookmarked revision, its
4581 If -B/--bookmark is used, the specified bookmarked revision, its
4579 ancestors, and the bookmark will be pushed to the remote
4582 ancestors, and the bookmark will be pushed to the remote
4580 repository.
4583 repository.
4581
4584
4582 Please see :hg:`help urls` for important details about ``ssh://``
4585 Please see :hg:`help urls` for important details about ``ssh://``
4583 URLs. If DESTINATION is omitted, a default path will be used.
4586 URLs. If DESTINATION is omitted, a default path will be used.
4584
4587
4585 Returns 0 if push was successful, 1 if nothing to push.
4588 Returns 0 if push was successful, 1 if nothing to push.
4586 """
4589 """
4587
4590
4588 if opts.get('bookmark'):
4591 if opts.get('bookmark'):
4589 for b in opts['bookmark']:
4592 for b in opts['bookmark']:
4590 # translate -B options to -r so changesets get pushed
4593 # translate -B options to -r so changesets get pushed
4591 if b in repo._bookmarks:
4594 if b in repo._bookmarks:
4592 opts.setdefault('rev', []).append(b)
4595 opts.setdefault('rev', []).append(b)
4593 else:
4596 else:
4594 # if we try to push a deleted bookmark, translate it to null
4597 # if we try to push a deleted bookmark, translate it to null
4595 # this lets simultaneous -r, -b options continue working
4598 # this lets simultaneous -r, -b options continue working
4596 opts.setdefault('rev', []).append("null")
4599 opts.setdefault('rev', []).append("null")
4597
4600
4598 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4601 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4599 dest, branches = hg.parseurl(dest, opts.get('branch'))
4602 dest, branches = hg.parseurl(dest, opts.get('branch'))
4600 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4603 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4601 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4604 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4602 other = hg.peer(repo, opts, dest)
4605 other = hg.peer(repo, opts, dest)
4603 if revs:
4606 if revs:
4604 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4607 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4605
4608
4606 repo._subtoppath = dest
4609 repo._subtoppath = dest
4607 try:
4610 try:
4608 # push subrepos depth-first for coherent ordering
4611 # push subrepos depth-first for coherent ordering
4609 c = repo['']
4612 c = repo['']
4610 subs = c.substate # only repos that are committed
4613 subs = c.substate # only repos that are committed
4611 for s in sorted(subs):
4614 for s in sorted(subs):
4612 if c.sub(s).push(opts) == 0:
4615 if c.sub(s).push(opts) == 0:
4613 return False
4616 return False
4614 finally:
4617 finally:
4615 del repo._subtoppath
4618 del repo._subtoppath
4616 result = repo.push(other, opts.get('force'), revs=revs,
4619 result = repo.push(other, opts.get('force'), revs=revs,
4617 newbranch=opts.get('new_branch'))
4620 newbranch=opts.get('new_branch'))
4618
4621
4619 result = not result
4622 result = not result
4620
4623
4621 if opts.get('bookmark'):
4624 if opts.get('bookmark'):
4622 rb = other.listkeys('bookmarks')
4625 rb = other.listkeys('bookmarks')
4623 for b in opts['bookmark']:
4626 for b in opts['bookmark']:
4624 # explicit push overrides remote bookmark if any
4627 # explicit push overrides remote bookmark if any
4625 if b in repo._bookmarks:
4628 if b in repo._bookmarks:
4626 ui.status(_("exporting bookmark %s\n") % b)
4629 ui.status(_("exporting bookmark %s\n") % b)
4627 new = repo[b].hex()
4630 new = repo[b].hex()
4628 elif b in rb:
4631 elif b in rb:
4629 ui.status(_("deleting remote bookmark %s\n") % b)
4632 ui.status(_("deleting remote bookmark %s\n") % b)
4630 new = '' # delete
4633 new = '' # delete
4631 else:
4634 else:
4632 ui.warn(_('bookmark %s does not exist on the local '
4635 ui.warn(_('bookmark %s does not exist on the local '
4633 'or remote repository!\n') % b)
4636 'or remote repository!\n') % b)
4634 return 2
4637 return 2
4635 old = rb.get(b, '')
4638 old = rb.get(b, '')
4636 r = other.pushkey('bookmarks', b, old, new)
4639 r = other.pushkey('bookmarks', b, old, new)
4637 if not r:
4640 if not r:
4638 ui.warn(_('updating bookmark %s failed!\n') % b)
4641 ui.warn(_('updating bookmark %s failed!\n') % b)
4639 if not result:
4642 if not result:
4640 result = 2
4643 result = 2
4641
4644
4642 return result
4645 return result
4643
4646
4644 @command('recover', [])
4647 @command('recover', [])
4645 def recover(ui, repo):
4648 def recover(ui, repo):
4646 """roll back an interrupted transaction
4649 """roll back an interrupted transaction
4647
4650
4648 Recover from an interrupted commit or pull.
4651 Recover from an interrupted commit or pull.
4649
4652
4650 This command tries to fix the repository status after an
4653 This command tries to fix the repository status after an
4651 interrupted operation. It should only be necessary when Mercurial
4654 interrupted operation. It should only be necessary when Mercurial
4652 suggests it.
4655 suggests it.
4653
4656
4654 Returns 0 if successful, 1 if nothing to recover or verify fails.
4657 Returns 0 if successful, 1 if nothing to recover or verify fails.
4655 """
4658 """
4656 if repo.recover():
4659 if repo.recover():
4657 return hg.verify(repo)
4660 return hg.verify(repo)
4658 return 1
4661 return 1
4659
4662
4660 @command('^remove|rm',
4663 @command('^remove|rm',
4661 [('A', 'after', None, _('record delete for missing files')),
4664 [('A', 'after', None, _('record delete for missing files')),
4662 ('f', 'force', None,
4665 ('f', 'force', None,
4663 _('remove (and delete) file even if added or modified')),
4666 _('remove (and delete) file even if added or modified')),
4664 ] + walkopts,
4667 ] + walkopts,
4665 _('[OPTION]... FILE...'))
4668 _('[OPTION]... FILE...'))
4666 def remove(ui, repo, *pats, **opts):
4669 def remove(ui, repo, *pats, **opts):
4667 """remove the specified files on the next commit
4670 """remove the specified files on the next commit
4668
4671
4669 Schedule the indicated files for removal from the current branch.
4672 Schedule the indicated files for removal from the current branch.
4670
4673
4671 This command schedules the files to be removed at the next commit.
4674 This command schedules the files to be removed at the next commit.
4672 To undo a remove before that, see :hg:`revert`. To undo added
4675 To undo a remove before that, see :hg:`revert`. To undo added
4673 files, see :hg:`forget`.
4676 files, see :hg:`forget`.
4674
4677
4675 .. container:: verbose
4678 .. container:: verbose
4676
4679
4677 -A/--after can be used to remove only files that have already
4680 -A/--after can be used to remove only files that have already
4678 been deleted, -f/--force can be used to force deletion, and -Af
4681 been deleted, -f/--force can be used to force deletion, and -Af
4679 can be used to remove files from the next revision without
4682 can be used to remove files from the next revision without
4680 deleting them from the working directory.
4683 deleting them from the working directory.
4681
4684
4682 The following table details the behavior of remove for different
4685 The following table details the behavior of remove for different
4683 file states (columns) and option combinations (rows). The file
4686 file states (columns) and option combinations (rows). The file
4684 states are Added [A], Clean [C], Modified [M] and Missing [!]
4687 states are Added [A], Clean [C], Modified [M] and Missing [!]
4685 (as reported by :hg:`status`). The actions are Warn, Remove
4688 (as reported by :hg:`status`). The actions are Warn, Remove
4686 (from branch) and Delete (from disk):
4689 (from branch) and Delete (from disk):
4687
4690
4688 ======= == == == ==
4691 ======= == == == ==
4689 A C M !
4692 A C M !
4690 ======= == == == ==
4693 ======= == == == ==
4691 none W RD W R
4694 none W RD W R
4692 -f R RD RD R
4695 -f R RD RD R
4693 -A W W W R
4696 -A W W W R
4694 -Af R R R R
4697 -Af R R R R
4695 ======= == == == ==
4698 ======= == == == ==
4696
4699
4697 Note that remove never deletes files in Added [A] state from the
4700 Note that remove never deletes files in Added [A] state from the
4698 working directory, not even if option --force is specified.
4701 working directory, not even if option --force is specified.
4699
4702
4700 Returns 0 on success, 1 if any warnings encountered.
4703 Returns 0 on success, 1 if any warnings encountered.
4701 """
4704 """
4702
4705
4703 ret = 0
4706 ret = 0
4704 after, force = opts.get('after'), opts.get('force')
4707 after, force = opts.get('after'), opts.get('force')
4705 if not pats and not after:
4708 if not pats and not after:
4706 raise util.Abort(_('no files specified'))
4709 raise util.Abort(_('no files specified'))
4707
4710
4708 m = scmutil.match(repo[None], pats, opts)
4711 m = scmutil.match(repo[None], pats, opts)
4709 s = repo.status(match=m, clean=True)
4712 s = repo.status(match=m, clean=True)
4710 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4713 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4711
4714
4712 # warn about failure to delete explicit files/dirs
4715 # warn about failure to delete explicit files/dirs
4713 wctx = repo[None]
4716 wctx = repo[None]
4714 for f in m.files():
4717 for f in m.files():
4715 if f in repo.dirstate or f in wctx.dirs():
4718 if f in repo.dirstate or f in wctx.dirs():
4716 continue
4719 continue
4717 if os.path.exists(m.rel(f)):
4720 if os.path.exists(m.rel(f)):
4718 if os.path.isdir(m.rel(f)):
4721 if os.path.isdir(m.rel(f)):
4719 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4722 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4720 else:
4723 else:
4721 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4724 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4722 # missing files will generate a warning elsewhere
4725 # missing files will generate a warning elsewhere
4723 ret = 1
4726 ret = 1
4724
4727
4725 if force:
4728 if force:
4726 list = modified + deleted + clean + added
4729 list = modified + deleted + clean + added
4727 elif after:
4730 elif after:
4728 list = deleted
4731 list = deleted
4729 for f in modified + added + clean:
4732 for f in modified + added + clean:
4730 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4733 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4731 ret = 1
4734 ret = 1
4732 else:
4735 else:
4733 list = deleted + clean
4736 list = deleted + clean
4734 for f in modified:
4737 for f in modified:
4735 ui.warn(_('not removing %s: file is modified (use -f'
4738 ui.warn(_('not removing %s: file is modified (use -f'
4736 ' to force removal)\n') % m.rel(f))
4739 ' to force removal)\n') % m.rel(f))
4737 ret = 1
4740 ret = 1
4738 for f in added:
4741 for f in added:
4739 ui.warn(_('not removing %s: file has been marked for add'
4742 ui.warn(_('not removing %s: file has been marked for add'
4740 ' (use forget to undo)\n') % m.rel(f))
4743 ' (use forget to undo)\n') % m.rel(f))
4741 ret = 1
4744 ret = 1
4742
4745
4743 for f in sorted(list):
4746 for f in sorted(list):
4744 if ui.verbose or not m.exact(f):
4747 if ui.verbose or not m.exact(f):
4745 ui.status(_('removing %s\n') % m.rel(f))
4748 ui.status(_('removing %s\n') % m.rel(f))
4746
4749
4747 wlock = repo.wlock()
4750 wlock = repo.wlock()
4748 try:
4751 try:
4749 if not after:
4752 if not after:
4750 for f in list:
4753 for f in list:
4751 if f in added:
4754 if f in added:
4752 continue # we never unlink added files on remove
4755 continue # we never unlink added files on remove
4753 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4756 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4754 repo[None].forget(list)
4757 repo[None].forget(list)
4755 finally:
4758 finally:
4756 wlock.release()
4759 wlock.release()
4757
4760
4758 return ret
4761 return ret
4759
4762
4760 @command('rename|move|mv',
4763 @command('rename|move|mv',
4761 [('A', 'after', None, _('record a rename that has already occurred')),
4764 [('A', 'after', None, _('record a rename that has already occurred')),
4762 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4765 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4763 ] + walkopts + dryrunopts,
4766 ] + walkopts + dryrunopts,
4764 _('[OPTION]... SOURCE... DEST'))
4767 _('[OPTION]... SOURCE... DEST'))
4765 def rename(ui, repo, *pats, **opts):
4768 def rename(ui, repo, *pats, **opts):
4766 """rename files; equivalent of copy + remove
4769 """rename files; equivalent of copy + remove
4767
4770
4768 Mark dest as copies of sources; mark sources for deletion. If dest
4771 Mark dest as copies of sources; mark sources for deletion. If dest
4769 is a directory, copies are put in that directory. If dest is a
4772 is a directory, copies are put in that directory. If dest is a
4770 file, there can only be one source.
4773 file, there can only be one source.
4771
4774
4772 By default, this command copies the contents of files as they
4775 By default, this command copies the contents of files as they
4773 exist in the working directory. If invoked with -A/--after, the
4776 exist in the working directory. If invoked with -A/--after, the
4774 operation is recorded, but no copying is performed.
4777 operation is recorded, but no copying is performed.
4775
4778
4776 This command takes effect at the next commit. To undo a rename
4779 This command takes effect at the next commit. To undo a rename
4777 before that, see :hg:`revert`.
4780 before that, see :hg:`revert`.
4778
4781
4779 Returns 0 on success, 1 if errors are encountered.
4782 Returns 0 on success, 1 if errors are encountered.
4780 """
4783 """
4781 wlock = repo.wlock(False)
4784 wlock = repo.wlock(False)
4782 try:
4785 try:
4783 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4786 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4784 finally:
4787 finally:
4785 wlock.release()
4788 wlock.release()
4786
4789
4787 @command('resolve',
4790 @command('resolve',
4788 [('a', 'all', None, _('select all unresolved files')),
4791 [('a', 'all', None, _('select all unresolved files')),
4789 ('l', 'list', None, _('list state of files needing merge')),
4792 ('l', 'list', None, _('list state of files needing merge')),
4790 ('m', 'mark', None, _('mark files as resolved')),
4793 ('m', 'mark', None, _('mark files as resolved')),
4791 ('u', 'unmark', None, _('mark files as unresolved')),
4794 ('u', 'unmark', None, _('mark files as unresolved')),
4792 ('n', 'no-status', None, _('hide status prefix'))]
4795 ('n', 'no-status', None, _('hide status prefix'))]
4793 + mergetoolopts + walkopts,
4796 + mergetoolopts + walkopts,
4794 _('[OPTION]... [FILE]...'))
4797 _('[OPTION]... [FILE]...'))
4795 def resolve(ui, repo, *pats, **opts):
4798 def resolve(ui, repo, *pats, **opts):
4796 """redo merges or set/view the merge status of files
4799 """redo merges or set/view the merge status of files
4797
4800
4798 Merges with unresolved conflicts are often the result of
4801 Merges with unresolved conflicts are often the result of
4799 non-interactive merging using the ``internal:merge`` configuration
4802 non-interactive merging using the ``internal:merge`` configuration
4800 setting, or a command-line merge tool like ``diff3``. The resolve
4803 setting, or a command-line merge tool like ``diff3``. The resolve
4801 command is used to manage the files involved in a merge, after
4804 command is used to manage the files involved in a merge, after
4802 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4805 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4803 working directory must have two parents). See :hg:`help
4806 working directory must have two parents). See :hg:`help
4804 merge-tools` for information on configuring merge tools.
4807 merge-tools` for information on configuring merge tools.
4805
4808
4806 The resolve command can be used in the following ways:
4809 The resolve command can be used in the following ways:
4807
4810
4808 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4811 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4809 files, discarding any previous merge attempts. Re-merging is not
4812 files, discarding any previous merge attempts. Re-merging is not
4810 performed for files already marked as resolved. Use ``--all/-a``
4813 performed for files already marked as resolved. Use ``--all/-a``
4811 to select all unresolved files. ``--tool`` can be used to specify
4814 to select all unresolved files. ``--tool`` can be used to specify
4812 the merge tool used for the given files. It overrides the HGMERGE
4815 the merge tool used for the given files. It overrides the HGMERGE
4813 environment variable and your configuration files. Previous file
4816 environment variable and your configuration files. Previous file
4814 contents are saved with a ``.orig`` suffix.
4817 contents are saved with a ``.orig`` suffix.
4815
4818
4816 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4819 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4817 (e.g. after having manually fixed-up the files). The default is
4820 (e.g. after having manually fixed-up the files). The default is
4818 to mark all unresolved files.
4821 to mark all unresolved files.
4819
4822
4820 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4823 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4821 default is to mark all resolved files.
4824 default is to mark all resolved files.
4822
4825
4823 - :hg:`resolve -l`: list files which had or still have conflicts.
4826 - :hg:`resolve -l`: list files which had or still have conflicts.
4824 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4827 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4825
4828
4826 Note that Mercurial will not let you commit files with unresolved
4829 Note that Mercurial will not let you commit files with unresolved
4827 merge conflicts. You must use :hg:`resolve -m ...` before you can
4830 merge conflicts. You must use :hg:`resolve -m ...` before you can
4828 commit after a conflicting merge.
4831 commit after a conflicting merge.
4829
4832
4830 Returns 0 on success, 1 if any files fail a resolve attempt.
4833 Returns 0 on success, 1 if any files fail a resolve attempt.
4831 """
4834 """
4832
4835
4833 all, mark, unmark, show, nostatus = \
4836 all, mark, unmark, show, nostatus = \
4834 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4837 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4835
4838
4836 if (show and (mark or unmark)) or (mark and unmark):
4839 if (show and (mark or unmark)) or (mark and unmark):
4837 raise util.Abort(_("too many options specified"))
4840 raise util.Abort(_("too many options specified"))
4838 if pats and all:
4841 if pats and all:
4839 raise util.Abort(_("can't specify --all and patterns"))
4842 raise util.Abort(_("can't specify --all and patterns"))
4840 if not (all or pats or show or mark or unmark):
4843 if not (all or pats or show or mark or unmark):
4841 raise util.Abort(_('no files or directories specified; '
4844 raise util.Abort(_('no files or directories specified; '
4842 'use --all to remerge all files'))
4845 'use --all to remerge all files'))
4843
4846
4844 ms = mergemod.mergestate(repo)
4847 ms = mergemod.mergestate(repo)
4845 m = scmutil.match(repo[None], pats, opts)
4848 m = scmutil.match(repo[None], pats, opts)
4846 ret = 0
4849 ret = 0
4847
4850
4848 for f in ms:
4851 for f in ms:
4849 if m(f):
4852 if m(f):
4850 if show:
4853 if show:
4851 if nostatus:
4854 if nostatus:
4852 ui.write("%s\n" % f)
4855 ui.write("%s\n" % f)
4853 else:
4856 else:
4854 ui.write("%s %s\n" % (ms[f].upper(), f),
4857 ui.write("%s %s\n" % (ms[f].upper(), f),
4855 label='resolve.' +
4858 label='resolve.' +
4856 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4859 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4857 elif mark:
4860 elif mark:
4858 ms.mark(f, "r")
4861 ms.mark(f, "r")
4859 elif unmark:
4862 elif unmark:
4860 ms.mark(f, "u")
4863 ms.mark(f, "u")
4861 else:
4864 else:
4862 wctx = repo[None]
4865 wctx = repo[None]
4863 mctx = wctx.parents()[-1]
4866 mctx = wctx.parents()[-1]
4864
4867
4865 # backup pre-resolve (merge uses .orig for its own purposes)
4868 # backup pre-resolve (merge uses .orig for its own purposes)
4866 a = repo.wjoin(f)
4869 a = repo.wjoin(f)
4867 util.copyfile(a, a + ".resolve")
4870 util.copyfile(a, a + ".resolve")
4868
4871
4869 try:
4872 try:
4870 # resolve file
4873 # resolve file
4871 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4874 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4872 if ms.resolve(f, wctx, mctx):
4875 if ms.resolve(f, wctx, mctx):
4873 ret = 1
4876 ret = 1
4874 finally:
4877 finally:
4875 ui.setconfig('ui', 'forcemerge', '')
4878 ui.setconfig('ui', 'forcemerge', '')
4876 ms.commit()
4879 ms.commit()
4877
4880
4878 # replace filemerge's .orig file with our resolve file
4881 # replace filemerge's .orig file with our resolve file
4879 util.rename(a + ".resolve", a + ".orig")
4882 util.rename(a + ".resolve", a + ".orig")
4880
4883
4881 ms.commit()
4884 ms.commit()
4882 return ret
4885 return ret
4883
4886
4884 @command('revert',
4887 @command('revert',
4885 [('a', 'all', None, _('revert all changes when no arguments given')),
4888 [('a', 'all', None, _('revert all changes when no arguments given')),
4886 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4889 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4887 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4890 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4888 ('C', 'no-backup', None, _('do not save backup copies of files')),
4891 ('C', 'no-backup', None, _('do not save backup copies of files')),
4889 ] + walkopts + dryrunopts,
4892 ] + walkopts + dryrunopts,
4890 _('[OPTION]... [-r REV] [NAME]...'))
4893 _('[OPTION]... [-r REV] [NAME]...'))
4891 def revert(ui, repo, *pats, **opts):
4894 def revert(ui, repo, *pats, **opts):
4892 """restore files to their checkout state
4895 """restore files to their checkout state
4893
4896
4894 .. note::
4897 .. note::
4895
4898
4896 To check out earlier revisions, you should use :hg:`update REV`.
4899 To check out earlier revisions, you should use :hg:`update REV`.
4897 To cancel an uncommitted merge (and lose your changes), use
4900 To cancel an uncommitted merge (and lose your changes), use
4898 :hg:`update --clean .`.
4901 :hg:`update --clean .`.
4899
4902
4900 With no revision specified, revert the specified files or directories
4903 With no revision specified, revert the specified files or directories
4901 to the contents they had in the parent of the working directory.
4904 to the contents they had in the parent of the working directory.
4902 This restores the contents of files to an unmodified
4905 This restores the contents of files to an unmodified
4903 state and unschedules adds, removes, copies, and renames. If the
4906 state and unschedules adds, removes, copies, and renames. If the
4904 working directory has two parents, you must explicitly specify a
4907 working directory has two parents, you must explicitly specify a
4905 revision.
4908 revision.
4906
4909
4907 Using the -r/--rev or -d/--date options, revert the given files or
4910 Using the -r/--rev or -d/--date options, revert the given files or
4908 directories to their states as of a specific revision. Because
4911 directories to their states as of a specific revision. Because
4909 revert does not change the working directory parents, this will
4912 revert does not change the working directory parents, this will
4910 cause these files to appear modified. This can be helpful to "back
4913 cause these files to appear modified. This can be helpful to "back
4911 out" some or all of an earlier change. See :hg:`backout` for a
4914 out" some or all of an earlier change. See :hg:`backout` for a
4912 related method.
4915 related method.
4913
4916
4914 Modified files are saved with a .orig suffix before reverting.
4917 Modified files are saved with a .orig suffix before reverting.
4915 To disable these backups, use --no-backup.
4918 To disable these backups, use --no-backup.
4916
4919
4917 See :hg:`help dates` for a list of formats valid for -d/--date.
4920 See :hg:`help dates` for a list of formats valid for -d/--date.
4918
4921
4919 Returns 0 on success.
4922 Returns 0 on success.
4920 """
4923 """
4921
4924
4922 if opts.get("date"):
4925 if opts.get("date"):
4923 if opts.get("rev"):
4926 if opts.get("rev"):
4924 raise util.Abort(_("you can't specify a revision and a date"))
4927 raise util.Abort(_("you can't specify a revision and a date"))
4925 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4928 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4926
4929
4927 parent, p2 = repo.dirstate.parents()
4930 parent, p2 = repo.dirstate.parents()
4928 if not opts.get('rev') and p2 != nullid:
4931 if not opts.get('rev') and p2 != nullid:
4929 # revert after merge is a trap for new users (issue2915)
4932 # revert after merge is a trap for new users (issue2915)
4930 raise util.Abort(_('uncommitted merge with no revision specified'),
4933 raise util.Abort(_('uncommitted merge with no revision specified'),
4931 hint=_('use "hg update" or see "hg help revert"'))
4934 hint=_('use "hg update" or see "hg help revert"'))
4932
4935
4933 ctx = scmutil.revsingle(repo, opts.get('rev'))
4936 ctx = scmutil.revsingle(repo, opts.get('rev'))
4934
4937
4935 if not pats and not opts.get('all'):
4938 if not pats and not opts.get('all'):
4936 msg = _("no files or directories specified")
4939 msg = _("no files or directories specified")
4937 if p2 != nullid:
4940 if p2 != nullid:
4938 hint = _("uncommitted merge, use --all to discard all changes,"
4941 hint = _("uncommitted merge, use --all to discard all changes,"
4939 " or 'hg update -C .' to abort the merge")
4942 " or 'hg update -C .' to abort the merge")
4940 raise util.Abort(msg, hint=hint)
4943 raise util.Abort(msg, hint=hint)
4941 dirty = util.any(repo.status())
4944 dirty = util.any(repo.status())
4942 node = ctx.node()
4945 node = ctx.node()
4943 if node != parent:
4946 if node != parent:
4944 if dirty:
4947 if dirty:
4945 hint = _("uncommitted changes, use --all to discard all"
4948 hint = _("uncommitted changes, use --all to discard all"
4946 " changes, or 'hg update %s' to update") % ctx.rev()
4949 " changes, or 'hg update %s' to update") % ctx.rev()
4947 else:
4950 else:
4948 hint = _("use --all to revert all files,"
4951 hint = _("use --all to revert all files,"
4949 " or 'hg update %s' to update") % ctx.rev()
4952 " or 'hg update %s' to update") % ctx.rev()
4950 elif dirty:
4953 elif dirty:
4951 hint = _("uncommitted changes, use --all to discard all changes")
4954 hint = _("uncommitted changes, use --all to discard all changes")
4952 else:
4955 else:
4953 hint = _("use --all to revert all files")
4956 hint = _("use --all to revert all files")
4954 raise util.Abort(msg, hint=hint)
4957 raise util.Abort(msg, hint=hint)
4955
4958
4956 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4959 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4957
4960
4958 @command('rollback', dryrunopts +
4961 @command('rollback', dryrunopts +
4959 [('f', 'force', False, _('ignore safety measures'))])
4962 [('f', 'force', False, _('ignore safety measures'))])
4960 def rollback(ui, repo, **opts):
4963 def rollback(ui, repo, **opts):
4961 """roll back the last transaction (dangerous)
4964 """roll back the last transaction (dangerous)
4962
4965
4963 This command should be used with care. There is only one level of
4966 This command should be used with care. There is only one level of
4964 rollback, and there is no way to undo a rollback. It will also
4967 rollback, and there is no way to undo a rollback. It will also
4965 restore the dirstate at the time of the last transaction, losing
4968 restore the dirstate at the time of the last transaction, losing
4966 any dirstate changes since that time. This command does not alter
4969 any dirstate changes since that time. This command does not alter
4967 the working directory.
4970 the working directory.
4968
4971
4969 Transactions are used to encapsulate the effects of all commands
4972 Transactions are used to encapsulate the effects of all commands
4970 that create new changesets or propagate existing changesets into a
4973 that create new changesets or propagate existing changesets into a
4971 repository.
4974 repository.
4972
4975
4973 .. container:: verbose
4976 .. container:: verbose
4974
4977
4975 For example, the following commands are transactional, and their
4978 For example, the following commands are transactional, and their
4976 effects can be rolled back:
4979 effects can be rolled back:
4977
4980
4978 - commit
4981 - commit
4979 - import
4982 - import
4980 - pull
4983 - pull
4981 - push (with this repository as the destination)
4984 - push (with this repository as the destination)
4982 - unbundle
4985 - unbundle
4983
4986
4984 To avoid permanent data loss, rollback will refuse to rollback a
4987 To avoid permanent data loss, rollback will refuse to rollback a
4985 commit transaction if it isn't checked out. Use --force to
4988 commit transaction if it isn't checked out. Use --force to
4986 override this protection.
4989 override this protection.
4987
4990
4988 This command is not intended for use on public repositories. Once
4991 This command is not intended for use on public repositories. Once
4989 changes are visible for pull by other users, rolling a transaction
4992 changes are visible for pull by other users, rolling a transaction
4990 back locally is ineffective (someone else may already have pulled
4993 back locally is ineffective (someone else may already have pulled
4991 the changes). Furthermore, a race is possible with readers of the
4994 the changes). Furthermore, a race is possible with readers of the
4992 repository; for example an in-progress pull from the repository
4995 repository; for example an in-progress pull from the repository
4993 may fail if a rollback is performed.
4996 may fail if a rollback is performed.
4994
4997
4995 Returns 0 on success, 1 if no rollback data is available.
4998 Returns 0 on success, 1 if no rollback data is available.
4996 """
4999 """
4997 return repo.rollback(dryrun=opts.get('dry_run'),
5000 return repo.rollback(dryrun=opts.get('dry_run'),
4998 force=opts.get('force'))
5001 force=opts.get('force'))
4999
5002
5000 @command('root', [])
5003 @command('root', [])
5001 def root(ui, repo):
5004 def root(ui, repo):
5002 """print the root (top) of the current working directory
5005 """print the root (top) of the current working directory
5003
5006
5004 Print the root directory of the current repository.
5007 Print the root directory of the current repository.
5005
5008
5006 Returns 0 on success.
5009 Returns 0 on success.
5007 """
5010 """
5008 ui.write(repo.root + "\n")
5011 ui.write(repo.root + "\n")
5009
5012
5010 @command('^serve',
5013 @command('^serve',
5011 [('A', 'accesslog', '', _('name of access log file to write to'),
5014 [('A', 'accesslog', '', _('name of access log file to write to'),
5012 _('FILE')),
5015 _('FILE')),
5013 ('d', 'daemon', None, _('run server in background')),
5016 ('d', 'daemon', None, _('run server in background')),
5014 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5017 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5015 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5018 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5016 # use string type, then we can check if something was passed
5019 # use string type, then we can check if something was passed
5017 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5020 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5018 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5021 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5019 _('ADDR')),
5022 _('ADDR')),
5020 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5023 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5021 _('PREFIX')),
5024 _('PREFIX')),
5022 ('n', 'name', '',
5025 ('n', 'name', '',
5023 _('name to show in web pages (default: working directory)'), _('NAME')),
5026 _('name to show in web pages (default: working directory)'), _('NAME')),
5024 ('', 'web-conf', '',
5027 ('', 'web-conf', '',
5025 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5028 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5026 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5029 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5027 _('FILE')),
5030 _('FILE')),
5028 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5031 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5029 ('', 'stdio', None, _('for remote clients')),
5032 ('', 'stdio', None, _('for remote clients')),
5030 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5033 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5031 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5034 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5032 ('', 'style', '', _('template style to use'), _('STYLE')),
5035 ('', 'style', '', _('template style to use'), _('STYLE')),
5033 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5036 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5034 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5037 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5035 _('[OPTION]...'))
5038 _('[OPTION]...'))
5036 def serve(ui, repo, **opts):
5039 def serve(ui, repo, **opts):
5037 """start stand-alone webserver
5040 """start stand-alone webserver
5038
5041
5039 Start a local HTTP repository browser and pull server. You can use
5042 Start a local HTTP repository browser and pull server. You can use
5040 this for ad-hoc sharing and browsing of repositories. It is
5043 this for ad-hoc sharing and browsing of repositories. It is
5041 recommended to use a real web server to serve a repository for
5044 recommended to use a real web server to serve a repository for
5042 longer periods of time.
5045 longer periods of time.
5043
5046
5044 Please note that the server does not implement access control.
5047 Please note that the server does not implement access control.
5045 This means that, by default, anybody can read from the server and
5048 This means that, by default, anybody can read from the server and
5046 nobody can write to it by default. Set the ``web.allow_push``
5049 nobody can write to it by default. Set the ``web.allow_push``
5047 option to ``*`` to allow everybody to push to the server. You
5050 option to ``*`` to allow everybody to push to the server. You
5048 should use a real web server if you need to authenticate users.
5051 should use a real web server if you need to authenticate users.
5049
5052
5050 By default, the server logs accesses to stdout and errors to
5053 By default, the server logs accesses to stdout and errors to
5051 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5054 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5052 files.
5055 files.
5053
5056
5054 To have the server choose a free port number to listen on, specify
5057 To have the server choose a free port number to listen on, specify
5055 a port number of 0; in this case, the server will print the port
5058 a port number of 0; in this case, the server will print the port
5056 number it uses.
5059 number it uses.
5057
5060
5058 Returns 0 on success.
5061 Returns 0 on success.
5059 """
5062 """
5060
5063
5061 if opts["stdio"] and opts["cmdserver"]:
5064 if opts["stdio"] and opts["cmdserver"]:
5062 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5065 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5063
5066
5064 def checkrepo():
5067 def checkrepo():
5065 if repo is None:
5068 if repo is None:
5066 raise error.RepoError(_("there is no Mercurial repository here"
5069 raise error.RepoError(_("there is no Mercurial repository here"
5067 " (.hg not found)"))
5070 " (.hg not found)"))
5068
5071
5069 if opts["stdio"]:
5072 if opts["stdio"]:
5070 checkrepo()
5073 checkrepo()
5071 s = sshserver.sshserver(ui, repo)
5074 s = sshserver.sshserver(ui, repo)
5072 s.serve_forever()
5075 s.serve_forever()
5073
5076
5074 if opts["cmdserver"]:
5077 if opts["cmdserver"]:
5075 checkrepo()
5078 checkrepo()
5076 s = commandserver.server(ui, repo, opts["cmdserver"])
5079 s = commandserver.server(ui, repo, opts["cmdserver"])
5077 return s.serve()
5080 return s.serve()
5078
5081
5079 # this way we can check if something was given in the command-line
5082 # this way we can check if something was given in the command-line
5080 if opts.get('port'):
5083 if opts.get('port'):
5081 opts['port'] = util.getport(opts.get('port'))
5084 opts['port'] = util.getport(opts.get('port'))
5082
5085
5083 baseui = repo and repo.baseui or ui
5086 baseui = repo and repo.baseui or ui
5084 optlist = ("name templates style address port prefix ipv6"
5087 optlist = ("name templates style address port prefix ipv6"
5085 " accesslog errorlog certificate encoding")
5088 " accesslog errorlog certificate encoding")
5086 for o in optlist.split():
5089 for o in optlist.split():
5087 val = opts.get(o, '')
5090 val = opts.get(o, '')
5088 if val in (None, ''): # should check against default options instead
5091 if val in (None, ''): # should check against default options instead
5089 continue
5092 continue
5090 baseui.setconfig("web", o, val)
5093 baseui.setconfig("web", o, val)
5091 if repo and repo.ui != baseui:
5094 if repo and repo.ui != baseui:
5092 repo.ui.setconfig("web", o, val)
5095 repo.ui.setconfig("web", o, val)
5093
5096
5094 o = opts.get('web_conf') or opts.get('webdir_conf')
5097 o = opts.get('web_conf') or opts.get('webdir_conf')
5095 if not o:
5098 if not o:
5096 if not repo:
5099 if not repo:
5097 raise error.RepoError(_("there is no Mercurial repository"
5100 raise error.RepoError(_("there is no Mercurial repository"
5098 " here (.hg not found)"))
5101 " here (.hg not found)"))
5099 o = repo
5102 o = repo
5100
5103
5101 app = hgweb.hgweb(o, baseui=baseui)
5104 app = hgweb.hgweb(o, baseui=baseui)
5102
5105
5103 class service(object):
5106 class service(object):
5104 def init(self):
5107 def init(self):
5105 util.setsignalhandler()
5108 util.setsignalhandler()
5106 self.httpd = hgweb.server.create_server(ui, app)
5109 self.httpd = hgweb.server.create_server(ui, app)
5107
5110
5108 if opts['port'] and not ui.verbose:
5111 if opts['port'] and not ui.verbose:
5109 return
5112 return
5110
5113
5111 if self.httpd.prefix:
5114 if self.httpd.prefix:
5112 prefix = self.httpd.prefix.strip('/') + '/'
5115 prefix = self.httpd.prefix.strip('/') + '/'
5113 else:
5116 else:
5114 prefix = ''
5117 prefix = ''
5115
5118
5116 port = ':%d' % self.httpd.port
5119 port = ':%d' % self.httpd.port
5117 if port == ':80':
5120 if port == ':80':
5118 port = ''
5121 port = ''
5119
5122
5120 bindaddr = self.httpd.addr
5123 bindaddr = self.httpd.addr
5121 if bindaddr == '0.0.0.0':
5124 if bindaddr == '0.0.0.0':
5122 bindaddr = '*'
5125 bindaddr = '*'
5123 elif ':' in bindaddr: # IPv6
5126 elif ':' in bindaddr: # IPv6
5124 bindaddr = '[%s]' % bindaddr
5127 bindaddr = '[%s]' % bindaddr
5125
5128
5126 fqaddr = self.httpd.fqaddr
5129 fqaddr = self.httpd.fqaddr
5127 if ':' in fqaddr:
5130 if ':' in fqaddr:
5128 fqaddr = '[%s]' % fqaddr
5131 fqaddr = '[%s]' % fqaddr
5129 if opts['port']:
5132 if opts['port']:
5130 write = ui.status
5133 write = ui.status
5131 else:
5134 else:
5132 write = ui.write
5135 write = ui.write
5133 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5136 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5134 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5137 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5135
5138
5136 def run(self):
5139 def run(self):
5137 self.httpd.serve_forever()
5140 self.httpd.serve_forever()
5138
5141
5139 service = service()
5142 service = service()
5140
5143
5141 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5144 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5142
5145
5143 @command('showconfig|debugconfig',
5146 @command('showconfig|debugconfig',
5144 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5147 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5145 _('[-u] [NAME]...'))
5148 _('[-u] [NAME]...'))
5146 def showconfig(ui, repo, *values, **opts):
5149 def showconfig(ui, repo, *values, **opts):
5147 """show combined config settings from all hgrc files
5150 """show combined config settings from all hgrc files
5148
5151
5149 With no arguments, print names and values of all config items.
5152 With no arguments, print names and values of all config items.
5150
5153
5151 With one argument of the form section.name, print just the value
5154 With one argument of the form section.name, print just the value
5152 of that config item.
5155 of that config item.
5153
5156
5154 With multiple arguments, print names and values of all config
5157 With multiple arguments, print names and values of all config
5155 items with matching section names.
5158 items with matching section names.
5156
5159
5157 With --debug, the source (filename and line number) is printed
5160 With --debug, the source (filename and line number) is printed
5158 for each config item.
5161 for each config item.
5159
5162
5160 Returns 0 on success.
5163 Returns 0 on success.
5161 """
5164 """
5162
5165
5163 for f in scmutil.rcpath():
5166 for f in scmutil.rcpath():
5164 ui.debug('read config from: %s\n' % f)
5167 ui.debug('read config from: %s\n' % f)
5165 untrusted = bool(opts.get('untrusted'))
5168 untrusted = bool(opts.get('untrusted'))
5166 if values:
5169 if values:
5167 sections = [v for v in values if '.' not in v]
5170 sections = [v for v in values if '.' not in v]
5168 items = [v for v in values if '.' in v]
5171 items = [v for v in values if '.' in v]
5169 if len(items) > 1 or items and sections:
5172 if len(items) > 1 or items and sections:
5170 raise util.Abort(_('only one config item permitted'))
5173 raise util.Abort(_('only one config item permitted'))
5171 for section, name, value in ui.walkconfig(untrusted=untrusted):
5174 for section, name, value in ui.walkconfig(untrusted=untrusted):
5172 value = str(value).replace('\n', '\\n')
5175 value = str(value).replace('\n', '\\n')
5173 sectname = section + '.' + name
5176 sectname = section + '.' + name
5174 if values:
5177 if values:
5175 for v in values:
5178 for v in values:
5176 if v == section:
5179 if v == section:
5177 ui.debug('%s: ' %
5180 ui.debug('%s: ' %
5178 ui.configsource(section, name, untrusted))
5181 ui.configsource(section, name, untrusted))
5179 ui.write('%s=%s\n' % (sectname, value))
5182 ui.write('%s=%s\n' % (sectname, value))
5180 elif v == sectname:
5183 elif v == sectname:
5181 ui.debug('%s: ' %
5184 ui.debug('%s: ' %
5182 ui.configsource(section, name, untrusted))
5185 ui.configsource(section, name, untrusted))
5183 ui.write(value, '\n')
5186 ui.write(value, '\n')
5184 else:
5187 else:
5185 ui.debug('%s: ' %
5188 ui.debug('%s: ' %
5186 ui.configsource(section, name, untrusted))
5189 ui.configsource(section, name, untrusted))
5187 ui.write('%s=%s\n' % (sectname, value))
5190 ui.write('%s=%s\n' % (sectname, value))
5188
5191
5189 @command('^status|st',
5192 @command('^status|st',
5190 [('A', 'all', None, _('show status of all files')),
5193 [('A', 'all', None, _('show status of all files')),
5191 ('m', 'modified', None, _('show only modified files')),
5194 ('m', 'modified', None, _('show only modified files')),
5192 ('a', 'added', None, _('show only added files')),
5195 ('a', 'added', None, _('show only added files')),
5193 ('r', 'removed', None, _('show only removed files')),
5196 ('r', 'removed', None, _('show only removed files')),
5194 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5197 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5195 ('c', 'clean', None, _('show only files without changes')),
5198 ('c', 'clean', None, _('show only files without changes')),
5196 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5199 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5197 ('i', 'ignored', None, _('show only ignored files')),
5200 ('i', 'ignored', None, _('show only ignored files')),
5198 ('n', 'no-status', None, _('hide status prefix')),
5201 ('n', 'no-status', None, _('hide status prefix')),
5199 ('C', 'copies', None, _('show source of copied files')),
5202 ('C', 'copies', None, _('show source of copied files')),
5200 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5203 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5201 ('', 'rev', [], _('show difference from revision'), _('REV')),
5204 ('', 'rev', [], _('show difference from revision'), _('REV')),
5202 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5205 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5203 ] + walkopts + subrepoopts,
5206 ] + walkopts + subrepoopts,
5204 _('[OPTION]... [FILE]...'))
5207 _('[OPTION]... [FILE]...'))
5205 def status(ui, repo, *pats, **opts):
5208 def status(ui, repo, *pats, **opts):
5206 """show changed files in the working directory
5209 """show changed files in the working directory
5207
5210
5208 Show status of files in the repository. If names are given, only
5211 Show status of files in the repository. If names are given, only
5209 files that match are shown. Files that are clean or ignored or
5212 files that match are shown. Files that are clean or ignored or
5210 the source of a copy/move operation, are not listed unless
5213 the source of a copy/move operation, are not listed unless
5211 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5214 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5212 Unless options described with "show only ..." are given, the
5215 Unless options described with "show only ..." are given, the
5213 options -mardu are used.
5216 options -mardu are used.
5214
5217
5215 Option -q/--quiet hides untracked (unknown and ignored) files
5218 Option -q/--quiet hides untracked (unknown and ignored) files
5216 unless explicitly requested with -u/--unknown or -i/--ignored.
5219 unless explicitly requested with -u/--unknown or -i/--ignored.
5217
5220
5218 .. note::
5221 .. note::
5219 status may appear to disagree with diff if permissions have
5222 status may appear to disagree with diff if permissions have
5220 changed or a merge has occurred. The standard diff format does
5223 changed or a merge has occurred. The standard diff format does
5221 not report permission changes and diff only reports changes
5224 not report permission changes and diff only reports changes
5222 relative to one merge parent.
5225 relative to one merge parent.
5223
5226
5224 If one revision is given, it is used as the base revision.
5227 If one revision is given, it is used as the base revision.
5225 If two revisions are given, the differences between them are
5228 If two revisions are given, the differences between them are
5226 shown. The --change option can also be used as a shortcut to list
5229 shown. The --change option can also be used as a shortcut to list
5227 the changed files of a revision from its first parent.
5230 the changed files of a revision from its first parent.
5228
5231
5229 The codes used to show the status of files are::
5232 The codes used to show the status of files are::
5230
5233
5231 M = modified
5234 M = modified
5232 A = added
5235 A = added
5233 R = removed
5236 R = removed
5234 C = clean
5237 C = clean
5235 ! = missing (deleted by non-hg command, but still tracked)
5238 ! = missing (deleted by non-hg command, but still tracked)
5236 ? = not tracked
5239 ? = not tracked
5237 I = ignored
5240 I = ignored
5238 = origin of the previous file listed as A (added)
5241 = origin of the previous file listed as A (added)
5239
5242
5240 .. container:: verbose
5243 .. container:: verbose
5241
5244
5242 Examples:
5245 Examples:
5243
5246
5244 - show changes in the working directory relative to a
5247 - show changes in the working directory relative to a
5245 changeset::
5248 changeset::
5246
5249
5247 hg status --rev 9353
5250 hg status --rev 9353
5248
5251
5249 - show all changes including copies in an existing changeset::
5252 - show all changes including copies in an existing changeset::
5250
5253
5251 hg status --copies --change 9353
5254 hg status --copies --change 9353
5252
5255
5253 - get a NUL separated list of added files, suitable for xargs::
5256 - get a NUL separated list of added files, suitable for xargs::
5254
5257
5255 hg status -an0
5258 hg status -an0
5256
5259
5257 Returns 0 on success.
5260 Returns 0 on success.
5258 """
5261 """
5259
5262
5260 revs = opts.get('rev')
5263 revs = opts.get('rev')
5261 change = opts.get('change')
5264 change = opts.get('change')
5262
5265
5263 if revs and change:
5266 if revs and change:
5264 msg = _('cannot specify --rev and --change at the same time')
5267 msg = _('cannot specify --rev and --change at the same time')
5265 raise util.Abort(msg)
5268 raise util.Abort(msg)
5266 elif change:
5269 elif change:
5267 node2 = scmutil.revsingle(repo, change, None).node()
5270 node2 = scmutil.revsingle(repo, change, None).node()
5268 node1 = repo[node2].p1().node()
5271 node1 = repo[node2].p1().node()
5269 else:
5272 else:
5270 node1, node2 = scmutil.revpair(repo, revs)
5273 node1, node2 = scmutil.revpair(repo, revs)
5271
5274
5272 cwd = (pats and repo.getcwd()) or ''
5275 cwd = (pats and repo.getcwd()) or ''
5273 end = opts.get('print0') and '\0' or '\n'
5276 end = opts.get('print0') and '\0' or '\n'
5274 copy = {}
5277 copy = {}
5275 states = 'modified added removed deleted unknown ignored clean'.split()
5278 states = 'modified added removed deleted unknown ignored clean'.split()
5276 show = [k for k in states if opts.get(k)]
5279 show = [k for k in states if opts.get(k)]
5277 if opts.get('all'):
5280 if opts.get('all'):
5278 show += ui.quiet and (states[:4] + ['clean']) or states
5281 show += ui.quiet and (states[:4] + ['clean']) or states
5279 if not show:
5282 if not show:
5280 show = ui.quiet and states[:4] or states[:5]
5283 show = ui.quiet and states[:4] or states[:5]
5281
5284
5282 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5285 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5283 'ignored' in show, 'clean' in show, 'unknown' in show,
5286 'ignored' in show, 'clean' in show, 'unknown' in show,
5284 opts.get('subrepos'))
5287 opts.get('subrepos'))
5285 changestates = zip(states, 'MAR!?IC', stat)
5288 changestates = zip(states, 'MAR!?IC', stat)
5286
5289
5287 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5290 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5288 copy = copies.pathcopies(repo[node1], repo[node2])
5291 copy = copies.pathcopies(repo[node1], repo[node2])
5289
5292
5290 fm = ui.formatter('status', opts)
5293 fm = ui.formatter('status', opts)
5291 fmt = '%s' + end
5294 fmt = '%s' + end
5292 showchar = not opts.get('no_status')
5295 showchar = not opts.get('no_status')
5293
5296
5294 for state, char, files in changestates:
5297 for state, char, files in changestates:
5295 if state in show:
5298 if state in show:
5296 label = 'status.' + state
5299 label = 'status.' + state
5297 for f in files:
5300 for f in files:
5298 fm.startitem()
5301 fm.startitem()
5299 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5302 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5300 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5303 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5301 if f in copy:
5304 if f in copy:
5302 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5305 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5303 label='status.copied')
5306 label='status.copied')
5304 fm.end()
5307 fm.end()
5305
5308
5306 @command('^summary|sum',
5309 @command('^summary|sum',
5307 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5310 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5308 def summary(ui, repo, **opts):
5311 def summary(ui, repo, **opts):
5309 """summarize working directory state
5312 """summarize working directory state
5310
5313
5311 This generates a brief summary of the working directory state,
5314 This generates a brief summary of the working directory state,
5312 including parents, branch, commit status, and available updates.
5315 including parents, branch, commit status, and available updates.
5313
5316
5314 With the --remote option, this will check the default paths for
5317 With the --remote option, this will check the default paths for
5315 incoming and outgoing changes. This can be time-consuming.
5318 incoming and outgoing changes. This can be time-consuming.
5316
5319
5317 Returns 0 on success.
5320 Returns 0 on success.
5318 """
5321 """
5319
5322
5320 ctx = repo[None]
5323 ctx = repo[None]
5321 parents = ctx.parents()
5324 parents = ctx.parents()
5322 pnode = parents[0].node()
5325 pnode = parents[0].node()
5323 marks = []
5326 marks = []
5324
5327
5325 for p in parents:
5328 for p in parents:
5326 # label with log.changeset (instead of log.parent) since this
5329 # label with log.changeset (instead of log.parent) since this
5327 # shows a working directory parent *changeset*:
5330 # shows a working directory parent *changeset*:
5328 # i18n: column positioning for "hg summary"
5331 # i18n: column positioning for "hg summary"
5329 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5332 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5330 label='log.changeset changeset.%s' % p.phasestr())
5333 label='log.changeset changeset.%s' % p.phasestr())
5331 ui.write(' '.join(p.tags()), label='log.tag')
5334 ui.write(' '.join(p.tags()), label='log.tag')
5332 if p.bookmarks():
5335 if p.bookmarks():
5333 marks.extend(p.bookmarks())
5336 marks.extend(p.bookmarks())
5334 if p.rev() == -1:
5337 if p.rev() == -1:
5335 if not len(repo):
5338 if not len(repo):
5336 ui.write(_(' (empty repository)'))
5339 ui.write(_(' (empty repository)'))
5337 else:
5340 else:
5338 ui.write(_(' (no revision checked out)'))
5341 ui.write(_(' (no revision checked out)'))
5339 ui.write('\n')
5342 ui.write('\n')
5340 if p.description():
5343 if p.description():
5341 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5344 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5342 label='log.summary')
5345 label='log.summary')
5343
5346
5344 branch = ctx.branch()
5347 branch = ctx.branch()
5345 bheads = repo.branchheads(branch)
5348 bheads = repo.branchheads(branch)
5346 # i18n: column positioning for "hg summary"
5349 # i18n: column positioning for "hg summary"
5347 m = _('branch: %s\n') % branch
5350 m = _('branch: %s\n') % branch
5348 if branch != 'default':
5351 if branch != 'default':
5349 ui.write(m, label='log.branch')
5352 ui.write(m, label='log.branch')
5350 else:
5353 else:
5351 ui.status(m, label='log.branch')
5354 ui.status(m, label='log.branch')
5352
5355
5353 if marks:
5356 if marks:
5354 current = repo._bookmarkcurrent
5357 current = repo._bookmarkcurrent
5355 # i18n: column positioning for "hg summary"
5358 # i18n: column positioning for "hg summary"
5356 ui.write(_('bookmarks:'), label='log.bookmark')
5359 ui.write(_('bookmarks:'), label='log.bookmark')
5357 if current is not None:
5360 if current is not None:
5358 if current in marks:
5361 if current in marks:
5359 ui.write(' *' + current, label='bookmarks.current')
5362 ui.write(' *' + current, label='bookmarks.current')
5360 marks.remove(current)
5363 marks.remove(current)
5361 else:
5364 else:
5362 ui.write(' [%s]' % current, label='bookmarks.current')
5365 ui.write(' [%s]' % current, label='bookmarks.current')
5363 for m in marks:
5366 for m in marks:
5364 ui.write(' ' + m, label='log.bookmark')
5367 ui.write(' ' + m, label='log.bookmark')
5365 ui.write('\n', label='log.bookmark')
5368 ui.write('\n', label='log.bookmark')
5366
5369
5367 st = list(repo.status(unknown=True))[:6]
5370 st = list(repo.status(unknown=True))[:6]
5368
5371
5369 c = repo.dirstate.copies()
5372 c = repo.dirstate.copies()
5370 copied, renamed = [], []
5373 copied, renamed = [], []
5371 for d, s in c.iteritems():
5374 for d, s in c.iteritems():
5372 if s in st[2]:
5375 if s in st[2]:
5373 st[2].remove(s)
5376 st[2].remove(s)
5374 renamed.append(d)
5377 renamed.append(d)
5375 else:
5378 else:
5376 copied.append(d)
5379 copied.append(d)
5377 if d in st[1]:
5380 if d in st[1]:
5378 st[1].remove(d)
5381 st[1].remove(d)
5379 st.insert(3, renamed)
5382 st.insert(3, renamed)
5380 st.insert(4, copied)
5383 st.insert(4, copied)
5381
5384
5382 ms = mergemod.mergestate(repo)
5385 ms = mergemod.mergestate(repo)
5383 st.append([f for f in ms if ms[f] == 'u'])
5386 st.append([f for f in ms if ms[f] == 'u'])
5384
5387
5385 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5388 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5386 st.append(subs)
5389 st.append(subs)
5387
5390
5388 labels = [ui.label(_('%d modified'), 'status.modified'),
5391 labels = [ui.label(_('%d modified'), 'status.modified'),
5389 ui.label(_('%d added'), 'status.added'),
5392 ui.label(_('%d added'), 'status.added'),
5390 ui.label(_('%d removed'), 'status.removed'),
5393 ui.label(_('%d removed'), 'status.removed'),
5391 ui.label(_('%d renamed'), 'status.copied'),
5394 ui.label(_('%d renamed'), 'status.copied'),
5392 ui.label(_('%d copied'), 'status.copied'),
5395 ui.label(_('%d copied'), 'status.copied'),
5393 ui.label(_('%d deleted'), 'status.deleted'),
5396 ui.label(_('%d deleted'), 'status.deleted'),
5394 ui.label(_('%d unknown'), 'status.unknown'),
5397 ui.label(_('%d unknown'), 'status.unknown'),
5395 ui.label(_('%d ignored'), 'status.ignored'),
5398 ui.label(_('%d ignored'), 'status.ignored'),
5396 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5399 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5397 ui.label(_('%d subrepos'), 'status.modified')]
5400 ui.label(_('%d subrepos'), 'status.modified')]
5398 t = []
5401 t = []
5399 for s, l in zip(st, labels):
5402 for s, l in zip(st, labels):
5400 if s:
5403 if s:
5401 t.append(l % len(s))
5404 t.append(l % len(s))
5402
5405
5403 t = ', '.join(t)
5406 t = ', '.join(t)
5404 cleanworkdir = False
5407 cleanworkdir = False
5405
5408
5406 if len(parents) > 1:
5409 if len(parents) > 1:
5407 t += _(' (merge)')
5410 t += _(' (merge)')
5408 elif branch != parents[0].branch():
5411 elif branch != parents[0].branch():
5409 t += _(' (new branch)')
5412 t += _(' (new branch)')
5410 elif (parents[0].closesbranch() and
5413 elif (parents[0].closesbranch() and
5411 pnode in repo.branchheads(branch, closed=True)):
5414 pnode in repo.branchheads(branch, closed=True)):
5412 t += _(' (head closed)')
5415 t += _(' (head closed)')
5413 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5416 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5414 t += _(' (clean)')
5417 t += _(' (clean)')
5415 cleanworkdir = True
5418 cleanworkdir = True
5416 elif pnode not in bheads:
5419 elif pnode not in bheads:
5417 t += _(' (new branch head)')
5420 t += _(' (new branch head)')
5418
5421
5419 if cleanworkdir:
5422 if cleanworkdir:
5420 # i18n: column positioning for "hg summary"
5423 # i18n: column positioning for "hg summary"
5421 ui.status(_('commit: %s\n') % t.strip())
5424 ui.status(_('commit: %s\n') % t.strip())
5422 else:
5425 else:
5423 # i18n: column positioning for "hg summary"
5426 # i18n: column positioning for "hg summary"
5424 ui.write(_('commit: %s\n') % t.strip())
5427 ui.write(_('commit: %s\n') % t.strip())
5425
5428
5426 # all ancestors of branch heads - all ancestors of parent = new csets
5429 # all ancestors of branch heads - all ancestors of parent = new csets
5427 new = [0] * len(repo)
5430 new = [0] * len(repo)
5428 cl = repo.changelog
5431 cl = repo.changelog
5429 for a in [cl.rev(n) for n in bheads]:
5432 for a in [cl.rev(n) for n in bheads]:
5430 new[a] = 1
5433 new[a] = 1
5431 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5434 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5432 new[a] = 1
5435 new[a] = 1
5433 for a in [p.rev() for p in parents]:
5436 for a in [p.rev() for p in parents]:
5434 if a >= 0:
5437 if a >= 0:
5435 new[a] = 0
5438 new[a] = 0
5436 for a in cl.ancestors([p.rev() for p in parents]):
5439 for a in cl.ancestors([p.rev() for p in parents]):
5437 new[a] = 0
5440 new[a] = 0
5438 new = sum(new)
5441 new = sum(new)
5439
5442
5440 if new == 0:
5443 if new == 0:
5441 # i18n: column positioning for "hg summary"
5444 # i18n: column positioning for "hg summary"
5442 ui.status(_('update: (current)\n'))
5445 ui.status(_('update: (current)\n'))
5443 elif pnode not in bheads:
5446 elif pnode not in bheads:
5444 # i18n: column positioning for "hg summary"
5447 # i18n: column positioning for "hg summary"
5445 ui.write(_('update: %d new changesets (update)\n') % new)
5448 ui.write(_('update: %d new changesets (update)\n') % new)
5446 else:
5449 else:
5447 # i18n: column positioning for "hg summary"
5450 # i18n: column positioning for "hg summary"
5448 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5451 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5449 (new, len(bheads)))
5452 (new, len(bheads)))
5450
5453
5451 if opts.get('remote'):
5454 if opts.get('remote'):
5452 t = []
5455 t = []
5453 source, branches = hg.parseurl(ui.expandpath('default'))
5456 source, branches = hg.parseurl(ui.expandpath('default'))
5454 other = hg.peer(repo, {}, source)
5457 other = hg.peer(repo, {}, source)
5455 revs, checkout = hg.addbranchrevs(repo, other, branches,
5458 revs, checkout = hg.addbranchrevs(repo, other, branches,
5456 opts.get('rev'))
5459 opts.get('rev'))
5457 ui.debug('comparing with %s\n' % util.hidepassword(source))
5460 ui.debug('comparing with %s\n' % util.hidepassword(source))
5458 repo.ui.pushbuffer()
5461 repo.ui.pushbuffer()
5459 commoninc = discovery.findcommonincoming(repo, other)
5462 commoninc = discovery.findcommonincoming(repo, other)
5460 _common, incoming, _rheads = commoninc
5463 _common, incoming, _rheads = commoninc
5461 repo.ui.popbuffer()
5464 repo.ui.popbuffer()
5462 if incoming:
5465 if incoming:
5463 t.append(_('1 or more incoming'))
5466 t.append(_('1 or more incoming'))
5464
5467
5465 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5468 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5466 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5469 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5467 if source != dest:
5470 if source != dest:
5468 other = hg.peer(repo, {}, dest)
5471 other = hg.peer(repo, {}, dest)
5469 commoninc = None
5472 commoninc = None
5470 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5473 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5471 repo.ui.pushbuffer()
5474 repo.ui.pushbuffer()
5472 outgoing = discovery.findcommonoutgoing(repo, other,
5475 outgoing = discovery.findcommonoutgoing(repo, other,
5473 commoninc=commoninc)
5476 commoninc=commoninc)
5474 repo.ui.popbuffer()
5477 repo.ui.popbuffer()
5475 o = outgoing.missing
5478 o = outgoing.missing
5476 if o:
5479 if o:
5477 t.append(_('%d outgoing') % len(o))
5480 t.append(_('%d outgoing') % len(o))
5478 if 'bookmarks' in other.listkeys('namespaces'):
5481 if 'bookmarks' in other.listkeys('namespaces'):
5479 lmarks = repo.listkeys('bookmarks')
5482 lmarks = repo.listkeys('bookmarks')
5480 rmarks = other.listkeys('bookmarks')
5483 rmarks = other.listkeys('bookmarks')
5481 diff = set(rmarks) - set(lmarks)
5484 diff = set(rmarks) - set(lmarks)
5482 if len(diff) > 0:
5485 if len(diff) > 0:
5483 t.append(_('%d incoming bookmarks') % len(diff))
5486 t.append(_('%d incoming bookmarks') % len(diff))
5484 diff = set(lmarks) - set(rmarks)
5487 diff = set(lmarks) - set(rmarks)
5485 if len(diff) > 0:
5488 if len(diff) > 0:
5486 t.append(_('%d outgoing bookmarks') % len(diff))
5489 t.append(_('%d outgoing bookmarks') % len(diff))
5487
5490
5488 if t:
5491 if t:
5489 # i18n: column positioning for "hg summary"
5492 # i18n: column positioning for "hg summary"
5490 ui.write(_('remote: %s\n') % (', '.join(t)))
5493 ui.write(_('remote: %s\n') % (', '.join(t)))
5491 else:
5494 else:
5492 # i18n: column positioning for "hg summary"
5495 # i18n: column positioning for "hg summary"
5493 ui.status(_('remote: (synced)\n'))
5496 ui.status(_('remote: (synced)\n'))
5494
5497
5495 @command('tag',
5498 @command('tag',
5496 [('f', 'force', None, _('force tag')),
5499 [('f', 'force', None, _('force tag')),
5497 ('l', 'local', None, _('make the tag local')),
5500 ('l', 'local', None, _('make the tag local')),
5498 ('r', 'rev', '', _('revision to tag'), _('REV')),
5501 ('r', 'rev', '', _('revision to tag'), _('REV')),
5499 ('', 'remove', None, _('remove a tag')),
5502 ('', 'remove', None, _('remove a tag')),
5500 # -l/--local is already there, commitopts cannot be used
5503 # -l/--local is already there, commitopts cannot be used
5501 ('e', 'edit', None, _('edit commit message')),
5504 ('e', 'edit', None, _('edit commit message')),
5502 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5505 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5503 ] + commitopts2,
5506 ] + commitopts2,
5504 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5507 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5505 def tag(ui, repo, name1, *names, **opts):
5508 def tag(ui, repo, name1, *names, **opts):
5506 """add one or more tags for the current or given revision
5509 """add one or more tags for the current or given revision
5507
5510
5508 Name a particular revision using <name>.
5511 Name a particular revision using <name>.
5509
5512
5510 Tags are used to name particular revisions of the repository and are
5513 Tags are used to name particular revisions of the repository and are
5511 very useful to compare different revisions, to go back to significant
5514 very useful to compare different revisions, to go back to significant
5512 earlier versions or to mark branch points as releases, etc. Changing
5515 earlier versions or to mark branch points as releases, etc. Changing
5513 an existing tag is normally disallowed; use -f/--force to override.
5516 an existing tag is normally disallowed; use -f/--force to override.
5514
5517
5515 If no revision is given, the parent of the working directory is
5518 If no revision is given, the parent of the working directory is
5516 used, or tip if no revision is checked out.
5519 used, or tip if no revision is checked out.
5517
5520
5518 To facilitate version control, distribution, and merging of tags,
5521 To facilitate version control, distribution, and merging of tags,
5519 they are stored as a file named ".hgtags" which is managed similarly
5522 they are stored as a file named ".hgtags" which is managed similarly
5520 to other project files and can be hand-edited if necessary. This
5523 to other project files and can be hand-edited if necessary. This
5521 also means that tagging creates a new commit. The file
5524 also means that tagging creates a new commit. The file
5522 ".hg/localtags" is used for local tags (not shared among
5525 ".hg/localtags" is used for local tags (not shared among
5523 repositories).
5526 repositories).
5524
5527
5525 Tag commits are usually made at the head of a branch. If the parent
5528 Tag commits are usually made at the head of a branch. If the parent
5526 of the working directory is not a branch head, :hg:`tag` aborts; use
5529 of the working directory is not a branch head, :hg:`tag` aborts; use
5527 -f/--force to force the tag commit to be based on a non-head
5530 -f/--force to force the tag commit to be based on a non-head
5528 changeset.
5531 changeset.
5529
5532
5530 See :hg:`help dates` for a list of formats valid for -d/--date.
5533 See :hg:`help dates` for a list of formats valid for -d/--date.
5531
5534
5532 Since tag names have priority over branch names during revision
5535 Since tag names have priority over branch names during revision
5533 lookup, using an existing branch name as a tag name is discouraged.
5536 lookup, using an existing branch name as a tag name is discouraged.
5534
5537
5535 Returns 0 on success.
5538 Returns 0 on success.
5536 """
5539 """
5537 wlock = lock = None
5540 wlock = lock = None
5538 try:
5541 try:
5539 wlock = repo.wlock()
5542 wlock = repo.wlock()
5540 lock = repo.lock()
5543 lock = repo.lock()
5541 rev_ = "."
5544 rev_ = "."
5542 names = [t.strip() for t in (name1,) + names]
5545 names = [t.strip() for t in (name1,) + names]
5543 if len(names) != len(set(names)):
5546 if len(names) != len(set(names)):
5544 raise util.Abort(_('tag names must be unique'))
5547 raise util.Abort(_('tag names must be unique'))
5545 for n in names:
5548 for n in names:
5546 scmutil.checknewlabel(repo, n, 'tag')
5549 scmutil.checknewlabel(repo, n, 'tag')
5547 if not n:
5550 if not n:
5548 raise util.Abort(_('tag names cannot consist entirely of '
5551 raise util.Abort(_('tag names cannot consist entirely of '
5549 'whitespace'))
5552 'whitespace'))
5550 if opts.get('rev') and opts.get('remove'):
5553 if opts.get('rev') and opts.get('remove'):
5551 raise util.Abort(_("--rev and --remove are incompatible"))
5554 raise util.Abort(_("--rev and --remove are incompatible"))
5552 if opts.get('rev'):
5555 if opts.get('rev'):
5553 rev_ = opts['rev']
5556 rev_ = opts['rev']
5554 message = opts.get('message')
5557 message = opts.get('message')
5555 if opts.get('remove'):
5558 if opts.get('remove'):
5556 expectedtype = opts.get('local') and 'local' or 'global'
5559 expectedtype = opts.get('local') and 'local' or 'global'
5557 for n in names:
5560 for n in names:
5558 if not repo.tagtype(n):
5561 if not repo.tagtype(n):
5559 raise util.Abort(_("tag '%s' does not exist") % n)
5562 raise util.Abort(_("tag '%s' does not exist") % n)
5560 if repo.tagtype(n) != expectedtype:
5563 if repo.tagtype(n) != expectedtype:
5561 if expectedtype == 'global':
5564 if expectedtype == 'global':
5562 raise util.Abort(_("tag '%s' is not a global tag") % n)
5565 raise util.Abort(_("tag '%s' is not a global tag") % n)
5563 else:
5566 else:
5564 raise util.Abort(_("tag '%s' is not a local tag") % n)
5567 raise util.Abort(_("tag '%s' is not a local tag") % n)
5565 rev_ = nullid
5568 rev_ = nullid
5566 if not message:
5569 if not message:
5567 # we don't translate commit messages
5570 # we don't translate commit messages
5568 message = 'Removed tag %s' % ', '.join(names)
5571 message = 'Removed tag %s' % ', '.join(names)
5569 elif not opts.get('force'):
5572 elif not opts.get('force'):
5570 for n in names:
5573 for n in names:
5571 if n in repo.tags():
5574 if n in repo.tags():
5572 raise util.Abort(_("tag '%s' already exists "
5575 raise util.Abort(_("tag '%s' already exists "
5573 "(use -f to force)") % n)
5576 "(use -f to force)") % n)
5574 if not opts.get('local'):
5577 if not opts.get('local'):
5575 p1, p2 = repo.dirstate.parents()
5578 p1, p2 = repo.dirstate.parents()
5576 if p2 != nullid:
5579 if p2 != nullid:
5577 raise util.Abort(_('uncommitted merge'))
5580 raise util.Abort(_('uncommitted merge'))
5578 bheads = repo.branchheads()
5581 bheads = repo.branchheads()
5579 if not opts.get('force') and bheads and p1 not in bheads:
5582 if not opts.get('force') and bheads and p1 not in bheads:
5580 raise util.Abort(_('not at a branch head (use -f to force)'))
5583 raise util.Abort(_('not at a branch head (use -f to force)'))
5581 r = scmutil.revsingle(repo, rev_).node()
5584 r = scmutil.revsingle(repo, rev_).node()
5582
5585
5583 if not message:
5586 if not message:
5584 # we don't translate commit messages
5587 # we don't translate commit messages
5585 message = ('Added tag %s for changeset %s' %
5588 message = ('Added tag %s for changeset %s' %
5586 (', '.join(names), short(r)))
5589 (', '.join(names), short(r)))
5587
5590
5588 date = opts.get('date')
5591 date = opts.get('date')
5589 if date:
5592 if date:
5590 date = util.parsedate(date)
5593 date = util.parsedate(date)
5591
5594
5592 if opts.get('edit'):
5595 if opts.get('edit'):
5593 message = ui.edit(message, ui.username())
5596 message = ui.edit(message, ui.username())
5594
5597
5595 # don't allow tagging the null rev
5598 # don't allow tagging the null rev
5596 if (not opts.get('remove') and
5599 if (not opts.get('remove') and
5597 scmutil.revsingle(repo, rev_).rev() == nullrev):
5600 scmutil.revsingle(repo, rev_).rev() == nullrev):
5598 raise util.Abort(_("cannot tag null revision"))
5601 raise util.Abort(_("cannot tag null revision"))
5599
5602
5600 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5603 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5601 finally:
5604 finally:
5602 release(lock, wlock)
5605 release(lock, wlock)
5603
5606
5604 @command('tags', [], '')
5607 @command('tags', [], '')
5605 def tags(ui, repo, **opts):
5608 def tags(ui, repo, **opts):
5606 """list repository tags
5609 """list repository tags
5607
5610
5608 This lists both regular and local tags. When the -v/--verbose
5611 This lists both regular and local tags. When the -v/--verbose
5609 switch is used, a third column "local" is printed for local tags.
5612 switch is used, a third column "local" is printed for local tags.
5610
5613
5611 Returns 0 on success.
5614 Returns 0 on success.
5612 """
5615 """
5613
5616
5614 fm = ui.formatter('tags', opts)
5617 fm = ui.formatter('tags', opts)
5615 hexfunc = ui.debugflag and hex or short
5618 hexfunc = ui.debugflag and hex or short
5616 tagtype = ""
5619 tagtype = ""
5617
5620
5618 for t, n in reversed(repo.tagslist()):
5621 for t, n in reversed(repo.tagslist()):
5619 hn = hexfunc(n)
5622 hn = hexfunc(n)
5620 label = 'tags.normal'
5623 label = 'tags.normal'
5621 tagtype = ''
5624 tagtype = ''
5622 if repo.tagtype(t) == 'local':
5625 if repo.tagtype(t) == 'local':
5623 label = 'tags.local'
5626 label = 'tags.local'
5624 tagtype = 'local'
5627 tagtype = 'local'
5625
5628
5626 fm.startitem()
5629 fm.startitem()
5627 fm.write('tag', '%s', t, label=label)
5630 fm.write('tag', '%s', t, label=label)
5628 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5631 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5629 fm.condwrite(not ui.quiet, 'rev id', fmt,
5632 fm.condwrite(not ui.quiet, 'rev id', fmt,
5630 repo.changelog.rev(n), hn, label=label)
5633 repo.changelog.rev(n), hn, label=label)
5631 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5634 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5632 tagtype, label=label)
5635 tagtype, label=label)
5633 fm.plain('\n')
5636 fm.plain('\n')
5634 fm.end()
5637 fm.end()
5635
5638
5636 @command('tip',
5639 @command('tip',
5637 [('p', 'patch', None, _('show patch')),
5640 [('p', 'patch', None, _('show patch')),
5638 ('g', 'git', None, _('use git extended diff format')),
5641 ('g', 'git', None, _('use git extended diff format')),
5639 ] + templateopts,
5642 ] + templateopts,
5640 _('[-p] [-g]'))
5643 _('[-p] [-g]'))
5641 def tip(ui, repo, **opts):
5644 def tip(ui, repo, **opts):
5642 """show the tip revision
5645 """show the tip revision
5643
5646
5644 The tip revision (usually just called the tip) is the changeset
5647 The tip revision (usually just called the tip) is the changeset
5645 most recently added to the repository (and therefore the most
5648 most recently added to the repository (and therefore the most
5646 recently changed head).
5649 recently changed head).
5647
5650
5648 If you have just made a commit, that commit will be the tip. If
5651 If you have just made a commit, that commit will be the tip. If
5649 you have just pulled changes from another repository, the tip of
5652 you have just pulled changes from another repository, the tip of
5650 that repository becomes the current tip. The "tip" tag is special
5653 that repository becomes the current tip. The "tip" tag is special
5651 and cannot be renamed or assigned to a different changeset.
5654 and cannot be renamed or assigned to a different changeset.
5652
5655
5653 Returns 0 on success.
5656 Returns 0 on success.
5654 """
5657 """
5655 displayer = cmdutil.show_changeset(ui, repo, opts)
5658 displayer = cmdutil.show_changeset(ui, repo, opts)
5656 displayer.show(repo['tip'])
5659 displayer.show(repo['tip'])
5657 displayer.close()
5660 displayer.close()
5658
5661
5659 @command('unbundle',
5662 @command('unbundle',
5660 [('u', 'update', None,
5663 [('u', 'update', None,
5661 _('update to new branch head if changesets were unbundled'))],
5664 _('update to new branch head if changesets were unbundled'))],
5662 _('[-u] FILE...'))
5665 _('[-u] FILE...'))
5663 def unbundle(ui, repo, fname1, *fnames, **opts):
5666 def unbundle(ui, repo, fname1, *fnames, **opts):
5664 """apply one or more changegroup files
5667 """apply one or more changegroup files
5665
5668
5666 Apply one or more compressed changegroup files generated by the
5669 Apply one or more compressed changegroup files generated by the
5667 bundle command.
5670 bundle command.
5668
5671
5669 Returns 0 on success, 1 if an update has unresolved files.
5672 Returns 0 on success, 1 if an update has unresolved files.
5670 """
5673 """
5671 fnames = (fname1,) + fnames
5674 fnames = (fname1,) + fnames
5672
5675
5673 lock = repo.lock()
5676 lock = repo.lock()
5674 wc = repo['.']
5677 wc = repo['.']
5675 try:
5678 try:
5676 for fname in fnames:
5679 for fname in fnames:
5677 f = hg.openpath(ui, fname)
5680 f = hg.openpath(ui, fname)
5678 gen = changegroup.readbundle(f, fname)
5681 gen = changegroup.readbundle(f, fname)
5679 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5682 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5680 finally:
5683 finally:
5681 lock.release()
5684 lock.release()
5682 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5685 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5683 return postincoming(ui, repo, modheads, opts.get('update'), None)
5686 return postincoming(ui, repo, modheads, opts.get('update'), None)
5684
5687
5685 @command('^update|up|checkout|co',
5688 @command('^update|up|checkout|co',
5686 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5689 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5687 ('c', 'check', None,
5690 ('c', 'check', None,
5688 _('update across branches if no uncommitted changes')),
5691 _('update across branches if no uncommitted changes')),
5689 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5692 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5690 ('r', 'rev', '', _('revision'), _('REV'))],
5693 ('r', 'rev', '', _('revision'), _('REV'))],
5691 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5694 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5692 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5695 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5693 """update working directory (or switch revisions)
5696 """update working directory (or switch revisions)
5694
5697
5695 Update the repository's working directory to the specified
5698 Update the repository's working directory to the specified
5696 changeset. If no changeset is specified, update to the tip of the
5699 changeset. If no changeset is specified, update to the tip of the
5697 current named branch and move the current bookmark (see :hg:`help
5700 current named branch and move the current bookmark (see :hg:`help
5698 bookmarks`).
5701 bookmarks`).
5699
5702
5700 Update sets the working directory's parent revision to the specified
5703 Update sets the working directory's parent revision to the specified
5701 changeset (see :hg:`help parents`).
5704 changeset (see :hg:`help parents`).
5702
5705
5703 If the changeset is not a descendant or ancestor of the working
5706 If the changeset is not a descendant or ancestor of the working
5704 directory's parent, the update is aborted. With the -c/--check
5707 directory's parent, the update is aborted. With the -c/--check
5705 option, the working directory is checked for uncommitted changes; if
5708 option, the working directory is checked for uncommitted changes; if
5706 none are found, the working directory is updated to the specified
5709 none are found, the working directory is updated to the specified
5707 changeset.
5710 changeset.
5708
5711
5709 .. container:: verbose
5712 .. container:: verbose
5710
5713
5711 The following rules apply when the working directory contains
5714 The following rules apply when the working directory contains
5712 uncommitted changes:
5715 uncommitted changes:
5713
5716
5714 1. If neither -c/--check nor -C/--clean is specified, and if
5717 1. If neither -c/--check nor -C/--clean is specified, and if
5715 the requested changeset is an ancestor or descendant of
5718 the requested changeset is an ancestor or descendant of
5716 the working directory's parent, the uncommitted changes
5719 the working directory's parent, the uncommitted changes
5717 are merged into the requested changeset and the merged
5720 are merged into the requested changeset and the merged
5718 result is left uncommitted. If the requested changeset is
5721 result is left uncommitted. If the requested changeset is
5719 not an ancestor or descendant (that is, it is on another
5722 not an ancestor or descendant (that is, it is on another
5720 branch), the update is aborted and the uncommitted changes
5723 branch), the update is aborted and the uncommitted changes
5721 are preserved.
5724 are preserved.
5722
5725
5723 2. With the -c/--check option, the update is aborted and the
5726 2. With the -c/--check option, the update is aborted and the
5724 uncommitted changes are preserved.
5727 uncommitted changes are preserved.
5725
5728
5726 3. With the -C/--clean option, uncommitted changes are discarded and
5729 3. With the -C/--clean option, uncommitted changes are discarded and
5727 the working directory is updated to the requested changeset.
5730 the working directory is updated to the requested changeset.
5728
5731
5729 To cancel an uncommitted merge (and lose your changes), use
5732 To cancel an uncommitted merge (and lose your changes), use
5730 :hg:`update --clean .`.
5733 :hg:`update --clean .`.
5731
5734
5732 Use null as the changeset to remove the working directory (like
5735 Use null as the changeset to remove the working directory (like
5733 :hg:`clone -U`).
5736 :hg:`clone -U`).
5734
5737
5735 If you want to revert just one file to an older revision, use
5738 If you want to revert just one file to an older revision, use
5736 :hg:`revert [-r REV] NAME`.
5739 :hg:`revert [-r REV] NAME`.
5737
5740
5738 See :hg:`help dates` for a list of formats valid for -d/--date.
5741 See :hg:`help dates` for a list of formats valid for -d/--date.
5739
5742
5740 Returns 0 on success, 1 if there are unresolved files.
5743 Returns 0 on success, 1 if there are unresolved files.
5741 """
5744 """
5742 if rev and node:
5745 if rev and node:
5743 raise util.Abort(_("please specify just one revision"))
5746 raise util.Abort(_("please specify just one revision"))
5744
5747
5745 if rev is None or rev == '':
5748 if rev is None or rev == '':
5746 rev = node
5749 rev = node
5747
5750
5748 # with no argument, we also move the current bookmark, if any
5751 # with no argument, we also move the current bookmark, if any
5749 movemarkfrom = None
5752 movemarkfrom = None
5750 if rev is None:
5753 if rev is None:
5751 curmark = repo._bookmarkcurrent
5754 curmark = repo._bookmarkcurrent
5752 if bookmarks.iscurrent(repo):
5755 if bookmarks.iscurrent(repo):
5753 movemarkfrom = repo['.'].node()
5756 movemarkfrom = repo['.'].node()
5754 elif curmark:
5757 elif curmark:
5755 ui.status(_("updating to active bookmark %s\n") % curmark)
5758 ui.status(_("updating to active bookmark %s\n") % curmark)
5756 rev = curmark
5759 rev = curmark
5757
5760
5758 # if we defined a bookmark, we have to remember the original bookmark name
5761 # if we defined a bookmark, we have to remember the original bookmark name
5759 brev = rev
5762 brev = rev
5760 rev = scmutil.revsingle(repo, rev, rev).rev()
5763 rev = scmutil.revsingle(repo, rev, rev).rev()
5761
5764
5762 if check and clean:
5765 if check and clean:
5763 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5766 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5764
5767
5765 if date:
5768 if date:
5766 if rev is not None:
5769 if rev is not None:
5767 raise util.Abort(_("you can't specify a revision and a date"))
5770 raise util.Abort(_("you can't specify a revision and a date"))
5768 rev = cmdutil.finddate(ui, repo, date)
5771 rev = cmdutil.finddate(ui, repo, date)
5769
5772
5770 if check:
5773 if check:
5771 c = repo[None]
5774 c = repo[None]
5772 if c.dirty(merge=False, branch=False, missing=True):
5775 if c.dirty(merge=False, branch=False, missing=True):
5773 raise util.Abort(_("uncommitted local changes"))
5776 raise util.Abort(_("uncommitted local changes"))
5774 if rev is None:
5777 if rev is None:
5775 rev = repo[repo[None].branch()].rev()
5778 rev = repo[repo[None].branch()].rev()
5776 mergemod._checkunknown(repo, repo[None], repo[rev])
5779 mergemod._checkunknown(repo, repo[None], repo[rev])
5777
5780
5778 if clean:
5781 if clean:
5779 ret = hg.clean(repo, rev)
5782 ret = hg.clean(repo, rev)
5780 else:
5783 else:
5781 ret = hg.update(repo, rev)
5784 ret = hg.update(repo, rev)
5782
5785
5783 if not ret and movemarkfrom:
5786 if not ret and movemarkfrom:
5784 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5787 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5785 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5788 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5786 elif brev in repo._bookmarks:
5789 elif brev in repo._bookmarks:
5787 bookmarks.setcurrent(repo, brev)
5790 bookmarks.setcurrent(repo, brev)
5788 elif brev:
5791 elif brev:
5789 bookmarks.unsetcurrent(repo)
5792 bookmarks.unsetcurrent(repo)
5790
5793
5791 return ret
5794 return ret
5792
5795
5793 @command('verify', [])
5796 @command('verify', [])
5794 def verify(ui, repo):
5797 def verify(ui, repo):
5795 """verify the integrity of the repository
5798 """verify the integrity of the repository
5796
5799
5797 Verify the integrity of the current repository.
5800 Verify the integrity of the current repository.
5798
5801
5799 This will perform an extensive check of the repository's
5802 This will perform an extensive check of the repository's
5800 integrity, validating the hashes and checksums of each entry in
5803 integrity, validating the hashes and checksums of each entry in
5801 the changelog, manifest, and tracked files, as well as the
5804 the changelog, manifest, and tracked files, as well as the
5802 integrity of their crosslinks and indices.
5805 integrity of their crosslinks and indices.
5803
5806
5804 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5807 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5805 for more information about recovery from corruption of the
5808 for more information about recovery from corruption of the
5806 repository.
5809 repository.
5807
5810
5808 Returns 0 on success, 1 if errors are encountered.
5811 Returns 0 on success, 1 if errors are encountered.
5809 """
5812 """
5810 return hg.verify(repo)
5813 return hg.verify(repo)
5811
5814
5812 @command('version', [])
5815 @command('version', [])
5813 def version_(ui):
5816 def version_(ui):
5814 """output version and copyright information"""
5817 """output version and copyright information"""
5815 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5818 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5816 % util.version())
5819 % util.version())
5817 ui.status(_(
5820 ui.status(_(
5818 "(see http://mercurial.selenic.com for more information)\n"
5821 "(see http://mercurial.selenic.com for more information)\n"
5819 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5822 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5820 "This is free software; see the source for copying conditions. "
5823 "This is free software; see the source for copying conditions. "
5821 "There is NO\nwarranty; "
5824 "There is NO\nwarranty; "
5822 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5825 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5823 ))
5826 ))
5824
5827
5825 norepo = ("clone init version help debugcommands debugcomplete"
5828 norepo = ("clone init version help debugcommands debugcomplete"
5826 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5829 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5827 " debugknown debuggetbundle debugbundle")
5830 " debugknown debuggetbundle debugbundle")
5828 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5831 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5829 " debugdata debugindex debugindexdot debugrevlog")
5832 " debugdata debugindex debugindexdot debugrevlog")
5830 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5833 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5831 " remove resolve status debugwalk")
5834 " remove resolve status debugwalk")
@@ -1,188 +1,203 b''
1 $ hg init repo
1 $ hg init repo
2 $ cd repo
2 $ cd repo
3 $ touch foo
3 $ touch foo
4 $ hg add foo
4 $ hg add foo
5 $ for i in 0 1 2 3 4 5 6 7 8 9 10 11; do
5 $ for i in 0 1 2 3 4 5 6 7 8 9 10 11; do
6 > echo "foo-$i" >> foo
6 > echo "foo-$i" >> foo
7 > hg ci -m "foo-$i"
7 > hg ci -m "foo-$i"
8 > done
8 > done
9
9
10 $ for out in "%nof%N" "%%%H" "%b-%R" "%h" "%r" "%m"; do
10 $ for out in "%nof%N" "%%%H" "%b-%R" "%h" "%r" "%m"; do
11 > echo
11 > echo
12 > echo "# foo-$out.patch"
12 > echo "# foo-$out.patch"
13 > hg export -v -o "foo-$out.patch" 2:tip
13 > hg export -v -o "foo-$out.patch" 2:tip
14 > done
14 > done
15
15
16 # foo-%nof%N.patch
16 # foo-%nof%N.patch
17 exporting patches:
17 exporting patches:
18 foo-01of10.patch
18 foo-01of10.patch
19 foo-02of10.patch
19 foo-02of10.patch
20 foo-03of10.patch
20 foo-03of10.patch
21 foo-04of10.patch
21 foo-04of10.patch
22 foo-05of10.patch
22 foo-05of10.patch
23 foo-06of10.patch
23 foo-06of10.patch
24 foo-07of10.patch
24 foo-07of10.patch
25 foo-08of10.patch
25 foo-08of10.patch
26 foo-09of10.patch
26 foo-09of10.patch
27 foo-10of10.patch
27 foo-10of10.patch
28
28
29 # foo-%%%H.patch
29 # foo-%%%H.patch
30 exporting patches:
30 exporting patches:
31 foo-%617188a1c80f869a7b66c85134da88a6fb145f67.patch
31 foo-%617188a1c80f869a7b66c85134da88a6fb145f67.patch
32 foo-%dd41a5ff707a5225204105611ba49cc5c229d55f.patch
32 foo-%dd41a5ff707a5225204105611ba49cc5c229d55f.patch
33 foo-%f95a5410f8664b6e1490a4af654e4b7d41a7b321.patch
33 foo-%f95a5410f8664b6e1490a4af654e4b7d41a7b321.patch
34 foo-%4346bcfde53b4d9042489078bcfa9c3e28201db2.patch
34 foo-%4346bcfde53b4d9042489078bcfa9c3e28201db2.patch
35 foo-%afda8c3a009cc99449a05ad8aa4655648c4ecd34.patch
35 foo-%afda8c3a009cc99449a05ad8aa4655648c4ecd34.patch
36 foo-%35284ce2b6b99c9d2ac66268fe99e68e1974e1aa.patch
36 foo-%35284ce2b6b99c9d2ac66268fe99e68e1974e1aa.patch
37 foo-%9688c41894e6931305fa7165a37f6568050b4e9b.patch
37 foo-%9688c41894e6931305fa7165a37f6568050b4e9b.patch
38 foo-%747d3c68f8ec44bb35816bfcd59aeb50b9654c2f.patch
38 foo-%747d3c68f8ec44bb35816bfcd59aeb50b9654c2f.patch
39 foo-%5f17a83f5fbd9414006a5e563eab4c8a00729efd.patch
39 foo-%5f17a83f5fbd9414006a5e563eab4c8a00729efd.patch
40 foo-%f3acbafac161ec68f1598af38f794f28847ca5d3.patch
40 foo-%f3acbafac161ec68f1598af38f794f28847ca5d3.patch
41
41
42 # foo-%b-%R.patch
42 # foo-%b-%R.patch
43 exporting patches:
43 exporting patches:
44 foo-repo-2.patch
44 foo-repo-2.patch
45 foo-repo-3.patch
45 foo-repo-3.patch
46 foo-repo-4.patch
46 foo-repo-4.patch
47 foo-repo-5.patch
47 foo-repo-5.patch
48 foo-repo-6.patch
48 foo-repo-6.patch
49 foo-repo-7.patch
49 foo-repo-7.patch
50 foo-repo-8.patch
50 foo-repo-8.patch
51 foo-repo-9.patch
51 foo-repo-9.patch
52 foo-repo-10.patch
52 foo-repo-10.patch
53 foo-repo-11.patch
53 foo-repo-11.patch
54
54
55 # foo-%h.patch
55 # foo-%h.patch
56 exporting patches:
56 exporting patches:
57 foo-617188a1c80f.patch
57 foo-617188a1c80f.patch
58 foo-dd41a5ff707a.patch
58 foo-dd41a5ff707a.patch
59 foo-f95a5410f866.patch
59 foo-f95a5410f866.patch
60 foo-4346bcfde53b.patch
60 foo-4346bcfde53b.patch
61 foo-afda8c3a009c.patch
61 foo-afda8c3a009c.patch
62 foo-35284ce2b6b9.patch
62 foo-35284ce2b6b9.patch
63 foo-9688c41894e6.patch
63 foo-9688c41894e6.patch
64 foo-747d3c68f8ec.patch
64 foo-747d3c68f8ec.patch
65 foo-5f17a83f5fbd.patch
65 foo-5f17a83f5fbd.patch
66 foo-f3acbafac161.patch
66 foo-f3acbafac161.patch
67
67
68 # foo-%r.patch
68 # foo-%r.patch
69 exporting patches:
69 exporting patches:
70 foo-02.patch
70 foo-02.patch
71 foo-03.patch
71 foo-03.patch
72 foo-04.patch
72 foo-04.patch
73 foo-05.patch
73 foo-05.patch
74 foo-06.patch
74 foo-06.patch
75 foo-07.patch
75 foo-07.patch
76 foo-08.patch
76 foo-08.patch
77 foo-09.patch
77 foo-09.patch
78 foo-10.patch
78 foo-10.patch
79 foo-11.patch
79 foo-11.patch
80
80
81 # foo-%m.patch
81 # foo-%m.patch
82 exporting patches:
82 exporting patches:
83 foo-foo_2.patch
83 foo-foo_2.patch
84 foo-foo_3.patch
84 foo-foo_3.patch
85 foo-foo_4.patch
85 foo-foo_4.patch
86 foo-foo_5.patch
86 foo-foo_5.patch
87 foo-foo_6.patch
87 foo-foo_6.patch
88 foo-foo_7.patch
88 foo-foo_7.patch
89 foo-foo_8.patch
89 foo-foo_8.patch
90 foo-foo_9.patch
90 foo-foo_9.patch
91 foo-foo_10.patch
91 foo-foo_10.patch
92 foo-foo_11.patch
92 foo-foo_11.patch
93
93
94 Doing it again clobbers the files rather than appending:
94 Doing it again clobbers the files rather than appending:
95 $ hg export -v -o "foo-%m.patch" 2:3
95 $ hg export -v -o "foo-%m.patch" 2:3
96 exporting patches:
96 exporting patches:
97 foo-foo_2.patch
97 foo-foo_2.patch
98 foo-foo_3.patch
98 foo-foo_3.patch
99 $ grep HG foo-foo_2.patch | wc -l
99 $ grep HG foo-foo_2.patch | wc -l
100 \s*1 (re)
100 \s*1 (re)
101 $ grep HG foo-foo_3.patch | wc -l
101 $ grep HG foo-foo_3.patch | wc -l
102 \s*1 (re)
102 \s*1 (re)
103
103
104 Exporting 4 changesets to a file:
104 Exporting 4 changesets to a file:
105
105
106 $ hg export -o export_internal 1 2 3 4
106 $ hg export -o export_internal 1 2 3 4
107 $ grep HG export_internal | wc -l
107 $ grep HG export_internal | wc -l
108 \s*4 (re)
108 \s*4 (re)
109
109
110 Doing it again clobbers the file rather than appending:
110 Doing it again clobbers the file rather than appending:
111 $ hg export -o export_internal 1 2 3 4
111 $ hg export -o export_internal 1 2 3 4
112 $ grep HG export_internal | wc -l
112 $ grep HG export_internal | wc -l
113 \s*4 (re)
113 \s*4 (re)
114
114
115 Exporting 4 changesets to stdout:
115 Exporting 4 changesets to stdout:
116
116
117 $ hg export 1 2 3 4 | grep HG | wc -l
117 $ hg export 1 2 3 4 | grep HG | wc -l
118 \s*4 (re)
118 \s*4 (re)
119
119
120 Exporting revision -2 to a file:
120 Exporting revision -2 to a file:
121
121
122 $ hg export -- -2
122 $ hg export -- -2
123 # HG changeset patch
123 # HG changeset patch
124 # User test
124 # User test
125 # Date 0 0
125 # Date 0 0
126 # Thu Jan 01 00:00:00 1970 +0000
126 # Thu Jan 01 00:00:00 1970 +0000
127 # Node ID 5f17a83f5fbd9414006a5e563eab4c8a00729efd
127 # Node ID 5f17a83f5fbd9414006a5e563eab4c8a00729efd
128 # Parent 747d3c68f8ec44bb35816bfcd59aeb50b9654c2f
128 # Parent 747d3c68f8ec44bb35816bfcd59aeb50b9654c2f
129 foo-10
129 foo-10
130
130
131 diff -r 747d3c68f8ec -r 5f17a83f5fbd foo
131 diff -r 747d3c68f8ec -r 5f17a83f5fbd foo
132 --- a/foo Thu Jan 01 00:00:00 1970 +0000
132 --- a/foo Thu Jan 01 00:00:00 1970 +0000
133 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
133 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
134 @@ -8,3 +8,4 @@
134 @@ -8,3 +8,4 @@
135 foo-7
135 foo-7
136 foo-8
136 foo-8
137 foo-9
137 foo-9
138 +foo-10
138 +foo-10
139
139
140 Checking if only alphanumeric characters are used in the file name (%m option):
140 Checking if only alphanumeric characters are used in the file name (%m option):
141
141
142 $ echo "line" >> foo
142 $ echo "line" >> foo
143 $ hg commit -m " !\"#$%&(,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~"
143 $ hg commit -m " !\"#$%&(,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~"
144 $ hg export -v -o %m.patch tip
144 $ hg export -v -o %m.patch tip
145 exporting patch:
145 exporting patch:
146 ____________0123456789_______ABCDEFGHIJKLMNOPQRSTUVWXYZ______abcdefghijklmnopqrstuvwxyz____.patch
146 ____________0123456789_______ABCDEFGHIJKLMNOPQRSTUVWXYZ______abcdefghijklmnopqrstuvwxyz____.patch
147
147
148 Catch exporting unknown revisions (especially empty revsets, see issue3353)
148 Catch exporting unknown revisions (especially empty revsets, see issue3353)
149
149
150 $ hg export
150 $ hg export
151 abort: export requires at least one changeset
151 # HG changeset patch
152 [255]
152 # User test
153 # Date 0 0
154 # Thu Jan 01 00:00:00 1970 +0000
155 # Node ID 197ecd81a57f760b54f34a58817ad5b04991fa47
156 # Parent f3acbafac161ec68f1598af38f794f28847ca5d3
157 !"#$%&(,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
158
159 diff -r f3acbafac161 -r 197ecd81a57f foo
160 --- a/foo Thu Jan 01 00:00:00 1970 +0000
161 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
162 @@ -10,3 +10,4 @@
163 foo-9
164 foo-10
165 foo-11
166 +line
167
153 $ hg export ""
168 $ hg export ""
154 hg: parse error: empty query
169 hg: parse error: empty query
155 [255]
170 [255]
156 $ hg export 999
171 $ hg export 999
157 abort: unknown revision '999'!
172 abort: unknown revision '999'!
158 [255]
173 [255]
159 $ hg export "not all()"
174 $ hg export "not all()"
160 abort: export requires at least one changeset
175 abort: export requires at least one changeset
161 [255]
176 [255]
162
177
163 Check for color output
178 Check for color output
164 $ echo "[color]" >> $HGRCPATH
179 $ echo "[color]" >> $HGRCPATH
165 $ echo "mode = ansi" >> $HGRCPATH
180 $ echo "mode = ansi" >> $HGRCPATH
166 $ echo "[extensions]" >> $HGRCPATH
181 $ echo "[extensions]" >> $HGRCPATH
167 $ echo "color=" >> $HGRCPATH
182 $ echo "color=" >> $HGRCPATH
168
183
169 $ hg export --color always --nodates tip
184 $ hg export --color always --nodates tip
170 # HG changeset patch
185 # HG changeset patch
171 # User test
186 # User test
172 # Date 0 0
187 # Date 0 0
173 # Thu Jan 01 00:00:00 1970 +0000
188 # Thu Jan 01 00:00:00 1970 +0000
174 # Node ID * (glob)
189 # Node ID * (glob)
175 # Parent * (glob)
190 # Parent * (glob)
176 !"#$%&(,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
191 !"#$%&(,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
177
192
178 \x1b[0;1mdiff -r f3acbafac161 -r 197ecd81a57f foo\x1b[0m (esc)
193 \x1b[0;1mdiff -r f3acbafac161 -r 197ecd81a57f foo\x1b[0m (esc)
179 \x1b[0;31;1m--- a/foo\x1b[0m (esc)
194 \x1b[0;31;1m--- a/foo\x1b[0m (esc)
180 \x1b[0;32;1m+++ b/foo\x1b[0m (esc)
195 \x1b[0;32;1m+++ b/foo\x1b[0m (esc)
181 \x1b[0;35m@@ -10,3 +10,4 @@\x1b[0m (esc)
196 \x1b[0;35m@@ -10,3 +10,4 @@\x1b[0m (esc)
182 foo-9
197 foo-9
183 foo-10
198 foo-10
184 foo-11
199 foo-11
185 \x1b[0;32m+line\x1b[0m (esc)
200 \x1b[0;32m+line\x1b[0m (esc)
186
201
187
202
188 $ cd ..
203 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now