##// END OF EJS Templates
bundle: display info about secret changets while no sharable changeset found
Alain Leufroy <alain.leufroyATgmailMYDOTcom> -
r15991:85ec8036 stable
parent child Browse files
Show More
@@ -1,5758 +1,5762 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 _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, 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
18 import dagparser, context, simplemerge
19 import random, setdiscovery, treediscovery, dagutil
19 import random, setdiscovery, treediscovery, dagutil
20 import phases
20 import phases
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 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ] + templateopts
101 ] + templateopts
102
102
103 diffopts = [
103 diffopts = [
104 ('a', 'text', None, _('treat all files as text')),
104 ('a', 'text', None, _('treat all files as text')),
105 ('g', 'git', None, _('use git extended diff format')),
105 ('g', 'git', None, _('use git extended diff format')),
106 ('', 'nodates', None, _('omit dates from diff headers'))
106 ('', 'nodates', None, _('omit dates from diff headers'))
107 ]
107 ]
108
108
109 diffwsopts = [
109 diffwsopts = [
110 ('w', 'ignore-all-space', None,
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
115 _('ignore changes whose lines are all blank')),
116 ]
116 ]
117
117
118 diffopts2 = [
118 diffopts2 = [
119 ('p', 'show-function', None, _('show which function each change is in')),
119 ('p', 'show-function', None, _('show which function each change is in')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ] + diffwsopts + [
121 ] + diffwsopts + [
122 ('U', 'unified', '',
122 ('U', 'unified', '',
123 _('number of lines of context to show'), _('NUM')),
123 _('number of lines of context to show'), _('NUM')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ]
125 ]
126
126
127 mergetoolopts = [
127 mergetoolopts = [
128 ('t', 'tool', '', _('specify merge tool')),
128 ('t', 'tool', '', _('specify merge tool')),
129 ]
129 ]
130
130
131 similarityopts = [
131 similarityopts = [
132 ('s', 'similarity', '',
132 ('s', 'similarity', '',
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 ]
134 ]
135
135
136 subrepoopts = [
136 subrepoopts = [
137 ('S', 'subrepos', None,
137 ('S', 'subrepos', None,
138 _('recurse into subrepositories'))
138 _('recurse into subrepositories'))
139 ]
139 ]
140
140
141 # Commands start here, listed alphabetically
141 # Commands start here, listed alphabetically
142
142
143 @command('^add',
143 @command('^add',
144 walkopts + subrepoopts + dryrunopts,
144 walkopts + subrepoopts + dryrunopts,
145 _('[OPTION]... [FILE]...'))
145 _('[OPTION]... [FILE]...'))
146 def add(ui, repo, *pats, **opts):
146 def add(ui, repo, *pats, **opts):
147 """add the specified files on the next commit
147 """add the specified files on the next commit
148
148
149 Schedule files to be version controlled and added to the
149 Schedule files to be version controlled and added to the
150 repository.
150 repository.
151
151
152 The files will be added to the repository at the next commit. To
152 The files will be added to the repository at the next commit. To
153 undo an add before that, see :hg:`forget`.
153 undo an add before that, see :hg:`forget`.
154
154
155 If no names are given, add all files to the repository.
155 If no names are given, add all files to the repository.
156
156
157 .. container:: verbose
157 .. container:: verbose
158
158
159 An example showing how new (unknown) files are added
159 An example showing how new (unknown) files are added
160 automatically by :hg:`add`::
160 automatically by :hg:`add`::
161
161
162 $ ls
162 $ ls
163 foo.c
163 foo.c
164 $ hg status
164 $ hg status
165 ? foo.c
165 ? foo.c
166 $ hg add
166 $ hg add
167 adding foo.c
167 adding foo.c
168 $ hg status
168 $ hg status
169 A foo.c
169 A foo.c
170
170
171 Returns 0 if all files are successfully added.
171 Returns 0 if all files are successfully added.
172 """
172 """
173
173
174 m = scmutil.match(repo[None], pats, opts)
174 m = scmutil.match(repo[None], pats, opts)
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 opts.get('subrepos'), prefix="", explicitonly=False)
176 opts.get('subrepos'), prefix="", explicitonly=False)
177 return rejected and 1 or 0
177 return rejected and 1 or 0
178
178
179 @command('addremove',
179 @command('addremove',
180 similarityopts + walkopts + dryrunopts,
180 similarityopts + walkopts + dryrunopts,
181 _('[OPTION]... [FILE]...'))
181 _('[OPTION]... [FILE]...'))
182 def addremove(ui, repo, *pats, **opts):
182 def addremove(ui, repo, *pats, **opts):
183 """add all new files, delete all missing files
183 """add all new files, delete all missing files
184
184
185 Add all new files and remove all missing files from the
185 Add all new files and remove all missing files from the
186 repository.
186 repository.
187
187
188 New files are ignored if they match any of the patterns in
188 New files are ignored if they match any of the patterns in
189 ``.hgignore``. As with add, these changes take effect at the next
189 ``.hgignore``. As with add, these changes take effect at the next
190 commit.
190 commit.
191
191
192 Use the -s/--similarity option to detect renamed files. With a
192 Use the -s/--similarity option to detect renamed files. With a
193 parameter greater than 0, this compares every removed file with
193 parameter greater than 0, this compares every removed file with
194 every added file and records those similar enough as renames. This
194 every added file and records those similar enough as renames. 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. Detecting renamed files this way
196 be identical) as its parameter. Detecting renamed files this way
197 can be expensive. After using this option, :hg:`status -C` can be
197 can be expensive. After using this option, :hg:`status -C` can be
198 used to check which files were identified as moved or renamed.
198 used to check which files were identified as moved or renamed.
199
199
200 Returns 0 if all files are successfully added.
200 Returns 0 if all files are successfully added.
201 """
201 """
202 try:
202 try:
203 sim = float(opts.get('similarity') or 100)
203 sim = float(opts.get('similarity') or 100)
204 except ValueError:
204 except ValueError:
205 raise util.Abort(_('similarity must be a number'))
205 raise util.Abort(_('similarity must be a number'))
206 if sim < 0 or sim > 100:
206 if sim < 0 or sim > 100:
207 raise util.Abort(_('similarity must be between 0 and 100'))
207 raise util.Abort(_('similarity must be between 0 and 100'))
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
209
209
210 @command('^annotate|blame',
210 @command('^annotate|blame',
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
212 ('', 'follow', None,
212 ('', 'follow', None,
213 _('follow copies/renames and list the filename (DEPRECATED)')),
213 _('follow copies/renames and list the filename (DEPRECATED)')),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
215 ('a', 'text', None, _('treat all files as text')),
215 ('a', 'text', None, _('treat all files as text')),
216 ('u', 'user', None, _('list the author (long with -v)')),
216 ('u', 'user', None, _('list the author (long with -v)')),
217 ('f', 'file', None, _('list the filename')),
217 ('f', 'file', None, _('list the filename')),
218 ('d', 'date', None, _('list the date (short with -q)')),
218 ('d', 'date', None, _('list the date (short with -q)')),
219 ('n', 'number', None, _('list the revision number (default)')),
219 ('n', 'number', None, _('list the revision number (default)')),
220 ('c', 'changeset', None, _('list the changeset')),
220 ('c', 'changeset', None, _('list the changeset')),
221 ('l', 'line-number', None, _('show line number at the first appearance'))
221 ('l', 'line-number', None, _('show line number at the first appearance'))
222 ] + diffwsopts + walkopts,
222 ] + diffwsopts + walkopts,
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
224 def annotate(ui, repo, *pats, **opts):
224 def annotate(ui, repo, *pats, **opts):
225 """show changeset information by line for each file
225 """show changeset information by line for each file
226
226
227 List changes in files, showing the revision id responsible for
227 List changes in files, showing the revision id responsible for
228 each line
228 each line
229
229
230 This command is useful for discovering when a change was made and
230 This command is useful for discovering when a change was made and
231 by whom.
231 by whom.
232
232
233 Without the -a/--text option, annotate will avoid processing files
233 Without the -a/--text option, annotate will avoid processing files
234 it detects as binary. With -a, annotate will annotate the file
234 it detects as binary. With -a, annotate will annotate the file
235 anyway, although the results will probably be neither useful
235 anyway, although the results will probably be neither useful
236 nor desirable.
236 nor desirable.
237
237
238 Returns 0 on success.
238 Returns 0 on success.
239 """
239 """
240 if opts.get('follow'):
240 if opts.get('follow'):
241 # --follow is deprecated and now just an alias for -f/--file
241 # --follow is deprecated and now just an alias for -f/--file
242 # to mimic the behavior of Mercurial before version 1.5
242 # to mimic the behavior of Mercurial before version 1.5
243 opts['file'] = True
243 opts['file'] = True
244
244
245 datefunc = ui.quiet and util.shortdate or util.datestr
245 datefunc = ui.quiet and util.shortdate or util.datestr
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
247
247
248 if not pats:
248 if not pats:
249 raise util.Abort(_('at least one filename or pattern is required'))
249 raise util.Abort(_('at least one filename or pattern is required'))
250
250
251 hexfn = ui.debugflag and hex or short
251 hexfn = ui.debugflag and hex or short
252
252
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
254 ('number', ' ', lambda x: str(x[0].rev())),
254 ('number', ' ', lambda x: str(x[0].rev())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
256 ('date', ' ', getdate),
256 ('date', ' ', getdate),
257 ('file', ' ', lambda x: x[0].path()),
257 ('file', ' ', lambda x: x[0].path()),
258 ('line_number', ':', lambda x: str(x[1])),
258 ('line_number', ':', lambda x: str(x[1])),
259 ]
259 ]
260
260
261 if (not opts.get('user') and not opts.get('changeset')
261 if (not opts.get('user') and not opts.get('changeset')
262 and not opts.get('date') and not opts.get('file')):
262 and not opts.get('date') and not opts.get('file')):
263 opts['number'] = True
263 opts['number'] = True
264
264
265 linenumber = opts.get('line_number') is not None
265 linenumber = opts.get('line_number') is not None
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
268
268
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
271
271
272 def bad(x, y):
272 def bad(x, y):
273 raise util.Abort("%s: %s" % (x, y))
273 raise util.Abort("%s: %s" % (x, y))
274
274
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
276 m = scmutil.match(ctx, pats, opts)
276 m = scmutil.match(ctx, pats, opts)
277 m.bad = bad
277 m.bad = bad
278 follow = not opts.get('no_follow')
278 follow = not opts.get('no_follow')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
280 for abs in ctx.walk(m):
280 for abs in ctx.walk(m):
281 fctx = ctx[abs]
281 fctx = ctx[abs]
282 if not opts.get('text') and util.binary(fctx.data()):
282 if not opts.get('text') and util.binary(fctx.data()):
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
284 continue
284 continue
285
285
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
287 diffopts=diffopts)
287 diffopts=diffopts)
288 pieces = []
288 pieces = []
289
289
290 for f, sep in funcmap:
290 for f, sep in funcmap:
291 l = [f(n) for n, dummy in lines]
291 l = [f(n) for n, dummy in lines]
292 if l:
292 if l:
293 sized = [(x, encoding.colwidth(x)) for x in l]
293 sized = [(x, encoding.colwidth(x)) for x in l]
294 ml = max([w for x, w in sized])
294 ml = max([w for x, w in sized])
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
296 for x, w in sized])
296 for x, w in sized])
297
297
298 if pieces:
298 if pieces:
299 for p, l in zip(zip(*pieces), lines):
299 for p, l in zip(zip(*pieces), lines):
300 ui.write("%s: %s" % ("".join(p), l[1]))
300 ui.write("%s: %s" % ("".join(p), l[1]))
301
301
302 if lines and not lines[-1][1].endswith('\n'):
302 if lines and not lines[-1][1].endswith('\n'):
303 ui.write('\n')
303 ui.write('\n')
304
304
305 @command('archive',
305 @command('archive',
306 [('', 'no-decode', None, _('do not pass files through decoders')),
306 [('', 'no-decode', None, _('do not pass files through decoders')),
307 ('p', 'prefix', '', _('directory prefix for files in archive'),
307 ('p', 'prefix', '', _('directory prefix for files in archive'),
308 _('PREFIX')),
308 _('PREFIX')),
309 ('r', 'rev', '', _('revision to distribute'), _('REV')),
309 ('r', 'rev', '', _('revision to distribute'), _('REV')),
310 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
310 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
311 ] + subrepoopts + walkopts,
311 ] + subrepoopts + walkopts,
312 _('[OPTION]... DEST'))
312 _('[OPTION]... DEST'))
313 def archive(ui, repo, dest, **opts):
313 def archive(ui, repo, dest, **opts):
314 '''create an unversioned archive of a repository revision
314 '''create an unversioned archive of a repository revision
315
315
316 By default, the revision used is the parent of the working
316 By default, the revision used is the parent of the working
317 directory; use -r/--rev to specify a different revision.
317 directory; use -r/--rev to specify a different revision.
318
318
319 The archive type is automatically detected based on file
319 The archive type is automatically detected based on file
320 extension (or override using -t/--type).
320 extension (or override using -t/--type).
321
321
322 .. container:: verbose
322 .. container:: verbose
323
323
324 Examples:
324 Examples:
325
325
326 - create a zip file containing the 1.0 release::
326 - create a zip file containing the 1.0 release::
327
327
328 hg archive -r 1.0 project-1.0.zip
328 hg archive -r 1.0 project-1.0.zip
329
329
330 - create a tarball excluding .hg files::
330 - create a tarball excluding .hg files::
331
331
332 hg archive project.tar.gz -X ".hg*"
332 hg archive project.tar.gz -X ".hg*"
333
333
334 Valid types are:
334 Valid types are:
335
335
336 :``files``: a directory full of files (default)
336 :``files``: a directory full of files (default)
337 :``tar``: tar archive, uncompressed
337 :``tar``: tar archive, uncompressed
338 :``tbz2``: tar archive, compressed using bzip2
338 :``tbz2``: tar archive, compressed using bzip2
339 :``tgz``: tar archive, compressed using gzip
339 :``tgz``: tar archive, compressed using gzip
340 :``uzip``: zip archive, uncompressed
340 :``uzip``: zip archive, uncompressed
341 :``zip``: zip archive, compressed using deflate
341 :``zip``: zip archive, compressed using deflate
342
342
343 The exact name of the destination archive or directory is given
343 The exact name of the destination archive or directory is given
344 using a format string; see :hg:`help export` for details.
344 using a format string; see :hg:`help export` for details.
345
345
346 Each member added to an archive file has a directory prefix
346 Each member added to an archive file has a directory prefix
347 prepended. Use -p/--prefix to specify a format string for the
347 prepended. Use -p/--prefix to specify a format string for the
348 prefix. The default is the basename of the archive, with suffixes
348 prefix. The default is the basename of the archive, with suffixes
349 removed.
349 removed.
350
350
351 Returns 0 on success.
351 Returns 0 on success.
352 '''
352 '''
353
353
354 ctx = scmutil.revsingle(repo, opts.get('rev'))
354 ctx = scmutil.revsingle(repo, opts.get('rev'))
355 if not ctx:
355 if not ctx:
356 raise util.Abort(_('no working directory: please specify a revision'))
356 raise util.Abort(_('no working directory: please specify a revision'))
357 node = ctx.node()
357 node = ctx.node()
358 dest = cmdutil.makefilename(repo, dest, node)
358 dest = cmdutil.makefilename(repo, dest, node)
359 if os.path.realpath(dest) == repo.root:
359 if os.path.realpath(dest) == repo.root:
360 raise util.Abort(_('repository root cannot be destination'))
360 raise util.Abort(_('repository root cannot be destination'))
361
361
362 kind = opts.get('type') or archival.guesskind(dest) or 'files'
362 kind = opts.get('type') or archival.guesskind(dest) or 'files'
363 prefix = opts.get('prefix')
363 prefix = opts.get('prefix')
364
364
365 if dest == '-':
365 if dest == '-':
366 if kind == 'files':
366 if kind == 'files':
367 raise util.Abort(_('cannot archive plain files to stdout'))
367 raise util.Abort(_('cannot archive plain files to stdout'))
368 dest = cmdutil.makefileobj(repo, dest)
368 dest = cmdutil.makefileobj(repo, dest)
369 if not prefix:
369 if not prefix:
370 prefix = os.path.basename(repo.root) + '-%h'
370 prefix = os.path.basename(repo.root) + '-%h'
371
371
372 prefix = cmdutil.makefilename(repo, prefix, node)
372 prefix = cmdutil.makefilename(repo, prefix, node)
373 matchfn = scmutil.match(ctx, [], opts)
373 matchfn = scmutil.match(ctx, [], opts)
374 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
374 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
375 matchfn, prefix, subrepos=opts.get('subrepos'))
375 matchfn, prefix, subrepos=opts.get('subrepos'))
376
376
377 @command('backout',
377 @command('backout',
378 [('', 'merge', None, _('merge with old dirstate parent after backout')),
378 [('', 'merge', None, _('merge with old dirstate parent after backout')),
379 ('', 'parent', '',
379 ('', 'parent', '',
380 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
380 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
381 ('r', 'rev', '', _('revision to backout'), _('REV')),
381 ('r', 'rev', '', _('revision to backout'), _('REV')),
382 ] + mergetoolopts + walkopts + commitopts + commitopts2,
382 ] + mergetoolopts + walkopts + commitopts + commitopts2,
383 _('[OPTION]... [-r] REV'))
383 _('[OPTION]... [-r] REV'))
384 def backout(ui, repo, node=None, rev=None, **opts):
384 def backout(ui, repo, node=None, rev=None, **opts):
385 '''reverse effect of earlier changeset
385 '''reverse effect of earlier changeset
386
386
387 Prepare a new changeset with the effect of REV undone in the
387 Prepare a new changeset with the effect of REV undone in the
388 current working directory.
388 current working directory.
389
389
390 If REV is the parent of the working directory, then this new changeset
390 If REV is the parent of the working directory, then this new changeset
391 is committed automatically. Otherwise, hg needs to merge the
391 is committed automatically. Otherwise, hg needs to merge the
392 changes and the merged result is left uncommitted.
392 changes and the merged result is left uncommitted.
393
393
394 .. note::
394 .. note::
395 backout cannot be used to fix either an unwanted or
395 backout cannot be used to fix either an unwanted or
396 incorrect merge.
396 incorrect merge.
397
397
398 .. container:: verbose
398 .. container:: verbose
399
399
400 By default, the pending changeset will have one parent,
400 By default, the pending changeset will have one parent,
401 maintaining a linear history. With --merge, the pending
401 maintaining a linear history. With --merge, the pending
402 changeset will instead have two parents: the old parent of the
402 changeset will instead have two parents: the old parent of the
403 working directory and a new child of REV that simply undoes REV.
403 working directory and a new child of REV that simply undoes REV.
404
404
405 Before version 1.7, the behavior without --merge was equivalent
405 Before version 1.7, the behavior without --merge was equivalent
406 to specifying --merge followed by :hg:`update --clean .` to
406 to specifying --merge followed by :hg:`update --clean .` to
407 cancel the merge and leave the child of REV as a head to be
407 cancel the merge and leave the child of REV as a head to be
408 merged separately.
408 merged separately.
409
409
410 See :hg:`help dates` for a list of formats valid for -d/--date.
410 See :hg:`help dates` for a list of formats valid for -d/--date.
411
411
412 Returns 0 on success.
412 Returns 0 on success.
413 '''
413 '''
414 if rev and node:
414 if rev and node:
415 raise util.Abort(_("please specify just one revision"))
415 raise util.Abort(_("please specify just one revision"))
416
416
417 if not rev:
417 if not rev:
418 rev = node
418 rev = node
419
419
420 if not rev:
420 if not rev:
421 raise util.Abort(_("please specify a revision to backout"))
421 raise util.Abort(_("please specify a revision to backout"))
422
422
423 date = opts.get('date')
423 date = opts.get('date')
424 if date:
424 if date:
425 opts['date'] = util.parsedate(date)
425 opts['date'] = util.parsedate(date)
426
426
427 cmdutil.bailifchanged(repo)
427 cmdutil.bailifchanged(repo)
428 node = scmutil.revsingle(repo, rev).node()
428 node = scmutil.revsingle(repo, rev).node()
429
429
430 op1, op2 = repo.dirstate.parents()
430 op1, op2 = repo.dirstate.parents()
431 a = repo.changelog.ancestor(op1, node)
431 a = repo.changelog.ancestor(op1, node)
432 if a != node:
432 if a != node:
433 raise util.Abort(_('cannot backout change on a different branch'))
433 raise util.Abort(_('cannot backout change on a different branch'))
434
434
435 p1, p2 = repo.changelog.parents(node)
435 p1, p2 = repo.changelog.parents(node)
436 if p1 == nullid:
436 if p1 == nullid:
437 raise util.Abort(_('cannot backout a change with no parents'))
437 raise util.Abort(_('cannot backout a change with no parents'))
438 if p2 != nullid:
438 if p2 != nullid:
439 if not opts.get('parent'):
439 if not opts.get('parent'):
440 raise util.Abort(_('cannot backout a merge changeset'))
440 raise util.Abort(_('cannot backout a merge changeset'))
441 p = repo.lookup(opts['parent'])
441 p = repo.lookup(opts['parent'])
442 if p not in (p1, p2):
442 if p not in (p1, p2):
443 raise util.Abort(_('%s is not a parent of %s') %
443 raise util.Abort(_('%s is not a parent of %s') %
444 (short(p), short(node)))
444 (short(p), short(node)))
445 parent = p
445 parent = p
446 else:
446 else:
447 if opts.get('parent'):
447 if opts.get('parent'):
448 raise util.Abort(_('cannot use --parent on non-merge changeset'))
448 raise util.Abort(_('cannot use --parent on non-merge changeset'))
449 parent = p1
449 parent = p1
450
450
451 # the backout should appear on the same branch
451 # the backout should appear on the same branch
452 branch = repo.dirstate.branch()
452 branch = repo.dirstate.branch()
453 hg.clean(repo, node, show_stats=False)
453 hg.clean(repo, node, show_stats=False)
454 repo.dirstate.setbranch(branch)
454 repo.dirstate.setbranch(branch)
455 revert_opts = opts.copy()
455 revert_opts = opts.copy()
456 revert_opts['date'] = None
456 revert_opts['date'] = None
457 revert_opts['all'] = True
457 revert_opts['all'] = True
458 revert_opts['rev'] = hex(parent)
458 revert_opts['rev'] = hex(parent)
459 revert_opts['no_backup'] = None
459 revert_opts['no_backup'] = None
460 revert(ui, repo, **revert_opts)
460 revert(ui, repo, **revert_opts)
461 if not opts.get('merge') and op1 != node:
461 if not opts.get('merge') and op1 != node:
462 try:
462 try:
463 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
463 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
464 return hg.update(repo, op1)
464 return hg.update(repo, op1)
465 finally:
465 finally:
466 ui.setconfig('ui', 'forcemerge', '')
466 ui.setconfig('ui', 'forcemerge', '')
467
467
468 commit_opts = opts.copy()
468 commit_opts = opts.copy()
469 commit_opts['addremove'] = False
469 commit_opts['addremove'] = False
470 if not commit_opts['message'] and not commit_opts['logfile']:
470 if not commit_opts['message'] and not commit_opts['logfile']:
471 # we don't translate commit messages
471 # we don't translate commit messages
472 commit_opts['message'] = "Backed out changeset %s" % short(node)
472 commit_opts['message'] = "Backed out changeset %s" % short(node)
473 commit_opts['force_editor'] = True
473 commit_opts['force_editor'] = True
474 commit(ui, repo, **commit_opts)
474 commit(ui, repo, **commit_opts)
475 def nice(node):
475 def nice(node):
476 return '%d:%s' % (repo.changelog.rev(node), short(node))
476 return '%d:%s' % (repo.changelog.rev(node), short(node))
477 ui.status(_('changeset %s backs out changeset %s\n') %
477 ui.status(_('changeset %s backs out changeset %s\n') %
478 (nice(repo.changelog.tip()), nice(node)))
478 (nice(repo.changelog.tip()), nice(node)))
479 if opts.get('merge') and op1 != node:
479 if opts.get('merge') and op1 != node:
480 hg.clean(repo, op1, show_stats=False)
480 hg.clean(repo, op1, show_stats=False)
481 ui.status(_('merging with changeset %s\n')
481 ui.status(_('merging with changeset %s\n')
482 % nice(repo.changelog.tip()))
482 % nice(repo.changelog.tip()))
483 try:
483 try:
484 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
484 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
485 return hg.merge(repo, hex(repo.changelog.tip()))
485 return hg.merge(repo, hex(repo.changelog.tip()))
486 finally:
486 finally:
487 ui.setconfig('ui', 'forcemerge', '')
487 ui.setconfig('ui', 'forcemerge', '')
488 return 0
488 return 0
489
489
490 @command('bisect',
490 @command('bisect',
491 [('r', 'reset', False, _('reset bisect state')),
491 [('r', 'reset', False, _('reset bisect state')),
492 ('g', 'good', False, _('mark changeset good')),
492 ('g', 'good', False, _('mark changeset good')),
493 ('b', 'bad', False, _('mark changeset bad')),
493 ('b', 'bad', False, _('mark changeset bad')),
494 ('s', 'skip', False, _('skip testing changeset')),
494 ('s', 'skip', False, _('skip testing changeset')),
495 ('e', 'extend', False, _('extend the bisect range')),
495 ('e', 'extend', False, _('extend the bisect range')),
496 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
496 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
497 ('U', 'noupdate', False, _('do not update to target'))],
497 ('U', 'noupdate', False, _('do not update to target'))],
498 _("[-gbsr] [-U] [-c CMD] [REV]"))
498 _("[-gbsr] [-U] [-c CMD] [REV]"))
499 def bisect(ui, repo, rev=None, extra=None, command=None,
499 def bisect(ui, repo, rev=None, extra=None, command=None,
500 reset=None, good=None, bad=None, skip=None, extend=None,
500 reset=None, good=None, bad=None, skip=None, extend=None,
501 noupdate=None):
501 noupdate=None):
502 """subdivision search of changesets
502 """subdivision search of changesets
503
503
504 This command helps to find changesets which introduce problems. To
504 This command helps to find changesets which introduce problems. To
505 use, mark the earliest changeset you know exhibits the problem as
505 use, mark the earliest changeset you know exhibits the problem as
506 bad, then mark the latest changeset which is free from the problem
506 bad, then mark the latest changeset which is free from the problem
507 as good. Bisect will update your working directory to a revision
507 as good. Bisect will update your working directory to a revision
508 for testing (unless the -U/--noupdate option is specified). Once
508 for testing (unless the -U/--noupdate option is specified). Once
509 you have performed tests, mark the working directory as good or
509 you have performed tests, mark the working directory as good or
510 bad, and bisect will either update to another candidate changeset
510 bad, and bisect will either update to another candidate changeset
511 or announce that it has found the bad revision.
511 or announce that it has found the bad revision.
512
512
513 As a shortcut, you can also use the revision argument to mark a
513 As a shortcut, you can also use the revision argument to mark a
514 revision as good or bad without checking it out first.
514 revision as good or bad without checking it out first.
515
515
516 If you supply a command, it will be used for automatic bisection.
516 If you supply a command, it will be used for automatic bisection.
517 Its exit status will be used to mark revisions as good or bad:
517 Its exit status will be used to mark revisions as good or bad:
518 status 0 means good, 125 means to skip the revision, 127
518 status 0 means good, 125 means to skip the revision, 127
519 (command not found) will abort the bisection, and any other
519 (command not found) will abort the bisection, and any other
520 non-zero exit status means the revision is bad.
520 non-zero exit status means the revision is bad.
521
521
522 .. container:: verbose
522 .. container:: verbose
523
523
524 Some examples:
524 Some examples:
525
525
526 - start a bisection with known bad revision 12, and good revision 34::
526 - start a bisection with known bad revision 12, and good revision 34::
527
527
528 hg bisect --bad 34
528 hg bisect --bad 34
529 hg bisect --good 12
529 hg bisect --good 12
530
530
531 - advance the current bisection by marking current revision as good or
531 - advance the current bisection by marking current revision as good or
532 bad::
532 bad::
533
533
534 hg bisect --good
534 hg bisect --good
535 hg bisect --bad
535 hg bisect --bad
536
536
537 - mark the current revision, or a known revision, to be skipped (eg. if
537 - mark the current revision, or a known revision, to be skipped (eg. if
538 that revision is not usable because of another issue)::
538 that revision is not usable because of another issue)::
539
539
540 hg bisect --skip
540 hg bisect --skip
541 hg bisect --skip 23
541 hg bisect --skip 23
542
542
543 - forget the current bisection::
543 - forget the current bisection::
544
544
545 hg bisect --reset
545 hg bisect --reset
546
546
547 - use 'make && make tests' to automatically find the first broken
547 - use 'make && make tests' to automatically find the first broken
548 revision::
548 revision::
549
549
550 hg bisect --reset
550 hg bisect --reset
551 hg bisect --bad 34
551 hg bisect --bad 34
552 hg bisect --good 12
552 hg bisect --good 12
553 hg bisect --command 'make && make tests'
553 hg bisect --command 'make && make tests'
554
554
555 - see all changesets whose states are already known in the current
555 - see all changesets whose states are already known in the current
556 bisection::
556 bisection::
557
557
558 hg log -r "bisect(pruned)"
558 hg log -r "bisect(pruned)"
559
559
560 - see all changesets that took part in the current bisection::
560 - see all changesets that took part in the current bisection::
561
561
562 hg log -r "bisect(range)"
562 hg log -r "bisect(range)"
563
563
564 - with the graphlog extension, you can even get a nice graph::
564 - with the graphlog extension, you can even get a nice graph::
565
565
566 hg log --graph -r "bisect(range)"
566 hg log --graph -r "bisect(range)"
567
567
568 See :hg:`help revsets` for more about the `bisect()` keyword.
568 See :hg:`help revsets` for more about the `bisect()` keyword.
569
569
570 Returns 0 on success.
570 Returns 0 on success.
571 """
571 """
572 def extendbisectrange(nodes, good):
572 def extendbisectrange(nodes, good):
573 # bisect is incomplete when it ends on a merge node and
573 # bisect is incomplete when it ends on a merge node and
574 # one of the parent was not checked.
574 # one of the parent was not checked.
575 parents = repo[nodes[0]].parents()
575 parents = repo[nodes[0]].parents()
576 if len(parents) > 1:
576 if len(parents) > 1:
577 side = good and state['bad'] or state['good']
577 side = good and state['bad'] or state['good']
578 num = len(set(i.node() for i in parents) & set(side))
578 num = len(set(i.node() for i in parents) & set(side))
579 if num == 1:
579 if num == 1:
580 return parents[0].ancestor(parents[1])
580 return parents[0].ancestor(parents[1])
581 return None
581 return None
582
582
583 def print_result(nodes, good):
583 def print_result(nodes, good):
584 displayer = cmdutil.show_changeset(ui, repo, {})
584 displayer = cmdutil.show_changeset(ui, repo, {})
585 if len(nodes) == 1:
585 if len(nodes) == 1:
586 # narrowed it down to a single revision
586 # narrowed it down to a single revision
587 if good:
587 if good:
588 ui.write(_("The first good revision is:\n"))
588 ui.write(_("The first good revision is:\n"))
589 else:
589 else:
590 ui.write(_("The first bad revision is:\n"))
590 ui.write(_("The first bad revision is:\n"))
591 displayer.show(repo[nodes[0]])
591 displayer.show(repo[nodes[0]])
592 extendnode = extendbisectrange(nodes, good)
592 extendnode = extendbisectrange(nodes, good)
593 if extendnode is not None:
593 if extendnode is not None:
594 ui.write(_('Not all ancestors of this changeset have been'
594 ui.write(_('Not all ancestors of this changeset have been'
595 ' checked.\nUse bisect --extend to continue the '
595 ' checked.\nUse bisect --extend to continue the '
596 'bisection from\nthe common ancestor, %s.\n')
596 'bisection from\nthe common ancestor, %s.\n')
597 % extendnode)
597 % extendnode)
598 else:
598 else:
599 # multiple possible revisions
599 # multiple possible revisions
600 if good:
600 if good:
601 ui.write(_("Due to skipped revisions, the first "
601 ui.write(_("Due to skipped revisions, the first "
602 "good revision could be any of:\n"))
602 "good revision could be any of:\n"))
603 else:
603 else:
604 ui.write(_("Due to skipped revisions, the first "
604 ui.write(_("Due to skipped revisions, the first "
605 "bad revision could be any of:\n"))
605 "bad revision could be any of:\n"))
606 for n in nodes:
606 for n in nodes:
607 displayer.show(repo[n])
607 displayer.show(repo[n])
608 displayer.close()
608 displayer.close()
609
609
610 def check_state(state, interactive=True):
610 def check_state(state, interactive=True):
611 if not state['good'] or not state['bad']:
611 if not state['good'] or not state['bad']:
612 if (good or bad or skip or reset) and interactive:
612 if (good or bad or skip or reset) and interactive:
613 return
613 return
614 if not state['good']:
614 if not state['good']:
615 raise util.Abort(_('cannot bisect (no known good revisions)'))
615 raise util.Abort(_('cannot bisect (no known good revisions)'))
616 else:
616 else:
617 raise util.Abort(_('cannot bisect (no known bad revisions)'))
617 raise util.Abort(_('cannot bisect (no known bad revisions)'))
618 return True
618 return True
619
619
620 # backward compatibility
620 # backward compatibility
621 if rev in "good bad reset init".split():
621 if rev in "good bad reset init".split():
622 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
622 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
623 cmd, rev, extra = rev, extra, None
623 cmd, rev, extra = rev, extra, None
624 if cmd == "good":
624 if cmd == "good":
625 good = True
625 good = True
626 elif cmd == "bad":
626 elif cmd == "bad":
627 bad = True
627 bad = True
628 else:
628 else:
629 reset = True
629 reset = True
630 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
630 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
631 raise util.Abort(_('incompatible arguments'))
631 raise util.Abort(_('incompatible arguments'))
632
632
633 if reset:
633 if reset:
634 p = repo.join("bisect.state")
634 p = repo.join("bisect.state")
635 if os.path.exists(p):
635 if os.path.exists(p):
636 os.unlink(p)
636 os.unlink(p)
637 return
637 return
638
638
639 state = hbisect.load_state(repo)
639 state = hbisect.load_state(repo)
640
640
641 if command:
641 if command:
642 changesets = 1
642 changesets = 1
643 try:
643 try:
644 while changesets:
644 while changesets:
645 # update state
645 # update state
646 status = util.system(command, out=ui.fout)
646 status = util.system(command, out=ui.fout)
647 if status == 125:
647 if status == 125:
648 transition = "skip"
648 transition = "skip"
649 elif status == 0:
649 elif status == 0:
650 transition = "good"
650 transition = "good"
651 # status < 0 means process was killed
651 # status < 0 means process was killed
652 elif status == 127:
652 elif status == 127:
653 raise util.Abort(_("failed to execute %s") % command)
653 raise util.Abort(_("failed to execute %s") % command)
654 elif status < 0:
654 elif status < 0:
655 raise util.Abort(_("%s killed") % command)
655 raise util.Abort(_("%s killed") % command)
656 else:
656 else:
657 transition = "bad"
657 transition = "bad"
658 ctx = scmutil.revsingle(repo, rev)
658 ctx = scmutil.revsingle(repo, rev)
659 rev = None # clear for future iterations
659 rev = None # clear for future iterations
660 state[transition].append(ctx.node())
660 state[transition].append(ctx.node())
661 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
661 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
662 check_state(state, interactive=False)
662 check_state(state, interactive=False)
663 # bisect
663 # bisect
664 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
664 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
665 # update to next check
665 # update to next check
666 cmdutil.bailifchanged(repo)
666 cmdutil.bailifchanged(repo)
667 hg.clean(repo, nodes[0], show_stats=False)
667 hg.clean(repo, nodes[0], show_stats=False)
668 finally:
668 finally:
669 hbisect.save_state(repo, state)
669 hbisect.save_state(repo, state)
670 print_result(nodes, good)
670 print_result(nodes, good)
671 return
671 return
672
672
673 # update state
673 # update state
674
674
675 if rev:
675 if rev:
676 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
676 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
677 else:
677 else:
678 nodes = [repo.lookup('.')]
678 nodes = [repo.lookup('.')]
679
679
680 if good or bad or skip:
680 if good or bad or skip:
681 if good:
681 if good:
682 state['good'] += nodes
682 state['good'] += nodes
683 elif bad:
683 elif bad:
684 state['bad'] += nodes
684 state['bad'] += nodes
685 elif skip:
685 elif skip:
686 state['skip'] += nodes
686 state['skip'] += nodes
687 hbisect.save_state(repo, state)
687 hbisect.save_state(repo, state)
688
688
689 if not check_state(state):
689 if not check_state(state):
690 return
690 return
691
691
692 # actually bisect
692 # actually bisect
693 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
693 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
694 if extend:
694 if extend:
695 if not changesets:
695 if not changesets:
696 extendnode = extendbisectrange(nodes, good)
696 extendnode = extendbisectrange(nodes, good)
697 if extendnode is not None:
697 if extendnode is not None:
698 ui.write(_("Extending search to changeset %d:%s\n"
698 ui.write(_("Extending search to changeset %d:%s\n"
699 % (extendnode.rev(), extendnode)))
699 % (extendnode.rev(), extendnode)))
700 if noupdate:
700 if noupdate:
701 return
701 return
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 return hg.clean(repo, extendnode.node())
703 return hg.clean(repo, extendnode.node())
704 raise util.Abort(_("nothing to extend"))
704 raise util.Abort(_("nothing to extend"))
705
705
706 if changesets == 0:
706 if changesets == 0:
707 print_result(nodes, good)
707 print_result(nodes, good)
708 else:
708 else:
709 assert len(nodes) == 1 # only a single node can be tested next
709 assert len(nodes) == 1 # only a single node can be tested next
710 node = nodes[0]
710 node = nodes[0]
711 # compute the approximate number of remaining tests
711 # compute the approximate number of remaining tests
712 tests, size = 0, 2
712 tests, size = 0, 2
713 while size <= changesets:
713 while size <= changesets:
714 tests, size = tests + 1, size * 2
714 tests, size = tests + 1, size * 2
715 rev = repo.changelog.rev(node)
715 rev = repo.changelog.rev(node)
716 ui.write(_("Testing changeset %d:%s "
716 ui.write(_("Testing changeset %d:%s "
717 "(%d changesets remaining, ~%d tests)\n")
717 "(%d changesets remaining, ~%d tests)\n")
718 % (rev, short(node), changesets, tests))
718 % (rev, short(node), changesets, tests))
719 if not noupdate:
719 if not noupdate:
720 cmdutil.bailifchanged(repo)
720 cmdutil.bailifchanged(repo)
721 return hg.clean(repo, node)
721 return hg.clean(repo, node)
722
722
723 @command('bookmarks',
723 @command('bookmarks',
724 [('f', 'force', False, _('force')),
724 [('f', 'force', False, _('force')),
725 ('r', 'rev', '', _('revision'), _('REV')),
725 ('r', 'rev', '', _('revision'), _('REV')),
726 ('d', 'delete', False, _('delete a given bookmark')),
726 ('d', 'delete', False, _('delete a given bookmark')),
727 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
727 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
728 ('i', 'inactive', False, _('mark a bookmark inactive'))],
728 ('i', 'inactive', False, _('mark a bookmark inactive'))],
729 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
729 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
730 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
730 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
731 rename=None, inactive=False):
731 rename=None, inactive=False):
732 '''track a line of development with movable markers
732 '''track a line of development with movable markers
733
733
734 Bookmarks are pointers to certain commits that move when committing.
734 Bookmarks are pointers to certain commits that move when committing.
735 Bookmarks are local. They can be renamed, copied and deleted. It is
735 Bookmarks are local. They can be renamed, copied and deleted. It is
736 possible to use :hg:`merge NAME` to merge from a given bookmark, and
736 possible to use :hg:`merge NAME` to merge from a given bookmark, and
737 :hg:`update NAME` to update to a given bookmark.
737 :hg:`update NAME` to update to a given bookmark.
738
738
739 You can use :hg:`bookmark NAME` to set a bookmark on the working
739 You can use :hg:`bookmark NAME` to set a bookmark on the working
740 directory's parent revision with the given name. If you specify
740 directory's parent revision with the given name. If you specify
741 a revision using -r REV (where REV may be an existing bookmark),
741 a revision using -r REV (where REV may be an existing bookmark),
742 the bookmark is assigned to that revision.
742 the bookmark is assigned to that revision.
743
743
744 Bookmarks can be pushed and pulled between repositories (see :hg:`help
744 Bookmarks can be pushed and pulled between repositories (see :hg:`help
745 push` and :hg:`help pull`). This requires both the local and remote
745 push` and :hg:`help pull`). This requires both the local and remote
746 repositories to support bookmarks. For versions prior to 1.8, this means
746 repositories to support bookmarks. For versions prior to 1.8, this means
747 the bookmarks extension must be enabled.
747 the bookmarks extension must be enabled.
748
748
749 With -i/--inactive, the new bookmark will not be made the active
749 With -i/--inactive, the new bookmark will not be made the active
750 bookmark. If -r/--rev is given, the new bookmark will not be made
750 bookmark. If -r/--rev is given, the new bookmark will not be made
751 active even if -i/--inactive is not given. If no NAME is given, the
751 active even if -i/--inactive is not given. If no NAME is given, the
752 current active bookmark will be marked inactive.
752 current active bookmark will be marked inactive.
753 '''
753 '''
754 hexfn = ui.debugflag and hex or short
754 hexfn = ui.debugflag and hex or short
755 marks = repo._bookmarks
755 marks = repo._bookmarks
756 cur = repo.changectx('.').node()
756 cur = repo.changectx('.').node()
757
757
758 if delete:
758 if delete:
759 if mark is None:
759 if mark is None:
760 raise util.Abort(_("bookmark name required"))
760 raise util.Abort(_("bookmark name required"))
761 if mark not in marks:
761 if mark not in marks:
762 raise util.Abort(_("bookmark '%s' does not exist") % mark)
762 raise util.Abort(_("bookmark '%s' does not exist") % mark)
763 if mark == repo._bookmarkcurrent:
763 if mark == repo._bookmarkcurrent:
764 bookmarks.setcurrent(repo, None)
764 bookmarks.setcurrent(repo, None)
765 del marks[mark]
765 del marks[mark]
766 bookmarks.write(repo)
766 bookmarks.write(repo)
767 return
767 return
768
768
769 if rename:
769 if rename:
770 if rename not in marks:
770 if rename not in marks:
771 raise util.Abort(_("bookmark '%s' does not exist") % rename)
771 raise util.Abort(_("bookmark '%s' does not exist") % rename)
772 if mark in marks and not force:
772 if mark in marks and not force:
773 raise util.Abort(_("bookmark '%s' already exists "
773 raise util.Abort(_("bookmark '%s' already exists "
774 "(use -f to force)") % mark)
774 "(use -f to force)") % mark)
775 if mark is None:
775 if mark is None:
776 raise util.Abort(_("new bookmark name required"))
776 raise util.Abort(_("new bookmark name required"))
777 marks[mark] = marks[rename]
777 marks[mark] = marks[rename]
778 if repo._bookmarkcurrent == rename and not inactive:
778 if repo._bookmarkcurrent == rename and not inactive:
779 bookmarks.setcurrent(repo, mark)
779 bookmarks.setcurrent(repo, mark)
780 del marks[rename]
780 del marks[rename]
781 bookmarks.write(repo)
781 bookmarks.write(repo)
782 return
782 return
783
783
784 if mark is not None:
784 if mark is not None:
785 if "\n" in mark:
785 if "\n" in mark:
786 raise util.Abort(_("bookmark name cannot contain newlines"))
786 raise util.Abort(_("bookmark name cannot contain newlines"))
787 mark = mark.strip()
787 mark = mark.strip()
788 if not mark:
788 if not mark:
789 raise util.Abort(_("bookmark names cannot consist entirely of "
789 raise util.Abort(_("bookmark names cannot consist entirely of "
790 "whitespace"))
790 "whitespace"))
791 if inactive and mark == repo._bookmarkcurrent:
791 if inactive and mark == repo._bookmarkcurrent:
792 bookmarks.setcurrent(repo, None)
792 bookmarks.setcurrent(repo, None)
793 return
793 return
794 if mark in marks and not force:
794 if mark in marks and not force:
795 raise util.Abort(_("bookmark '%s' already exists "
795 raise util.Abort(_("bookmark '%s' already exists "
796 "(use -f to force)") % mark)
796 "(use -f to force)") % mark)
797 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
797 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
798 and not force):
798 and not force):
799 raise util.Abort(
799 raise util.Abort(
800 _("a bookmark cannot have the name of an existing branch"))
800 _("a bookmark cannot have the name of an existing branch"))
801 if rev:
801 if rev:
802 marks[mark] = repo.lookup(rev)
802 marks[mark] = repo.lookup(rev)
803 else:
803 else:
804 marks[mark] = cur
804 marks[mark] = cur
805 if not inactive and cur == marks[mark]:
805 if not inactive and cur == marks[mark]:
806 bookmarks.setcurrent(repo, mark)
806 bookmarks.setcurrent(repo, mark)
807 bookmarks.write(repo)
807 bookmarks.write(repo)
808 return
808 return
809
809
810 if mark is None:
810 if mark is None:
811 if rev:
811 if rev:
812 raise util.Abort(_("bookmark name required"))
812 raise util.Abort(_("bookmark name required"))
813 if len(marks) == 0:
813 if len(marks) == 0:
814 ui.status(_("no bookmarks set\n"))
814 ui.status(_("no bookmarks set\n"))
815 else:
815 else:
816 for bmark, n in sorted(marks.iteritems()):
816 for bmark, n in sorted(marks.iteritems()):
817 current = repo._bookmarkcurrent
817 current = repo._bookmarkcurrent
818 if bmark == current and n == cur:
818 if bmark == current and n == cur:
819 prefix, label = '*', 'bookmarks.current'
819 prefix, label = '*', 'bookmarks.current'
820 else:
820 else:
821 prefix, label = ' ', ''
821 prefix, label = ' ', ''
822
822
823 if ui.quiet:
823 if ui.quiet:
824 ui.write("%s\n" % bmark, label=label)
824 ui.write("%s\n" % bmark, label=label)
825 else:
825 else:
826 ui.write(" %s %-25s %d:%s\n" % (
826 ui.write(" %s %-25s %d:%s\n" % (
827 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
827 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
828 label=label)
828 label=label)
829 return
829 return
830
830
831 @command('branch',
831 @command('branch',
832 [('f', 'force', None,
832 [('f', 'force', None,
833 _('set branch name even if it shadows an existing branch')),
833 _('set branch name even if it shadows an existing branch')),
834 ('C', 'clean', None, _('reset branch name to parent branch name'))],
834 ('C', 'clean', None, _('reset branch name to parent branch name'))],
835 _('[-fC] [NAME]'))
835 _('[-fC] [NAME]'))
836 def branch(ui, repo, label=None, **opts):
836 def branch(ui, repo, label=None, **opts):
837 """set or show the current branch name
837 """set or show the current branch name
838
838
839 .. note::
839 .. note::
840 Branch names are permanent and global. Use :hg:`bookmark` to create a
840 Branch names are permanent and global. Use :hg:`bookmark` to create a
841 light-weight bookmark instead. See :hg:`help glossary` for more
841 light-weight bookmark instead. See :hg:`help glossary` for more
842 information about named branches and bookmarks.
842 information about named branches and bookmarks.
843
843
844 With no argument, show the current branch name. With one argument,
844 With no argument, show the current branch name. With one argument,
845 set the working directory branch name (the branch will not exist
845 set the working directory branch name (the branch will not exist
846 in the repository until the next commit). Standard practice
846 in the repository until the next commit). Standard practice
847 recommends that primary development take place on the 'default'
847 recommends that primary development take place on the 'default'
848 branch.
848 branch.
849
849
850 Unless -f/--force is specified, branch will not let you set a
850 Unless -f/--force is specified, branch will not let you set a
851 branch name that already exists, even if it's inactive.
851 branch name that already exists, even if it's inactive.
852
852
853 Use -C/--clean to reset the working directory branch to that of
853 Use -C/--clean to reset the working directory branch to that of
854 the parent of the working directory, negating a previous branch
854 the parent of the working directory, negating a previous branch
855 change.
855 change.
856
856
857 Use the command :hg:`update` to switch to an existing branch. Use
857 Use the command :hg:`update` to switch to an existing branch. Use
858 :hg:`commit --close-branch` to mark this branch as closed.
858 :hg:`commit --close-branch` to mark this branch as closed.
859
859
860 Returns 0 on success.
860 Returns 0 on success.
861 """
861 """
862
862
863 if opts.get('clean'):
863 if opts.get('clean'):
864 label = repo[None].p1().branch()
864 label = repo[None].p1().branch()
865 repo.dirstate.setbranch(label)
865 repo.dirstate.setbranch(label)
866 ui.status(_('reset working directory to branch %s\n') % label)
866 ui.status(_('reset working directory to branch %s\n') % label)
867 elif label:
867 elif label:
868 if not opts.get('force') and label in repo.branchtags():
868 if not opts.get('force') and label in repo.branchtags():
869 if label not in [p.branch() for p in repo.parents()]:
869 if label not in [p.branch() for p in repo.parents()]:
870 raise util.Abort(_('a branch of the same name already exists'),
870 raise util.Abort(_('a branch of the same name already exists'),
871 # i18n: "it" refers to an existing branch
871 # i18n: "it" refers to an existing branch
872 hint=_("use 'hg update' to switch to it"))
872 hint=_("use 'hg update' to switch to it"))
873 repo.dirstate.setbranch(label)
873 repo.dirstate.setbranch(label)
874 ui.status(_('marked working directory as branch %s\n') % label)
874 ui.status(_('marked working directory as branch %s\n') % label)
875 ui.status(_('(branches are permanent and global, '
875 ui.status(_('(branches are permanent and global, '
876 'did you want a bookmark?)\n'))
876 'did you want a bookmark?)\n'))
877 else:
877 else:
878 ui.write("%s\n" % repo.dirstate.branch())
878 ui.write("%s\n" % repo.dirstate.branch())
879
879
880 @command('branches',
880 @command('branches',
881 [('a', 'active', False, _('show only branches that have unmerged heads')),
881 [('a', 'active', False, _('show only branches that have unmerged heads')),
882 ('c', 'closed', False, _('show normal and closed branches'))],
882 ('c', 'closed', False, _('show normal and closed branches'))],
883 _('[-ac]'))
883 _('[-ac]'))
884 def branches(ui, repo, active=False, closed=False):
884 def branches(ui, repo, active=False, closed=False):
885 """list repository named branches
885 """list repository named branches
886
886
887 List the repository's named branches, indicating which ones are
887 List the repository's named branches, indicating which ones are
888 inactive. If -c/--closed is specified, also list branches which have
888 inactive. If -c/--closed is specified, also list branches which have
889 been marked closed (see :hg:`commit --close-branch`).
889 been marked closed (see :hg:`commit --close-branch`).
890
890
891 If -a/--active is specified, only show active branches. A branch
891 If -a/--active is specified, only show active branches. A branch
892 is considered active if it contains repository heads.
892 is considered active if it contains repository heads.
893
893
894 Use the command :hg:`update` to switch to an existing branch.
894 Use the command :hg:`update` to switch to an existing branch.
895
895
896 Returns 0.
896 Returns 0.
897 """
897 """
898
898
899 hexfunc = ui.debugflag and hex or short
899 hexfunc = ui.debugflag and hex or short
900 activebranches = [repo[n].branch() for n in repo.heads()]
900 activebranches = [repo[n].branch() for n in repo.heads()]
901 def testactive(tag, node):
901 def testactive(tag, node):
902 realhead = tag in activebranches
902 realhead = tag in activebranches
903 open = node in repo.branchheads(tag, closed=False)
903 open = node in repo.branchheads(tag, closed=False)
904 return realhead and open
904 return realhead and open
905 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
905 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
906 for tag, node in repo.branchtags().items()],
906 for tag, node in repo.branchtags().items()],
907 reverse=True)
907 reverse=True)
908
908
909 for isactive, node, tag in branches:
909 for isactive, node, tag in branches:
910 if (not active) or isactive:
910 if (not active) or isactive:
911 if ui.quiet:
911 if ui.quiet:
912 ui.write("%s\n" % tag)
912 ui.write("%s\n" % tag)
913 else:
913 else:
914 hn = repo.lookup(node)
914 hn = repo.lookup(node)
915 if isactive:
915 if isactive:
916 label = 'branches.active'
916 label = 'branches.active'
917 notice = ''
917 notice = ''
918 elif hn not in repo.branchheads(tag, closed=False):
918 elif hn not in repo.branchheads(tag, closed=False):
919 if not closed:
919 if not closed:
920 continue
920 continue
921 label = 'branches.closed'
921 label = 'branches.closed'
922 notice = _(' (closed)')
922 notice = _(' (closed)')
923 else:
923 else:
924 label = 'branches.inactive'
924 label = 'branches.inactive'
925 notice = _(' (inactive)')
925 notice = _(' (inactive)')
926 if tag == repo.dirstate.branch():
926 if tag == repo.dirstate.branch():
927 label = 'branches.current'
927 label = 'branches.current'
928 rev = str(node).rjust(31 - encoding.colwidth(tag))
928 rev = str(node).rjust(31 - encoding.colwidth(tag))
929 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
929 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
930 tag = ui.label(tag, label)
930 tag = ui.label(tag, label)
931 ui.write("%s %s%s\n" % (tag, rev, notice))
931 ui.write("%s %s%s\n" % (tag, rev, notice))
932
932
933 @command('bundle',
933 @command('bundle',
934 [('f', 'force', None, _('run even when the destination is unrelated')),
934 [('f', 'force', None, _('run even when the destination is unrelated')),
935 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
935 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
936 _('REV')),
936 _('REV')),
937 ('b', 'branch', [], _('a specific branch you would like to bundle'),
937 ('b', 'branch', [], _('a specific branch you would like to bundle'),
938 _('BRANCH')),
938 _('BRANCH')),
939 ('', 'base', [],
939 ('', 'base', [],
940 _('a base changeset assumed to be available at the destination'),
940 _('a base changeset assumed to be available at the destination'),
941 _('REV')),
941 _('REV')),
942 ('a', 'all', None, _('bundle all changesets in the repository')),
942 ('a', 'all', None, _('bundle all changesets in the repository')),
943 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
943 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
944 ] + remoteopts,
944 ] + remoteopts,
945 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
945 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
946 def bundle(ui, repo, fname, dest=None, **opts):
946 def bundle(ui, repo, fname, dest=None, **opts):
947 """create a changegroup file
947 """create a changegroup file
948
948
949 Generate a compressed changegroup file collecting changesets not
949 Generate a compressed changegroup file collecting changesets not
950 known to be in another repository.
950 known to be in another repository.
951
951
952 If you omit the destination repository, then hg assumes the
952 If you omit the destination repository, then hg assumes the
953 destination will have all the nodes you specify with --base
953 destination will have all the nodes you specify with --base
954 parameters. To create a bundle containing all changesets, use
954 parameters. To create a bundle containing all changesets, use
955 -a/--all (or --base null).
955 -a/--all (or --base null).
956
956
957 You can change compression method with the -t/--type option.
957 You can change compression method with the -t/--type option.
958 The available compression methods are: none, bzip2, and
958 The available compression methods are: none, bzip2, and
959 gzip (by default, bundles are compressed using bzip2).
959 gzip (by default, bundles are compressed using bzip2).
960
960
961 The bundle file can then be transferred using conventional means
961 The bundle file can then be transferred using conventional means
962 and applied to another repository with the unbundle or pull
962 and applied to another repository with the unbundle or pull
963 command. This is useful when direct push and pull are not
963 command. This is useful when direct push and pull are not
964 available or when exporting an entire repository is undesirable.
964 available or when exporting an entire repository is undesirable.
965
965
966 Applying bundles preserves all changeset contents including
966 Applying bundles preserves all changeset contents including
967 permissions, copy/rename information, and revision history.
967 permissions, copy/rename information, and revision history.
968
968
969 Returns 0 on success, 1 if no changes found.
969 Returns 0 on success, 1 if no changes found.
970 """
970 """
971 revs = None
971 revs = None
972 if 'rev' in opts:
972 if 'rev' in opts:
973 revs = scmutil.revrange(repo, opts['rev'])
973 revs = scmutil.revrange(repo, opts['rev'])
974
974
975 if opts.get('all'):
975 if opts.get('all'):
976 base = ['null']
976 base = ['null']
977 else:
977 else:
978 base = scmutil.revrange(repo, opts.get('base'))
978 base = scmutil.revrange(repo, opts.get('base'))
979 if base:
979 if base:
980 if dest:
980 if dest:
981 raise util.Abort(_("--base is incompatible with specifying "
981 raise util.Abort(_("--base is incompatible with specifying "
982 "a destination"))
982 "a destination"))
983 common = [repo.lookup(rev) for rev in base]
983 common = [repo.lookup(rev) for rev in base]
984 heads = revs and map(repo.lookup, revs) or revs
984 heads = revs and map(repo.lookup, revs) or revs
985 cg = repo.getbundle('bundle', heads=heads, common=common)
985 cg = repo.getbundle('bundle', heads=heads, common=common)
986 else:
986 else:
987 dest = ui.expandpath(dest or 'default-push', dest or 'default')
987 dest = ui.expandpath(dest or 'default-push', dest or 'default')
988 dest, branches = hg.parseurl(dest, opts.get('branch'))
988 dest, branches = hg.parseurl(dest, opts.get('branch'))
989 other = hg.peer(repo, opts, dest)
989 other = hg.peer(repo, opts, dest)
990 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
990 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
991 heads = revs and map(repo.lookup, revs) or revs
991 heads = revs and map(repo.lookup, revs) or revs
992 outgoing = discovery.findcommonoutgoing(repo, other,
992 outgoing = discovery.findcommonoutgoing(repo, other,
993 onlyheads=heads,
993 onlyheads=heads,
994 force=opts.get('force'))
994 force=opts.get('force'))
995 cg = repo.getlocalbundle('bundle', outgoing)
995 cg = repo.getlocalbundle('bundle', outgoing)
996 if not cg:
996 if not cg:
997 ui.status(_("no changes found\n"))
997 if 'outgoing' in locals() and outgoing.excluded:
998 repo.ui.status(_("no changes found but %i secret changesets\n")
999 % len(outgoing.excluded))
1000 else:
1001 ui.status(_("no changes found\n"))
998 return 1
1002 return 1
999
1003
1000 bundletype = opts.get('type', 'bzip2').lower()
1004 bundletype = opts.get('type', 'bzip2').lower()
1001 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1005 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1002 bundletype = btypes.get(bundletype)
1006 bundletype = btypes.get(bundletype)
1003 if bundletype not in changegroup.bundletypes:
1007 if bundletype not in changegroup.bundletypes:
1004 raise util.Abort(_('unknown bundle type specified with --type'))
1008 raise util.Abort(_('unknown bundle type specified with --type'))
1005
1009
1006 changegroup.writebundle(cg, fname, bundletype)
1010 changegroup.writebundle(cg, fname, bundletype)
1007
1011
1008 @command('cat',
1012 @command('cat',
1009 [('o', 'output', '',
1013 [('o', 'output', '',
1010 _('print output to file with formatted name'), _('FORMAT')),
1014 _('print output to file with formatted name'), _('FORMAT')),
1011 ('r', 'rev', '', _('print the given revision'), _('REV')),
1015 ('r', 'rev', '', _('print the given revision'), _('REV')),
1012 ('', 'decode', None, _('apply any matching decode filter')),
1016 ('', 'decode', None, _('apply any matching decode filter')),
1013 ] + walkopts,
1017 ] + walkopts,
1014 _('[OPTION]... FILE...'))
1018 _('[OPTION]... FILE...'))
1015 def cat(ui, repo, file1, *pats, **opts):
1019 def cat(ui, repo, file1, *pats, **opts):
1016 """output the current or given revision of files
1020 """output the current or given revision of files
1017
1021
1018 Print the specified files as they were at the given revision. If
1022 Print the specified files as they were at the given revision. If
1019 no revision is given, the parent of the working directory is used,
1023 no revision is given, the parent of the working directory is used,
1020 or tip if no revision is checked out.
1024 or tip if no revision is checked out.
1021
1025
1022 Output may be to a file, in which case the name of the file is
1026 Output may be to a file, in which case the name of the file is
1023 given using a format string. The formatting rules are the same as
1027 given using a format string. The formatting rules are the same as
1024 for the export command, with the following additions:
1028 for the export command, with the following additions:
1025
1029
1026 :``%s``: basename of file being printed
1030 :``%s``: basename of file being printed
1027 :``%d``: dirname of file being printed, or '.' if in repository root
1031 :``%d``: dirname of file being printed, or '.' if in repository root
1028 :``%p``: root-relative path name of file being printed
1032 :``%p``: root-relative path name of file being printed
1029
1033
1030 Returns 0 on success.
1034 Returns 0 on success.
1031 """
1035 """
1032 ctx = scmutil.revsingle(repo, opts.get('rev'))
1036 ctx = scmutil.revsingle(repo, opts.get('rev'))
1033 err = 1
1037 err = 1
1034 m = scmutil.match(ctx, (file1,) + pats, opts)
1038 m = scmutil.match(ctx, (file1,) + pats, opts)
1035 for abs in ctx.walk(m):
1039 for abs in ctx.walk(m):
1036 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1040 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1037 pathname=abs)
1041 pathname=abs)
1038 data = ctx[abs].data()
1042 data = ctx[abs].data()
1039 if opts.get('decode'):
1043 if opts.get('decode'):
1040 data = repo.wwritedata(abs, data)
1044 data = repo.wwritedata(abs, data)
1041 fp.write(data)
1045 fp.write(data)
1042 fp.close()
1046 fp.close()
1043 err = 0
1047 err = 0
1044 return err
1048 return err
1045
1049
1046 @command('^clone',
1050 @command('^clone',
1047 [('U', 'noupdate', None,
1051 [('U', 'noupdate', None,
1048 _('the clone will include an empty working copy (only a repository)')),
1052 _('the clone will include an empty working copy (only a repository)')),
1049 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1053 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1050 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1054 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1051 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1055 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1052 ('', 'pull', None, _('use pull protocol to copy metadata')),
1056 ('', 'pull', None, _('use pull protocol to copy metadata')),
1053 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1057 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1054 ] + remoteopts,
1058 ] + remoteopts,
1055 _('[OPTION]... SOURCE [DEST]'))
1059 _('[OPTION]... SOURCE [DEST]'))
1056 def clone(ui, source, dest=None, **opts):
1060 def clone(ui, source, dest=None, **opts):
1057 """make a copy of an existing repository
1061 """make a copy of an existing repository
1058
1062
1059 Create a copy of an existing repository in a new directory.
1063 Create a copy of an existing repository in a new directory.
1060
1064
1061 If no destination directory name is specified, it defaults to the
1065 If no destination directory name is specified, it defaults to the
1062 basename of the source.
1066 basename of the source.
1063
1067
1064 The location of the source is added to the new repository's
1068 The location of the source is added to the new repository's
1065 ``.hg/hgrc`` file, as the default to be used for future pulls.
1069 ``.hg/hgrc`` file, as the default to be used for future pulls.
1066
1070
1067 Only local paths and ``ssh://`` URLs are supported as
1071 Only local paths and ``ssh://`` URLs are supported as
1068 destinations. For ``ssh://`` destinations, no working directory or
1072 destinations. For ``ssh://`` destinations, no working directory or
1069 ``.hg/hgrc`` will be created on the remote side.
1073 ``.hg/hgrc`` will be created on the remote side.
1070
1074
1071 To pull only a subset of changesets, specify one or more revisions
1075 To pull only a subset of changesets, specify one or more revisions
1072 identifiers with -r/--rev or branches with -b/--branch. The
1076 identifiers with -r/--rev or branches with -b/--branch. The
1073 resulting clone will contain only the specified changesets and
1077 resulting clone will contain only the specified changesets and
1074 their ancestors. These options (or 'clone src#rev dest') imply
1078 their ancestors. These options (or 'clone src#rev dest') imply
1075 --pull, even for local source repositories. Note that specifying a
1079 --pull, even for local source repositories. Note that specifying a
1076 tag will include the tagged changeset but not the changeset
1080 tag will include the tagged changeset but not the changeset
1077 containing the tag.
1081 containing the tag.
1078
1082
1079 To check out a particular version, use -u/--update, or
1083 To check out a particular version, use -u/--update, or
1080 -U/--noupdate to create a clone with no working directory.
1084 -U/--noupdate to create a clone with no working directory.
1081
1085
1082 .. container:: verbose
1086 .. container:: verbose
1083
1087
1084 For efficiency, hardlinks are used for cloning whenever the
1088 For efficiency, hardlinks are used for cloning whenever the
1085 source and destination are on the same filesystem (note this
1089 source and destination are on the same filesystem (note this
1086 applies only to the repository data, not to the working
1090 applies only to the repository data, not to the working
1087 directory). Some filesystems, such as AFS, implement hardlinking
1091 directory). Some filesystems, such as AFS, implement hardlinking
1088 incorrectly, but do not report errors. In these cases, use the
1092 incorrectly, but do not report errors. In these cases, use the
1089 --pull option to avoid hardlinking.
1093 --pull option to avoid hardlinking.
1090
1094
1091 In some cases, you can clone repositories and the working
1095 In some cases, you can clone repositories and the working
1092 directory using full hardlinks with ::
1096 directory using full hardlinks with ::
1093
1097
1094 $ cp -al REPO REPOCLONE
1098 $ cp -al REPO REPOCLONE
1095
1099
1096 This is the fastest way to clone, but it is not always safe. The
1100 This is the fastest way to clone, but it is not always safe. The
1097 operation is not atomic (making sure REPO is not modified during
1101 operation is not atomic (making sure REPO is not modified during
1098 the operation is up to you) and you have to make sure your
1102 the operation is up to you) and you have to make sure your
1099 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1103 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1100 so). Also, this is not compatible with certain extensions that
1104 so). Also, this is not compatible with certain extensions that
1101 place their metadata under the .hg directory, such as mq.
1105 place their metadata under the .hg directory, such as mq.
1102
1106
1103 Mercurial will update the working directory to the first applicable
1107 Mercurial will update the working directory to the first applicable
1104 revision from this list:
1108 revision from this list:
1105
1109
1106 a) null if -U or the source repository has no changesets
1110 a) null if -U or the source repository has no changesets
1107 b) if -u . and the source repository is local, the first parent of
1111 b) if -u . and the source repository is local, the first parent of
1108 the source repository's working directory
1112 the source repository's working directory
1109 c) the changeset specified with -u (if a branch name, this means the
1113 c) the changeset specified with -u (if a branch name, this means the
1110 latest head of that branch)
1114 latest head of that branch)
1111 d) the changeset specified with -r
1115 d) the changeset specified with -r
1112 e) the tipmost head specified with -b
1116 e) the tipmost head specified with -b
1113 f) the tipmost head specified with the url#branch source syntax
1117 f) the tipmost head specified with the url#branch source syntax
1114 g) the tipmost head of the default branch
1118 g) the tipmost head of the default branch
1115 h) tip
1119 h) tip
1116
1120
1117 Examples:
1121 Examples:
1118
1122
1119 - clone a remote repository to a new directory named hg/::
1123 - clone a remote repository to a new directory named hg/::
1120
1124
1121 hg clone http://selenic.com/hg
1125 hg clone http://selenic.com/hg
1122
1126
1123 - create a lightweight local clone::
1127 - create a lightweight local clone::
1124
1128
1125 hg clone project/ project-feature/
1129 hg clone project/ project-feature/
1126
1130
1127 - clone from an absolute path on an ssh server (note double-slash)::
1131 - clone from an absolute path on an ssh server (note double-slash)::
1128
1132
1129 hg clone ssh://user@server//home/projects/alpha/
1133 hg clone ssh://user@server//home/projects/alpha/
1130
1134
1131 - do a high-speed clone over a LAN while checking out a
1135 - do a high-speed clone over a LAN while checking out a
1132 specified version::
1136 specified version::
1133
1137
1134 hg clone --uncompressed http://server/repo -u 1.5
1138 hg clone --uncompressed http://server/repo -u 1.5
1135
1139
1136 - create a repository without changesets after a particular revision::
1140 - create a repository without changesets after a particular revision::
1137
1141
1138 hg clone -r 04e544 experimental/ good/
1142 hg clone -r 04e544 experimental/ good/
1139
1143
1140 - clone (and track) a particular named branch::
1144 - clone (and track) a particular named branch::
1141
1145
1142 hg clone http://selenic.com/hg#stable
1146 hg clone http://selenic.com/hg#stable
1143
1147
1144 See :hg:`help urls` for details on specifying URLs.
1148 See :hg:`help urls` for details on specifying URLs.
1145
1149
1146 Returns 0 on success.
1150 Returns 0 on success.
1147 """
1151 """
1148 if opts.get('noupdate') and opts.get('updaterev'):
1152 if opts.get('noupdate') and opts.get('updaterev'):
1149 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1153 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1150
1154
1151 r = hg.clone(ui, opts, source, dest,
1155 r = hg.clone(ui, opts, source, dest,
1152 pull=opts.get('pull'),
1156 pull=opts.get('pull'),
1153 stream=opts.get('uncompressed'),
1157 stream=opts.get('uncompressed'),
1154 rev=opts.get('rev'),
1158 rev=opts.get('rev'),
1155 update=opts.get('updaterev') or not opts.get('noupdate'),
1159 update=opts.get('updaterev') or not opts.get('noupdate'),
1156 branch=opts.get('branch'))
1160 branch=opts.get('branch'))
1157
1161
1158 return r is None
1162 return r is None
1159
1163
1160 @command('^commit|ci',
1164 @command('^commit|ci',
1161 [('A', 'addremove', None,
1165 [('A', 'addremove', None,
1162 _('mark new/missing files as added/removed before committing')),
1166 _('mark new/missing files as added/removed before committing')),
1163 ('', 'close-branch', None,
1167 ('', 'close-branch', None,
1164 _('mark a branch as closed, hiding it from the branch list')),
1168 _('mark a branch as closed, hiding it from the branch list')),
1165 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1169 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1166 _('[OPTION]... [FILE]...'))
1170 _('[OPTION]... [FILE]...'))
1167 def commit(ui, repo, *pats, **opts):
1171 def commit(ui, repo, *pats, **opts):
1168 """commit the specified files or all outstanding changes
1172 """commit the specified files or all outstanding changes
1169
1173
1170 Commit changes to the given files into the repository. Unlike a
1174 Commit changes to the given files into the repository. Unlike a
1171 centralized SCM, this operation is a local operation. See
1175 centralized SCM, this operation is a local operation. See
1172 :hg:`push` for a way to actively distribute your changes.
1176 :hg:`push` for a way to actively distribute your changes.
1173
1177
1174 If a list of files is omitted, all changes reported by :hg:`status`
1178 If a list of files is omitted, all changes reported by :hg:`status`
1175 will be committed.
1179 will be committed.
1176
1180
1177 If you are committing the result of a merge, do not provide any
1181 If you are committing the result of a merge, do not provide any
1178 filenames or -I/-X filters.
1182 filenames or -I/-X filters.
1179
1183
1180 If no commit message is specified, Mercurial starts your
1184 If no commit message is specified, Mercurial starts your
1181 configured editor where you can enter a message. In case your
1185 configured editor where you can enter a message. In case your
1182 commit fails, you will find a backup of your message in
1186 commit fails, you will find a backup of your message in
1183 ``.hg/last-message.txt``.
1187 ``.hg/last-message.txt``.
1184
1188
1185 See :hg:`help dates` for a list of formats valid for -d/--date.
1189 See :hg:`help dates` for a list of formats valid for -d/--date.
1186
1190
1187 Returns 0 on success, 1 if nothing changed.
1191 Returns 0 on success, 1 if nothing changed.
1188 """
1192 """
1189 if opts.get('subrepos'):
1193 if opts.get('subrepos'):
1190 # Let --subrepos on the command line overide config setting.
1194 # Let --subrepos on the command line overide config setting.
1191 ui.setconfig('ui', 'commitsubrepos', True)
1195 ui.setconfig('ui', 'commitsubrepos', True)
1192
1196
1193 extra = {}
1197 extra = {}
1194 if opts.get('close_branch'):
1198 if opts.get('close_branch'):
1195 if repo['.'].node() not in repo.branchheads():
1199 if repo['.'].node() not in repo.branchheads():
1196 # The topo heads set is included in the branch heads set of the
1200 # The topo heads set is included in the branch heads set of the
1197 # current branch, so it's sufficient to test branchheads
1201 # current branch, so it's sufficient to test branchheads
1198 raise util.Abort(_('can only close branch heads'))
1202 raise util.Abort(_('can only close branch heads'))
1199 extra['close'] = 1
1203 extra['close'] = 1
1200 e = cmdutil.commiteditor
1204 e = cmdutil.commiteditor
1201 if opts.get('force_editor'):
1205 if opts.get('force_editor'):
1202 e = cmdutil.commitforceeditor
1206 e = cmdutil.commitforceeditor
1203
1207
1204 def commitfunc(ui, repo, message, match, opts):
1208 def commitfunc(ui, repo, message, match, opts):
1205 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1209 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1206 editor=e, extra=extra)
1210 editor=e, extra=extra)
1207
1211
1208 branch = repo[None].branch()
1212 branch = repo[None].branch()
1209 bheads = repo.branchheads(branch)
1213 bheads = repo.branchheads(branch)
1210
1214
1211 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1215 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1212 if not node:
1216 if not node:
1213 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1217 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1214 if stat[3]:
1218 if stat[3]:
1215 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1219 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1216 % len(stat[3]))
1220 % len(stat[3]))
1217 else:
1221 else:
1218 ui.status(_("nothing changed\n"))
1222 ui.status(_("nothing changed\n"))
1219 return 1
1223 return 1
1220
1224
1221 ctx = repo[node]
1225 ctx = repo[node]
1222 parents = ctx.parents()
1226 parents = ctx.parents()
1223
1227
1224 if (bheads and node not in bheads and not
1228 if (bheads and node not in bheads and not
1225 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1229 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1226 ui.status(_('created new head\n'))
1230 ui.status(_('created new head\n'))
1227 # The message is not printed for initial roots. For the other
1231 # The message is not printed for initial roots. For the other
1228 # changesets, it is printed in the following situations:
1232 # changesets, it is printed in the following situations:
1229 #
1233 #
1230 # Par column: for the 2 parents with ...
1234 # Par column: for the 2 parents with ...
1231 # N: null or no parent
1235 # N: null or no parent
1232 # B: parent is on another named branch
1236 # B: parent is on another named branch
1233 # C: parent is a regular non head changeset
1237 # C: parent is a regular non head changeset
1234 # H: parent was a branch head of the current branch
1238 # H: parent was a branch head of the current branch
1235 # Msg column: whether we print "created new head" message
1239 # Msg column: whether we print "created new head" message
1236 # In the following, it is assumed that there already exists some
1240 # In the following, it is assumed that there already exists some
1237 # initial branch heads of the current branch, otherwise nothing is
1241 # initial branch heads of the current branch, otherwise nothing is
1238 # printed anyway.
1242 # printed anyway.
1239 #
1243 #
1240 # Par Msg Comment
1244 # Par Msg Comment
1241 # NN y additional topo root
1245 # NN y additional topo root
1242 #
1246 #
1243 # BN y additional branch root
1247 # BN y additional branch root
1244 # CN y additional topo head
1248 # CN y additional topo head
1245 # HN n usual case
1249 # HN n usual case
1246 #
1250 #
1247 # BB y weird additional branch root
1251 # BB y weird additional branch root
1248 # CB y branch merge
1252 # CB y branch merge
1249 # HB n merge with named branch
1253 # HB n merge with named branch
1250 #
1254 #
1251 # CC y additional head from merge
1255 # CC y additional head from merge
1252 # CH n merge with a head
1256 # CH n merge with a head
1253 #
1257 #
1254 # HH n head merge: head count decreases
1258 # HH n head merge: head count decreases
1255
1259
1256 if not opts.get('close_branch'):
1260 if not opts.get('close_branch'):
1257 for r in parents:
1261 for r in parents:
1258 if r.extra().get('close') and r.branch() == branch:
1262 if r.extra().get('close') and r.branch() == branch:
1259 ui.status(_('reopening closed branch head %d\n') % r)
1263 ui.status(_('reopening closed branch head %d\n') % r)
1260
1264
1261 if ui.debugflag:
1265 if ui.debugflag:
1262 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1266 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1263 elif ui.verbose:
1267 elif ui.verbose:
1264 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1268 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1265
1269
1266 @command('copy|cp',
1270 @command('copy|cp',
1267 [('A', 'after', None, _('record a copy that has already occurred')),
1271 [('A', 'after', None, _('record a copy that has already occurred')),
1268 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1272 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1269 ] + walkopts + dryrunopts,
1273 ] + walkopts + dryrunopts,
1270 _('[OPTION]... [SOURCE]... DEST'))
1274 _('[OPTION]... [SOURCE]... DEST'))
1271 def copy(ui, repo, *pats, **opts):
1275 def copy(ui, repo, *pats, **opts):
1272 """mark files as copied for the next commit
1276 """mark files as copied for the next commit
1273
1277
1274 Mark dest as having copies of source files. If dest is a
1278 Mark dest as having copies of source files. If dest is a
1275 directory, copies are put in that directory. If dest is a file,
1279 directory, copies are put in that directory. If dest is a file,
1276 the source must be a single file.
1280 the source must be a single file.
1277
1281
1278 By default, this command copies the contents of files as they
1282 By default, this command copies the contents of files as they
1279 exist in the working directory. If invoked with -A/--after, the
1283 exist in the working directory. If invoked with -A/--after, the
1280 operation is recorded, but no copying is performed.
1284 operation is recorded, but no copying is performed.
1281
1285
1282 This command takes effect with the next commit. To undo a copy
1286 This command takes effect with the next commit. To undo a copy
1283 before that, see :hg:`revert`.
1287 before that, see :hg:`revert`.
1284
1288
1285 Returns 0 on success, 1 if errors are encountered.
1289 Returns 0 on success, 1 if errors are encountered.
1286 """
1290 """
1287 wlock = repo.wlock(False)
1291 wlock = repo.wlock(False)
1288 try:
1292 try:
1289 return cmdutil.copy(ui, repo, pats, opts)
1293 return cmdutil.copy(ui, repo, pats, opts)
1290 finally:
1294 finally:
1291 wlock.release()
1295 wlock.release()
1292
1296
1293 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1297 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1294 def debugancestor(ui, repo, *args):
1298 def debugancestor(ui, repo, *args):
1295 """find the ancestor revision of two revisions in a given index"""
1299 """find the ancestor revision of two revisions in a given index"""
1296 if len(args) == 3:
1300 if len(args) == 3:
1297 index, rev1, rev2 = args
1301 index, rev1, rev2 = args
1298 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1302 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1299 lookup = r.lookup
1303 lookup = r.lookup
1300 elif len(args) == 2:
1304 elif len(args) == 2:
1301 if not repo:
1305 if not repo:
1302 raise util.Abort(_("there is no Mercurial repository here "
1306 raise util.Abort(_("there is no Mercurial repository here "
1303 "(.hg not found)"))
1307 "(.hg not found)"))
1304 rev1, rev2 = args
1308 rev1, rev2 = args
1305 r = repo.changelog
1309 r = repo.changelog
1306 lookup = repo.lookup
1310 lookup = repo.lookup
1307 else:
1311 else:
1308 raise util.Abort(_('either two or three arguments required'))
1312 raise util.Abort(_('either two or three arguments required'))
1309 a = r.ancestor(lookup(rev1), lookup(rev2))
1313 a = r.ancestor(lookup(rev1), lookup(rev2))
1310 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1314 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1311
1315
1312 @command('debugbuilddag',
1316 @command('debugbuilddag',
1313 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1317 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1314 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1318 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1315 ('n', 'new-file', None, _('add new file at each rev'))],
1319 ('n', 'new-file', None, _('add new file at each rev'))],
1316 _('[OPTION]... [TEXT]'))
1320 _('[OPTION]... [TEXT]'))
1317 def debugbuilddag(ui, repo, text=None,
1321 def debugbuilddag(ui, repo, text=None,
1318 mergeable_file=False,
1322 mergeable_file=False,
1319 overwritten_file=False,
1323 overwritten_file=False,
1320 new_file=False):
1324 new_file=False):
1321 """builds a repo with a given DAG from scratch in the current empty repo
1325 """builds a repo with a given DAG from scratch in the current empty repo
1322
1326
1323 The description of the DAG is read from stdin if not given on the
1327 The description of the DAG is read from stdin if not given on the
1324 command line.
1328 command line.
1325
1329
1326 Elements:
1330 Elements:
1327
1331
1328 - "+n" is a linear run of n nodes based on the current default parent
1332 - "+n" is a linear run of n nodes based on the current default parent
1329 - "." is a single node based on the current default parent
1333 - "." is a single node based on the current default parent
1330 - "$" resets the default parent to null (implied at the start);
1334 - "$" resets the default parent to null (implied at the start);
1331 otherwise the default parent is always the last node created
1335 otherwise the default parent is always the last node created
1332 - "<p" sets the default parent to the backref p
1336 - "<p" sets the default parent to the backref p
1333 - "*p" is a fork at parent p, which is a backref
1337 - "*p" is a fork at parent p, which is a backref
1334 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1338 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1335 - "/p2" is a merge of the preceding node and p2
1339 - "/p2" is a merge of the preceding node and p2
1336 - ":tag" defines a local tag for the preceding node
1340 - ":tag" defines a local tag for the preceding node
1337 - "@branch" sets the named branch for subsequent nodes
1341 - "@branch" sets the named branch for subsequent nodes
1338 - "#...\\n" is a comment up to the end of the line
1342 - "#...\\n" is a comment up to the end of the line
1339
1343
1340 Whitespace between the above elements is ignored.
1344 Whitespace between the above elements is ignored.
1341
1345
1342 A backref is either
1346 A backref is either
1343
1347
1344 - a number n, which references the node curr-n, where curr is the current
1348 - a number n, which references the node curr-n, where curr is the current
1345 node, or
1349 node, or
1346 - the name of a local tag you placed earlier using ":tag", or
1350 - the name of a local tag you placed earlier using ":tag", or
1347 - empty to denote the default parent.
1351 - empty to denote the default parent.
1348
1352
1349 All string valued-elements are either strictly alphanumeric, or must
1353 All string valued-elements are either strictly alphanumeric, or must
1350 be enclosed in double quotes ("..."), with "\\" as escape character.
1354 be enclosed in double quotes ("..."), with "\\" as escape character.
1351 """
1355 """
1352
1356
1353 if text is None:
1357 if text is None:
1354 ui.status(_("reading DAG from stdin\n"))
1358 ui.status(_("reading DAG from stdin\n"))
1355 text = ui.fin.read()
1359 text = ui.fin.read()
1356
1360
1357 cl = repo.changelog
1361 cl = repo.changelog
1358 if len(cl) > 0:
1362 if len(cl) > 0:
1359 raise util.Abort(_('repository is not empty'))
1363 raise util.Abort(_('repository is not empty'))
1360
1364
1361 # determine number of revs in DAG
1365 # determine number of revs in DAG
1362 total = 0
1366 total = 0
1363 for type, data in dagparser.parsedag(text):
1367 for type, data in dagparser.parsedag(text):
1364 if type == 'n':
1368 if type == 'n':
1365 total += 1
1369 total += 1
1366
1370
1367 if mergeable_file:
1371 if mergeable_file:
1368 linesperrev = 2
1372 linesperrev = 2
1369 # make a file with k lines per rev
1373 # make a file with k lines per rev
1370 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1374 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1371 initialmergedlines.append("")
1375 initialmergedlines.append("")
1372
1376
1373 tags = []
1377 tags = []
1374
1378
1375 lock = tr = None
1379 lock = tr = None
1376 try:
1380 try:
1377 lock = repo.lock()
1381 lock = repo.lock()
1378 tr = repo.transaction("builddag")
1382 tr = repo.transaction("builddag")
1379
1383
1380 at = -1
1384 at = -1
1381 atbranch = 'default'
1385 atbranch = 'default'
1382 nodeids = []
1386 nodeids = []
1383 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1387 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1384 for type, data in dagparser.parsedag(text):
1388 for type, data in dagparser.parsedag(text):
1385 if type == 'n':
1389 if type == 'n':
1386 ui.note('node %s\n' % str(data))
1390 ui.note('node %s\n' % str(data))
1387 id, ps = data
1391 id, ps = data
1388
1392
1389 files = []
1393 files = []
1390 fctxs = {}
1394 fctxs = {}
1391
1395
1392 p2 = None
1396 p2 = None
1393 if mergeable_file:
1397 if mergeable_file:
1394 fn = "mf"
1398 fn = "mf"
1395 p1 = repo[ps[0]]
1399 p1 = repo[ps[0]]
1396 if len(ps) > 1:
1400 if len(ps) > 1:
1397 p2 = repo[ps[1]]
1401 p2 = repo[ps[1]]
1398 pa = p1.ancestor(p2)
1402 pa = p1.ancestor(p2)
1399 base, local, other = [x[fn].data() for x in pa, p1, p2]
1403 base, local, other = [x[fn].data() for x in pa, p1, p2]
1400 m3 = simplemerge.Merge3Text(base, local, other)
1404 m3 = simplemerge.Merge3Text(base, local, other)
1401 ml = [l.strip() for l in m3.merge_lines()]
1405 ml = [l.strip() for l in m3.merge_lines()]
1402 ml.append("")
1406 ml.append("")
1403 elif at > 0:
1407 elif at > 0:
1404 ml = p1[fn].data().split("\n")
1408 ml = p1[fn].data().split("\n")
1405 else:
1409 else:
1406 ml = initialmergedlines
1410 ml = initialmergedlines
1407 ml[id * linesperrev] += " r%i" % id
1411 ml[id * linesperrev] += " r%i" % id
1408 mergedtext = "\n".join(ml)
1412 mergedtext = "\n".join(ml)
1409 files.append(fn)
1413 files.append(fn)
1410 fctxs[fn] = context.memfilectx(fn, mergedtext)
1414 fctxs[fn] = context.memfilectx(fn, mergedtext)
1411
1415
1412 if overwritten_file:
1416 if overwritten_file:
1413 fn = "of"
1417 fn = "of"
1414 files.append(fn)
1418 files.append(fn)
1415 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1419 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1416
1420
1417 if new_file:
1421 if new_file:
1418 fn = "nf%i" % id
1422 fn = "nf%i" % id
1419 files.append(fn)
1423 files.append(fn)
1420 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1424 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1421 if len(ps) > 1:
1425 if len(ps) > 1:
1422 if not p2:
1426 if not p2:
1423 p2 = repo[ps[1]]
1427 p2 = repo[ps[1]]
1424 for fn in p2:
1428 for fn in p2:
1425 if fn.startswith("nf"):
1429 if fn.startswith("nf"):
1426 files.append(fn)
1430 files.append(fn)
1427 fctxs[fn] = p2[fn]
1431 fctxs[fn] = p2[fn]
1428
1432
1429 def fctxfn(repo, cx, path):
1433 def fctxfn(repo, cx, path):
1430 return fctxs.get(path)
1434 return fctxs.get(path)
1431
1435
1432 if len(ps) == 0 or ps[0] < 0:
1436 if len(ps) == 0 or ps[0] < 0:
1433 pars = [None, None]
1437 pars = [None, None]
1434 elif len(ps) == 1:
1438 elif len(ps) == 1:
1435 pars = [nodeids[ps[0]], None]
1439 pars = [nodeids[ps[0]], None]
1436 else:
1440 else:
1437 pars = [nodeids[p] for p in ps]
1441 pars = [nodeids[p] for p in ps]
1438 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1442 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1439 date=(id, 0),
1443 date=(id, 0),
1440 user="debugbuilddag",
1444 user="debugbuilddag",
1441 extra={'branch': atbranch})
1445 extra={'branch': atbranch})
1442 nodeid = repo.commitctx(cx)
1446 nodeid = repo.commitctx(cx)
1443 nodeids.append(nodeid)
1447 nodeids.append(nodeid)
1444 at = id
1448 at = id
1445 elif type == 'l':
1449 elif type == 'l':
1446 id, name = data
1450 id, name = data
1447 ui.note('tag %s\n' % name)
1451 ui.note('tag %s\n' % name)
1448 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1452 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1449 elif type == 'a':
1453 elif type == 'a':
1450 ui.note('branch %s\n' % data)
1454 ui.note('branch %s\n' % data)
1451 atbranch = data
1455 atbranch = data
1452 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1456 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1453 tr.close()
1457 tr.close()
1454
1458
1455 if tags:
1459 if tags:
1456 repo.opener.write("localtags", "".join(tags))
1460 repo.opener.write("localtags", "".join(tags))
1457 finally:
1461 finally:
1458 ui.progress(_('building'), None)
1462 ui.progress(_('building'), None)
1459 release(tr, lock)
1463 release(tr, lock)
1460
1464
1461 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1465 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1462 def debugbundle(ui, bundlepath, all=None, **opts):
1466 def debugbundle(ui, bundlepath, all=None, **opts):
1463 """lists the contents of a bundle"""
1467 """lists the contents of a bundle"""
1464 f = url.open(ui, bundlepath)
1468 f = url.open(ui, bundlepath)
1465 try:
1469 try:
1466 gen = changegroup.readbundle(f, bundlepath)
1470 gen = changegroup.readbundle(f, bundlepath)
1467 if all:
1471 if all:
1468 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1472 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1469
1473
1470 def showchunks(named):
1474 def showchunks(named):
1471 ui.write("\n%s\n" % named)
1475 ui.write("\n%s\n" % named)
1472 chain = None
1476 chain = None
1473 while True:
1477 while True:
1474 chunkdata = gen.deltachunk(chain)
1478 chunkdata = gen.deltachunk(chain)
1475 if not chunkdata:
1479 if not chunkdata:
1476 break
1480 break
1477 node = chunkdata['node']
1481 node = chunkdata['node']
1478 p1 = chunkdata['p1']
1482 p1 = chunkdata['p1']
1479 p2 = chunkdata['p2']
1483 p2 = chunkdata['p2']
1480 cs = chunkdata['cs']
1484 cs = chunkdata['cs']
1481 deltabase = chunkdata['deltabase']
1485 deltabase = chunkdata['deltabase']
1482 delta = chunkdata['delta']
1486 delta = chunkdata['delta']
1483 ui.write("%s %s %s %s %s %s\n" %
1487 ui.write("%s %s %s %s %s %s\n" %
1484 (hex(node), hex(p1), hex(p2),
1488 (hex(node), hex(p1), hex(p2),
1485 hex(cs), hex(deltabase), len(delta)))
1489 hex(cs), hex(deltabase), len(delta)))
1486 chain = node
1490 chain = node
1487
1491
1488 chunkdata = gen.changelogheader()
1492 chunkdata = gen.changelogheader()
1489 showchunks("changelog")
1493 showchunks("changelog")
1490 chunkdata = gen.manifestheader()
1494 chunkdata = gen.manifestheader()
1491 showchunks("manifest")
1495 showchunks("manifest")
1492 while True:
1496 while True:
1493 chunkdata = gen.filelogheader()
1497 chunkdata = gen.filelogheader()
1494 if not chunkdata:
1498 if not chunkdata:
1495 break
1499 break
1496 fname = chunkdata['filename']
1500 fname = chunkdata['filename']
1497 showchunks(fname)
1501 showchunks(fname)
1498 else:
1502 else:
1499 chunkdata = gen.changelogheader()
1503 chunkdata = gen.changelogheader()
1500 chain = None
1504 chain = None
1501 while True:
1505 while True:
1502 chunkdata = gen.deltachunk(chain)
1506 chunkdata = gen.deltachunk(chain)
1503 if not chunkdata:
1507 if not chunkdata:
1504 break
1508 break
1505 node = chunkdata['node']
1509 node = chunkdata['node']
1506 ui.write("%s\n" % hex(node))
1510 ui.write("%s\n" % hex(node))
1507 chain = node
1511 chain = node
1508 finally:
1512 finally:
1509 f.close()
1513 f.close()
1510
1514
1511 @command('debugcheckstate', [], '')
1515 @command('debugcheckstate', [], '')
1512 def debugcheckstate(ui, repo):
1516 def debugcheckstate(ui, repo):
1513 """validate the correctness of the current dirstate"""
1517 """validate the correctness of the current dirstate"""
1514 parent1, parent2 = repo.dirstate.parents()
1518 parent1, parent2 = repo.dirstate.parents()
1515 m1 = repo[parent1].manifest()
1519 m1 = repo[parent1].manifest()
1516 m2 = repo[parent2].manifest()
1520 m2 = repo[parent2].manifest()
1517 errors = 0
1521 errors = 0
1518 for f in repo.dirstate:
1522 for f in repo.dirstate:
1519 state = repo.dirstate[f]
1523 state = repo.dirstate[f]
1520 if state in "nr" and f not in m1:
1524 if state in "nr" and f not in m1:
1521 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1525 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1522 errors += 1
1526 errors += 1
1523 if state in "a" and f in m1:
1527 if state in "a" and f in m1:
1524 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1528 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1525 errors += 1
1529 errors += 1
1526 if state in "m" and f not in m1 and f not in m2:
1530 if state in "m" and f not in m1 and f not in m2:
1527 ui.warn(_("%s in state %s, but not in either manifest\n") %
1531 ui.warn(_("%s in state %s, but not in either manifest\n") %
1528 (f, state))
1532 (f, state))
1529 errors += 1
1533 errors += 1
1530 for f in m1:
1534 for f in m1:
1531 state = repo.dirstate[f]
1535 state = repo.dirstate[f]
1532 if state not in "nrm":
1536 if state not in "nrm":
1533 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1537 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1534 errors += 1
1538 errors += 1
1535 if errors:
1539 if errors:
1536 error = _(".hg/dirstate inconsistent with current parent's manifest")
1540 error = _(".hg/dirstate inconsistent with current parent's manifest")
1537 raise util.Abort(error)
1541 raise util.Abort(error)
1538
1542
1539 @command('debugcommands', [], _('[COMMAND]'))
1543 @command('debugcommands', [], _('[COMMAND]'))
1540 def debugcommands(ui, cmd='', *args):
1544 def debugcommands(ui, cmd='', *args):
1541 """list all available commands and options"""
1545 """list all available commands and options"""
1542 for cmd, vals in sorted(table.iteritems()):
1546 for cmd, vals in sorted(table.iteritems()):
1543 cmd = cmd.split('|')[0].strip('^')
1547 cmd = cmd.split('|')[0].strip('^')
1544 opts = ', '.join([i[1] for i in vals[1]])
1548 opts = ', '.join([i[1] for i in vals[1]])
1545 ui.write('%s: %s\n' % (cmd, opts))
1549 ui.write('%s: %s\n' % (cmd, opts))
1546
1550
1547 @command('debugcomplete',
1551 @command('debugcomplete',
1548 [('o', 'options', None, _('show the command options'))],
1552 [('o', 'options', None, _('show the command options'))],
1549 _('[-o] CMD'))
1553 _('[-o] CMD'))
1550 def debugcomplete(ui, cmd='', **opts):
1554 def debugcomplete(ui, cmd='', **opts):
1551 """returns the completion list associated with the given command"""
1555 """returns the completion list associated with the given command"""
1552
1556
1553 if opts.get('options'):
1557 if opts.get('options'):
1554 options = []
1558 options = []
1555 otables = [globalopts]
1559 otables = [globalopts]
1556 if cmd:
1560 if cmd:
1557 aliases, entry = cmdutil.findcmd(cmd, table, False)
1561 aliases, entry = cmdutil.findcmd(cmd, table, False)
1558 otables.append(entry[1])
1562 otables.append(entry[1])
1559 for t in otables:
1563 for t in otables:
1560 for o in t:
1564 for o in t:
1561 if "(DEPRECATED)" in o[3]:
1565 if "(DEPRECATED)" in o[3]:
1562 continue
1566 continue
1563 if o[0]:
1567 if o[0]:
1564 options.append('-%s' % o[0])
1568 options.append('-%s' % o[0])
1565 options.append('--%s' % o[1])
1569 options.append('--%s' % o[1])
1566 ui.write("%s\n" % "\n".join(options))
1570 ui.write("%s\n" % "\n".join(options))
1567 return
1571 return
1568
1572
1569 cmdlist = cmdutil.findpossible(cmd, table)
1573 cmdlist = cmdutil.findpossible(cmd, table)
1570 if ui.verbose:
1574 if ui.verbose:
1571 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1575 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1572 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1576 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1573
1577
1574 @command('debugdag',
1578 @command('debugdag',
1575 [('t', 'tags', None, _('use tags as labels')),
1579 [('t', 'tags', None, _('use tags as labels')),
1576 ('b', 'branches', None, _('annotate with branch names')),
1580 ('b', 'branches', None, _('annotate with branch names')),
1577 ('', 'dots', None, _('use dots for runs')),
1581 ('', 'dots', None, _('use dots for runs')),
1578 ('s', 'spaces', None, _('separate elements by spaces'))],
1582 ('s', 'spaces', None, _('separate elements by spaces'))],
1579 _('[OPTION]... [FILE [REV]...]'))
1583 _('[OPTION]... [FILE [REV]...]'))
1580 def debugdag(ui, repo, file_=None, *revs, **opts):
1584 def debugdag(ui, repo, file_=None, *revs, **opts):
1581 """format the changelog or an index DAG as a concise textual description
1585 """format the changelog or an index DAG as a concise textual description
1582
1586
1583 If you pass a revlog index, the revlog's DAG is emitted. If you list
1587 If you pass a revlog index, the revlog's DAG is emitted. If you list
1584 revision numbers, they get labelled in the output as rN.
1588 revision numbers, they get labelled in the output as rN.
1585
1589
1586 Otherwise, the changelog DAG of the current repo is emitted.
1590 Otherwise, the changelog DAG of the current repo is emitted.
1587 """
1591 """
1588 spaces = opts.get('spaces')
1592 spaces = opts.get('spaces')
1589 dots = opts.get('dots')
1593 dots = opts.get('dots')
1590 if file_:
1594 if file_:
1591 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1595 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1592 revs = set((int(r) for r in revs))
1596 revs = set((int(r) for r in revs))
1593 def events():
1597 def events():
1594 for r in rlog:
1598 for r in rlog:
1595 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1599 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1596 if r in revs:
1600 if r in revs:
1597 yield 'l', (r, "r%i" % r)
1601 yield 'l', (r, "r%i" % r)
1598 elif repo:
1602 elif repo:
1599 cl = repo.changelog
1603 cl = repo.changelog
1600 tags = opts.get('tags')
1604 tags = opts.get('tags')
1601 branches = opts.get('branches')
1605 branches = opts.get('branches')
1602 if tags:
1606 if tags:
1603 labels = {}
1607 labels = {}
1604 for l, n in repo.tags().items():
1608 for l, n in repo.tags().items():
1605 labels.setdefault(cl.rev(n), []).append(l)
1609 labels.setdefault(cl.rev(n), []).append(l)
1606 def events():
1610 def events():
1607 b = "default"
1611 b = "default"
1608 for r in cl:
1612 for r in cl:
1609 if branches:
1613 if branches:
1610 newb = cl.read(cl.node(r))[5]['branch']
1614 newb = cl.read(cl.node(r))[5]['branch']
1611 if newb != b:
1615 if newb != b:
1612 yield 'a', newb
1616 yield 'a', newb
1613 b = newb
1617 b = newb
1614 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1618 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1615 if tags:
1619 if tags:
1616 ls = labels.get(r)
1620 ls = labels.get(r)
1617 if ls:
1621 if ls:
1618 for l in ls:
1622 for l in ls:
1619 yield 'l', (r, l)
1623 yield 'l', (r, l)
1620 else:
1624 else:
1621 raise util.Abort(_('need repo for changelog dag'))
1625 raise util.Abort(_('need repo for changelog dag'))
1622
1626
1623 for line in dagparser.dagtextlines(events(),
1627 for line in dagparser.dagtextlines(events(),
1624 addspaces=spaces,
1628 addspaces=spaces,
1625 wraplabels=True,
1629 wraplabels=True,
1626 wrapannotations=True,
1630 wrapannotations=True,
1627 wrapnonlinear=dots,
1631 wrapnonlinear=dots,
1628 usedots=dots,
1632 usedots=dots,
1629 maxlinewidth=70):
1633 maxlinewidth=70):
1630 ui.write(line)
1634 ui.write(line)
1631 ui.write("\n")
1635 ui.write("\n")
1632
1636
1633 @command('debugdata',
1637 @command('debugdata',
1634 [('c', 'changelog', False, _('open changelog')),
1638 [('c', 'changelog', False, _('open changelog')),
1635 ('m', 'manifest', False, _('open manifest'))],
1639 ('m', 'manifest', False, _('open manifest'))],
1636 _('-c|-m|FILE REV'))
1640 _('-c|-m|FILE REV'))
1637 def debugdata(ui, repo, file_, rev = None, **opts):
1641 def debugdata(ui, repo, file_, rev = None, **opts):
1638 """dump the contents of a data file revision"""
1642 """dump the contents of a data file revision"""
1639 if opts.get('changelog') or opts.get('manifest'):
1643 if opts.get('changelog') or opts.get('manifest'):
1640 file_, rev = None, file_
1644 file_, rev = None, file_
1641 elif rev is None:
1645 elif rev is None:
1642 raise error.CommandError('debugdata', _('invalid arguments'))
1646 raise error.CommandError('debugdata', _('invalid arguments'))
1643 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1647 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1644 try:
1648 try:
1645 ui.write(r.revision(r.lookup(rev)))
1649 ui.write(r.revision(r.lookup(rev)))
1646 except KeyError:
1650 except KeyError:
1647 raise util.Abort(_('invalid revision identifier %s') % rev)
1651 raise util.Abort(_('invalid revision identifier %s') % rev)
1648
1652
1649 @command('debugdate',
1653 @command('debugdate',
1650 [('e', 'extended', None, _('try extended date formats'))],
1654 [('e', 'extended', None, _('try extended date formats'))],
1651 _('[-e] DATE [RANGE]'))
1655 _('[-e] DATE [RANGE]'))
1652 def debugdate(ui, date, range=None, **opts):
1656 def debugdate(ui, date, range=None, **opts):
1653 """parse and display a date"""
1657 """parse and display a date"""
1654 if opts["extended"]:
1658 if opts["extended"]:
1655 d = util.parsedate(date, util.extendeddateformats)
1659 d = util.parsedate(date, util.extendeddateformats)
1656 else:
1660 else:
1657 d = util.parsedate(date)
1661 d = util.parsedate(date)
1658 ui.write("internal: %s %s\n" % d)
1662 ui.write("internal: %s %s\n" % d)
1659 ui.write("standard: %s\n" % util.datestr(d))
1663 ui.write("standard: %s\n" % util.datestr(d))
1660 if range:
1664 if range:
1661 m = util.matchdate(range)
1665 m = util.matchdate(range)
1662 ui.write("match: %s\n" % m(d[0]))
1666 ui.write("match: %s\n" % m(d[0]))
1663
1667
1664 @command('debugdiscovery',
1668 @command('debugdiscovery',
1665 [('', 'old', None, _('use old-style discovery')),
1669 [('', 'old', None, _('use old-style discovery')),
1666 ('', 'nonheads', None,
1670 ('', 'nonheads', None,
1667 _('use old-style discovery with non-heads included')),
1671 _('use old-style discovery with non-heads included')),
1668 ] + remoteopts,
1672 ] + remoteopts,
1669 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1673 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1670 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1674 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1671 """runs the changeset discovery protocol in isolation"""
1675 """runs the changeset discovery protocol in isolation"""
1672 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1676 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1673 remote = hg.peer(repo, opts, remoteurl)
1677 remote = hg.peer(repo, opts, remoteurl)
1674 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1678 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1675
1679
1676 # make sure tests are repeatable
1680 # make sure tests are repeatable
1677 random.seed(12323)
1681 random.seed(12323)
1678
1682
1679 def doit(localheads, remoteheads):
1683 def doit(localheads, remoteheads):
1680 if opts.get('old'):
1684 if opts.get('old'):
1681 if localheads:
1685 if localheads:
1682 raise util.Abort('cannot use localheads with old style discovery')
1686 raise util.Abort('cannot use localheads with old style discovery')
1683 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1687 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1684 force=True)
1688 force=True)
1685 common = set(common)
1689 common = set(common)
1686 if not opts.get('nonheads'):
1690 if not opts.get('nonheads'):
1687 ui.write("unpruned common: %s\n" % " ".join([short(n)
1691 ui.write("unpruned common: %s\n" % " ".join([short(n)
1688 for n in common]))
1692 for n in common]))
1689 dag = dagutil.revlogdag(repo.changelog)
1693 dag = dagutil.revlogdag(repo.changelog)
1690 all = dag.ancestorset(dag.internalizeall(common))
1694 all = dag.ancestorset(dag.internalizeall(common))
1691 common = dag.externalizeall(dag.headsetofconnecteds(all))
1695 common = dag.externalizeall(dag.headsetofconnecteds(all))
1692 else:
1696 else:
1693 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1697 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1694 common = set(common)
1698 common = set(common)
1695 rheads = set(hds)
1699 rheads = set(hds)
1696 lheads = set(repo.heads())
1700 lheads = set(repo.heads())
1697 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1701 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1698 if lheads <= common:
1702 if lheads <= common:
1699 ui.write("local is subset\n")
1703 ui.write("local is subset\n")
1700 elif rheads <= common:
1704 elif rheads <= common:
1701 ui.write("remote is subset\n")
1705 ui.write("remote is subset\n")
1702
1706
1703 serverlogs = opts.get('serverlog')
1707 serverlogs = opts.get('serverlog')
1704 if serverlogs:
1708 if serverlogs:
1705 for filename in serverlogs:
1709 for filename in serverlogs:
1706 logfile = open(filename, 'r')
1710 logfile = open(filename, 'r')
1707 try:
1711 try:
1708 line = logfile.readline()
1712 line = logfile.readline()
1709 while line:
1713 while line:
1710 parts = line.strip().split(';')
1714 parts = line.strip().split(';')
1711 op = parts[1]
1715 op = parts[1]
1712 if op == 'cg':
1716 if op == 'cg':
1713 pass
1717 pass
1714 elif op == 'cgss':
1718 elif op == 'cgss':
1715 doit(parts[2].split(' '), parts[3].split(' '))
1719 doit(parts[2].split(' '), parts[3].split(' '))
1716 elif op == 'unb':
1720 elif op == 'unb':
1717 doit(parts[3].split(' '), parts[2].split(' '))
1721 doit(parts[3].split(' '), parts[2].split(' '))
1718 line = logfile.readline()
1722 line = logfile.readline()
1719 finally:
1723 finally:
1720 logfile.close()
1724 logfile.close()
1721
1725
1722 else:
1726 else:
1723 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1727 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1724 opts.get('remote_head'))
1728 opts.get('remote_head'))
1725 localrevs = opts.get('local_head')
1729 localrevs = opts.get('local_head')
1726 doit(localrevs, remoterevs)
1730 doit(localrevs, remoterevs)
1727
1731
1728 @command('debugfileset', [], ('REVSPEC'))
1732 @command('debugfileset', [], ('REVSPEC'))
1729 def debugfileset(ui, repo, expr):
1733 def debugfileset(ui, repo, expr):
1730 '''parse and apply a fileset specification'''
1734 '''parse and apply a fileset specification'''
1731 if ui.verbose:
1735 if ui.verbose:
1732 tree = fileset.parse(expr)[0]
1736 tree = fileset.parse(expr)[0]
1733 ui.note(tree, "\n")
1737 ui.note(tree, "\n")
1734
1738
1735 for f in fileset.getfileset(repo[None], expr):
1739 for f in fileset.getfileset(repo[None], expr):
1736 ui.write("%s\n" % f)
1740 ui.write("%s\n" % f)
1737
1741
1738 @command('debugfsinfo', [], _('[PATH]'))
1742 @command('debugfsinfo', [], _('[PATH]'))
1739 def debugfsinfo(ui, path = "."):
1743 def debugfsinfo(ui, path = "."):
1740 """show information detected about current filesystem"""
1744 """show information detected about current filesystem"""
1741 util.writefile('.debugfsinfo', '')
1745 util.writefile('.debugfsinfo', '')
1742 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1746 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1743 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1747 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1744 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1748 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1745 and 'yes' or 'no'))
1749 and 'yes' or 'no'))
1746 os.unlink('.debugfsinfo')
1750 os.unlink('.debugfsinfo')
1747
1751
1748 @command('debuggetbundle',
1752 @command('debuggetbundle',
1749 [('H', 'head', [], _('id of head node'), _('ID')),
1753 [('H', 'head', [], _('id of head node'), _('ID')),
1750 ('C', 'common', [], _('id of common node'), _('ID')),
1754 ('C', 'common', [], _('id of common node'), _('ID')),
1751 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1755 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1752 _('REPO FILE [-H|-C ID]...'))
1756 _('REPO FILE [-H|-C ID]...'))
1753 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1757 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1754 """retrieves a bundle from a repo
1758 """retrieves a bundle from a repo
1755
1759
1756 Every ID must be a full-length hex node id string. Saves the bundle to the
1760 Every ID must be a full-length hex node id string. Saves the bundle to the
1757 given file.
1761 given file.
1758 """
1762 """
1759 repo = hg.peer(ui, opts, repopath)
1763 repo = hg.peer(ui, opts, repopath)
1760 if not repo.capable('getbundle'):
1764 if not repo.capable('getbundle'):
1761 raise util.Abort("getbundle() not supported by target repository")
1765 raise util.Abort("getbundle() not supported by target repository")
1762 args = {}
1766 args = {}
1763 if common:
1767 if common:
1764 args['common'] = [bin(s) for s in common]
1768 args['common'] = [bin(s) for s in common]
1765 if head:
1769 if head:
1766 args['heads'] = [bin(s) for s in head]
1770 args['heads'] = [bin(s) for s in head]
1767 bundle = repo.getbundle('debug', **args)
1771 bundle = repo.getbundle('debug', **args)
1768
1772
1769 bundletype = opts.get('type', 'bzip2').lower()
1773 bundletype = opts.get('type', 'bzip2').lower()
1770 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1774 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1771 bundletype = btypes.get(bundletype)
1775 bundletype = btypes.get(bundletype)
1772 if bundletype not in changegroup.bundletypes:
1776 if bundletype not in changegroup.bundletypes:
1773 raise util.Abort(_('unknown bundle type specified with --type'))
1777 raise util.Abort(_('unknown bundle type specified with --type'))
1774 changegroup.writebundle(bundle, bundlepath, bundletype)
1778 changegroup.writebundle(bundle, bundlepath, bundletype)
1775
1779
1776 @command('debugignore', [], '')
1780 @command('debugignore', [], '')
1777 def debugignore(ui, repo, *values, **opts):
1781 def debugignore(ui, repo, *values, **opts):
1778 """display the combined ignore pattern"""
1782 """display the combined ignore pattern"""
1779 ignore = repo.dirstate._ignore
1783 ignore = repo.dirstate._ignore
1780 includepat = getattr(ignore, 'includepat', None)
1784 includepat = getattr(ignore, 'includepat', None)
1781 if includepat is not None:
1785 if includepat is not None:
1782 ui.write("%s\n" % includepat)
1786 ui.write("%s\n" % includepat)
1783 else:
1787 else:
1784 raise util.Abort(_("no ignore patterns found"))
1788 raise util.Abort(_("no ignore patterns found"))
1785
1789
1786 @command('debugindex',
1790 @command('debugindex',
1787 [('c', 'changelog', False, _('open changelog')),
1791 [('c', 'changelog', False, _('open changelog')),
1788 ('m', 'manifest', False, _('open manifest')),
1792 ('m', 'manifest', False, _('open manifest')),
1789 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1793 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1790 _('[-f FORMAT] -c|-m|FILE'))
1794 _('[-f FORMAT] -c|-m|FILE'))
1791 def debugindex(ui, repo, file_ = None, **opts):
1795 def debugindex(ui, repo, file_ = None, **opts):
1792 """dump the contents of an index file"""
1796 """dump the contents of an index file"""
1793 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1797 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1794 format = opts.get('format', 0)
1798 format = opts.get('format', 0)
1795 if format not in (0, 1):
1799 if format not in (0, 1):
1796 raise util.Abort(_("unknown format %d") % format)
1800 raise util.Abort(_("unknown format %d") % format)
1797
1801
1798 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1802 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1799 if generaldelta:
1803 if generaldelta:
1800 basehdr = ' delta'
1804 basehdr = ' delta'
1801 else:
1805 else:
1802 basehdr = ' base'
1806 basehdr = ' base'
1803
1807
1804 if format == 0:
1808 if format == 0:
1805 ui.write(" rev offset length " + basehdr + " linkrev"
1809 ui.write(" rev offset length " + basehdr + " linkrev"
1806 " nodeid p1 p2\n")
1810 " nodeid p1 p2\n")
1807 elif format == 1:
1811 elif format == 1:
1808 ui.write(" rev flag offset length"
1812 ui.write(" rev flag offset length"
1809 " size " + basehdr + " link p1 p2 nodeid\n")
1813 " size " + basehdr + " link p1 p2 nodeid\n")
1810
1814
1811 for i in r:
1815 for i in r:
1812 node = r.node(i)
1816 node = r.node(i)
1813 if generaldelta:
1817 if generaldelta:
1814 base = r.deltaparent(i)
1818 base = r.deltaparent(i)
1815 else:
1819 else:
1816 base = r.chainbase(i)
1820 base = r.chainbase(i)
1817 if format == 0:
1821 if format == 0:
1818 try:
1822 try:
1819 pp = r.parents(node)
1823 pp = r.parents(node)
1820 except:
1824 except:
1821 pp = [nullid, nullid]
1825 pp = [nullid, nullid]
1822 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1826 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1823 i, r.start(i), r.length(i), base, r.linkrev(i),
1827 i, r.start(i), r.length(i), base, r.linkrev(i),
1824 short(node), short(pp[0]), short(pp[1])))
1828 short(node), short(pp[0]), short(pp[1])))
1825 elif format == 1:
1829 elif format == 1:
1826 pr = r.parentrevs(i)
1830 pr = r.parentrevs(i)
1827 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1831 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1828 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1832 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1829 base, r.linkrev(i), pr[0], pr[1], short(node)))
1833 base, r.linkrev(i), pr[0], pr[1], short(node)))
1830
1834
1831 @command('debugindexdot', [], _('FILE'))
1835 @command('debugindexdot', [], _('FILE'))
1832 def debugindexdot(ui, repo, file_):
1836 def debugindexdot(ui, repo, file_):
1833 """dump an index DAG as a graphviz dot file"""
1837 """dump an index DAG as a graphviz dot file"""
1834 r = None
1838 r = None
1835 if repo:
1839 if repo:
1836 filelog = repo.file(file_)
1840 filelog = repo.file(file_)
1837 if len(filelog):
1841 if len(filelog):
1838 r = filelog
1842 r = filelog
1839 if not r:
1843 if not r:
1840 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1844 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1841 ui.write("digraph G {\n")
1845 ui.write("digraph G {\n")
1842 for i in r:
1846 for i in r:
1843 node = r.node(i)
1847 node = r.node(i)
1844 pp = r.parents(node)
1848 pp = r.parents(node)
1845 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1849 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1846 if pp[1] != nullid:
1850 if pp[1] != nullid:
1847 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1851 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1848 ui.write("}\n")
1852 ui.write("}\n")
1849
1853
1850 @command('debuginstall', [], '')
1854 @command('debuginstall', [], '')
1851 def debuginstall(ui):
1855 def debuginstall(ui):
1852 '''test Mercurial installation
1856 '''test Mercurial installation
1853
1857
1854 Returns 0 on success.
1858 Returns 0 on success.
1855 '''
1859 '''
1856
1860
1857 def writetemp(contents):
1861 def writetemp(contents):
1858 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1862 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1859 f = os.fdopen(fd, "wb")
1863 f = os.fdopen(fd, "wb")
1860 f.write(contents)
1864 f.write(contents)
1861 f.close()
1865 f.close()
1862 return name
1866 return name
1863
1867
1864 problems = 0
1868 problems = 0
1865
1869
1866 # encoding
1870 # encoding
1867 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1871 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1868 try:
1872 try:
1869 encoding.fromlocal("test")
1873 encoding.fromlocal("test")
1870 except util.Abort, inst:
1874 except util.Abort, inst:
1871 ui.write(" %s\n" % inst)
1875 ui.write(" %s\n" % inst)
1872 ui.write(_(" (check that your locale is properly set)\n"))
1876 ui.write(_(" (check that your locale is properly set)\n"))
1873 problems += 1
1877 problems += 1
1874
1878
1875 # compiled modules
1879 # compiled modules
1876 ui.status(_("Checking installed modules (%s)...\n")
1880 ui.status(_("Checking installed modules (%s)...\n")
1877 % os.path.dirname(__file__))
1881 % os.path.dirname(__file__))
1878 try:
1882 try:
1879 import bdiff, mpatch, base85, osutil
1883 import bdiff, mpatch, base85, osutil
1880 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1884 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1881 except Exception, inst:
1885 except Exception, inst:
1882 ui.write(" %s\n" % inst)
1886 ui.write(" %s\n" % inst)
1883 ui.write(_(" One or more extensions could not be found"))
1887 ui.write(_(" One or more extensions could not be found"))
1884 ui.write(_(" (check that you compiled the extensions)\n"))
1888 ui.write(_(" (check that you compiled the extensions)\n"))
1885 problems += 1
1889 problems += 1
1886
1890
1887 # templates
1891 # templates
1888 import templater
1892 import templater
1889 p = templater.templatepath()
1893 p = templater.templatepath()
1890 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1894 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1891 try:
1895 try:
1892 templater.templater(templater.templatepath("map-cmdline.default"))
1896 templater.templater(templater.templatepath("map-cmdline.default"))
1893 except Exception, inst:
1897 except Exception, inst:
1894 ui.write(" %s\n" % inst)
1898 ui.write(" %s\n" % inst)
1895 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1899 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1896 problems += 1
1900 problems += 1
1897
1901
1898 # editor
1902 # editor
1899 ui.status(_("Checking commit editor...\n"))
1903 ui.status(_("Checking commit editor...\n"))
1900 editor = ui.geteditor()
1904 editor = ui.geteditor()
1901 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1905 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1902 if not cmdpath:
1906 if not cmdpath:
1903 if editor == 'vi':
1907 if editor == 'vi':
1904 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1908 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1905 ui.write(_(" (specify a commit editor in your configuration"
1909 ui.write(_(" (specify a commit editor in your configuration"
1906 " file)\n"))
1910 " file)\n"))
1907 else:
1911 else:
1908 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1912 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1909 ui.write(_(" (specify a commit editor in your configuration"
1913 ui.write(_(" (specify a commit editor in your configuration"
1910 " file)\n"))
1914 " file)\n"))
1911 problems += 1
1915 problems += 1
1912
1916
1913 # check username
1917 # check username
1914 ui.status(_("Checking username...\n"))
1918 ui.status(_("Checking username...\n"))
1915 try:
1919 try:
1916 ui.username()
1920 ui.username()
1917 except util.Abort, e:
1921 except util.Abort, e:
1918 ui.write(" %s\n" % e)
1922 ui.write(" %s\n" % e)
1919 ui.write(_(" (specify a username in your configuration file)\n"))
1923 ui.write(_(" (specify a username in your configuration file)\n"))
1920 problems += 1
1924 problems += 1
1921
1925
1922 if not problems:
1926 if not problems:
1923 ui.status(_("No problems detected\n"))
1927 ui.status(_("No problems detected\n"))
1924 else:
1928 else:
1925 ui.write(_("%s problems detected,"
1929 ui.write(_("%s problems detected,"
1926 " please check your install!\n") % problems)
1930 " please check your install!\n") % problems)
1927
1931
1928 return problems
1932 return problems
1929
1933
1930 @command('debugknown', [], _('REPO ID...'))
1934 @command('debugknown', [], _('REPO ID...'))
1931 def debugknown(ui, repopath, *ids, **opts):
1935 def debugknown(ui, repopath, *ids, **opts):
1932 """test whether node ids are known to a repo
1936 """test whether node ids are known to a repo
1933
1937
1934 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1938 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1935 indicating unknown/known.
1939 indicating unknown/known.
1936 """
1940 """
1937 repo = hg.peer(ui, opts, repopath)
1941 repo = hg.peer(ui, opts, repopath)
1938 if not repo.capable('known'):
1942 if not repo.capable('known'):
1939 raise util.Abort("known() not supported by target repository")
1943 raise util.Abort("known() not supported by target repository")
1940 flags = repo.known([bin(s) for s in ids])
1944 flags = repo.known([bin(s) for s in ids])
1941 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1945 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1942
1946
1943 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1947 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1944 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1948 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1945 '''access the pushkey key/value protocol
1949 '''access the pushkey key/value protocol
1946
1950
1947 With two args, list the keys in the given namespace.
1951 With two args, list the keys in the given namespace.
1948
1952
1949 With five args, set a key to new if it currently is set to old.
1953 With five args, set a key to new if it currently is set to old.
1950 Reports success or failure.
1954 Reports success or failure.
1951 '''
1955 '''
1952
1956
1953 target = hg.peer(ui, {}, repopath)
1957 target = hg.peer(ui, {}, repopath)
1954 if keyinfo:
1958 if keyinfo:
1955 key, old, new = keyinfo
1959 key, old, new = keyinfo
1956 r = target.pushkey(namespace, key, old, new)
1960 r = target.pushkey(namespace, key, old, new)
1957 ui.status(str(r) + '\n')
1961 ui.status(str(r) + '\n')
1958 return not r
1962 return not r
1959 else:
1963 else:
1960 for k, v in target.listkeys(namespace).iteritems():
1964 for k, v in target.listkeys(namespace).iteritems():
1961 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1965 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1962 v.encode('string-escape')))
1966 v.encode('string-escape')))
1963
1967
1964 @command('debugrebuildstate',
1968 @command('debugrebuildstate',
1965 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1969 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1966 _('[-r REV] [REV]'))
1970 _('[-r REV] [REV]'))
1967 def debugrebuildstate(ui, repo, rev="tip"):
1971 def debugrebuildstate(ui, repo, rev="tip"):
1968 """rebuild the dirstate as it would look like for the given revision"""
1972 """rebuild the dirstate as it would look like for the given revision"""
1969 ctx = scmutil.revsingle(repo, rev)
1973 ctx = scmutil.revsingle(repo, rev)
1970 wlock = repo.wlock()
1974 wlock = repo.wlock()
1971 try:
1975 try:
1972 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1976 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1973 finally:
1977 finally:
1974 wlock.release()
1978 wlock.release()
1975
1979
1976 @command('debugrename',
1980 @command('debugrename',
1977 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1981 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1978 _('[-r REV] FILE'))
1982 _('[-r REV] FILE'))
1979 def debugrename(ui, repo, file1, *pats, **opts):
1983 def debugrename(ui, repo, file1, *pats, **opts):
1980 """dump rename information"""
1984 """dump rename information"""
1981
1985
1982 ctx = scmutil.revsingle(repo, opts.get('rev'))
1986 ctx = scmutil.revsingle(repo, opts.get('rev'))
1983 m = scmutil.match(ctx, (file1,) + pats, opts)
1987 m = scmutil.match(ctx, (file1,) + pats, opts)
1984 for abs in ctx.walk(m):
1988 for abs in ctx.walk(m):
1985 fctx = ctx[abs]
1989 fctx = ctx[abs]
1986 o = fctx.filelog().renamed(fctx.filenode())
1990 o = fctx.filelog().renamed(fctx.filenode())
1987 rel = m.rel(abs)
1991 rel = m.rel(abs)
1988 if o:
1992 if o:
1989 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1993 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1990 else:
1994 else:
1991 ui.write(_("%s not renamed\n") % rel)
1995 ui.write(_("%s not renamed\n") % rel)
1992
1996
1993 @command('debugrevlog',
1997 @command('debugrevlog',
1994 [('c', 'changelog', False, _('open changelog')),
1998 [('c', 'changelog', False, _('open changelog')),
1995 ('m', 'manifest', False, _('open manifest')),
1999 ('m', 'manifest', False, _('open manifest')),
1996 ('d', 'dump', False, _('dump index data'))],
2000 ('d', 'dump', False, _('dump index data'))],
1997 _('-c|-m|FILE'))
2001 _('-c|-m|FILE'))
1998 def debugrevlog(ui, repo, file_ = None, **opts):
2002 def debugrevlog(ui, repo, file_ = None, **opts):
1999 """show data and statistics about a revlog"""
2003 """show data and statistics about a revlog"""
2000 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2004 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2001
2005
2002 if opts.get("dump"):
2006 if opts.get("dump"):
2003 numrevs = len(r)
2007 numrevs = len(r)
2004 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2008 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2005 " rawsize totalsize compression heads\n")
2009 " rawsize totalsize compression heads\n")
2006 ts = 0
2010 ts = 0
2007 heads = set()
2011 heads = set()
2008 for rev in xrange(numrevs):
2012 for rev in xrange(numrevs):
2009 dbase = r.deltaparent(rev)
2013 dbase = r.deltaparent(rev)
2010 if dbase == -1:
2014 if dbase == -1:
2011 dbase = rev
2015 dbase = rev
2012 cbase = r.chainbase(rev)
2016 cbase = r.chainbase(rev)
2013 p1, p2 = r.parentrevs(rev)
2017 p1, p2 = r.parentrevs(rev)
2014 rs = r.rawsize(rev)
2018 rs = r.rawsize(rev)
2015 ts = ts + rs
2019 ts = ts + rs
2016 heads -= set(r.parentrevs(rev))
2020 heads -= set(r.parentrevs(rev))
2017 heads.add(rev)
2021 heads.add(rev)
2018 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2022 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2019 (rev, p1, p2, r.start(rev), r.end(rev),
2023 (rev, p1, p2, r.start(rev), r.end(rev),
2020 r.start(dbase), r.start(cbase),
2024 r.start(dbase), r.start(cbase),
2021 r.start(p1), r.start(p2),
2025 r.start(p1), r.start(p2),
2022 rs, ts, ts / r.end(rev), len(heads)))
2026 rs, ts, ts / r.end(rev), len(heads)))
2023 return 0
2027 return 0
2024
2028
2025 v = r.version
2029 v = r.version
2026 format = v & 0xFFFF
2030 format = v & 0xFFFF
2027 flags = []
2031 flags = []
2028 gdelta = False
2032 gdelta = False
2029 if v & revlog.REVLOGNGINLINEDATA:
2033 if v & revlog.REVLOGNGINLINEDATA:
2030 flags.append('inline')
2034 flags.append('inline')
2031 if v & revlog.REVLOGGENERALDELTA:
2035 if v & revlog.REVLOGGENERALDELTA:
2032 gdelta = True
2036 gdelta = True
2033 flags.append('generaldelta')
2037 flags.append('generaldelta')
2034 if not flags:
2038 if not flags:
2035 flags = ['(none)']
2039 flags = ['(none)']
2036
2040
2037 nummerges = 0
2041 nummerges = 0
2038 numfull = 0
2042 numfull = 0
2039 numprev = 0
2043 numprev = 0
2040 nump1 = 0
2044 nump1 = 0
2041 nump2 = 0
2045 nump2 = 0
2042 numother = 0
2046 numother = 0
2043 nump1prev = 0
2047 nump1prev = 0
2044 nump2prev = 0
2048 nump2prev = 0
2045 chainlengths = []
2049 chainlengths = []
2046
2050
2047 datasize = [None, 0, 0L]
2051 datasize = [None, 0, 0L]
2048 fullsize = [None, 0, 0L]
2052 fullsize = [None, 0, 0L]
2049 deltasize = [None, 0, 0L]
2053 deltasize = [None, 0, 0L]
2050
2054
2051 def addsize(size, l):
2055 def addsize(size, l):
2052 if l[0] is None or size < l[0]:
2056 if l[0] is None or size < l[0]:
2053 l[0] = size
2057 l[0] = size
2054 if size > l[1]:
2058 if size > l[1]:
2055 l[1] = size
2059 l[1] = size
2056 l[2] += size
2060 l[2] += size
2057
2061
2058 numrevs = len(r)
2062 numrevs = len(r)
2059 for rev in xrange(numrevs):
2063 for rev in xrange(numrevs):
2060 p1, p2 = r.parentrevs(rev)
2064 p1, p2 = r.parentrevs(rev)
2061 delta = r.deltaparent(rev)
2065 delta = r.deltaparent(rev)
2062 if format > 0:
2066 if format > 0:
2063 addsize(r.rawsize(rev), datasize)
2067 addsize(r.rawsize(rev), datasize)
2064 if p2 != nullrev:
2068 if p2 != nullrev:
2065 nummerges += 1
2069 nummerges += 1
2066 size = r.length(rev)
2070 size = r.length(rev)
2067 if delta == nullrev:
2071 if delta == nullrev:
2068 chainlengths.append(0)
2072 chainlengths.append(0)
2069 numfull += 1
2073 numfull += 1
2070 addsize(size, fullsize)
2074 addsize(size, fullsize)
2071 else:
2075 else:
2072 chainlengths.append(chainlengths[delta] + 1)
2076 chainlengths.append(chainlengths[delta] + 1)
2073 addsize(size, deltasize)
2077 addsize(size, deltasize)
2074 if delta == rev - 1:
2078 if delta == rev - 1:
2075 numprev += 1
2079 numprev += 1
2076 if delta == p1:
2080 if delta == p1:
2077 nump1prev += 1
2081 nump1prev += 1
2078 elif delta == p2:
2082 elif delta == p2:
2079 nump2prev += 1
2083 nump2prev += 1
2080 elif delta == p1:
2084 elif delta == p1:
2081 nump1 += 1
2085 nump1 += 1
2082 elif delta == p2:
2086 elif delta == p2:
2083 nump2 += 1
2087 nump2 += 1
2084 elif delta != nullrev:
2088 elif delta != nullrev:
2085 numother += 1
2089 numother += 1
2086
2090
2087 numdeltas = numrevs - numfull
2091 numdeltas = numrevs - numfull
2088 numoprev = numprev - nump1prev - nump2prev
2092 numoprev = numprev - nump1prev - nump2prev
2089 totalrawsize = datasize[2]
2093 totalrawsize = datasize[2]
2090 datasize[2] /= numrevs
2094 datasize[2] /= numrevs
2091 fulltotal = fullsize[2]
2095 fulltotal = fullsize[2]
2092 fullsize[2] /= numfull
2096 fullsize[2] /= numfull
2093 deltatotal = deltasize[2]
2097 deltatotal = deltasize[2]
2094 deltasize[2] /= numrevs - numfull
2098 deltasize[2] /= numrevs - numfull
2095 totalsize = fulltotal + deltatotal
2099 totalsize = fulltotal + deltatotal
2096 avgchainlen = sum(chainlengths) / numrevs
2100 avgchainlen = sum(chainlengths) / numrevs
2097 compratio = totalrawsize / totalsize
2101 compratio = totalrawsize / totalsize
2098
2102
2099 basedfmtstr = '%%%dd\n'
2103 basedfmtstr = '%%%dd\n'
2100 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2104 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2101
2105
2102 def dfmtstr(max):
2106 def dfmtstr(max):
2103 return basedfmtstr % len(str(max))
2107 return basedfmtstr % len(str(max))
2104 def pcfmtstr(max, padding=0):
2108 def pcfmtstr(max, padding=0):
2105 return basepcfmtstr % (len(str(max)), ' ' * padding)
2109 return basepcfmtstr % (len(str(max)), ' ' * padding)
2106
2110
2107 def pcfmt(value, total):
2111 def pcfmt(value, total):
2108 return (value, 100 * float(value) / total)
2112 return (value, 100 * float(value) / total)
2109
2113
2110 ui.write('format : %d\n' % format)
2114 ui.write('format : %d\n' % format)
2111 ui.write('flags : %s\n' % ', '.join(flags))
2115 ui.write('flags : %s\n' % ', '.join(flags))
2112
2116
2113 ui.write('\n')
2117 ui.write('\n')
2114 fmt = pcfmtstr(totalsize)
2118 fmt = pcfmtstr(totalsize)
2115 fmt2 = dfmtstr(totalsize)
2119 fmt2 = dfmtstr(totalsize)
2116 ui.write('revisions : ' + fmt2 % numrevs)
2120 ui.write('revisions : ' + fmt2 % numrevs)
2117 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2121 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2118 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2122 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2119 ui.write('revisions : ' + fmt2 % numrevs)
2123 ui.write('revisions : ' + fmt2 % numrevs)
2120 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2124 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2121 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2125 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2122 ui.write('revision size : ' + fmt2 % totalsize)
2126 ui.write('revision size : ' + fmt2 % totalsize)
2123 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2127 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2124 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2128 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2125
2129
2126 ui.write('\n')
2130 ui.write('\n')
2127 fmt = dfmtstr(max(avgchainlen, compratio))
2131 fmt = dfmtstr(max(avgchainlen, compratio))
2128 ui.write('avg chain length : ' + fmt % avgchainlen)
2132 ui.write('avg chain length : ' + fmt % avgchainlen)
2129 ui.write('compression ratio : ' + fmt % compratio)
2133 ui.write('compression ratio : ' + fmt % compratio)
2130
2134
2131 if format > 0:
2135 if format > 0:
2132 ui.write('\n')
2136 ui.write('\n')
2133 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2137 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2134 % tuple(datasize))
2138 % tuple(datasize))
2135 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2139 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2136 % tuple(fullsize))
2140 % tuple(fullsize))
2137 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2141 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2138 % tuple(deltasize))
2142 % tuple(deltasize))
2139
2143
2140 if numdeltas > 0:
2144 if numdeltas > 0:
2141 ui.write('\n')
2145 ui.write('\n')
2142 fmt = pcfmtstr(numdeltas)
2146 fmt = pcfmtstr(numdeltas)
2143 fmt2 = pcfmtstr(numdeltas, 4)
2147 fmt2 = pcfmtstr(numdeltas, 4)
2144 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2148 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2145 if numprev > 0:
2149 if numprev > 0:
2146 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2150 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2147 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2151 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2148 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2152 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2149 if gdelta:
2153 if gdelta:
2150 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2154 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2151 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2155 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2152 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2156 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2153
2157
2154 @command('debugrevspec', [], ('REVSPEC'))
2158 @command('debugrevspec', [], ('REVSPEC'))
2155 def debugrevspec(ui, repo, expr):
2159 def debugrevspec(ui, repo, expr):
2156 '''parse and apply a revision specification'''
2160 '''parse and apply a revision specification'''
2157 if ui.verbose:
2161 if ui.verbose:
2158 tree = revset.parse(expr)[0]
2162 tree = revset.parse(expr)[0]
2159 ui.note(tree, "\n")
2163 ui.note(tree, "\n")
2160 newtree = revset.findaliases(ui, tree)
2164 newtree = revset.findaliases(ui, tree)
2161 if newtree != tree:
2165 if newtree != tree:
2162 ui.note(newtree, "\n")
2166 ui.note(newtree, "\n")
2163 func = revset.match(ui, expr)
2167 func = revset.match(ui, expr)
2164 for c in func(repo, range(len(repo))):
2168 for c in func(repo, range(len(repo))):
2165 ui.write("%s\n" % c)
2169 ui.write("%s\n" % c)
2166
2170
2167 @command('debugsetparents', [], _('REV1 [REV2]'))
2171 @command('debugsetparents', [], _('REV1 [REV2]'))
2168 def debugsetparents(ui, repo, rev1, rev2=None):
2172 def debugsetparents(ui, repo, rev1, rev2=None):
2169 """manually set the parents of the current working directory
2173 """manually set the parents of the current working directory
2170
2174
2171 This is useful for writing repository conversion tools, but should
2175 This is useful for writing repository conversion tools, but should
2172 be used with care.
2176 be used with care.
2173
2177
2174 Returns 0 on success.
2178 Returns 0 on success.
2175 """
2179 """
2176
2180
2177 r1 = scmutil.revsingle(repo, rev1).node()
2181 r1 = scmutil.revsingle(repo, rev1).node()
2178 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2182 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2179
2183
2180 wlock = repo.wlock()
2184 wlock = repo.wlock()
2181 try:
2185 try:
2182 repo.dirstate.setparents(r1, r2)
2186 repo.dirstate.setparents(r1, r2)
2183 finally:
2187 finally:
2184 wlock.release()
2188 wlock.release()
2185
2189
2186 @command('debugstate',
2190 @command('debugstate',
2187 [('', 'nodates', None, _('do not display the saved mtime')),
2191 [('', 'nodates', None, _('do not display the saved mtime')),
2188 ('', 'datesort', None, _('sort by saved mtime'))],
2192 ('', 'datesort', None, _('sort by saved mtime'))],
2189 _('[OPTION]...'))
2193 _('[OPTION]...'))
2190 def debugstate(ui, repo, nodates=None, datesort=None):
2194 def debugstate(ui, repo, nodates=None, datesort=None):
2191 """show the contents of the current dirstate"""
2195 """show the contents of the current dirstate"""
2192 timestr = ""
2196 timestr = ""
2193 showdate = not nodates
2197 showdate = not nodates
2194 if datesort:
2198 if datesort:
2195 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2199 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2196 else:
2200 else:
2197 keyfunc = None # sort by filename
2201 keyfunc = None # sort by filename
2198 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2202 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2199 if showdate:
2203 if showdate:
2200 if ent[3] == -1:
2204 if ent[3] == -1:
2201 # Pad or slice to locale representation
2205 # Pad or slice to locale representation
2202 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2206 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2203 time.localtime(0)))
2207 time.localtime(0)))
2204 timestr = 'unset'
2208 timestr = 'unset'
2205 timestr = (timestr[:locale_len] +
2209 timestr = (timestr[:locale_len] +
2206 ' ' * (locale_len - len(timestr)))
2210 ' ' * (locale_len - len(timestr)))
2207 else:
2211 else:
2208 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2212 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2209 time.localtime(ent[3]))
2213 time.localtime(ent[3]))
2210 if ent[1] & 020000:
2214 if ent[1] & 020000:
2211 mode = 'lnk'
2215 mode = 'lnk'
2212 else:
2216 else:
2213 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2217 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2214 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2218 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2215 for f in repo.dirstate.copies():
2219 for f in repo.dirstate.copies():
2216 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2220 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2217
2221
2218 @command('debugsub',
2222 @command('debugsub',
2219 [('r', 'rev', '',
2223 [('r', 'rev', '',
2220 _('revision to check'), _('REV'))],
2224 _('revision to check'), _('REV'))],
2221 _('[-r REV] [REV]'))
2225 _('[-r REV] [REV]'))
2222 def debugsub(ui, repo, rev=None):
2226 def debugsub(ui, repo, rev=None):
2223 ctx = scmutil.revsingle(repo, rev, None)
2227 ctx = scmutil.revsingle(repo, rev, None)
2224 for k, v in sorted(ctx.substate.items()):
2228 for k, v in sorted(ctx.substate.items()):
2225 ui.write('path %s\n' % k)
2229 ui.write('path %s\n' % k)
2226 ui.write(' source %s\n' % v[0])
2230 ui.write(' source %s\n' % v[0])
2227 ui.write(' revision %s\n' % v[1])
2231 ui.write(' revision %s\n' % v[1])
2228
2232
2229 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2233 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2230 def debugwalk(ui, repo, *pats, **opts):
2234 def debugwalk(ui, repo, *pats, **opts):
2231 """show how files match on given patterns"""
2235 """show how files match on given patterns"""
2232 m = scmutil.match(repo[None], pats, opts)
2236 m = scmutil.match(repo[None], pats, opts)
2233 items = list(repo.walk(m))
2237 items = list(repo.walk(m))
2234 if not items:
2238 if not items:
2235 return
2239 return
2236 fmt = 'f %%-%ds %%-%ds %%s' % (
2240 fmt = 'f %%-%ds %%-%ds %%s' % (
2237 max([len(abs) for abs in items]),
2241 max([len(abs) for abs in items]),
2238 max([len(m.rel(abs)) for abs in items]))
2242 max([len(m.rel(abs)) for abs in items]))
2239 for abs in items:
2243 for abs in items:
2240 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2244 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2241 ui.write("%s\n" % line.rstrip())
2245 ui.write("%s\n" % line.rstrip())
2242
2246
2243 @command('debugwireargs',
2247 @command('debugwireargs',
2244 [('', 'three', '', 'three'),
2248 [('', 'three', '', 'three'),
2245 ('', 'four', '', 'four'),
2249 ('', 'four', '', 'four'),
2246 ('', 'five', '', 'five'),
2250 ('', 'five', '', 'five'),
2247 ] + remoteopts,
2251 ] + remoteopts,
2248 _('REPO [OPTIONS]... [ONE [TWO]]'))
2252 _('REPO [OPTIONS]... [ONE [TWO]]'))
2249 def debugwireargs(ui, repopath, *vals, **opts):
2253 def debugwireargs(ui, repopath, *vals, **opts):
2250 repo = hg.peer(ui, opts, repopath)
2254 repo = hg.peer(ui, opts, repopath)
2251 for opt in remoteopts:
2255 for opt in remoteopts:
2252 del opts[opt[1]]
2256 del opts[opt[1]]
2253 args = {}
2257 args = {}
2254 for k, v in opts.iteritems():
2258 for k, v in opts.iteritems():
2255 if v:
2259 if v:
2256 args[k] = v
2260 args[k] = v
2257 # run twice to check that we don't mess up the stream for the next command
2261 # run twice to check that we don't mess up the stream for the next command
2258 res1 = repo.debugwireargs(*vals, **args)
2262 res1 = repo.debugwireargs(*vals, **args)
2259 res2 = repo.debugwireargs(*vals, **args)
2263 res2 = repo.debugwireargs(*vals, **args)
2260 ui.write("%s\n" % res1)
2264 ui.write("%s\n" % res1)
2261 if res1 != res2:
2265 if res1 != res2:
2262 ui.warn("%s\n" % res2)
2266 ui.warn("%s\n" % res2)
2263
2267
2264 @command('^diff',
2268 @command('^diff',
2265 [('r', 'rev', [], _('revision'), _('REV')),
2269 [('r', 'rev', [], _('revision'), _('REV')),
2266 ('c', 'change', '', _('change made by revision'), _('REV'))
2270 ('c', 'change', '', _('change made by revision'), _('REV'))
2267 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2271 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2268 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2272 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2269 def diff(ui, repo, *pats, **opts):
2273 def diff(ui, repo, *pats, **opts):
2270 """diff repository (or selected files)
2274 """diff repository (or selected files)
2271
2275
2272 Show differences between revisions for the specified files.
2276 Show differences between revisions for the specified files.
2273
2277
2274 Differences between files are shown using the unified diff format.
2278 Differences between files are shown using the unified diff format.
2275
2279
2276 .. note::
2280 .. note::
2277 diff may generate unexpected results for merges, as it will
2281 diff may generate unexpected results for merges, as it will
2278 default to comparing against the working directory's first
2282 default to comparing against the working directory's first
2279 parent changeset if no revisions are specified.
2283 parent changeset if no revisions are specified.
2280
2284
2281 When two revision arguments are given, then changes are shown
2285 When two revision arguments are given, then changes are shown
2282 between those revisions. If only one revision is specified then
2286 between those revisions. If only one revision is specified then
2283 that revision is compared to the working directory, and, when no
2287 that revision is compared to the working directory, and, when no
2284 revisions are specified, the working directory files are compared
2288 revisions are specified, the working directory files are compared
2285 to its parent.
2289 to its parent.
2286
2290
2287 Alternatively you can specify -c/--change with a revision to see
2291 Alternatively you can specify -c/--change with a revision to see
2288 the changes in that changeset relative to its first parent.
2292 the changes in that changeset relative to its first parent.
2289
2293
2290 Without the -a/--text option, diff will avoid generating diffs of
2294 Without the -a/--text option, diff will avoid generating diffs of
2291 files it detects as binary. With -a, diff will generate a diff
2295 files it detects as binary. With -a, diff will generate a diff
2292 anyway, probably with undesirable results.
2296 anyway, probably with undesirable results.
2293
2297
2294 Use the -g/--git option to generate diffs in the git extended diff
2298 Use the -g/--git option to generate diffs in the git extended diff
2295 format. For more information, read :hg:`help diffs`.
2299 format. For more information, read :hg:`help diffs`.
2296
2300
2297 .. container:: verbose
2301 .. container:: verbose
2298
2302
2299 Examples:
2303 Examples:
2300
2304
2301 - compare a file in the current working directory to its parent::
2305 - compare a file in the current working directory to its parent::
2302
2306
2303 hg diff foo.c
2307 hg diff foo.c
2304
2308
2305 - compare two historical versions of a directory, with rename info::
2309 - compare two historical versions of a directory, with rename info::
2306
2310
2307 hg diff --git -r 1.0:1.2 lib/
2311 hg diff --git -r 1.0:1.2 lib/
2308
2312
2309 - get change stats relative to the last change on some date::
2313 - get change stats relative to the last change on some date::
2310
2314
2311 hg diff --stat -r "date('may 2')"
2315 hg diff --stat -r "date('may 2')"
2312
2316
2313 - diff all newly-added files that contain a keyword::
2317 - diff all newly-added files that contain a keyword::
2314
2318
2315 hg diff "set:added() and grep(GNU)"
2319 hg diff "set:added() and grep(GNU)"
2316
2320
2317 - compare a revision and its parents::
2321 - compare a revision and its parents::
2318
2322
2319 hg diff -c 9353 # compare against first parent
2323 hg diff -c 9353 # compare against first parent
2320 hg diff -r 9353^:9353 # same using revset syntax
2324 hg diff -r 9353^:9353 # same using revset syntax
2321 hg diff -r 9353^2:9353 # compare against the second parent
2325 hg diff -r 9353^2:9353 # compare against the second parent
2322
2326
2323 Returns 0 on success.
2327 Returns 0 on success.
2324 """
2328 """
2325
2329
2326 revs = opts.get('rev')
2330 revs = opts.get('rev')
2327 change = opts.get('change')
2331 change = opts.get('change')
2328 stat = opts.get('stat')
2332 stat = opts.get('stat')
2329 reverse = opts.get('reverse')
2333 reverse = opts.get('reverse')
2330
2334
2331 if revs and change:
2335 if revs and change:
2332 msg = _('cannot specify --rev and --change at the same time')
2336 msg = _('cannot specify --rev and --change at the same time')
2333 raise util.Abort(msg)
2337 raise util.Abort(msg)
2334 elif change:
2338 elif change:
2335 node2 = scmutil.revsingle(repo, change, None).node()
2339 node2 = scmutil.revsingle(repo, change, None).node()
2336 node1 = repo[node2].p1().node()
2340 node1 = repo[node2].p1().node()
2337 else:
2341 else:
2338 node1, node2 = scmutil.revpair(repo, revs)
2342 node1, node2 = scmutil.revpair(repo, revs)
2339
2343
2340 if reverse:
2344 if reverse:
2341 node1, node2 = node2, node1
2345 node1, node2 = node2, node1
2342
2346
2343 diffopts = patch.diffopts(ui, opts)
2347 diffopts = patch.diffopts(ui, opts)
2344 m = scmutil.match(repo[node2], pats, opts)
2348 m = scmutil.match(repo[node2], pats, opts)
2345 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2349 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2346 listsubrepos=opts.get('subrepos'))
2350 listsubrepos=opts.get('subrepos'))
2347
2351
2348 @command('^export',
2352 @command('^export',
2349 [('o', 'output', '',
2353 [('o', 'output', '',
2350 _('print output to file with formatted name'), _('FORMAT')),
2354 _('print output to file with formatted name'), _('FORMAT')),
2351 ('', 'switch-parent', None, _('diff against the second parent')),
2355 ('', 'switch-parent', None, _('diff against the second parent')),
2352 ('r', 'rev', [], _('revisions to export'), _('REV')),
2356 ('r', 'rev', [], _('revisions to export'), _('REV')),
2353 ] + diffopts,
2357 ] + diffopts,
2354 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2358 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2355 def export(ui, repo, *changesets, **opts):
2359 def export(ui, repo, *changesets, **opts):
2356 """dump the header and diffs for one or more changesets
2360 """dump the header and diffs for one or more changesets
2357
2361
2358 Print the changeset header and diffs for one or more revisions.
2362 Print the changeset header and diffs for one or more revisions.
2359
2363
2360 The information shown in the changeset header is: author, date,
2364 The information shown in the changeset header is: author, date,
2361 branch name (if non-default), changeset hash, parent(s) and commit
2365 branch name (if non-default), changeset hash, parent(s) and commit
2362 comment.
2366 comment.
2363
2367
2364 .. note::
2368 .. note::
2365 export may generate unexpected diff output for merge
2369 export may generate unexpected diff output for merge
2366 changesets, as it will compare the merge changeset against its
2370 changesets, as it will compare the merge changeset against its
2367 first parent only.
2371 first parent only.
2368
2372
2369 Output may be to a file, in which case the name of the file is
2373 Output may be to a file, in which case the name of the file is
2370 given using a format string. The formatting rules are as follows:
2374 given using a format string. The formatting rules are as follows:
2371
2375
2372 :``%%``: literal "%" character
2376 :``%%``: literal "%" character
2373 :``%H``: changeset hash (40 hexadecimal digits)
2377 :``%H``: changeset hash (40 hexadecimal digits)
2374 :``%N``: number of patches being generated
2378 :``%N``: number of patches being generated
2375 :``%R``: changeset revision number
2379 :``%R``: changeset revision number
2376 :``%b``: basename of the exporting repository
2380 :``%b``: basename of the exporting repository
2377 :``%h``: short-form changeset hash (12 hexadecimal digits)
2381 :``%h``: short-form changeset hash (12 hexadecimal digits)
2378 :``%m``: first line of the commit message (only alphanumeric characters)
2382 :``%m``: first line of the commit message (only alphanumeric characters)
2379 :``%n``: zero-padded sequence number, starting at 1
2383 :``%n``: zero-padded sequence number, starting at 1
2380 :``%r``: zero-padded changeset revision number
2384 :``%r``: zero-padded changeset revision number
2381
2385
2382 Without the -a/--text option, export will avoid generating diffs
2386 Without the -a/--text option, export will avoid generating diffs
2383 of files it detects as binary. With -a, export will generate a
2387 of files it detects as binary. With -a, export will generate a
2384 diff anyway, probably with undesirable results.
2388 diff anyway, probably with undesirable results.
2385
2389
2386 Use the -g/--git option to generate diffs in the git extended diff
2390 Use the -g/--git option to generate diffs in the git extended diff
2387 format. See :hg:`help diffs` for more information.
2391 format. See :hg:`help diffs` for more information.
2388
2392
2389 With the --switch-parent option, the diff will be against the
2393 With the --switch-parent option, the diff will be against the
2390 second parent. It can be useful to review a merge.
2394 second parent. It can be useful to review a merge.
2391
2395
2392 .. container:: verbose
2396 .. container:: verbose
2393
2397
2394 Examples:
2398 Examples:
2395
2399
2396 - use export and import to transplant a bugfix to the current
2400 - use export and import to transplant a bugfix to the current
2397 branch::
2401 branch::
2398
2402
2399 hg export -r 9353 | hg import -
2403 hg export -r 9353 | hg import -
2400
2404
2401 - export all the changesets between two revisions to a file with
2405 - export all the changesets between two revisions to a file with
2402 rename information::
2406 rename information::
2403
2407
2404 hg export --git -r 123:150 > changes.txt
2408 hg export --git -r 123:150 > changes.txt
2405
2409
2406 - split outgoing changes into a series of patches with
2410 - split outgoing changes into a series of patches with
2407 descriptive names::
2411 descriptive names::
2408
2412
2409 hg export -r "outgoing()" -o "%n-%m.patch"
2413 hg export -r "outgoing()" -o "%n-%m.patch"
2410
2414
2411 Returns 0 on success.
2415 Returns 0 on success.
2412 """
2416 """
2413 changesets += tuple(opts.get('rev', []))
2417 changesets += tuple(opts.get('rev', []))
2414 if not changesets:
2418 if not changesets:
2415 raise util.Abort(_("export requires at least one changeset"))
2419 raise util.Abort(_("export requires at least one changeset"))
2416 revs = scmutil.revrange(repo, changesets)
2420 revs = scmutil.revrange(repo, changesets)
2417 if len(revs) > 1:
2421 if len(revs) > 1:
2418 ui.note(_('exporting patches:\n'))
2422 ui.note(_('exporting patches:\n'))
2419 else:
2423 else:
2420 ui.note(_('exporting patch:\n'))
2424 ui.note(_('exporting patch:\n'))
2421 cmdutil.export(repo, revs, template=opts.get('output'),
2425 cmdutil.export(repo, revs, template=opts.get('output'),
2422 switch_parent=opts.get('switch_parent'),
2426 switch_parent=opts.get('switch_parent'),
2423 opts=patch.diffopts(ui, opts))
2427 opts=patch.diffopts(ui, opts))
2424
2428
2425 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2429 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2426 def forget(ui, repo, *pats, **opts):
2430 def forget(ui, repo, *pats, **opts):
2427 """forget the specified files on the next commit
2431 """forget the specified files on the next commit
2428
2432
2429 Mark the specified files so they will no longer be tracked
2433 Mark the specified files so they will no longer be tracked
2430 after the next commit.
2434 after the next commit.
2431
2435
2432 This only removes files from the current branch, not from the
2436 This only removes files from the current branch, not from the
2433 entire project history, and it does not delete them from the
2437 entire project history, and it does not delete them from the
2434 working directory.
2438 working directory.
2435
2439
2436 To undo a forget before the next commit, see :hg:`add`.
2440 To undo a forget before the next commit, see :hg:`add`.
2437
2441
2438 .. container:: verbose
2442 .. container:: verbose
2439
2443
2440 Examples:
2444 Examples:
2441
2445
2442 - forget newly-added binary files::
2446 - forget newly-added binary files::
2443
2447
2444 hg forget "set:added() and binary()"
2448 hg forget "set:added() and binary()"
2445
2449
2446 - forget files that would be excluded by .hgignore::
2450 - forget files that would be excluded by .hgignore::
2447
2451
2448 hg forget "set:hgignore()"
2452 hg forget "set:hgignore()"
2449
2453
2450 Returns 0 on success.
2454 Returns 0 on success.
2451 """
2455 """
2452
2456
2453 if not pats:
2457 if not pats:
2454 raise util.Abort(_('no files specified'))
2458 raise util.Abort(_('no files specified'))
2455
2459
2456 m = scmutil.match(repo[None], pats, opts)
2460 m = scmutil.match(repo[None], pats, opts)
2457 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2461 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2458 return rejected and 1 or 0
2462 return rejected and 1 or 0
2459
2463
2460 @command(
2464 @command(
2461 'graft',
2465 'graft',
2462 [('c', 'continue', False, _('resume interrupted graft')),
2466 [('c', 'continue', False, _('resume interrupted graft')),
2463 ('e', 'edit', False, _('invoke editor on commit messages')),
2467 ('e', 'edit', False, _('invoke editor on commit messages')),
2464 ('D', 'currentdate', False,
2468 ('D', 'currentdate', False,
2465 _('record the current date as commit date')),
2469 _('record the current date as commit date')),
2466 ('U', 'currentuser', False,
2470 ('U', 'currentuser', False,
2467 _('record the current user as committer'), _('DATE'))]
2471 _('record the current user as committer'), _('DATE'))]
2468 + commitopts2 + mergetoolopts,
2472 + commitopts2 + mergetoolopts,
2469 _('[OPTION]... REVISION...'))
2473 _('[OPTION]... REVISION...'))
2470 def graft(ui, repo, *revs, **opts):
2474 def graft(ui, repo, *revs, **opts):
2471 '''copy changes from other branches onto the current branch
2475 '''copy changes from other branches onto the current branch
2472
2476
2473 This command uses Mercurial's merge logic to copy individual
2477 This command uses Mercurial's merge logic to copy individual
2474 changes from other branches without merging branches in the
2478 changes from other branches without merging branches in the
2475 history graph. This is sometimes known as 'backporting' or
2479 history graph. This is sometimes known as 'backporting' or
2476 'cherry-picking'. By default, graft will copy user, date, and
2480 'cherry-picking'. By default, graft will copy user, date, and
2477 description from the source changesets.
2481 description from the source changesets.
2478
2482
2479 Changesets that are ancestors of the current revision, that have
2483 Changesets that are ancestors of the current revision, that have
2480 already been grafted, or that are merges will be skipped.
2484 already been grafted, or that are merges will be skipped.
2481
2485
2482 If a graft merge results in conflicts, the graft process is
2486 If a graft merge results in conflicts, the graft process is
2483 interrupted so that the current merge can be manually resolved.
2487 interrupted so that the current merge can be manually resolved.
2484 Once all conflicts are addressed, the graft process can be
2488 Once all conflicts are addressed, the graft process can be
2485 continued with the -c/--continue option.
2489 continued with the -c/--continue option.
2486
2490
2487 .. note::
2491 .. note::
2488 The -c/--continue option does not reapply earlier options.
2492 The -c/--continue option does not reapply earlier options.
2489
2493
2490 .. container:: verbose
2494 .. container:: verbose
2491
2495
2492 Examples:
2496 Examples:
2493
2497
2494 - copy a single change to the stable branch and edit its description::
2498 - copy a single change to the stable branch and edit its description::
2495
2499
2496 hg update stable
2500 hg update stable
2497 hg graft --edit 9393
2501 hg graft --edit 9393
2498
2502
2499 - graft a range of changesets with one exception, updating dates::
2503 - graft a range of changesets with one exception, updating dates::
2500
2504
2501 hg graft -D "2085::2093 and not 2091"
2505 hg graft -D "2085::2093 and not 2091"
2502
2506
2503 - continue a graft after resolving conflicts::
2507 - continue a graft after resolving conflicts::
2504
2508
2505 hg graft -c
2509 hg graft -c
2506
2510
2507 - show the source of a grafted changeset::
2511 - show the source of a grafted changeset::
2508
2512
2509 hg log --debug -r tip
2513 hg log --debug -r tip
2510
2514
2511 Returns 0 on successful completion.
2515 Returns 0 on successful completion.
2512 '''
2516 '''
2513
2517
2514 if not opts.get('user') and opts.get('currentuser'):
2518 if not opts.get('user') and opts.get('currentuser'):
2515 opts['user'] = ui.username()
2519 opts['user'] = ui.username()
2516 if not opts.get('date') and opts.get('currentdate'):
2520 if not opts.get('date') and opts.get('currentdate'):
2517 opts['date'] = "%d %d" % util.makedate()
2521 opts['date'] = "%d %d" % util.makedate()
2518
2522
2519 editor = None
2523 editor = None
2520 if opts.get('edit'):
2524 if opts.get('edit'):
2521 editor = cmdutil.commitforceeditor
2525 editor = cmdutil.commitforceeditor
2522
2526
2523 cont = False
2527 cont = False
2524 if opts['continue']:
2528 if opts['continue']:
2525 cont = True
2529 cont = True
2526 if revs:
2530 if revs:
2527 raise util.Abort(_("can't specify --continue and revisions"))
2531 raise util.Abort(_("can't specify --continue and revisions"))
2528 # read in unfinished revisions
2532 # read in unfinished revisions
2529 try:
2533 try:
2530 nodes = repo.opener.read('graftstate').splitlines()
2534 nodes = repo.opener.read('graftstate').splitlines()
2531 revs = [repo[node].rev() for node in nodes]
2535 revs = [repo[node].rev() for node in nodes]
2532 except IOError, inst:
2536 except IOError, inst:
2533 if inst.errno != errno.ENOENT:
2537 if inst.errno != errno.ENOENT:
2534 raise
2538 raise
2535 raise util.Abort(_("no graft state found, can't continue"))
2539 raise util.Abort(_("no graft state found, can't continue"))
2536 else:
2540 else:
2537 cmdutil.bailifchanged(repo)
2541 cmdutil.bailifchanged(repo)
2538 if not revs:
2542 if not revs:
2539 raise util.Abort(_('no revisions specified'))
2543 raise util.Abort(_('no revisions specified'))
2540 revs = scmutil.revrange(repo, revs)
2544 revs = scmutil.revrange(repo, revs)
2541
2545
2542 # check for merges
2546 # check for merges
2543 for rev in repo.revs('%ld and merge()', revs):
2547 for rev in repo.revs('%ld and merge()', revs):
2544 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2548 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2545 revs.remove(rev)
2549 revs.remove(rev)
2546 if not revs:
2550 if not revs:
2547 return -1
2551 return -1
2548
2552
2549 # check for ancestors of dest branch
2553 # check for ancestors of dest branch
2550 for rev in repo.revs('::. and %ld', revs):
2554 for rev in repo.revs('::. and %ld', revs):
2551 ui.warn(_('skipping ancestor revision %s\n') % rev)
2555 ui.warn(_('skipping ancestor revision %s\n') % rev)
2552 revs.remove(rev)
2556 revs.remove(rev)
2553 if not revs:
2557 if not revs:
2554 return -1
2558 return -1
2555
2559
2556 # analyze revs for earlier grafts
2560 # analyze revs for earlier grafts
2557 ids = {}
2561 ids = {}
2558 for ctx in repo.set("%ld", revs):
2562 for ctx in repo.set("%ld", revs):
2559 ids[ctx.hex()] = ctx.rev()
2563 ids[ctx.hex()] = ctx.rev()
2560 n = ctx.extra().get('source')
2564 n = ctx.extra().get('source')
2561 if n:
2565 if n:
2562 ids[n] = ctx.rev()
2566 ids[n] = ctx.rev()
2563
2567
2564 # check ancestors for earlier grafts
2568 # check ancestors for earlier grafts
2565 ui.debug('scanning for duplicate grafts\n')
2569 ui.debug('scanning for duplicate grafts\n')
2566 for ctx in repo.set("::. - ::%ld", revs):
2570 for ctx in repo.set("::. - ::%ld", revs):
2567 n = ctx.extra().get('source')
2571 n = ctx.extra().get('source')
2568 if n in ids:
2572 if n in ids:
2569 r = repo[n].rev()
2573 r = repo[n].rev()
2570 if r in revs:
2574 if r in revs:
2571 ui.warn(_('skipping already grafted revision %s\n') % r)
2575 ui.warn(_('skipping already grafted revision %s\n') % r)
2572 revs.remove(r)
2576 revs.remove(r)
2573 elif ids[n] in revs:
2577 elif ids[n] in revs:
2574 ui.warn(_('skipping already grafted revision %s '
2578 ui.warn(_('skipping already grafted revision %s '
2575 '(same origin %d)\n') % (ids[n], r))
2579 '(same origin %d)\n') % (ids[n], r))
2576 revs.remove(ids[n])
2580 revs.remove(ids[n])
2577 elif ctx.hex() in ids:
2581 elif ctx.hex() in ids:
2578 r = ids[ctx.hex()]
2582 r = ids[ctx.hex()]
2579 ui.warn(_('skipping already grafted revision %s '
2583 ui.warn(_('skipping already grafted revision %s '
2580 '(was grafted from %d)\n') % (r, ctx.rev()))
2584 '(was grafted from %d)\n') % (r, ctx.rev()))
2581 revs.remove(r)
2585 revs.remove(r)
2582 if not revs:
2586 if not revs:
2583 return -1
2587 return -1
2584
2588
2585 for pos, ctx in enumerate(repo.set("%ld", revs)):
2589 for pos, ctx in enumerate(repo.set("%ld", revs)):
2586 current = repo['.']
2590 current = repo['.']
2587 ui.status(_('grafting revision %s\n') % ctx.rev())
2591 ui.status(_('grafting revision %s\n') % ctx.rev())
2588
2592
2589 # we don't merge the first commit when continuing
2593 # we don't merge the first commit when continuing
2590 if not cont:
2594 if not cont:
2591 # perform the graft merge with p1(rev) as 'ancestor'
2595 # perform the graft merge with p1(rev) as 'ancestor'
2592 try:
2596 try:
2593 # ui.forcemerge is an internal variable, do not document
2597 # ui.forcemerge is an internal variable, do not document
2594 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2598 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2595 stats = mergemod.update(repo, ctx.node(), True, True, False,
2599 stats = mergemod.update(repo, ctx.node(), True, True, False,
2596 ctx.p1().node())
2600 ctx.p1().node())
2597 finally:
2601 finally:
2598 ui.setconfig('ui', 'forcemerge', '')
2602 ui.setconfig('ui', 'forcemerge', '')
2599 # drop the second merge parent
2603 # drop the second merge parent
2600 repo.dirstate.setparents(current.node(), nullid)
2604 repo.dirstate.setparents(current.node(), nullid)
2601 repo.dirstate.write()
2605 repo.dirstate.write()
2602 # fix up dirstate for copies and renames
2606 # fix up dirstate for copies and renames
2603 cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
2607 cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
2604 # report any conflicts
2608 # report any conflicts
2605 if stats and stats[3] > 0:
2609 if stats and stats[3] > 0:
2606 # write out state for --continue
2610 # write out state for --continue
2607 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2611 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2608 repo.opener.write('graftstate', ''.join(nodelines))
2612 repo.opener.write('graftstate', ''.join(nodelines))
2609 raise util.Abort(
2613 raise util.Abort(
2610 _("unresolved conflicts, can't continue"),
2614 _("unresolved conflicts, can't continue"),
2611 hint=_('use hg resolve and hg graft --continue'))
2615 hint=_('use hg resolve and hg graft --continue'))
2612 else:
2616 else:
2613 cont = False
2617 cont = False
2614
2618
2615 # commit
2619 # commit
2616 source = ctx.extra().get('source')
2620 source = ctx.extra().get('source')
2617 if not source:
2621 if not source:
2618 source = ctx.hex()
2622 source = ctx.hex()
2619 extra = {'source': source}
2623 extra = {'source': source}
2620 user = ctx.user()
2624 user = ctx.user()
2621 if opts.get('user'):
2625 if opts.get('user'):
2622 user = opts['user']
2626 user = opts['user']
2623 date = ctx.date()
2627 date = ctx.date()
2624 if opts.get('date'):
2628 if opts.get('date'):
2625 date = opts['date']
2629 date = opts['date']
2626 repo.commit(text=ctx.description(), user=user,
2630 repo.commit(text=ctx.description(), user=user,
2627 date=date, extra=extra, editor=editor)
2631 date=date, extra=extra, editor=editor)
2628
2632
2629 # remove state when we complete successfully
2633 # remove state when we complete successfully
2630 if os.path.exists(repo.join('graftstate')):
2634 if os.path.exists(repo.join('graftstate')):
2631 util.unlinkpath(repo.join('graftstate'))
2635 util.unlinkpath(repo.join('graftstate'))
2632
2636
2633 return 0
2637 return 0
2634
2638
2635 @command('grep',
2639 @command('grep',
2636 [('0', 'print0', None, _('end fields with NUL')),
2640 [('0', 'print0', None, _('end fields with NUL')),
2637 ('', 'all', None, _('print all revisions that match')),
2641 ('', 'all', None, _('print all revisions that match')),
2638 ('a', 'text', None, _('treat all files as text')),
2642 ('a', 'text', None, _('treat all files as text')),
2639 ('f', 'follow', None,
2643 ('f', 'follow', None,
2640 _('follow changeset history,'
2644 _('follow changeset history,'
2641 ' or file history across copies and renames')),
2645 ' or file history across copies and renames')),
2642 ('i', 'ignore-case', None, _('ignore case when matching')),
2646 ('i', 'ignore-case', None, _('ignore case when matching')),
2643 ('l', 'files-with-matches', None,
2647 ('l', 'files-with-matches', None,
2644 _('print only filenames and revisions that match')),
2648 _('print only filenames and revisions that match')),
2645 ('n', 'line-number', None, _('print matching line numbers')),
2649 ('n', 'line-number', None, _('print matching line numbers')),
2646 ('r', 'rev', [],
2650 ('r', 'rev', [],
2647 _('only search files changed within revision range'), _('REV')),
2651 _('only search files changed within revision range'), _('REV')),
2648 ('u', 'user', None, _('list the author (long with -v)')),
2652 ('u', 'user', None, _('list the author (long with -v)')),
2649 ('d', 'date', None, _('list the date (short with -q)')),
2653 ('d', 'date', None, _('list the date (short with -q)')),
2650 ] + walkopts,
2654 ] + walkopts,
2651 _('[OPTION]... PATTERN [FILE]...'))
2655 _('[OPTION]... PATTERN [FILE]...'))
2652 def grep(ui, repo, pattern, *pats, **opts):
2656 def grep(ui, repo, pattern, *pats, **opts):
2653 """search for a pattern in specified files and revisions
2657 """search for a pattern in specified files and revisions
2654
2658
2655 Search revisions of files for a regular expression.
2659 Search revisions of files for a regular expression.
2656
2660
2657 This command behaves differently than Unix grep. It only accepts
2661 This command behaves differently than Unix grep. It only accepts
2658 Python/Perl regexps. It searches repository history, not the
2662 Python/Perl regexps. It searches repository history, not the
2659 working directory. It always prints the revision number in which a
2663 working directory. It always prints the revision number in which a
2660 match appears.
2664 match appears.
2661
2665
2662 By default, grep only prints output for the first revision of a
2666 By default, grep only prints output for the first revision of a
2663 file in which it finds a match. To get it to print every revision
2667 file in which it finds a match. To get it to print every revision
2664 that contains a change in match status ("-" for a match that
2668 that contains a change in match status ("-" for a match that
2665 becomes a non-match, or "+" for a non-match that becomes a match),
2669 becomes a non-match, or "+" for a non-match that becomes a match),
2666 use the --all flag.
2670 use the --all flag.
2667
2671
2668 Returns 0 if a match is found, 1 otherwise.
2672 Returns 0 if a match is found, 1 otherwise.
2669 """
2673 """
2670 reflags = re.M
2674 reflags = re.M
2671 if opts.get('ignore_case'):
2675 if opts.get('ignore_case'):
2672 reflags |= re.I
2676 reflags |= re.I
2673 try:
2677 try:
2674 regexp = re.compile(pattern, reflags)
2678 regexp = re.compile(pattern, reflags)
2675 except re.error, inst:
2679 except re.error, inst:
2676 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2680 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2677 return 1
2681 return 1
2678 sep, eol = ':', '\n'
2682 sep, eol = ':', '\n'
2679 if opts.get('print0'):
2683 if opts.get('print0'):
2680 sep = eol = '\0'
2684 sep = eol = '\0'
2681
2685
2682 getfile = util.lrucachefunc(repo.file)
2686 getfile = util.lrucachefunc(repo.file)
2683
2687
2684 def matchlines(body):
2688 def matchlines(body):
2685 begin = 0
2689 begin = 0
2686 linenum = 0
2690 linenum = 0
2687 while True:
2691 while True:
2688 match = regexp.search(body, begin)
2692 match = regexp.search(body, begin)
2689 if not match:
2693 if not match:
2690 break
2694 break
2691 mstart, mend = match.span()
2695 mstart, mend = match.span()
2692 linenum += body.count('\n', begin, mstart) + 1
2696 linenum += body.count('\n', begin, mstart) + 1
2693 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2697 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2694 begin = body.find('\n', mend) + 1 or len(body) + 1
2698 begin = body.find('\n', mend) + 1 or len(body) + 1
2695 lend = begin - 1
2699 lend = begin - 1
2696 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2700 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2697
2701
2698 class linestate(object):
2702 class linestate(object):
2699 def __init__(self, line, linenum, colstart, colend):
2703 def __init__(self, line, linenum, colstart, colend):
2700 self.line = line
2704 self.line = line
2701 self.linenum = linenum
2705 self.linenum = linenum
2702 self.colstart = colstart
2706 self.colstart = colstart
2703 self.colend = colend
2707 self.colend = colend
2704
2708
2705 def __hash__(self):
2709 def __hash__(self):
2706 return hash((self.linenum, self.line))
2710 return hash((self.linenum, self.line))
2707
2711
2708 def __eq__(self, other):
2712 def __eq__(self, other):
2709 return self.line == other.line
2713 return self.line == other.line
2710
2714
2711 matches = {}
2715 matches = {}
2712 copies = {}
2716 copies = {}
2713 def grepbody(fn, rev, body):
2717 def grepbody(fn, rev, body):
2714 matches[rev].setdefault(fn, [])
2718 matches[rev].setdefault(fn, [])
2715 m = matches[rev][fn]
2719 m = matches[rev][fn]
2716 for lnum, cstart, cend, line in matchlines(body):
2720 for lnum, cstart, cend, line in matchlines(body):
2717 s = linestate(line, lnum, cstart, cend)
2721 s = linestate(line, lnum, cstart, cend)
2718 m.append(s)
2722 m.append(s)
2719
2723
2720 def difflinestates(a, b):
2724 def difflinestates(a, b):
2721 sm = difflib.SequenceMatcher(None, a, b)
2725 sm = difflib.SequenceMatcher(None, a, b)
2722 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2726 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2723 if tag == 'insert':
2727 if tag == 'insert':
2724 for i in xrange(blo, bhi):
2728 for i in xrange(blo, bhi):
2725 yield ('+', b[i])
2729 yield ('+', b[i])
2726 elif tag == 'delete':
2730 elif tag == 'delete':
2727 for i in xrange(alo, ahi):
2731 for i in xrange(alo, ahi):
2728 yield ('-', a[i])
2732 yield ('-', a[i])
2729 elif tag == 'replace':
2733 elif tag == 'replace':
2730 for i in xrange(alo, ahi):
2734 for i in xrange(alo, ahi):
2731 yield ('-', a[i])
2735 yield ('-', a[i])
2732 for i in xrange(blo, bhi):
2736 for i in xrange(blo, bhi):
2733 yield ('+', b[i])
2737 yield ('+', b[i])
2734
2738
2735 def display(fn, ctx, pstates, states):
2739 def display(fn, ctx, pstates, states):
2736 rev = ctx.rev()
2740 rev = ctx.rev()
2737 datefunc = ui.quiet and util.shortdate or util.datestr
2741 datefunc = ui.quiet and util.shortdate or util.datestr
2738 found = False
2742 found = False
2739 filerevmatches = {}
2743 filerevmatches = {}
2740 def binary():
2744 def binary():
2741 flog = getfile(fn)
2745 flog = getfile(fn)
2742 return util.binary(flog.read(ctx.filenode(fn)))
2746 return util.binary(flog.read(ctx.filenode(fn)))
2743
2747
2744 if opts.get('all'):
2748 if opts.get('all'):
2745 iter = difflinestates(pstates, states)
2749 iter = difflinestates(pstates, states)
2746 else:
2750 else:
2747 iter = [('', l) for l in states]
2751 iter = [('', l) for l in states]
2748 for change, l in iter:
2752 for change, l in iter:
2749 cols = [fn, str(rev)]
2753 cols = [fn, str(rev)]
2750 before, match, after = None, None, None
2754 before, match, after = None, None, None
2751 if opts.get('line_number'):
2755 if opts.get('line_number'):
2752 cols.append(str(l.linenum))
2756 cols.append(str(l.linenum))
2753 if opts.get('all'):
2757 if opts.get('all'):
2754 cols.append(change)
2758 cols.append(change)
2755 if opts.get('user'):
2759 if opts.get('user'):
2756 cols.append(ui.shortuser(ctx.user()))
2760 cols.append(ui.shortuser(ctx.user()))
2757 if opts.get('date'):
2761 if opts.get('date'):
2758 cols.append(datefunc(ctx.date()))
2762 cols.append(datefunc(ctx.date()))
2759 if opts.get('files_with_matches'):
2763 if opts.get('files_with_matches'):
2760 c = (fn, rev)
2764 c = (fn, rev)
2761 if c in filerevmatches:
2765 if c in filerevmatches:
2762 continue
2766 continue
2763 filerevmatches[c] = 1
2767 filerevmatches[c] = 1
2764 else:
2768 else:
2765 before = l.line[:l.colstart]
2769 before = l.line[:l.colstart]
2766 match = l.line[l.colstart:l.colend]
2770 match = l.line[l.colstart:l.colend]
2767 after = l.line[l.colend:]
2771 after = l.line[l.colend:]
2768 ui.write(sep.join(cols))
2772 ui.write(sep.join(cols))
2769 if before is not None:
2773 if before is not None:
2770 if not opts.get('text') and binary():
2774 if not opts.get('text') and binary():
2771 ui.write(sep + " Binary file matches")
2775 ui.write(sep + " Binary file matches")
2772 else:
2776 else:
2773 ui.write(sep + before)
2777 ui.write(sep + before)
2774 ui.write(match, label='grep.match')
2778 ui.write(match, label='grep.match')
2775 ui.write(after)
2779 ui.write(after)
2776 ui.write(eol)
2780 ui.write(eol)
2777 found = True
2781 found = True
2778 return found
2782 return found
2779
2783
2780 skip = {}
2784 skip = {}
2781 revfiles = {}
2785 revfiles = {}
2782 matchfn = scmutil.match(repo[None], pats, opts)
2786 matchfn = scmutil.match(repo[None], pats, opts)
2783 found = False
2787 found = False
2784 follow = opts.get('follow')
2788 follow = opts.get('follow')
2785
2789
2786 def prep(ctx, fns):
2790 def prep(ctx, fns):
2787 rev = ctx.rev()
2791 rev = ctx.rev()
2788 pctx = ctx.p1()
2792 pctx = ctx.p1()
2789 parent = pctx.rev()
2793 parent = pctx.rev()
2790 matches.setdefault(rev, {})
2794 matches.setdefault(rev, {})
2791 matches.setdefault(parent, {})
2795 matches.setdefault(parent, {})
2792 files = revfiles.setdefault(rev, [])
2796 files = revfiles.setdefault(rev, [])
2793 for fn in fns:
2797 for fn in fns:
2794 flog = getfile(fn)
2798 flog = getfile(fn)
2795 try:
2799 try:
2796 fnode = ctx.filenode(fn)
2800 fnode = ctx.filenode(fn)
2797 except error.LookupError:
2801 except error.LookupError:
2798 continue
2802 continue
2799
2803
2800 copied = flog.renamed(fnode)
2804 copied = flog.renamed(fnode)
2801 copy = follow and copied and copied[0]
2805 copy = follow and copied and copied[0]
2802 if copy:
2806 if copy:
2803 copies.setdefault(rev, {})[fn] = copy
2807 copies.setdefault(rev, {})[fn] = copy
2804 if fn in skip:
2808 if fn in skip:
2805 if copy:
2809 if copy:
2806 skip[copy] = True
2810 skip[copy] = True
2807 continue
2811 continue
2808 files.append(fn)
2812 files.append(fn)
2809
2813
2810 if fn not in matches[rev]:
2814 if fn not in matches[rev]:
2811 grepbody(fn, rev, flog.read(fnode))
2815 grepbody(fn, rev, flog.read(fnode))
2812
2816
2813 pfn = copy or fn
2817 pfn = copy or fn
2814 if pfn not in matches[parent]:
2818 if pfn not in matches[parent]:
2815 try:
2819 try:
2816 fnode = pctx.filenode(pfn)
2820 fnode = pctx.filenode(pfn)
2817 grepbody(pfn, parent, flog.read(fnode))
2821 grepbody(pfn, parent, flog.read(fnode))
2818 except error.LookupError:
2822 except error.LookupError:
2819 pass
2823 pass
2820
2824
2821 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2825 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2822 rev = ctx.rev()
2826 rev = ctx.rev()
2823 parent = ctx.p1().rev()
2827 parent = ctx.p1().rev()
2824 for fn in sorted(revfiles.get(rev, [])):
2828 for fn in sorted(revfiles.get(rev, [])):
2825 states = matches[rev][fn]
2829 states = matches[rev][fn]
2826 copy = copies.get(rev, {}).get(fn)
2830 copy = copies.get(rev, {}).get(fn)
2827 if fn in skip:
2831 if fn in skip:
2828 if copy:
2832 if copy:
2829 skip[copy] = True
2833 skip[copy] = True
2830 continue
2834 continue
2831 pstates = matches.get(parent, {}).get(copy or fn, [])
2835 pstates = matches.get(parent, {}).get(copy or fn, [])
2832 if pstates or states:
2836 if pstates or states:
2833 r = display(fn, ctx, pstates, states)
2837 r = display(fn, ctx, pstates, states)
2834 found = found or r
2838 found = found or r
2835 if r and not opts.get('all'):
2839 if r and not opts.get('all'):
2836 skip[fn] = True
2840 skip[fn] = True
2837 if copy:
2841 if copy:
2838 skip[copy] = True
2842 skip[copy] = True
2839 del matches[rev]
2843 del matches[rev]
2840 del revfiles[rev]
2844 del revfiles[rev]
2841
2845
2842 return not found
2846 return not found
2843
2847
2844 @command('heads',
2848 @command('heads',
2845 [('r', 'rev', '',
2849 [('r', 'rev', '',
2846 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2850 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2847 ('t', 'topo', False, _('show topological heads only')),
2851 ('t', 'topo', False, _('show topological heads only')),
2848 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2852 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2849 ('c', 'closed', False, _('show normal and closed branch heads')),
2853 ('c', 'closed', False, _('show normal and closed branch heads')),
2850 ] + templateopts,
2854 ] + templateopts,
2851 _('[-ac] [-r STARTREV] [REV]...'))
2855 _('[-ac] [-r STARTREV] [REV]...'))
2852 def heads(ui, repo, *branchrevs, **opts):
2856 def heads(ui, repo, *branchrevs, **opts):
2853 """show current repository heads or show branch heads
2857 """show current repository heads or show branch heads
2854
2858
2855 With no arguments, show all repository branch heads.
2859 With no arguments, show all repository branch heads.
2856
2860
2857 Repository "heads" are changesets with no child changesets. They are
2861 Repository "heads" are changesets with no child changesets. They are
2858 where development generally takes place and are the usual targets
2862 where development generally takes place and are the usual targets
2859 for update and merge operations. Branch heads are changesets that have
2863 for update and merge operations. Branch heads are changesets that have
2860 no child changeset on the same branch.
2864 no child changeset on the same branch.
2861
2865
2862 If one or more REVs are given, only branch heads on the branches
2866 If one or more REVs are given, only branch heads on the branches
2863 associated with the specified changesets are shown. This means
2867 associated with the specified changesets are shown. This means
2864 that you can use :hg:`heads foo` to see the heads on a branch
2868 that you can use :hg:`heads foo` to see the heads on a branch
2865 named ``foo``.
2869 named ``foo``.
2866
2870
2867 If -c/--closed is specified, also show branch heads marked closed
2871 If -c/--closed is specified, also show branch heads marked closed
2868 (see :hg:`commit --close-branch`).
2872 (see :hg:`commit --close-branch`).
2869
2873
2870 If STARTREV is specified, only those heads that are descendants of
2874 If STARTREV is specified, only those heads that are descendants of
2871 STARTREV will be displayed.
2875 STARTREV will be displayed.
2872
2876
2873 If -t/--topo is specified, named branch mechanics will be ignored and only
2877 If -t/--topo is specified, named branch mechanics will be ignored and only
2874 changesets without children will be shown.
2878 changesets without children will be shown.
2875
2879
2876 Returns 0 if matching heads are found, 1 if not.
2880 Returns 0 if matching heads are found, 1 if not.
2877 """
2881 """
2878
2882
2879 start = None
2883 start = None
2880 if 'rev' in opts:
2884 if 'rev' in opts:
2881 start = scmutil.revsingle(repo, opts['rev'], None).node()
2885 start = scmutil.revsingle(repo, opts['rev'], None).node()
2882
2886
2883 if opts.get('topo'):
2887 if opts.get('topo'):
2884 heads = [repo[h] for h in repo.heads(start)]
2888 heads = [repo[h] for h in repo.heads(start)]
2885 else:
2889 else:
2886 heads = []
2890 heads = []
2887 for branch in repo.branchmap():
2891 for branch in repo.branchmap():
2888 heads += repo.branchheads(branch, start, opts.get('closed'))
2892 heads += repo.branchheads(branch, start, opts.get('closed'))
2889 heads = [repo[h] for h in heads]
2893 heads = [repo[h] for h in heads]
2890
2894
2891 if branchrevs:
2895 if branchrevs:
2892 branches = set(repo[br].branch() for br in branchrevs)
2896 branches = set(repo[br].branch() for br in branchrevs)
2893 heads = [h for h in heads if h.branch() in branches]
2897 heads = [h for h in heads if h.branch() in branches]
2894
2898
2895 if opts.get('active') and branchrevs:
2899 if opts.get('active') and branchrevs:
2896 dagheads = repo.heads(start)
2900 dagheads = repo.heads(start)
2897 heads = [h for h in heads if h.node() in dagheads]
2901 heads = [h for h in heads if h.node() in dagheads]
2898
2902
2899 if branchrevs:
2903 if branchrevs:
2900 haveheads = set(h.branch() for h in heads)
2904 haveheads = set(h.branch() for h in heads)
2901 if branches - haveheads:
2905 if branches - haveheads:
2902 headless = ', '.join(b for b in branches - haveheads)
2906 headless = ', '.join(b for b in branches - haveheads)
2903 msg = _('no open branch heads found on branches %s')
2907 msg = _('no open branch heads found on branches %s')
2904 if opts.get('rev'):
2908 if opts.get('rev'):
2905 msg += _(' (started at %s)' % opts['rev'])
2909 msg += _(' (started at %s)' % opts['rev'])
2906 ui.warn((msg + '\n') % headless)
2910 ui.warn((msg + '\n') % headless)
2907
2911
2908 if not heads:
2912 if not heads:
2909 return 1
2913 return 1
2910
2914
2911 heads = sorted(heads, key=lambda x: -x.rev())
2915 heads = sorted(heads, key=lambda x: -x.rev())
2912 displayer = cmdutil.show_changeset(ui, repo, opts)
2916 displayer = cmdutil.show_changeset(ui, repo, opts)
2913 for ctx in heads:
2917 for ctx in heads:
2914 displayer.show(ctx)
2918 displayer.show(ctx)
2915 displayer.close()
2919 displayer.close()
2916
2920
2917 @command('help',
2921 @command('help',
2918 [('e', 'extension', None, _('show only help for extensions')),
2922 [('e', 'extension', None, _('show only help for extensions')),
2919 ('c', 'command', None, _('show only help for commands'))],
2923 ('c', 'command', None, _('show only help for commands'))],
2920 _('[-ec] [TOPIC]'))
2924 _('[-ec] [TOPIC]'))
2921 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2925 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2922 """show help for a given topic or a help overview
2926 """show help for a given topic or a help overview
2923
2927
2924 With no arguments, print a list of commands with short help messages.
2928 With no arguments, print a list of commands with short help messages.
2925
2929
2926 Given a topic, extension, or command name, print help for that
2930 Given a topic, extension, or command name, print help for that
2927 topic.
2931 topic.
2928
2932
2929 Returns 0 if successful.
2933 Returns 0 if successful.
2930 """
2934 """
2931
2935
2932 textwidth = min(ui.termwidth(), 80) - 2
2936 textwidth = min(ui.termwidth(), 80) - 2
2933
2937
2934 def optrst(options):
2938 def optrst(options):
2935 data = []
2939 data = []
2936 multioccur = False
2940 multioccur = False
2937 for option in options:
2941 for option in options:
2938 if len(option) == 5:
2942 if len(option) == 5:
2939 shortopt, longopt, default, desc, optlabel = option
2943 shortopt, longopt, default, desc, optlabel = option
2940 else:
2944 else:
2941 shortopt, longopt, default, desc = option
2945 shortopt, longopt, default, desc = option
2942 optlabel = _("VALUE") # default label
2946 optlabel = _("VALUE") # default label
2943
2947
2944 if _("DEPRECATED") in desc and not ui.verbose:
2948 if _("DEPRECATED") in desc and not ui.verbose:
2945 continue
2949 continue
2946
2950
2947 so = ''
2951 so = ''
2948 if shortopt:
2952 if shortopt:
2949 so = '-' + shortopt
2953 so = '-' + shortopt
2950 lo = '--' + longopt
2954 lo = '--' + longopt
2951 if default:
2955 if default:
2952 desc += _(" (default: %s)") % default
2956 desc += _(" (default: %s)") % default
2953
2957
2954 if isinstance(default, list):
2958 if isinstance(default, list):
2955 lo += " %s [+]" % optlabel
2959 lo += " %s [+]" % optlabel
2956 multioccur = True
2960 multioccur = True
2957 elif (default is not None) and not isinstance(default, bool):
2961 elif (default is not None) and not isinstance(default, bool):
2958 lo += " %s" % optlabel
2962 lo += " %s" % optlabel
2959
2963
2960 data.append((so, lo, desc))
2964 data.append((so, lo, desc))
2961
2965
2962 rst = minirst.maketable(data, 1)
2966 rst = minirst.maketable(data, 1)
2963
2967
2964 if multioccur:
2968 if multioccur:
2965 rst += _("\n[+] marked option can be specified multiple times\n")
2969 rst += _("\n[+] marked option can be specified multiple times\n")
2966
2970
2967 return rst
2971 return rst
2968
2972
2969 # list all option lists
2973 # list all option lists
2970 def opttext(optlist, width):
2974 def opttext(optlist, width):
2971 rst = ''
2975 rst = ''
2972 if not optlist:
2976 if not optlist:
2973 return ''
2977 return ''
2974
2978
2975 for title, options in optlist:
2979 for title, options in optlist:
2976 rst += '\n%s\n' % title
2980 rst += '\n%s\n' % title
2977 if options:
2981 if options:
2978 rst += "\n"
2982 rst += "\n"
2979 rst += optrst(options)
2983 rst += optrst(options)
2980 rst += '\n'
2984 rst += '\n'
2981
2985
2982 return '\n' + minirst.format(rst, width)
2986 return '\n' + minirst.format(rst, width)
2983
2987
2984 def addglobalopts(optlist, aliases):
2988 def addglobalopts(optlist, aliases):
2985 if ui.quiet:
2989 if ui.quiet:
2986 return []
2990 return []
2987
2991
2988 if ui.verbose:
2992 if ui.verbose:
2989 optlist.append((_("global options:"), globalopts))
2993 optlist.append((_("global options:"), globalopts))
2990 if name == 'shortlist':
2994 if name == 'shortlist':
2991 optlist.append((_('use "hg help" for the full list '
2995 optlist.append((_('use "hg help" for the full list '
2992 'of commands'), ()))
2996 'of commands'), ()))
2993 else:
2997 else:
2994 if name == 'shortlist':
2998 if name == 'shortlist':
2995 msg = _('use "hg help" for the full list of commands '
2999 msg = _('use "hg help" for the full list of commands '
2996 'or "hg -v" for details')
3000 'or "hg -v" for details')
2997 elif name and not full:
3001 elif name and not full:
2998 msg = _('use "hg help %s" to show the full help text' % name)
3002 msg = _('use "hg help %s" to show the full help text' % name)
2999 elif aliases:
3003 elif aliases:
3000 msg = _('use "hg -v help%s" to show builtin aliases and '
3004 msg = _('use "hg -v help%s" to show builtin aliases and '
3001 'global options') % (name and " " + name or "")
3005 'global options') % (name and " " + name or "")
3002 else:
3006 else:
3003 msg = _('use "hg -v help %s" to show more info') % name
3007 msg = _('use "hg -v help %s" to show more info') % name
3004 optlist.append((msg, ()))
3008 optlist.append((msg, ()))
3005
3009
3006 def helpcmd(name):
3010 def helpcmd(name):
3007 try:
3011 try:
3008 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3012 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3009 except error.AmbiguousCommand, inst:
3013 except error.AmbiguousCommand, inst:
3010 # py3k fix: except vars can't be used outside the scope of the
3014 # py3k fix: except vars can't be used outside the scope of the
3011 # except block, nor can be used inside a lambda. python issue4617
3015 # except block, nor can be used inside a lambda. python issue4617
3012 prefix = inst.args[0]
3016 prefix = inst.args[0]
3013 select = lambda c: c.lstrip('^').startswith(prefix)
3017 select = lambda c: c.lstrip('^').startswith(prefix)
3014 helplist(select)
3018 helplist(select)
3015 return
3019 return
3016
3020
3017 # check if it's an invalid alias and display its error if it is
3021 # check if it's an invalid alias and display its error if it is
3018 if getattr(entry[0], 'badalias', False):
3022 if getattr(entry[0], 'badalias', False):
3019 if not unknowncmd:
3023 if not unknowncmd:
3020 entry[0](ui)
3024 entry[0](ui)
3021 return
3025 return
3022
3026
3023 rst = ""
3027 rst = ""
3024
3028
3025 # synopsis
3029 # synopsis
3026 if len(entry) > 2:
3030 if len(entry) > 2:
3027 if entry[2].startswith('hg'):
3031 if entry[2].startswith('hg'):
3028 rst += "%s\n" % entry[2]
3032 rst += "%s\n" % entry[2]
3029 else:
3033 else:
3030 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3034 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3031 else:
3035 else:
3032 rst += 'hg %s\n' % aliases[0]
3036 rst += 'hg %s\n' % aliases[0]
3033
3037
3034 # aliases
3038 # aliases
3035 if full and not ui.quiet and len(aliases) > 1:
3039 if full and not ui.quiet and len(aliases) > 1:
3036 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3040 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3037
3041
3038 # description
3042 # description
3039 doc = gettext(entry[0].__doc__)
3043 doc = gettext(entry[0].__doc__)
3040 if not doc:
3044 if not doc:
3041 doc = _("(no help text available)")
3045 doc = _("(no help text available)")
3042 if util.safehasattr(entry[0], 'definition'): # aliased command
3046 if util.safehasattr(entry[0], 'definition'): # aliased command
3043 if entry[0].definition.startswith('!'): # shell alias
3047 if entry[0].definition.startswith('!'): # shell alias
3044 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3048 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3045 else:
3049 else:
3046 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3050 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3047 if ui.quiet or not full:
3051 if ui.quiet or not full:
3048 doc = doc.splitlines()[0]
3052 doc = doc.splitlines()[0]
3049 rst += "\n" + doc + "\n"
3053 rst += "\n" + doc + "\n"
3050
3054
3051 # check if this command shadows a non-trivial (multi-line)
3055 # check if this command shadows a non-trivial (multi-line)
3052 # extension help text
3056 # extension help text
3053 try:
3057 try:
3054 mod = extensions.find(name)
3058 mod = extensions.find(name)
3055 doc = gettext(mod.__doc__) or ''
3059 doc = gettext(mod.__doc__) or ''
3056 if '\n' in doc.strip():
3060 if '\n' in doc.strip():
3057 msg = _('use "hg help -e %s" to show help for '
3061 msg = _('use "hg help -e %s" to show help for '
3058 'the %s extension') % (name, name)
3062 'the %s extension') % (name, name)
3059 rst += '\n%s\n' % msg
3063 rst += '\n%s\n' % msg
3060 except KeyError:
3064 except KeyError:
3061 pass
3065 pass
3062
3066
3063 # options
3067 # options
3064 if not ui.quiet and entry[1]:
3068 if not ui.quiet and entry[1]:
3065 rst += '\n'
3069 rst += '\n'
3066 rst += _("options:")
3070 rst += _("options:")
3067 rst += '\n\n'
3071 rst += '\n\n'
3068 rst += optrst(entry[1])
3072 rst += optrst(entry[1])
3069
3073
3070 if ui.verbose:
3074 if ui.verbose:
3071 rst += '\n'
3075 rst += '\n'
3072 rst += _("global options:")
3076 rst += _("global options:")
3073 rst += '\n\n'
3077 rst += '\n\n'
3074 rst += optrst(globalopts)
3078 rst += optrst(globalopts)
3075
3079
3076 keep = ui.verbose and ['verbose'] or []
3080 keep = ui.verbose and ['verbose'] or []
3077 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3081 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3078 ui.write(formatted)
3082 ui.write(formatted)
3079
3083
3080 if not ui.verbose:
3084 if not ui.verbose:
3081 if not full:
3085 if not full:
3082 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3086 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3083 % name)
3087 % name)
3084 elif not ui.quiet:
3088 elif not ui.quiet:
3085 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3089 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3086
3090
3087
3091
3088 def helplist(select=None):
3092 def helplist(select=None):
3089 # list of commands
3093 # list of commands
3090 if name == "shortlist":
3094 if name == "shortlist":
3091 header = _('basic commands:\n\n')
3095 header = _('basic commands:\n\n')
3092 else:
3096 else:
3093 header = _('list of commands:\n\n')
3097 header = _('list of commands:\n\n')
3094
3098
3095 h = {}
3099 h = {}
3096 cmds = {}
3100 cmds = {}
3097 for c, e in table.iteritems():
3101 for c, e in table.iteritems():
3098 f = c.split("|", 1)[0]
3102 f = c.split("|", 1)[0]
3099 if select and not select(f):
3103 if select and not select(f):
3100 continue
3104 continue
3101 if (not select and name != 'shortlist' and
3105 if (not select and name != 'shortlist' and
3102 e[0].__module__ != __name__):
3106 e[0].__module__ != __name__):
3103 continue
3107 continue
3104 if name == "shortlist" and not f.startswith("^"):
3108 if name == "shortlist" and not f.startswith("^"):
3105 continue
3109 continue
3106 f = f.lstrip("^")
3110 f = f.lstrip("^")
3107 if not ui.debugflag and f.startswith("debug"):
3111 if not ui.debugflag and f.startswith("debug"):
3108 continue
3112 continue
3109 doc = e[0].__doc__
3113 doc = e[0].__doc__
3110 if doc and 'DEPRECATED' in doc and not ui.verbose:
3114 if doc and 'DEPRECATED' in doc and not ui.verbose:
3111 continue
3115 continue
3112 doc = gettext(doc)
3116 doc = gettext(doc)
3113 if not doc:
3117 if not doc:
3114 doc = _("(no help text available)")
3118 doc = _("(no help text available)")
3115 h[f] = doc.splitlines()[0].rstrip()
3119 h[f] = doc.splitlines()[0].rstrip()
3116 cmds[f] = c.lstrip("^")
3120 cmds[f] = c.lstrip("^")
3117
3121
3118 if not h:
3122 if not h:
3119 ui.status(_('no commands defined\n'))
3123 ui.status(_('no commands defined\n'))
3120 return
3124 return
3121
3125
3122 ui.status(header)
3126 ui.status(header)
3123 fns = sorted(h)
3127 fns = sorted(h)
3124 m = max(map(len, fns))
3128 m = max(map(len, fns))
3125 for f in fns:
3129 for f in fns:
3126 if ui.verbose:
3130 if ui.verbose:
3127 commands = cmds[f].replace("|",", ")
3131 commands = cmds[f].replace("|",", ")
3128 ui.write(" %s:\n %s\n"%(commands, h[f]))
3132 ui.write(" %s:\n %s\n"%(commands, h[f]))
3129 else:
3133 else:
3130 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3134 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3131 initindent=' %-*s ' % (m, f),
3135 initindent=' %-*s ' % (m, f),
3132 hangindent=' ' * (m + 4))))
3136 hangindent=' ' * (m + 4))))
3133
3137
3134 if not name:
3138 if not name:
3135 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3139 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3136 if text:
3140 if text:
3137 ui.write("\n%s" % minirst.format(text, textwidth))
3141 ui.write("\n%s" % minirst.format(text, textwidth))
3138
3142
3139 ui.write(_("\nadditional help topics:\n\n"))
3143 ui.write(_("\nadditional help topics:\n\n"))
3140 topics = []
3144 topics = []
3141 for names, header, doc in help.helptable:
3145 for names, header, doc in help.helptable:
3142 topics.append((sorted(names, key=len, reverse=True)[0], header))
3146 topics.append((sorted(names, key=len, reverse=True)[0], header))
3143 topics_len = max([len(s[0]) for s in topics])
3147 topics_len = max([len(s[0]) for s in topics])
3144 for t, desc in topics:
3148 for t, desc in topics:
3145 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3149 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3146
3150
3147 optlist = []
3151 optlist = []
3148 addglobalopts(optlist, True)
3152 addglobalopts(optlist, True)
3149 ui.write(opttext(optlist, textwidth))
3153 ui.write(opttext(optlist, textwidth))
3150
3154
3151 def helptopic(name):
3155 def helptopic(name):
3152 for names, header, doc in help.helptable:
3156 for names, header, doc in help.helptable:
3153 if name in names:
3157 if name in names:
3154 break
3158 break
3155 else:
3159 else:
3156 raise error.UnknownCommand(name)
3160 raise error.UnknownCommand(name)
3157
3161
3158 # description
3162 # description
3159 if not doc:
3163 if not doc:
3160 doc = _("(no help text available)")
3164 doc = _("(no help text available)")
3161 if util.safehasattr(doc, '__call__'):
3165 if util.safehasattr(doc, '__call__'):
3162 doc = doc()
3166 doc = doc()
3163
3167
3164 ui.write("%s\n\n" % header)
3168 ui.write("%s\n\n" % header)
3165 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3169 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3166 try:
3170 try:
3167 cmdutil.findcmd(name, table)
3171 cmdutil.findcmd(name, table)
3168 ui.write(_('\nuse "hg help -c %s" to see help for '
3172 ui.write(_('\nuse "hg help -c %s" to see help for '
3169 'the %s command\n') % (name, name))
3173 'the %s command\n') % (name, name))
3170 except error.UnknownCommand:
3174 except error.UnknownCommand:
3171 pass
3175 pass
3172
3176
3173 def helpext(name):
3177 def helpext(name):
3174 try:
3178 try:
3175 mod = extensions.find(name)
3179 mod = extensions.find(name)
3176 doc = gettext(mod.__doc__) or _('no help text available')
3180 doc = gettext(mod.__doc__) or _('no help text available')
3177 except KeyError:
3181 except KeyError:
3178 mod = None
3182 mod = None
3179 doc = extensions.disabledext(name)
3183 doc = extensions.disabledext(name)
3180 if not doc:
3184 if not doc:
3181 raise error.UnknownCommand(name)
3185 raise error.UnknownCommand(name)
3182
3186
3183 if '\n' not in doc:
3187 if '\n' not in doc:
3184 head, tail = doc, ""
3188 head, tail = doc, ""
3185 else:
3189 else:
3186 head, tail = doc.split('\n', 1)
3190 head, tail = doc.split('\n', 1)
3187 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3191 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3188 if tail:
3192 if tail:
3189 ui.write(minirst.format(tail, textwidth))
3193 ui.write(minirst.format(tail, textwidth))
3190 ui.status('\n')
3194 ui.status('\n')
3191
3195
3192 if mod:
3196 if mod:
3193 try:
3197 try:
3194 ct = mod.cmdtable
3198 ct = mod.cmdtable
3195 except AttributeError:
3199 except AttributeError:
3196 ct = {}
3200 ct = {}
3197 modcmds = set([c.split('|', 1)[0] for c in ct])
3201 modcmds = set([c.split('|', 1)[0] for c in ct])
3198 helplist(modcmds.__contains__)
3202 helplist(modcmds.__contains__)
3199 else:
3203 else:
3200 ui.write(_('use "hg help extensions" for information on enabling '
3204 ui.write(_('use "hg help extensions" for information on enabling '
3201 'extensions\n'))
3205 'extensions\n'))
3202
3206
3203 def helpextcmd(name):
3207 def helpextcmd(name):
3204 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3208 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3205 doc = gettext(mod.__doc__).splitlines()[0]
3209 doc = gettext(mod.__doc__).splitlines()[0]
3206
3210
3207 msg = help.listexts(_("'%s' is provided by the following "
3211 msg = help.listexts(_("'%s' is provided by the following "
3208 "extension:") % cmd, {ext: doc}, indent=4)
3212 "extension:") % cmd, {ext: doc}, indent=4)
3209 ui.write(minirst.format(msg, textwidth))
3213 ui.write(minirst.format(msg, textwidth))
3210 ui.write('\n')
3214 ui.write('\n')
3211 ui.write(_('use "hg help extensions" for information on enabling '
3215 ui.write(_('use "hg help extensions" for information on enabling '
3212 'extensions\n'))
3216 'extensions\n'))
3213
3217
3214 if name and name != 'shortlist':
3218 if name and name != 'shortlist':
3215 i = None
3219 i = None
3216 if unknowncmd:
3220 if unknowncmd:
3217 queries = (helpextcmd,)
3221 queries = (helpextcmd,)
3218 elif opts.get('extension'):
3222 elif opts.get('extension'):
3219 queries = (helpext,)
3223 queries = (helpext,)
3220 elif opts.get('command'):
3224 elif opts.get('command'):
3221 queries = (helpcmd,)
3225 queries = (helpcmd,)
3222 else:
3226 else:
3223 queries = (helptopic, helpcmd, helpext, helpextcmd)
3227 queries = (helptopic, helpcmd, helpext, helpextcmd)
3224 for f in queries:
3228 for f in queries:
3225 try:
3229 try:
3226 f(name)
3230 f(name)
3227 i = None
3231 i = None
3228 break
3232 break
3229 except error.UnknownCommand, inst:
3233 except error.UnknownCommand, inst:
3230 i = inst
3234 i = inst
3231 if i:
3235 if i:
3232 raise i
3236 raise i
3233 else:
3237 else:
3234 # program name
3238 # program name
3235 ui.status(_("Mercurial Distributed SCM\n"))
3239 ui.status(_("Mercurial Distributed SCM\n"))
3236 ui.status('\n')
3240 ui.status('\n')
3237 helplist()
3241 helplist()
3238
3242
3239
3243
3240 @command('identify|id',
3244 @command('identify|id',
3241 [('r', 'rev', '',
3245 [('r', 'rev', '',
3242 _('identify the specified revision'), _('REV')),
3246 _('identify the specified revision'), _('REV')),
3243 ('n', 'num', None, _('show local revision number')),
3247 ('n', 'num', None, _('show local revision number')),
3244 ('i', 'id', None, _('show global revision id')),
3248 ('i', 'id', None, _('show global revision id')),
3245 ('b', 'branch', None, _('show branch')),
3249 ('b', 'branch', None, _('show branch')),
3246 ('t', 'tags', None, _('show tags')),
3250 ('t', 'tags', None, _('show tags')),
3247 ('B', 'bookmarks', None, _('show bookmarks')),
3251 ('B', 'bookmarks', None, _('show bookmarks')),
3248 ] + remoteopts,
3252 ] + remoteopts,
3249 _('[-nibtB] [-r REV] [SOURCE]'))
3253 _('[-nibtB] [-r REV] [SOURCE]'))
3250 def identify(ui, repo, source=None, rev=None,
3254 def identify(ui, repo, source=None, rev=None,
3251 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3255 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3252 """identify the working copy or specified revision
3256 """identify the working copy or specified revision
3253
3257
3254 Print a summary identifying the repository state at REV using one or
3258 Print a summary identifying the repository state at REV using one or
3255 two parent hash identifiers, followed by a "+" if the working
3259 two parent hash identifiers, followed by a "+" if the working
3256 directory has uncommitted changes, the branch name (if not default),
3260 directory has uncommitted changes, the branch name (if not default),
3257 a list of tags, and a list of bookmarks.
3261 a list of tags, and a list of bookmarks.
3258
3262
3259 When REV is not given, print a summary of the current state of the
3263 When REV is not given, print a summary of the current state of the
3260 repository.
3264 repository.
3261
3265
3262 Specifying a path to a repository root or Mercurial bundle will
3266 Specifying a path to a repository root or Mercurial bundle will
3263 cause lookup to operate on that repository/bundle.
3267 cause lookup to operate on that repository/bundle.
3264
3268
3265 .. container:: verbose
3269 .. container:: verbose
3266
3270
3267 Examples:
3271 Examples:
3268
3272
3269 - generate a build identifier for the working directory::
3273 - generate a build identifier for the working directory::
3270
3274
3271 hg id --id > build-id.dat
3275 hg id --id > build-id.dat
3272
3276
3273 - find the revision corresponding to a tag::
3277 - find the revision corresponding to a tag::
3274
3278
3275 hg id -n -r 1.3
3279 hg id -n -r 1.3
3276
3280
3277 - check the most recent revision of a remote repository::
3281 - check the most recent revision of a remote repository::
3278
3282
3279 hg id -r tip http://selenic.com/hg/
3283 hg id -r tip http://selenic.com/hg/
3280
3284
3281 Returns 0 if successful.
3285 Returns 0 if successful.
3282 """
3286 """
3283
3287
3284 if not repo and not source:
3288 if not repo and not source:
3285 raise util.Abort(_("there is no Mercurial repository here "
3289 raise util.Abort(_("there is no Mercurial repository here "
3286 "(.hg not found)"))
3290 "(.hg not found)"))
3287
3291
3288 hexfunc = ui.debugflag and hex or short
3292 hexfunc = ui.debugflag and hex or short
3289 default = not (num or id or branch or tags or bookmarks)
3293 default = not (num or id or branch or tags or bookmarks)
3290 output = []
3294 output = []
3291 revs = []
3295 revs = []
3292
3296
3293 if source:
3297 if source:
3294 source, branches = hg.parseurl(ui.expandpath(source))
3298 source, branches = hg.parseurl(ui.expandpath(source))
3295 repo = hg.peer(ui, opts, source)
3299 repo = hg.peer(ui, opts, source)
3296 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3300 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3297
3301
3298 if not repo.local():
3302 if not repo.local():
3299 if num or branch or tags:
3303 if num or branch or tags:
3300 raise util.Abort(
3304 raise util.Abort(
3301 _("can't query remote revision number, branch, or tags"))
3305 _("can't query remote revision number, branch, or tags"))
3302 if not rev and revs:
3306 if not rev and revs:
3303 rev = revs[0]
3307 rev = revs[0]
3304 if not rev:
3308 if not rev:
3305 rev = "tip"
3309 rev = "tip"
3306
3310
3307 remoterev = repo.lookup(rev)
3311 remoterev = repo.lookup(rev)
3308 if default or id:
3312 if default or id:
3309 output = [hexfunc(remoterev)]
3313 output = [hexfunc(remoterev)]
3310
3314
3311 def getbms():
3315 def getbms():
3312 bms = []
3316 bms = []
3313
3317
3314 if 'bookmarks' in repo.listkeys('namespaces'):
3318 if 'bookmarks' in repo.listkeys('namespaces'):
3315 hexremoterev = hex(remoterev)
3319 hexremoterev = hex(remoterev)
3316 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3320 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3317 if bmr == hexremoterev]
3321 if bmr == hexremoterev]
3318
3322
3319 return bms
3323 return bms
3320
3324
3321 if bookmarks:
3325 if bookmarks:
3322 output.extend(getbms())
3326 output.extend(getbms())
3323 elif default and not ui.quiet:
3327 elif default and not ui.quiet:
3324 # multiple bookmarks for a single parent separated by '/'
3328 # multiple bookmarks for a single parent separated by '/'
3325 bm = '/'.join(getbms())
3329 bm = '/'.join(getbms())
3326 if bm:
3330 if bm:
3327 output.append(bm)
3331 output.append(bm)
3328 else:
3332 else:
3329 if not rev:
3333 if not rev:
3330 ctx = repo[None]
3334 ctx = repo[None]
3331 parents = ctx.parents()
3335 parents = ctx.parents()
3332 changed = ""
3336 changed = ""
3333 if default or id or num:
3337 if default or id or num:
3334 changed = util.any(repo.status()) and "+" or ""
3338 changed = util.any(repo.status()) and "+" or ""
3335 if default or id:
3339 if default or id:
3336 output = ["%s%s" %
3340 output = ["%s%s" %
3337 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3341 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3338 if num:
3342 if num:
3339 output.append("%s%s" %
3343 output.append("%s%s" %
3340 ('+'.join([str(p.rev()) for p in parents]), changed))
3344 ('+'.join([str(p.rev()) for p in parents]), changed))
3341 else:
3345 else:
3342 ctx = scmutil.revsingle(repo, rev)
3346 ctx = scmutil.revsingle(repo, rev)
3343 if default or id:
3347 if default or id:
3344 output = [hexfunc(ctx.node())]
3348 output = [hexfunc(ctx.node())]
3345 if num:
3349 if num:
3346 output.append(str(ctx.rev()))
3350 output.append(str(ctx.rev()))
3347
3351
3348 if default and not ui.quiet:
3352 if default and not ui.quiet:
3349 b = ctx.branch()
3353 b = ctx.branch()
3350 if b != 'default':
3354 if b != 'default':
3351 output.append("(%s)" % b)
3355 output.append("(%s)" % b)
3352
3356
3353 # multiple tags for a single parent separated by '/'
3357 # multiple tags for a single parent separated by '/'
3354 t = '/'.join(ctx.tags())
3358 t = '/'.join(ctx.tags())
3355 if t:
3359 if t:
3356 output.append(t)
3360 output.append(t)
3357
3361
3358 # multiple bookmarks for a single parent separated by '/'
3362 # multiple bookmarks for a single parent separated by '/'
3359 bm = '/'.join(ctx.bookmarks())
3363 bm = '/'.join(ctx.bookmarks())
3360 if bm:
3364 if bm:
3361 output.append(bm)
3365 output.append(bm)
3362 else:
3366 else:
3363 if branch:
3367 if branch:
3364 output.append(ctx.branch())
3368 output.append(ctx.branch())
3365
3369
3366 if tags:
3370 if tags:
3367 output.extend(ctx.tags())
3371 output.extend(ctx.tags())
3368
3372
3369 if bookmarks:
3373 if bookmarks:
3370 output.extend(ctx.bookmarks())
3374 output.extend(ctx.bookmarks())
3371
3375
3372 ui.write("%s\n" % ' '.join(output))
3376 ui.write("%s\n" % ' '.join(output))
3373
3377
3374 @command('import|patch',
3378 @command('import|patch',
3375 [('p', 'strip', 1,
3379 [('p', 'strip', 1,
3376 _('directory strip option for patch. This has the same '
3380 _('directory strip option for patch. This has the same '
3377 'meaning as the corresponding patch option'), _('NUM')),
3381 'meaning as the corresponding patch option'), _('NUM')),
3378 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3382 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3379 ('e', 'edit', False, _('invoke editor on commit messages')),
3383 ('e', 'edit', False, _('invoke editor on commit messages')),
3380 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3384 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3381 ('', 'no-commit', None,
3385 ('', 'no-commit', None,
3382 _("don't commit, just update the working directory")),
3386 _("don't commit, just update the working directory")),
3383 ('', 'bypass', None,
3387 ('', 'bypass', None,
3384 _("apply patch without touching the working directory")),
3388 _("apply patch without touching the working directory")),
3385 ('', 'exact', None,
3389 ('', 'exact', None,
3386 _('apply patch to the nodes from which it was generated')),
3390 _('apply patch to the nodes from which it was generated')),
3387 ('', 'import-branch', None,
3391 ('', 'import-branch', None,
3388 _('use any branch information in patch (implied by --exact)'))] +
3392 _('use any branch information in patch (implied by --exact)'))] +
3389 commitopts + commitopts2 + similarityopts,
3393 commitopts + commitopts2 + similarityopts,
3390 _('[OPTION]... PATCH...'))
3394 _('[OPTION]... PATCH...'))
3391 def import_(ui, repo, patch1=None, *patches, **opts):
3395 def import_(ui, repo, patch1=None, *patches, **opts):
3392 """import an ordered set of patches
3396 """import an ordered set of patches
3393
3397
3394 Import a list of patches and commit them individually (unless
3398 Import a list of patches and commit them individually (unless
3395 --no-commit is specified).
3399 --no-commit is specified).
3396
3400
3397 If there are outstanding changes in the working directory, import
3401 If there are outstanding changes in the working directory, import
3398 will abort unless given the -f/--force flag.
3402 will abort unless given the -f/--force flag.
3399
3403
3400 You can import a patch straight from a mail message. Even patches
3404 You can import a patch straight from a mail message. Even patches
3401 as attachments work (to use the body part, it must have type
3405 as attachments work (to use the body part, it must have type
3402 text/plain or text/x-patch). From and Subject headers of email
3406 text/plain or text/x-patch). From and Subject headers of email
3403 message are used as default committer and commit message. All
3407 message are used as default committer and commit message. All
3404 text/plain body parts before first diff are added to commit
3408 text/plain body parts before first diff are added to commit
3405 message.
3409 message.
3406
3410
3407 If the imported patch was generated by :hg:`export`, user and
3411 If the imported patch was generated by :hg:`export`, user and
3408 description from patch override values from message headers and
3412 description from patch override values from message headers and
3409 body. Values given on command line with -m/--message and -u/--user
3413 body. Values given on command line with -m/--message and -u/--user
3410 override these.
3414 override these.
3411
3415
3412 If --exact is specified, import will set the working directory to
3416 If --exact is specified, import will set the working directory to
3413 the parent of each patch before applying it, and will abort if the
3417 the parent of each patch before applying it, and will abort if the
3414 resulting changeset has a different ID than the one recorded in
3418 resulting changeset has a different ID than the one recorded in
3415 the patch. This may happen due to character set problems or other
3419 the patch. This may happen due to character set problems or other
3416 deficiencies in the text patch format.
3420 deficiencies in the text patch format.
3417
3421
3418 Use --bypass to apply and commit patches directly to the
3422 Use --bypass to apply and commit patches directly to the
3419 repository, not touching the working directory. Without --exact,
3423 repository, not touching the working directory. Without --exact,
3420 patches will be applied on top of the working directory parent
3424 patches will be applied on top of the working directory parent
3421 revision.
3425 revision.
3422
3426
3423 With -s/--similarity, hg will attempt to discover renames and
3427 With -s/--similarity, hg will attempt to discover renames and
3424 copies in the patch in the same way as :hg:`addremove`.
3428 copies in the patch in the same way as :hg:`addremove`.
3425
3429
3426 To read a patch from standard input, use "-" as the patch name. If
3430 To read a patch from standard input, use "-" as the patch name. If
3427 a URL is specified, the patch will be downloaded from it.
3431 a URL is specified, the patch will be downloaded from it.
3428 See :hg:`help dates` for a list of formats valid for -d/--date.
3432 See :hg:`help dates` for a list of formats valid for -d/--date.
3429
3433
3430 .. container:: verbose
3434 .. container:: verbose
3431
3435
3432 Examples:
3436 Examples:
3433
3437
3434 - import a traditional patch from a website and detect renames::
3438 - import a traditional patch from a website and detect renames::
3435
3439
3436 hg import -s 80 http://example.com/bugfix.patch
3440 hg import -s 80 http://example.com/bugfix.patch
3437
3441
3438 - import a changeset from an hgweb server::
3442 - import a changeset from an hgweb server::
3439
3443
3440 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3444 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3441
3445
3442 - import all the patches in an Unix-style mbox::
3446 - import all the patches in an Unix-style mbox::
3443
3447
3444 hg import incoming-patches.mbox
3448 hg import incoming-patches.mbox
3445
3449
3446 - attempt to exactly restore an exported changeset (not always
3450 - attempt to exactly restore an exported changeset (not always
3447 possible)::
3451 possible)::
3448
3452
3449 hg import --exact proposed-fix.patch
3453 hg import --exact proposed-fix.patch
3450
3454
3451 Returns 0 on success.
3455 Returns 0 on success.
3452 """
3456 """
3453
3457
3454 if not patch1:
3458 if not patch1:
3455 raise util.Abort(_('need at least one patch to import'))
3459 raise util.Abort(_('need at least one patch to import'))
3456
3460
3457 patches = (patch1,) + patches
3461 patches = (patch1,) + patches
3458
3462
3459 date = opts.get('date')
3463 date = opts.get('date')
3460 if date:
3464 if date:
3461 opts['date'] = util.parsedate(date)
3465 opts['date'] = util.parsedate(date)
3462
3466
3463 editor = cmdutil.commiteditor
3467 editor = cmdutil.commiteditor
3464 if opts.get('edit'):
3468 if opts.get('edit'):
3465 editor = cmdutil.commitforceeditor
3469 editor = cmdutil.commitforceeditor
3466
3470
3467 update = not opts.get('bypass')
3471 update = not opts.get('bypass')
3468 if not update and opts.get('no_commit'):
3472 if not update and opts.get('no_commit'):
3469 raise util.Abort(_('cannot use --no-commit with --bypass'))
3473 raise util.Abort(_('cannot use --no-commit with --bypass'))
3470 try:
3474 try:
3471 sim = float(opts.get('similarity') or 0)
3475 sim = float(opts.get('similarity') or 0)
3472 except ValueError:
3476 except ValueError:
3473 raise util.Abort(_('similarity must be a number'))
3477 raise util.Abort(_('similarity must be a number'))
3474 if sim < 0 or sim > 100:
3478 if sim < 0 or sim > 100:
3475 raise util.Abort(_('similarity must be between 0 and 100'))
3479 raise util.Abort(_('similarity must be between 0 and 100'))
3476 if sim and not update:
3480 if sim and not update:
3477 raise util.Abort(_('cannot use --similarity with --bypass'))
3481 raise util.Abort(_('cannot use --similarity with --bypass'))
3478
3482
3479 if (opts.get('exact') or not opts.get('force')) and update:
3483 if (opts.get('exact') or not opts.get('force')) and update:
3480 cmdutil.bailifchanged(repo)
3484 cmdutil.bailifchanged(repo)
3481
3485
3482 base = opts["base"]
3486 base = opts["base"]
3483 strip = opts["strip"]
3487 strip = opts["strip"]
3484 wlock = lock = tr = None
3488 wlock = lock = tr = None
3485 msgs = []
3489 msgs = []
3486
3490
3487 def checkexact(repo, n, nodeid):
3491 def checkexact(repo, n, nodeid):
3488 if opts.get('exact') and hex(n) != nodeid:
3492 if opts.get('exact') and hex(n) != nodeid:
3489 repo.rollback()
3493 repo.rollback()
3490 raise util.Abort(_('patch is damaged or loses information'))
3494 raise util.Abort(_('patch is damaged or loses information'))
3491
3495
3492 def tryone(ui, hunk, parents):
3496 def tryone(ui, hunk, parents):
3493 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3497 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3494 patch.extract(ui, hunk)
3498 patch.extract(ui, hunk)
3495
3499
3496 if not tmpname:
3500 if not tmpname:
3497 return (None, None)
3501 return (None, None)
3498 msg = _('applied to working directory')
3502 msg = _('applied to working directory')
3499
3503
3500 try:
3504 try:
3501 cmdline_message = cmdutil.logmessage(ui, opts)
3505 cmdline_message = cmdutil.logmessage(ui, opts)
3502 if cmdline_message:
3506 if cmdline_message:
3503 # pickup the cmdline msg
3507 # pickup the cmdline msg
3504 message = cmdline_message
3508 message = cmdline_message
3505 elif message:
3509 elif message:
3506 # pickup the patch msg
3510 # pickup the patch msg
3507 message = message.strip()
3511 message = message.strip()
3508 else:
3512 else:
3509 # launch the editor
3513 # launch the editor
3510 message = None
3514 message = None
3511 ui.debug('message:\n%s\n' % message)
3515 ui.debug('message:\n%s\n' % message)
3512
3516
3513 if len(parents) == 1:
3517 if len(parents) == 1:
3514 parents.append(repo[nullid])
3518 parents.append(repo[nullid])
3515 if opts.get('exact'):
3519 if opts.get('exact'):
3516 if not nodeid or not p1:
3520 if not nodeid or not p1:
3517 raise util.Abort(_('not a Mercurial patch'))
3521 raise util.Abort(_('not a Mercurial patch'))
3518 p1 = repo[p1]
3522 p1 = repo[p1]
3519 p2 = repo[p2 or nullid]
3523 p2 = repo[p2 or nullid]
3520 elif p2:
3524 elif p2:
3521 try:
3525 try:
3522 p1 = repo[p1]
3526 p1 = repo[p1]
3523 p2 = repo[p2]
3527 p2 = repo[p2]
3524 # Without any options, consider p2 only if the
3528 # Without any options, consider p2 only if the
3525 # patch is being applied on top of the recorded
3529 # patch is being applied on top of the recorded
3526 # first parent.
3530 # first parent.
3527 if p1 != parents[0]:
3531 if p1 != parents[0]:
3528 p1 = parents[0]
3532 p1 = parents[0]
3529 p2 = repo[nullid]
3533 p2 = repo[nullid]
3530 except error.RepoError:
3534 except error.RepoError:
3531 p1, p2 = parents
3535 p1, p2 = parents
3532 else:
3536 else:
3533 p1, p2 = parents
3537 p1, p2 = parents
3534
3538
3535 n = None
3539 n = None
3536 if update:
3540 if update:
3537 if p1 != parents[0]:
3541 if p1 != parents[0]:
3538 hg.clean(repo, p1.node())
3542 hg.clean(repo, p1.node())
3539 if p2 != parents[1]:
3543 if p2 != parents[1]:
3540 repo.dirstate.setparents(p1.node(), p2.node())
3544 repo.dirstate.setparents(p1.node(), p2.node())
3541
3545
3542 if opts.get('exact') or opts.get('import_branch'):
3546 if opts.get('exact') or opts.get('import_branch'):
3543 repo.dirstate.setbranch(branch or 'default')
3547 repo.dirstate.setbranch(branch or 'default')
3544
3548
3545 files = set()
3549 files = set()
3546 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3550 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3547 eolmode=None, similarity=sim / 100.0)
3551 eolmode=None, similarity=sim / 100.0)
3548 files = list(files)
3552 files = list(files)
3549 if opts.get('no_commit'):
3553 if opts.get('no_commit'):
3550 if message:
3554 if message:
3551 msgs.append(message)
3555 msgs.append(message)
3552 else:
3556 else:
3553 if opts.get('exact') or p2:
3557 if opts.get('exact') or p2:
3554 # If you got here, you either use --force and know what
3558 # If you got here, you either use --force and know what
3555 # you are doing or used --exact or a merge patch while
3559 # you are doing or used --exact or a merge patch while
3556 # being updated to its first parent.
3560 # being updated to its first parent.
3557 m = None
3561 m = None
3558 else:
3562 else:
3559 m = scmutil.matchfiles(repo, files or [])
3563 m = scmutil.matchfiles(repo, files or [])
3560 n = repo.commit(message, opts.get('user') or user,
3564 n = repo.commit(message, opts.get('user') or user,
3561 opts.get('date') or date, match=m,
3565 opts.get('date') or date, match=m,
3562 editor=editor)
3566 editor=editor)
3563 checkexact(repo, n, nodeid)
3567 checkexact(repo, n, nodeid)
3564 else:
3568 else:
3565 if opts.get('exact') or opts.get('import_branch'):
3569 if opts.get('exact') or opts.get('import_branch'):
3566 branch = branch or 'default'
3570 branch = branch or 'default'
3567 else:
3571 else:
3568 branch = p1.branch()
3572 branch = p1.branch()
3569 store = patch.filestore()
3573 store = patch.filestore()
3570 try:
3574 try:
3571 files = set()
3575 files = set()
3572 try:
3576 try:
3573 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3577 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3574 files, eolmode=None)
3578 files, eolmode=None)
3575 except patch.PatchError, e:
3579 except patch.PatchError, e:
3576 raise util.Abort(str(e))
3580 raise util.Abort(str(e))
3577 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3581 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3578 message,
3582 message,
3579 opts.get('user') or user,
3583 opts.get('user') or user,
3580 opts.get('date') or date,
3584 opts.get('date') or date,
3581 branch, files, store,
3585 branch, files, store,
3582 editor=cmdutil.commiteditor)
3586 editor=cmdutil.commiteditor)
3583 repo.savecommitmessage(memctx.description())
3587 repo.savecommitmessage(memctx.description())
3584 n = memctx.commit()
3588 n = memctx.commit()
3585 checkexact(repo, n, nodeid)
3589 checkexact(repo, n, nodeid)
3586 finally:
3590 finally:
3587 store.close()
3591 store.close()
3588 if n:
3592 if n:
3589 # i18n: refers to a short changeset id
3593 # i18n: refers to a short changeset id
3590 msg = _('created %s') % short(n)
3594 msg = _('created %s') % short(n)
3591 return (msg, n)
3595 return (msg, n)
3592 finally:
3596 finally:
3593 os.unlink(tmpname)
3597 os.unlink(tmpname)
3594
3598
3595 try:
3599 try:
3596 try:
3600 try:
3597 wlock = repo.wlock()
3601 wlock = repo.wlock()
3598 lock = repo.lock()
3602 lock = repo.lock()
3599 tr = repo.transaction('import')
3603 tr = repo.transaction('import')
3600 parents = repo.parents()
3604 parents = repo.parents()
3601 for patchurl in patches:
3605 for patchurl in patches:
3602 if patchurl == '-':
3606 if patchurl == '-':
3603 ui.status(_('applying patch from stdin\n'))
3607 ui.status(_('applying patch from stdin\n'))
3604 patchfile = ui.fin
3608 patchfile = ui.fin
3605 patchurl = 'stdin' # for error message
3609 patchurl = 'stdin' # for error message
3606 else:
3610 else:
3607 patchurl = os.path.join(base, patchurl)
3611 patchurl = os.path.join(base, patchurl)
3608 ui.status(_('applying %s\n') % patchurl)
3612 ui.status(_('applying %s\n') % patchurl)
3609 patchfile = url.open(ui, patchurl)
3613 patchfile = url.open(ui, patchurl)
3610
3614
3611 haspatch = False
3615 haspatch = False
3612 for hunk in patch.split(patchfile):
3616 for hunk in patch.split(patchfile):
3613 (msg, node) = tryone(ui, hunk, parents)
3617 (msg, node) = tryone(ui, hunk, parents)
3614 if msg:
3618 if msg:
3615 haspatch = True
3619 haspatch = True
3616 ui.note(msg + '\n')
3620 ui.note(msg + '\n')
3617 if update or opts.get('exact'):
3621 if update or opts.get('exact'):
3618 parents = repo.parents()
3622 parents = repo.parents()
3619 else:
3623 else:
3620 parents = [repo[node]]
3624 parents = [repo[node]]
3621
3625
3622 if not haspatch:
3626 if not haspatch:
3623 raise util.Abort(_('%s: no diffs found') % patchurl)
3627 raise util.Abort(_('%s: no diffs found') % patchurl)
3624
3628
3625 tr.close()
3629 tr.close()
3626 if msgs:
3630 if msgs:
3627 repo.savecommitmessage('\n* * *\n'.join(msgs))
3631 repo.savecommitmessage('\n* * *\n'.join(msgs))
3628 except:
3632 except:
3629 # wlock.release() indirectly calls dirstate.write(): since
3633 # wlock.release() indirectly calls dirstate.write(): since
3630 # we're crashing, we do not want to change the working dir
3634 # we're crashing, we do not want to change the working dir
3631 # parent after all, so make sure it writes nothing
3635 # parent after all, so make sure it writes nothing
3632 repo.dirstate.invalidate()
3636 repo.dirstate.invalidate()
3633 raise
3637 raise
3634 finally:
3638 finally:
3635 if tr:
3639 if tr:
3636 tr.release()
3640 tr.release()
3637 release(lock, wlock)
3641 release(lock, wlock)
3638
3642
3639 @command('incoming|in',
3643 @command('incoming|in',
3640 [('f', 'force', None,
3644 [('f', 'force', None,
3641 _('run even if remote repository is unrelated')),
3645 _('run even if remote repository is unrelated')),
3642 ('n', 'newest-first', None, _('show newest record first')),
3646 ('n', 'newest-first', None, _('show newest record first')),
3643 ('', 'bundle', '',
3647 ('', 'bundle', '',
3644 _('file to store the bundles into'), _('FILE')),
3648 _('file to store the bundles into'), _('FILE')),
3645 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3649 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3646 ('B', 'bookmarks', False, _("compare bookmarks")),
3650 ('B', 'bookmarks', False, _("compare bookmarks")),
3647 ('b', 'branch', [],
3651 ('b', 'branch', [],
3648 _('a specific branch you would like to pull'), _('BRANCH')),
3652 _('a specific branch you would like to pull'), _('BRANCH')),
3649 ] + logopts + remoteopts + subrepoopts,
3653 ] + logopts + remoteopts + subrepoopts,
3650 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3654 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3651 def incoming(ui, repo, source="default", **opts):
3655 def incoming(ui, repo, source="default", **opts):
3652 """show new changesets found in source
3656 """show new changesets found in source
3653
3657
3654 Show new changesets found in the specified path/URL or the default
3658 Show new changesets found in the specified path/URL or the default
3655 pull location. These are the changesets that would have been pulled
3659 pull location. These are the changesets that would have been pulled
3656 if a pull at the time you issued this command.
3660 if a pull at the time you issued this command.
3657
3661
3658 For remote repository, using --bundle avoids downloading the
3662 For remote repository, using --bundle avoids downloading the
3659 changesets twice if the incoming is followed by a pull.
3663 changesets twice if the incoming is followed by a pull.
3660
3664
3661 See pull for valid source format details.
3665 See pull for valid source format details.
3662
3666
3663 Returns 0 if there are incoming changes, 1 otherwise.
3667 Returns 0 if there are incoming changes, 1 otherwise.
3664 """
3668 """
3665 if opts.get('bundle') and opts.get('subrepos'):
3669 if opts.get('bundle') and opts.get('subrepos'):
3666 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3670 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3667
3671
3668 if opts.get('bookmarks'):
3672 if opts.get('bookmarks'):
3669 source, branches = hg.parseurl(ui.expandpath(source),
3673 source, branches = hg.parseurl(ui.expandpath(source),
3670 opts.get('branch'))
3674 opts.get('branch'))
3671 other = hg.peer(repo, opts, source)
3675 other = hg.peer(repo, opts, source)
3672 if 'bookmarks' not in other.listkeys('namespaces'):
3676 if 'bookmarks' not in other.listkeys('namespaces'):
3673 ui.warn(_("remote doesn't support bookmarks\n"))
3677 ui.warn(_("remote doesn't support bookmarks\n"))
3674 return 0
3678 return 0
3675 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3679 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3676 return bookmarks.diff(ui, repo, other)
3680 return bookmarks.diff(ui, repo, other)
3677
3681
3678 repo._subtoppath = ui.expandpath(source)
3682 repo._subtoppath = ui.expandpath(source)
3679 try:
3683 try:
3680 return hg.incoming(ui, repo, source, opts)
3684 return hg.incoming(ui, repo, source, opts)
3681 finally:
3685 finally:
3682 del repo._subtoppath
3686 del repo._subtoppath
3683
3687
3684
3688
3685 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3689 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3686 def init(ui, dest=".", **opts):
3690 def init(ui, dest=".", **opts):
3687 """create a new repository in the given directory
3691 """create a new repository in the given directory
3688
3692
3689 Initialize a new repository in the given directory. If the given
3693 Initialize a new repository in the given directory. If the given
3690 directory does not exist, it will be created.
3694 directory does not exist, it will be created.
3691
3695
3692 If no directory is given, the current directory is used.
3696 If no directory is given, the current directory is used.
3693
3697
3694 It is possible to specify an ``ssh://`` URL as the destination.
3698 It is possible to specify an ``ssh://`` URL as the destination.
3695 See :hg:`help urls` for more information.
3699 See :hg:`help urls` for more information.
3696
3700
3697 Returns 0 on success.
3701 Returns 0 on success.
3698 """
3702 """
3699 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3703 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3700
3704
3701 @command('locate',
3705 @command('locate',
3702 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3706 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3703 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3707 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3704 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3708 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3705 ] + walkopts,
3709 ] + walkopts,
3706 _('[OPTION]... [PATTERN]...'))
3710 _('[OPTION]... [PATTERN]...'))
3707 def locate(ui, repo, *pats, **opts):
3711 def locate(ui, repo, *pats, **opts):
3708 """locate files matching specific patterns
3712 """locate files matching specific patterns
3709
3713
3710 Print files under Mercurial control in the working directory whose
3714 Print files under Mercurial control in the working directory whose
3711 names match the given patterns.
3715 names match the given patterns.
3712
3716
3713 By default, this command searches all directories in the working
3717 By default, this command searches all directories in the working
3714 directory. To search just the current directory and its
3718 directory. To search just the current directory and its
3715 subdirectories, use "--include .".
3719 subdirectories, use "--include .".
3716
3720
3717 If no patterns are given to match, this command prints the names
3721 If no patterns are given to match, this command prints the names
3718 of all files under Mercurial control in the working directory.
3722 of all files under Mercurial control in the working directory.
3719
3723
3720 If you want to feed the output of this command into the "xargs"
3724 If you want to feed the output of this command into the "xargs"
3721 command, use the -0 option to both this command and "xargs". This
3725 command, use the -0 option to both this command and "xargs". This
3722 will avoid the problem of "xargs" treating single filenames that
3726 will avoid the problem of "xargs" treating single filenames that
3723 contain whitespace as multiple filenames.
3727 contain whitespace as multiple filenames.
3724
3728
3725 Returns 0 if a match is found, 1 otherwise.
3729 Returns 0 if a match is found, 1 otherwise.
3726 """
3730 """
3727 end = opts.get('print0') and '\0' or '\n'
3731 end = opts.get('print0') and '\0' or '\n'
3728 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3732 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3729
3733
3730 ret = 1
3734 ret = 1
3731 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3735 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3732 m.bad = lambda x, y: False
3736 m.bad = lambda x, y: False
3733 for abs in repo[rev].walk(m):
3737 for abs in repo[rev].walk(m):
3734 if not rev and abs not in repo.dirstate:
3738 if not rev and abs not in repo.dirstate:
3735 continue
3739 continue
3736 if opts.get('fullpath'):
3740 if opts.get('fullpath'):
3737 ui.write(repo.wjoin(abs), end)
3741 ui.write(repo.wjoin(abs), end)
3738 else:
3742 else:
3739 ui.write(((pats and m.rel(abs)) or abs), end)
3743 ui.write(((pats and m.rel(abs)) or abs), end)
3740 ret = 0
3744 ret = 0
3741
3745
3742 return ret
3746 return ret
3743
3747
3744 @command('^log|history',
3748 @command('^log|history',
3745 [('f', 'follow', None,
3749 [('f', 'follow', None,
3746 _('follow changeset history, or file history across copies and renames')),
3750 _('follow changeset history, or file history across copies and renames')),
3747 ('', 'follow-first', None,
3751 ('', 'follow-first', None,
3748 _('only follow the first parent of merge changesets (DEPRECATED)')),
3752 _('only follow the first parent of merge changesets (DEPRECATED)')),
3749 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3753 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3750 ('C', 'copies', None, _('show copied files')),
3754 ('C', 'copies', None, _('show copied files')),
3751 ('k', 'keyword', [],
3755 ('k', 'keyword', [],
3752 _('do case-insensitive search for a given text'), _('TEXT')),
3756 _('do case-insensitive search for a given text'), _('TEXT')),
3753 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3757 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3754 ('', 'removed', None, _('include revisions where files were removed')),
3758 ('', 'removed', None, _('include revisions where files were removed')),
3755 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3759 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3756 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3760 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3757 ('', 'only-branch', [],
3761 ('', 'only-branch', [],
3758 _('show only changesets within the given named branch (DEPRECATED)'),
3762 _('show only changesets within the given named branch (DEPRECATED)'),
3759 _('BRANCH')),
3763 _('BRANCH')),
3760 ('b', 'branch', [],
3764 ('b', 'branch', [],
3761 _('show changesets within the given named branch'), _('BRANCH')),
3765 _('show changesets within the given named branch'), _('BRANCH')),
3762 ('P', 'prune', [],
3766 ('P', 'prune', [],
3763 _('do not display revision or any of its ancestors'), _('REV')),
3767 _('do not display revision or any of its ancestors'), _('REV')),
3764 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3768 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3765 ] + logopts + walkopts,
3769 ] + logopts + walkopts,
3766 _('[OPTION]... [FILE]'))
3770 _('[OPTION]... [FILE]'))
3767 def log(ui, repo, *pats, **opts):
3771 def log(ui, repo, *pats, **opts):
3768 """show revision history of entire repository or files
3772 """show revision history of entire repository or files
3769
3773
3770 Print the revision history of the specified files or the entire
3774 Print the revision history of the specified files or the entire
3771 project.
3775 project.
3772
3776
3773 If no revision range is specified, the default is ``tip:0`` unless
3777 If no revision range is specified, the default is ``tip:0`` unless
3774 --follow is set, in which case the working directory parent is
3778 --follow is set, in which case the working directory parent is
3775 used as the starting revision.
3779 used as the starting revision.
3776
3780
3777 File history is shown without following rename or copy history of
3781 File history is shown without following rename or copy history of
3778 files. Use -f/--follow with a filename to follow history across
3782 files. Use -f/--follow with a filename to follow history across
3779 renames and copies. --follow without a filename will only show
3783 renames and copies. --follow without a filename will only show
3780 ancestors or descendants of the starting revision.
3784 ancestors or descendants of the starting revision.
3781
3785
3782 By default this command prints revision number and changeset id,
3786 By default this command prints revision number and changeset id,
3783 tags, non-trivial parents, user, date and time, and a summary for
3787 tags, non-trivial parents, user, date and time, and a summary for
3784 each commit. When the -v/--verbose switch is used, the list of
3788 each commit. When the -v/--verbose switch is used, the list of
3785 changed files and full commit message are shown.
3789 changed files and full commit message are shown.
3786
3790
3787 .. note::
3791 .. note::
3788 log -p/--patch may generate unexpected diff output for merge
3792 log -p/--patch may generate unexpected diff output for merge
3789 changesets, as it will only compare the merge changeset against
3793 changesets, as it will only compare the merge changeset against
3790 its first parent. Also, only files different from BOTH parents
3794 its first parent. Also, only files different from BOTH parents
3791 will appear in files:.
3795 will appear in files:.
3792
3796
3793 .. note::
3797 .. note::
3794 for performance reasons, log FILE may omit duplicate changes
3798 for performance reasons, log FILE may omit duplicate changes
3795 made on branches and will not show deletions. To see all
3799 made on branches and will not show deletions. To see all
3796 changes including duplicates and deletions, use the --removed
3800 changes including duplicates and deletions, use the --removed
3797 switch.
3801 switch.
3798
3802
3799 .. container:: verbose
3803 .. container:: verbose
3800
3804
3801 Some examples:
3805 Some examples:
3802
3806
3803 - changesets with full descriptions and file lists::
3807 - changesets with full descriptions and file lists::
3804
3808
3805 hg log -v
3809 hg log -v
3806
3810
3807 - changesets ancestral to the working directory::
3811 - changesets ancestral to the working directory::
3808
3812
3809 hg log -f
3813 hg log -f
3810
3814
3811 - last 10 commits on the current branch::
3815 - last 10 commits on the current branch::
3812
3816
3813 hg log -l 10 -b .
3817 hg log -l 10 -b .
3814
3818
3815 - changesets showing all modifications of a file, including removals::
3819 - changesets showing all modifications of a file, including removals::
3816
3820
3817 hg log --removed file.c
3821 hg log --removed file.c
3818
3822
3819 - all changesets that touch a directory, with diffs, excluding merges::
3823 - all changesets that touch a directory, with diffs, excluding merges::
3820
3824
3821 hg log -Mp lib/
3825 hg log -Mp lib/
3822
3826
3823 - all revision numbers that match a keyword::
3827 - all revision numbers that match a keyword::
3824
3828
3825 hg log -k bug --template "{rev}\\n"
3829 hg log -k bug --template "{rev}\\n"
3826
3830
3827 - check if a given changeset is included is a tagged release::
3831 - check if a given changeset is included is a tagged release::
3828
3832
3829 hg log -r "a21ccf and ancestor(1.9)"
3833 hg log -r "a21ccf and ancestor(1.9)"
3830
3834
3831 - find all changesets by some user in a date range::
3835 - find all changesets by some user in a date range::
3832
3836
3833 hg log -k alice -d "may 2008 to jul 2008"
3837 hg log -k alice -d "may 2008 to jul 2008"
3834
3838
3835 - summary of all changesets after the last tag::
3839 - summary of all changesets after the last tag::
3836
3840
3837 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3841 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3838
3842
3839 See :hg:`help dates` for a list of formats valid for -d/--date.
3843 See :hg:`help dates` for a list of formats valid for -d/--date.
3840
3844
3841 See :hg:`help revisions` and :hg:`help revsets` for more about
3845 See :hg:`help revisions` and :hg:`help revsets` for more about
3842 specifying revisions.
3846 specifying revisions.
3843
3847
3844 Returns 0 on success.
3848 Returns 0 on success.
3845 """
3849 """
3846
3850
3847 matchfn = scmutil.match(repo[None], pats, opts)
3851 matchfn = scmutil.match(repo[None], pats, opts)
3848 limit = cmdutil.loglimit(opts)
3852 limit = cmdutil.loglimit(opts)
3849 count = 0
3853 count = 0
3850
3854
3851 endrev = None
3855 endrev = None
3852 if opts.get('copies') and opts.get('rev'):
3856 if opts.get('copies') and opts.get('rev'):
3853 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3857 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3854
3858
3855 df = False
3859 df = False
3856 if opts["date"]:
3860 if opts["date"]:
3857 df = util.matchdate(opts["date"])
3861 df = util.matchdate(opts["date"])
3858
3862
3859 branches = opts.get('branch', []) + opts.get('only_branch', [])
3863 branches = opts.get('branch', []) + opts.get('only_branch', [])
3860 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3864 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3861
3865
3862 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3866 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3863 def prep(ctx, fns):
3867 def prep(ctx, fns):
3864 rev = ctx.rev()
3868 rev = ctx.rev()
3865 parents = [p for p in repo.changelog.parentrevs(rev)
3869 parents = [p for p in repo.changelog.parentrevs(rev)
3866 if p != nullrev]
3870 if p != nullrev]
3867 if opts.get('no_merges') and len(parents) == 2:
3871 if opts.get('no_merges') and len(parents) == 2:
3868 return
3872 return
3869 if opts.get('only_merges') and len(parents) != 2:
3873 if opts.get('only_merges') and len(parents) != 2:
3870 return
3874 return
3871 if opts.get('branch') and ctx.branch() not in opts['branch']:
3875 if opts.get('branch') and ctx.branch() not in opts['branch']:
3872 return
3876 return
3873 if not opts.get('hidden') and ctx.hidden():
3877 if not opts.get('hidden') and ctx.hidden():
3874 return
3878 return
3875 if df and not df(ctx.date()[0]):
3879 if df and not df(ctx.date()[0]):
3876 return
3880 return
3877
3881
3878 lower = encoding.lower
3882 lower = encoding.lower
3879 if opts.get('user'):
3883 if opts.get('user'):
3880 luser = lower(ctx.user())
3884 luser = lower(ctx.user())
3881 for k in [lower(x) for x in opts['user']]:
3885 for k in [lower(x) for x in opts['user']]:
3882 if (k in luser):
3886 if (k in luser):
3883 break
3887 break
3884 else:
3888 else:
3885 return
3889 return
3886 if opts.get('keyword'):
3890 if opts.get('keyword'):
3887 luser = lower(ctx.user())
3891 luser = lower(ctx.user())
3888 ldesc = lower(ctx.description())
3892 ldesc = lower(ctx.description())
3889 lfiles = lower(" ".join(ctx.files()))
3893 lfiles = lower(" ".join(ctx.files()))
3890 for k in [lower(x) for x in opts['keyword']]:
3894 for k in [lower(x) for x in opts['keyword']]:
3891 if (k in luser or k in ldesc or k in lfiles):
3895 if (k in luser or k in ldesc or k in lfiles):
3892 break
3896 break
3893 else:
3897 else:
3894 return
3898 return
3895
3899
3896 copies = None
3900 copies = None
3897 if opts.get('copies') and rev:
3901 if opts.get('copies') and rev:
3898 copies = []
3902 copies = []
3899 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3903 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3900 for fn in ctx.files():
3904 for fn in ctx.files():
3901 rename = getrenamed(fn, rev)
3905 rename = getrenamed(fn, rev)
3902 if rename:
3906 if rename:
3903 copies.append((fn, rename[0]))
3907 copies.append((fn, rename[0]))
3904
3908
3905 revmatchfn = None
3909 revmatchfn = None
3906 if opts.get('patch') or opts.get('stat'):
3910 if opts.get('patch') or opts.get('stat'):
3907 if opts.get('follow') or opts.get('follow_first'):
3911 if opts.get('follow') or opts.get('follow_first'):
3908 # note: this might be wrong when following through merges
3912 # note: this might be wrong when following through merges
3909 revmatchfn = scmutil.match(repo[None], fns, default='path')
3913 revmatchfn = scmutil.match(repo[None], fns, default='path')
3910 else:
3914 else:
3911 revmatchfn = matchfn
3915 revmatchfn = matchfn
3912
3916
3913 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3917 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3914
3918
3915 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3919 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3916 if count == limit:
3920 if count == limit:
3917 break
3921 break
3918 if displayer.flush(ctx.rev()):
3922 if displayer.flush(ctx.rev()):
3919 count += 1
3923 count += 1
3920 displayer.close()
3924 displayer.close()
3921
3925
3922 @command('manifest',
3926 @command('manifest',
3923 [('r', 'rev', '', _('revision to display'), _('REV')),
3927 [('r', 'rev', '', _('revision to display'), _('REV')),
3924 ('', 'all', False, _("list files from all revisions"))],
3928 ('', 'all', False, _("list files from all revisions"))],
3925 _('[-r REV]'))
3929 _('[-r REV]'))
3926 def manifest(ui, repo, node=None, rev=None, **opts):
3930 def manifest(ui, repo, node=None, rev=None, **opts):
3927 """output the current or given revision of the project manifest
3931 """output the current or given revision of the project manifest
3928
3932
3929 Print a list of version controlled files for the given revision.
3933 Print a list of version controlled files for the given revision.
3930 If no revision is given, the first parent of the working directory
3934 If no revision is given, the first parent of the working directory
3931 is used, or the null revision if no revision is checked out.
3935 is used, or the null revision if no revision is checked out.
3932
3936
3933 With -v, print file permissions, symlink and executable bits.
3937 With -v, print file permissions, symlink and executable bits.
3934 With --debug, print file revision hashes.
3938 With --debug, print file revision hashes.
3935
3939
3936 If option --all is specified, the list of all files from all revisions
3940 If option --all is specified, the list of all files from all revisions
3937 is printed. This includes deleted and renamed files.
3941 is printed. This includes deleted and renamed files.
3938
3942
3939 Returns 0 on success.
3943 Returns 0 on success.
3940 """
3944 """
3941 if opts.get('all'):
3945 if opts.get('all'):
3942 if rev or node:
3946 if rev or node:
3943 raise util.Abort(_("can't specify a revision with --all"))
3947 raise util.Abort(_("can't specify a revision with --all"))
3944
3948
3945 res = []
3949 res = []
3946 prefix = "data/"
3950 prefix = "data/"
3947 suffix = ".i"
3951 suffix = ".i"
3948 plen = len(prefix)
3952 plen = len(prefix)
3949 slen = len(suffix)
3953 slen = len(suffix)
3950 lock = repo.lock()
3954 lock = repo.lock()
3951 try:
3955 try:
3952 for fn, b, size in repo.store.datafiles():
3956 for fn, b, size in repo.store.datafiles():
3953 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3957 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3954 res.append(fn[plen:-slen])
3958 res.append(fn[plen:-slen])
3955 finally:
3959 finally:
3956 lock.release()
3960 lock.release()
3957 for f in sorted(res):
3961 for f in sorted(res):
3958 ui.write("%s\n" % f)
3962 ui.write("%s\n" % f)
3959 return
3963 return
3960
3964
3961 if rev and node:
3965 if rev and node:
3962 raise util.Abort(_("please specify just one revision"))
3966 raise util.Abort(_("please specify just one revision"))
3963
3967
3964 if not node:
3968 if not node:
3965 node = rev
3969 node = rev
3966
3970
3967 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3971 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3968 ctx = scmutil.revsingle(repo, node)
3972 ctx = scmutil.revsingle(repo, node)
3969 for f in ctx:
3973 for f in ctx:
3970 if ui.debugflag:
3974 if ui.debugflag:
3971 ui.write("%40s " % hex(ctx.manifest()[f]))
3975 ui.write("%40s " % hex(ctx.manifest()[f]))
3972 if ui.verbose:
3976 if ui.verbose:
3973 ui.write(decor[ctx.flags(f)])
3977 ui.write(decor[ctx.flags(f)])
3974 ui.write("%s\n" % f)
3978 ui.write("%s\n" % f)
3975
3979
3976 @command('^merge',
3980 @command('^merge',
3977 [('f', 'force', None, _('force a merge with outstanding changes')),
3981 [('f', 'force', None, _('force a merge with outstanding changes')),
3978 ('r', 'rev', '', _('revision to merge'), _('REV')),
3982 ('r', 'rev', '', _('revision to merge'), _('REV')),
3979 ('P', 'preview', None,
3983 ('P', 'preview', None,
3980 _('review revisions to merge (no merge is performed)'))
3984 _('review revisions to merge (no merge is performed)'))
3981 ] + mergetoolopts,
3985 ] + mergetoolopts,
3982 _('[-P] [-f] [[-r] REV]'))
3986 _('[-P] [-f] [[-r] REV]'))
3983 def merge(ui, repo, node=None, **opts):
3987 def merge(ui, repo, node=None, **opts):
3984 """merge working directory with another revision
3988 """merge working directory with another revision
3985
3989
3986 The current working directory is updated with all changes made in
3990 The current working directory is updated with all changes made in
3987 the requested revision since the last common predecessor revision.
3991 the requested revision since the last common predecessor revision.
3988
3992
3989 Files that changed between either parent are marked as changed for
3993 Files that changed between either parent are marked as changed for
3990 the next commit and a commit must be performed before any further
3994 the next commit and a commit must be performed before any further
3991 updates to the repository are allowed. The next commit will have
3995 updates to the repository are allowed. The next commit will have
3992 two parents.
3996 two parents.
3993
3997
3994 ``--tool`` can be used to specify the merge tool used for file
3998 ``--tool`` can be used to specify the merge tool used for file
3995 merges. It overrides the HGMERGE environment variable and your
3999 merges. It overrides the HGMERGE environment variable and your
3996 configuration files. See :hg:`help merge-tools` for options.
4000 configuration files. See :hg:`help merge-tools` for options.
3997
4001
3998 If no revision is specified, the working directory's parent is a
4002 If no revision is specified, the working directory's parent is a
3999 head revision, and the current branch contains exactly one other
4003 head revision, and the current branch contains exactly one other
4000 head, the other head is merged with by default. Otherwise, an
4004 head, the other head is merged with by default. Otherwise, an
4001 explicit revision with which to merge with must be provided.
4005 explicit revision with which to merge with must be provided.
4002
4006
4003 :hg:`resolve` must be used to resolve unresolved files.
4007 :hg:`resolve` must be used to resolve unresolved files.
4004
4008
4005 To undo an uncommitted merge, use :hg:`update --clean .` which
4009 To undo an uncommitted merge, use :hg:`update --clean .` which
4006 will check out a clean copy of the original merge parent, losing
4010 will check out a clean copy of the original merge parent, losing
4007 all changes.
4011 all changes.
4008
4012
4009 Returns 0 on success, 1 if there are unresolved files.
4013 Returns 0 on success, 1 if there are unresolved files.
4010 """
4014 """
4011
4015
4012 if opts.get('rev') and node:
4016 if opts.get('rev') and node:
4013 raise util.Abort(_("please specify just one revision"))
4017 raise util.Abort(_("please specify just one revision"))
4014 if not node:
4018 if not node:
4015 node = opts.get('rev')
4019 node = opts.get('rev')
4016
4020
4017 if not node:
4021 if not node:
4018 branch = repo[None].branch()
4022 branch = repo[None].branch()
4019 bheads = repo.branchheads(branch)
4023 bheads = repo.branchheads(branch)
4020 if len(bheads) > 2:
4024 if len(bheads) > 2:
4021 raise util.Abort(_("branch '%s' has %d heads - "
4025 raise util.Abort(_("branch '%s' has %d heads - "
4022 "please merge with an explicit rev")
4026 "please merge with an explicit rev")
4023 % (branch, len(bheads)),
4027 % (branch, len(bheads)),
4024 hint=_("run 'hg heads .' to see heads"))
4028 hint=_("run 'hg heads .' to see heads"))
4025
4029
4026 parent = repo.dirstate.p1()
4030 parent = repo.dirstate.p1()
4027 if len(bheads) == 1:
4031 if len(bheads) == 1:
4028 if len(repo.heads()) > 1:
4032 if len(repo.heads()) > 1:
4029 raise util.Abort(_("branch '%s' has one head - "
4033 raise util.Abort(_("branch '%s' has one head - "
4030 "please merge with an explicit rev")
4034 "please merge with an explicit rev")
4031 % branch,
4035 % branch,
4032 hint=_("run 'hg heads' to see all heads"))
4036 hint=_("run 'hg heads' to see all heads"))
4033 msg, hint = _('nothing to merge'), None
4037 msg, hint = _('nothing to merge'), None
4034 if parent != repo.lookup(branch):
4038 if parent != repo.lookup(branch):
4035 hint = _("use 'hg update' instead")
4039 hint = _("use 'hg update' instead")
4036 raise util.Abort(msg, hint=hint)
4040 raise util.Abort(msg, hint=hint)
4037
4041
4038 if parent not in bheads:
4042 if parent not in bheads:
4039 raise util.Abort(_('working directory not at a head revision'),
4043 raise util.Abort(_('working directory not at a head revision'),
4040 hint=_("use 'hg update' or merge with an "
4044 hint=_("use 'hg update' or merge with an "
4041 "explicit revision"))
4045 "explicit revision"))
4042 node = parent == bheads[0] and bheads[-1] or bheads[0]
4046 node = parent == bheads[0] and bheads[-1] or bheads[0]
4043 else:
4047 else:
4044 node = scmutil.revsingle(repo, node).node()
4048 node = scmutil.revsingle(repo, node).node()
4045
4049
4046 if opts.get('preview'):
4050 if opts.get('preview'):
4047 # find nodes that are ancestors of p2 but not of p1
4051 # find nodes that are ancestors of p2 but not of p1
4048 p1 = repo.lookup('.')
4052 p1 = repo.lookup('.')
4049 p2 = repo.lookup(node)
4053 p2 = repo.lookup(node)
4050 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4054 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4051
4055
4052 displayer = cmdutil.show_changeset(ui, repo, opts)
4056 displayer = cmdutil.show_changeset(ui, repo, opts)
4053 for node in nodes:
4057 for node in nodes:
4054 displayer.show(repo[node])
4058 displayer.show(repo[node])
4055 displayer.close()
4059 displayer.close()
4056 return 0
4060 return 0
4057
4061
4058 try:
4062 try:
4059 # ui.forcemerge is an internal variable, do not document
4063 # ui.forcemerge is an internal variable, do not document
4060 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4064 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4061 return hg.merge(repo, node, force=opts.get('force'))
4065 return hg.merge(repo, node, force=opts.get('force'))
4062 finally:
4066 finally:
4063 ui.setconfig('ui', 'forcemerge', '')
4067 ui.setconfig('ui', 'forcemerge', '')
4064
4068
4065 @command('outgoing|out',
4069 @command('outgoing|out',
4066 [('f', 'force', None, _('run even when the destination is unrelated')),
4070 [('f', 'force', None, _('run even when the destination is unrelated')),
4067 ('r', 'rev', [],
4071 ('r', 'rev', [],
4068 _('a changeset intended to be included in the destination'), _('REV')),
4072 _('a changeset intended to be included in the destination'), _('REV')),
4069 ('n', 'newest-first', None, _('show newest record first')),
4073 ('n', 'newest-first', None, _('show newest record first')),
4070 ('B', 'bookmarks', False, _('compare bookmarks')),
4074 ('B', 'bookmarks', False, _('compare bookmarks')),
4071 ('b', 'branch', [], _('a specific branch you would like to push'),
4075 ('b', 'branch', [], _('a specific branch you would like to push'),
4072 _('BRANCH')),
4076 _('BRANCH')),
4073 ] + logopts + remoteopts + subrepoopts,
4077 ] + logopts + remoteopts + subrepoopts,
4074 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4078 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4075 def outgoing(ui, repo, dest=None, **opts):
4079 def outgoing(ui, repo, dest=None, **opts):
4076 """show changesets not found in the destination
4080 """show changesets not found in the destination
4077
4081
4078 Show changesets not found in the specified destination repository
4082 Show changesets not found in the specified destination repository
4079 or the default push location. These are the changesets that would
4083 or the default push location. These are the changesets that would
4080 be pushed if a push was requested.
4084 be pushed if a push was requested.
4081
4085
4082 See pull for details of valid destination formats.
4086 See pull for details of valid destination formats.
4083
4087
4084 Returns 0 if there are outgoing changes, 1 otherwise.
4088 Returns 0 if there are outgoing changes, 1 otherwise.
4085 """
4089 """
4086
4090
4087 if opts.get('bookmarks'):
4091 if opts.get('bookmarks'):
4088 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4092 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4089 dest, branches = hg.parseurl(dest, opts.get('branch'))
4093 dest, branches = hg.parseurl(dest, opts.get('branch'))
4090 other = hg.peer(repo, opts, dest)
4094 other = hg.peer(repo, opts, dest)
4091 if 'bookmarks' not in other.listkeys('namespaces'):
4095 if 'bookmarks' not in other.listkeys('namespaces'):
4092 ui.warn(_("remote doesn't support bookmarks\n"))
4096 ui.warn(_("remote doesn't support bookmarks\n"))
4093 return 0
4097 return 0
4094 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4098 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4095 return bookmarks.diff(ui, other, repo)
4099 return bookmarks.diff(ui, other, repo)
4096
4100
4097 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4101 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4098 try:
4102 try:
4099 return hg.outgoing(ui, repo, dest, opts)
4103 return hg.outgoing(ui, repo, dest, opts)
4100 finally:
4104 finally:
4101 del repo._subtoppath
4105 del repo._subtoppath
4102
4106
4103 @command('parents',
4107 @command('parents',
4104 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4108 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4105 ] + templateopts,
4109 ] + templateopts,
4106 _('[-r REV] [FILE]'))
4110 _('[-r REV] [FILE]'))
4107 def parents(ui, repo, file_=None, **opts):
4111 def parents(ui, repo, file_=None, **opts):
4108 """show the parents of the working directory or revision
4112 """show the parents of the working directory or revision
4109
4113
4110 Print the working directory's parent revisions. If a revision is
4114 Print the working directory's parent revisions. If a revision is
4111 given via -r/--rev, the parent of that revision will be printed.
4115 given via -r/--rev, the parent of that revision will be printed.
4112 If a file argument is given, the revision in which the file was
4116 If a file argument is given, the revision in which the file was
4113 last changed (before the working directory revision or the
4117 last changed (before the working directory revision or the
4114 argument to --rev if given) is printed.
4118 argument to --rev if given) is printed.
4115
4119
4116 Returns 0 on success.
4120 Returns 0 on success.
4117 """
4121 """
4118
4122
4119 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4123 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4120
4124
4121 if file_:
4125 if file_:
4122 m = scmutil.match(ctx, (file_,), opts)
4126 m = scmutil.match(ctx, (file_,), opts)
4123 if m.anypats() or len(m.files()) != 1:
4127 if m.anypats() or len(m.files()) != 1:
4124 raise util.Abort(_('can only specify an explicit filename'))
4128 raise util.Abort(_('can only specify an explicit filename'))
4125 file_ = m.files()[0]
4129 file_ = m.files()[0]
4126 filenodes = []
4130 filenodes = []
4127 for cp in ctx.parents():
4131 for cp in ctx.parents():
4128 if not cp:
4132 if not cp:
4129 continue
4133 continue
4130 try:
4134 try:
4131 filenodes.append(cp.filenode(file_))
4135 filenodes.append(cp.filenode(file_))
4132 except error.LookupError:
4136 except error.LookupError:
4133 pass
4137 pass
4134 if not filenodes:
4138 if not filenodes:
4135 raise util.Abort(_("'%s' not found in manifest!") % file_)
4139 raise util.Abort(_("'%s' not found in manifest!") % file_)
4136 fl = repo.file(file_)
4140 fl = repo.file(file_)
4137 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4141 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4138 else:
4142 else:
4139 p = [cp.node() for cp in ctx.parents()]
4143 p = [cp.node() for cp in ctx.parents()]
4140
4144
4141 displayer = cmdutil.show_changeset(ui, repo, opts)
4145 displayer = cmdutil.show_changeset(ui, repo, opts)
4142 for n in p:
4146 for n in p:
4143 if n != nullid:
4147 if n != nullid:
4144 displayer.show(repo[n])
4148 displayer.show(repo[n])
4145 displayer.close()
4149 displayer.close()
4146
4150
4147 @command('paths', [], _('[NAME]'))
4151 @command('paths', [], _('[NAME]'))
4148 def paths(ui, repo, search=None):
4152 def paths(ui, repo, search=None):
4149 """show aliases for remote repositories
4153 """show aliases for remote repositories
4150
4154
4151 Show definition of symbolic path name NAME. If no name is given,
4155 Show definition of symbolic path name NAME. If no name is given,
4152 show definition of all available names.
4156 show definition of all available names.
4153
4157
4154 Option -q/--quiet suppresses all output when searching for NAME
4158 Option -q/--quiet suppresses all output when searching for NAME
4155 and shows only the path names when listing all definitions.
4159 and shows only the path names when listing all definitions.
4156
4160
4157 Path names are defined in the [paths] section of your
4161 Path names are defined in the [paths] section of your
4158 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4162 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4159 repository, ``.hg/hgrc`` is used, too.
4163 repository, ``.hg/hgrc`` is used, too.
4160
4164
4161 The path names ``default`` and ``default-push`` have a special
4165 The path names ``default`` and ``default-push`` have a special
4162 meaning. When performing a push or pull operation, they are used
4166 meaning. When performing a push or pull operation, they are used
4163 as fallbacks if no location is specified on the command-line.
4167 as fallbacks if no location is specified on the command-line.
4164 When ``default-push`` is set, it will be used for push and
4168 When ``default-push`` is set, it will be used for push and
4165 ``default`` will be used for pull; otherwise ``default`` is used
4169 ``default`` will be used for pull; otherwise ``default`` is used
4166 as the fallback for both. When cloning a repository, the clone
4170 as the fallback for both. When cloning a repository, the clone
4167 source is written as ``default`` in ``.hg/hgrc``. Note that
4171 source is written as ``default`` in ``.hg/hgrc``. Note that
4168 ``default`` and ``default-push`` apply to all inbound (e.g.
4172 ``default`` and ``default-push`` apply to all inbound (e.g.
4169 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4173 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4170 :hg:`bundle`) operations.
4174 :hg:`bundle`) operations.
4171
4175
4172 See :hg:`help urls` for more information.
4176 See :hg:`help urls` for more information.
4173
4177
4174 Returns 0 on success.
4178 Returns 0 on success.
4175 """
4179 """
4176 if search:
4180 if search:
4177 for name, path in ui.configitems("paths"):
4181 for name, path in ui.configitems("paths"):
4178 if name == search:
4182 if name == search:
4179 ui.status("%s\n" % util.hidepassword(path))
4183 ui.status("%s\n" % util.hidepassword(path))
4180 return
4184 return
4181 if not ui.quiet:
4185 if not ui.quiet:
4182 ui.warn(_("not found!\n"))
4186 ui.warn(_("not found!\n"))
4183 return 1
4187 return 1
4184 else:
4188 else:
4185 for name, path in ui.configitems("paths"):
4189 for name, path in ui.configitems("paths"):
4186 if ui.quiet:
4190 if ui.quiet:
4187 ui.write("%s\n" % name)
4191 ui.write("%s\n" % name)
4188 else:
4192 else:
4189 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4193 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4190
4194
4191 @command('^phase',
4195 @command('^phase',
4192 [('p', 'public', False, _('set changeset phase to public')),
4196 [('p', 'public', False, _('set changeset phase to public')),
4193 ('d', 'draft', False, _('set changeset phase to draft')),
4197 ('d', 'draft', False, _('set changeset phase to draft')),
4194 ('s', 'secret', False, _('set changeset phase to secret')),
4198 ('s', 'secret', False, _('set changeset phase to secret')),
4195 ('f', 'force', False, _('allow to move boundary backward')),
4199 ('f', 'force', False, _('allow to move boundary backward')),
4196 ('r', 'rev', [], _('target revision'), _('REV')),
4200 ('r', 'rev', [], _('target revision'), _('REV')),
4197 ],
4201 ],
4198 _('[-p|-d|-s] [-f] [-r] REV...'))
4202 _('[-p|-d|-s] [-f] [-r] REV...'))
4199 def phase(ui, repo, *revs, **opts):
4203 def phase(ui, repo, *revs, **opts):
4200 """set or show the current phase name
4204 """set or show the current phase name
4201
4205
4202 With no argument, show the phase name of specified revisions.
4206 With no argument, show the phase name of specified revisions.
4203
4207
4204 With one of -p/--public, -d/--draft or -s/--secret, change the
4208 With one of -p/--public, -d/--draft or -s/--secret, change the
4205 phase value of the specified revisions.
4209 phase value of the specified revisions.
4206
4210
4207 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4211 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4208 lower phase to an higher phase. Phases are ordered as follows::
4212 lower phase to an higher phase. Phases are ordered as follows::
4209
4213
4210 public < draft < secret
4214 public < draft < secret
4211
4215
4212 Return 0 on success, 1 if no phases were changed.
4216 Return 0 on success, 1 if no phases were changed.
4213 """
4217 """
4214 # search for a unique phase argument
4218 # search for a unique phase argument
4215 targetphase = None
4219 targetphase = None
4216 for idx, name in enumerate(phases.phasenames):
4220 for idx, name in enumerate(phases.phasenames):
4217 if opts[name]:
4221 if opts[name]:
4218 if targetphase is not None:
4222 if targetphase is not None:
4219 raise util.Abort(_('only one phase can be specified'))
4223 raise util.Abort(_('only one phase can be specified'))
4220 targetphase = idx
4224 targetphase = idx
4221
4225
4222 # look for specified revision
4226 # look for specified revision
4223 revs = list(revs)
4227 revs = list(revs)
4224 revs.extend(opts['rev'])
4228 revs.extend(opts['rev'])
4225 if not revs:
4229 if not revs:
4226 raise util.Abort(_('no revisions specified'))
4230 raise util.Abort(_('no revisions specified'))
4227
4231
4228 lock = None
4232 lock = None
4229 ret = 0
4233 ret = 0
4230 if targetphase is None:
4234 if targetphase is None:
4231 # display
4235 # display
4232 for ctx in repo.set('%lr', revs):
4236 for ctx in repo.set('%lr', revs):
4233 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4237 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4234 else:
4238 else:
4235 lock = repo.lock()
4239 lock = repo.lock()
4236 try:
4240 try:
4237 # set phase
4241 # set phase
4238 nodes = [ctx.node() for ctx in repo.set('%lr', revs)]
4242 nodes = [ctx.node() for ctx in repo.set('%lr', revs)]
4239 if not nodes:
4243 if not nodes:
4240 raise util.Abort(_('empty revision set'))
4244 raise util.Abort(_('empty revision set'))
4241 olddata = repo._phaserev[:]
4245 olddata = repo._phaserev[:]
4242 phases.advanceboundary(repo, targetphase, nodes)
4246 phases.advanceboundary(repo, targetphase, nodes)
4243 if opts['force']:
4247 if opts['force']:
4244 phases.retractboundary(repo, targetphase, nodes)
4248 phases.retractboundary(repo, targetphase, nodes)
4245 finally:
4249 finally:
4246 lock.release()
4250 lock.release()
4247 if olddata is not None:
4251 if olddata is not None:
4248 changes = 0
4252 changes = 0
4249 newdata = repo._phaserev
4253 newdata = repo._phaserev
4250 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4254 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4251 if changes:
4255 if changes:
4252 ui.note(_('phase change for %i changesets\n') % changes)
4256 ui.note(_('phase change for %i changesets\n') % changes)
4253 else:
4257 else:
4254 ui.warn(_('no phases changed\n'))
4258 ui.warn(_('no phases changed\n'))
4255 ret = 1
4259 ret = 1
4256 return ret
4260 return ret
4257
4261
4258 def postincoming(ui, repo, modheads, optupdate, checkout):
4262 def postincoming(ui, repo, modheads, optupdate, checkout):
4259 if modheads == 0:
4263 if modheads == 0:
4260 return
4264 return
4261 if optupdate:
4265 if optupdate:
4262 try:
4266 try:
4263 return hg.update(repo, checkout)
4267 return hg.update(repo, checkout)
4264 except util.Abort, inst:
4268 except util.Abort, inst:
4265 ui.warn(_("not updating: %s\n" % str(inst)))
4269 ui.warn(_("not updating: %s\n" % str(inst)))
4266 return 0
4270 return 0
4267 if modheads > 1:
4271 if modheads > 1:
4268 currentbranchheads = len(repo.branchheads())
4272 currentbranchheads = len(repo.branchheads())
4269 if currentbranchheads == modheads:
4273 if currentbranchheads == modheads:
4270 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4274 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4271 elif currentbranchheads > 1:
4275 elif currentbranchheads > 1:
4272 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4276 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4273 else:
4277 else:
4274 ui.status(_("(run 'hg heads' to see heads)\n"))
4278 ui.status(_("(run 'hg heads' to see heads)\n"))
4275 else:
4279 else:
4276 ui.status(_("(run 'hg update' to get a working copy)\n"))
4280 ui.status(_("(run 'hg update' to get a working copy)\n"))
4277
4281
4278 @command('^pull',
4282 @command('^pull',
4279 [('u', 'update', None,
4283 [('u', 'update', None,
4280 _('update to new branch head if changesets were pulled')),
4284 _('update to new branch head if changesets were pulled')),
4281 ('f', 'force', None, _('run even when remote repository is unrelated')),
4285 ('f', 'force', None, _('run even when remote repository is unrelated')),
4282 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4286 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4283 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4287 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4284 ('b', 'branch', [], _('a specific branch you would like to pull'),
4288 ('b', 'branch', [], _('a specific branch you would like to pull'),
4285 _('BRANCH')),
4289 _('BRANCH')),
4286 ] + remoteopts,
4290 ] + remoteopts,
4287 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4291 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4288 def pull(ui, repo, source="default", **opts):
4292 def pull(ui, repo, source="default", **opts):
4289 """pull changes from the specified source
4293 """pull changes from the specified source
4290
4294
4291 Pull changes from a remote repository to a local one.
4295 Pull changes from a remote repository to a local one.
4292
4296
4293 This finds all changes from the repository at the specified path
4297 This finds all changes from the repository at the specified path
4294 or URL and adds them to a local repository (the current one unless
4298 or URL and adds them to a local repository (the current one unless
4295 -R is specified). By default, this does not update the copy of the
4299 -R is specified). By default, this does not update the copy of the
4296 project in the working directory.
4300 project in the working directory.
4297
4301
4298 Use :hg:`incoming` if you want to see what would have been added
4302 Use :hg:`incoming` if you want to see what would have been added
4299 by a pull at the time you issued this command. If you then decide
4303 by a pull at the time you issued this command. If you then decide
4300 to add those changes to the repository, you should use :hg:`pull
4304 to add those changes to the repository, you should use :hg:`pull
4301 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4305 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4302
4306
4303 If SOURCE is omitted, the 'default' path will be used.
4307 If SOURCE is omitted, the 'default' path will be used.
4304 See :hg:`help urls` for more information.
4308 See :hg:`help urls` for more information.
4305
4309
4306 Returns 0 on success, 1 if an update had unresolved files.
4310 Returns 0 on success, 1 if an update had unresolved files.
4307 """
4311 """
4308 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4312 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4309 other = hg.peer(repo, opts, source)
4313 other = hg.peer(repo, opts, source)
4310 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4314 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4311 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4315 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4312
4316
4313 if opts.get('bookmark'):
4317 if opts.get('bookmark'):
4314 if not revs:
4318 if not revs:
4315 revs = []
4319 revs = []
4316 rb = other.listkeys('bookmarks')
4320 rb = other.listkeys('bookmarks')
4317 for b in opts['bookmark']:
4321 for b in opts['bookmark']:
4318 if b not in rb:
4322 if b not in rb:
4319 raise util.Abort(_('remote bookmark %s not found!') % b)
4323 raise util.Abort(_('remote bookmark %s not found!') % b)
4320 revs.append(rb[b])
4324 revs.append(rb[b])
4321
4325
4322 if revs:
4326 if revs:
4323 try:
4327 try:
4324 revs = [other.lookup(rev) for rev in revs]
4328 revs = [other.lookup(rev) for rev in revs]
4325 except error.CapabilityError:
4329 except error.CapabilityError:
4326 err = _("other repository doesn't support revision lookup, "
4330 err = _("other repository doesn't support revision lookup, "
4327 "so a rev cannot be specified.")
4331 "so a rev cannot be specified.")
4328 raise util.Abort(err)
4332 raise util.Abort(err)
4329
4333
4330 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4334 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4331 bookmarks.updatefromremote(ui, repo, other, source)
4335 bookmarks.updatefromremote(ui, repo, other, source)
4332 if checkout:
4336 if checkout:
4333 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4337 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4334 repo._subtoppath = source
4338 repo._subtoppath = source
4335 try:
4339 try:
4336 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4340 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4337
4341
4338 finally:
4342 finally:
4339 del repo._subtoppath
4343 del repo._subtoppath
4340
4344
4341 # update specified bookmarks
4345 # update specified bookmarks
4342 if opts.get('bookmark'):
4346 if opts.get('bookmark'):
4343 for b in opts['bookmark']:
4347 for b in opts['bookmark']:
4344 # explicit pull overrides local bookmark if any
4348 # explicit pull overrides local bookmark if any
4345 ui.status(_("importing bookmark %s\n") % b)
4349 ui.status(_("importing bookmark %s\n") % b)
4346 repo._bookmarks[b] = repo[rb[b]].node()
4350 repo._bookmarks[b] = repo[rb[b]].node()
4347 bookmarks.write(repo)
4351 bookmarks.write(repo)
4348
4352
4349 return ret
4353 return ret
4350
4354
4351 @command('^push',
4355 @command('^push',
4352 [('f', 'force', None, _('force push')),
4356 [('f', 'force', None, _('force push')),
4353 ('r', 'rev', [],
4357 ('r', 'rev', [],
4354 _('a changeset intended to be included in the destination'),
4358 _('a changeset intended to be included in the destination'),
4355 _('REV')),
4359 _('REV')),
4356 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4360 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4357 ('b', 'branch', [],
4361 ('b', 'branch', [],
4358 _('a specific branch you would like to push'), _('BRANCH')),
4362 _('a specific branch you would like to push'), _('BRANCH')),
4359 ('', 'new-branch', False, _('allow pushing a new branch')),
4363 ('', 'new-branch', False, _('allow pushing a new branch')),
4360 ] + remoteopts,
4364 ] + remoteopts,
4361 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4365 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4362 def push(ui, repo, dest=None, **opts):
4366 def push(ui, repo, dest=None, **opts):
4363 """push changes to the specified destination
4367 """push changes to the specified destination
4364
4368
4365 Push changesets from the local repository to the specified
4369 Push changesets from the local repository to the specified
4366 destination.
4370 destination.
4367
4371
4368 This operation is symmetrical to pull: it is identical to a pull
4372 This operation is symmetrical to pull: it is identical to a pull
4369 in the destination repository from the current one.
4373 in the destination repository from the current one.
4370
4374
4371 By default, push will not allow creation of new heads at the
4375 By default, push will not allow creation of new heads at the
4372 destination, since multiple heads would make it unclear which head
4376 destination, since multiple heads would make it unclear which head
4373 to use. In this situation, it is recommended to pull and merge
4377 to use. In this situation, it is recommended to pull and merge
4374 before pushing.
4378 before pushing.
4375
4379
4376 Use --new-branch if you want to allow push to create a new named
4380 Use --new-branch if you want to allow push to create a new named
4377 branch that is not present at the destination. This allows you to
4381 branch that is not present at the destination. This allows you to
4378 only create a new branch without forcing other changes.
4382 only create a new branch without forcing other changes.
4379
4383
4380 Use -f/--force to override the default behavior and push all
4384 Use -f/--force to override the default behavior and push all
4381 changesets on all branches.
4385 changesets on all branches.
4382
4386
4383 If -r/--rev is used, the specified revision and all its ancestors
4387 If -r/--rev is used, the specified revision and all its ancestors
4384 will be pushed to the remote repository.
4388 will be pushed to the remote repository.
4385
4389
4386 Please see :hg:`help urls` for important details about ``ssh://``
4390 Please see :hg:`help urls` for important details about ``ssh://``
4387 URLs. If DESTINATION is omitted, a default path will be used.
4391 URLs. If DESTINATION is omitted, a default path will be used.
4388
4392
4389 Returns 0 if push was successful, 1 if nothing to push.
4393 Returns 0 if push was successful, 1 if nothing to push.
4390 """
4394 """
4391
4395
4392 if opts.get('bookmark'):
4396 if opts.get('bookmark'):
4393 for b in opts['bookmark']:
4397 for b in opts['bookmark']:
4394 # translate -B options to -r so changesets get pushed
4398 # translate -B options to -r so changesets get pushed
4395 if b in repo._bookmarks:
4399 if b in repo._bookmarks:
4396 opts.setdefault('rev', []).append(b)
4400 opts.setdefault('rev', []).append(b)
4397 else:
4401 else:
4398 # if we try to push a deleted bookmark, translate it to null
4402 # if we try to push a deleted bookmark, translate it to null
4399 # this lets simultaneous -r, -b options continue working
4403 # this lets simultaneous -r, -b options continue working
4400 opts.setdefault('rev', []).append("null")
4404 opts.setdefault('rev', []).append("null")
4401
4405
4402 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4406 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4403 dest, branches = hg.parseurl(dest, opts.get('branch'))
4407 dest, branches = hg.parseurl(dest, opts.get('branch'))
4404 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4408 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4405 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4409 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4406 other = hg.peer(repo, opts, dest)
4410 other = hg.peer(repo, opts, dest)
4407 if revs:
4411 if revs:
4408 revs = [repo.lookup(rev) for rev in revs]
4412 revs = [repo.lookup(rev) for rev in revs]
4409
4413
4410 repo._subtoppath = dest
4414 repo._subtoppath = dest
4411 try:
4415 try:
4412 # push subrepos depth-first for coherent ordering
4416 # push subrepos depth-first for coherent ordering
4413 c = repo['']
4417 c = repo['']
4414 subs = c.substate # only repos that are committed
4418 subs = c.substate # only repos that are committed
4415 for s in sorted(subs):
4419 for s in sorted(subs):
4416 if not c.sub(s).push(opts):
4420 if not c.sub(s).push(opts):
4417 return False
4421 return False
4418 finally:
4422 finally:
4419 del repo._subtoppath
4423 del repo._subtoppath
4420 result = repo.push(other, opts.get('force'), revs=revs,
4424 result = repo.push(other, opts.get('force'), revs=revs,
4421 newbranch=opts.get('new_branch'))
4425 newbranch=opts.get('new_branch'))
4422
4426
4423 result = (result == 0)
4427 result = (result == 0)
4424
4428
4425 if opts.get('bookmark'):
4429 if opts.get('bookmark'):
4426 rb = other.listkeys('bookmarks')
4430 rb = other.listkeys('bookmarks')
4427 for b in opts['bookmark']:
4431 for b in opts['bookmark']:
4428 # explicit push overrides remote bookmark if any
4432 # explicit push overrides remote bookmark if any
4429 if b in repo._bookmarks:
4433 if b in repo._bookmarks:
4430 ui.status(_("exporting bookmark %s\n") % b)
4434 ui.status(_("exporting bookmark %s\n") % b)
4431 new = repo[b].hex()
4435 new = repo[b].hex()
4432 elif b in rb:
4436 elif b in rb:
4433 ui.status(_("deleting remote bookmark %s\n") % b)
4437 ui.status(_("deleting remote bookmark %s\n") % b)
4434 new = '' # delete
4438 new = '' # delete
4435 else:
4439 else:
4436 ui.warn(_('bookmark %s does not exist on the local '
4440 ui.warn(_('bookmark %s does not exist on the local '
4437 'or remote repository!\n') % b)
4441 'or remote repository!\n') % b)
4438 return 2
4442 return 2
4439 old = rb.get(b, '')
4443 old = rb.get(b, '')
4440 r = other.pushkey('bookmarks', b, old, new)
4444 r = other.pushkey('bookmarks', b, old, new)
4441 if not r:
4445 if not r:
4442 ui.warn(_('updating bookmark %s failed!\n') % b)
4446 ui.warn(_('updating bookmark %s failed!\n') % b)
4443 if not result:
4447 if not result:
4444 result = 2
4448 result = 2
4445
4449
4446 return result
4450 return result
4447
4451
4448 @command('recover', [])
4452 @command('recover', [])
4449 def recover(ui, repo):
4453 def recover(ui, repo):
4450 """roll back an interrupted transaction
4454 """roll back an interrupted transaction
4451
4455
4452 Recover from an interrupted commit or pull.
4456 Recover from an interrupted commit or pull.
4453
4457
4454 This command tries to fix the repository status after an
4458 This command tries to fix the repository status after an
4455 interrupted operation. It should only be necessary when Mercurial
4459 interrupted operation. It should only be necessary when Mercurial
4456 suggests it.
4460 suggests it.
4457
4461
4458 Returns 0 if successful, 1 if nothing to recover or verify fails.
4462 Returns 0 if successful, 1 if nothing to recover or verify fails.
4459 """
4463 """
4460 if repo.recover():
4464 if repo.recover():
4461 return hg.verify(repo)
4465 return hg.verify(repo)
4462 return 1
4466 return 1
4463
4467
4464 @command('^remove|rm',
4468 @command('^remove|rm',
4465 [('A', 'after', None, _('record delete for missing files')),
4469 [('A', 'after', None, _('record delete for missing files')),
4466 ('f', 'force', None,
4470 ('f', 'force', None,
4467 _('remove (and delete) file even if added or modified')),
4471 _('remove (and delete) file even if added or modified')),
4468 ] + walkopts,
4472 ] + walkopts,
4469 _('[OPTION]... FILE...'))
4473 _('[OPTION]... FILE...'))
4470 def remove(ui, repo, *pats, **opts):
4474 def remove(ui, repo, *pats, **opts):
4471 """remove the specified files on the next commit
4475 """remove the specified files on the next commit
4472
4476
4473 Schedule the indicated files for removal from the current branch.
4477 Schedule the indicated files for removal from the current branch.
4474
4478
4475 This command schedules the files to be removed at the next commit.
4479 This command schedules the files to be removed at the next commit.
4476 To undo a remove before that, see :hg:`revert`. To undo added
4480 To undo a remove before that, see :hg:`revert`. To undo added
4477 files, see :hg:`forget`.
4481 files, see :hg:`forget`.
4478
4482
4479 .. container:: verbose
4483 .. container:: verbose
4480
4484
4481 -A/--after can be used to remove only files that have already
4485 -A/--after can be used to remove only files that have already
4482 been deleted, -f/--force can be used to force deletion, and -Af
4486 been deleted, -f/--force can be used to force deletion, and -Af
4483 can be used to remove files from the next revision without
4487 can be used to remove files from the next revision without
4484 deleting them from the working directory.
4488 deleting them from the working directory.
4485
4489
4486 The following table details the behavior of remove for different
4490 The following table details the behavior of remove for different
4487 file states (columns) and option combinations (rows). The file
4491 file states (columns) and option combinations (rows). The file
4488 states are Added [A], Clean [C], Modified [M] and Missing [!]
4492 states are Added [A], Clean [C], Modified [M] and Missing [!]
4489 (as reported by :hg:`status`). The actions are Warn, Remove
4493 (as reported by :hg:`status`). The actions are Warn, Remove
4490 (from branch) and Delete (from disk):
4494 (from branch) and Delete (from disk):
4491
4495
4492 ======= == == == ==
4496 ======= == == == ==
4493 A C M !
4497 A C M !
4494 ======= == == == ==
4498 ======= == == == ==
4495 none W RD W R
4499 none W RD W R
4496 -f R RD RD R
4500 -f R RD RD R
4497 -A W W W R
4501 -A W W W R
4498 -Af R R R R
4502 -Af R R R R
4499 ======= == == == ==
4503 ======= == == == ==
4500
4504
4501 Note that remove never deletes files in Added [A] state from the
4505 Note that remove never deletes files in Added [A] state from the
4502 working directory, not even if option --force is specified.
4506 working directory, not even if option --force is specified.
4503
4507
4504 Returns 0 on success, 1 if any warnings encountered.
4508 Returns 0 on success, 1 if any warnings encountered.
4505 """
4509 """
4506
4510
4507 ret = 0
4511 ret = 0
4508 after, force = opts.get('after'), opts.get('force')
4512 after, force = opts.get('after'), opts.get('force')
4509 if not pats and not after:
4513 if not pats and not after:
4510 raise util.Abort(_('no files specified'))
4514 raise util.Abort(_('no files specified'))
4511
4515
4512 m = scmutil.match(repo[None], pats, opts)
4516 m = scmutil.match(repo[None], pats, opts)
4513 s = repo.status(match=m, clean=True)
4517 s = repo.status(match=m, clean=True)
4514 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4518 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4515
4519
4516 for f in m.files():
4520 for f in m.files():
4517 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4521 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4518 if os.path.exists(m.rel(f)):
4522 if os.path.exists(m.rel(f)):
4519 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4523 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4520 ret = 1
4524 ret = 1
4521
4525
4522 if force:
4526 if force:
4523 list = modified + deleted + clean + added
4527 list = modified + deleted + clean + added
4524 elif after:
4528 elif after:
4525 list = deleted
4529 list = deleted
4526 for f in modified + added + clean:
4530 for f in modified + added + clean:
4527 ui.warn(_('not removing %s: file still exists (use -f'
4531 ui.warn(_('not removing %s: file still exists (use -f'
4528 ' to force removal)\n') % m.rel(f))
4532 ' to force removal)\n') % m.rel(f))
4529 ret = 1
4533 ret = 1
4530 else:
4534 else:
4531 list = deleted + clean
4535 list = deleted + clean
4532 for f in modified:
4536 for f in modified:
4533 ui.warn(_('not removing %s: file is modified (use -f'
4537 ui.warn(_('not removing %s: file is modified (use -f'
4534 ' to force removal)\n') % m.rel(f))
4538 ' to force removal)\n') % m.rel(f))
4535 ret = 1
4539 ret = 1
4536 for f in added:
4540 for f in added:
4537 ui.warn(_('not removing %s: file has been marked for add'
4541 ui.warn(_('not removing %s: file has been marked for add'
4538 ' (use forget to undo)\n') % m.rel(f))
4542 ' (use forget to undo)\n') % m.rel(f))
4539 ret = 1
4543 ret = 1
4540
4544
4541 for f in sorted(list):
4545 for f in sorted(list):
4542 if ui.verbose or not m.exact(f):
4546 if ui.verbose or not m.exact(f):
4543 ui.status(_('removing %s\n') % m.rel(f))
4547 ui.status(_('removing %s\n') % m.rel(f))
4544
4548
4545 wlock = repo.wlock()
4549 wlock = repo.wlock()
4546 try:
4550 try:
4547 if not after:
4551 if not after:
4548 for f in list:
4552 for f in list:
4549 if f in added:
4553 if f in added:
4550 continue # we never unlink added files on remove
4554 continue # we never unlink added files on remove
4551 try:
4555 try:
4552 util.unlinkpath(repo.wjoin(f))
4556 util.unlinkpath(repo.wjoin(f))
4553 except OSError, inst:
4557 except OSError, inst:
4554 if inst.errno != errno.ENOENT:
4558 if inst.errno != errno.ENOENT:
4555 raise
4559 raise
4556 repo[None].forget(list)
4560 repo[None].forget(list)
4557 finally:
4561 finally:
4558 wlock.release()
4562 wlock.release()
4559
4563
4560 return ret
4564 return ret
4561
4565
4562 @command('rename|move|mv',
4566 @command('rename|move|mv',
4563 [('A', 'after', None, _('record a rename that has already occurred')),
4567 [('A', 'after', None, _('record a rename that has already occurred')),
4564 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4568 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4565 ] + walkopts + dryrunopts,
4569 ] + walkopts + dryrunopts,
4566 _('[OPTION]... SOURCE... DEST'))
4570 _('[OPTION]... SOURCE... DEST'))
4567 def rename(ui, repo, *pats, **opts):
4571 def rename(ui, repo, *pats, **opts):
4568 """rename files; equivalent of copy + remove
4572 """rename files; equivalent of copy + remove
4569
4573
4570 Mark dest as copies of sources; mark sources for deletion. If dest
4574 Mark dest as copies of sources; mark sources for deletion. If dest
4571 is a directory, copies are put in that directory. If dest is a
4575 is a directory, copies are put in that directory. If dest is a
4572 file, there can only be one source.
4576 file, there can only be one source.
4573
4577
4574 By default, this command copies the contents of files as they
4578 By default, this command copies the contents of files as they
4575 exist in the working directory. If invoked with -A/--after, the
4579 exist in the working directory. If invoked with -A/--after, the
4576 operation is recorded, but no copying is performed.
4580 operation is recorded, but no copying is performed.
4577
4581
4578 This command takes effect at the next commit. To undo a rename
4582 This command takes effect at the next commit. To undo a rename
4579 before that, see :hg:`revert`.
4583 before that, see :hg:`revert`.
4580
4584
4581 Returns 0 on success, 1 if errors are encountered.
4585 Returns 0 on success, 1 if errors are encountered.
4582 """
4586 """
4583 wlock = repo.wlock(False)
4587 wlock = repo.wlock(False)
4584 try:
4588 try:
4585 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4589 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4586 finally:
4590 finally:
4587 wlock.release()
4591 wlock.release()
4588
4592
4589 @command('resolve',
4593 @command('resolve',
4590 [('a', 'all', None, _('select all unresolved files')),
4594 [('a', 'all', None, _('select all unresolved files')),
4591 ('l', 'list', None, _('list state of files needing merge')),
4595 ('l', 'list', None, _('list state of files needing merge')),
4592 ('m', 'mark', None, _('mark files as resolved')),
4596 ('m', 'mark', None, _('mark files as resolved')),
4593 ('u', 'unmark', None, _('mark files as unresolved')),
4597 ('u', 'unmark', None, _('mark files as unresolved')),
4594 ('n', 'no-status', None, _('hide status prefix'))]
4598 ('n', 'no-status', None, _('hide status prefix'))]
4595 + mergetoolopts + walkopts,
4599 + mergetoolopts + walkopts,
4596 _('[OPTION]... [FILE]...'))
4600 _('[OPTION]... [FILE]...'))
4597 def resolve(ui, repo, *pats, **opts):
4601 def resolve(ui, repo, *pats, **opts):
4598 """redo merges or set/view the merge status of files
4602 """redo merges or set/view the merge status of files
4599
4603
4600 Merges with unresolved conflicts are often the result of
4604 Merges with unresolved conflicts are often the result of
4601 non-interactive merging using the ``internal:merge`` configuration
4605 non-interactive merging using the ``internal:merge`` configuration
4602 setting, or a command-line merge tool like ``diff3``. The resolve
4606 setting, or a command-line merge tool like ``diff3``. The resolve
4603 command is used to manage the files involved in a merge, after
4607 command is used to manage the files involved in a merge, after
4604 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4608 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4605 working directory must have two parents).
4609 working directory must have two parents).
4606
4610
4607 The resolve command can be used in the following ways:
4611 The resolve command can be used in the following ways:
4608
4612
4609 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4613 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4610 files, discarding any previous merge attempts. Re-merging is not
4614 files, discarding any previous merge attempts. Re-merging is not
4611 performed for files already marked as resolved. Use ``--all/-a``
4615 performed for files already marked as resolved. Use ``--all/-a``
4612 to select all unresolved files. ``--tool`` can be used to specify
4616 to select all unresolved files. ``--tool`` can be used to specify
4613 the merge tool used for the given files. It overrides the HGMERGE
4617 the merge tool used for the given files. It overrides the HGMERGE
4614 environment variable and your configuration files. Previous file
4618 environment variable and your configuration files. Previous file
4615 contents are saved with a ``.orig`` suffix.
4619 contents are saved with a ``.orig`` suffix.
4616
4620
4617 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4621 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4618 (e.g. after having manually fixed-up the files). The default is
4622 (e.g. after having manually fixed-up the files). The default is
4619 to mark all unresolved files.
4623 to mark all unresolved files.
4620
4624
4621 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4625 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4622 default is to mark all resolved files.
4626 default is to mark all resolved files.
4623
4627
4624 - :hg:`resolve -l`: list files which had or still have conflicts.
4628 - :hg:`resolve -l`: list files which had or still have conflicts.
4625 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4629 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4626
4630
4627 Note that Mercurial will not let you commit files with unresolved
4631 Note that Mercurial will not let you commit files with unresolved
4628 merge conflicts. You must use :hg:`resolve -m ...` before you can
4632 merge conflicts. You must use :hg:`resolve -m ...` before you can
4629 commit after a conflicting merge.
4633 commit after a conflicting merge.
4630
4634
4631 Returns 0 on success, 1 if any files fail a resolve attempt.
4635 Returns 0 on success, 1 if any files fail a resolve attempt.
4632 """
4636 """
4633
4637
4634 all, mark, unmark, show, nostatus = \
4638 all, mark, unmark, show, nostatus = \
4635 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4639 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4636
4640
4637 if (show and (mark or unmark)) or (mark and unmark):
4641 if (show and (mark or unmark)) or (mark and unmark):
4638 raise util.Abort(_("too many options specified"))
4642 raise util.Abort(_("too many options specified"))
4639 if pats and all:
4643 if pats and all:
4640 raise util.Abort(_("can't specify --all and patterns"))
4644 raise util.Abort(_("can't specify --all and patterns"))
4641 if not (all or pats or show or mark or unmark):
4645 if not (all or pats or show or mark or unmark):
4642 raise util.Abort(_('no files or directories specified; '
4646 raise util.Abort(_('no files or directories specified; '
4643 'use --all to remerge all files'))
4647 'use --all to remerge all files'))
4644
4648
4645 ms = mergemod.mergestate(repo)
4649 ms = mergemod.mergestate(repo)
4646 m = scmutil.match(repo[None], pats, opts)
4650 m = scmutil.match(repo[None], pats, opts)
4647 ret = 0
4651 ret = 0
4648
4652
4649 for f in ms:
4653 for f in ms:
4650 if m(f):
4654 if m(f):
4651 if show:
4655 if show:
4652 if nostatus:
4656 if nostatus:
4653 ui.write("%s\n" % f)
4657 ui.write("%s\n" % f)
4654 else:
4658 else:
4655 ui.write("%s %s\n" % (ms[f].upper(), f),
4659 ui.write("%s %s\n" % (ms[f].upper(), f),
4656 label='resolve.' +
4660 label='resolve.' +
4657 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4661 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4658 elif mark:
4662 elif mark:
4659 ms.mark(f, "r")
4663 ms.mark(f, "r")
4660 elif unmark:
4664 elif unmark:
4661 ms.mark(f, "u")
4665 ms.mark(f, "u")
4662 else:
4666 else:
4663 wctx = repo[None]
4667 wctx = repo[None]
4664 mctx = wctx.parents()[-1]
4668 mctx = wctx.parents()[-1]
4665
4669
4666 # backup pre-resolve (merge uses .orig for its own purposes)
4670 # backup pre-resolve (merge uses .orig for its own purposes)
4667 a = repo.wjoin(f)
4671 a = repo.wjoin(f)
4668 util.copyfile(a, a + ".resolve")
4672 util.copyfile(a, a + ".resolve")
4669
4673
4670 try:
4674 try:
4671 # resolve file
4675 # resolve file
4672 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4676 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4673 if ms.resolve(f, wctx, mctx):
4677 if ms.resolve(f, wctx, mctx):
4674 ret = 1
4678 ret = 1
4675 finally:
4679 finally:
4676 ui.setconfig('ui', 'forcemerge', '')
4680 ui.setconfig('ui', 'forcemerge', '')
4677
4681
4678 # replace filemerge's .orig file with our resolve file
4682 # replace filemerge's .orig file with our resolve file
4679 util.rename(a + ".resolve", a + ".orig")
4683 util.rename(a + ".resolve", a + ".orig")
4680
4684
4681 ms.commit()
4685 ms.commit()
4682 return ret
4686 return ret
4683
4687
4684 @command('revert',
4688 @command('revert',
4685 [('a', 'all', None, _('revert all changes when no arguments given')),
4689 [('a', 'all', None, _('revert all changes when no arguments given')),
4686 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4690 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4687 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4691 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4688 ('C', 'no-backup', None, _('do not save backup copies of files')),
4692 ('C', 'no-backup', None, _('do not save backup copies of files')),
4689 ] + walkopts + dryrunopts,
4693 ] + walkopts + dryrunopts,
4690 _('[OPTION]... [-r REV] [NAME]...'))
4694 _('[OPTION]... [-r REV] [NAME]...'))
4691 def revert(ui, repo, *pats, **opts):
4695 def revert(ui, repo, *pats, **opts):
4692 """restore files to their checkout state
4696 """restore files to their checkout state
4693
4697
4694 .. note::
4698 .. note::
4695 To check out earlier revisions, you should use :hg:`update REV`.
4699 To check out earlier revisions, you should use :hg:`update REV`.
4696 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4700 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4697
4701
4698 With no revision specified, revert the specified files or directories
4702 With no revision specified, revert the specified files or directories
4699 to the contents they had in the parent of the working directory.
4703 to the contents they had in the parent of the working directory.
4700 This restores the contents of files to an unmodified
4704 This restores the contents of files to an unmodified
4701 state and unschedules adds, removes, copies, and renames. If the
4705 state and unschedules adds, removes, copies, and renames. If the
4702 working directory has two parents, you must explicitly specify a
4706 working directory has two parents, you must explicitly specify a
4703 revision.
4707 revision.
4704
4708
4705 Using the -r/--rev or -d/--date options, revert the given files or
4709 Using the -r/--rev or -d/--date options, revert the given files or
4706 directories to their states as of a specific revision. Because
4710 directories to their states as of a specific revision. Because
4707 revert does not change the working directory parents, this will
4711 revert does not change the working directory parents, this will
4708 cause these files to appear modified. This can be helpful to "back
4712 cause these files to appear modified. This can be helpful to "back
4709 out" some or all of an earlier change. See :hg:`backout` for a
4713 out" some or all of an earlier change. See :hg:`backout` for a
4710 related method.
4714 related method.
4711
4715
4712 Modified files are saved with a .orig suffix before reverting.
4716 Modified files are saved with a .orig suffix before reverting.
4713 To disable these backups, use --no-backup.
4717 To disable these backups, use --no-backup.
4714
4718
4715 See :hg:`help dates` for a list of formats valid for -d/--date.
4719 See :hg:`help dates` for a list of formats valid for -d/--date.
4716
4720
4717 Returns 0 on success.
4721 Returns 0 on success.
4718 """
4722 """
4719
4723
4720 if opts.get("date"):
4724 if opts.get("date"):
4721 if opts.get("rev"):
4725 if opts.get("rev"):
4722 raise util.Abort(_("you can't specify a revision and a date"))
4726 raise util.Abort(_("you can't specify a revision and a date"))
4723 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4727 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4724
4728
4725 parent, p2 = repo.dirstate.parents()
4729 parent, p2 = repo.dirstate.parents()
4726 if not opts.get('rev') and p2 != nullid:
4730 if not opts.get('rev') and p2 != nullid:
4727 # revert after merge is a trap for new users (issue2915)
4731 # revert after merge is a trap for new users (issue2915)
4728 raise util.Abort(_('uncommitted merge with no revision specified'),
4732 raise util.Abort(_('uncommitted merge with no revision specified'),
4729 hint=_('use "hg update" or see "hg help revert"'))
4733 hint=_('use "hg update" or see "hg help revert"'))
4730
4734
4731 ctx = scmutil.revsingle(repo, opts.get('rev'))
4735 ctx = scmutil.revsingle(repo, opts.get('rev'))
4732 node = ctx.node()
4736 node = ctx.node()
4733
4737
4734 if not pats and not opts.get('all'):
4738 if not pats and not opts.get('all'):
4735 msg = _("no files or directories specified")
4739 msg = _("no files or directories specified")
4736 if p2 != nullid:
4740 if p2 != nullid:
4737 hint = _("uncommitted merge, use --all to discard all changes,"
4741 hint = _("uncommitted merge, use --all to discard all changes,"
4738 " or 'hg update -C .' to abort the merge")
4742 " or 'hg update -C .' to abort the merge")
4739 raise util.Abort(msg, hint=hint)
4743 raise util.Abort(msg, hint=hint)
4740 dirty = util.any(repo.status())
4744 dirty = util.any(repo.status())
4741 if node != parent:
4745 if node != parent:
4742 if dirty:
4746 if dirty:
4743 hint = _("uncommitted changes, use --all to discard all"
4747 hint = _("uncommitted changes, use --all to discard all"
4744 " changes, or 'hg update %s' to update") % ctx.rev()
4748 " changes, or 'hg update %s' to update") % ctx.rev()
4745 else:
4749 else:
4746 hint = _("use --all to revert all files,"
4750 hint = _("use --all to revert all files,"
4747 " or 'hg update %s' to update") % ctx.rev()
4751 " or 'hg update %s' to update") % ctx.rev()
4748 elif dirty:
4752 elif dirty:
4749 hint = _("uncommitted changes, use --all to discard all changes")
4753 hint = _("uncommitted changes, use --all to discard all changes")
4750 else:
4754 else:
4751 hint = _("use --all to revert all files")
4755 hint = _("use --all to revert all files")
4752 raise util.Abort(msg, hint=hint)
4756 raise util.Abort(msg, hint=hint)
4753
4757
4754 mf = ctx.manifest()
4758 mf = ctx.manifest()
4755 if node == parent:
4759 if node == parent:
4756 pmf = mf
4760 pmf = mf
4757 else:
4761 else:
4758 pmf = None
4762 pmf = None
4759
4763
4760 # need all matching names in dirstate and manifest of target rev,
4764 # need all matching names in dirstate and manifest of target rev,
4761 # so have to walk both. do not print errors if files exist in one
4765 # so have to walk both. do not print errors if files exist in one
4762 # but not other.
4766 # but not other.
4763
4767
4764 names = {}
4768 names = {}
4765
4769
4766 wlock = repo.wlock()
4770 wlock = repo.wlock()
4767 try:
4771 try:
4768 # walk dirstate.
4772 # walk dirstate.
4769
4773
4770 m = scmutil.match(repo[None], pats, opts)
4774 m = scmutil.match(repo[None], pats, opts)
4771 m.bad = lambda x, y: False
4775 m.bad = lambda x, y: False
4772 for abs in repo.walk(m):
4776 for abs in repo.walk(m):
4773 names[abs] = m.rel(abs), m.exact(abs)
4777 names[abs] = m.rel(abs), m.exact(abs)
4774
4778
4775 # walk target manifest.
4779 # walk target manifest.
4776
4780
4777 def badfn(path, msg):
4781 def badfn(path, msg):
4778 if path in names:
4782 if path in names:
4779 return
4783 return
4780 if path in repo[node].substate:
4784 if path in repo[node].substate:
4781 ui.warn("%s: %s\n" % (m.rel(path),
4785 ui.warn("%s: %s\n" % (m.rel(path),
4782 'reverting subrepos is unsupported'))
4786 'reverting subrepos is unsupported'))
4783 return
4787 return
4784 path_ = path + '/'
4788 path_ = path + '/'
4785 for f in names:
4789 for f in names:
4786 if f.startswith(path_):
4790 if f.startswith(path_):
4787 return
4791 return
4788 ui.warn("%s: %s\n" % (m.rel(path), msg))
4792 ui.warn("%s: %s\n" % (m.rel(path), msg))
4789
4793
4790 m = scmutil.match(repo[node], pats, opts)
4794 m = scmutil.match(repo[node], pats, opts)
4791 m.bad = badfn
4795 m.bad = badfn
4792 for abs in repo[node].walk(m):
4796 for abs in repo[node].walk(m):
4793 if abs not in names:
4797 if abs not in names:
4794 names[abs] = m.rel(abs), m.exact(abs)
4798 names[abs] = m.rel(abs), m.exact(abs)
4795
4799
4796 m = scmutil.matchfiles(repo, names)
4800 m = scmutil.matchfiles(repo, names)
4797 changes = repo.status(match=m)[:4]
4801 changes = repo.status(match=m)[:4]
4798 modified, added, removed, deleted = map(set, changes)
4802 modified, added, removed, deleted = map(set, changes)
4799
4803
4800 # if f is a rename, also revert the source
4804 # if f is a rename, also revert the source
4801 cwd = repo.getcwd()
4805 cwd = repo.getcwd()
4802 for f in added:
4806 for f in added:
4803 src = repo.dirstate.copied(f)
4807 src = repo.dirstate.copied(f)
4804 if src and src not in names and repo.dirstate[src] == 'r':
4808 if src and src not in names and repo.dirstate[src] == 'r':
4805 removed.add(src)
4809 removed.add(src)
4806 names[src] = (repo.pathto(src, cwd), True)
4810 names[src] = (repo.pathto(src, cwd), True)
4807
4811
4808 def removeforget(abs):
4812 def removeforget(abs):
4809 if repo.dirstate[abs] == 'a':
4813 if repo.dirstate[abs] == 'a':
4810 return _('forgetting %s\n')
4814 return _('forgetting %s\n')
4811 return _('removing %s\n')
4815 return _('removing %s\n')
4812
4816
4813 revert = ([], _('reverting %s\n'))
4817 revert = ([], _('reverting %s\n'))
4814 add = ([], _('adding %s\n'))
4818 add = ([], _('adding %s\n'))
4815 remove = ([], removeforget)
4819 remove = ([], removeforget)
4816 undelete = ([], _('undeleting %s\n'))
4820 undelete = ([], _('undeleting %s\n'))
4817
4821
4818 disptable = (
4822 disptable = (
4819 # dispatch table:
4823 # dispatch table:
4820 # file state
4824 # file state
4821 # action if in target manifest
4825 # action if in target manifest
4822 # action if not in target manifest
4826 # action if not in target manifest
4823 # make backup if in target manifest
4827 # make backup if in target manifest
4824 # make backup if not in target manifest
4828 # make backup if not in target manifest
4825 (modified, revert, remove, True, True),
4829 (modified, revert, remove, True, True),
4826 (added, revert, remove, True, False),
4830 (added, revert, remove, True, False),
4827 (removed, undelete, None, False, False),
4831 (removed, undelete, None, False, False),
4828 (deleted, revert, remove, False, False),
4832 (deleted, revert, remove, False, False),
4829 )
4833 )
4830
4834
4831 for abs, (rel, exact) in sorted(names.items()):
4835 for abs, (rel, exact) in sorted(names.items()):
4832 mfentry = mf.get(abs)
4836 mfentry = mf.get(abs)
4833 target = repo.wjoin(abs)
4837 target = repo.wjoin(abs)
4834 def handle(xlist, dobackup):
4838 def handle(xlist, dobackup):
4835 xlist[0].append(abs)
4839 xlist[0].append(abs)
4836 if (dobackup and not opts.get('no_backup') and
4840 if (dobackup and not opts.get('no_backup') and
4837 os.path.lexists(target)):
4841 os.path.lexists(target)):
4838 bakname = "%s.orig" % rel
4842 bakname = "%s.orig" % rel
4839 ui.note(_('saving current version of %s as %s\n') %
4843 ui.note(_('saving current version of %s as %s\n') %
4840 (rel, bakname))
4844 (rel, bakname))
4841 if not opts.get('dry_run'):
4845 if not opts.get('dry_run'):
4842 util.rename(target, bakname)
4846 util.rename(target, bakname)
4843 if ui.verbose or not exact:
4847 if ui.verbose or not exact:
4844 msg = xlist[1]
4848 msg = xlist[1]
4845 if not isinstance(msg, basestring):
4849 if not isinstance(msg, basestring):
4846 msg = msg(abs)
4850 msg = msg(abs)
4847 ui.status(msg % rel)
4851 ui.status(msg % rel)
4848 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4852 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4849 if abs not in table:
4853 if abs not in table:
4850 continue
4854 continue
4851 # file has changed in dirstate
4855 # file has changed in dirstate
4852 if mfentry:
4856 if mfentry:
4853 handle(hitlist, backuphit)
4857 handle(hitlist, backuphit)
4854 elif misslist is not None:
4858 elif misslist is not None:
4855 handle(misslist, backupmiss)
4859 handle(misslist, backupmiss)
4856 break
4860 break
4857 else:
4861 else:
4858 if abs not in repo.dirstate:
4862 if abs not in repo.dirstate:
4859 if mfentry:
4863 if mfentry:
4860 handle(add, True)
4864 handle(add, True)
4861 elif exact:
4865 elif exact:
4862 ui.warn(_('file not managed: %s\n') % rel)
4866 ui.warn(_('file not managed: %s\n') % rel)
4863 continue
4867 continue
4864 # file has not changed in dirstate
4868 # file has not changed in dirstate
4865 if node == parent:
4869 if node == parent:
4866 if exact:
4870 if exact:
4867 ui.warn(_('no changes needed to %s\n') % rel)
4871 ui.warn(_('no changes needed to %s\n') % rel)
4868 continue
4872 continue
4869 if pmf is None:
4873 if pmf is None:
4870 # only need parent manifest in this unlikely case,
4874 # only need parent manifest in this unlikely case,
4871 # so do not read by default
4875 # so do not read by default
4872 pmf = repo[parent].manifest()
4876 pmf = repo[parent].manifest()
4873 if abs in pmf and mfentry:
4877 if abs in pmf and mfentry:
4874 # if version of file is same in parent and target
4878 # if version of file is same in parent and target
4875 # manifests, do nothing
4879 # manifests, do nothing
4876 if (pmf[abs] != mfentry or
4880 if (pmf[abs] != mfentry or
4877 pmf.flags(abs) != mf.flags(abs)):
4881 pmf.flags(abs) != mf.flags(abs)):
4878 handle(revert, False)
4882 handle(revert, False)
4879 else:
4883 else:
4880 handle(remove, False)
4884 handle(remove, False)
4881
4885
4882 if not opts.get('dry_run'):
4886 if not opts.get('dry_run'):
4883 def checkout(f):
4887 def checkout(f):
4884 fc = ctx[f]
4888 fc = ctx[f]
4885 repo.wwrite(f, fc.data(), fc.flags())
4889 repo.wwrite(f, fc.data(), fc.flags())
4886
4890
4887 audit_path = scmutil.pathauditor(repo.root)
4891 audit_path = scmutil.pathauditor(repo.root)
4888 for f in remove[0]:
4892 for f in remove[0]:
4889 if repo.dirstate[f] == 'a':
4893 if repo.dirstate[f] == 'a':
4890 repo.dirstate.drop(f)
4894 repo.dirstate.drop(f)
4891 continue
4895 continue
4892 audit_path(f)
4896 audit_path(f)
4893 try:
4897 try:
4894 util.unlinkpath(repo.wjoin(f))
4898 util.unlinkpath(repo.wjoin(f))
4895 except OSError:
4899 except OSError:
4896 pass
4900 pass
4897 repo.dirstate.remove(f)
4901 repo.dirstate.remove(f)
4898
4902
4899 normal = None
4903 normal = None
4900 if node == parent:
4904 if node == parent:
4901 # We're reverting to our parent. If possible, we'd like status
4905 # We're reverting to our parent. If possible, we'd like status
4902 # to report the file as clean. We have to use normallookup for
4906 # to report the file as clean. We have to use normallookup for
4903 # merges to avoid losing information about merged/dirty files.
4907 # merges to avoid losing information about merged/dirty files.
4904 if p2 != nullid:
4908 if p2 != nullid:
4905 normal = repo.dirstate.normallookup
4909 normal = repo.dirstate.normallookup
4906 else:
4910 else:
4907 normal = repo.dirstate.normal
4911 normal = repo.dirstate.normal
4908 for f in revert[0]:
4912 for f in revert[0]:
4909 checkout(f)
4913 checkout(f)
4910 if normal:
4914 if normal:
4911 normal(f)
4915 normal(f)
4912
4916
4913 for f in add[0]:
4917 for f in add[0]:
4914 checkout(f)
4918 checkout(f)
4915 repo.dirstate.add(f)
4919 repo.dirstate.add(f)
4916
4920
4917 normal = repo.dirstate.normallookup
4921 normal = repo.dirstate.normallookup
4918 if node == parent and p2 == nullid:
4922 if node == parent and p2 == nullid:
4919 normal = repo.dirstate.normal
4923 normal = repo.dirstate.normal
4920 for f in undelete[0]:
4924 for f in undelete[0]:
4921 checkout(f)
4925 checkout(f)
4922 normal(f)
4926 normal(f)
4923
4927
4924 finally:
4928 finally:
4925 wlock.release()
4929 wlock.release()
4926
4930
4927 @command('rollback', dryrunopts +
4931 @command('rollback', dryrunopts +
4928 [('f', 'force', False, _('ignore safety measures'))])
4932 [('f', 'force', False, _('ignore safety measures'))])
4929 def rollback(ui, repo, **opts):
4933 def rollback(ui, repo, **opts):
4930 """roll back the last transaction (dangerous)
4934 """roll back the last transaction (dangerous)
4931
4935
4932 This command should be used with care. There is only one level of
4936 This command should be used with care. There is only one level of
4933 rollback, and there is no way to undo a rollback. It will also
4937 rollback, and there is no way to undo a rollback. It will also
4934 restore the dirstate at the time of the last transaction, losing
4938 restore the dirstate at the time of the last transaction, losing
4935 any dirstate changes since that time. This command does not alter
4939 any dirstate changes since that time. This command does not alter
4936 the working directory.
4940 the working directory.
4937
4941
4938 Transactions are used to encapsulate the effects of all commands
4942 Transactions are used to encapsulate the effects of all commands
4939 that create new changesets or propagate existing changesets into a
4943 that create new changesets or propagate existing changesets into a
4940 repository. For example, the following commands are transactional,
4944 repository. For example, the following commands are transactional,
4941 and their effects can be rolled back:
4945 and their effects can be rolled back:
4942
4946
4943 - commit
4947 - commit
4944 - import
4948 - import
4945 - pull
4949 - pull
4946 - push (with this repository as the destination)
4950 - push (with this repository as the destination)
4947 - unbundle
4951 - unbundle
4948
4952
4949 To avoid permanent data loss, rollback will refuse to rollback a
4953 To avoid permanent data loss, rollback will refuse to rollback a
4950 commit transaction if it isn't checked out. Use --force to
4954 commit transaction if it isn't checked out. Use --force to
4951 override this protection.
4955 override this protection.
4952
4956
4953 This command is not intended for use on public repositories. Once
4957 This command is not intended for use on public repositories. Once
4954 changes are visible for pull by other users, rolling a transaction
4958 changes are visible for pull by other users, rolling a transaction
4955 back locally is ineffective (someone else may already have pulled
4959 back locally is ineffective (someone else may already have pulled
4956 the changes). Furthermore, a race is possible with readers of the
4960 the changes). Furthermore, a race is possible with readers of the
4957 repository; for example an in-progress pull from the repository
4961 repository; for example an in-progress pull from the repository
4958 may fail if a rollback is performed.
4962 may fail if a rollback is performed.
4959
4963
4960 Returns 0 on success, 1 if no rollback data is available.
4964 Returns 0 on success, 1 if no rollback data is available.
4961 """
4965 """
4962 return repo.rollback(dryrun=opts.get('dry_run'),
4966 return repo.rollback(dryrun=opts.get('dry_run'),
4963 force=opts.get('force'))
4967 force=opts.get('force'))
4964
4968
4965 @command('root', [])
4969 @command('root', [])
4966 def root(ui, repo):
4970 def root(ui, repo):
4967 """print the root (top) of the current working directory
4971 """print the root (top) of the current working directory
4968
4972
4969 Print the root directory of the current repository.
4973 Print the root directory of the current repository.
4970
4974
4971 Returns 0 on success.
4975 Returns 0 on success.
4972 """
4976 """
4973 ui.write(repo.root + "\n")
4977 ui.write(repo.root + "\n")
4974
4978
4975 @command('^serve',
4979 @command('^serve',
4976 [('A', 'accesslog', '', _('name of access log file to write to'),
4980 [('A', 'accesslog', '', _('name of access log file to write to'),
4977 _('FILE')),
4981 _('FILE')),
4978 ('d', 'daemon', None, _('run server in background')),
4982 ('d', 'daemon', None, _('run server in background')),
4979 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4983 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4980 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4984 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4981 # use string type, then we can check if something was passed
4985 # use string type, then we can check if something was passed
4982 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4986 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4983 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4987 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4984 _('ADDR')),
4988 _('ADDR')),
4985 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4989 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4986 _('PREFIX')),
4990 _('PREFIX')),
4987 ('n', 'name', '',
4991 ('n', 'name', '',
4988 _('name to show in web pages (default: working directory)'), _('NAME')),
4992 _('name to show in web pages (default: working directory)'), _('NAME')),
4989 ('', 'web-conf', '',
4993 ('', 'web-conf', '',
4990 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4994 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4991 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4995 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4992 _('FILE')),
4996 _('FILE')),
4993 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4997 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4994 ('', 'stdio', None, _('for remote clients')),
4998 ('', 'stdio', None, _('for remote clients')),
4995 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4999 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4996 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5000 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4997 ('', 'style', '', _('template style to use'), _('STYLE')),
5001 ('', 'style', '', _('template style to use'), _('STYLE')),
4998 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5002 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4999 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5003 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5000 _('[OPTION]...'))
5004 _('[OPTION]...'))
5001 def serve(ui, repo, **opts):
5005 def serve(ui, repo, **opts):
5002 """start stand-alone webserver
5006 """start stand-alone webserver
5003
5007
5004 Start a local HTTP repository browser and pull server. You can use
5008 Start a local HTTP repository browser and pull server. You can use
5005 this for ad-hoc sharing and browsing of repositories. It is
5009 this for ad-hoc sharing and browsing of repositories. It is
5006 recommended to use a real web server to serve a repository for
5010 recommended to use a real web server to serve a repository for
5007 longer periods of time.
5011 longer periods of time.
5008
5012
5009 Please note that the server does not implement access control.
5013 Please note that the server does not implement access control.
5010 This means that, by default, anybody can read from the server and
5014 This means that, by default, anybody can read from the server and
5011 nobody can write to it by default. Set the ``web.allow_push``
5015 nobody can write to it by default. Set the ``web.allow_push``
5012 option to ``*`` to allow everybody to push to the server. You
5016 option to ``*`` to allow everybody to push to the server. You
5013 should use a real web server if you need to authenticate users.
5017 should use a real web server if you need to authenticate users.
5014
5018
5015 By default, the server logs accesses to stdout and errors to
5019 By default, the server logs accesses to stdout and errors to
5016 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5020 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5017 files.
5021 files.
5018
5022
5019 To have the server choose a free port number to listen on, specify
5023 To have the server choose a free port number to listen on, specify
5020 a port number of 0; in this case, the server will print the port
5024 a port number of 0; in this case, the server will print the port
5021 number it uses.
5025 number it uses.
5022
5026
5023 Returns 0 on success.
5027 Returns 0 on success.
5024 """
5028 """
5025
5029
5026 if opts["stdio"] and opts["cmdserver"]:
5030 if opts["stdio"] and opts["cmdserver"]:
5027 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5031 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5028
5032
5029 def checkrepo():
5033 def checkrepo():
5030 if repo is None:
5034 if repo is None:
5031 raise error.RepoError(_("There is no Mercurial repository here"
5035 raise error.RepoError(_("There is no Mercurial repository here"
5032 " (.hg not found)"))
5036 " (.hg not found)"))
5033
5037
5034 if opts["stdio"]:
5038 if opts["stdio"]:
5035 checkrepo()
5039 checkrepo()
5036 s = sshserver.sshserver(ui, repo)
5040 s = sshserver.sshserver(ui, repo)
5037 s.serve_forever()
5041 s.serve_forever()
5038
5042
5039 if opts["cmdserver"]:
5043 if opts["cmdserver"]:
5040 checkrepo()
5044 checkrepo()
5041 s = commandserver.server(ui, repo, opts["cmdserver"])
5045 s = commandserver.server(ui, repo, opts["cmdserver"])
5042 return s.serve()
5046 return s.serve()
5043
5047
5044 # this way we can check if something was given in the command-line
5048 # this way we can check if something was given in the command-line
5045 if opts.get('port'):
5049 if opts.get('port'):
5046 opts['port'] = util.getport(opts.get('port'))
5050 opts['port'] = util.getport(opts.get('port'))
5047
5051
5048 baseui = repo and repo.baseui or ui
5052 baseui = repo and repo.baseui or ui
5049 optlist = ("name templates style address port prefix ipv6"
5053 optlist = ("name templates style address port prefix ipv6"
5050 " accesslog errorlog certificate encoding")
5054 " accesslog errorlog certificate encoding")
5051 for o in optlist.split():
5055 for o in optlist.split():
5052 val = opts.get(o, '')
5056 val = opts.get(o, '')
5053 if val in (None, ''): # should check against default options instead
5057 if val in (None, ''): # should check against default options instead
5054 continue
5058 continue
5055 baseui.setconfig("web", o, val)
5059 baseui.setconfig("web", o, val)
5056 if repo and repo.ui != baseui:
5060 if repo and repo.ui != baseui:
5057 repo.ui.setconfig("web", o, val)
5061 repo.ui.setconfig("web", o, val)
5058
5062
5059 o = opts.get('web_conf') or opts.get('webdir_conf')
5063 o = opts.get('web_conf') or opts.get('webdir_conf')
5060 if not o:
5064 if not o:
5061 if not repo:
5065 if not repo:
5062 raise error.RepoError(_("There is no Mercurial repository"
5066 raise error.RepoError(_("There is no Mercurial repository"
5063 " here (.hg not found)"))
5067 " here (.hg not found)"))
5064 o = repo.root
5068 o = repo.root
5065
5069
5066 app = hgweb.hgweb(o, baseui=ui)
5070 app = hgweb.hgweb(o, baseui=ui)
5067
5071
5068 class service(object):
5072 class service(object):
5069 def init(self):
5073 def init(self):
5070 util.setsignalhandler()
5074 util.setsignalhandler()
5071 self.httpd = hgweb.server.create_server(ui, app)
5075 self.httpd = hgweb.server.create_server(ui, app)
5072
5076
5073 if opts['port'] and not ui.verbose:
5077 if opts['port'] and not ui.verbose:
5074 return
5078 return
5075
5079
5076 if self.httpd.prefix:
5080 if self.httpd.prefix:
5077 prefix = self.httpd.prefix.strip('/') + '/'
5081 prefix = self.httpd.prefix.strip('/') + '/'
5078 else:
5082 else:
5079 prefix = ''
5083 prefix = ''
5080
5084
5081 port = ':%d' % self.httpd.port
5085 port = ':%d' % self.httpd.port
5082 if port == ':80':
5086 if port == ':80':
5083 port = ''
5087 port = ''
5084
5088
5085 bindaddr = self.httpd.addr
5089 bindaddr = self.httpd.addr
5086 if bindaddr == '0.0.0.0':
5090 if bindaddr == '0.0.0.0':
5087 bindaddr = '*'
5091 bindaddr = '*'
5088 elif ':' in bindaddr: # IPv6
5092 elif ':' in bindaddr: # IPv6
5089 bindaddr = '[%s]' % bindaddr
5093 bindaddr = '[%s]' % bindaddr
5090
5094
5091 fqaddr = self.httpd.fqaddr
5095 fqaddr = self.httpd.fqaddr
5092 if ':' in fqaddr:
5096 if ':' in fqaddr:
5093 fqaddr = '[%s]' % fqaddr
5097 fqaddr = '[%s]' % fqaddr
5094 if opts['port']:
5098 if opts['port']:
5095 write = ui.status
5099 write = ui.status
5096 else:
5100 else:
5097 write = ui.write
5101 write = ui.write
5098 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5102 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5099 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5103 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5100
5104
5101 def run(self):
5105 def run(self):
5102 self.httpd.serve_forever()
5106 self.httpd.serve_forever()
5103
5107
5104 service = service()
5108 service = service()
5105
5109
5106 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5110 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5107
5111
5108 @command('showconfig|debugconfig',
5112 @command('showconfig|debugconfig',
5109 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5113 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5110 _('[-u] [NAME]...'))
5114 _('[-u] [NAME]...'))
5111 def showconfig(ui, repo, *values, **opts):
5115 def showconfig(ui, repo, *values, **opts):
5112 """show combined config settings from all hgrc files
5116 """show combined config settings from all hgrc files
5113
5117
5114 With no arguments, print names and values of all config items.
5118 With no arguments, print names and values of all config items.
5115
5119
5116 With one argument of the form section.name, print just the value
5120 With one argument of the form section.name, print just the value
5117 of that config item.
5121 of that config item.
5118
5122
5119 With multiple arguments, print names and values of all config
5123 With multiple arguments, print names and values of all config
5120 items with matching section names.
5124 items with matching section names.
5121
5125
5122 With --debug, the source (filename and line number) is printed
5126 With --debug, the source (filename and line number) is printed
5123 for each config item.
5127 for each config item.
5124
5128
5125 Returns 0 on success.
5129 Returns 0 on success.
5126 """
5130 """
5127
5131
5128 for f in scmutil.rcpath():
5132 for f in scmutil.rcpath():
5129 ui.debug('read config from: %s\n' % f)
5133 ui.debug('read config from: %s\n' % f)
5130 untrusted = bool(opts.get('untrusted'))
5134 untrusted = bool(opts.get('untrusted'))
5131 if values:
5135 if values:
5132 sections = [v for v in values if '.' not in v]
5136 sections = [v for v in values if '.' not in v]
5133 items = [v for v in values if '.' in v]
5137 items = [v for v in values if '.' in v]
5134 if len(items) > 1 or items and sections:
5138 if len(items) > 1 or items and sections:
5135 raise util.Abort(_('only one config item permitted'))
5139 raise util.Abort(_('only one config item permitted'))
5136 for section, name, value in ui.walkconfig(untrusted=untrusted):
5140 for section, name, value in ui.walkconfig(untrusted=untrusted):
5137 value = str(value).replace('\n', '\\n')
5141 value = str(value).replace('\n', '\\n')
5138 sectname = section + '.' + name
5142 sectname = section + '.' + name
5139 if values:
5143 if values:
5140 for v in values:
5144 for v in values:
5141 if v == section:
5145 if v == section:
5142 ui.debug('%s: ' %
5146 ui.debug('%s: ' %
5143 ui.configsource(section, name, untrusted))
5147 ui.configsource(section, name, untrusted))
5144 ui.write('%s=%s\n' % (sectname, value))
5148 ui.write('%s=%s\n' % (sectname, value))
5145 elif v == sectname:
5149 elif v == sectname:
5146 ui.debug('%s: ' %
5150 ui.debug('%s: ' %
5147 ui.configsource(section, name, untrusted))
5151 ui.configsource(section, name, untrusted))
5148 ui.write(value, '\n')
5152 ui.write(value, '\n')
5149 else:
5153 else:
5150 ui.debug('%s: ' %
5154 ui.debug('%s: ' %
5151 ui.configsource(section, name, untrusted))
5155 ui.configsource(section, name, untrusted))
5152 ui.write('%s=%s\n' % (sectname, value))
5156 ui.write('%s=%s\n' % (sectname, value))
5153
5157
5154 @command('^status|st',
5158 @command('^status|st',
5155 [('A', 'all', None, _('show status of all files')),
5159 [('A', 'all', None, _('show status of all files')),
5156 ('m', 'modified', None, _('show only modified files')),
5160 ('m', 'modified', None, _('show only modified files')),
5157 ('a', 'added', None, _('show only added files')),
5161 ('a', 'added', None, _('show only added files')),
5158 ('r', 'removed', None, _('show only removed files')),
5162 ('r', 'removed', None, _('show only removed files')),
5159 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5163 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5160 ('c', 'clean', None, _('show only files without changes')),
5164 ('c', 'clean', None, _('show only files without changes')),
5161 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5165 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5162 ('i', 'ignored', None, _('show only ignored files')),
5166 ('i', 'ignored', None, _('show only ignored files')),
5163 ('n', 'no-status', None, _('hide status prefix')),
5167 ('n', 'no-status', None, _('hide status prefix')),
5164 ('C', 'copies', None, _('show source of copied files')),
5168 ('C', 'copies', None, _('show source of copied files')),
5165 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5169 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5166 ('', 'rev', [], _('show difference from revision'), _('REV')),
5170 ('', 'rev', [], _('show difference from revision'), _('REV')),
5167 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5171 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5168 ] + walkopts + subrepoopts,
5172 ] + walkopts + subrepoopts,
5169 _('[OPTION]... [FILE]...'))
5173 _('[OPTION]... [FILE]...'))
5170 def status(ui, repo, *pats, **opts):
5174 def status(ui, repo, *pats, **opts):
5171 """show changed files in the working directory
5175 """show changed files in the working directory
5172
5176
5173 Show status of files in the repository. If names are given, only
5177 Show status of files in the repository. If names are given, only
5174 files that match are shown. Files that are clean or ignored or
5178 files that match are shown. Files that are clean or ignored or
5175 the source of a copy/move operation, are not listed unless
5179 the source of a copy/move operation, are not listed unless
5176 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5180 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5177 Unless options described with "show only ..." are given, the
5181 Unless options described with "show only ..." are given, the
5178 options -mardu are used.
5182 options -mardu are used.
5179
5183
5180 Option -q/--quiet hides untracked (unknown and ignored) files
5184 Option -q/--quiet hides untracked (unknown and ignored) files
5181 unless explicitly requested with -u/--unknown or -i/--ignored.
5185 unless explicitly requested with -u/--unknown or -i/--ignored.
5182
5186
5183 .. note::
5187 .. note::
5184 status may appear to disagree with diff if permissions have
5188 status may appear to disagree with diff if permissions have
5185 changed or a merge has occurred. The standard diff format does
5189 changed or a merge has occurred. The standard diff format does
5186 not report permission changes and diff only reports changes
5190 not report permission changes and diff only reports changes
5187 relative to one merge parent.
5191 relative to one merge parent.
5188
5192
5189 If one revision is given, it is used as the base revision.
5193 If one revision is given, it is used as the base revision.
5190 If two revisions are given, the differences between them are
5194 If two revisions are given, the differences between them are
5191 shown. The --change option can also be used as a shortcut to list
5195 shown. The --change option can also be used as a shortcut to list
5192 the changed files of a revision from its first parent.
5196 the changed files of a revision from its first parent.
5193
5197
5194 The codes used to show the status of files are::
5198 The codes used to show the status of files are::
5195
5199
5196 M = modified
5200 M = modified
5197 A = added
5201 A = added
5198 R = removed
5202 R = removed
5199 C = clean
5203 C = clean
5200 ! = missing (deleted by non-hg command, but still tracked)
5204 ! = missing (deleted by non-hg command, but still tracked)
5201 ? = not tracked
5205 ? = not tracked
5202 I = ignored
5206 I = ignored
5203 = origin of the previous file listed as A (added)
5207 = origin of the previous file listed as A (added)
5204
5208
5205 .. container:: verbose
5209 .. container:: verbose
5206
5210
5207 Examples:
5211 Examples:
5208
5212
5209 - show changes in the working directory relative to a
5213 - show changes in the working directory relative to a
5210 changeset::
5214 changeset::
5211
5215
5212 hg status --rev 9353
5216 hg status --rev 9353
5213
5217
5214 - show all changes including copies in an existing changeset::
5218 - show all changes including copies in an existing changeset::
5215
5219
5216 hg status --copies --change 9353
5220 hg status --copies --change 9353
5217
5221
5218 - get a NUL separated list of added files, suitable for xargs::
5222 - get a NUL separated list of added files, suitable for xargs::
5219
5223
5220 hg status -an0
5224 hg status -an0
5221
5225
5222 Returns 0 on success.
5226 Returns 0 on success.
5223 """
5227 """
5224
5228
5225 revs = opts.get('rev')
5229 revs = opts.get('rev')
5226 change = opts.get('change')
5230 change = opts.get('change')
5227
5231
5228 if revs and change:
5232 if revs and change:
5229 msg = _('cannot specify --rev and --change at the same time')
5233 msg = _('cannot specify --rev and --change at the same time')
5230 raise util.Abort(msg)
5234 raise util.Abort(msg)
5231 elif change:
5235 elif change:
5232 node2 = scmutil.revsingle(repo, change, None).node()
5236 node2 = scmutil.revsingle(repo, change, None).node()
5233 node1 = repo[node2].p1().node()
5237 node1 = repo[node2].p1().node()
5234 else:
5238 else:
5235 node1, node2 = scmutil.revpair(repo, revs)
5239 node1, node2 = scmutil.revpair(repo, revs)
5236
5240
5237 cwd = (pats and repo.getcwd()) or ''
5241 cwd = (pats and repo.getcwd()) or ''
5238 end = opts.get('print0') and '\0' or '\n'
5242 end = opts.get('print0') and '\0' or '\n'
5239 copy = {}
5243 copy = {}
5240 states = 'modified added removed deleted unknown ignored clean'.split()
5244 states = 'modified added removed deleted unknown ignored clean'.split()
5241 show = [k for k in states if opts.get(k)]
5245 show = [k for k in states if opts.get(k)]
5242 if opts.get('all'):
5246 if opts.get('all'):
5243 show += ui.quiet and (states[:4] + ['clean']) or states
5247 show += ui.quiet and (states[:4] + ['clean']) or states
5244 if not show:
5248 if not show:
5245 show = ui.quiet and states[:4] or states[:5]
5249 show = ui.quiet and states[:4] or states[:5]
5246
5250
5247 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5251 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5248 'ignored' in show, 'clean' in show, 'unknown' in show,
5252 'ignored' in show, 'clean' in show, 'unknown' in show,
5249 opts.get('subrepos'))
5253 opts.get('subrepos'))
5250 changestates = zip(states, 'MAR!?IC', stat)
5254 changestates = zip(states, 'MAR!?IC', stat)
5251
5255
5252 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5256 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5253 copy = copies.pathcopies(repo[node1], repo[node2])
5257 copy = copies.pathcopies(repo[node1], repo[node2])
5254
5258
5255 for state, char, files in changestates:
5259 for state, char, files in changestates:
5256 if state in show:
5260 if state in show:
5257 format = "%s %%s%s" % (char, end)
5261 format = "%s %%s%s" % (char, end)
5258 if opts.get('no_status'):
5262 if opts.get('no_status'):
5259 format = "%%s%s" % end
5263 format = "%%s%s" % end
5260
5264
5261 for f in files:
5265 for f in files:
5262 ui.write(format % repo.pathto(f, cwd),
5266 ui.write(format % repo.pathto(f, cwd),
5263 label='status.' + state)
5267 label='status.' + state)
5264 if f in copy:
5268 if f in copy:
5265 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5269 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5266 label='status.copied')
5270 label='status.copied')
5267
5271
5268 @command('^summary|sum',
5272 @command('^summary|sum',
5269 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5273 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5270 def summary(ui, repo, **opts):
5274 def summary(ui, repo, **opts):
5271 """summarize working directory state
5275 """summarize working directory state
5272
5276
5273 This generates a brief summary of the working directory state,
5277 This generates a brief summary of the working directory state,
5274 including parents, branch, commit status, and available updates.
5278 including parents, branch, commit status, and available updates.
5275
5279
5276 With the --remote option, this will check the default paths for
5280 With the --remote option, this will check the default paths for
5277 incoming and outgoing changes. This can be time-consuming.
5281 incoming and outgoing changes. This can be time-consuming.
5278
5282
5279 Returns 0 on success.
5283 Returns 0 on success.
5280 """
5284 """
5281
5285
5282 ctx = repo[None]
5286 ctx = repo[None]
5283 parents = ctx.parents()
5287 parents = ctx.parents()
5284 pnode = parents[0].node()
5288 pnode = parents[0].node()
5285 marks = []
5289 marks = []
5286
5290
5287 for p in parents:
5291 for p in parents:
5288 # label with log.changeset (instead of log.parent) since this
5292 # label with log.changeset (instead of log.parent) since this
5289 # shows a working directory parent *changeset*:
5293 # shows a working directory parent *changeset*:
5290 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5294 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5291 label='log.changeset')
5295 label='log.changeset')
5292 ui.write(' '.join(p.tags()), label='log.tag')
5296 ui.write(' '.join(p.tags()), label='log.tag')
5293 if p.bookmarks():
5297 if p.bookmarks():
5294 marks.extend(p.bookmarks())
5298 marks.extend(p.bookmarks())
5295 if p.rev() == -1:
5299 if p.rev() == -1:
5296 if not len(repo):
5300 if not len(repo):
5297 ui.write(_(' (empty repository)'))
5301 ui.write(_(' (empty repository)'))
5298 else:
5302 else:
5299 ui.write(_(' (no revision checked out)'))
5303 ui.write(_(' (no revision checked out)'))
5300 ui.write('\n')
5304 ui.write('\n')
5301 if p.description():
5305 if p.description():
5302 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5306 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5303 label='log.summary')
5307 label='log.summary')
5304
5308
5305 branch = ctx.branch()
5309 branch = ctx.branch()
5306 bheads = repo.branchheads(branch)
5310 bheads = repo.branchheads(branch)
5307 m = _('branch: %s\n') % branch
5311 m = _('branch: %s\n') % branch
5308 if branch != 'default':
5312 if branch != 'default':
5309 ui.write(m, label='log.branch')
5313 ui.write(m, label='log.branch')
5310 else:
5314 else:
5311 ui.status(m, label='log.branch')
5315 ui.status(m, label='log.branch')
5312
5316
5313 if marks:
5317 if marks:
5314 current = repo._bookmarkcurrent
5318 current = repo._bookmarkcurrent
5315 ui.write(_('bookmarks:'), label='log.bookmark')
5319 ui.write(_('bookmarks:'), label='log.bookmark')
5316 if current is not None:
5320 if current is not None:
5317 try:
5321 try:
5318 marks.remove(current)
5322 marks.remove(current)
5319 ui.write(' *' + current, label='bookmarks.current')
5323 ui.write(' *' + current, label='bookmarks.current')
5320 except ValueError:
5324 except ValueError:
5321 # current bookmark not in parent ctx marks
5325 # current bookmark not in parent ctx marks
5322 pass
5326 pass
5323 for m in marks:
5327 for m in marks:
5324 ui.write(' ' + m, label='log.bookmark')
5328 ui.write(' ' + m, label='log.bookmark')
5325 ui.write('\n', label='log.bookmark')
5329 ui.write('\n', label='log.bookmark')
5326
5330
5327 st = list(repo.status(unknown=True))[:6]
5331 st = list(repo.status(unknown=True))[:6]
5328
5332
5329 c = repo.dirstate.copies()
5333 c = repo.dirstate.copies()
5330 copied, renamed = [], []
5334 copied, renamed = [], []
5331 for d, s in c.iteritems():
5335 for d, s in c.iteritems():
5332 if s in st[2]:
5336 if s in st[2]:
5333 st[2].remove(s)
5337 st[2].remove(s)
5334 renamed.append(d)
5338 renamed.append(d)
5335 else:
5339 else:
5336 copied.append(d)
5340 copied.append(d)
5337 if d in st[1]:
5341 if d in st[1]:
5338 st[1].remove(d)
5342 st[1].remove(d)
5339 st.insert(3, renamed)
5343 st.insert(3, renamed)
5340 st.insert(4, copied)
5344 st.insert(4, copied)
5341
5345
5342 ms = mergemod.mergestate(repo)
5346 ms = mergemod.mergestate(repo)
5343 st.append([f for f in ms if ms[f] == 'u'])
5347 st.append([f for f in ms if ms[f] == 'u'])
5344
5348
5345 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5349 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5346 st.append(subs)
5350 st.append(subs)
5347
5351
5348 labels = [ui.label(_('%d modified'), 'status.modified'),
5352 labels = [ui.label(_('%d modified'), 'status.modified'),
5349 ui.label(_('%d added'), 'status.added'),
5353 ui.label(_('%d added'), 'status.added'),
5350 ui.label(_('%d removed'), 'status.removed'),
5354 ui.label(_('%d removed'), 'status.removed'),
5351 ui.label(_('%d renamed'), 'status.copied'),
5355 ui.label(_('%d renamed'), 'status.copied'),
5352 ui.label(_('%d copied'), 'status.copied'),
5356 ui.label(_('%d copied'), 'status.copied'),
5353 ui.label(_('%d deleted'), 'status.deleted'),
5357 ui.label(_('%d deleted'), 'status.deleted'),
5354 ui.label(_('%d unknown'), 'status.unknown'),
5358 ui.label(_('%d unknown'), 'status.unknown'),
5355 ui.label(_('%d ignored'), 'status.ignored'),
5359 ui.label(_('%d ignored'), 'status.ignored'),
5356 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5360 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5357 ui.label(_('%d subrepos'), 'status.modified')]
5361 ui.label(_('%d subrepos'), 'status.modified')]
5358 t = []
5362 t = []
5359 for s, l in zip(st, labels):
5363 for s, l in zip(st, labels):
5360 if s:
5364 if s:
5361 t.append(l % len(s))
5365 t.append(l % len(s))
5362
5366
5363 t = ', '.join(t)
5367 t = ', '.join(t)
5364 cleanworkdir = False
5368 cleanworkdir = False
5365
5369
5366 if len(parents) > 1:
5370 if len(parents) > 1:
5367 t += _(' (merge)')
5371 t += _(' (merge)')
5368 elif branch != parents[0].branch():
5372 elif branch != parents[0].branch():
5369 t += _(' (new branch)')
5373 t += _(' (new branch)')
5370 elif (parents[0].extra().get('close') and
5374 elif (parents[0].extra().get('close') and
5371 pnode in repo.branchheads(branch, closed=True)):
5375 pnode in repo.branchheads(branch, closed=True)):
5372 t += _(' (head closed)')
5376 t += _(' (head closed)')
5373 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5377 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5374 t += _(' (clean)')
5378 t += _(' (clean)')
5375 cleanworkdir = True
5379 cleanworkdir = True
5376 elif pnode not in bheads:
5380 elif pnode not in bheads:
5377 t += _(' (new branch head)')
5381 t += _(' (new branch head)')
5378
5382
5379 if cleanworkdir:
5383 if cleanworkdir:
5380 ui.status(_('commit: %s\n') % t.strip())
5384 ui.status(_('commit: %s\n') % t.strip())
5381 else:
5385 else:
5382 ui.write(_('commit: %s\n') % t.strip())
5386 ui.write(_('commit: %s\n') % t.strip())
5383
5387
5384 # all ancestors of branch heads - all ancestors of parent = new csets
5388 # all ancestors of branch heads - all ancestors of parent = new csets
5385 new = [0] * len(repo)
5389 new = [0] * len(repo)
5386 cl = repo.changelog
5390 cl = repo.changelog
5387 for a in [cl.rev(n) for n in bheads]:
5391 for a in [cl.rev(n) for n in bheads]:
5388 new[a] = 1
5392 new[a] = 1
5389 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5393 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5390 new[a] = 1
5394 new[a] = 1
5391 for a in [p.rev() for p in parents]:
5395 for a in [p.rev() for p in parents]:
5392 if a >= 0:
5396 if a >= 0:
5393 new[a] = 0
5397 new[a] = 0
5394 for a in cl.ancestors(*[p.rev() for p in parents]):
5398 for a in cl.ancestors(*[p.rev() for p in parents]):
5395 new[a] = 0
5399 new[a] = 0
5396 new = sum(new)
5400 new = sum(new)
5397
5401
5398 if new == 0:
5402 if new == 0:
5399 ui.status(_('update: (current)\n'))
5403 ui.status(_('update: (current)\n'))
5400 elif pnode not in bheads:
5404 elif pnode not in bheads:
5401 ui.write(_('update: %d new changesets (update)\n') % new)
5405 ui.write(_('update: %d new changesets (update)\n') % new)
5402 else:
5406 else:
5403 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5407 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5404 (new, len(bheads)))
5408 (new, len(bheads)))
5405
5409
5406 if opts.get('remote'):
5410 if opts.get('remote'):
5407 t = []
5411 t = []
5408 source, branches = hg.parseurl(ui.expandpath('default'))
5412 source, branches = hg.parseurl(ui.expandpath('default'))
5409 other = hg.peer(repo, {}, source)
5413 other = hg.peer(repo, {}, source)
5410 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5414 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5411 ui.debug('comparing with %s\n' % util.hidepassword(source))
5415 ui.debug('comparing with %s\n' % util.hidepassword(source))
5412 repo.ui.pushbuffer()
5416 repo.ui.pushbuffer()
5413 commoninc = discovery.findcommonincoming(repo, other)
5417 commoninc = discovery.findcommonincoming(repo, other)
5414 _common, incoming, _rheads = commoninc
5418 _common, incoming, _rheads = commoninc
5415 repo.ui.popbuffer()
5419 repo.ui.popbuffer()
5416 if incoming:
5420 if incoming:
5417 t.append(_('1 or more incoming'))
5421 t.append(_('1 or more incoming'))
5418
5422
5419 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5423 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5420 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5424 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5421 if source != dest:
5425 if source != dest:
5422 other = hg.peer(repo, {}, dest)
5426 other = hg.peer(repo, {}, dest)
5423 commoninc = None
5427 commoninc = None
5424 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5428 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5425 repo.ui.pushbuffer()
5429 repo.ui.pushbuffer()
5426 outgoing = discovery.findcommonoutgoing(repo, other,
5430 outgoing = discovery.findcommonoutgoing(repo, other,
5427 commoninc=commoninc)
5431 commoninc=commoninc)
5428 repo.ui.popbuffer()
5432 repo.ui.popbuffer()
5429 o = outgoing.missing
5433 o = outgoing.missing
5430 if o:
5434 if o:
5431 t.append(_('%d outgoing') % len(o))
5435 t.append(_('%d outgoing') % len(o))
5432 if 'bookmarks' in other.listkeys('namespaces'):
5436 if 'bookmarks' in other.listkeys('namespaces'):
5433 lmarks = repo.listkeys('bookmarks')
5437 lmarks = repo.listkeys('bookmarks')
5434 rmarks = other.listkeys('bookmarks')
5438 rmarks = other.listkeys('bookmarks')
5435 diff = set(rmarks) - set(lmarks)
5439 diff = set(rmarks) - set(lmarks)
5436 if len(diff) > 0:
5440 if len(diff) > 0:
5437 t.append(_('%d incoming bookmarks') % len(diff))
5441 t.append(_('%d incoming bookmarks') % len(diff))
5438 diff = set(lmarks) - set(rmarks)
5442 diff = set(lmarks) - set(rmarks)
5439 if len(diff) > 0:
5443 if len(diff) > 0:
5440 t.append(_('%d outgoing bookmarks') % len(diff))
5444 t.append(_('%d outgoing bookmarks') % len(diff))
5441
5445
5442 if t:
5446 if t:
5443 ui.write(_('remote: %s\n') % (', '.join(t)))
5447 ui.write(_('remote: %s\n') % (', '.join(t)))
5444 else:
5448 else:
5445 ui.status(_('remote: (synced)\n'))
5449 ui.status(_('remote: (synced)\n'))
5446
5450
5447 @command('tag',
5451 @command('tag',
5448 [('f', 'force', None, _('force tag')),
5452 [('f', 'force', None, _('force tag')),
5449 ('l', 'local', None, _('make the tag local')),
5453 ('l', 'local', None, _('make the tag local')),
5450 ('r', 'rev', '', _('revision to tag'), _('REV')),
5454 ('r', 'rev', '', _('revision to tag'), _('REV')),
5451 ('', 'remove', None, _('remove a tag')),
5455 ('', 'remove', None, _('remove a tag')),
5452 # -l/--local is already there, commitopts cannot be used
5456 # -l/--local is already there, commitopts cannot be used
5453 ('e', 'edit', None, _('edit commit message')),
5457 ('e', 'edit', None, _('edit commit message')),
5454 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5458 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5455 ] + commitopts2,
5459 ] + commitopts2,
5456 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5460 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5457 def tag(ui, repo, name1, *names, **opts):
5461 def tag(ui, repo, name1, *names, **opts):
5458 """add one or more tags for the current or given revision
5462 """add one or more tags for the current or given revision
5459
5463
5460 Name a particular revision using <name>.
5464 Name a particular revision using <name>.
5461
5465
5462 Tags are used to name particular revisions of the repository and are
5466 Tags are used to name particular revisions of the repository and are
5463 very useful to compare different revisions, to go back to significant
5467 very useful to compare different revisions, to go back to significant
5464 earlier versions or to mark branch points as releases, etc. Changing
5468 earlier versions or to mark branch points as releases, etc. Changing
5465 an existing tag is normally disallowed; use -f/--force to override.
5469 an existing tag is normally disallowed; use -f/--force to override.
5466
5470
5467 If no revision is given, the parent of the working directory is
5471 If no revision is given, the parent of the working directory is
5468 used, or tip if no revision is checked out.
5472 used, or tip if no revision is checked out.
5469
5473
5470 To facilitate version control, distribution, and merging of tags,
5474 To facilitate version control, distribution, and merging of tags,
5471 they are stored as a file named ".hgtags" which is managed similarly
5475 they are stored as a file named ".hgtags" which is managed similarly
5472 to other project files and can be hand-edited if necessary. This
5476 to other project files and can be hand-edited if necessary. This
5473 also means that tagging creates a new commit. The file
5477 also means that tagging creates a new commit. The file
5474 ".hg/localtags" is used for local tags (not shared among
5478 ".hg/localtags" is used for local tags (not shared among
5475 repositories).
5479 repositories).
5476
5480
5477 Tag commits are usually made at the head of a branch. If the parent
5481 Tag commits are usually made at the head of a branch. If the parent
5478 of the working directory is not a branch head, :hg:`tag` aborts; use
5482 of the working directory is not a branch head, :hg:`tag` aborts; use
5479 -f/--force to force the tag commit to be based on a non-head
5483 -f/--force to force the tag commit to be based on a non-head
5480 changeset.
5484 changeset.
5481
5485
5482 See :hg:`help dates` for a list of formats valid for -d/--date.
5486 See :hg:`help dates` for a list of formats valid for -d/--date.
5483
5487
5484 Since tag names have priority over branch names during revision
5488 Since tag names have priority over branch names during revision
5485 lookup, using an existing branch name as a tag name is discouraged.
5489 lookup, using an existing branch name as a tag name is discouraged.
5486
5490
5487 Returns 0 on success.
5491 Returns 0 on success.
5488 """
5492 """
5489 wlock = lock = None
5493 wlock = lock = None
5490 try:
5494 try:
5491 wlock = repo.wlock()
5495 wlock = repo.wlock()
5492 lock = repo.lock()
5496 lock = repo.lock()
5493 rev_ = "."
5497 rev_ = "."
5494 names = [t.strip() for t in (name1,) + names]
5498 names = [t.strip() for t in (name1,) + names]
5495 if len(names) != len(set(names)):
5499 if len(names) != len(set(names)):
5496 raise util.Abort(_('tag names must be unique'))
5500 raise util.Abort(_('tag names must be unique'))
5497 for n in names:
5501 for n in names:
5498 if n in ['tip', '.', 'null']:
5502 if n in ['tip', '.', 'null']:
5499 raise util.Abort(_("the name '%s' is reserved") % n)
5503 raise util.Abort(_("the name '%s' is reserved") % n)
5500 if not n:
5504 if not n:
5501 raise util.Abort(_('tag names cannot consist entirely of '
5505 raise util.Abort(_('tag names cannot consist entirely of '
5502 'whitespace'))
5506 'whitespace'))
5503 if opts.get('rev') and opts.get('remove'):
5507 if opts.get('rev') and opts.get('remove'):
5504 raise util.Abort(_("--rev and --remove are incompatible"))
5508 raise util.Abort(_("--rev and --remove are incompatible"))
5505 if opts.get('rev'):
5509 if opts.get('rev'):
5506 rev_ = opts['rev']
5510 rev_ = opts['rev']
5507 message = opts.get('message')
5511 message = opts.get('message')
5508 if opts.get('remove'):
5512 if opts.get('remove'):
5509 expectedtype = opts.get('local') and 'local' or 'global'
5513 expectedtype = opts.get('local') and 'local' or 'global'
5510 for n in names:
5514 for n in names:
5511 if not repo.tagtype(n):
5515 if not repo.tagtype(n):
5512 raise util.Abort(_("tag '%s' does not exist") % n)
5516 raise util.Abort(_("tag '%s' does not exist") % n)
5513 if repo.tagtype(n) != expectedtype:
5517 if repo.tagtype(n) != expectedtype:
5514 if expectedtype == 'global':
5518 if expectedtype == 'global':
5515 raise util.Abort(_("tag '%s' is not a global tag") % n)
5519 raise util.Abort(_("tag '%s' is not a global tag") % n)
5516 else:
5520 else:
5517 raise util.Abort(_("tag '%s' is not a local tag") % n)
5521 raise util.Abort(_("tag '%s' is not a local tag") % n)
5518 rev_ = nullid
5522 rev_ = nullid
5519 if not message:
5523 if not message:
5520 # we don't translate commit messages
5524 # we don't translate commit messages
5521 message = 'Removed tag %s' % ', '.join(names)
5525 message = 'Removed tag %s' % ', '.join(names)
5522 elif not opts.get('force'):
5526 elif not opts.get('force'):
5523 for n in names:
5527 for n in names:
5524 if n in repo.tags():
5528 if n in repo.tags():
5525 raise util.Abort(_("tag '%s' already exists "
5529 raise util.Abort(_("tag '%s' already exists "
5526 "(use -f to force)") % n)
5530 "(use -f to force)") % n)
5527 if not opts.get('local'):
5531 if not opts.get('local'):
5528 p1, p2 = repo.dirstate.parents()
5532 p1, p2 = repo.dirstate.parents()
5529 if p2 != nullid:
5533 if p2 != nullid:
5530 raise util.Abort(_('uncommitted merge'))
5534 raise util.Abort(_('uncommitted merge'))
5531 bheads = repo.branchheads()
5535 bheads = repo.branchheads()
5532 if not opts.get('force') and bheads and p1 not in bheads:
5536 if not opts.get('force') and bheads and p1 not in bheads:
5533 raise util.Abort(_('not at a branch head (use -f to force)'))
5537 raise util.Abort(_('not at a branch head (use -f to force)'))
5534 r = scmutil.revsingle(repo, rev_).node()
5538 r = scmutil.revsingle(repo, rev_).node()
5535
5539
5536 if not message:
5540 if not message:
5537 # we don't translate commit messages
5541 # we don't translate commit messages
5538 message = ('Added tag %s for changeset %s' %
5542 message = ('Added tag %s for changeset %s' %
5539 (', '.join(names), short(r)))
5543 (', '.join(names), short(r)))
5540
5544
5541 date = opts.get('date')
5545 date = opts.get('date')
5542 if date:
5546 if date:
5543 date = util.parsedate(date)
5547 date = util.parsedate(date)
5544
5548
5545 if opts.get('edit'):
5549 if opts.get('edit'):
5546 message = ui.edit(message, ui.username())
5550 message = ui.edit(message, ui.username())
5547
5551
5548 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5552 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5549 finally:
5553 finally:
5550 release(lock, wlock)
5554 release(lock, wlock)
5551
5555
5552 @command('tags', [], '')
5556 @command('tags', [], '')
5553 def tags(ui, repo):
5557 def tags(ui, repo):
5554 """list repository tags
5558 """list repository tags
5555
5559
5556 This lists both regular and local tags. When the -v/--verbose
5560 This lists both regular and local tags. When the -v/--verbose
5557 switch is used, a third column "local" is printed for local tags.
5561 switch is used, a third column "local" is printed for local tags.
5558
5562
5559 Returns 0 on success.
5563 Returns 0 on success.
5560 """
5564 """
5561
5565
5562 hexfunc = ui.debugflag and hex or short
5566 hexfunc = ui.debugflag and hex or short
5563 tagtype = ""
5567 tagtype = ""
5564
5568
5565 for t, n in reversed(repo.tagslist()):
5569 for t, n in reversed(repo.tagslist()):
5566 if ui.quiet:
5570 if ui.quiet:
5567 ui.write("%s\n" % t, label='tags.normal')
5571 ui.write("%s\n" % t, label='tags.normal')
5568 continue
5572 continue
5569
5573
5570 hn = hexfunc(n)
5574 hn = hexfunc(n)
5571 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5575 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5572 rev = ui.label(r, 'log.changeset')
5576 rev = ui.label(r, 'log.changeset')
5573 spaces = " " * (30 - encoding.colwidth(t))
5577 spaces = " " * (30 - encoding.colwidth(t))
5574
5578
5575 tag = ui.label(t, 'tags.normal')
5579 tag = ui.label(t, 'tags.normal')
5576 if ui.verbose:
5580 if ui.verbose:
5577 if repo.tagtype(t) == 'local':
5581 if repo.tagtype(t) == 'local':
5578 tagtype = " local"
5582 tagtype = " local"
5579 tag = ui.label(t, 'tags.local')
5583 tag = ui.label(t, 'tags.local')
5580 else:
5584 else:
5581 tagtype = ""
5585 tagtype = ""
5582 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5586 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5583
5587
5584 @command('tip',
5588 @command('tip',
5585 [('p', 'patch', None, _('show patch')),
5589 [('p', 'patch', None, _('show patch')),
5586 ('g', 'git', None, _('use git extended diff format')),
5590 ('g', 'git', None, _('use git extended diff format')),
5587 ] + templateopts,
5591 ] + templateopts,
5588 _('[-p] [-g]'))
5592 _('[-p] [-g]'))
5589 def tip(ui, repo, **opts):
5593 def tip(ui, repo, **opts):
5590 """show the tip revision
5594 """show the tip revision
5591
5595
5592 The tip revision (usually just called the tip) is the changeset
5596 The tip revision (usually just called the tip) is the changeset
5593 most recently added to the repository (and therefore the most
5597 most recently added to the repository (and therefore the most
5594 recently changed head).
5598 recently changed head).
5595
5599
5596 If you have just made a commit, that commit will be the tip. If
5600 If you have just made a commit, that commit will be the tip. If
5597 you have just pulled changes from another repository, the tip of
5601 you have just pulled changes from another repository, the tip of
5598 that repository becomes the current tip. The "tip" tag is special
5602 that repository becomes the current tip. The "tip" tag is special
5599 and cannot be renamed or assigned to a different changeset.
5603 and cannot be renamed or assigned to a different changeset.
5600
5604
5601 Returns 0 on success.
5605 Returns 0 on success.
5602 """
5606 """
5603 displayer = cmdutil.show_changeset(ui, repo, opts)
5607 displayer = cmdutil.show_changeset(ui, repo, opts)
5604 displayer.show(repo[len(repo) - 1])
5608 displayer.show(repo[len(repo) - 1])
5605 displayer.close()
5609 displayer.close()
5606
5610
5607 @command('unbundle',
5611 @command('unbundle',
5608 [('u', 'update', None,
5612 [('u', 'update', None,
5609 _('update to new branch head if changesets were unbundled'))],
5613 _('update to new branch head if changesets were unbundled'))],
5610 _('[-u] FILE...'))
5614 _('[-u] FILE...'))
5611 def unbundle(ui, repo, fname1, *fnames, **opts):
5615 def unbundle(ui, repo, fname1, *fnames, **opts):
5612 """apply one or more changegroup files
5616 """apply one or more changegroup files
5613
5617
5614 Apply one or more compressed changegroup files generated by the
5618 Apply one or more compressed changegroup files generated by the
5615 bundle command.
5619 bundle command.
5616
5620
5617 Returns 0 on success, 1 if an update has unresolved files.
5621 Returns 0 on success, 1 if an update has unresolved files.
5618 """
5622 """
5619 fnames = (fname1,) + fnames
5623 fnames = (fname1,) + fnames
5620
5624
5621 lock = repo.lock()
5625 lock = repo.lock()
5622 wc = repo['.']
5626 wc = repo['.']
5623 try:
5627 try:
5624 for fname in fnames:
5628 for fname in fnames:
5625 f = url.open(ui, fname)
5629 f = url.open(ui, fname)
5626 gen = changegroup.readbundle(f, fname)
5630 gen = changegroup.readbundle(f, fname)
5627 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5631 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5628 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5632 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5629 finally:
5633 finally:
5630 lock.release()
5634 lock.release()
5631 return postincoming(ui, repo, modheads, opts.get('update'), None)
5635 return postincoming(ui, repo, modheads, opts.get('update'), None)
5632
5636
5633 @command('^update|up|checkout|co',
5637 @command('^update|up|checkout|co',
5634 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5638 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5635 ('c', 'check', None,
5639 ('c', 'check', None,
5636 _('update across branches if no uncommitted changes')),
5640 _('update across branches if no uncommitted changes')),
5637 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5641 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5638 ('r', 'rev', '', _('revision'), _('REV'))],
5642 ('r', 'rev', '', _('revision'), _('REV'))],
5639 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5643 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5640 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5644 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5641 """update working directory (or switch revisions)
5645 """update working directory (or switch revisions)
5642
5646
5643 Update the repository's working directory to the specified
5647 Update the repository's working directory to the specified
5644 changeset. If no changeset is specified, update to the tip of the
5648 changeset. If no changeset is specified, update to the tip of the
5645 current named branch and move the current bookmark (see :hg:`help
5649 current named branch and move the current bookmark (see :hg:`help
5646 bookmarks`).
5650 bookmarks`).
5647
5651
5648 If the changeset is not a descendant of the working directory's
5652 If the changeset is not a descendant of the working directory's
5649 parent, the update is aborted. With the -c/--check option, the
5653 parent, the update is aborted. With the -c/--check option, the
5650 working directory is checked for uncommitted changes; if none are
5654 working directory is checked for uncommitted changes; if none are
5651 found, the working directory is updated to the specified
5655 found, the working directory is updated to the specified
5652 changeset.
5656 changeset.
5653
5657
5654 Update sets the working directory's parent revison to the specified
5658 Update sets the working directory's parent revison to the specified
5655 changeset (see :hg:`help parents`).
5659 changeset (see :hg:`help parents`).
5656
5660
5657 The following rules apply when the working directory contains
5661 The following rules apply when the working directory contains
5658 uncommitted changes:
5662 uncommitted changes:
5659
5663
5660 1. If neither -c/--check nor -C/--clean is specified, and if
5664 1. If neither -c/--check nor -C/--clean is specified, and if
5661 the requested changeset is an ancestor or descendant of
5665 the requested changeset is an ancestor or descendant of
5662 the working directory's parent, the uncommitted changes
5666 the working directory's parent, the uncommitted changes
5663 are merged into the requested changeset and the merged
5667 are merged into the requested changeset and the merged
5664 result is left uncommitted. If the requested changeset is
5668 result is left uncommitted. If the requested changeset is
5665 not an ancestor or descendant (that is, it is on another
5669 not an ancestor or descendant (that is, it is on another
5666 branch), the update is aborted and the uncommitted changes
5670 branch), the update is aborted and the uncommitted changes
5667 are preserved.
5671 are preserved.
5668
5672
5669 2. With the -c/--check option, the update is aborted and the
5673 2. With the -c/--check option, the update is aborted and the
5670 uncommitted changes are preserved.
5674 uncommitted changes are preserved.
5671
5675
5672 3. With the -C/--clean option, uncommitted changes are discarded and
5676 3. With the -C/--clean option, uncommitted changes are discarded and
5673 the working directory is updated to the requested changeset.
5677 the working directory is updated to the requested changeset.
5674
5678
5675 Use null as the changeset to remove the working directory (like
5679 Use null as the changeset to remove the working directory (like
5676 :hg:`clone -U`).
5680 :hg:`clone -U`).
5677
5681
5678 If you want to revert just one file to an older revision, use
5682 If you want to revert just one file to an older revision, use
5679 :hg:`revert [-r REV] NAME`.
5683 :hg:`revert [-r REV] NAME`.
5680
5684
5681 See :hg:`help dates` for a list of formats valid for -d/--date.
5685 See :hg:`help dates` for a list of formats valid for -d/--date.
5682
5686
5683 Returns 0 on success, 1 if there are unresolved files.
5687 Returns 0 on success, 1 if there are unresolved files.
5684 """
5688 """
5685 if rev and node:
5689 if rev and node:
5686 raise util.Abort(_("please specify just one revision"))
5690 raise util.Abort(_("please specify just one revision"))
5687
5691
5688 if rev is None or rev == '':
5692 if rev is None or rev == '':
5689 rev = node
5693 rev = node
5690
5694
5691 # with no argument, we also move the current bookmark, if any
5695 # with no argument, we also move the current bookmark, if any
5692 movemarkfrom = None
5696 movemarkfrom = None
5693 if node is None or node == '':
5697 if node is None or node == '':
5694 movemarkfrom = repo['.'].node()
5698 movemarkfrom = repo['.'].node()
5695
5699
5696 # if we defined a bookmark, we have to remember the original bookmark name
5700 # if we defined a bookmark, we have to remember the original bookmark name
5697 brev = rev
5701 brev = rev
5698 rev = scmutil.revsingle(repo, rev, rev).rev()
5702 rev = scmutil.revsingle(repo, rev, rev).rev()
5699
5703
5700 if check and clean:
5704 if check and clean:
5701 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5705 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5702
5706
5703 if check:
5707 if check:
5704 # we could use dirty() but we can ignore merge and branch trivia
5708 # we could use dirty() but we can ignore merge and branch trivia
5705 c = repo[None]
5709 c = repo[None]
5706 if c.modified() or c.added() or c.removed():
5710 if c.modified() or c.added() or c.removed():
5707 raise util.Abort(_("uncommitted local changes"))
5711 raise util.Abort(_("uncommitted local changes"))
5708
5712
5709 if date:
5713 if date:
5710 if rev is not None:
5714 if rev is not None:
5711 raise util.Abort(_("you can't specify a revision and a date"))
5715 raise util.Abort(_("you can't specify a revision and a date"))
5712 rev = cmdutil.finddate(ui, repo, date)
5716 rev = cmdutil.finddate(ui, repo, date)
5713
5717
5714 if clean or check:
5718 if clean or check:
5715 ret = hg.clean(repo, rev)
5719 ret = hg.clean(repo, rev)
5716 else:
5720 else:
5717 ret = hg.update(repo, rev)
5721 ret = hg.update(repo, rev)
5718
5722
5719 if not ret and movemarkfrom:
5723 if not ret and movemarkfrom:
5720 bookmarks.update(repo, [movemarkfrom], repo['.'].node())
5724 bookmarks.update(repo, [movemarkfrom], repo['.'].node())
5721 elif brev in repo._bookmarks:
5725 elif brev in repo._bookmarks:
5722 bookmarks.setcurrent(repo, brev)
5726 bookmarks.setcurrent(repo, brev)
5723
5727
5724 return ret
5728 return ret
5725
5729
5726 @command('verify', [])
5730 @command('verify', [])
5727 def verify(ui, repo):
5731 def verify(ui, repo):
5728 """verify the integrity of the repository
5732 """verify the integrity of the repository
5729
5733
5730 Verify the integrity of the current repository.
5734 Verify the integrity of the current repository.
5731
5735
5732 This will perform an extensive check of the repository's
5736 This will perform an extensive check of the repository's
5733 integrity, validating the hashes and checksums of each entry in
5737 integrity, validating the hashes and checksums of each entry in
5734 the changelog, manifest, and tracked files, as well as the
5738 the changelog, manifest, and tracked files, as well as the
5735 integrity of their crosslinks and indices.
5739 integrity of their crosslinks and indices.
5736
5740
5737 Returns 0 on success, 1 if errors are encountered.
5741 Returns 0 on success, 1 if errors are encountered.
5738 """
5742 """
5739 return hg.verify(repo)
5743 return hg.verify(repo)
5740
5744
5741 @command('version', [])
5745 @command('version', [])
5742 def version_(ui):
5746 def version_(ui):
5743 """output version and copyright information"""
5747 """output version and copyright information"""
5744 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5748 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5745 % util.version())
5749 % util.version())
5746 ui.status(_(
5750 ui.status(_(
5747 "(see http://mercurial.selenic.com for more information)\n"
5751 "(see http://mercurial.selenic.com for more information)\n"
5748 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5752 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5749 "This is free software; see the source for copying conditions. "
5753 "This is free software; see the source for copying conditions. "
5750 "There is NO\nwarranty; "
5754 "There is NO\nwarranty; "
5751 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5755 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5752 ))
5756 ))
5753
5757
5754 norepo = ("clone init version help debugcommands debugcomplete"
5758 norepo = ("clone init version help debugcommands debugcomplete"
5755 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5759 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5756 " debugknown debuggetbundle debugbundle")
5760 " debugknown debuggetbundle debugbundle")
5757 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5761 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5758 " debugdata debugindex debugindexdot debugrevlog")
5762 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,576 +1,585 b''
1 $ "$TESTDIR/hghave" system-sh || exit 80
1 $ "$TESTDIR/hghave" system-sh || exit 80
2
2
3 Setting up test
3 Setting up test
4
4
5 $ hg init test
5 $ hg init test
6 $ cd test
6 $ cd test
7 $ echo 0 > afile
7 $ echo 0 > afile
8 $ hg add afile
8 $ hg add afile
9 $ hg commit -m "0.0"
9 $ hg commit -m "0.0"
10 $ echo 1 >> afile
10 $ echo 1 >> afile
11 $ hg commit -m "0.1"
11 $ hg commit -m "0.1"
12 $ echo 2 >> afile
12 $ echo 2 >> afile
13 $ hg commit -m "0.2"
13 $ hg commit -m "0.2"
14 $ echo 3 >> afile
14 $ echo 3 >> afile
15 $ hg commit -m "0.3"
15 $ hg commit -m "0.3"
16 $ hg update -C 0
16 $ hg update -C 0
17 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
18 $ echo 1 >> afile
18 $ echo 1 >> afile
19 $ hg commit -m "1.1"
19 $ hg commit -m "1.1"
20 created new head
20 created new head
21 $ echo 2 >> afile
21 $ echo 2 >> afile
22 $ hg commit -m "1.2"
22 $ hg commit -m "1.2"
23 $ echo "a line" > fred
23 $ echo "a line" > fred
24 $ echo 3 >> afile
24 $ echo 3 >> afile
25 $ hg add fred
25 $ hg add fred
26 $ hg commit -m "1.3"
26 $ hg commit -m "1.3"
27 $ hg mv afile adifferentfile
27 $ hg mv afile adifferentfile
28 $ hg commit -m "1.3m"
28 $ hg commit -m "1.3m"
29 $ hg update -C 3
29 $ hg update -C 3
30 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
30 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
31 $ hg mv afile anotherfile
31 $ hg mv afile anotherfile
32 $ hg commit -m "0.3m"
32 $ hg commit -m "0.3m"
33 $ hg verify
33 $ hg verify
34 checking changesets
34 checking changesets
35 checking manifests
35 checking manifests
36 crosschecking files in changesets and manifests
36 crosschecking files in changesets and manifests
37 checking files
37 checking files
38 4 files, 9 changesets, 7 total revisions
38 4 files, 9 changesets, 7 total revisions
39 $ cd ..
39 $ cd ..
40 $ hg init empty
40 $ hg init empty
41
41
42 Bundle and phase
43
44 $ hg -R test phase --force --secret 0
45 $ hg -R test bundle phase.hg empty
46 searching for changes
47 no changes found but 9 secret changesets
48 [1]
49 $ hg -R test phase --draft -r 'head()'
50
42 Bundle --all
51 Bundle --all
43
52
44 $ hg -R test bundle --all all.hg
53 $ hg -R test bundle --all all.hg
45 9 changesets found
54 9 changesets found
46
55
47 Bundle test to full.hg
56 Bundle test to full.hg
48
57
49 $ hg -R test bundle full.hg empty
58 $ hg -R test bundle full.hg empty
50 searching for changes
59 searching for changes
51 9 changesets found
60 9 changesets found
52
61
53 Unbundle full.hg in test
62 Unbundle full.hg in test
54
63
55 $ hg -R test unbundle full.hg
64 $ hg -R test unbundle full.hg
56 adding changesets
65 adding changesets
57 adding manifests
66 adding manifests
58 adding file changes
67 adding file changes
59 added 0 changesets with 0 changes to 4 files
68 added 0 changesets with 0 changes to 4 files
60 (run 'hg update' to get a working copy)
69 (run 'hg update' to get a working copy)
61
70
62 Verify empty
71 Verify empty
63
72
64 $ hg -R empty heads
73 $ hg -R empty heads
65 [1]
74 [1]
66 $ hg -R empty verify
75 $ hg -R empty verify
67 checking changesets
76 checking changesets
68 checking manifests
77 checking manifests
69 crosschecking files in changesets and manifests
78 crosschecking files in changesets and manifests
70 checking files
79 checking files
71 0 files, 0 changesets, 0 total revisions
80 0 files, 0 changesets, 0 total revisions
72
81
73 Pull full.hg into test (using --cwd)
82 Pull full.hg into test (using --cwd)
74
83
75 $ hg --cwd test pull ../full.hg
84 $ hg --cwd test pull ../full.hg
76 pulling from ../full.hg
85 pulling from ../full.hg
77 searching for changes
86 searching for changes
78 no changes found
87 no changes found
79
88
80 Pull full.hg into empty (using --cwd)
89 Pull full.hg into empty (using --cwd)
81
90
82 $ hg --cwd empty pull ../full.hg
91 $ hg --cwd empty pull ../full.hg
83 pulling from ../full.hg
92 pulling from ../full.hg
84 requesting all changes
93 requesting all changes
85 adding changesets
94 adding changesets
86 adding manifests
95 adding manifests
87 adding file changes
96 adding file changes
88 added 9 changesets with 7 changes to 4 files (+1 heads)
97 added 9 changesets with 7 changes to 4 files (+1 heads)
89 (run 'hg heads' to see heads, 'hg merge' to merge)
98 (run 'hg heads' to see heads, 'hg merge' to merge)
90
99
91 Rollback empty
100 Rollback empty
92
101
93 $ hg -R empty rollback
102 $ hg -R empty rollback
94 repository tip rolled back to revision -1 (undo pull)
103 repository tip rolled back to revision -1 (undo pull)
95
104
96 Pull full.hg into empty again (using --cwd)
105 Pull full.hg into empty again (using --cwd)
97
106
98 $ hg --cwd empty pull ../full.hg
107 $ hg --cwd empty pull ../full.hg
99 pulling from ../full.hg
108 pulling from ../full.hg
100 requesting all changes
109 requesting all changes
101 adding changesets
110 adding changesets
102 adding manifests
111 adding manifests
103 adding file changes
112 adding file changes
104 added 9 changesets with 7 changes to 4 files (+1 heads)
113 added 9 changesets with 7 changes to 4 files (+1 heads)
105 (run 'hg heads' to see heads, 'hg merge' to merge)
114 (run 'hg heads' to see heads, 'hg merge' to merge)
106
115
107 Pull full.hg into test (using -R)
116 Pull full.hg into test (using -R)
108
117
109 $ hg -R test pull full.hg
118 $ hg -R test pull full.hg
110 pulling from full.hg
119 pulling from full.hg
111 searching for changes
120 searching for changes
112 no changes found
121 no changes found
113
122
114 Pull full.hg into empty (using -R)
123 Pull full.hg into empty (using -R)
115
124
116 $ hg -R empty pull full.hg
125 $ hg -R empty pull full.hg
117 pulling from full.hg
126 pulling from full.hg
118 searching for changes
127 searching for changes
119 no changes found
128 no changes found
120
129
121 Rollback empty
130 Rollback empty
122
131
123 $ hg -R empty rollback
132 $ hg -R empty rollback
124 repository tip rolled back to revision -1 (undo pull)
133 repository tip rolled back to revision -1 (undo pull)
125
134
126 Pull full.hg into empty again (using -R)
135 Pull full.hg into empty again (using -R)
127
136
128 $ hg -R empty pull full.hg
137 $ hg -R empty pull full.hg
129 pulling from full.hg
138 pulling from full.hg
130 requesting all changes
139 requesting all changes
131 adding changesets
140 adding changesets
132 adding manifests
141 adding manifests
133 adding file changes
142 adding file changes
134 added 9 changesets with 7 changes to 4 files (+1 heads)
143 added 9 changesets with 7 changes to 4 files (+1 heads)
135 (run 'hg heads' to see heads, 'hg merge' to merge)
144 (run 'hg heads' to see heads, 'hg merge' to merge)
136
145
137 Log -R full.hg in fresh empty
146 Log -R full.hg in fresh empty
138
147
139 $ rm -r empty
148 $ rm -r empty
140 $ hg init empty
149 $ hg init empty
141 $ cd empty
150 $ cd empty
142 $ hg -R bundle://../full.hg log
151 $ hg -R bundle://../full.hg log
143 changeset: 8:aa35859c02ea
152 changeset: 8:aa35859c02ea
144 tag: tip
153 tag: tip
145 parent: 3:eebf5a27f8ca
154 parent: 3:eebf5a27f8ca
146 user: test
155 user: test
147 date: Thu Jan 01 00:00:00 1970 +0000
156 date: Thu Jan 01 00:00:00 1970 +0000
148 summary: 0.3m
157 summary: 0.3m
149
158
150 changeset: 7:a6a34bfa0076
159 changeset: 7:a6a34bfa0076
151 user: test
160 user: test
152 date: Thu Jan 01 00:00:00 1970 +0000
161 date: Thu Jan 01 00:00:00 1970 +0000
153 summary: 1.3m
162 summary: 1.3m
154
163
155 changeset: 6:7373c1169842
164 changeset: 6:7373c1169842
156 user: test
165 user: test
157 date: Thu Jan 01 00:00:00 1970 +0000
166 date: Thu Jan 01 00:00:00 1970 +0000
158 summary: 1.3
167 summary: 1.3
159
168
160 changeset: 5:1bb50a9436a7
169 changeset: 5:1bb50a9436a7
161 user: test
170 user: test
162 date: Thu Jan 01 00:00:00 1970 +0000
171 date: Thu Jan 01 00:00:00 1970 +0000
163 summary: 1.2
172 summary: 1.2
164
173
165 changeset: 4:095197eb4973
174 changeset: 4:095197eb4973
166 parent: 0:f9ee2f85a263
175 parent: 0:f9ee2f85a263
167 user: test
176 user: test
168 date: Thu Jan 01 00:00:00 1970 +0000
177 date: Thu Jan 01 00:00:00 1970 +0000
169 summary: 1.1
178 summary: 1.1
170
179
171 changeset: 3:eebf5a27f8ca
180 changeset: 3:eebf5a27f8ca
172 user: test
181 user: test
173 date: Thu Jan 01 00:00:00 1970 +0000
182 date: Thu Jan 01 00:00:00 1970 +0000
174 summary: 0.3
183 summary: 0.3
175
184
176 changeset: 2:e38ba6f5b7e0
185 changeset: 2:e38ba6f5b7e0
177 user: test
186 user: test
178 date: Thu Jan 01 00:00:00 1970 +0000
187 date: Thu Jan 01 00:00:00 1970 +0000
179 summary: 0.2
188 summary: 0.2
180
189
181 changeset: 1:34c2bf6b0626
190 changeset: 1:34c2bf6b0626
182 user: test
191 user: test
183 date: Thu Jan 01 00:00:00 1970 +0000
192 date: Thu Jan 01 00:00:00 1970 +0000
184 summary: 0.1
193 summary: 0.1
185
194
186 changeset: 0:f9ee2f85a263
195 changeset: 0:f9ee2f85a263
187 user: test
196 user: test
188 date: Thu Jan 01 00:00:00 1970 +0000
197 date: Thu Jan 01 00:00:00 1970 +0000
189 summary: 0.0
198 summary: 0.0
190
199
191 Make sure bundlerepo doesn't leak tempfiles (issue2491)
200 Make sure bundlerepo doesn't leak tempfiles (issue2491)
192
201
193 $ ls .hg
202 $ ls .hg
194 00changelog.i
203 00changelog.i
195 cache
204 cache
196 requires
205 requires
197 store
206 store
198
207
199 Pull ../full.hg into empty (with hook)
208 Pull ../full.hg into empty (with hook)
200
209
201 $ echo '[hooks]' >> .hg/hgrc
210 $ echo '[hooks]' >> .hg/hgrc
202 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup' >> .hg/hgrc
211 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup' >> .hg/hgrc
203
212
204 doesn't work (yet ?)
213 doesn't work (yet ?)
205
214
206 hg -R bundle://../full.hg verify
215 hg -R bundle://../full.hg verify
207
216
208 $ hg pull bundle://../full.hg
217 $ hg pull bundle://../full.hg
209 pulling from bundle:../full.hg
218 pulling from bundle:../full.hg
210 requesting all changes
219 requesting all changes
211 adding changesets
220 adding changesets
212 adding manifests
221 adding manifests
213 adding file changes
222 adding file changes
214 added 9 changesets with 7 changes to 4 files (+1 heads)
223 added 9 changesets with 7 changes to 4 files (+1 heads)
215 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:../full.hg
224 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:../full.hg
216 (run 'hg heads' to see heads, 'hg merge' to merge)
225 (run 'hg heads' to see heads, 'hg merge' to merge)
217
226
218 Rollback empty
227 Rollback empty
219
228
220 $ hg rollback
229 $ hg rollback
221 repository tip rolled back to revision -1 (undo pull)
230 repository tip rolled back to revision -1 (undo pull)
222 $ cd ..
231 $ cd ..
223
232
224 Log -R bundle:empty+full.hg
233 Log -R bundle:empty+full.hg
225
234
226 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
235 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
227 8 7 6 5 4 3 2 1 0
236 8 7 6 5 4 3 2 1 0
228
237
229 Pull full.hg into empty again (using -R; with hook)
238 Pull full.hg into empty again (using -R; with hook)
230
239
231 $ hg -R empty pull full.hg
240 $ hg -R empty pull full.hg
232 pulling from full.hg
241 pulling from full.hg
233 requesting all changes
242 requesting all changes
234 adding changesets
243 adding changesets
235 adding manifests
244 adding manifests
236 adding file changes
245 adding file changes
237 added 9 changesets with 7 changes to 4 files (+1 heads)
246 added 9 changesets with 7 changes to 4 files (+1 heads)
238 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:empty+full.hg
247 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:empty+full.hg
239 (run 'hg heads' to see heads, 'hg merge' to merge)
248 (run 'hg heads' to see heads, 'hg merge' to merge)
240
249
241 Create partial clones
250 Create partial clones
242
251
243 $ rm -r empty
252 $ rm -r empty
244 $ hg init empty
253 $ hg init empty
245 $ hg clone -r 3 test partial
254 $ hg clone -r 3 test partial
246 adding changesets
255 adding changesets
247 adding manifests
256 adding manifests
248 adding file changes
257 adding file changes
249 added 4 changesets with 4 changes to 1 files
258 added 4 changesets with 4 changes to 1 files
250 updating to branch default
259 updating to branch default
251 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
260 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
252 $ hg clone partial partial2
261 $ hg clone partial partial2
253 updating to branch default
262 updating to branch default
254 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
255 $ cd partial
264 $ cd partial
256
265
257 Log -R full.hg in partial
266 Log -R full.hg in partial
258
267
259 $ hg -R bundle://../full.hg log
268 $ hg -R bundle://../full.hg log
260 changeset: 8:aa35859c02ea
269 changeset: 8:aa35859c02ea
261 tag: tip
270 tag: tip
262 parent: 3:eebf5a27f8ca
271 parent: 3:eebf5a27f8ca
263 user: test
272 user: test
264 date: Thu Jan 01 00:00:00 1970 +0000
273 date: Thu Jan 01 00:00:00 1970 +0000
265 summary: 0.3m
274 summary: 0.3m
266
275
267 changeset: 7:a6a34bfa0076
276 changeset: 7:a6a34bfa0076
268 user: test
277 user: test
269 date: Thu Jan 01 00:00:00 1970 +0000
278 date: Thu Jan 01 00:00:00 1970 +0000
270 summary: 1.3m
279 summary: 1.3m
271
280
272 changeset: 6:7373c1169842
281 changeset: 6:7373c1169842
273 user: test
282 user: test
274 date: Thu Jan 01 00:00:00 1970 +0000
283 date: Thu Jan 01 00:00:00 1970 +0000
275 summary: 1.3
284 summary: 1.3
276
285
277 changeset: 5:1bb50a9436a7
286 changeset: 5:1bb50a9436a7
278 user: test
287 user: test
279 date: Thu Jan 01 00:00:00 1970 +0000
288 date: Thu Jan 01 00:00:00 1970 +0000
280 summary: 1.2
289 summary: 1.2
281
290
282 changeset: 4:095197eb4973
291 changeset: 4:095197eb4973
283 parent: 0:f9ee2f85a263
292 parent: 0:f9ee2f85a263
284 user: test
293 user: test
285 date: Thu Jan 01 00:00:00 1970 +0000
294 date: Thu Jan 01 00:00:00 1970 +0000
286 summary: 1.1
295 summary: 1.1
287
296
288 changeset: 3:eebf5a27f8ca
297 changeset: 3:eebf5a27f8ca
289 user: test
298 user: test
290 date: Thu Jan 01 00:00:00 1970 +0000
299 date: Thu Jan 01 00:00:00 1970 +0000
291 summary: 0.3
300 summary: 0.3
292
301
293 changeset: 2:e38ba6f5b7e0
302 changeset: 2:e38ba6f5b7e0
294 user: test
303 user: test
295 date: Thu Jan 01 00:00:00 1970 +0000
304 date: Thu Jan 01 00:00:00 1970 +0000
296 summary: 0.2
305 summary: 0.2
297
306
298 changeset: 1:34c2bf6b0626
307 changeset: 1:34c2bf6b0626
299 user: test
308 user: test
300 date: Thu Jan 01 00:00:00 1970 +0000
309 date: Thu Jan 01 00:00:00 1970 +0000
301 summary: 0.1
310 summary: 0.1
302
311
303 changeset: 0:f9ee2f85a263
312 changeset: 0:f9ee2f85a263
304 user: test
313 user: test
305 date: Thu Jan 01 00:00:00 1970 +0000
314 date: Thu Jan 01 00:00:00 1970 +0000
306 summary: 0.0
315 summary: 0.0
307
316
308
317
309 Incoming full.hg in partial
318 Incoming full.hg in partial
310
319
311 $ hg incoming bundle://../full.hg
320 $ hg incoming bundle://../full.hg
312 comparing with bundle:../full.hg
321 comparing with bundle:../full.hg
313 searching for changes
322 searching for changes
314 changeset: 4:095197eb4973
323 changeset: 4:095197eb4973
315 parent: 0:f9ee2f85a263
324 parent: 0:f9ee2f85a263
316 user: test
325 user: test
317 date: Thu Jan 01 00:00:00 1970 +0000
326 date: Thu Jan 01 00:00:00 1970 +0000
318 summary: 1.1
327 summary: 1.1
319
328
320 changeset: 5:1bb50a9436a7
329 changeset: 5:1bb50a9436a7
321 user: test
330 user: test
322 date: Thu Jan 01 00:00:00 1970 +0000
331 date: Thu Jan 01 00:00:00 1970 +0000
323 summary: 1.2
332 summary: 1.2
324
333
325 changeset: 6:7373c1169842
334 changeset: 6:7373c1169842
326 user: test
335 user: test
327 date: Thu Jan 01 00:00:00 1970 +0000
336 date: Thu Jan 01 00:00:00 1970 +0000
328 summary: 1.3
337 summary: 1.3
329
338
330 changeset: 7:a6a34bfa0076
339 changeset: 7:a6a34bfa0076
331 user: test
340 user: test
332 date: Thu Jan 01 00:00:00 1970 +0000
341 date: Thu Jan 01 00:00:00 1970 +0000
333 summary: 1.3m
342 summary: 1.3m
334
343
335 changeset: 8:aa35859c02ea
344 changeset: 8:aa35859c02ea
336 tag: tip
345 tag: tip
337 parent: 3:eebf5a27f8ca
346 parent: 3:eebf5a27f8ca
338 user: test
347 user: test
339 date: Thu Jan 01 00:00:00 1970 +0000
348 date: Thu Jan 01 00:00:00 1970 +0000
340 summary: 0.3m
349 summary: 0.3m
341
350
342
351
343 Outgoing -R full.hg vs partial2 in partial
352 Outgoing -R full.hg vs partial2 in partial
344
353
345 $ hg -R bundle://../full.hg outgoing ../partial2
354 $ hg -R bundle://../full.hg outgoing ../partial2
346 comparing with ../partial2
355 comparing with ../partial2
347 searching for changes
356 searching for changes
348 changeset: 4:095197eb4973
357 changeset: 4:095197eb4973
349 parent: 0:f9ee2f85a263
358 parent: 0:f9ee2f85a263
350 user: test
359 user: test
351 date: Thu Jan 01 00:00:00 1970 +0000
360 date: Thu Jan 01 00:00:00 1970 +0000
352 summary: 1.1
361 summary: 1.1
353
362
354 changeset: 5:1bb50a9436a7
363 changeset: 5:1bb50a9436a7
355 user: test
364 user: test
356 date: Thu Jan 01 00:00:00 1970 +0000
365 date: Thu Jan 01 00:00:00 1970 +0000
357 summary: 1.2
366 summary: 1.2
358
367
359 changeset: 6:7373c1169842
368 changeset: 6:7373c1169842
360 user: test
369 user: test
361 date: Thu Jan 01 00:00:00 1970 +0000
370 date: Thu Jan 01 00:00:00 1970 +0000
362 summary: 1.3
371 summary: 1.3
363
372
364 changeset: 7:a6a34bfa0076
373 changeset: 7:a6a34bfa0076
365 user: test
374 user: test
366 date: Thu Jan 01 00:00:00 1970 +0000
375 date: Thu Jan 01 00:00:00 1970 +0000
367 summary: 1.3m
376 summary: 1.3m
368
377
369 changeset: 8:aa35859c02ea
378 changeset: 8:aa35859c02ea
370 tag: tip
379 tag: tip
371 parent: 3:eebf5a27f8ca
380 parent: 3:eebf5a27f8ca
372 user: test
381 user: test
373 date: Thu Jan 01 00:00:00 1970 +0000
382 date: Thu Jan 01 00:00:00 1970 +0000
374 summary: 0.3m
383 summary: 0.3m
375
384
376
385
377 Outgoing -R does-not-exist.hg vs partial2 in partial
386 Outgoing -R does-not-exist.hg vs partial2 in partial
378
387
379 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
388 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
380 abort: *: ../does-not-exist.hg (glob)
389 abort: *: ../does-not-exist.hg (glob)
381 [255]
390 [255]
382 $ cd ..
391 $ cd ..
383
392
384 Direct clone from bundle (all-history)
393 Direct clone from bundle (all-history)
385
394
386 $ hg clone full.hg full-clone
395 $ hg clone full.hg full-clone
387 requesting all changes
396 requesting all changes
388 adding changesets
397 adding changesets
389 adding manifests
398 adding manifests
390 adding file changes
399 adding file changes
391 added 9 changesets with 7 changes to 4 files (+1 heads)
400 added 9 changesets with 7 changes to 4 files (+1 heads)
392 updating to branch default
401 updating to branch default
393 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
402 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
394 $ hg -R full-clone heads
403 $ hg -R full-clone heads
395 changeset: 8:aa35859c02ea
404 changeset: 8:aa35859c02ea
396 tag: tip
405 tag: tip
397 parent: 3:eebf5a27f8ca
406 parent: 3:eebf5a27f8ca
398 user: test
407 user: test
399 date: Thu Jan 01 00:00:00 1970 +0000
408 date: Thu Jan 01 00:00:00 1970 +0000
400 summary: 0.3m
409 summary: 0.3m
401
410
402 changeset: 7:a6a34bfa0076
411 changeset: 7:a6a34bfa0076
403 user: test
412 user: test
404 date: Thu Jan 01 00:00:00 1970 +0000
413 date: Thu Jan 01 00:00:00 1970 +0000
405 summary: 1.3m
414 summary: 1.3m
406
415
407 $ rm -r full-clone
416 $ rm -r full-clone
408
417
409 When cloning from a non-copiable repository into '', do not
418 When cloning from a non-copiable repository into '', do not
410 recurse infinitely (issue 2528)
419 recurse infinitely (issue 2528)
411
420
412 $ hg clone full.hg ''
421 $ hg clone full.hg ''
413 abort: * (glob)
422 abort: * (glob)
414 [255]
423 [255]
415
424
416 test for http://mercurial.selenic.com/bts/issue216
425 test for http://mercurial.selenic.com/bts/issue216
417
426
418 Unbundle incremental bundles into fresh empty in one go
427 Unbundle incremental bundles into fresh empty in one go
419
428
420 $ rm -r empty
429 $ rm -r empty
421 $ hg init empty
430 $ hg init empty
422 $ hg -R test bundle --base null -r 0 ../0.hg
431 $ hg -R test bundle --base null -r 0 ../0.hg
423 1 changesets found
432 1 changesets found
424 $ hg -R test bundle --base 0 -r 1 ../1.hg
433 $ hg -R test bundle --base 0 -r 1 ../1.hg
425 1 changesets found
434 1 changesets found
426 $ hg -R empty unbundle -u ../0.hg ../1.hg
435 $ hg -R empty unbundle -u ../0.hg ../1.hg
427 adding changesets
436 adding changesets
428 adding manifests
437 adding manifests
429 adding file changes
438 adding file changes
430 added 1 changesets with 1 changes to 1 files
439 added 1 changesets with 1 changes to 1 files
431 adding changesets
440 adding changesets
432 adding manifests
441 adding manifests
433 adding file changes
442 adding file changes
434 added 1 changesets with 1 changes to 1 files
443 added 1 changesets with 1 changes to 1 files
435 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
444 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
436
445
437 test for 540d1059c802
446 test for 540d1059c802
438
447
439 test for 540d1059c802
448 test for 540d1059c802
440
449
441 $ hg init orig
450 $ hg init orig
442 $ cd orig
451 $ cd orig
443 $ echo foo > foo
452 $ echo foo > foo
444 $ hg add foo
453 $ hg add foo
445 $ hg ci -m 'add foo'
454 $ hg ci -m 'add foo'
446
455
447 $ hg clone . ../copy
456 $ hg clone . ../copy
448 updating to branch default
457 updating to branch default
449 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
458 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
450 $ hg tag foo
459 $ hg tag foo
451
460
452 $ cd ../copy
461 $ cd ../copy
453 $ echo >> foo
462 $ echo >> foo
454 $ hg ci -m 'change foo'
463 $ hg ci -m 'change foo'
455 $ hg bundle ../bundle.hg ../orig
464 $ hg bundle ../bundle.hg ../orig
456 searching for changes
465 searching for changes
457 1 changesets found
466 1 changesets found
458
467
459 $ cd ../orig
468 $ cd ../orig
460 $ hg incoming ../bundle.hg
469 $ hg incoming ../bundle.hg
461 comparing with ../bundle.hg
470 comparing with ../bundle.hg
462 searching for changes
471 searching for changes
463 changeset: 2:ed1b79f46b9a
472 changeset: 2:ed1b79f46b9a
464 tag: tip
473 tag: tip
465 parent: 0:bbd179dfa0a7
474 parent: 0:bbd179dfa0a7
466 user: test
475 user: test
467 date: Thu Jan 01 00:00:00 1970 +0000
476 date: Thu Jan 01 00:00:00 1970 +0000
468 summary: change foo
477 summary: change foo
469
478
470 $ cd ..
479 $ cd ..
471
480
472 test bundle with # in the filename (issue2154):
481 test bundle with # in the filename (issue2154):
473
482
474 $ cp bundle.hg 'test#bundle.hg'
483 $ cp bundle.hg 'test#bundle.hg'
475 $ cd orig
484 $ cd orig
476 $ hg incoming '../test#bundle.hg'
485 $ hg incoming '../test#bundle.hg'
477 comparing with ../test
486 comparing with ../test
478 abort: unknown revision 'bundle.hg'!
487 abort: unknown revision 'bundle.hg'!
479 [255]
488 [255]
480
489
481 note that percent encoding is not handled:
490 note that percent encoding is not handled:
482
491
483 $ hg incoming ../test%23bundle.hg
492 $ hg incoming ../test%23bundle.hg
484 abort: repository ../test%23bundle.hg not found!
493 abort: repository ../test%23bundle.hg not found!
485 [255]
494 [255]
486 $ cd ..
495 $ cd ..
487
496
488 test for http://mercurial.selenic.com/bts/issue1144
497 test for http://mercurial.selenic.com/bts/issue1144
489
498
490 test that verify bundle does not traceback
499 test that verify bundle does not traceback
491
500
492 partial history bundle, fails w/ unkown parent
501 partial history bundle, fails w/ unkown parent
493
502
494 $ hg -R bundle.hg verify
503 $ hg -R bundle.hg verify
495 abort: 00changelog.i@bbd179dfa0a7: unknown parent!
504 abort: 00changelog.i@bbd179dfa0a7: unknown parent!
496 [255]
505 [255]
497
506
498 full history bundle, refuses to verify non-local repo
507 full history bundle, refuses to verify non-local repo
499
508
500 $ hg -R all.hg verify
509 $ hg -R all.hg verify
501 abort: cannot verify bundle or remote repos
510 abort: cannot verify bundle or remote repos
502 [255]
511 [255]
503
512
504 but, regular verify must continue to work
513 but, regular verify must continue to work
505
514
506 $ hg -R orig verify
515 $ hg -R orig verify
507 checking changesets
516 checking changesets
508 checking manifests
517 checking manifests
509 crosschecking files in changesets and manifests
518 crosschecking files in changesets and manifests
510 checking files
519 checking files
511 2 files, 2 changesets, 2 total revisions
520 2 files, 2 changesets, 2 total revisions
512
521
513 diff against bundle
522 diff against bundle
514
523
515 $ hg init b
524 $ hg init b
516 $ cd b
525 $ cd b
517 $ hg -R ../all.hg diff -r tip
526 $ hg -R ../all.hg diff -r tip
518 diff -r aa35859c02ea anotherfile
527 diff -r aa35859c02ea anotherfile
519 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
528 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
520 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
529 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
521 @@ -1,4 +0,0 @@
530 @@ -1,4 +0,0 @@
522 -0
531 -0
523 -1
532 -1
524 -2
533 -2
525 -3
534 -3
526 $ cd ..
535 $ cd ..
527
536
528 bundle single branch
537 bundle single branch
529
538
530 $ hg init branchy
539 $ hg init branchy
531 $ cd branchy
540 $ cd branchy
532 $ echo a >a
541 $ echo a >a
533 $ hg ci -Ama
542 $ hg ci -Ama
534 adding a
543 adding a
535 $ echo b >b
544 $ echo b >b
536 $ hg ci -Amb
545 $ hg ci -Amb
537 adding b
546 adding b
538 $ echo b1 >b1
547 $ echo b1 >b1
539 $ hg ci -Amb1
548 $ hg ci -Amb1
540 adding b1
549 adding b1
541 $ hg up 0
550 $ hg up 0
542 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
551 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
543 $ echo c >c
552 $ echo c >c
544 $ hg ci -Amc
553 $ hg ci -Amc
545 adding c
554 adding c
546 created new head
555 created new head
547 $ echo c1 >c1
556 $ echo c1 >c1
548 $ hg ci -Amc1
557 $ hg ci -Amc1
549 adding c1
558 adding c1
550 $ hg clone -q .#tip part
559 $ hg clone -q .#tip part
551
560
552 == bundling via incoming
561 == bundling via incoming
553
562
554 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
563 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
555 comparing with .
564 comparing with .
556 searching for changes
565 searching for changes
557 d2ae7f538514cd87c17547b0de4cea71fe1af9fb
566 d2ae7f538514cd87c17547b0de4cea71fe1af9fb
558 5ece8e77363e2b5269e27c66828b72da29e4341a
567 5ece8e77363e2b5269e27c66828b72da29e4341a
559
568
560 == bundling
569 == bundling
561
570
562 $ hg bundle bundle.hg part --debug
571 $ hg bundle bundle.hg part --debug
563 query 1; heads
572 query 1; heads
564 searching for changes
573 searching for changes
565 all remote heads known locally
574 all remote heads known locally
566 2 changesets found
575 2 changesets found
567 list of changesets:
576 list of changesets:
568 d2ae7f538514cd87c17547b0de4cea71fe1af9fb
577 d2ae7f538514cd87c17547b0de4cea71fe1af9fb
569 5ece8e77363e2b5269e27c66828b72da29e4341a
578 5ece8e77363e2b5269e27c66828b72da29e4341a
570 bundling: 1/2 changesets (50.00%)
579 bundling: 1/2 changesets (50.00%)
571 bundling: 2/2 changesets (100.00%)
580 bundling: 2/2 changesets (100.00%)
572 bundling: 1/2 manifests (50.00%)
581 bundling: 1/2 manifests (50.00%)
573 bundling: 2/2 manifests (100.00%)
582 bundling: 2/2 manifests (100.00%)
574 bundling: b 1/2 files (50.00%)
583 bundling: b 1/2 files (50.00%)
575 bundling: b1 2/2 files (100.00%)
584 bundling: b1 2/2 files (100.00%)
576
585
General Comments 0
You need to be logged in to leave comments. Login now