##// END OF EJS Templates
bookmarks: automatically advance bookmark on naked update (BC) (issue2894)
Matt Mackall -
r15935:6c97eb44 default
parent child Browse files
Show More
@@ -1,5741 +1,5748
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, _('do not mark a new bookmark active'))],
728 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
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 hexfn = ui.debugflag and hex or short
749 hexfn = ui.debugflag and hex or short
750 marks = repo._bookmarks
750 marks = repo._bookmarks
751 cur = repo.changectx('.').node()
751 cur = repo.changectx('.').node()
752
752
753 if delete:
753 if delete:
754 if mark is None:
754 if mark is None:
755 raise util.Abort(_("bookmark name required"))
755 raise util.Abort(_("bookmark name required"))
756 if mark not in marks:
756 if mark not in marks:
757 raise util.Abort(_("bookmark '%s' does not exist") % mark)
757 raise util.Abort(_("bookmark '%s' does not exist") % mark)
758 if mark == repo._bookmarkcurrent:
758 if mark == repo._bookmarkcurrent:
759 bookmarks.setcurrent(repo, None)
759 bookmarks.setcurrent(repo, None)
760 del marks[mark]
760 del marks[mark]
761 bookmarks.write(repo)
761 bookmarks.write(repo)
762 return
762 return
763
763
764 if rename:
764 if rename:
765 if rename not in marks:
765 if rename not in marks:
766 raise util.Abort(_("bookmark '%s' does not exist") % rename)
766 raise util.Abort(_("bookmark '%s' does not exist") % rename)
767 if mark in marks and not force:
767 if mark in marks and not force:
768 raise util.Abort(_("bookmark '%s' already exists "
768 raise util.Abort(_("bookmark '%s' already exists "
769 "(use -f to force)") % mark)
769 "(use -f to force)") % mark)
770 if mark is None:
770 if mark is None:
771 raise util.Abort(_("new bookmark name required"))
771 raise util.Abort(_("new bookmark name required"))
772 marks[mark] = marks[rename]
772 marks[mark] = marks[rename]
773 if repo._bookmarkcurrent == rename and not inactive:
773 if repo._bookmarkcurrent == rename and not inactive:
774 bookmarks.setcurrent(repo, mark)
774 bookmarks.setcurrent(repo, mark)
775 del marks[rename]
775 del marks[rename]
776 bookmarks.write(repo)
776 bookmarks.write(repo)
777 return
777 return
778
778
779 if mark is not None:
779 if mark is not None:
780 if "\n" in mark:
780 if "\n" in mark:
781 raise util.Abort(_("bookmark name cannot contain newlines"))
781 raise util.Abort(_("bookmark name cannot contain newlines"))
782 mark = mark.strip()
782 mark = mark.strip()
783 if not mark:
783 if not mark:
784 raise util.Abort(_("bookmark names cannot consist entirely of "
784 raise util.Abort(_("bookmark names cannot consist entirely of "
785 "whitespace"))
785 "whitespace"))
786 if inactive and mark == repo._bookmarkcurrent:
786 if inactive and mark == repo._bookmarkcurrent:
787 bookmarks.setcurrent(repo, None)
787 bookmarks.setcurrent(repo, None)
788 return
788 return
789 if mark in marks and not force:
789 if mark in marks and not force:
790 raise util.Abort(_("bookmark '%s' already exists "
790 raise util.Abort(_("bookmark '%s' already exists "
791 "(use -f to force)") % mark)
791 "(use -f to force)") % mark)
792 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
792 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
793 and not force):
793 and not force):
794 raise util.Abort(
794 raise util.Abort(
795 _("a bookmark cannot have the name of an existing branch"))
795 _("a bookmark cannot have the name of an existing branch"))
796 if rev:
796 if rev:
797 marks[mark] = repo.lookup(rev)
797 marks[mark] = repo.lookup(rev)
798 else:
798 else:
799 marks[mark] = cur
799 marks[mark] = cur
800 if not inactive and cur == marks[mark]:
800 if not inactive and cur == marks[mark]:
801 bookmarks.setcurrent(repo, mark)
801 bookmarks.setcurrent(repo, mark)
802 bookmarks.write(repo)
802 bookmarks.write(repo)
803 return
803 return
804
804
805 if mark is None:
805 if mark is None:
806 if rev:
806 if rev:
807 raise util.Abort(_("bookmark name required"))
807 raise util.Abort(_("bookmark name required"))
808 if len(marks) == 0:
808 if len(marks) == 0:
809 ui.status(_("no bookmarks set\n"))
809 ui.status(_("no bookmarks set\n"))
810 else:
810 else:
811 for bmark, n in sorted(marks.iteritems()):
811 for bmark, n in sorted(marks.iteritems()):
812 current = repo._bookmarkcurrent
812 current = repo._bookmarkcurrent
813 if bmark == current and n == cur:
813 if bmark == current and n == cur:
814 prefix, label = '*', 'bookmarks.current'
814 prefix, label = '*', 'bookmarks.current'
815 else:
815 else:
816 prefix, label = ' ', ''
816 prefix, label = ' ', ''
817
817
818 if ui.quiet:
818 if ui.quiet:
819 ui.write("%s\n" % bmark, label=label)
819 ui.write("%s\n" % bmark, label=label)
820 else:
820 else:
821 ui.write(" %s %-25s %d:%s\n" % (
821 ui.write(" %s %-25s %d:%s\n" % (
822 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
822 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
823 label=label)
823 label=label)
824 return
824 return
825
825
826 @command('branch',
826 @command('branch',
827 [('f', 'force', None,
827 [('f', 'force', None,
828 _('set branch name even if it shadows an existing branch')),
828 _('set branch name even if it shadows an existing branch')),
829 ('C', 'clean', None, _('reset branch name to parent branch name'))],
829 ('C', 'clean', None, _('reset branch name to parent branch name'))],
830 _('[-fC] [NAME]'))
830 _('[-fC] [NAME]'))
831 def branch(ui, repo, label=None, **opts):
831 def branch(ui, repo, label=None, **opts):
832 """set or show the current branch name
832 """set or show the current branch name
833
833
834 .. note::
834 .. note::
835 Branch names are permanent and global. Use :hg:`bookmark` to create a
835 Branch names are permanent and global. Use :hg:`bookmark` to create a
836 light-weight bookmark instead. See :hg:`help glossary` for more
836 light-weight bookmark instead. See :hg:`help glossary` for more
837 information about named branches and bookmarks.
837 information about named branches and bookmarks.
838
838
839 With no argument, show the current branch name. With one argument,
839 With no argument, show the current branch name. With one argument,
840 set the working directory branch name (the branch will not exist
840 set the working directory branch name (the branch will not exist
841 in the repository until the next commit). Standard practice
841 in the repository until the next commit). Standard practice
842 recommends that primary development take place on the 'default'
842 recommends that primary development take place on the 'default'
843 branch.
843 branch.
844
844
845 Unless -f/--force is specified, branch will not let you set a
845 Unless -f/--force is specified, branch will not let you set a
846 branch name that already exists, even if it's inactive.
846 branch name that already exists, even if it's inactive.
847
847
848 Use -C/--clean to reset the working directory branch to that of
848 Use -C/--clean to reset the working directory branch to that of
849 the parent of the working directory, negating a previous branch
849 the parent of the working directory, negating a previous branch
850 change.
850 change.
851
851
852 Use the command :hg:`update` to switch to an existing branch. Use
852 Use the command :hg:`update` to switch to an existing branch. Use
853 :hg:`commit --close-branch` to mark this branch as closed.
853 :hg:`commit --close-branch` to mark this branch as closed.
854
854
855 Returns 0 on success.
855 Returns 0 on success.
856 """
856 """
857
857
858 if opts.get('clean'):
858 if opts.get('clean'):
859 label = repo[None].p1().branch()
859 label = repo[None].p1().branch()
860 repo.dirstate.setbranch(label)
860 repo.dirstate.setbranch(label)
861 ui.status(_('reset working directory to branch %s\n') % label)
861 ui.status(_('reset working directory to branch %s\n') % label)
862 elif label:
862 elif label:
863 if not opts.get('force') and label in repo.branchtags():
863 if not opts.get('force') and label in repo.branchtags():
864 if label not in [p.branch() for p in repo.parents()]:
864 if label not in [p.branch() for p in repo.parents()]:
865 raise util.Abort(_('a branch of the same name already exists'),
865 raise util.Abort(_('a branch of the same name already exists'),
866 # i18n: "it" refers to an existing branch
866 # i18n: "it" refers to an existing branch
867 hint=_("use 'hg update' to switch to it"))
867 hint=_("use 'hg update' to switch to it"))
868 repo.dirstate.setbranch(label)
868 repo.dirstate.setbranch(label)
869 ui.status(_('marked working directory as branch %s\n') % label)
869 ui.status(_('marked working directory as branch %s\n') % label)
870 ui.status(_('(branches are permanent and global, '
870 ui.status(_('(branches are permanent and global, '
871 'did you want a bookmark?)\n'))
871 'did you want a bookmark?)\n'))
872 else:
872 else:
873 ui.write("%s\n" % repo.dirstate.branch())
873 ui.write("%s\n" % repo.dirstate.branch())
874
874
875 @command('branches',
875 @command('branches',
876 [('a', 'active', False, _('show only branches that have unmerged heads')),
876 [('a', 'active', False, _('show only branches that have unmerged heads')),
877 ('c', 'closed', False, _('show normal and closed branches'))],
877 ('c', 'closed', False, _('show normal and closed branches'))],
878 _('[-ac]'))
878 _('[-ac]'))
879 def branches(ui, repo, active=False, closed=False):
879 def branches(ui, repo, active=False, closed=False):
880 """list repository named branches
880 """list repository named branches
881
881
882 List the repository's named branches, indicating which ones are
882 List the repository's named branches, indicating which ones are
883 inactive. If -c/--closed is specified, also list branches which have
883 inactive. If -c/--closed is specified, also list branches which have
884 been marked closed (see :hg:`commit --close-branch`).
884 been marked closed (see :hg:`commit --close-branch`).
885
885
886 If -a/--active is specified, only show active branches. A branch
886 If -a/--active is specified, only show active branches. A branch
887 is considered active if it contains repository heads.
887 is considered active if it contains repository heads.
888
888
889 Use the command :hg:`update` to switch to an existing branch.
889 Use the command :hg:`update` to switch to an existing branch.
890
890
891 Returns 0.
891 Returns 0.
892 """
892 """
893
893
894 hexfunc = ui.debugflag and hex or short
894 hexfunc = ui.debugflag and hex or short
895 activebranches = [repo[n].branch() for n in repo.heads()]
895 activebranches = [repo[n].branch() for n in repo.heads()]
896 def testactive(tag, node):
896 def testactive(tag, node):
897 realhead = tag in activebranches
897 realhead = tag in activebranches
898 open = node in repo.branchheads(tag, closed=False)
898 open = node in repo.branchheads(tag, closed=False)
899 return realhead and open
899 return realhead and open
900 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
900 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
901 for tag, node in repo.branchtags().items()],
901 for tag, node in repo.branchtags().items()],
902 reverse=True)
902 reverse=True)
903
903
904 for isactive, node, tag in branches:
904 for isactive, node, tag in branches:
905 if (not active) or isactive:
905 if (not active) or isactive:
906 if ui.quiet:
906 if ui.quiet:
907 ui.write("%s\n" % tag)
907 ui.write("%s\n" % tag)
908 else:
908 else:
909 hn = repo.lookup(node)
909 hn = repo.lookup(node)
910 if isactive:
910 if isactive:
911 label = 'branches.active'
911 label = 'branches.active'
912 notice = ''
912 notice = ''
913 elif hn not in repo.branchheads(tag, closed=False):
913 elif hn not in repo.branchheads(tag, closed=False):
914 if not closed:
914 if not closed:
915 continue
915 continue
916 label = 'branches.closed'
916 label = 'branches.closed'
917 notice = _(' (closed)')
917 notice = _(' (closed)')
918 else:
918 else:
919 label = 'branches.inactive'
919 label = 'branches.inactive'
920 notice = _(' (inactive)')
920 notice = _(' (inactive)')
921 if tag == repo.dirstate.branch():
921 if tag == repo.dirstate.branch():
922 label = 'branches.current'
922 label = 'branches.current'
923 rev = str(node).rjust(31 - encoding.colwidth(tag))
923 rev = str(node).rjust(31 - encoding.colwidth(tag))
924 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
924 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
925 tag = ui.label(tag, label)
925 tag = ui.label(tag, label)
926 ui.write("%s %s%s\n" % (tag, rev, notice))
926 ui.write("%s %s%s\n" % (tag, rev, notice))
927
927
928 @command('bundle',
928 @command('bundle',
929 [('f', 'force', None, _('run even when the destination is unrelated')),
929 [('f', 'force', None, _('run even when the destination is unrelated')),
930 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
930 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
931 _('REV')),
931 _('REV')),
932 ('b', 'branch', [], _('a specific branch you would like to bundle'),
932 ('b', 'branch', [], _('a specific branch you would like to bundle'),
933 _('BRANCH')),
933 _('BRANCH')),
934 ('', 'base', [],
934 ('', 'base', [],
935 _('a base changeset assumed to be available at the destination'),
935 _('a base changeset assumed to be available at the destination'),
936 _('REV')),
936 _('REV')),
937 ('a', 'all', None, _('bundle all changesets in the repository')),
937 ('a', 'all', None, _('bundle all changesets in the repository')),
938 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
938 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
939 ] + remoteopts,
939 ] + remoteopts,
940 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
940 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
941 def bundle(ui, repo, fname, dest=None, **opts):
941 def bundle(ui, repo, fname, dest=None, **opts):
942 """create a changegroup file
942 """create a changegroup file
943
943
944 Generate a compressed changegroup file collecting changesets not
944 Generate a compressed changegroup file collecting changesets not
945 known to be in another repository.
945 known to be in another repository.
946
946
947 If you omit the destination repository, then hg assumes the
947 If you omit the destination repository, then hg assumes the
948 destination will have all the nodes you specify with --base
948 destination will have all the nodes you specify with --base
949 parameters. To create a bundle containing all changesets, use
949 parameters. To create a bundle containing all changesets, use
950 -a/--all (or --base null).
950 -a/--all (or --base null).
951
951
952 You can change compression method with the -t/--type option.
952 You can change compression method with the -t/--type option.
953 The available compression methods are: none, bzip2, and
953 The available compression methods are: none, bzip2, and
954 gzip (by default, bundles are compressed using bzip2).
954 gzip (by default, bundles are compressed using bzip2).
955
955
956 The bundle file can then be transferred using conventional means
956 The bundle file can then be transferred using conventional means
957 and applied to another repository with the unbundle or pull
957 and applied to another repository with the unbundle or pull
958 command. This is useful when direct push and pull are not
958 command. This is useful when direct push and pull are not
959 available or when exporting an entire repository is undesirable.
959 available or when exporting an entire repository is undesirable.
960
960
961 Applying bundles preserves all changeset contents including
961 Applying bundles preserves all changeset contents including
962 permissions, copy/rename information, and revision history.
962 permissions, copy/rename information, and revision history.
963
963
964 Returns 0 on success, 1 if no changes found.
964 Returns 0 on success, 1 if no changes found.
965 """
965 """
966 revs = None
966 revs = None
967 if 'rev' in opts:
967 if 'rev' in opts:
968 revs = scmutil.revrange(repo, opts['rev'])
968 revs = scmutil.revrange(repo, opts['rev'])
969
969
970 if opts.get('all'):
970 if opts.get('all'):
971 base = ['null']
971 base = ['null']
972 else:
972 else:
973 base = scmutil.revrange(repo, opts.get('base'))
973 base = scmutil.revrange(repo, opts.get('base'))
974 if base:
974 if base:
975 if dest:
975 if dest:
976 raise util.Abort(_("--base is incompatible with specifying "
976 raise util.Abort(_("--base is incompatible with specifying "
977 "a destination"))
977 "a destination"))
978 common = [repo.lookup(rev) for rev in base]
978 common = [repo.lookup(rev) for rev in base]
979 heads = revs and map(repo.lookup, revs) or revs
979 heads = revs and map(repo.lookup, revs) or revs
980 cg = repo.getbundle('bundle', heads=heads, common=common)
980 cg = repo.getbundle('bundle', heads=heads, common=common)
981 else:
981 else:
982 dest = ui.expandpath(dest or 'default-push', dest or 'default')
982 dest = ui.expandpath(dest or 'default-push', dest or 'default')
983 dest, branches = hg.parseurl(dest, opts.get('branch'))
983 dest, branches = hg.parseurl(dest, opts.get('branch'))
984 other = hg.peer(repo, opts, dest)
984 other = hg.peer(repo, opts, dest)
985 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
985 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
986 heads = revs and map(repo.lookup, revs) or revs
986 heads = revs and map(repo.lookup, revs) or revs
987 outgoing = discovery.findcommonoutgoing(repo, other,
987 outgoing = discovery.findcommonoutgoing(repo, other,
988 onlyheads=heads,
988 onlyheads=heads,
989 force=opts.get('force'))
989 force=opts.get('force'))
990 cg = repo.getlocalbundle('bundle', outgoing)
990 cg = repo.getlocalbundle('bundle', outgoing)
991 if not cg:
991 if not cg:
992 ui.status(_("no changes found\n"))
992 ui.status(_("no changes found\n"))
993 return 1
993 return 1
994
994
995 bundletype = opts.get('type', 'bzip2').lower()
995 bundletype = opts.get('type', 'bzip2').lower()
996 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
996 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
997 bundletype = btypes.get(bundletype)
997 bundletype = btypes.get(bundletype)
998 if bundletype not in changegroup.bundletypes:
998 if bundletype not in changegroup.bundletypes:
999 raise util.Abort(_('unknown bundle type specified with --type'))
999 raise util.Abort(_('unknown bundle type specified with --type'))
1000
1000
1001 changegroup.writebundle(cg, fname, bundletype)
1001 changegroup.writebundle(cg, fname, bundletype)
1002
1002
1003 @command('cat',
1003 @command('cat',
1004 [('o', 'output', '',
1004 [('o', 'output', '',
1005 _('print output to file with formatted name'), _('FORMAT')),
1005 _('print output to file with formatted name'), _('FORMAT')),
1006 ('r', 'rev', '', _('print the given revision'), _('REV')),
1006 ('r', 'rev', '', _('print the given revision'), _('REV')),
1007 ('', 'decode', None, _('apply any matching decode filter')),
1007 ('', 'decode', None, _('apply any matching decode filter')),
1008 ] + walkopts,
1008 ] + walkopts,
1009 _('[OPTION]... FILE...'))
1009 _('[OPTION]... FILE...'))
1010 def cat(ui, repo, file1, *pats, **opts):
1010 def cat(ui, repo, file1, *pats, **opts):
1011 """output the current or given revision of files
1011 """output the current or given revision of files
1012
1012
1013 Print the specified files as they were at the given revision. If
1013 Print the specified files as they were at the given revision. If
1014 no revision is given, the parent of the working directory is used,
1014 no revision is given, the parent of the working directory is used,
1015 or tip if no revision is checked out.
1015 or tip if no revision is checked out.
1016
1016
1017 Output may be to a file, in which case the name of the file is
1017 Output may be to a file, in which case the name of the file is
1018 given using a format string. The formatting rules are the same as
1018 given using a format string. The formatting rules are the same as
1019 for the export command, with the following additions:
1019 for the export command, with the following additions:
1020
1020
1021 :``%s``: basename of file being printed
1021 :``%s``: basename of file being printed
1022 :``%d``: dirname of file being printed, or '.' if in repository root
1022 :``%d``: dirname of file being printed, or '.' if in repository root
1023 :``%p``: root-relative path name of file being printed
1023 :``%p``: root-relative path name of file being printed
1024
1024
1025 Returns 0 on success.
1025 Returns 0 on success.
1026 """
1026 """
1027 ctx = scmutil.revsingle(repo, opts.get('rev'))
1027 ctx = scmutil.revsingle(repo, opts.get('rev'))
1028 err = 1
1028 err = 1
1029 m = scmutil.match(ctx, (file1,) + pats, opts)
1029 m = scmutil.match(ctx, (file1,) + pats, opts)
1030 for abs in ctx.walk(m):
1030 for abs in ctx.walk(m):
1031 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1031 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1032 pathname=abs)
1032 pathname=abs)
1033 data = ctx[abs].data()
1033 data = ctx[abs].data()
1034 if opts.get('decode'):
1034 if opts.get('decode'):
1035 data = repo.wwritedata(abs, data)
1035 data = repo.wwritedata(abs, data)
1036 fp.write(data)
1036 fp.write(data)
1037 fp.close()
1037 fp.close()
1038 err = 0
1038 err = 0
1039 return err
1039 return err
1040
1040
1041 @command('^clone',
1041 @command('^clone',
1042 [('U', 'noupdate', None,
1042 [('U', 'noupdate', None,
1043 _('the clone will include an empty working copy (only a repository)')),
1043 _('the clone will include an empty working copy (only a repository)')),
1044 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1044 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1045 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1045 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1046 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1046 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1047 ('', 'pull', None, _('use pull protocol to copy metadata')),
1047 ('', 'pull', None, _('use pull protocol to copy metadata')),
1048 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1048 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1049 ] + remoteopts,
1049 ] + remoteopts,
1050 _('[OPTION]... SOURCE [DEST]'))
1050 _('[OPTION]... SOURCE [DEST]'))
1051 def clone(ui, source, dest=None, **opts):
1051 def clone(ui, source, dest=None, **opts):
1052 """make a copy of an existing repository
1052 """make a copy of an existing repository
1053
1053
1054 Create a copy of an existing repository in a new directory.
1054 Create a copy of an existing repository in a new directory.
1055
1055
1056 If no destination directory name is specified, it defaults to the
1056 If no destination directory name is specified, it defaults to the
1057 basename of the source.
1057 basename of the source.
1058
1058
1059 The location of the source is added to the new repository's
1059 The location of the source is added to the new repository's
1060 ``.hg/hgrc`` file, as the default to be used for future pulls.
1060 ``.hg/hgrc`` file, as the default to be used for future pulls.
1061
1061
1062 Only local paths and ``ssh://`` URLs are supported as
1062 Only local paths and ``ssh://`` URLs are supported as
1063 destinations. For ``ssh://`` destinations, no working directory or
1063 destinations. For ``ssh://`` destinations, no working directory or
1064 ``.hg/hgrc`` will be created on the remote side.
1064 ``.hg/hgrc`` will be created on the remote side.
1065
1065
1066 To pull only a subset of changesets, specify one or more revisions
1066 To pull only a subset of changesets, specify one or more revisions
1067 identifiers with -r/--rev or branches with -b/--branch. The
1067 identifiers with -r/--rev or branches with -b/--branch. The
1068 resulting clone will contain only the specified changesets and
1068 resulting clone will contain only the specified changesets and
1069 their ancestors. These options (or 'clone src#rev dest') imply
1069 their ancestors. These options (or 'clone src#rev dest') imply
1070 --pull, even for local source repositories. Note that specifying a
1070 --pull, even for local source repositories. Note that specifying a
1071 tag will include the tagged changeset but not the changeset
1071 tag will include the tagged changeset but not the changeset
1072 containing the tag.
1072 containing the tag.
1073
1073
1074 To check out a particular version, use -u/--update, or
1074 To check out a particular version, use -u/--update, or
1075 -U/--noupdate to create a clone with no working directory.
1075 -U/--noupdate to create a clone with no working directory.
1076
1076
1077 .. container:: verbose
1077 .. container:: verbose
1078
1078
1079 For efficiency, hardlinks are used for cloning whenever the
1079 For efficiency, hardlinks are used for cloning whenever the
1080 source and destination are on the same filesystem (note this
1080 source and destination are on the same filesystem (note this
1081 applies only to the repository data, not to the working
1081 applies only to the repository data, not to the working
1082 directory). Some filesystems, such as AFS, implement hardlinking
1082 directory). Some filesystems, such as AFS, implement hardlinking
1083 incorrectly, but do not report errors. In these cases, use the
1083 incorrectly, but do not report errors. In these cases, use the
1084 --pull option to avoid hardlinking.
1084 --pull option to avoid hardlinking.
1085
1085
1086 In some cases, you can clone repositories and the working
1086 In some cases, you can clone repositories and the working
1087 directory using full hardlinks with ::
1087 directory using full hardlinks with ::
1088
1088
1089 $ cp -al REPO REPOCLONE
1089 $ cp -al REPO REPOCLONE
1090
1090
1091 This is the fastest way to clone, but it is not always safe. The
1091 This is the fastest way to clone, but it is not always safe. The
1092 operation is not atomic (making sure REPO is not modified during
1092 operation is not atomic (making sure REPO is not modified during
1093 the operation is up to you) and you have to make sure your
1093 the operation is up to you) and you have to make sure your
1094 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1094 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1095 so). Also, this is not compatible with certain extensions that
1095 so). Also, this is not compatible with certain extensions that
1096 place their metadata under the .hg directory, such as mq.
1096 place their metadata under the .hg directory, such as mq.
1097
1097
1098 Mercurial will update the working directory to the first applicable
1098 Mercurial will update the working directory to the first applicable
1099 revision from this list:
1099 revision from this list:
1100
1100
1101 a) null if -U or the source repository has no changesets
1101 a) null if -U or the source repository has no changesets
1102 b) if -u . and the source repository is local, the first parent of
1102 b) if -u . and the source repository is local, the first parent of
1103 the source repository's working directory
1103 the source repository's working directory
1104 c) the changeset specified with -u (if a branch name, this means the
1104 c) the changeset specified with -u (if a branch name, this means the
1105 latest head of that branch)
1105 latest head of that branch)
1106 d) the changeset specified with -r
1106 d) the changeset specified with -r
1107 e) the tipmost head specified with -b
1107 e) the tipmost head specified with -b
1108 f) the tipmost head specified with the url#branch source syntax
1108 f) the tipmost head specified with the url#branch source syntax
1109 g) the tipmost head of the default branch
1109 g) the tipmost head of the default branch
1110 h) tip
1110 h) tip
1111
1111
1112 Examples:
1112 Examples:
1113
1113
1114 - clone a remote repository to a new directory named hg/::
1114 - clone a remote repository to a new directory named hg/::
1115
1115
1116 hg clone http://selenic.com/hg
1116 hg clone http://selenic.com/hg
1117
1117
1118 - create a lightweight local clone::
1118 - create a lightweight local clone::
1119
1119
1120 hg clone project/ project-feature/
1120 hg clone project/ project-feature/
1121
1121
1122 - clone from an absolute path on an ssh server (note double-slash)::
1122 - clone from an absolute path on an ssh server (note double-slash)::
1123
1123
1124 hg clone ssh://user@server//home/projects/alpha/
1124 hg clone ssh://user@server//home/projects/alpha/
1125
1125
1126 - do a high-speed clone over a LAN while checking out a
1126 - do a high-speed clone over a LAN while checking out a
1127 specified version::
1127 specified version::
1128
1128
1129 hg clone --uncompressed http://server/repo -u 1.5
1129 hg clone --uncompressed http://server/repo -u 1.5
1130
1130
1131 - create a repository without changesets after a particular revision::
1131 - create a repository without changesets after a particular revision::
1132
1132
1133 hg clone -r 04e544 experimental/ good/
1133 hg clone -r 04e544 experimental/ good/
1134
1134
1135 - clone (and track) a particular named branch::
1135 - clone (and track) a particular named branch::
1136
1136
1137 hg clone http://selenic.com/hg#stable
1137 hg clone http://selenic.com/hg#stable
1138
1138
1139 See :hg:`help urls` for details on specifying URLs.
1139 See :hg:`help urls` for details on specifying URLs.
1140
1140
1141 Returns 0 on success.
1141 Returns 0 on success.
1142 """
1142 """
1143 if opts.get('noupdate') and opts.get('updaterev'):
1143 if opts.get('noupdate') and opts.get('updaterev'):
1144 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1144 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1145
1145
1146 r = hg.clone(ui, opts, source, dest,
1146 r = hg.clone(ui, opts, source, dest,
1147 pull=opts.get('pull'),
1147 pull=opts.get('pull'),
1148 stream=opts.get('uncompressed'),
1148 stream=opts.get('uncompressed'),
1149 rev=opts.get('rev'),
1149 rev=opts.get('rev'),
1150 update=opts.get('updaterev') or not opts.get('noupdate'),
1150 update=opts.get('updaterev') or not opts.get('noupdate'),
1151 branch=opts.get('branch'))
1151 branch=opts.get('branch'))
1152
1152
1153 return r is None
1153 return r is None
1154
1154
1155 @command('^commit|ci',
1155 @command('^commit|ci',
1156 [('A', 'addremove', None,
1156 [('A', 'addremove', None,
1157 _('mark new/missing files as added/removed before committing')),
1157 _('mark new/missing files as added/removed before committing')),
1158 ('', 'close-branch', None,
1158 ('', 'close-branch', None,
1159 _('mark a branch as closed, hiding it from the branch list')),
1159 _('mark a branch as closed, hiding it from the branch list')),
1160 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1160 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1161 _('[OPTION]... [FILE]...'))
1161 _('[OPTION]... [FILE]...'))
1162 def commit(ui, repo, *pats, **opts):
1162 def commit(ui, repo, *pats, **opts):
1163 """commit the specified files or all outstanding changes
1163 """commit the specified files or all outstanding changes
1164
1164
1165 Commit changes to the given files into the repository. Unlike a
1165 Commit changes to the given files into the repository. Unlike a
1166 centralized SCM, this operation is a local operation. See
1166 centralized SCM, this operation is a local operation. See
1167 :hg:`push` for a way to actively distribute your changes.
1167 :hg:`push` for a way to actively distribute your changes.
1168
1168
1169 If a list of files is omitted, all changes reported by :hg:`status`
1169 If a list of files is omitted, all changes reported by :hg:`status`
1170 will be committed.
1170 will be committed.
1171
1171
1172 If you are committing the result of a merge, do not provide any
1172 If you are committing the result of a merge, do not provide any
1173 filenames or -I/-X filters.
1173 filenames or -I/-X filters.
1174
1174
1175 If no commit message is specified, Mercurial starts your
1175 If no commit message is specified, Mercurial starts your
1176 configured editor where you can enter a message. In case your
1176 configured editor where you can enter a message. In case your
1177 commit fails, you will find a backup of your message in
1177 commit fails, you will find a backup of your message in
1178 ``.hg/last-message.txt``.
1178 ``.hg/last-message.txt``.
1179
1179
1180 See :hg:`help dates` for a list of formats valid for -d/--date.
1180 See :hg:`help dates` for a list of formats valid for -d/--date.
1181
1181
1182 Returns 0 on success, 1 if nothing changed.
1182 Returns 0 on success, 1 if nothing changed.
1183 """
1183 """
1184 if opts.get('subrepos'):
1184 if opts.get('subrepos'):
1185 # Let --subrepos on the command line overide config setting.
1185 # Let --subrepos on the command line overide config setting.
1186 ui.setconfig('ui', 'commitsubrepos', True)
1186 ui.setconfig('ui', 'commitsubrepos', True)
1187
1187
1188 extra = {}
1188 extra = {}
1189 if opts.get('close_branch'):
1189 if opts.get('close_branch'):
1190 if repo['.'].node() not in repo.branchheads():
1190 if repo['.'].node() not in repo.branchheads():
1191 # The topo heads set is included in the branch heads set of the
1191 # The topo heads set is included in the branch heads set of the
1192 # current branch, so it's sufficient to test branchheads
1192 # current branch, so it's sufficient to test branchheads
1193 raise util.Abort(_('can only close branch heads'))
1193 raise util.Abort(_('can only close branch heads'))
1194 extra['close'] = 1
1194 extra['close'] = 1
1195 e = cmdutil.commiteditor
1195 e = cmdutil.commiteditor
1196 if opts.get('force_editor'):
1196 if opts.get('force_editor'):
1197 e = cmdutil.commitforceeditor
1197 e = cmdutil.commitforceeditor
1198
1198
1199 def commitfunc(ui, repo, message, match, opts):
1199 def commitfunc(ui, repo, message, match, opts):
1200 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1200 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1201 editor=e, extra=extra)
1201 editor=e, extra=extra)
1202
1202
1203 branch = repo[None].branch()
1203 branch = repo[None].branch()
1204 bheads = repo.branchheads(branch)
1204 bheads = repo.branchheads(branch)
1205
1205
1206 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1206 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1207 if not node:
1207 if not node:
1208 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1208 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1209 if stat[3]:
1209 if stat[3]:
1210 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1210 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1211 % len(stat[3]))
1211 % len(stat[3]))
1212 else:
1212 else:
1213 ui.status(_("nothing changed\n"))
1213 ui.status(_("nothing changed\n"))
1214 return 1
1214 return 1
1215
1215
1216 ctx = repo[node]
1216 ctx = repo[node]
1217 parents = ctx.parents()
1217 parents = ctx.parents()
1218
1218
1219 if (bheads and node not in bheads and not
1219 if (bheads and node not in bheads and not
1220 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1220 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1221 ui.status(_('created new head\n'))
1221 ui.status(_('created new head\n'))
1222 # The message is not printed for initial roots. For the other
1222 # The message is not printed for initial roots. For the other
1223 # changesets, it is printed in the following situations:
1223 # changesets, it is printed in the following situations:
1224 #
1224 #
1225 # Par column: for the 2 parents with ...
1225 # Par column: for the 2 parents with ...
1226 # N: null or no parent
1226 # N: null or no parent
1227 # B: parent is on another named branch
1227 # B: parent is on another named branch
1228 # C: parent is a regular non head changeset
1228 # C: parent is a regular non head changeset
1229 # H: parent was a branch head of the current branch
1229 # H: parent was a branch head of the current branch
1230 # Msg column: whether we print "created new head" message
1230 # Msg column: whether we print "created new head" message
1231 # In the following, it is assumed that there already exists some
1231 # In the following, it is assumed that there already exists some
1232 # initial branch heads of the current branch, otherwise nothing is
1232 # initial branch heads of the current branch, otherwise nothing is
1233 # printed anyway.
1233 # printed anyway.
1234 #
1234 #
1235 # Par Msg Comment
1235 # Par Msg Comment
1236 # NN y additional topo root
1236 # NN y additional topo root
1237 #
1237 #
1238 # BN y additional branch root
1238 # BN y additional branch root
1239 # CN y additional topo head
1239 # CN y additional topo head
1240 # HN n usual case
1240 # HN n usual case
1241 #
1241 #
1242 # BB y weird additional branch root
1242 # BB y weird additional branch root
1243 # CB y branch merge
1243 # CB y branch merge
1244 # HB n merge with named branch
1244 # HB n merge with named branch
1245 #
1245 #
1246 # CC y additional head from merge
1246 # CC y additional head from merge
1247 # CH n merge with a head
1247 # CH n merge with a head
1248 #
1248 #
1249 # HH n head merge: head count decreases
1249 # HH n head merge: head count decreases
1250
1250
1251 if not opts.get('close_branch'):
1251 if not opts.get('close_branch'):
1252 for r in parents:
1252 for r in parents:
1253 if r.extra().get('close') and r.branch() == branch:
1253 if r.extra().get('close') and r.branch() == branch:
1254 ui.status(_('reopening closed branch head %d\n') % r)
1254 ui.status(_('reopening closed branch head %d\n') % r)
1255
1255
1256 if ui.debugflag:
1256 if ui.debugflag:
1257 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1257 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1258 elif ui.verbose:
1258 elif ui.verbose:
1259 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1259 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1260
1260
1261 @command('copy|cp',
1261 @command('copy|cp',
1262 [('A', 'after', None, _('record a copy that has already occurred')),
1262 [('A', 'after', None, _('record a copy that has already occurred')),
1263 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1263 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1264 ] + walkopts + dryrunopts,
1264 ] + walkopts + dryrunopts,
1265 _('[OPTION]... [SOURCE]... DEST'))
1265 _('[OPTION]... [SOURCE]... DEST'))
1266 def copy(ui, repo, *pats, **opts):
1266 def copy(ui, repo, *pats, **opts):
1267 """mark files as copied for the next commit
1267 """mark files as copied for the next commit
1268
1268
1269 Mark dest as having copies of source files. If dest is a
1269 Mark dest as having copies of source files. If dest is a
1270 directory, copies are put in that directory. If dest is a file,
1270 directory, copies are put in that directory. If dest is a file,
1271 the source must be a single file.
1271 the source must be a single file.
1272
1272
1273 By default, this command copies the contents of files as they
1273 By default, this command copies the contents of files as they
1274 exist in the working directory. If invoked with -A/--after, the
1274 exist in the working directory. If invoked with -A/--after, the
1275 operation is recorded, but no copying is performed.
1275 operation is recorded, but no copying is performed.
1276
1276
1277 This command takes effect with the next commit. To undo a copy
1277 This command takes effect with the next commit. To undo a copy
1278 before that, see :hg:`revert`.
1278 before that, see :hg:`revert`.
1279
1279
1280 Returns 0 on success, 1 if errors are encountered.
1280 Returns 0 on success, 1 if errors are encountered.
1281 """
1281 """
1282 wlock = repo.wlock(False)
1282 wlock = repo.wlock(False)
1283 try:
1283 try:
1284 return cmdutil.copy(ui, repo, pats, opts)
1284 return cmdutil.copy(ui, repo, pats, opts)
1285 finally:
1285 finally:
1286 wlock.release()
1286 wlock.release()
1287
1287
1288 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1288 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1289 def debugancestor(ui, repo, *args):
1289 def debugancestor(ui, repo, *args):
1290 """find the ancestor revision of two revisions in a given index"""
1290 """find the ancestor revision of two revisions in a given index"""
1291 if len(args) == 3:
1291 if len(args) == 3:
1292 index, rev1, rev2 = args
1292 index, rev1, rev2 = args
1293 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1293 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1294 lookup = r.lookup
1294 lookup = r.lookup
1295 elif len(args) == 2:
1295 elif len(args) == 2:
1296 if not repo:
1296 if not repo:
1297 raise util.Abort(_("there is no Mercurial repository here "
1297 raise util.Abort(_("there is no Mercurial repository here "
1298 "(.hg not found)"))
1298 "(.hg not found)"))
1299 rev1, rev2 = args
1299 rev1, rev2 = args
1300 r = repo.changelog
1300 r = repo.changelog
1301 lookup = repo.lookup
1301 lookup = repo.lookup
1302 else:
1302 else:
1303 raise util.Abort(_('either two or three arguments required'))
1303 raise util.Abort(_('either two or three arguments required'))
1304 a = r.ancestor(lookup(rev1), lookup(rev2))
1304 a = r.ancestor(lookup(rev1), lookup(rev2))
1305 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1305 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1306
1306
1307 @command('debugbuilddag',
1307 @command('debugbuilddag',
1308 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1308 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1309 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1309 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1310 ('n', 'new-file', None, _('add new file at each rev'))],
1310 ('n', 'new-file', None, _('add new file at each rev'))],
1311 _('[OPTION]... [TEXT]'))
1311 _('[OPTION]... [TEXT]'))
1312 def debugbuilddag(ui, repo, text=None,
1312 def debugbuilddag(ui, repo, text=None,
1313 mergeable_file=False,
1313 mergeable_file=False,
1314 overwritten_file=False,
1314 overwritten_file=False,
1315 new_file=False):
1315 new_file=False):
1316 """builds a repo with a given DAG from scratch in the current empty repo
1316 """builds a repo with a given DAG from scratch in the current empty repo
1317
1317
1318 The description of the DAG is read from stdin if not given on the
1318 The description of the DAG is read from stdin if not given on the
1319 command line.
1319 command line.
1320
1320
1321 Elements:
1321 Elements:
1322
1322
1323 - "+n" is a linear run of n nodes based on the current default parent
1323 - "+n" is a linear run of n nodes based on the current default parent
1324 - "." is a single node based on the current default parent
1324 - "." is a single node based on the current default parent
1325 - "$" resets the default parent to null (implied at the start);
1325 - "$" resets the default parent to null (implied at the start);
1326 otherwise the default parent is always the last node created
1326 otherwise the default parent is always the last node created
1327 - "<p" sets the default parent to the backref p
1327 - "<p" sets the default parent to the backref p
1328 - "*p" is a fork at parent p, which is a backref
1328 - "*p" is a fork at parent p, which is a backref
1329 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1329 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1330 - "/p2" is a merge of the preceding node and p2
1330 - "/p2" is a merge of the preceding node and p2
1331 - ":tag" defines a local tag for the preceding node
1331 - ":tag" defines a local tag for the preceding node
1332 - "@branch" sets the named branch for subsequent nodes
1332 - "@branch" sets the named branch for subsequent nodes
1333 - "#...\\n" is a comment up to the end of the line
1333 - "#...\\n" is a comment up to the end of the line
1334
1334
1335 Whitespace between the above elements is ignored.
1335 Whitespace between the above elements is ignored.
1336
1336
1337 A backref is either
1337 A backref is either
1338
1338
1339 - a number n, which references the node curr-n, where curr is the current
1339 - a number n, which references the node curr-n, where curr is the current
1340 node, or
1340 node, or
1341 - the name of a local tag you placed earlier using ":tag", or
1341 - the name of a local tag you placed earlier using ":tag", or
1342 - empty to denote the default parent.
1342 - empty to denote the default parent.
1343
1343
1344 All string valued-elements are either strictly alphanumeric, or must
1344 All string valued-elements are either strictly alphanumeric, or must
1345 be enclosed in double quotes ("..."), with "\\" as escape character.
1345 be enclosed in double quotes ("..."), with "\\" as escape character.
1346 """
1346 """
1347
1347
1348 if text is None:
1348 if text is None:
1349 ui.status(_("reading DAG from stdin\n"))
1349 ui.status(_("reading DAG from stdin\n"))
1350 text = ui.fin.read()
1350 text = ui.fin.read()
1351
1351
1352 cl = repo.changelog
1352 cl = repo.changelog
1353 if len(cl) > 0:
1353 if len(cl) > 0:
1354 raise util.Abort(_('repository is not empty'))
1354 raise util.Abort(_('repository is not empty'))
1355
1355
1356 # determine number of revs in DAG
1356 # determine number of revs in DAG
1357 total = 0
1357 total = 0
1358 for type, data in dagparser.parsedag(text):
1358 for type, data in dagparser.parsedag(text):
1359 if type == 'n':
1359 if type == 'n':
1360 total += 1
1360 total += 1
1361
1361
1362 if mergeable_file:
1362 if mergeable_file:
1363 linesperrev = 2
1363 linesperrev = 2
1364 # make a file with k lines per rev
1364 # make a file with k lines per rev
1365 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1365 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1366 initialmergedlines.append("")
1366 initialmergedlines.append("")
1367
1367
1368 tags = []
1368 tags = []
1369
1369
1370 lock = tr = None
1370 lock = tr = None
1371 try:
1371 try:
1372 lock = repo.lock()
1372 lock = repo.lock()
1373 tr = repo.transaction("builddag")
1373 tr = repo.transaction("builddag")
1374
1374
1375 at = -1
1375 at = -1
1376 atbranch = 'default'
1376 atbranch = 'default'
1377 nodeids = []
1377 nodeids = []
1378 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1378 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1379 for type, data in dagparser.parsedag(text):
1379 for type, data in dagparser.parsedag(text):
1380 if type == 'n':
1380 if type == 'n':
1381 ui.note('node %s\n' % str(data))
1381 ui.note('node %s\n' % str(data))
1382 id, ps = data
1382 id, ps = data
1383
1383
1384 files = []
1384 files = []
1385 fctxs = {}
1385 fctxs = {}
1386
1386
1387 p2 = None
1387 p2 = None
1388 if mergeable_file:
1388 if mergeable_file:
1389 fn = "mf"
1389 fn = "mf"
1390 p1 = repo[ps[0]]
1390 p1 = repo[ps[0]]
1391 if len(ps) > 1:
1391 if len(ps) > 1:
1392 p2 = repo[ps[1]]
1392 p2 = repo[ps[1]]
1393 pa = p1.ancestor(p2)
1393 pa = p1.ancestor(p2)
1394 base, local, other = [x[fn].data() for x in pa, p1, p2]
1394 base, local, other = [x[fn].data() for x in pa, p1, p2]
1395 m3 = simplemerge.Merge3Text(base, local, other)
1395 m3 = simplemerge.Merge3Text(base, local, other)
1396 ml = [l.strip() for l in m3.merge_lines()]
1396 ml = [l.strip() for l in m3.merge_lines()]
1397 ml.append("")
1397 ml.append("")
1398 elif at > 0:
1398 elif at > 0:
1399 ml = p1[fn].data().split("\n")
1399 ml = p1[fn].data().split("\n")
1400 else:
1400 else:
1401 ml = initialmergedlines
1401 ml = initialmergedlines
1402 ml[id * linesperrev] += " r%i" % id
1402 ml[id * linesperrev] += " r%i" % id
1403 mergedtext = "\n".join(ml)
1403 mergedtext = "\n".join(ml)
1404 files.append(fn)
1404 files.append(fn)
1405 fctxs[fn] = context.memfilectx(fn, mergedtext)
1405 fctxs[fn] = context.memfilectx(fn, mergedtext)
1406
1406
1407 if overwritten_file:
1407 if overwritten_file:
1408 fn = "of"
1408 fn = "of"
1409 files.append(fn)
1409 files.append(fn)
1410 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1410 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1411
1411
1412 if new_file:
1412 if new_file:
1413 fn = "nf%i" % id
1413 fn = "nf%i" % id
1414 files.append(fn)
1414 files.append(fn)
1415 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1415 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1416 if len(ps) > 1:
1416 if len(ps) > 1:
1417 if not p2:
1417 if not p2:
1418 p2 = repo[ps[1]]
1418 p2 = repo[ps[1]]
1419 for fn in p2:
1419 for fn in p2:
1420 if fn.startswith("nf"):
1420 if fn.startswith("nf"):
1421 files.append(fn)
1421 files.append(fn)
1422 fctxs[fn] = p2[fn]
1422 fctxs[fn] = p2[fn]
1423
1423
1424 def fctxfn(repo, cx, path):
1424 def fctxfn(repo, cx, path):
1425 return fctxs.get(path)
1425 return fctxs.get(path)
1426
1426
1427 if len(ps) == 0 or ps[0] < 0:
1427 if len(ps) == 0 or ps[0] < 0:
1428 pars = [None, None]
1428 pars = [None, None]
1429 elif len(ps) == 1:
1429 elif len(ps) == 1:
1430 pars = [nodeids[ps[0]], None]
1430 pars = [nodeids[ps[0]], None]
1431 else:
1431 else:
1432 pars = [nodeids[p] for p in ps]
1432 pars = [nodeids[p] for p in ps]
1433 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1433 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1434 date=(id, 0),
1434 date=(id, 0),
1435 user="debugbuilddag",
1435 user="debugbuilddag",
1436 extra={'branch': atbranch})
1436 extra={'branch': atbranch})
1437 nodeid = repo.commitctx(cx)
1437 nodeid = repo.commitctx(cx)
1438 nodeids.append(nodeid)
1438 nodeids.append(nodeid)
1439 at = id
1439 at = id
1440 elif type == 'l':
1440 elif type == 'l':
1441 id, name = data
1441 id, name = data
1442 ui.note('tag %s\n' % name)
1442 ui.note('tag %s\n' % name)
1443 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1443 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1444 elif type == 'a':
1444 elif type == 'a':
1445 ui.note('branch %s\n' % data)
1445 ui.note('branch %s\n' % data)
1446 atbranch = data
1446 atbranch = data
1447 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1447 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1448 tr.close()
1448 tr.close()
1449
1449
1450 if tags:
1450 if tags:
1451 repo.opener.write("localtags", "".join(tags))
1451 repo.opener.write("localtags", "".join(tags))
1452 finally:
1452 finally:
1453 ui.progress(_('building'), None)
1453 ui.progress(_('building'), None)
1454 release(tr, lock)
1454 release(tr, lock)
1455
1455
1456 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1456 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1457 def debugbundle(ui, bundlepath, all=None, **opts):
1457 def debugbundle(ui, bundlepath, all=None, **opts):
1458 """lists the contents of a bundle"""
1458 """lists the contents of a bundle"""
1459 f = url.open(ui, bundlepath)
1459 f = url.open(ui, bundlepath)
1460 try:
1460 try:
1461 gen = changegroup.readbundle(f, bundlepath)
1461 gen = changegroup.readbundle(f, bundlepath)
1462 if all:
1462 if all:
1463 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1463 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1464
1464
1465 def showchunks(named):
1465 def showchunks(named):
1466 ui.write("\n%s\n" % named)
1466 ui.write("\n%s\n" % named)
1467 chain = None
1467 chain = None
1468 while True:
1468 while True:
1469 chunkdata = gen.deltachunk(chain)
1469 chunkdata = gen.deltachunk(chain)
1470 if not chunkdata:
1470 if not chunkdata:
1471 break
1471 break
1472 node = chunkdata['node']
1472 node = chunkdata['node']
1473 p1 = chunkdata['p1']
1473 p1 = chunkdata['p1']
1474 p2 = chunkdata['p2']
1474 p2 = chunkdata['p2']
1475 cs = chunkdata['cs']
1475 cs = chunkdata['cs']
1476 deltabase = chunkdata['deltabase']
1476 deltabase = chunkdata['deltabase']
1477 delta = chunkdata['delta']
1477 delta = chunkdata['delta']
1478 ui.write("%s %s %s %s %s %s\n" %
1478 ui.write("%s %s %s %s %s %s\n" %
1479 (hex(node), hex(p1), hex(p2),
1479 (hex(node), hex(p1), hex(p2),
1480 hex(cs), hex(deltabase), len(delta)))
1480 hex(cs), hex(deltabase), len(delta)))
1481 chain = node
1481 chain = node
1482
1482
1483 chunkdata = gen.changelogheader()
1483 chunkdata = gen.changelogheader()
1484 showchunks("changelog")
1484 showchunks("changelog")
1485 chunkdata = gen.manifestheader()
1485 chunkdata = gen.manifestheader()
1486 showchunks("manifest")
1486 showchunks("manifest")
1487 while True:
1487 while True:
1488 chunkdata = gen.filelogheader()
1488 chunkdata = gen.filelogheader()
1489 if not chunkdata:
1489 if not chunkdata:
1490 break
1490 break
1491 fname = chunkdata['filename']
1491 fname = chunkdata['filename']
1492 showchunks(fname)
1492 showchunks(fname)
1493 else:
1493 else:
1494 chunkdata = gen.changelogheader()
1494 chunkdata = gen.changelogheader()
1495 chain = None
1495 chain = None
1496 while True:
1496 while True:
1497 chunkdata = gen.deltachunk(chain)
1497 chunkdata = gen.deltachunk(chain)
1498 if not chunkdata:
1498 if not chunkdata:
1499 break
1499 break
1500 node = chunkdata['node']
1500 node = chunkdata['node']
1501 ui.write("%s\n" % hex(node))
1501 ui.write("%s\n" % hex(node))
1502 chain = node
1502 chain = node
1503 finally:
1503 finally:
1504 f.close()
1504 f.close()
1505
1505
1506 @command('debugcheckstate', [], '')
1506 @command('debugcheckstate', [], '')
1507 def debugcheckstate(ui, repo):
1507 def debugcheckstate(ui, repo):
1508 """validate the correctness of the current dirstate"""
1508 """validate the correctness of the current dirstate"""
1509 parent1, parent2 = repo.dirstate.parents()
1509 parent1, parent2 = repo.dirstate.parents()
1510 m1 = repo[parent1].manifest()
1510 m1 = repo[parent1].manifest()
1511 m2 = repo[parent2].manifest()
1511 m2 = repo[parent2].manifest()
1512 errors = 0
1512 errors = 0
1513 for f in repo.dirstate:
1513 for f in repo.dirstate:
1514 state = repo.dirstate[f]
1514 state = repo.dirstate[f]
1515 if state in "nr" and f not in m1:
1515 if state in "nr" and f not in m1:
1516 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1516 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1517 errors += 1
1517 errors += 1
1518 if state in "a" and f in m1:
1518 if state in "a" and f in m1:
1519 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1519 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1520 errors += 1
1520 errors += 1
1521 if state in "m" and f not in m1 and f not in m2:
1521 if state in "m" and f not in m1 and f not in m2:
1522 ui.warn(_("%s in state %s, but not in either manifest\n") %
1522 ui.warn(_("%s in state %s, but not in either manifest\n") %
1523 (f, state))
1523 (f, state))
1524 errors += 1
1524 errors += 1
1525 for f in m1:
1525 for f in m1:
1526 state = repo.dirstate[f]
1526 state = repo.dirstate[f]
1527 if state not in "nrm":
1527 if state not in "nrm":
1528 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1528 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1529 errors += 1
1529 errors += 1
1530 if errors:
1530 if errors:
1531 error = _(".hg/dirstate inconsistent with current parent's manifest")
1531 error = _(".hg/dirstate inconsistent with current parent's manifest")
1532 raise util.Abort(error)
1532 raise util.Abort(error)
1533
1533
1534 @command('debugcommands', [], _('[COMMAND]'))
1534 @command('debugcommands', [], _('[COMMAND]'))
1535 def debugcommands(ui, cmd='', *args):
1535 def debugcommands(ui, cmd='', *args):
1536 """list all available commands and options"""
1536 """list all available commands and options"""
1537 for cmd, vals in sorted(table.iteritems()):
1537 for cmd, vals in sorted(table.iteritems()):
1538 cmd = cmd.split('|')[0].strip('^')
1538 cmd = cmd.split('|')[0].strip('^')
1539 opts = ', '.join([i[1] for i in vals[1]])
1539 opts = ', '.join([i[1] for i in vals[1]])
1540 ui.write('%s: %s\n' % (cmd, opts))
1540 ui.write('%s: %s\n' % (cmd, opts))
1541
1541
1542 @command('debugcomplete',
1542 @command('debugcomplete',
1543 [('o', 'options', None, _('show the command options'))],
1543 [('o', 'options', None, _('show the command options'))],
1544 _('[-o] CMD'))
1544 _('[-o] CMD'))
1545 def debugcomplete(ui, cmd='', **opts):
1545 def debugcomplete(ui, cmd='', **opts):
1546 """returns the completion list associated with the given command"""
1546 """returns the completion list associated with the given command"""
1547
1547
1548 if opts.get('options'):
1548 if opts.get('options'):
1549 options = []
1549 options = []
1550 otables = [globalopts]
1550 otables = [globalopts]
1551 if cmd:
1551 if cmd:
1552 aliases, entry = cmdutil.findcmd(cmd, table, False)
1552 aliases, entry = cmdutil.findcmd(cmd, table, False)
1553 otables.append(entry[1])
1553 otables.append(entry[1])
1554 for t in otables:
1554 for t in otables:
1555 for o in t:
1555 for o in t:
1556 if "(DEPRECATED)" in o[3]:
1556 if "(DEPRECATED)" in o[3]:
1557 continue
1557 continue
1558 if o[0]:
1558 if o[0]:
1559 options.append('-%s' % o[0])
1559 options.append('-%s' % o[0])
1560 options.append('--%s' % o[1])
1560 options.append('--%s' % o[1])
1561 ui.write("%s\n" % "\n".join(options))
1561 ui.write("%s\n" % "\n".join(options))
1562 return
1562 return
1563
1563
1564 cmdlist = cmdutil.findpossible(cmd, table)
1564 cmdlist = cmdutil.findpossible(cmd, table)
1565 if ui.verbose:
1565 if ui.verbose:
1566 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1566 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1567 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1567 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1568
1568
1569 @command('debugdag',
1569 @command('debugdag',
1570 [('t', 'tags', None, _('use tags as labels')),
1570 [('t', 'tags', None, _('use tags as labels')),
1571 ('b', 'branches', None, _('annotate with branch names')),
1571 ('b', 'branches', None, _('annotate with branch names')),
1572 ('', 'dots', None, _('use dots for runs')),
1572 ('', 'dots', None, _('use dots for runs')),
1573 ('s', 'spaces', None, _('separate elements by spaces'))],
1573 ('s', 'spaces', None, _('separate elements by spaces'))],
1574 _('[OPTION]... [FILE [REV]...]'))
1574 _('[OPTION]... [FILE [REV]...]'))
1575 def debugdag(ui, repo, file_=None, *revs, **opts):
1575 def debugdag(ui, repo, file_=None, *revs, **opts):
1576 """format the changelog or an index DAG as a concise textual description
1576 """format the changelog or an index DAG as a concise textual description
1577
1577
1578 If you pass a revlog index, the revlog's DAG is emitted. If you list
1578 If you pass a revlog index, the revlog's DAG is emitted. If you list
1579 revision numbers, they get labelled in the output as rN.
1579 revision numbers, they get labelled in the output as rN.
1580
1580
1581 Otherwise, the changelog DAG of the current repo is emitted.
1581 Otherwise, the changelog DAG of the current repo is emitted.
1582 """
1582 """
1583 spaces = opts.get('spaces')
1583 spaces = opts.get('spaces')
1584 dots = opts.get('dots')
1584 dots = opts.get('dots')
1585 if file_:
1585 if file_:
1586 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1586 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1587 revs = set((int(r) for r in revs))
1587 revs = set((int(r) for r in revs))
1588 def events():
1588 def events():
1589 for r in rlog:
1589 for r in rlog:
1590 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1590 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1591 if r in revs:
1591 if r in revs:
1592 yield 'l', (r, "r%i" % r)
1592 yield 'l', (r, "r%i" % r)
1593 elif repo:
1593 elif repo:
1594 cl = repo.changelog
1594 cl = repo.changelog
1595 tags = opts.get('tags')
1595 tags = opts.get('tags')
1596 branches = opts.get('branches')
1596 branches = opts.get('branches')
1597 if tags:
1597 if tags:
1598 labels = {}
1598 labels = {}
1599 for l, n in repo.tags().items():
1599 for l, n in repo.tags().items():
1600 labels.setdefault(cl.rev(n), []).append(l)
1600 labels.setdefault(cl.rev(n), []).append(l)
1601 def events():
1601 def events():
1602 b = "default"
1602 b = "default"
1603 for r in cl:
1603 for r in cl:
1604 if branches:
1604 if branches:
1605 newb = cl.read(cl.node(r))[5]['branch']
1605 newb = cl.read(cl.node(r))[5]['branch']
1606 if newb != b:
1606 if newb != b:
1607 yield 'a', newb
1607 yield 'a', newb
1608 b = newb
1608 b = newb
1609 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1609 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1610 if tags:
1610 if tags:
1611 ls = labels.get(r)
1611 ls = labels.get(r)
1612 if ls:
1612 if ls:
1613 for l in ls:
1613 for l in ls:
1614 yield 'l', (r, l)
1614 yield 'l', (r, l)
1615 else:
1615 else:
1616 raise util.Abort(_('need repo for changelog dag'))
1616 raise util.Abort(_('need repo for changelog dag'))
1617
1617
1618 for line in dagparser.dagtextlines(events(),
1618 for line in dagparser.dagtextlines(events(),
1619 addspaces=spaces,
1619 addspaces=spaces,
1620 wraplabels=True,
1620 wraplabels=True,
1621 wrapannotations=True,
1621 wrapannotations=True,
1622 wrapnonlinear=dots,
1622 wrapnonlinear=dots,
1623 usedots=dots,
1623 usedots=dots,
1624 maxlinewidth=70):
1624 maxlinewidth=70):
1625 ui.write(line)
1625 ui.write(line)
1626 ui.write("\n")
1626 ui.write("\n")
1627
1627
1628 @command('debugdata',
1628 @command('debugdata',
1629 [('c', 'changelog', False, _('open changelog')),
1629 [('c', 'changelog', False, _('open changelog')),
1630 ('m', 'manifest', False, _('open manifest'))],
1630 ('m', 'manifest', False, _('open manifest'))],
1631 _('-c|-m|FILE REV'))
1631 _('-c|-m|FILE REV'))
1632 def debugdata(ui, repo, file_, rev = None, **opts):
1632 def debugdata(ui, repo, file_, rev = None, **opts):
1633 """dump the contents of a data file revision"""
1633 """dump the contents of a data file revision"""
1634 if opts.get('changelog') or opts.get('manifest'):
1634 if opts.get('changelog') or opts.get('manifest'):
1635 file_, rev = None, file_
1635 file_, rev = None, file_
1636 elif rev is None:
1636 elif rev is None:
1637 raise error.CommandError('debugdata', _('invalid arguments'))
1637 raise error.CommandError('debugdata', _('invalid arguments'))
1638 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1638 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1639 try:
1639 try:
1640 ui.write(r.revision(r.lookup(rev)))
1640 ui.write(r.revision(r.lookup(rev)))
1641 except KeyError:
1641 except KeyError:
1642 raise util.Abort(_('invalid revision identifier %s') % rev)
1642 raise util.Abort(_('invalid revision identifier %s') % rev)
1643
1643
1644 @command('debugdate',
1644 @command('debugdate',
1645 [('e', 'extended', None, _('try extended date formats'))],
1645 [('e', 'extended', None, _('try extended date formats'))],
1646 _('[-e] DATE [RANGE]'))
1646 _('[-e] DATE [RANGE]'))
1647 def debugdate(ui, date, range=None, **opts):
1647 def debugdate(ui, date, range=None, **opts):
1648 """parse and display a date"""
1648 """parse and display a date"""
1649 if opts["extended"]:
1649 if opts["extended"]:
1650 d = util.parsedate(date, util.extendeddateformats)
1650 d = util.parsedate(date, util.extendeddateformats)
1651 else:
1651 else:
1652 d = util.parsedate(date)
1652 d = util.parsedate(date)
1653 ui.write("internal: %s %s\n" % d)
1653 ui.write("internal: %s %s\n" % d)
1654 ui.write("standard: %s\n" % util.datestr(d))
1654 ui.write("standard: %s\n" % util.datestr(d))
1655 if range:
1655 if range:
1656 m = util.matchdate(range)
1656 m = util.matchdate(range)
1657 ui.write("match: %s\n" % m(d[0]))
1657 ui.write("match: %s\n" % m(d[0]))
1658
1658
1659 @command('debugdiscovery',
1659 @command('debugdiscovery',
1660 [('', 'old', None, _('use old-style discovery')),
1660 [('', 'old', None, _('use old-style discovery')),
1661 ('', 'nonheads', None,
1661 ('', 'nonheads', None,
1662 _('use old-style discovery with non-heads included')),
1662 _('use old-style discovery with non-heads included')),
1663 ] + remoteopts,
1663 ] + remoteopts,
1664 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1664 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1665 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1665 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1666 """runs the changeset discovery protocol in isolation"""
1666 """runs the changeset discovery protocol in isolation"""
1667 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1667 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1668 remote = hg.peer(repo, opts, remoteurl)
1668 remote = hg.peer(repo, opts, remoteurl)
1669 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1669 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1670
1670
1671 # make sure tests are repeatable
1671 # make sure tests are repeatable
1672 random.seed(12323)
1672 random.seed(12323)
1673
1673
1674 def doit(localheads, remoteheads):
1674 def doit(localheads, remoteheads):
1675 if opts.get('old'):
1675 if opts.get('old'):
1676 if localheads:
1676 if localheads:
1677 raise util.Abort('cannot use localheads with old style discovery')
1677 raise util.Abort('cannot use localheads with old style discovery')
1678 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1678 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1679 force=True)
1679 force=True)
1680 common = set(common)
1680 common = set(common)
1681 if not opts.get('nonheads'):
1681 if not opts.get('nonheads'):
1682 ui.write("unpruned common: %s\n" % " ".join([short(n)
1682 ui.write("unpruned common: %s\n" % " ".join([short(n)
1683 for n in common]))
1683 for n in common]))
1684 dag = dagutil.revlogdag(repo.changelog)
1684 dag = dagutil.revlogdag(repo.changelog)
1685 all = dag.ancestorset(dag.internalizeall(common))
1685 all = dag.ancestorset(dag.internalizeall(common))
1686 common = dag.externalizeall(dag.headsetofconnecteds(all))
1686 common = dag.externalizeall(dag.headsetofconnecteds(all))
1687 else:
1687 else:
1688 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1688 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1689 common = set(common)
1689 common = set(common)
1690 rheads = set(hds)
1690 rheads = set(hds)
1691 lheads = set(repo.heads())
1691 lheads = set(repo.heads())
1692 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1692 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1693 if lheads <= common:
1693 if lheads <= common:
1694 ui.write("local is subset\n")
1694 ui.write("local is subset\n")
1695 elif rheads <= common:
1695 elif rheads <= common:
1696 ui.write("remote is subset\n")
1696 ui.write("remote is subset\n")
1697
1697
1698 serverlogs = opts.get('serverlog')
1698 serverlogs = opts.get('serverlog')
1699 if serverlogs:
1699 if serverlogs:
1700 for filename in serverlogs:
1700 for filename in serverlogs:
1701 logfile = open(filename, 'r')
1701 logfile = open(filename, 'r')
1702 try:
1702 try:
1703 line = logfile.readline()
1703 line = logfile.readline()
1704 while line:
1704 while line:
1705 parts = line.strip().split(';')
1705 parts = line.strip().split(';')
1706 op = parts[1]
1706 op = parts[1]
1707 if op == 'cg':
1707 if op == 'cg':
1708 pass
1708 pass
1709 elif op == 'cgss':
1709 elif op == 'cgss':
1710 doit(parts[2].split(' '), parts[3].split(' '))
1710 doit(parts[2].split(' '), parts[3].split(' '))
1711 elif op == 'unb':
1711 elif op == 'unb':
1712 doit(parts[3].split(' '), parts[2].split(' '))
1712 doit(parts[3].split(' '), parts[2].split(' '))
1713 line = logfile.readline()
1713 line = logfile.readline()
1714 finally:
1714 finally:
1715 logfile.close()
1715 logfile.close()
1716
1716
1717 else:
1717 else:
1718 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1718 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1719 opts.get('remote_head'))
1719 opts.get('remote_head'))
1720 localrevs = opts.get('local_head')
1720 localrevs = opts.get('local_head')
1721 doit(localrevs, remoterevs)
1721 doit(localrevs, remoterevs)
1722
1722
1723 @command('debugfileset', [], ('REVSPEC'))
1723 @command('debugfileset', [], ('REVSPEC'))
1724 def debugfileset(ui, repo, expr):
1724 def debugfileset(ui, repo, expr):
1725 '''parse and apply a fileset specification'''
1725 '''parse and apply a fileset specification'''
1726 if ui.verbose:
1726 if ui.verbose:
1727 tree = fileset.parse(expr)[0]
1727 tree = fileset.parse(expr)[0]
1728 ui.note(tree, "\n")
1728 ui.note(tree, "\n")
1729
1729
1730 for f in fileset.getfileset(repo[None], expr):
1730 for f in fileset.getfileset(repo[None], expr):
1731 ui.write("%s\n" % f)
1731 ui.write("%s\n" % f)
1732
1732
1733 @command('debugfsinfo', [], _('[PATH]'))
1733 @command('debugfsinfo', [], _('[PATH]'))
1734 def debugfsinfo(ui, path = "."):
1734 def debugfsinfo(ui, path = "."):
1735 """show information detected about current filesystem"""
1735 """show information detected about current filesystem"""
1736 util.writefile('.debugfsinfo', '')
1736 util.writefile('.debugfsinfo', '')
1737 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1737 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1738 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1738 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1739 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1739 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1740 and 'yes' or 'no'))
1740 and 'yes' or 'no'))
1741 os.unlink('.debugfsinfo')
1741 os.unlink('.debugfsinfo')
1742
1742
1743 @command('debuggetbundle',
1743 @command('debuggetbundle',
1744 [('H', 'head', [], _('id of head node'), _('ID')),
1744 [('H', 'head', [], _('id of head node'), _('ID')),
1745 ('C', 'common', [], _('id of common node'), _('ID')),
1745 ('C', 'common', [], _('id of common node'), _('ID')),
1746 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1746 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1747 _('REPO FILE [-H|-C ID]...'))
1747 _('REPO FILE [-H|-C ID]...'))
1748 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1748 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1749 """retrieves a bundle from a repo
1749 """retrieves a bundle from a repo
1750
1750
1751 Every ID must be a full-length hex node id string. Saves the bundle to the
1751 Every ID must be a full-length hex node id string. Saves the bundle to the
1752 given file.
1752 given file.
1753 """
1753 """
1754 repo = hg.peer(ui, opts, repopath)
1754 repo = hg.peer(ui, opts, repopath)
1755 if not repo.capable('getbundle'):
1755 if not repo.capable('getbundle'):
1756 raise util.Abort("getbundle() not supported by target repository")
1756 raise util.Abort("getbundle() not supported by target repository")
1757 args = {}
1757 args = {}
1758 if common:
1758 if common:
1759 args['common'] = [bin(s) for s in common]
1759 args['common'] = [bin(s) for s in common]
1760 if head:
1760 if head:
1761 args['heads'] = [bin(s) for s in head]
1761 args['heads'] = [bin(s) for s in head]
1762 bundle = repo.getbundle('debug', **args)
1762 bundle = repo.getbundle('debug', **args)
1763
1763
1764 bundletype = opts.get('type', 'bzip2').lower()
1764 bundletype = opts.get('type', 'bzip2').lower()
1765 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1765 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1766 bundletype = btypes.get(bundletype)
1766 bundletype = btypes.get(bundletype)
1767 if bundletype not in changegroup.bundletypes:
1767 if bundletype not in changegroup.bundletypes:
1768 raise util.Abort(_('unknown bundle type specified with --type'))
1768 raise util.Abort(_('unknown bundle type specified with --type'))
1769 changegroup.writebundle(bundle, bundlepath, bundletype)
1769 changegroup.writebundle(bundle, bundlepath, bundletype)
1770
1770
1771 @command('debugignore', [], '')
1771 @command('debugignore', [], '')
1772 def debugignore(ui, repo, *values, **opts):
1772 def debugignore(ui, repo, *values, **opts):
1773 """display the combined ignore pattern"""
1773 """display the combined ignore pattern"""
1774 ignore = repo.dirstate._ignore
1774 ignore = repo.dirstate._ignore
1775 includepat = getattr(ignore, 'includepat', None)
1775 includepat = getattr(ignore, 'includepat', None)
1776 if includepat is not None:
1776 if includepat is not None:
1777 ui.write("%s\n" % includepat)
1777 ui.write("%s\n" % includepat)
1778 else:
1778 else:
1779 raise util.Abort(_("no ignore patterns found"))
1779 raise util.Abort(_("no ignore patterns found"))
1780
1780
1781 @command('debugindex',
1781 @command('debugindex',
1782 [('c', 'changelog', False, _('open changelog')),
1782 [('c', 'changelog', False, _('open changelog')),
1783 ('m', 'manifest', False, _('open manifest')),
1783 ('m', 'manifest', False, _('open manifest')),
1784 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1784 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1785 _('[-f FORMAT] -c|-m|FILE'))
1785 _('[-f FORMAT] -c|-m|FILE'))
1786 def debugindex(ui, repo, file_ = None, **opts):
1786 def debugindex(ui, repo, file_ = None, **opts):
1787 """dump the contents of an index file"""
1787 """dump the contents of an index file"""
1788 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1788 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1789 format = opts.get('format', 0)
1789 format = opts.get('format', 0)
1790 if format not in (0, 1):
1790 if format not in (0, 1):
1791 raise util.Abort(_("unknown format %d") % format)
1791 raise util.Abort(_("unknown format %d") % format)
1792
1792
1793 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1793 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1794 if generaldelta:
1794 if generaldelta:
1795 basehdr = ' delta'
1795 basehdr = ' delta'
1796 else:
1796 else:
1797 basehdr = ' base'
1797 basehdr = ' base'
1798
1798
1799 if format == 0:
1799 if format == 0:
1800 ui.write(" rev offset length " + basehdr + " linkrev"
1800 ui.write(" rev offset length " + basehdr + " linkrev"
1801 " nodeid p1 p2\n")
1801 " nodeid p1 p2\n")
1802 elif format == 1:
1802 elif format == 1:
1803 ui.write(" rev flag offset length"
1803 ui.write(" rev flag offset length"
1804 " size " + basehdr + " link p1 p2 nodeid\n")
1804 " size " + basehdr + " link p1 p2 nodeid\n")
1805
1805
1806 for i in r:
1806 for i in r:
1807 node = r.node(i)
1807 node = r.node(i)
1808 if generaldelta:
1808 if generaldelta:
1809 base = r.deltaparent(i)
1809 base = r.deltaparent(i)
1810 else:
1810 else:
1811 base = r.chainbase(i)
1811 base = r.chainbase(i)
1812 if format == 0:
1812 if format == 0:
1813 try:
1813 try:
1814 pp = r.parents(node)
1814 pp = r.parents(node)
1815 except:
1815 except:
1816 pp = [nullid, nullid]
1816 pp = [nullid, nullid]
1817 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1817 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1818 i, r.start(i), r.length(i), base, r.linkrev(i),
1818 i, r.start(i), r.length(i), base, r.linkrev(i),
1819 short(node), short(pp[0]), short(pp[1])))
1819 short(node), short(pp[0]), short(pp[1])))
1820 elif format == 1:
1820 elif format == 1:
1821 pr = r.parentrevs(i)
1821 pr = r.parentrevs(i)
1822 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1822 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1823 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1823 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1824 base, r.linkrev(i), pr[0], pr[1], short(node)))
1824 base, r.linkrev(i), pr[0], pr[1], short(node)))
1825
1825
1826 @command('debugindexdot', [], _('FILE'))
1826 @command('debugindexdot', [], _('FILE'))
1827 def debugindexdot(ui, repo, file_):
1827 def debugindexdot(ui, repo, file_):
1828 """dump an index DAG as a graphviz dot file"""
1828 """dump an index DAG as a graphviz dot file"""
1829 r = None
1829 r = None
1830 if repo:
1830 if repo:
1831 filelog = repo.file(file_)
1831 filelog = repo.file(file_)
1832 if len(filelog):
1832 if len(filelog):
1833 r = filelog
1833 r = filelog
1834 if not r:
1834 if not r:
1835 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1835 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1836 ui.write("digraph G {\n")
1836 ui.write("digraph G {\n")
1837 for i in r:
1837 for i in r:
1838 node = r.node(i)
1838 node = r.node(i)
1839 pp = r.parents(node)
1839 pp = r.parents(node)
1840 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1840 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1841 if pp[1] != nullid:
1841 if pp[1] != nullid:
1842 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1842 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1843 ui.write("}\n")
1843 ui.write("}\n")
1844
1844
1845 @command('debuginstall', [], '')
1845 @command('debuginstall', [], '')
1846 def debuginstall(ui):
1846 def debuginstall(ui):
1847 '''test Mercurial installation
1847 '''test Mercurial installation
1848
1848
1849 Returns 0 on success.
1849 Returns 0 on success.
1850 '''
1850 '''
1851
1851
1852 def writetemp(contents):
1852 def writetemp(contents):
1853 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1853 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1854 f = os.fdopen(fd, "wb")
1854 f = os.fdopen(fd, "wb")
1855 f.write(contents)
1855 f.write(contents)
1856 f.close()
1856 f.close()
1857 return name
1857 return name
1858
1858
1859 problems = 0
1859 problems = 0
1860
1860
1861 # encoding
1861 # encoding
1862 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1862 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1863 try:
1863 try:
1864 encoding.fromlocal("test")
1864 encoding.fromlocal("test")
1865 except util.Abort, inst:
1865 except util.Abort, inst:
1866 ui.write(" %s\n" % inst)
1866 ui.write(" %s\n" % inst)
1867 ui.write(_(" (check that your locale is properly set)\n"))
1867 ui.write(_(" (check that your locale is properly set)\n"))
1868 problems += 1
1868 problems += 1
1869
1869
1870 # compiled modules
1870 # compiled modules
1871 ui.status(_("Checking installed modules (%s)...\n")
1871 ui.status(_("Checking installed modules (%s)...\n")
1872 % os.path.dirname(__file__))
1872 % os.path.dirname(__file__))
1873 try:
1873 try:
1874 import bdiff, mpatch, base85, osutil
1874 import bdiff, mpatch, base85, osutil
1875 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1875 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1876 except Exception, inst:
1876 except Exception, inst:
1877 ui.write(" %s\n" % inst)
1877 ui.write(" %s\n" % inst)
1878 ui.write(_(" One or more extensions could not be found"))
1878 ui.write(_(" One or more extensions could not be found"))
1879 ui.write(_(" (check that you compiled the extensions)\n"))
1879 ui.write(_(" (check that you compiled the extensions)\n"))
1880 problems += 1
1880 problems += 1
1881
1881
1882 # templates
1882 # templates
1883 import templater
1883 import templater
1884 p = templater.templatepath()
1884 p = templater.templatepath()
1885 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1885 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1886 try:
1886 try:
1887 templater.templater(templater.templatepath("map-cmdline.default"))
1887 templater.templater(templater.templatepath("map-cmdline.default"))
1888 except Exception, inst:
1888 except Exception, inst:
1889 ui.write(" %s\n" % inst)
1889 ui.write(" %s\n" % inst)
1890 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1890 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1891 problems += 1
1891 problems += 1
1892
1892
1893 # editor
1893 # editor
1894 ui.status(_("Checking commit editor...\n"))
1894 ui.status(_("Checking commit editor...\n"))
1895 editor = ui.geteditor()
1895 editor = ui.geteditor()
1896 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1896 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1897 if not cmdpath:
1897 if not cmdpath:
1898 if editor == 'vi':
1898 if editor == 'vi':
1899 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1899 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1900 ui.write(_(" (specify a commit editor in your configuration"
1900 ui.write(_(" (specify a commit editor in your configuration"
1901 " file)\n"))
1901 " file)\n"))
1902 else:
1902 else:
1903 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1903 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1904 ui.write(_(" (specify a commit editor in your configuration"
1904 ui.write(_(" (specify a commit editor in your configuration"
1905 " file)\n"))
1905 " file)\n"))
1906 problems += 1
1906 problems += 1
1907
1907
1908 # check username
1908 # check username
1909 ui.status(_("Checking username...\n"))
1909 ui.status(_("Checking username...\n"))
1910 try:
1910 try:
1911 ui.username()
1911 ui.username()
1912 except util.Abort, e:
1912 except util.Abort, e:
1913 ui.write(" %s\n" % e)
1913 ui.write(" %s\n" % e)
1914 ui.write(_(" (specify a username in your configuration file)\n"))
1914 ui.write(_(" (specify a username in your configuration file)\n"))
1915 problems += 1
1915 problems += 1
1916
1916
1917 if not problems:
1917 if not problems:
1918 ui.status(_("No problems detected\n"))
1918 ui.status(_("No problems detected\n"))
1919 else:
1919 else:
1920 ui.write(_("%s problems detected,"
1920 ui.write(_("%s problems detected,"
1921 " please check your install!\n") % problems)
1921 " please check your install!\n") % problems)
1922
1922
1923 return problems
1923 return problems
1924
1924
1925 @command('debugknown', [], _('REPO ID...'))
1925 @command('debugknown', [], _('REPO ID...'))
1926 def debugknown(ui, repopath, *ids, **opts):
1926 def debugknown(ui, repopath, *ids, **opts):
1927 """test whether node ids are known to a repo
1927 """test whether node ids are known to a repo
1928
1928
1929 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1929 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1930 indicating unknown/known.
1930 indicating unknown/known.
1931 """
1931 """
1932 repo = hg.peer(ui, opts, repopath)
1932 repo = hg.peer(ui, opts, repopath)
1933 if not repo.capable('known'):
1933 if not repo.capable('known'):
1934 raise util.Abort("known() not supported by target repository")
1934 raise util.Abort("known() not supported by target repository")
1935 flags = repo.known([bin(s) for s in ids])
1935 flags = repo.known([bin(s) for s in ids])
1936 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1936 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1937
1937
1938 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1938 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1939 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1939 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1940 '''access the pushkey key/value protocol
1940 '''access the pushkey key/value protocol
1941
1941
1942 With two args, list the keys in the given namespace.
1942 With two args, list the keys in the given namespace.
1943
1943
1944 With five args, set a key to new if it currently is set to old.
1944 With five args, set a key to new if it currently is set to old.
1945 Reports success or failure.
1945 Reports success or failure.
1946 '''
1946 '''
1947
1947
1948 target = hg.peer(ui, {}, repopath)
1948 target = hg.peer(ui, {}, repopath)
1949 if keyinfo:
1949 if keyinfo:
1950 key, old, new = keyinfo
1950 key, old, new = keyinfo
1951 r = target.pushkey(namespace, key, old, new)
1951 r = target.pushkey(namespace, key, old, new)
1952 ui.status(str(r) + '\n')
1952 ui.status(str(r) + '\n')
1953 return not r
1953 return not r
1954 else:
1954 else:
1955 for k, v in target.listkeys(namespace).iteritems():
1955 for k, v in target.listkeys(namespace).iteritems():
1956 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1956 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1957 v.encode('string-escape')))
1957 v.encode('string-escape')))
1958
1958
1959 @command('debugrebuildstate',
1959 @command('debugrebuildstate',
1960 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1960 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1961 _('[-r REV] [REV]'))
1961 _('[-r REV] [REV]'))
1962 def debugrebuildstate(ui, repo, rev="tip"):
1962 def debugrebuildstate(ui, repo, rev="tip"):
1963 """rebuild the dirstate as it would look like for the given revision"""
1963 """rebuild the dirstate as it would look like for the given revision"""
1964 ctx = scmutil.revsingle(repo, rev)
1964 ctx = scmutil.revsingle(repo, rev)
1965 wlock = repo.wlock()
1965 wlock = repo.wlock()
1966 try:
1966 try:
1967 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1967 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1968 finally:
1968 finally:
1969 wlock.release()
1969 wlock.release()
1970
1970
1971 @command('debugrename',
1971 @command('debugrename',
1972 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1972 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1973 _('[-r REV] FILE'))
1973 _('[-r REV] FILE'))
1974 def debugrename(ui, repo, file1, *pats, **opts):
1974 def debugrename(ui, repo, file1, *pats, **opts):
1975 """dump rename information"""
1975 """dump rename information"""
1976
1976
1977 ctx = scmutil.revsingle(repo, opts.get('rev'))
1977 ctx = scmutil.revsingle(repo, opts.get('rev'))
1978 m = scmutil.match(ctx, (file1,) + pats, opts)
1978 m = scmutil.match(ctx, (file1,) + pats, opts)
1979 for abs in ctx.walk(m):
1979 for abs in ctx.walk(m):
1980 fctx = ctx[abs]
1980 fctx = ctx[abs]
1981 o = fctx.filelog().renamed(fctx.filenode())
1981 o = fctx.filelog().renamed(fctx.filenode())
1982 rel = m.rel(abs)
1982 rel = m.rel(abs)
1983 if o:
1983 if o:
1984 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1984 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1985 else:
1985 else:
1986 ui.write(_("%s not renamed\n") % rel)
1986 ui.write(_("%s not renamed\n") % rel)
1987
1987
1988 @command('debugrevlog',
1988 @command('debugrevlog',
1989 [('c', 'changelog', False, _('open changelog')),
1989 [('c', 'changelog', False, _('open changelog')),
1990 ('m', 'manifest', False, _('open manifest')),
1990 ('m', 'manifest', False, _('open manifest')),
1991 ('d', 'dump', False, _('dump index data'))],
1991 ('d', 'dump', False, _('dump index data'))],
1992 _('-c|-m|FILE'))
1992 _('-c|-m|FILE'))
1993 def debugrevlog(ui, repo, file_ = None, **opts):
1993 def debugrevlog(ui, repo, file_ = None, **opts):
1994 """show data and statistics about a revlog"""
1994 """show data and statistics about a revlog"""
1995 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1995 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1996
1996
1997 if opts.get("dump"):
1997 if opts.get("dump"):
1998 numrevs = len(r)
1998 numrevs = len(r)
1999 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1999 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2000 " rawsize totalsize compression heads\n")
2000 " rawsize totalsize compression heads\n")
2001 ts = 0
2001 ts = 0
2002 heads = set()
2002 heads = set()
2003 for rev in xrange(numrevs):
2003 for rev in xrange(numrevs):
2004 dbase = r.deltaparent(rev)
2004 dbase = r.deltaparent(rev)
2005 if dbase == -1:
2005 if dbase == -1:
2006 dbase = rev
2006 dbase = rev
2007 cbase = r.chainbase(rev)
2007 cbase = r.chainbase(rev)
2008 p1, p2 = r.parentrevs(rev)
2008 p1, p2 = r.parentrevs(rev)
2009 rs = r.rawsize(rev)
2009 rs = r.rawsize(rev)
2010 ts = ts + rs
2010 ts = ts + rs
2011 heads -= set(r.parentrevs(rev))
2011 heads -= set(r.parentrevs(rev))
2012 heads.add(rev)
2012 heads.add(rev)
2013 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2013 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2014 (rev, p1, p2, r.start(rev), r.end(rev),
2014 (rev, p1, p2, r.start(rev), r.end(rev),
2015 r.start(dbase), r.start(cbase),
2015 r.start(dbase), r.start(cbase),
2016 r.start(p1), r.start(p2),
2016 r.start(p1), r.start(p2),
2017 rs, ts, ts / r.end(rev), len(heads)))
2017 rs, ts, ts / r.end(rev), len(heads)))
2018 return 0
2018 return 0
2019
2019
2020 v = r.version
2020 v = r.version
2021 format = v & 0xFFFF
2021 format = v & 0xFFFF
2022 flags = []
2022 flags = []
2023 gdelta = False
2023 gdelta = False
2024 if v & revlog.REVLOGNGINLINEDATA:
2024 if v & revlog.REVLOGNGINLINEDATA:
2025 flags.append('inline')
2025 flags.append('inline')
2026 if v & revlog.REVLOGGENERALDELTA:
2026 if v & revlog.REVLOGGENERALDELTA:
2027 gdelta = True
2027 gdelta = True
2028 flags.append('generaldelta')
2028 flags.append('generaldelta')
2029 if not flags:
2029 if not flags:
2030 flags = ['(none)']
2030 flags = ['(none)']
2031
2031
2032 nummerges = 0
2032 nummerges = 0
2033 numfull = 0
2033 numfull = 0
2034 numprev = 0
2034 numprev = 0
2035 nump1 = 0
2035 nump1 = 0
2036 nump2 = 0
2036 nump2 = 0
2037 numother = 0
2037 numother = 0
2038 nump1prev = 0
2038 nump1prev = 0
2039 nump2prev = 0
2039 nump2prev = 0
2040 chainlengths = []
2040 chainlengths = []
2041
2041
2042 datasize = [None, 0, 0L]
2042 datasize = [None, 0, 0L]
2043 fullsize = [None, 0, 0L]
2043 fullsize = [None, 0, 0L]
2044 deltasize = [None, 0, 0L]
2044 deltasize = [None, 0, 0L]
2045
2045
2046 def addsize(size, l):
2046 def addsize(size, l):
2047 if l[0] is None or size < l[0]:
2047 if l[0] is None or size < l[0]:
2048 l[0] = size
2048 l[0] = size
2049 if size > l[1]:
2049 if size > l[1]:
2050 l[1] = size
2050 l[1] = size
2051 l[2] += size
2051 l[2] += size
2052
2052
2053 numrevs = len(r)
2053 numrevs = len(r)
2054 for rev in xrange(numrevs):
2054 for rev in xrange(numrevs):
2055 p1, p2 = r.parentrevs(rev)
2055 p1, p2 = r.parentrevs(rev)
2056 delta = r.deltaparent(rev)
2056 delta = r.deltaparent(rev)
2057 if format > 0:
2057 if format > 0:
2058 addsize(r.rawsize(rev), datasize)
2058 addsize(r.rawsize(rev), datasize)
2059 if p2 != nullrev:
2059 if p2 != nullrev:
2060 nummerges += 1
2060 nummerges += 1
2061 size = r.length(rev)
2061 size = r.length(rev)
2062 if delta == nullrev:
2062 if delta == nullrev:
2063 chainlengths.append(0)
2063 chainlengths.append(0)
2064 numfull += 1
2064 numfull += 1
2065 addsize(size, fullsize)
2065 addsize(size, fullsize)
2066 else:
2066 else:
2067 chainlengths.append(chainlengths[delta] + 1)
2067 chainlengths.append(chainlengths[delta] + 1)
2068 addsize(size, deltasize)
2068 addsize(size, deltasize)
2069 if delta == rev - 1:
2069 if delta == rev - 1:
2070 numprev += 1
2070 numprev += 1
2071 if delta == p1:
2071 if delta == p1:
2072 nump1prev += 1
2072 nump1prev += 1
2073 elif delta == p2:
2073 elif delta == p2:
2074 nump2prev += 1
2074 nump2prev += 1
2075 elif delta == p1:
2075 elif delta == p1:
2076 nump1 += 1
2076 nump1 += 1
2077 elif delta == p2:
2077 elif delta == p2:
2078 nump2 += 1
2078 nump2 += 1
2079 elif delta != nullrev:
2079 elif delta != nullrev:
2080 numother += 1
2080 numother += 1
2081
2081
2082 numdeltas = numrevs - numfull
2082 numdeltas = numrevs - numfull
2083 numoprev = numprev - nump1prev - nump2prev
2083 numoprev = numprev - nump1prev - nump2prev
2084 totalrawsize = datasize[2]
2084 totalrawsize = datasize[2]
2085 datasize[2] /= numrevs
2085 datasize[2] /= numrevs
2086 fulltotal = fullsize[2]
2086 fulltotal = fullsize[2]
2087 fullsize[2] /= numfull
2087 fullsize[2] /= numfull
2088 deltatotal = deltasize[2]
2088 deltatotal = deltasize[2]
2089 deltasize[2] /= numrevs - numfull
2089 deltasize[2] /= numrevs - numfull
2090 totalsize = fulltotal + deltatotal
2090 totalsize = fulltotal + deltatotal
2091 avgchainlen = sum(chainlengths) / numrevs
2091 avgchainlen = sum(chainlengths) / numrevs
2092 compratio = totalrawsize / totalsize
2092 compratio = totalrawsize / totalsize
2093
2093
2094 basedfmtstr = '%%%dd\n'
2094 basedfmtstr = '%%%dd\n'
2095 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2095 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2096
2096
2097 def dfmtstr(max):
2097 def dfmtstr(max):
2098 return basedfmtstr % len(str(max))
2098 return basedfmtstr % len(str(max))
2099 def pcfmtstr(max, padding=0):
2099 def pcfmtstr(max, padding=0):
2100 return basepcfmtstr % (len(str(max)), ' ' * padding)
2100 return basepcfmtstr % (len(str(max)), ' ' * padding)
2101
2101
2102 def pcfmt(value, total):
2102 def pcfmt(value, total):
2103 return (value, 100 * float(value) / total)
2103 return (value, 100 * float(value) / total)
2104
2104
2105 ui.write('format : %d\n' % format)
2105 ui.write('format : %d\n' % format)
2106 ui.write('flags : %s\n' % ', '.join(flags))
2106 ui.write('flags : %s\n' % ', '.join(flags))
2107
2107
2108 ui.write('\n')
2108 ui.write('\n')
2109 fmt = pcfmtstr(totalsize)
2109 fmt = pcfmtstr(totalsize)
2110 fmt2 = dfmtstr(totalsize)
2110 fmt2 = dfmtstr(totalsize)
2111 ui.write('revisions : ' + fmt2 % numrevs)
2111 ui.write('revisions : ' + fmt2 % numrevs)
2112 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2112 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2113 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2113 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2114 ui.write('revisions : ' + fmt2 % numrevs)
2114 ui.write('revisions : ' + fmt2 % numrevs)
2115 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2115 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2116 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2116 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2117 ui.write('revision size : ' + fmt2 % totalsize)
2117 ui.write('revision size : ' + fmt2 % totalsize)
2118 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2118 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2119 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2119 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2120
2120
2121 ui.write('\n')
2121 ui.write('\n')
2122 fmt = dfmtstr(max(avgchainlen, compratio))
2122 fmt = dfmtstr(max(avgchainlen, compratio))
2123 ui.write('avg chain length : ' + fmt % avgchainlen)
2123 ui.write('avg chain length : ' + fmt % avgchainlen)
2124 ui.write('compression ratio : ' + fmt % compratio)
2124 ui.write('compression ratio : ' + fmt % compratio)
2125
2125
2126 if format > 0:
2126 if format > 0:
2127 ui.write('\n')
2127 ui.write('\n')
2128 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2128 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2129 % tuple(datasize))
2129 % tuple(datasize))
2130 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2130 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2131 % tuple(fullsize))
2131 % tuple(fullsize))
2132 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2132 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2133 % tuple(deltasize))
2133 % tuple(deltasize))
2134
2134
2135 if numdeltas > 0:
2135 if numdeltas > 0:
2136 ui.write('\n')
2136 ui.write('\n')
2137 fmt = pcfmtstr(numdeltas)
2137 fmt = pcfmtstr(numdeltas)
2138 fmt2 = pcfmtstr(numdeltas, 4)
2138 fmt2 = pcfmtstr(numdeltas, 4)
2139 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2139 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2140 if numprev > 0:
2140 if numprev > 0:
2141 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2141 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2142 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2142 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2143 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2143 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2144 if gdelta:
2144 if gdelta:
2145 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2145 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2146 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2146 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2147 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2147 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2148
2148
2149 @command('debugrevspec', [], ('REVSPEC'))
2149 @command('debugrevspec', [], ('REVSPEC'))
2150 def debugrevspec(ui, repo, expr):
2150 def debugrevspec(ui, repo, expr):
2151 '''parse and apply a revision specification'''
2151 '''parse and apply a revision specification'''
2152 if ui.verbose:
2152 if ui.verbose:
2153 tree = revset.parse(expr)[0]
2153 tree = revset.parse(expr)[0]
2154 ui.note(tree, "\n")
2154 ui.note(tree, "\n")
2155 newtree = revset.findaliases(ui, tree)
2155 newtree = revset.findaliases(ui, tree)
2156 if newtree != tree:
2156 if newtree != tree:
2157 ui.note(newtree, "\n")
2157 ui.note(newtree, "\n")
2158 func = revset.match(ui, expr)
2158 func = revset.match(ui, expr)
2159 for c in func(repo, range(len(repo))):
2159 for c in func(repo, range(len(repo))):
2160 ui.write("%s\n" % c)
2160 ui.write("%s\n" % c)
2161
2161
2162 @command('debugsetparents', [], _('REV1 [REV2]'))
2162 @command('debugsetparents', [], _('REV1 [REV2]'))
2163 def debugsetparents(ui, repo, rev1, rev2=None):
2163 def debugsetparents(ui, repo, rev1, rev2=None):
2164 """manually set the parents of the current working directory
2164 """manually set the parents of the current working directory
2165
2165
2166 This is useful for writing repository conversion tools, but should
2166 This is useful for writing repository conversion tools, but should
2167 be used with care.
2167 be used with care.
2168
2168
2169 Returns 0 on success.
2169 Returns 0 on success.
2170 """
2170 """
2171
2171
2172 r1 = scmutil.revsingle(repo, rev1).node()
2172 r1 = scmutil.revsingle(repo, rev1).node()
2173 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2173 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2174
2174
2175 wlock = repo.wlock()
2175 wlock = repo.wlock()
2176 try:
2176 try:
2177 repo.dirstate.setparents(r1, r2)
2177 repo.dirstate.setparents(r1, r2)
2178 finally:
2178 finally:
2179 wlock.release()
2179 wlock.release()
2180
2180
2181 @command('debugstate',
2181 @command('debugstate',
2182 [('', 'nodates', None, _('do not display the saved mtime')),
2182 [('', 'nodates', None, _('do not display the saved mtime')),
2183 ('', 'datesort', None, _('sort by saved mtime'))],
2183 ('', 'datesort', None, _('sort by saved mtime'))],
2184 _('[OPTION]...'))
2184 _('[OPTION]...'))
2185 def debugstate(ui, repo, nodates=None, datesort=None):
2185 def debugstate(ui, repo, nodates=None, datesort=None):
2186 """show the contents of the current dirstate"""
2186 """show the contents of the current dirstate"""
2187 timestr = ""
2187 timestr = ""
2188 showdate = not nodates
2188 showdate = not nodates
2189 if datesort:
2189 if datesort:
2190 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2190 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2191 else:
2191 else:
2192 keyfunc = None # sort by filename
2192 keyfunc = None # sort by filename
2193 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2193 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2194 if showdate:
2194 if showdate:
2195 if ent[3] == -1:
2195 if ent[3] == -1:
2196 # Pad or slice to locale representation
2196 # Pad or slice to locale representation
2197 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2197 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2198 time.localtime(0)))
2198 time.localtime(0)))
2199 timestr = 'unset'
2199 timestr = 'unset'
2200 timestr = (timestr[:locale_len] +
2200 timestr = (timestr[:locale_len] +
2201 ' ' * (locale_len - len(timestr)))
2201 ' ' * (locale_len - len(timestr)))
2202 else:
2202 else:
2203 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2203 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2204 time.localtime(ent[3]))
2204 time.localtime(ent[3]))
2205 if ent[1] & 020000:
2205 if ent[1] & 020000:
2206 mode = 'lnk'
2206 mode = 'lnk'
2207 else:
2207 else:
2208 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2208 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2209 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2209 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2210 for f in repo.dirstate.copies():
2210 for f in repo.dirstate.copies():
2211 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2211 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2212
2212
2213 @command('debugsub',
2213 @command('debugsub',
2214 [('r', 'rev', '',
2214 [('r', 'rev', '',
2215 _('revision to check'), _('REV'))],
2215 _('revision to check'), _('REV'))],
2216 _('[-r REV] [REV]'))
2216 _('[-r REV] [REV]'))
2217 def debugsub(ui, repo, rev=None):
2217 def debugsub(ui, repo, rev=None):
2218 ctx = scmutil.revsingle(repo, rev, None)
2218 ctx = scmutil.revsingle(repo, rev, None)
2219 for k, v in sorted(ctx.substate.items()):
2219 for k, v in sorted(ctx.substate.items()):
2220 ui.write('path %s\n' % k)
2220 ui.write('path %s\n' % k)
2221 ui.write(' source %s\n' % v[0])
2221 ui.write(' source %s\n' % v[0])
2222 ui.write(' revision %s\n' % v[1])
2222 ui.write(' revision %s\n' % v[1])
2223
2223
2224 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2224 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2225 def debugwalk(ui, repo, *pats, **opts):
2225 def debugwalk(ui, repo, *pats, **opts):
2226 """show how files match on given patterns"""
2226 """show how files match on given patterns"""
2227 m = scmutil.match(repo[None], pats, opts)
2227 m = scmutil.match(repo[None], pats, opts)
2228 items = list(repo.walk(m))
2228 items = list(repo.walk(m))
2229 if not items:
2229 if not items:
2230 return
2230 return
2231 fmt = 'f %%-%ds %%-%ds %%s' % (
2231 fmt = 'f %%-%ds %%-%ds %%s' % (
2232 max([len(abs) for abs in items]),
2232 max([len(abs) for abs in items]),
2233 max([len(m.rel(abs)) for abs in items]))
2233 max([len(m.rel(abs)) for abs in items]))
2234 for abs in items:
2234 for abs in items:
2235 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2235 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2236 ui.write("%s\n" % line.rstrip())
2236 ui.write("%s\n" % line.rstrip())
2237
2237
2238 @command('debugwireargs',
2238 @command('debugwireargs',
2239 [('', 'three', '', 'three'),
2239 [('', 'three', '', 'three'),
2240 ('', 'four', '', 'four'),
2240 ('', 'four', '', 'four'),
2241 ('', 'five', '', 'five'),
2241 ('', 'five', '', 'five'),
2242 ] + remoteopts,
2242 ] + remoteopts,
2243 _('REPO [OPTIONS]... [ONE [TWO]]'))
2243 _('REPO [OPTIONS]... [ONE [TWO]]'))
2244 def debugwireargs(ui, repopath, *vals, **opts):
2244 def debugwireargs(ui, repopath, *vals, **opts):
2245 repo = hg.peer(ui, opts, repopath)
2245 repo = hg.peer(ui, opts, repopath)
2246 for opt in remoteopts:
2246 for opt in remoteopts:
2247 del opts[opt[1]]
2247 del opts[opt[1]]
2248 args = {}
2248 args = {}
2249 for k, v in opts.iteritems():
2249 for k, v in opts.iteritems():
2250 if v:
2250 if v:
2251 args[k] = v
2251 args[k] = v
2252 # run twice to check that we don't mess up the stream for the next command
2252 # run twice to check that we don't mess up the stream for the next command
2253 res1 = repo.debugwireargs(*vals, **args)
2253 res1 = repo.debugwireargs(*vals, **args)
2254 res2 = repo.debugwireargs(*vals, **args)
2254 res2 = repo.debugwireargs(*vals, **args)
2255 ui.write("%s\n" % res1)
2255 ui.write("%s\n" % res1)
2256 if res1 != res2:
2256 if res1 != res2:
2257 ui.warn("%s\n" % res2)
2257 ui.warn("%s\n" % res2)
2258
2258
2259 @command('^diff',
2259 @command('^diff',
2260 [('r', 'rev', [], _('revision'), _('REV')),
2260 [('r', 'rev', [], _('revision'), _('REV')),
2261 ('c', 'change', '', _('change made by revision'), _('REV'))
2261 ('c', 'change', '', _('change made by revision'), _('REV'))
2262 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2262 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2263 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2263 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2264 def diff(ui, repo, *pats, **opts):
2264 def diff(ui, repo, *pats, **opts):
2265 """diff repository (or selected files)
2265 """diff repository (or selected files)
2266
2266
2267 Show differences between revisions for the specified files.
2267 Show differences between revisions for the specified files.
2268
2268
2269 Differences between files are shown using the unified diff format.
2269 Differences between files are shown using the unified diff format.
2270
2270
2271 .. note::
2271 .. note::
2272 diff may generate unexpected results for merges, as it will
2272 diff may generate unexpected results for merges, as it will
2273 default to comparing against the working directory's first
2273 default to comparing against the working directory's first
2274 parent changeset if no revisions are specified.
2274 parent changeset if no revisions are specified.
2275
2275
2276 When two revision arguments are given, then changes are shown
2276 When two revision arguments are given, then changes are shown
2277 between those revisions. If only one revision is specified then
2277 between those revisions. If only one revision is specified then
2278 that revision is compared to the working directory, and, when no
2278 that revision is compared to the working directory, and, when no
2279 revisions are specified, the working directory files are compared
2279 revisions are specified, the working directory files are compared
2280 to its parent.
2280 to its parent.
2281
2281
2282 Alternatively you can specify -c/--change with a revision to see
2282 Alternatively you can specify -c/--change with a revision to see
2283 the changes in that changeset relative to its first parent.
2283 the changes in that changeset relative to its first parent.
2284
2284
2285 Without the -a/--text option, diff will avoid generating diffs of
2285 Without the -a/--text option, diff will avoid generating diffs of
2286 files it detects as binary. With -a, diff will generate a diff
2286 files it detects as binary. With -a, diff will generate a diff
2287 anyway, probably with undesirable results.
2287 anyway, probably with undesirable results.
2288
2288
2289 Use the -g/--git option to generate diffs in the git extended diff
2289 Use the -g/--git option to generate diffs in the git extended diff
2290 format. For more information, read :hg:`help diffs`.
2290 format. For more information, read :hg:`help diffs`.
2291
2291
2292 .. container:: verbose
2292 .. container:: verbose
2293
2293
2294 Examples:
2294 Examples:
2295
2295
2296 - compare a file in the current working directory to its parent::
2296 - compare a file in the current working directory to its parent::
2297
2297
2298 hg diff foo.c
2298 hg diff foo.c
2299
2299
2300 - compare two historical versions of a directory, with rename info::
2300 - compare two historical versions of a directory, with rename info::
2301
2301
2302 hg diff --git -r 1.0:1.2 lib/
2302 hg diff --git -r 1.0:1.2 lib/
2303
2303
2304 - get change stats relative to the last change on some date::
2304 - get change stats relative to the last change on some date::
2305
2305
2306 hg diff --stat -r "date('may 2')"
2306 hg diff --stat -r "date('may 2')"
2307
2307
2308 - diff all newly-added files that contain a keyword::
2308 - diff all newly-added files that contain a keyword::
2309
2309
2310 hg diff "set:added() and grep(GNU)"
2310 hg diff "set:added() and grep(GNU)"
2311
2311
2312 - compare a revision and its parents::
2312 - compare a revision and its parents::
2313
2313
2314 hg diff -c 9353 # compare against first parent
2314 hg diff -c 9353 # compare against first parent
2315 hg diff -r 9353^:9353 # same using revset syntax
2315 hg diff -r 9353^:9353 # same using revset syntax
2316 hg diff -r 9353^2:9353 # compare against the second parent
2316 hg diff -r 9353^2:9353 # compare against the second parent
2317
2317
2318 Returns 0 on success.
2318 Returns 0 on success.
2319 """
2319 """
2320
2320
2321 revs = opts.get('rev')
2321 revs = opts.get('rev')
2322 change = opts.get('change')
2322 change = opts.get('change')
2323 stat = opts.get('stat')
2323 stat = opts.get('stat')
2324 reverse = opts.get('reverse')
2324 reverse = opts.get('reverse')
2325
2325
2326 if revs and change:
2326 if revs and change:
2327 msg = _('cannot specify --rev and --change at the same time')
2327 msg = _('cannot specify --rev and --change at the same time')
2328 raise util.Abort(msg)
2328 raise util.Abort(msg)
2329 elif change:
2329 elif change:
2330 node2 = scmutil.revsingle(repo, change, None).node()
2330 node2 = scmutil.revsingle(repo, change, None).node()
2331 node1 = repo[node2].p1().node()
2331 node1 = repo[node2].p1().node()
2332 else:
2332 else:
2333 node1, node2 = scmutil.revpair(repo, revs)
2333 node1, node2 = scmutil.revpair(repo, revs)
2334
2334
2335 if reverse:
2335 if reverse:
2336 node1, node2 = node2, node1
2336 node1, node2 = node2, node1
2337
2337
2338 diffopts = patch.diffopts(ui, opts)
2338 diffopts = patch.diffopts(ui, opts)
2339 m = scmutil.match(repo[node2], pats, opts)
2339 m = scmutil.match(repo[node2], pats, opts)
2340 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2340 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2341 listsubrepos=opts.get('subrepos'))
2341 listsubrepos=opts.get('subrepos'))
2342
2342
2343 @command('^export',
2343 @command('^export',
2344 [('o', 'output', '',
2344 [('o', 'output', '',
2345 _('print output to file with formatted name'), _('FORMAT')),
2345 _('print output to file with formatted name'), _('FORMAT')),
2346 ('', 'switch-parent', None, _('diff against the second parent')),
2346 ('', 'switch-parent', None, _('diff against the second parent')),
2347 ('r', 'rev', [], _('revisions to export'), _('REV')),
2347 ('r', 'rev', [], _('revisions to export'), _('REV')),
2348 ] + diffopts,
2348 ] + diffopts,
2349 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2349 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2350 def export(ui, repo, *changesets, **opts):
2350 def export(ui, repo, *changesets, **opts):
2351 """dump the header and diffs for one or more changesets
2351 """dump the header and diffs for one or more changesets
2352
2352
2353 Print the changeset header and diffs for one or more revisions.
2353 Print the changeset header and diffs for one or more revisions.
2354
2354
2355 The information shown in the changeset header is: author, date,
2355 The information shown in the changeset header is: author, date,
2356 branch name (if non-default), changeset hash, parent(s) and commit
2356 branch name (if non-default), changeset hash, parent(s) and commit
2357 comment.
2357 comment.
2358
2358
2359 .. note::
2359 .. note::
2360 export may generate unexpected diff output for merge
2360 export may generate unexpected diff output for merge
2361 changesets, as it will compare the merge changeset against its
2361 changesets, as it will compare the merge changeset against its
2362 first parent only.
2362 first parent only.
2363
2363
2364 Output may be to a file, in which case the name of the file is
2364 Output may be to a file, in which case the name of the file is
2365 given using a format string. The formatting rules are as follows:
2365 given using a format string. The formatting rules are as follows:
2366
2366
2367 :``%%``: literal "%" character
2367 :``%%``: literal "%" character
2368 :``%H``: changeset hash (40 hexadecimal digits)
2368 :``%H``: changeset hash (40 hexadecimal digits)
2369 :``%N``: number of patches being generated
2369 :``%N``: number of patches being generated
2370 :``%R``: changeset revision number
2370 :``%R``: changeset revision number
2371 :``%b``: basename of the exporting repository
2371 :``%b``: basename of the exporting repository
2372 :``%h``: short-form changeset hash (12 hexadecimal digits)
2372 :``%h``: short-form changeset hash (12 hexadecimal digits)
2373 :``%m``: first line of the commit message (only alphanumeric characters)
2373 :``%m``: first line of the commit message (only alphanumeric characters)
2374 :``%n``: zero-padded sequence number, starting at 1
2374 :``%n``: zero-padded sequence number, starting at 1
2375 :``%r``: zero-padded changeset revision number
2375 :``%r``: zero-padded changeset revision number
2376
2376
2377 Without the -a/--text option, export will avoid generating diffs
2377 Without the -a/--text option, export will avoid generating diffs
2378 of files it detects as binary. With -a, export will generate a
2378 of files it detects as binary. With -a, export will generate a
2379 diff anyway, probably with undesirable results.
2379 diff anyway, probably with undesirable results.
2380
2380
2381 Use the -g/--git option to generate diffs in the git extended diff
2381 Use the -g/--git option to generate diffs in the git extended diff
2382 format. See :hg:`help diffs` for more information.
2382 format. See :hg:`help diffs` for more information.
2383
2383
2384 With the --switch-parent option, the diff will be against the
2384 With the --switch-parent option, the diff will be against the
2385 second parent. It can be useful to review a merge.
2385 second parent. It can be useful to review a merge.
2386
2386
2387 .. container:: verbose
2387 .. container:: verbose
2388
2388
2389 Examples:
2389 Examples:
2390
2390
2391 - use export and import to transplant a bugfix to the current
2391 - use export and import to transplant a bugfix to the current
2392 branch::
2392 branch::
2393
2393
2394 hg export -r 9353 | hg import -
2394 hg export -r 9353 | hg import -
2395
2395
2396 - export all the changesets between two revisions to a file with
2396 - export all the changesets between two revisions to a file with
2397 rename information::
2397 rename information::
2398
2398
2399 hg export --git -r 123:150 > changes.txt
2399 hg export --git -r 123:150 > changes.txt
2400
2400
2401 - split outgoing changes into a series of patches with
2401 - split outgoing changes into a series of patches with
2402 descriptive names::
2402 descriptive names::
2403
2403
2404 hg export -r "outgoing()" -o "%n-%m.patch"
2404 hg export -r "outgoing()" -o "%n-%m.patch"
2405
2405
2406 Returns 0 on success.
2406 Returns 0 on success.
2407 """
2407 """
2408 changesets += tuple(opts.get('rev', []))
2408 changesets += tuple(opts.get('rev', []))
2409 if not changesets:
2409 if not changesets:
2410 raise util.Abort(_("export requires at least one changeset"))
2410 raise util.Abort(_("export requires at least one changeset"))
2411 revs = scmutil.revrange(repo, changesets)
2411 revs = scmutil.revrange(repo, changesets)
2412 if len(revs) > 1:
2412 if len(revs) > 1:
2413 ui.note(_('exporting patches:\n'))
2413 ui.note(_('exporting patches:\n'))
2414 else:
2414 else:
2415 ui.note(_('exporting patch:\n'))
2415 ui.note(_('exporting patch:\n'))
2416 cmdutil.export(repo, revs, template=opts.get('output'),
2416 cmdutil.export(repo, revs, template=opts.get('output'),
2417 switch_parent=opts.get('switch_parent'),
2417 switch_parent=opts.get('switch_parent'),
2418 opts=patch.diffopts(ui, opts))
2418 opts=patch.diffopts(ui, opts))
2419
2419
2420 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2420 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2421 def forget(ui, repo, *pats, **opts):
2421 def forget(ui, repo, *pats, **opts):
2422 """forget the specified files on the next commit
2422 """forget the specified files on the next commit
2423
2423
2424 Mark the specified files so they will no longer be tracked
2424 Mark the specified files so they will no longer be tracked
2425 after the next commit.
2425 after the next commit.
2426
2426
2427 This only removes files from the current branch, not from the
2427 This only removes files from the current branch, not from the
2428 entire project history, and it does not delete them from the
2428 entire project history, and it does not delete them from the
2429 working directory.
2429 working directory.
2430
2430
2431 To undo a forget before the next commit, see :hg:`add`.
2431 To undo a forget before the next commit, see :hg:`add`.
2432
2432
2433 .. container:: verbose
2433 .. container:: verbose
2434
2434
2435 Examples:
2435 Examples:
2436
2436
2437 - forget newly-added binary files::
2437 - forget newly-added binary files::
2438
2438
2439 hg forget "set:added() and binary()"
2439 hg forget "set:added() and binary()"
2440
2440
2441 - forget files that would be excluded by .hgignore::
2441 - forget files that would be excluded by .hgignore::
2442
2442
2443 hg forget "set:hgignore()"
2443 hg forget "set:hgignore()"
2444
2444
2445 Returns 0 on success.
2445 Returns 0 on success.
2446 """
2446 """
2447
2447
2448 if not pats:
2448 if not pats:
2449 raise util.Abort(_('no files specified'))
2449 raise util.Abort(_('no files specified'))
2450
2450
2451 m = scmutil.match(repo[None], pats, opts)
2451 m = scmutil.match(repo[None], pats, opts)
2452 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2452 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2453 return rejected and 1 or 0
2453 return rejected and 1 or 0
2454
2454
2455 @command(
2455 @command(
2456 'graft',
2456 'graft',
2457 [('c', 'continue', False, _('resume interrupted graft')),
2457 [('c', 'continue', False, _('resume interrupted graft')),
2458 ('e', 'edit', False, _('invoke editor on commit messages')),
2458 ('e', 'edit', False, _('invoke editor on commit messages')),
2459 ('D', 'currentdate', False,
2459 ('D', 'currentdate', False,
2460 _('record the current date as commit date')),
2460 _('record the current date as commit date')),
2461 ('U', 'currentuser', False,
2461 ('U', 'currentuser', False,
2462 _('record the current user as committer'), _('DATE'))]
2462 _('record the current user as committer'), _('DATE'))]
2463 + commitopts2 + mergetoolopts,
2463 + commitopts2 + mergetoolopts,
2464 _('[OPTION]... REVISION...'))
2464 _('[OPTION]... REVISION...'))
2465 def graft(ui, repo, *revs, **opts):
2465 def graft(ui, repo, *revs, **opts):
2466 '''copy changes from other branches onto the current branch
2466 '''copy changes from other branches onto the current branch
2467
2467
2468 This command uses Mercurial's merge logic to copy individual
2468 This command uses Mercurial's merge logic to copy individual
2469 changes from other branches without merging branches in the
2469 changes from other branches without merging branches in the
2470 history graph. This is sometimes known as 'backporting' or
2470 history graph. This is sometimes known as 'backporting' or
2471 'cherry-picking'. By default, graft will copy user, date, and
2471 'cherry-picking'. By default, graft will copy user, date, and
2472 description from the source changesets.
2472 description from the source changesets.
2473
2473
2474 Changesets that are ancestors of the current revision, that have
2474 Changesets that are ancestors of the current revision, that have
2475 already been grafted, or that are merges will be skipped.
2475 already been grafted, or that are merges will be skipped.
2476
2476
2477 If a graft merge results in conflicts, the graft process is
2477 If a graft merge results in conflicts, the graft process is
2478 interrupted so that the current merge can be manually resolved.
2478 interrupted so that the current merge can be manually resolved.
2479 Once all conflicts are addressed, the graft process can be
2479 Once all conflicts are addressed, the graft process can be
2480 continued with the -c/--continue option.
2480 continued with the -c/--continue option.
2481
2481
2482 .. note::
2482 .. note::
2483 The -c/--continue option does not reapply earlier options.
2483 The -c/--continue option does not reapply earlier options.
2484
2484
2485 .. container:: verbose
2485 .. container:: verbose
2486
2486
2487 Examples:
2487 Examples:
2488
2488
2489 - copy a single change to the stable branch and edit its description::
2489 - copy a single change to the stable branch and edit its description::
2490
2490
2491 hg update stable
2491 hg update stable
2492 hg graft --edit 9393
2492 hg graft --edit 9393
2493
2493
2494 - graft a range of changesets with one exception, updating dates::
2494 - graft a range of changesets with one exception, updating dates::
2495
2495
2496 hg graft -D "2085::2093 and not 2091"
2496 hg graft -D "2085::2093 and not 2091"
2497
2497
2498 - continue a graft after resolving conflicts::
2498 - continue a graft after resolving conflicts::
2499
2499
2500 hg graft -c
2500 hg graft -c
2501
2501
2502 - show the source of a grafted changeset::
2502 - show the source of a grafted changeset::
2503
2503
2504 hg log --debug -r tip
2504 hg log --debug -r tip
2505
2505
2506 Returns 0 on successful completion.
2506 Returns 0 on successful completion.
2507 '''
2507 '''
2508
2508
2509 if not opts.get('user') and opts.get('currentuser'):
2509 if not opts.get('user') and opts.get('currentuser'):
2510 opts['user'] = ui.username()
2510 opts['user'] = ui.username()
2511 if not opts.get('date') and opts.get('currentdate'):
2511 if not opts.get('date') and opts.get('currentdate'):
2512 opts['date'] = "%d %d" % util.makedate()
2512 opts['date'] = "%d %d" % util.makedate()
2513
2513
2514 editor = None
2514 editor = None
2515 if opts.get('edit'):
2515 if opts.get('edit'):
2516 editor = cmdutil.commitforceeditor
2516 editor = cmdutil.commitforceeditor
2517
2517
2518 cont = False
2518 cont = False
2519 if opts['continue']:
2519 if opts['continue']:
2520 cont = True
2520 cont = True
2521 if revs:
2521 if revs:
2522 raise util.Abort(_("can't specify --continue and revisions"))
2522 raise util.Abort(_("can't specify --continue and revisions"))
2523 # read in unfinished revisions
2523 # read in unfinished revisions
2524 try:
2524 try:
2525 nodes = repo.opener.read('graftstate').splitlines()
2525 nodes = repo.opener.read('graftstate').splitlines()
2526 revs = [repo[node].rev() for node in nodes]
2526 revs = [repo[node].rev() for node in nodes]
2527 except IOError, inst:
2527 except IOError, inst:
2528 if inst.errno != errno.ENOENT:
2528 if inst.errno != errno.ENOENT:
2529 raise
2529 raise
2530 raise util.Abort(_("no graft state found, can't continue"))
2530 raise util.Abort(_("no graft state found, can't continue"))
2531 else:
2531 else:
2532 cmdutil.bailifchanged(repo)
2532 cmdutil.bailifchanged(repo)
2533 if not revs:
2533 if not revs:
2534 raise util.Abort(_('no revisions specified'))
2534 raise util.Abort(_('no revisions specified'))
2535 revs = scmutil.revrange(repo, revs)
2535 revs = scmutil.revrange(repo, revs)
2536
2536
2537 # check for merges
2537 # check for merges
2538 for rev in repo.revs('%ld and merge()', revs):
2538 for rev in repo.revs('%ld and merge()', revs):
2539 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2539 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2540 revs.remove(rev)
2540 revs.remove(rev)
2541 if not revs:
2541 if not revs:
2542 return -1
2542 return -1
2543
2543
2544 # check for ancestors of dest branch
2544 # check for ancestors of dest branch
2545 for rev in repo.revs('::. and %ld', revs):
2545 for rev in repo.revs('::. and %ld', revs):
2546 ui.warn(_('skipping ancestor revision %s\n') % rev)
2546 ui.warn(_('skipping ancestor revision %s\n') % rev)
2547 revs.remove(rev)
2547 revs.remove(rev)
2548 if not revs:
2548 if not revs:
2549 return -1
2549 return -1
2550
2550
2551 # analyze revs for earlier grafts
2551 # analyze revs for earlier grafts
2552 ids = {}
2552 ids = {}
2553 for ctx in repo.set("%ld", revs):
2553 for ctx in repo.set("%ld", revs):
2554 ids[ctx.hex()] = ctx.rev()
2554 ids[ctx.hex()] = ctx.rev()
2555 n = ctx.extra().get('source')
2555 n = ctx.extra().get('source')
2556 if n:
2556 if n:
2557 ids[n] = ctx.rev()
2557 ids[n] = ctx.rev()
2558
2558
2559 # check ancestors for earlier grafts
2559 # check ancestors for earlier grafts
2560 ui.debug('scanning for duplicate grafts\n')
2560 ui.debug('scanning for duplicate grafts\n')
2561 for ctx in repo.set("::. - ::%ld", revs):
2561 for ctx in repo.set("::. - ::%ld", revs):
2562 n = ctx.extra().get('source')
2562 n = ctx.extra().get('source')
2563 if n in ids:
2563 if n in ids:
2564 r = repo[n].rev()
2564 r = repo[n].rev()
2565 if r in revs:
2565 if r in revs:
2566 ui.warn(_('skipping already grafted revision %s\n') % r)
2566 ui.warn(_('skipping already grafted revision %s\n') % r)
2567 revs.remove(r)
2567 revs.remove(r)
2568 elif ids[n] in revs:
2568 elif ids[n] in revs:
2569 ui.warn(_('skipping already grafted revision %s '
2569 ui.warn(_('skipping already grafted revision %s '
2570 '(same origin %d)\n') % (ids[n], r))
2570 '(same origin %d)\n') % (ids[n], r))
2571 revs.remove(ids[n])
2571 revs.remove(ids[n])
2572 elif ctx.hex() in ids:
2572 elif ctx.hex() in ids:
2573 r = ids[ctx.hex()]
2573 r = ids[ctx.hex()]
2574 ui.warn(_('skipping already grafted revision %s '
2574 ui.warn(_('skipping already grafted revision %s '
2575 '(was grafted from %d)\n') % (r, ctx.rev()))
2575 '(was grafted from %d)\n') % (r, ctx.rev()))
2576 revs.remove(r)
2576 revs.remove(r)
2577 if not revs:
2577 if not revs:
2578 return -1
2578 return -1
2579
2579
2580 for pos, ctx in enumerate(repo.set("%ld", revs)):
2580 for pos, ctx in enumerate(repo.set("%ld", revs)):
2581 current = repo['.']
2581 current = repo['.']
2582 ui.status(_('grafting revision %s\n') % ctx.rev())
2582 ui.status(_('grafting revision %s\n') % ctx.rev())
2583
2583
2584 # we don't merge the first commit when continuing
2584 # we don't merge the first commit when continuing
2585 if not cont:
2585 if not cont:
2586 # perform the graft merge with p1(rev) as 'ancestor'
2586 # perform the graft merge with p1(rev) as 'ancestor'
2587 try:
2587 try:
2588 # ui.forcemerge is an internal variable, do not document
2588 # ui.forcemerge is an internal variable, do not document
2589 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2589 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2590 stats = mergemod.update(repo, ctx.node(), True, True, False,
2590 stats = mergemod.update(repo, ctx.node(), True, True, False,
2591 ctx.p1().node())
2591 ctx.p1().node())
2592 finally:
2592 finally:
2593 ui.setconfig('ui', 'forcemerge', '')
2593 ui.setconfig('ui', 'forcemerge', '')
2594 # drop the second merge parent
2594 # drop the second merge parent
2595 repo.dirstate.setparents(current.node(), nullid)
2595 repo.dirstate.setparents(current.node(), nullid)
2596 repo.dirstate.write()
2596 repo.dirstate.write()
2597 # fix up dirstate for copies and renames
2597 # fix up dirstate for copies and renames
2598 cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
2598 cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
2599 # report any conflicts
2599 # report any conflicts
2600 if stats and stats[3] > 0:
2600 if stats and stats[3] > 0:
2601 # write out state for --continue
2601 # write out state for --continue
2602 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2602 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2603 repo.opener.write('graftstate', ''.join(nodelines))
2603 repo.opener.write('graftstate', ''.join(nodelines))
2604 raise util.Abort(
2604 raise util.Abort(
2605 _("unresolved conflicts, can't continue"),
2605 _("unresolved conflicts, can't continue"),
2606 hint=_('use hg resolve and hg graft --continue'))
2606 hint=_('use hg resolve and hg graft --continue'))
2607 else:
2607 else:
2608 cont = False
2608 cont = False
2609
2609
2610 # commit
2610 # commit
2611 source = ctx.extra().get('source')
2611 source = ctx.extra().get('source')
2612 if not source:
2612 if not source:
2613 source = ctx.hex()
2613 source = ctx.hex()
2614 extra = {'source': source}
2614 extra = {'source': source}
2615 user = ctx.user()
2615 user = ctx.user()
2616 if opts.get('user'):
2616 if opts.get('user'):
2617 user = opts['user']
2617 user = opts['user']
2618 date = ctx.date()
2618 date = ctx.date()
2619 if opts.get('date'):
2619 if opts.get('date'):
2620 date = opts['date']
2620 date = opts['date']
2621 repo.commit(text=ctx.description(), user=user,
2621 repo.commit(text=ctx.description(), user=user,
2622 date=date, extra=extra, editor=editor)
2622 date=date, extra=extra, editor=editor)
2623
2623
2624 # remove state when we complete successfully
2624 # remove state when we complete successfully
2625 if os.path.exists(repo.join('graftstate')):
2625 if os.path.exists(repo.join('graftstate')):
2626 util.unlinkpath(repo.join('graftstate'))
2626 util.unlinkpath(repo.join('graftstate'))
2627
2627
2628 return 0
2628 return 0
2629
2629
2630 @command('grep',
2630 @command('grep',
2631 [('0', 'print0', None, _('end fields with NUL')),
2631 [('0', 'print0', None, _('end fields with NUL')),
2632 ('', 'all', None, _('print all revisions that match')),
2632 ('', 'all', None, _('print all revisions that match')),
2633 ('a', 'text', None, _('treat all files as text')),
2633 ('a', 'text', None, _('treat all files as text')),
2634 ('f', 'follow', None,
2634 ('f', 'follow', None,
2635 _('follow changeset history,'
2635 _('follow changeset history,'
2636 ' or file history across copies and renames')),
2636 ' or file history across copies and renames')),
2637 ('i', 'ignore-case', None, _('ignore case when matching')),
2637 ('i', 'ignore-case', None, _('ignore case when matching')),
2638 ('l', 'files-with-matches', None,
2638 ('l', 'files-with-matches', None,
2639 _('print only filenames and revisions that match')),
2639 _('print only filenames and revisions that match')),
2640 ('n', 'line-number', None, _('print matching line numbers')),
2640 ('n', 'line-number', None, _('print matching line numbers')),
2641 ('r', 'rev', [],
2641 ('r', 'rev', [],
2642 _('only search files changed within revision range'), _('REV')),
2642 _('only search files changed within revision range'), _('REV')),
2643 ('u', 'user', None, _('list the author (long with -v)')),
2643 ('u', 'user', None, _('list the author (long with -v)')),
2644 ('d', 'date', None, _('list the date (short with -q)')),
2644 ('d', 'date', None, _('list the date (short with -q)')),
2645 ] + walkopts,
2645 ] + walkopts,
2646 _('[OPTION]... PATTERN [FILE]...'))
2646 _('[OPTION]... PATTERN [FILE]...'))
2647 def grep(ui, repo, pattern, *pats, **opts):
2647 def grep(ui, repo, pattern, *pats, **opts):
2648 """search for a pattern in specified files and revisions
2648 """search for a pattern in specified files and revisions
2649
2649
2650 Search revisions of files for a regular expression.
2650 Search revisions of files for a regular expression.
2651
2651
2652 This command behaves differently than Unix grep. It only accepts
2652 This command behaves differently than Unix grep. It only accepts
2653 Python/Perl regexps. It searches repository history, not the
2653 Python/Perl regexps. It searches repository history, not the
2654 working directory. It always prints the revision number in which a
2654 working directory. It always prints the revision number in which a
2655 match appears.
2655 match appears.
2656
2656
2657 By default, grep only prints output for the first revision of a
2657 By default, grep only prints output for the first revision of a
2658 file in which it finds a match. To get it to print every revision
2658 file in which it finds a match. To get it to print every revision
2659 that contains a change in match status ("-" for a match that
2659 that contains a change in match status ("-" for a match that
2660 becomes a non-match, or "+" for a non-match that becomes a match),
2660 becomes a non-match, or "+" for a non-match that becomes a match),
2661 use the --all flag.
2661 use the --all flag.
2662
2662
2663 Returns 0 if a match is found, 1 otherwise.
2663 Returns 0 if a match is found, 1 otherwise.
2664 """
2664 """
2665 reflags = re.M
2665 reflags = re.M
2666 if opts.get('ignore_case'):
2666 if opts.get('ignore_case'):
2667 reflags |= re.I
2667 reflags |= re.I
2668 try:
2668 try:
2669 regexp = re.compile(pattern, reflags)
2669 regexp = re.compile(pattern, reflags)
2670 except re.error, inst:
2670 except re.error, inst:
2671 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2671 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2672 return 1
2672 return 1
2673 sep, eol = ':', '\n'
2673 sep, eol = ':', '\n'
2674 if opts.get('print0'):
2674 if opts.get('print0'):
2675 sep = eol = '\0'
2675 sep = eol = '\0'
2676
2676
2677 getfile = util.lrucachefunc(repo.file)
2677 getfile = util.lrucachefunc(repo.file)
2678
2678
2679 def matchlines(body):
2679 def matchlines(body):
2680 begin = 0
2680 begin = 0
2681 linenum = 0
2681 linenum = 0
2682 while True:
2682 while True:
2683 match = regexp.search(body, begin)
2683 match = regexp.search(body, begin)
2684 if not match:
2684 if not match:
2685 break
2685 break
2686 mstart, mend = match.span()
2686 mstart, mend = match.span()
2687 linenum += body.count('\n', begin, mstart) + 1
2687 linenum += body.count('\n', begin, mstart) + 1
2688 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2688 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2689 begin = body.find('\n', mend) + 1 or len(body) + 1
2689 begin = body.find('\n', mend) + 1 or len(body) + 1
2690 lend = begin - 1
2690 lend = begin - 1
2691 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2691 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2692
2692
2693 class linestate(object):
2693 class linestate(object):
2694 def __init__(self, line, linenum, colstart, colend):
2694 def __init__(self, line, linenum, colstart, colend):
2695 self.line = line
2695 self.line = line
2696 self.linenum = linenum
2696 self.linenum = linenum
2697 self.colstart = colstart
2697 self.colstart = colstart
2698 self.colend = colend
2698 self.colend = colend
2699
2699
2700 def __hash__(self):
2700 def __hash__(self):
2701 return hash((self.linenum, self.line))
2701 return hash((self.linenum, self.line))
2702
2702
2703 def __eq__(self, other):
2703 def __eq__(self, other):
2704 return self.line == other.line
2704 return self.line == other.line
2705
2705
2706 matches = {}
2706 matches = {}
2707 copies = {}
2707 copies = {}
2708 def grepbody(fn, rev, body):
2708 def grepbody(fn, rev, body):
2709 matches[rev].setdefault(fn, [])
2709 matches[rev].setdefault(fn, [])
2710 m = matches[rev][fn]
2710 m = matches[rev][fn]
2711 for lnum, cstart, cend, line in matchlines(body):
2711 for lnum, cstart, cend, line in matchlines(body):
2712 s = linestate(line, lnum, cstart, cend)
2712 s = linestate(line, lnum, cstart, cend)
2713 m.append(s)
2713 m.append(s)
2714
2714
2715 def difflinestates(a, b):
2715 def difflinestates(a, b):
2716 sm = difflib.SequenceMatcher(None, a, b)
2716 sm = difflib.SequenceMatcher(None, a, b)
2717 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2717 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2718 if tag == 'insert':
2718 if tag == 'insert':
2719 for i in xrange(blo, bhi):
2719 for i in xrange(blo, bhi):
2720 yield ('+', b[i])
2720 yield ('+', b[i])
2721 elif tag == 'delete':
2721 elif tag == 'delete':
2722 for i in xrange(alo, ahi):
2722 for i in xrange(alo, ahi):
2723 yield ('-', a[i])
2723 yield ('-', a[i])
2724 elif tag == 'replace':
2724 elif tag == 'replace':
2725 for i in xrange(alo, ahi):
2725 for i in xrange(alo, ahi):
2726 yield ('-', a[i])
2726 yield ('-', a[i])
2727 for i in xrange(blo, bhi):
2727 for i in xrange(blo, bhi):
2728 yield ('+', b[i])
2728 yield ('+', b[i])
2729
2729
2730 def display(fn, ctx, pstates, states):
2730 def display(fn, ctx, pstates, states):
2731 rev = ctx.rev()
2731 rev = ctx.rev()
2732 datefunc = ui.quiet and util.shortdate or util.datestr
2732 datefunc = ui.quiet and util.shortdate or util.datestr
2733 found = False
2733 found = False
2734 filerevmatches = {}
2734 filerevmatches = {}
2735 def binary():
2735 def binary():
2736 flog = getfile(fn)
2736 flog = getfile(fn)
2737 return util.binary(flog.read(ctx.filenode(fn)))
2737 return util.binary(flog.read(ctx.filenode(fn)))
2738
2738
2739 if opts.get('all'):
2739 if opts.get('all'):
2740 iter = difflinestates(pstates, states)
2740 iter = difflinestates(pstates, states)
2741 else:
2741 else:
2742 iter = [('', l) for l in states]
2742 iter = [('', l) for l in states]
2743 for change, l in iter:
2743 for change, l in iter:
2744 cols = [fn, str(rev)]
2744 cols = [fn, str(rev)]
2745 before, match, after = None, None, None
2745 before, match, after = None, None, None
2746 if opts.get('line_number'):
2746 if opts.get('line_number'):
2747 cols.append(str(l.linenum))
2747 cols.append(str(l.linenum))
2748 if opts.get('all'):
2748 if opts.get('all'):
2749 cols.append(change)
2749 cols.append(change)
2750 if opts.get('user'):
2750 if opts.get('user'):
2751 cols.append(ui.shortuser(ctx.user()))
2751 cols.append(ui.shortuser(ctx.user()))
2752 if opts.get('date'):
2752 if opts.get('date'):
2753 cols.append(datefunc(ctx.date()))
2753 cols.append(datefunc(ctx.date()))
2754 if opts.get('files_with_matches'):
2754 if opts.get('files_with_matches'):
2755 c = (fn, rev)
2755 c = (fn, rev)
2756 if c in filerevmatches:
2756 if c in filerevmatches:
2757 continue
2757 continue
2758 filerevmatches[c] = 1
2758 filerevmatches[c] = 1
2759 else:
2759 else:
2760 before = l.line[:l.colstart]
2760 before = l.line[:l.colstart]
2761 match = l.line[l.colstart:l.colend]
2761 match = l.line[l.colstart:l.colend]
2762 after = l.line[l.colend:]
2762 after = l.line[l.colend:]
2763 ui.write(sep.join(cols))
2763 ui.write(sep.join(cols))
2764 if before is not None:
2764 if before is not None:
2765 if not opts.get('text') and binary():
2765 if not opts.get('text') and binary():
2766 ui.write(sep + " Binary file matches")
2766 ui.write(sep + " Binary file matches")
2767 else:
2767 else:
2768 ui.write(sep + before)
2768 ui.write(sep + before)
2769 ui.write(match, label='grep.match')
2769 ui.write(match, label='grep.match')
2770 ui.write(after)
2770 ui.write(after)
2771 ui.write(eol)
2771 ui.write(eol)
2772 found = True
2772 found = True
2773 return found
2773 return found
2774
2774
2775 skip = {}
2775 skip = {}
2776 revfiles = {}
2776 revfiles = {}
2777 matchfn = scmutil.match(repo[None], pats, opts)
2777 matchfn = scmutil.match(repo[None], pats, opts)
2778 found = False
2778 found = False
2779 follow = opts.get('follow')
2779 follow = opts.get('follow')
2780
2780
2781 def prep(ctx, fns):
2781 def prep(ctx, fns):
2782 rev = ctx.rev()
2782 rev = ctx.rev()
2783 pctx = ctx.p1()
2783 pctx = ctx.p1()
2784 parent = pctx.rev()
2784 parent = pctx.rev()
2785 matches.setdefault(rev, {})
2785 matches.setdefault(rev, {})
2786 matches.setdefault(parent, {})
2786 matches.setdefault(parent, {})
2787 files = revfiles.setdefault(rev, [])
2787 files = revfiles.setdefault(rev, [])
2788 for fn in fns:
2788 for fn in fns:
2789 flog = getfile(fn)
2789 flog = getfile(fn)
2790 try:
2790 try:
2791 fnode = ctx.filenode(fn)
2791 fnode = ctx.filenode(fn)
2792 except error.LookupError:
2792 except error.LookupError:
2793 continue
2793 continue
2794
2794
2795 copied = flog.renamed(fnode)
2795 copied = flog.renamed(fnode)
2796 copy = follow and copied and copied[0]
2796 copy = follow and copied and copied[0]
2797 if copy:
2797 if copy:
2798 copies.setdefault(rev, {})[fn] = copy
2798 copies.setdefault(rev, {})[fn] = copy
2799 if fn in skip:
2799 if fn in skip:
2800 if copy:
2800 if copy:
2801 skip[copy] = True
2801 skip[copy] = True
2802 continue
2802 continue
2803 files.append(fn)
2803 files.append(fn)
2804
2804
2805 if fn not in matches[rev]:
2805 if fn not in matches[rev]:
2806 grepbody(fn, rev, flog.read(fnode))
2806 grepbody(fn, rev, flog.read(fnode))
2807
2807
2808 pfn = copy or fn
2808 pfn = copy or fn
2809 if pfn not in matches[parent]:
2809 if pfn not in matches[parent]:
2810 try:
2810 try:
2811 fnode = pctx.filenode(pfn)
2811 fnode = pctx.filenode(pfn)
2812 grepbody(pfn, parent, flog.read(fnode))
2812 grepbody(pfn, parent, flog.read(fnode))
2813 except error.LookupError:
2813 except error.LookupError:
2814 pass
2814 pass
2815
2815
2816 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2816 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2817 rev = ctx.rev()
2817 rev = ctx.rev()
2818 parent = ctx.p1().rev()
2818 parent = ctx.p1().rev()
2819 for fn in sorted(revfiles.get(rev, [])):
2819 for fn in sorted(revfiles.get(rev, [])):
2820 states = matches[rev][fn]
2820 states = matches[rev][fn]
2821 copy = copies.get(rev, {}).get(fn)
2821 copy = copies.get(rev, {}).get(fn)
2822 if fn in skip:
2822 if fn in skip:
2823 if copy:
2823 if copy:
2824 skip[copy] = True
2824 skip[copy] = True
2825 continue
2825 continue
2826 pstates = matches.get(parent, {}).get(copy or fn, [])
2826 pstates = matches.get(parent, {}).get(copy or fn, [])
2827 if pstates or states:
2827 if pstates or states:
2828 r = display(fn, ctx, pstates, states)
2828 r = display(fn, ctx, pstates, states)
2829 found = found or r
2829 found = found or r
2830 if r and not opts.get('all'):
2830 if r and not opts.get('all'):
2831 skip[fn] = True
2831 skip[fn] = True
2832 if copy:
2832 if copy:
2833 skip[copy] = True
2833 skip[copy] = True
2834 del matches[rev]
2834 del matches[rev]
2835 del revfiles[rev]
2835 del revfiles[rev]
2836
2836
2837 return not found
2837 return not found
2838
2838
2839 @command('heads',
2839 @command('heads',
2840 [('r', 'rev', '',
2840 [('r', 'rev', '',
2841 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2841 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2842 ('t', 'topo', False, _('show topological heads only')),
2842 ('t', 'topo', False, _('show topological heads only')),
2843 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2843 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2844 ('c', 'closed', False, _('show normal and closed branch heads')),
2844 ('c', 'closed', False, _('show normal and closed branch heads')),
2845 ] + templateopts,
2845 ] + templateopts,
2846 _('[-ac] [-r STARTREV] [REV]...'))
2846 _('[-ac] [-r STARTREV] [REV]...'))
2847 def heads(ui, repo, *branchrevs, **opts):
2847 def heads(ui, repo, *branchrevs, **opts):
2848 """show current repository heads or show branch heads
2848 """show current repository heads or show branch heads
2849
2849
2850 With no arguments, show all repository branch heads.
2850 With no arguments, show all repository branch heads.
2851
2851
2852 Repository "heads" are changesets with no child changesets. They are
2852 Repository "heads" are changesets with no child changesets. They are
2853 where development generally takes place and are the usual targets
2853 where development generally takes place and are the usual targets
2854 for update and merge operations. Branch heads are changesets that have
2854 for update and merge operations. Branch heads are changesets that have
2855 no child changeset on the same branch.
2855 no child changeset on the same branch.
2856
2856
2857 If one or more REVs are given, only branch heads on the branches
2857 If one or more REVs are given, only branch heads on the branches
2858 associated with the specified changesets are shown. This means
2858 associated with the specified changesets are shown. This means
2859 that you can use :hg:`heads foo` to see the heads on a branch
2859 that you can use :hg:`heads foo` to see the heads on a branch
2860 named ``foo``.
2860 named ``foo``.
2861
2861
2862 If -c/--closed is specified, also show branch heads marked closed
2862 If -c/--closed is specified, also show branch heads marked closed
2863 (see :hg:`commit --close-branch`).
2863 (see :hg:`commit --close-branch`).
2864
2864
2865 If STARTREV is specified, only those heads that are descendants of
2865 If STARTREV is specified, only those heads that are descendants of
2866 STARTREV will be displayed.
2866 STARTREV will be displayed.
2867
2867
2868 If -t/--topo is specified, named branch mechanics will be ignored and only
2868 If -t/--topo is specified, named branch mechanics will be ignored and only
2869 changesets without children will be shown.
2869 changesets without children will be shown.
2870
2870
2871 Returns 0 if matching heads are found, 1 if not.
2871 Returns 0 if matching heads are found, 1 if not.
2872 """
2872 """
2873
2873
2874 start = None
2874 start = None
2875 if 'rev' in opts:
2875 if 'rev' in opts:
2876 start = scmutil.revsingle(repo, opts['rev'], None).node()
2876 start = scmutil.revsingle(repo, opts['rev'], None).node()
2877
2877
2878 if opts.get('topo'):
2878 if opts.get('topo'):
2879 heads = [repo[h] for h in repo.heads(start)]
2879 heads = [repo[h] for h in repo.heads(start)]
2880 else:
2880 else:
2881 heads = []
2881 heads = []
2882 for branch in repo.branchmap():
2882 for branch in repo.branchmap():
2883 heads += repo.branchheads(branch, start, opts.get('closed'))
2883 heads += repo.branchheads(branch, start, opts.get('closed'))
2884 heads = [repo[h] for h in heads]
2884 heads = [repo[h] for h in heads]
2885
2885
2886 if branchrevs:
2886 if branchrevs:
2887 branches = set(repo[br].branch() for br in branchrevs)
2887 branches = set(repo[br].branch() for br in branchrevs)
2888 heads = [h for h in heads if h.branch() in branches]
2888 heads = [h for h in heads if h.branch() in branches]
2889
2889
2890 if opts.get('active') and branchrevs:
2890 if opts.get('active') and branchrevs:
2891 dagheads = repo.heads(start)
2891 dagheads = repo.heads(start)
2892 heads = [h for h in heads if h.node() in dagheads]
2892 heads = [h for h in heads if h.node() in dagheads]
2893
2893
2894 if branchrevs:
2894 if branchrevs:
2895 haveheads = set(h.branch() for h in heads)
2895 haveheads = set(h.branch() for h in heads)
2896 if branches - haveheads:
2896 if branches - haveheads:
2897 headless = ', '.join(b for b in branches - haveheads)
2897 headless = ', '.join(b for b in branches - haveheads)
2898 msg = _('no open branch heads found on branches %s')
2898 msg = _('no open branch heads found on branches %s')
2899 if opts.get('rev'):
2899 if opts.get('rev'):
2900 msg += _(' (started at %s)' % opts['rev'])
2900 msg += _(' (started at %s)' % opts['rev'])
2901 ui.warn((msg + '\n') % headless)
2901 ui.warn((msg + '\n') % headless)
2902
2902
2903 if not heads:
2903 if not heads:
2904 return 1
2904 return 1
2905
2905
2906 heads = sorted(heads, key=lambda x: -x.rev())
2906 heads = sorted(heads, key=lambda x: -x.rev())
2907 displayer = cmdutil.show_changeset(ui, repo, opts)
2907 displayer = cmdutil.show_changeset(ui, repo, opts)
2908 for ctx in heads:
2908 for ctx in heads:
2909 displayer.show(ctx)
2909 displayer.show(ctx)
2910 displayer.close()
2910 displayer.close()
2911
2911
2912 @command('help',
2912 @command('help',
2913 [('e', 'extension', None, _('show only help for extensions')),
2913 [('e', 'extension', None, _('show only help for extensions')),
2914 ('c', 'command', None, _('show only help for commands'))],
2914 ('c', 'command', None, _('show only help for commands'))],
2915 _('[-ec] [TOPIC]'))
2915 _('[-ec] [TOPIC]'))
2916 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2916 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2917 """show help for a given topic or a help overview
2917 """show help for a given topic or a help overview
2918
2918
2919 With no arguments, print a list of commands with short help messages.
2919 With no arguments, print a list of commands with short help messages.
2920
2920
2921 Given a topic, extension, or command name, print help for that
2921 Given a topic, extension, or command name, print help for that
2922 topic.
2922 topic.
2923
2923
2924 Returns 0 if successful.
2924 Returns 0 if successful.
2925 """
2925 """
2926
2926
2927 textwidth = min(ui.termwidth(), 80) - 2
2927 textwidth = min(ui.termwidth(), 80) - 2
2928
2928
2929 def optrst(options):
2929 def optrst(options):
2930 data = []
2930 data = []
2931 multioccur = False
2931 multioccur = False
2932 for option in options:
2932 for option in options:
2933 if len(option) == 5:
2933 if len(option) == 5:
2934 shortopt, longopt, default, desc, optlabel = option
2934 shortopt, longopt, default, desc, optlabel = option
2935 else:
2935 else:
2936 shortopt, longopt, default, desc = option
2936 shortopt, longopt, default, desc = option
2937 optlabel = _("VALUE") # default label
2937 optlabel = _("VALUE") # default label
2938
2938
2939 if _("DEPRECATED") in desc and not ui.verbose:
2939 if _("DEPRECATED") in desc and not ui.verbose:
2940 continue
2940 continue
2941
2941
2942 so = ''
2942 so = ''
2943 if shortopt:
2943 if shortopt:
2944 so = '-' + shortopt
2944 so = '-' + shortopt
2945 lo = '--' + longopt
2945 lo = '--' + longopt
2946 if default:
2946 if default:
2947 desc += _(" (default: %s)") % default
2947 desc += _(" (default: %s)") % default
2948
2948
2949 if isinstance(default, list):
2949 if isinstance(default, list):
2950 lo += " %s [+]" % optlabel
2950 lo += " %s [+]" % optlabel
2951 multioccur = True
2951 multioccur = True
2952 elif (default is not None) and not isinstance(default, bool):
2952 elif (default is not None) and not isinstance(default, bool):
2953 lo += " %s" % optlabel
2953 lo += " %s" % optlabel
2954
2954
2955 data.append((so, lo, desc))
2955 data.append((so, lo, desc))
2956
2956
2957 rst = minirst.maketable(data, 1)
2957 rst = minirst.maketable(data, 1)
2958
2958
2959 if multioccur:
2959 if multioccur:
2960 rst += _("\n[+] marked option can be specified multiple times\n")
2960 rst += _("\n[+] marked option can be specified multiple times\n")
2961
2961
2962 return rst
2962 return rst
2963
2963
2964 # list all option lists
2964 # list all option lists
2965 def opttext(optlist, width):
2965 def opttext(optlist, width):
2966 rst = ''
2966 rst = ''
2967 if not optlist:
2967 if not optlist:
2968 return ''
2968 return ''
2969
2969
2970 for title, options in optlist:
2970 for title, options in optlist:
2971 rst += '\n%s\n' % title
2971 rst += '\n%s\n' % title
2972 if options:
2972 if options:
2973 rst += "\n"
2973 rst += "\n"
2974 rst += optrst(options)
2974 rst += optrst(options)
2975 rst += '\n'
2975 rst += '\n'
2976
2976
2977 return '\n' + minirst.format(rst, width)
2977 return '\n' + minirst.format(rst, width)
2978
2978
2979 def addglobalopts(optlist, aliases):
2979 def addglobalopts(optlist, aliases):
2980 if ui.quiet:
2980 if ui.quiet:
2981 return []
2981 return []
2982
2982
2983 if ui.verbose:
2983 if ui.verbose:
2984 optlist.append((_("global options:"), globalopts))
2984 optlist.append((_("global options:"), globalopts))
2985 if name == 'shortlist':
2985 if name == 'shortlist':
2986 optlist.append((_('use "hg help" for the full list '
2986 optlist.append((_('use "hg help" for the full list '
2987 'of commands'), ()))
2987 'of commands'), ()))
2988 else:
2988 else:
2989 if name == 'shortlist':
2989 if name == 'shortlist':
2990 msg = _('use "hg help" for the full list of commands '
2990 msg = _('use "hg help" for the full list of commands '
2991 'or "hg -v" for details')
2991 'or "hg -v" for details')
2992 elif name and not full:
2992 elif name and not full:
2993 msg = _('use "hg help %s" to show the full help text' % name)
2993 msg = _('use "hg help %s" to show the full help text' % name)
2994 elif aliases:
2994 elif aliases:
2995 msg = _('use "hg -v help%s" to show builtin aliases and '
2995 msg = _('use "hg -v help%s" to show builtin aliases and '
2996 'global options') % (name and " " + name or "")
2996 'global options') % (name and " " + name or "")
2997 else:
2997 else:
2998 msg = _('use "hg -v help %s" to show more info') % name
2998 msg = _('use "hg -v help %s" to show more info') % name
2999 optlist.append((msg, ()))
2999 optlist.append((msg, ()))
3000
3000
3001 def helpcmd(name):
3001 def helpcmd(name):
3002 try:
3002 try:
3003 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3003 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3004 except error.AmbiguousCommand, inst:
3004 except error.AmbiguousCommand, inst:
3005 # py3k fix: except vars can't be used outside the scope of the
3005 # py3k fix: except vars can't be used outside the scope of the
3006 # except block, nor can be used inside a lambda. python issue4617
3006 # except block, nor can be used inside a lambda. python issue4617
3007 prefix = inst.args[0]
3007 prefix = inst.args[0]
3008 select = lambda c: c.lstrip('^').startswith(prefix)
3008 select = lambda c: c.lstrip('^').startswith(prefix)
3009 helplist(select)
3009 helplist(select)
3010 return
3010 return
3011
3011
3012 # check if it's an invalid alias and display its error if it is
3012 # check if it's an invalid alias and display its error if it is
3013 if getattr(entry[0], 'badalias', False):
3013 if getattr(entry[0], 'badalias', False):
3014 if not unknowncmd:
3014 if not unknowncmd:
3015 entry[0](ui)
3015 entry[0](ui)
3016 return
3016 return
3017
3017
3018 rst = ""
3018 rst = ""
3019
3019
3020 # synopsis
3020 # synopsis
3021 if len(entry) > 2:
3021 if len(entry) > 2:
3022 if entry[2].startswith('hg'):
3022 if entry[2].startswith('hg'):
3023 rst += "%s\n" % entry[2]
3023 rst += "%s\n" % entry[2]
3024 else:
3024 else:
3025 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3025 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3026 else:
3026 else:
3027 rst += 'hg %s\n' % aliases[0]
3027 rst += 'hg %s\n' % aliases[0]
3028
3028
3029 # aliases
3029 # aliases
3030 if full and not ui.quiet and len(aliases) > 1:
3030 if full and not ui.quiet and len(aliases) > 1:
3031 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3031 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3032
3032
3033 # description
3033 # description
3034 doc = gettext(entry[0].__doc__)
3034 doc = gettext(entry[0].__doc__)
3035 if not doc:
3035 if not doc:
3036 doc = _("(no help text available)")
3036 doc = _("(no help text available)")
3037 if util.safehasattr(entry[0], 'definition'): # aliased command
3037 if util.safehasattr(entry[0], 'definition'): # aliased command
3038 if entry[0].definition.startswith('!'): # shell alias
3038 if entry[0].definition.startswith('!'): # shell alias
3039 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3039 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3040 else:
3040 else:
3041 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3041 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3042 if ui.quiet or not full:
3042 if ui.quiet or not full:
3043 doc = doc.splitlines()[0]
3043 doc = doc.splitlines()[0]
3044 rst += "\n" + doc + "\n"
3044 rst += "\n" + doc + "\n"
3045
3045
3046 # check if this command shadows a non-trivial (multi-line)
3046 # check if this command shadows a non-trivial (multi-line)
3047 # extension help text
3047 # extension help text
3048 try:
3048 try:
3049 mod = extensions.find(name)
3049 mod = extensions.find(name)
3050 doc = gettext(mod.__doc__) or ''
3050 doc = gettext(mod.__doc__) or ''
3051 if '\n' in doc.strip():
3051 if '\n' in doc.strip():
3052 msg = _('use "hg help -e %s" to show help for '
3052 msg = _('use "hg help -e %s" to show help for '
3053 'the %s extension') % (name, name)
3053 'the %s extension') % (name, name)
3054 rst += '\n%s\n' % msg
3054 rst += '\n%s\n' % msg
3055 except KeyError:
3055 except KeyError:
3056 pass
3056 pass
3057
3057
3058 # options
3058 # options
3059 if not ui.quiet and entry[1]:
3059 if not ui.quiet and entry[1]:
3060 rst += '\noptions:\n\n'
3060 rst += '\noptions:\n\n'
3061 rst += optrst(entry[1])
3061 rst += optrst(entry[1])
3062
3062
3063 if ui.verbose:
3063 if ui.verbose:
3064 rst += '\nglobal options:\n\n'
3064 rst += '\nglobal options:\n\n'
3065 rst += optrst(globalopts)
3065 rst += optrst(globalopts)
3066
3066
3067 keep = ui.verbose and ['verbose'] or []
3067 keep = ui.verbose and ['verbose'] or []
3068 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3068 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3069 ui.write(formatted)
3069 ui.write(formatted)
3070
3070
3071 if not ui.verbose:
3071 if not ui.verbose:
3072 if not full:
3072 if not full:
3073 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3073 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3074 % name)
3074 % name)
3075 elif not ui.quiet:
3075 elif not ui.quiet:
3076 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3076 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3077
3077
3078
3078
3079 def helplist(select=None):
3079 def helplist(select=None):
3080 # list of commands
3080 # list of commands
3081 if name == "shortlist":
3081 if name == "shortlist":
3082 header = _('basic commands:\n\n')
3082 header = _('basic commands:\n\n')
3083 else:
3083 else:
3084 header = _('list of commands:\n\n')
3084 header = _('list of commands:\n\n')
3085
3085
3086 h = {}
3086 h = {}
3087 cmds = {}
3087 cmds = {}
3088 for c, e in table.iteritems():
3088 for c, e in table.iteritems():
3089 f = c.split("|", 1)[0]
3089 f = c.split("|", 1)[0]
3090 if select and not select(f):
3090 if select and not select(f):
3091 continue
3091 continue
3092 if (not select and name != 'shortlist' and
3092 if (not select and name != 'shortlist' and
3093 e[0].__module__ != __name__):
3093 e[0].__module__ != __name__):
3094 continue
3094 continue
3095 if name == "shortlist" and not f.startswith("^"):
3095 if name == "shortlist" and not f.startswith("^"):
3096 continue
3096 continue
3097 f = f.lstrip("^")
3097 f = f.lstrip("^")
3098 if not ui.debugflag and f.startswith("debug"):
3098 if not ui.debugflag and f.startswith("debug"):
3099 continue
3099 continue
3100 doc = e[0].__doc__
3100 doc = e[0].__doc__
3101 if doc and 'DEPRECATED' in doc and not ui.verbose:
3101 if doc and 'DEPRECATED' in doc and not ui.verbose:
3102 continue
3102 continue
3103 doc = gettext(doc)
3103 doc = gettext(doc)
3104 if not doc:
3104 if not doc:
3105 doc = _("(no help text available)")
3105 doc = _("(no help text available)")
3106 h[f] = doc.splitlines()[0].rstrip()
3106 h[f] = doc.splitlines()[0].rstrip()
3107 cmds[f] = c.lstrip("^")
3107 cmds[f] = c.lstrip("^")
3108
3108
3109 if not h:
3109 if not h:
3110 ui.status(_('no commands defined\n'))
3110 ui.status(_('no commands defined\n'))
3111 return
3111 return
3112
3112
3113 ui.status(header)
3113 ui.status(header)
3114 fns = sorted(h)
3114 fns = sorted(h)
3115 m = max(map(len, fns))
3115 m = max(map(len, fns))
3116 for f in fns:
3116 for f in fns:
3117 if ui.verbose:
3117 if ui.verbose:
3118 commands = cmds[f].replace("|",", ")
3118 commands = cmds[f].replace("|",", ")
3119 ui.write(" %s:\n %s\n"%(commands, h[f]))
3119 ui.write(" %s:\n %s\n"%(commands, h[f]))
3120 else:
3120 else:
3121 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3121 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3122 initindent=' %-*s ' % (m, f),
3122 initindent=' %-*s ' % (m, f),
3123 hangindent=' ' * (m + 4))))
3123 hangindent=' ' * (m + 4))))
3124
3124
3125 if not name:
3125 if not name:
3126 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3126 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3127 if text:
3127 if text:
3128 ui.write("\n%s" % minirst.format(text, textwidth))
3128 ui.write("\n%s" % minirst.format(text, textwidth))
3129
3129
3130 ui.write(_("\nadditional help topics:\n\n"))
3130 ui.write(_("\nadditional help topics:\n\n"))
3131 topics = []
3131 topics = []
3132 for names, header, doc in help.helptable:
3132 for names, header, doc in help.helptable:
3133 topics.append((sorted(names, key=len, reverse=True)[0], header))
3133 topics.append((sorted(names, key=len, reverse=True)[0], header))
3134 topics_len = max([len(s[0]) for s in topics])
3134 topics_len = max([len(s[0]) for s in topics])
3135 for t, desc in topics:
3135 for t, desc in topics:
3136 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3136 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3137
3137
3138 optlist = []
3138 optlist = []
3139 addglobalopts(optlist, True)
3139 addglobalopts(optlist, True)
3140 ui.write(opttext(optlist, textwidth))
3140 ui.write(opttext(optlist, textwidth))
3141
3141
3142 def helptopic(name):
3142 def helptopic(name):
3143 for names, header, doc in help.helptable:
3143 for names, header, doc in help.helptable:
3144 if name in names:
3144 if name in names:
3145 break
3145 break
3146 else:
3146 else:
3147 raise error.UnknownCommand(name)
3147 raise error.UnknownCommand(name)
3148
3148
3149 # description
3149 # description
3150 if not doc:
3150 if not doc:
3151 doc = _("(no help text available)")
3151 doc = _("(no help text available)")
3152 if util.safehasattr(doc, '__call__'):
3152 if util.safehasattr(doc, '__call__'):
3153 doc = doc()
3153 doc = doc()
3154
3154
3155 ui.write("%s\n\n" % header)
3155 ui.write("%s\n\n" % header)
3156 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3156 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3157 try:
3157 try:
3158 cmdutil.findcmd(name, table)
3158 cmdutil.findcmd(name, table)
3159 ui.write(_('\nuse "hg help -c %s" to see help for '
3159 ui.write(_('\nuse "hg help -c %s" to see help for '
3160 'the %s command\n') % (name, name))
3160 'the %s command\n') % (name, name))
3161 except error.UnknownCommand:
3161 except error.UnknownCommand:
3162 pass
3162 pass
3163
3163
3164 def helpext(name):
3164 def helpext(name):
3165 try:
3165 try:
3166 mod = extensions.find(name)
3166 mod = extensions.find(name)
3167 doc = gettext(mod.__doc__) or _('no help text available')
3167 doc = gettext(mod.__doc__) or _('no help text available')
3168 except KeyError:
3168 except KeyError:
3169 mod = None
3169 mod = None
3170 doc = extensions.disabledext(name)
3170 doc = extensions.disabledext(name)
3171 if not doc:
3171 if not doc:
3172 raise error.UnknownCommand(name)
3172 raise error.UnknownCommand(name)
3173
3173
3174 if '\n' not in doc:
3174 if '\n' not in doc:
3175 head, tail = doc, ""
3175 head, tail = doc, ""
3176 else:
3176 else:
3177 head, tail = doc.split('\n', 1)
3177 head, tail = doc.split('\n', 1)
3178 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3178 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3179 if tail:
3179 if tail:
3180 ui.write(minirst.format(tail, textwidth))
3180 ui.write(minirst.format(tail, textwidth))
3181 ui.status('\n')
3181 ui.status('\n')
3182
3182
3183 if mod:
3183 if mod:
3184 try:
3184 try:
3185 ct = mod.cmdtable
3185 ct = mod.cmdtable
3186 except AttributeError:
3186 except AttributeError:
3187 ct = {}
3187 ct = {}
3188 modcmds = set([c.split('|', 1)[0] for c in ct])
3188 modcmds = set([c.split('|', 1)[0] for c in ct])
3189 helplist(modcmds.__contains__)
3189 helplist(modcmds.__contains__)
3190 else:
3190 else:
3191 ui.write(_('use "hg help extensions" for information on enabling '
3191 ui.write(_('use "hg help extensions" for information on enabling '
3192 'extensions\n'))
3192 'extensions\n'))
3193
3193
3194 def helpextcmd(name):
3194 def helpextcmd(name):
3195 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3195 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3196 doc = gettext(mod.__doc__).splitlines()[0]
3196 doc = gettext(mod.__doc__).splitlines()[0]
3197
3197
3198 msg = help.listexts(_("'%s' is provided by the following "
3198 msg = help.listexts(_("'%s' is provided by the following "
3199 "extension:") % cmd, {ext: doc}, indent=4)
3199 "extension:") % cmd, {ext: doc}, indent=4)
3200 ui.write(minirst.format(msg, textwidth))
3200 ui.write(minirst.format(msg, textwidth))
3201 ui.write('\n')
3201 ui.write('\n')
3202 ui.write(_('use "hg help extensions" for information on enabling '
3202 ui.write(_('use "hg help extensions" for information on enabling '
3203 'extensions\n'))
3203 'extensions\n'))
3204
3204
3205 if name and name != 'shortlist':
3205 if name and name != 'shortlist':
3206 i = None
3206 i = None
3207 if unknowncmd:
3207 if unknowncmd:
3208 queries = (helpextcmd,)
3208 queries = (helpextcmd,)
3209 elif opts.get('extension'):
3209 elif opts.get('extension'):
3210 queries = (helpext,)
3210 queries = (helpext,)
3211 elif opts.get('command'):
3211 elif opts.get('command'):
3212 queries = (helpcmd,)
3212 queries = (helpcmd,)
3213 else:
3213 else:
3214 queries = (helptopic, helpcmd, helpext, helpextcmd)
3214 queries = (helptopic, helpcmd, helpext, helpextcmd)
3215 for f in queries:
3215 for f in queries:
3216 try:
3216 try:
3217 f(name)
3217 f(name)
3218 i = None
3218 i = None
3219 break
3219 break
3220 except error.UnknownCommand, inst:
3220 except error.UnknownCommand, inst:
3221 i = inst
3221 i = inst
3222 if i:
3222 if i:
3223 raise i
3223 raise i
3224 else:
3224 else:
3225 # program name
3225 # program name
3226 ui.status(_("Mercurial Distributed SCM\n"))
3226 ui.status(_("Mercurial Distributed SCM\n"))
3227 ui.status('\n')
3227 ui.status('\n')
3228 helplist()
3228 helplist()
3229
3229
3230
3230
3231 @command('identify|id',
3231 @command('identify|id',
3232 [('r', 'rev', '',
3232 [('r', 'rev', '',
3233 _('identify the specified revision'), _('REV')),
3233 _('identify the specified revision'), _('REV')),
3234 ('n', 'num', None, _('show local revision number')),
3234 ('n', 'num', None, _('show local revision number')),
3235 ('i', 'id', None, _('show global revision id')),
3235 ('i', 'id', None, _('show global revision id')),
3236 ('b', 'branch', None, _('show branch')),
3236 ('b', 'branch', None, _('show branch')),
3237 ('t', 'tags', None, _('show tags')),
3237 ('t', 'tags', None, _('show tags')),
3238 ('B', 'bookmarks', None, _('show bookmarks')),
3238 ('B', 'bookmarks', None, _('show bookmarks')),
3239 ] + remoteopts,
3239 ] + remoteopts,
3240 _('[-nibtB] [-r REV] [SOURCE]'))
3240 _('[-nibtB] [-r REV] [SOURCE]'))
3241 def identify(ui, repo, source=None, rev=None,
3241 def identify(ui, repo, source=None, rev=None,
3242 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3242 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3243 """identify the working copy or specified revision
3243 """identify the working copy or specified revision
3244
3244
3245 Print a summary identifying the repository state at REV using one or
3245 Print a summary identifying the repository state at REV using one or
3246 two parent hash identifiers, followed by a "+" if the working
3246 two parent hash identifiers, followed by a "+" if the working
3247 directory has uncommitted changes, the branch name (if not default),
3247 directory has uncommitted changes, the branch name (if not default),
3248 a list of tags, and a list of bookmarks.
3248 a list of tags, and a list of bookmarks.
3249
3249
3250 When REV is not given, print a summary of the current state of the
3250 When REV is not given, print a summary of the current state of the
3251 repository.
3251 repository.
3252
3252
3253 Specifying a path to a repository root or Mercurial bundle will
3253 Specifying a path to a repository root or Mercurial bundle will
3254 cause lookup to operate on that repository/bundle.
3254 cause lookup to operate on that repository/bundle.
3255
3255
3256 .. container:: verbose
3256 .. container:: verbose
3257
3257
3258 Examples:
3258 Examples:
3259
3259
3260 - generate a build identifier for the working directory::
3260 - generate a build identifier for the working directory::
3261
3261
3262 hg id --id > build-id.dat
3262 hg id --id > build-id.dat
3263
3263
3264 - find the revision corresponding to a tag::
3264 - find the revision corresponding to a tag::
3265
3265
3266 hg id -n -r 1.3
3266 hg id -n -r 1.3
3267
3267
3268 - check the most recent revision of a remote repository::
3268 - check the most recent revision of a remote repository::
3269
3269
3270 hg id -r tip http://selenic.com/hg/
3270 hg id -r tip http://selenic.com/hg/
3271
3271
3272 Returns 0 if successful.
3272 Returns 0 if successful.
3273 """
3273 """
3274
3274
3275 if not repo and not source:
3275 if not repo and not source:
3276 raise util.Abort(_("there is no Mercurial repository here "
3276 raise util.Abort(_("there is no Mercurial repository here "
3277 "(.hg not found)"))
3277 "(.hg not found)"))
3278
3278
3279 hexfunc = ui.debugflag and hex or short
3279 hexfunc = ui.debugflag and hex or short
3280 default = not (num or id or branch or tags or bookmarks)
3280 default = not (num or id or branch or tags or bookmarks)
3281 output = []
3281 output = []
3282 revs = []
3282 revs = []
3283
3283
3284 if source:
3284 if source:
3285 source, branches = hg.parseurl(ui.expandpath(source))
3285 source, branches = hg.parseurl(ui.expandpath(source))
3286 repo = hg.peer(ui, opts, source)
3286 repo = hg.peer(ui, opts, source)
3287 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3287 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3288
3288
3289 if not repo.local():
3289 if not repo.local():
3290 if num or branch or tags:
3290 if num or branch or tags:
3291 raise util.Abort(
3291 raise util.Abort(
3292 _("can't query remote revision number, branch, or tags"))
3292 _("can't query remote revision number, branch, or tags"))
3293 if not rev and revs:
3293 if not rev and revs:
3294 rev = revs[0]
3294 rev = revs[0]
3295 if not rev:
3295 if not rev:
3296 rev = "tip"
3296 rev = "tip"
3297
3297
3298 remoterev = repo.lookup(rev)
3298 remoterev = repo.lookup(rev)
3299 if default or id:
3299 if default or id:
3300 output = [hexfunc(remoterev)]
3300 output = [hexfunc(remoterev)]
3301
3301
3302 def getbms():
3302 def getbms():
3303 bms = []
3303 bms = []
3304
3304
3305 if 'bookmarks' in repo.listkeys('namespaces'):
3305 if 'bookmarks' in repo.listkeys('namespaces'):
3306 hexremoterev = hex(remoterev)
3306 hexremoterev = hex(remoterev)
3307 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3307 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3308 if bmr == hexremoterev]
3308 if bmr == hexremoterev]
3309
3309
3310 return bms
3310 return bms
3311
3311
3312 if bookmarks:
3312 if bookmarks:
3313 output.extend(getbms())
3313 output.extend(getbms())
3314 elif default and not ui.quiet:
3314 elif default and not ui.quiet:
3315 # multiple bookmarks for a single parent separated by '/'
3315 # multiple bookmarks for a single parent separated by '/'
3316 bm = '/'.join(getbms())
3316 bm = '/'.join(getbms())
3317 if bm:
3317 if bm:
3318 output.append(bm)
3318 output.append(bm)
3319 else:
3319 else:
3320 if not rev:
3320 if not rev:
3321 ctx = repo[None]
3321 ctx = repo[None]
3322 parents = ctx.parents()
3322 parents = ctx.parents()
3323 changed = ""
3323 changed = ""
3324 if default or id or num:
3324 if default or id or num:
3325 changed = util.any(repo.status()) and "+" or ""
3325 changed = util.any(repo.status()) and "+" or ""
3326 if default or id:
3326 if default or id:
3327 output = ["%s%s" %
3327 output = ["%s%s" %
3328 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3328 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3329 if num:
3329 if num:
3330 output.append("%s%s" %
3330 output.append("%s%s" %
3331 ('+'.join([str(p.rev()) for p in parents]), changed))
3331 ('+'.join([str(p.rev()) for p in parents]), changed))
3332 else:
3332 else:
3333 ctx = scmutil.revsingle(repo, rev)
3333 ctx = scmutil.revsingle(repo, rev)
3334 if default or id:
3334 if default or id:
3335 output = [hexfunc(ctx.node())]
3335 output = [hexfunc(ctx.node())]
3336 if num:
3336 if num:
3337 output.append(str(ctx.rev()))
3337 output.append(str(ctx.rev()))
3338
3338
3339 if default and not ui.quiet:
3339 if default and not ui.quiet:
3340 b = ctx.branch()
3340 b = ctx.branch()
3341 if b != 'default':
3341 if b != 'default':
3342 output.append("(%s)" % b)
3342 output.append("(%s)" % b)
3343
3343
3344 # multiple tags for a single parent separated by '/'
3344 # multiple tags for a single parent separated by '/'
3345 t = '/'.join(ctx.tags())
3345 t = '/'.join(ctx.tags())
3346 if t:
3346 if t:
3347 output.append(t)
3347 output.append(t)
3348
3348
3349 # multiple bookmarks for a single parent separated by '/'
3349 # multiple bookmarks for a single parent separated by '/'
3350 bm = '/'.join(ctx.bookmarks())
3350 bm = '/'.join(ctx.bookmarks())
3351 if bm:
3351 if bm:
3352 output.append(bm)
3352 output.append(bm)
3353 else:
3353 else:
3354 if branch:
3354 if branch:
3355 output.append(ctx.branch())
3355 output.append(ctx.branch())
3356
3356
3357 if tags:
3357 if tags:
3358 output.extend(ctx.tags())
3358 output.extend(ctx.tags())
3359
3359
3360 if bookmarks:
3360 if bookmarks:
3361 output.extend(ctx.bookmarks())
3361 output.extend(ctx.bookmarks())
3362
3362
3363 ui.write("%s\n" % ' '.join(output))
3363 ui.write("%s\n" % ' '.join(output))
3364
3364
3365 @command('import|patch',
3365 @command('import|patch',
3366 [('p', 'strip', 1,
3366 [('p', 'strip', 1,
3367 _('directory strip option for patch. This has the same '
3367 _('directory strip option for patch. This has the same '
3368 'meaning as the corresponding patch option'), _('NUM')),
3368 'meaning as the corresponding patch option'), _('NUM')),
3369 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3369 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3370 ('e', 'edit', False, _('invoke editor on commit messages')),
3370 ('e', 'edit', False, _('invoke editor on commit messages')),
3371 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3371 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3372 ('', 'no-commit', None,
3372 ('', 'no-commit', None,
3373 _("don't commit, just update the working directory")),
3373 _("don't commit, just update the working directory")),
3374 ('', 'bypass', None,
3374 ('', 'bypass', None,
3375 _("apply patch without touching the working directory")),
3375 _("apply patch without touching the working directory")),
3376 ('', 'exact', None,
3376 ('', 'exact', None,
3377 _('apply patch to the nodes from which it was generated')),
3377 _('apply patch to the nodes from which it was generated')),
3378 ('', 'import-branch', None,
3378 ('', 'import-branch', None,
3379 _('use any branch information in patch (implied by --exact)'))] +
3379 _('use any branch information in patch (implied by --exact)'))] +
3380 commitopts + commitopts2 + similarityopts,
3380 commitopts + commitopts2 + similarityopts,
3381 _('[OPTION]... PATCH...'))
3381 _('[OPTION]... PATCH...'))
3382 def import_(ui, repo, patch1=None, *patches, **opts):
3382 def import_(ui, repo, patch1=None, *patches, **opts):
3383 """import an ordered set of patches
3383 """import an ordered set of patches
3384
3384
3385 Import a list of patches and commit them individually (unless
3385 Import a list of patches and commit them individually (unless
3386 --no-commit is specified).
3386 --no-commit is specified).
3387
3387
3388 If there are outstanding changes in the working directory, import
3388 If there are outstanding changes in the working directory, import
3389 will abort unless given the -f/--force flag.
3389 will abort unless given the -f/--force flag.
3390
3390
3391 You can import a patch straight from a mail message. Even patches
3391 You can import a patch straight from a mail message. Even patches
3392 as attachments work (to use the body part, it must have type
3392 as attachments work (to use the body part, it must have type
3393 text/plain or text/x-patch). From and Subject headers of email
3393 text/plain or text/x-patch). From and Subject headers of email
3394 message are used as default committer and commit message. All
3394 message are used as default committer and commit message. All
3395 text/plain body parts before first diff are added to commit
3395 text/plain body parts before first diff are added to commit
3396 message.
3396 message.
3397
3397
3398 If the imported patch was generated by :hg:`export`, user and
3398 If the imported patch was generated by :hg:`export`, user and
3399 description from patch override values from message headers and
3399 description from patch override values from message headers and
3400 body. Values given on command line with -m/--message and -u/--user
3400 body. Values given on command line with -m/--message and -u/--user
3401 override these.
3401 override these.
3402
3402
3403 If --exact is specified, import will set the working directory to
3403 If --exact is specified, import will set the working directory to
3404 the parent of each patch before applying it, and will abort if the
3404 the parent of each patch before applying it, and will abort if the
3405 resulting changeset has a different ID than the one recorded in
3405 resulting changeset has a different ID than the one recorded in
3406 the patch. This may happen due to character set problems or other
3406 the patch. This may happen due to character set problems or other
3407 deficiencies in the text patch format.
3407 deficiencies in the text patch format.
3408
3408
3409 Use --bypass to apply and commit patches directly to the
3409 Use --bypass to apply and commit patches directly to the
3410 repository, not touching the working directory. Without --exact,
3410 repository, not touching the working directory. Without --exact,
3411 patches will be applied on top of the working directory parent
3411 patches will be applied on top of the working directory parent
3412 revision.
3412 revision.
3413
3413
3414 With -s/--similarity, hg will attempt to discover renames and
3414 With -s/--similarity, hg will attempt to discover renames and
3415 copies in the patch in the same way as :hg:`addremove`.
3415 copies in the patch in the same way as :hg:`addremove`.
3416
3416
3417 To read a patch from standard input, use "-" as the patch name. If
3417 To read a patch from standard input, use "-" as the patch name. If
3418 a URL is specified, the patch will be downloaded from it.
3418 a URL is specified, the patch will be downloaded from it.
3419 See :hg:`help dates` for a list of formats valid for -d/--date.
3419 See :hg:`help dates` for a list of formats valid for -d/--date.
3420
3420
3421 .. container:: verbose
3421 .. container:: verbose
3422
3422
3423 Examples:
3423 Examples:
3424
3424
3425 - import a traditional patch from a website and detect renames::
3425 - import a traditional patch from a website and detect renames::
3426
3426
3427 hg import -s 80 http://example.com/bugfix.patch
3427 hg import -s 80 http://example.com/bugfix.patch
3428
3428
3429 - import a changeset from an hgweb server::
3429 - import a changeset from an hgweb server::
3430
3430
3431 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3431 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3432
3432
3433 - import all the patches in an Unix-style mbox::
3433 - import all the patches in an Unix-style mbox::
3434
3434
3435 hg import incoming-patches.mbox
3435 hg import incoming-patches.mbox
3436
3436
3437 - attempt to exactly restore an exported changeset (not always
3437 - attempt to exactly restore an exported changeset (not always
3438 possible)::
3438 possible)::
3439
3439
3440 hg import --exact proposed-fix.patch
3440 hg import --exact proposed-fix.patch
3441
3441
3442 Returns 0 on success.
3442 Returns 0 on success.
3443 """
3443 """
3444
3444
3445 if not patch1:
3445 if not patch1:
3446 raise util.Abort(_('need at least one patch to import'))
3446 raise util.Abort(_('need at least one patch to import'))
3447
3447
3448 patches = (patch1,) + patches
3448 patches = (patch1,) + patches
3449
3449
3450 date = opts.get('date')
3450 date = opts.get('date')
3451 if date:
3451 if date:
3452 opts['date'] = util.parsedate(date)
3452 opts['date'] = util.parsedate(date)
3453
3453
3454 editor = cmdutil.commiteditor
3454 editor = cmdutil.commiteditor
3455 if opts.get('edit'):
3455 if opts.get('edit'):
3456 editor = cmdutil.commitforceeditor
3456 editor = cmdutil.commitforceeditor
3457
3457
3458 update = not opts.get('bypass')
3458 update = not opts.get('bypass')
3459 if not update and opts.get('no_commit'):
3459 if not update and opts.get('no_commit'):
3460 raise util.Abort(_('cannot use --no-commit with --bypass'))
3460 raise util.Abort(_('cannot use --no-commit with --bypass'))
3461 try:
3461 try:
3462 sim = float(opts.get('similarity') or 0)
3462 sim = float(opts.get('similarity') or 0)
3463 except ValueError:
3463 except ValueError:
3464 raise util.Abort(_('similarity must be a number'))
3464 raise util.Abort(_('similarity must be a number'))
3465 if sim < 0 or sim > 100:
3465 if sim < 0 or sim > 100:
3466 raise util.Abort(_('similarity must be between 0 and 100'))
3466 raise util.Abort(_('similarity must be between 0 and 100'))
3467 if sim and not update:
3467 if sim and not update:
3468 raise util.Abort(_('cannot use --similarity with --bypass'))
3468 raise util.Abort(_('cannot use --similarity with --bypass'))
3469
3469
3470 if (opts.get('exact') or not opts.get('force')) and update:
3470 if (opts.get('exact') or not opts.get('force')) and update:
3471 cmdutil.bailifchanged(repo)
3471 cmdutil.bailifchanged(repo)
3472
3472
3473 base = opts["base"]
3473 base = opts["base"]
3474 strip = opts["strip"]
3474 strip = opts["strip"]
3475 wlock = lock = tr = None
3475 wlock = lock = tr = None
3476 msgs = []
3476 msgs = []
3477
3477
3478 def checkexact(repo, n, nodeid):
3478 def checkexact(repo, n, nodeid):
3479 if opts.get('exact') and hex(n) != nodeid:
3479 if opts.get('exact') and hex(n) != nodeid:
3480 repo.rollback()
3480 repo.rollback()
3481 raise util.Abort(_('patch is damaged or loses information'))
3481 raise util.Abort(_('patch is damaged or loses information'))
3482
3482
3483 def tryone(ui, hunk, parents):
3483 def tryone(ui, hunk, parents):
3484 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3484 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3485 patch.extract(ui, hunk)
3485 patch.extract(ui, hunk)
3486
3486
3487 if not tmpname:
3487 if not tmpname:
3488 return (None, None)
3488 return (None, None)
3489 msg = _('applied to working directory')
3489 msg = _('applied to working directory')
3490
3490
3491 try:
3491 try:
3492 cmdline_message = cmdutil.logmessage(ui, opts)
3492 cmdline_message = cmdutil.logmessage(ui, opts)
3493 if cmdline_message:
3493 if cmdline_message:
3494 # pickup the cmdline msg
3494 # pickup the cmdline msg
3495 message = cmdline_message
3495 message = cmdline_message
3496 elif message:
3496 elif message:
3497 # pickup the patch msg
3497 # pickup the patch msg
3498 message = message.strip()
3498 message = message.strip()
3499 else:
3499 else:
3500 # launch the editor
3500 # launch the editor
3501 message = None
3501 message = None
3502 ui.debug('message:\n%s\n' % message)
3502 ui.debug('message:\n%s\n' % message)
3503
3503
3504 if len(parents) == 1:
3504 if len(parents) == 1:
3505 parents.append(repo[nullid])
3505 parents.append(repo[nullid])
3506 if opts.get('exact'):
3506 if opts.get('exact'):
3507 if not nodeid or not p1:
3507 if not nodeid or not p1:
3508 raise util.Abort(_('not a Mercurial patch'))
3508 raise util.Abort(_('not a Mercurial patch'))
3509 p1 = repo[p1]
3509 p1 = repo[p1]
3510 p2 = repo[p2 or nullid]
3510 p2 = repo[p2 or nullid]
3511 elif p2:
3511 elif p2:
3512 try:
3512 try:
3513 p1 = repo[p1]
3513 p1 = repo[p1]
3514 p2 = repo[p2]
3514 p2 = repo[p2]
3515 # Without any options, consider p2 only if the
3515 # Without any options, consider p2 only if the
3516 # patch is being applied on top of the recorded
3516 # patch is being applied on top of the recorded
3517 # first parent.
3517 # first parent.
3518 if p1 != parents[0]:
3518 if p1 != parents[0]:
3519 p1 = parents[0]
3519 p1 = parents[0]
3520 p2 = repo[nullid]
3520 p2 = repo[nullid]
3521 except error.RepoError:
3521 except error.RepoError:
3522 p1, p2 = parents
3522 p1, p2 = parents
3523 else:
3523 else:
3524 p1, p2 = parents
3524 p1, p2 = parents
3525
3525
3526 n = None
3526 n = None
3527 if update:
3527 if update:
3528 if p1 != parents[0]:
3528 if p1 != parents[0]:
3529 hg.clean(repo, p1.node())
3529 hg.clean(repo, p1.node())
3530 if p2 != parents[1]:
3530 if p2 != parents[1]:
3531 repo.dirstate.setparents(p1.node(), p2.node())
3531 repo.dirstate.setparents(p1.node(), p2.node())
3532
3532
3533 if opts.get('exact') or opts.get('import_branch'):
3533 if opts.get('exact') or opts.get('import_branch'):
3534 repo.dirstate.setbranch(branch or 'default')
3534 repo.dirstate.setbranch(branch or 'default')
3535
3535
3536 files = set()
3536 files = set()
3537 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3537 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3538 eolmode=None, similarity=sim / 100.0)
3538 eolmode=None, similarity=sim / 100.0)
3539 files = list(files)
3539 files = list(files)
3540 if opts.get('no_commit'):
3540 if opts.get('no_commit'):
3541 if message:
3541 if message:
3542 msgs.append(message)
3542 msgs.append(message)
3543 else:
3543 else:
3544 if opts.get('exact') or p2:
3544 if opts.get('exact') or p2:
3545 # If you got here, you either use --force and know what
3545 # If you got here, you either use --force and know what
3546 # you are doing or used --exact or a merge patch while
3546 # you are doing or used --exact or a merge patch while
3547 # being updated to its first parent.
3547 # being updated to its first parent.
3548 m = None
3548 m = None
3549 else:
3549 else:
3550 m = scmutil.matchfiles(repo, files or [])
3550 m = scmutil.matchfiles(repo, files or [])
3551 n = repo.commit(message, opts.get('user') or user,
3551 n = repo.commit(message, opts.get('user') or user,
3552 opts.get('date') or date, match=m,
3552 opts.get('date') or date, match=m,
3553 editor=editor)
3553 editor=editor)
3554 checkexact(repo, n, nodeid)
3554 checkexact(repo, n, nodeid)
3555 else:
3555 else:
3556 if opts.get('exact') or opts.get('import_branch'):
3556 if opts.get('exact') or opts.get('import_branch'):
3557 branch = branch or 'default'
3557 branch = branch or 'default'
3558 else:
3558 else:
3559 branch = p1.branch()
3559 branch = p1.branch()
3560 store = patch.filestore()
3560 store = patch.filestore()
3561 try:
3561 try:
3562 files = set()
3562 files = set()
3563 try:
3563 try:
3564 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3564 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3565 files, eolmode=None)
3565 files, eolmode=None)
3566 except patch.PatchError, e:
3566 except patch.PatchError, e:
3567 raise util.Abort(str(e))
3567 raise util.Abort(str(e))
3568 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3568 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3569 message,
3569 message,
3570 opts.get('user') or user,
3570 opts.get('user') or user,
3571 opts.get('date') or date,
3571 opts.get('date') or date,
3572 branch, files, store,
3572 branch, files, store,
3573 editor=cmdutil.commiteditor)
3573 editor=cmdutil.commiteditor)
3574 repo.savecommitmessage(memctx.description())
3574 repo.savecommitmessage(memctx.description())
3575 n = memctx.commit()
3575 n = memctx.commit()
3576 checkexact(repo, n, nodeid)
3576 checkexact(repo, n, nodeid)
3577 finally:
3577 finally:
3578 store.close()
3578 store.close()
3579 if n:
3579 if n:
3580 # i18n: refers to a short changeset id
3580 # i18n: refers to a short changeset id
3581 msg = _('created %s') % short(n)
3581 msg = _('created %s') % short(n)
3582 return (msg, n)
3582 return (msg, n)
3583 finally:
3583 finally:
3584 os.unlink(tmpname)
3584 os.unlink(tmpname)
3585
3585
3586 try:
3586 try:
3587 try:
3587 try:
3588 wlock = repo.wlock()
3588 wlock = repo.wlock()
3589 lock = repo.lock()
3589 lock = repo.lock()
3590 tr = repo.transaction('import')
3590 tr = repo.transaction('import')
3591 parents = repo.parents()
3591 parents = repo.parents()
3592 for patchurl in patches:
3592 for patchurl in patches:
3593 if patchurl == '-':
3593 if patchurl == '-':
3594 ui.status(_('applying patch from stdin\n'))
3594 ui.status(_('applying patch from stdin\n'))
3595 patchfile = ui.fin
3595 patchfile = ui.fin
3596 patchurl = 'stdin' # for error message
3596 patchurl = 'stdin' # for error message
3597 else:
3597 else:
3598 patchurl = os.path.join(base, patchurl)
3598 patchurl = os.path.join(base, patchurl)
3599 ui.status(_('applying %s\n') % patchurl)
3599 ui.status(_('applying %s\n') % patchurl)
3600 patchfile = url.open(ui, patchurl)
3600 patchfile = url.open(ui, patchurl)
3601
3601
3602 haspatch = False
3602 haspatch = False
3603 for hunk in patch.split(patchfile):
3603 for hunk in patch.split(patchfile):
3604 (msg, node) = tryone(ui, hunk, parents)
3604 (msg, node) = tryone(ui, hunk, parents)
3605 if msg:
3605 if msg:
3606 haspatch = True
3606 haspatch = True
3607 ui.note(msg + '\n')
3607 ui.note(msg + '\n')
3608 if update or opts.get('exact'):
3608 if update or opts.get('exact'):
3609 parents = repo.parents()
3609 parents = repo.parents()
3610 else:
3610 else:
3611 parents = [repo[node]]
3611 parents = [repo[node]]
3612
3612
3613 if not haspatch:
3613 if not haspatch:
3614 raise util.Abort(_('%s: no diffs found') % patchurl)
3614 raise util.Abort(_('%s: no diffs found') % patchurl)
3615
3615
3616 tr.close()
3616 tr.close()
3617 if msgs:
3617 if msgs:
3618 repo.savecommitmessage('\n* * *\n'.join(msgs))
3618 repo.savecommitmessage('\n* * *\n'.join(msgs))
3619 except:
3619 except:
3620 # wlock.release() indirectly calls dirstate.write(): since
3620 # wlock.release() indirectly calls dirstate.write(): since
3621 # we're crashing, we do not want to change the working dir
3621 # we're crashing, we do not want to change the working dir
3622 # parent after all, so make sure it writes nothing
3622 # parent after all, so make sure it writes nothing
3623 repo.dirstate.invalidate()
3623 repo.dirstate.invalidate()
3624 raise
3624 raise
3625 finally:
3625 finally:
3626 if tr:
3626 if tr:
3627 tr.release()
3627 tr.release()
3628 release(lock, wlock)
3628 release(lock, wlock)
3629
3629
3630 @command('incoming|in',
3630 @command('incoming|in',
3631 [('f', 'force', None,
3631 [('f', 'force', None,
3632 _('run even if remote repository is unrelated')),
3632 _('run even if remote repository is unrelated')),
3633 ('n', 'newest-first', None, _('show newest record first')),
3633 ('n', 'newest-first', None, _('show newest record first')),
3634 ('', 'bundle', '',
3634 ('', 'bundle', '',
3635 _('file to store the bundles into'), _('FILE')),
3635 _('file to store the bundles into'), _('FILE')),
3636 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3636 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3637 ('B', 'bookmarks', False, _("compare bookmarks")),
3637 ('B', 'bookmarks', False, _("compare bookmarks")),
3638 ('b', 'branch', [],
3638 ('b', 'branch', [],
3639 _('a specific branch you would like to pull'), _('BRANCH')),
3639 _('a specific branch you would like to pull'), _('BRANCH')),
3640 ] + logopts + remoteopts + subrepoopts,
3640 ] + logopts + remoteopts + subrepoopts,
3641 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3641 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3642 def incoming(ui, repo, source="default", **opts):
3642 def incoming(ui, repo, source="default", **opts):
3643 """show new changesets found in source
3643 """show new changesets found in source
3644
3644
3645 Show new changesets found in the specified path/URL or the default
3645 Show new changesets found in the specified path/URL or the default
3646 pull location. These are the changesets that would have been pulled
3646 pull location. These are the changesets that would have been pulled
3647 if a pull at the time you issued this command.
3647 if a pull at the time you issued this command.
3648
3648
3649 For remote repository, using --bundle avoids downloading the
3649 For remote repository, using --bundle avoids downloading the
3650 changesets twice if the incoming is followed by a pull.
3650 changesets twice if the incoming is followed by a pull.
3651
3651
3652 See pull for valid source format details.
3652 See pull for valid source format details.
3653
3653
3654 Returns 0 if there are incoming changes, 1 otherwise.
3654 Returns 0 if there are incoming changes, 1 otherwise.
3655 """
3655 """
3656 if opts.get('bundle') and opts.get('subrepos'):
3656 if opts.get('bundle') and opts.get('subrepos'):
3657 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3657 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3658
3658
3659 if opts.get('bookmarks'):
3659 if opts.get('bookmarks'):
3660 source, branches = hg.parseurl(ui.expandpath(source),
3660 source, branches = hg.parseurl(ui.expandpath(source),
3661 opts.get('branch'))
3661 opts.get('branch'))
3662 other = hg.peer(repo, opts, source)
3662 other = hg.peer(repo, opts, source)
3663 if 'bookmarks' not in other.listkeys('namespaces'):
3663 if 'bookmarks' not in other.listkeys('namespaces'):
3664 ui.warn(_("remote doesn't support bookmarks\n"))
3664 ui.warn(_("remote doesn't support bookmarks\n"))
3665 return 0
3665 return 0
3666 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3666 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3667 return bookmarks.diff(ui, repo, other)
3667 return bookmarks.diff(ui, repo, other)
3668
3668
3669 repo._subtoppath = ui.expandpath(source)
3669 repo._subtoppath = ui.expandpath(source)
3670 try:
3670 try:
3671 return hg.incoming(ui, repo, source, opts)
3671 return hg.incoming(ui, repo, source, opts)
3672 finally:
3672 finally:
3673 del repo._subtoppath
3673 del repo._subtoppath
3674
3674
3675
3675
3676 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3676 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3677 def init(ui, dest=".", **opts):
3677 def init(ui, dest=".", **opts):
3678 """create a new repository in the given directory
3678 """create a new repository in the given directory
3679
3679
3680 Initialize a new repository in the given directory. If the given
3680 Initialize a new repository in the given directory. If the given
3681 directory does not exist, it will be created.
3681 directory does not exist, it will be created.
3682
3682
3683 If no directory is given, the current directory is used.
3683 If no directory is given, the current directory is used.
3684
3684
3685 It is possible to specify an ``ssh://`` URL as the destination.
3685 It is possible to specify an ``ssh://`` URL as the destination.
3686 See :hg:`help urls` for more information.
3686 See :hg:`help urls` for more information.
3687
3687
3688 Returns 0 on success.
3688 Returns 0 on success.
3689 """
3689 """
3690 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3690 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3691
3691
3692 @command('locate',
3692 @command('locate',
3693 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3693 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3694 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3694 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3695 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3695 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3696 ] + walkopts,
3696 ] + walkopts,
3697 _('[OPTION]... [PATTERN]...'))
3697 _('[OPTION]... [PATTERN]...'))
3698 def locate(ui, repo, *pats, **opts):
3698 def locate(ui, repo, *pats, **opts):
3699 """locate files matching specific patterns
3699 """locate files matching specific patterns
3700
3700
3701 Print files under Mercurial control in the working directory whose
3701 Print files under Mercurial control in the working directory whose
3702 names match the given patterns.
3702 names match the given patterns.
3703
3703
3704 By default, this command searches all directories in the working
3704 By default, this command searches all directories in the working
3705 directory. To search just the current directory and its
3705 directory. To search just the current directory and its
3706 subdirectories, use "--include .".
3706 subdirectories, use "--include .".
3707
3707
3708 If no patterns are given to match, this command prints the names
3708 If no patterns are given to match, this command prints the names
3709 of all files under Mercurial control in the working directory.
3709 of all files under Mercurial control in the working directory.
3710
3710
3711 If you want to feed the output of this command into the "xargs"
3711 If you want to feed the output of this command into the "xargs"
3712 command, use the -0 option to both this command and "xargs". This
3712 command, use the -0 option to both this command and "xargs". This
3713 will avoid the problem of "xargs" treating single filenames that
3713 will avoid the problem of "xargs" treating single filenames that
3714 contain whitespace as multiple filenames.
3714 contain whitespace as multiple filenames.
3715
3715
3716 Returns 0 if a match is found, 1 otherwise.
3716 Returns 0 if a match is found, 1 otherwise.
3717 """
3717 """
3718 end = opts.get('print0') and '\0' or '\n'
3718 end = opts.get('print0') and '\0' or '\n'
3719 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3719 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3720
3720
3721 ret = 1
3721 ret = 1
3722 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3722 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3723 m.bad = lambda x, y: False
3723 m.bad = lambda x, y: False
3724 for abs in repo[rev].walk(m):
3724 for abs in repo[rev].walk(m):
3725 if not rev and abs not in repo.dirstate:
3725 if not rev and abs not in repo.dirstate:
3726 continue
3726 continue
3727 if opts.get('fullpath'):
3727 if opts.get('fullpath'):
3728 ui.write(repo.wjoin(abs), end)
3728 ui.write(repo.wjoin(abs), end)
3729 else:
3729 else:
3730 ui.write(((pats and m.rel(abs)) or abs), end)
3730 ui.write(((pats and m.rel(abs)) or abs), end)
3731 ret = 0
3731 ret = 0
3732
3732
3733 return ret
3733 return ret
3734
3734
3735 @command('^log|history',
3735 @command('^log|history',
3736 [('f', 'follow', None,
3736 [('f', 'follow', None,
3737 _('follow changeset history, or file history across copies and renames')),
3737 _('follow changeset history, or file history across copies and renames')),
3738 ('', 'follow-first', None,
3738 ('', 'follow-first', None,
3739 _('only follow the first parent of merge changesets (DEPRECATED)')),
3739 _('only follow the first parent of merge changesets (DEPRECATED)')),
3740 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3740 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3741 ('C', 'copies', None, _('show copied files')),
3741 ('C', 'copies', None, _('show copied files')),
3742 ('k', 'keyword', [],
3742 ('k', 'keyword', [],
3743 _('do case-insensitive search for a given text'), _('TEXT')),
3743 _('do case-insensitive search for a given text'), _('TEXT')),
3744 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3744 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3745 ('', 'removed', None, _('include revisions where files were removed')),
3745 ('', 'removed', None, _('include revisions where files were removed')),
3746 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3746 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3747 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3747 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3748 ('', 'only-branch', [],
3748 ('', 'only-branch', [],
3749 _('show only changesets within the given named branch (DEPRECATED)'),
3749 _('show only changesets within the given named branch (DEPRECATED)'),
3750 _('BRANCH')),
3750 _('BRANCH')),
3751 ('b', 'branch', [],
3751 ('b', 'branch', [],
3752 _('show changesets within the given named branch'), _('BRANCH')),
3752 _('show changesets within the given named branch'), _('BRANCH')),
3753 ('P', 'prune', [],
3753 ('P', 'prune', [],
3754 _('do not display revision or any of its ancestors'), _('REV')),
3754 _('do not display revision or any of its ancestors'), _('REV')),
3755 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3755 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3756 ] + logopts + walkopts,
3756 ] + logopts + walkopts,
3757 _('[OPTION]... [FILE]'))
3757 _('[OPTION]... [FILE]'))
3758 def log(ui, repo, *pats, **opts):
3758 def log(ui, repo, *pats, **opts):
3759 """show revision history of entire repository or files
3759 """show revision history of entire repository or files
3760
3760
3761 Print the revision history of the specified files or the entire
3761 Print the revision history of the specified files or the entire
3762 project.
3762 project.
3763
3763
3764 If no revision range is specified, the default is ``tip:0`` unless
3764 If no revision range is specified, the default is ``tip:0`` unless
3765 --follow is set, in which case the working directory parent is
3765 --follow is set, in which case the working directory parent is
3766 used as the starting revision.
3766 used as the starting revision.
3767
3767
3768 File history is shown without following rename or copy history of
3768 File history is shown without following rename or copy history of
3769 files. Use -f/--follow with a filename to follow history across
3769 files. Use -f/--follow with a filename to follow history across
3770 renames and copies. --follow without a filename will only show
3770 renames and copies. --follow without a filename will only show
3771 ancestors or descendants of the starting revision.
3771 ancestors or descendants of the starting revision.
3772
3772
3773 By default this command prints revision number and changeset id,
3773 By default this command prints revision number and changeset id,
3774 tags, non-trivial parents, user, date and time, and a summary for
3774 tags, non-trivial parents, user, date and time, and a summary for
3775 each commit. When the -v/--verbose switch is used, the list of
3775 each commit. When the -v/--verbose switch is used, the list of
3776 changed files and full commit message are shown.
3776 changed files and full commit message are shown.
3777
3777
3778 .. note::
3778 .. note::
3779 log -p/--patch may generate unexpected diff output for merge
3779 log -p/--patch may generate unexpected diff output for merge
3780 changesets, as it will only compare the merge changeset against
3780 changesets, as it will only compare the merge changeset against
3781 its first parent. Also, only files different from BOTH parents
3781 its first parent. Also, only files different from BOTH parents
3782 will appear in files:.
3782 will appear in files:.
3783
3783
3784 .. note::
3784 .. note::
3785 for performance reasons, log FILE may omit duplicate changes
3785 for performance reasons, log FILE may omit duplicate changes
3786 made on branches and will not show deletions. To see all
3786 made on branches and will not show deletions. To see all
3787 changes including duplicates and deletions, use the --removed
3787 changes including duplicates and deletions, use the --removed
3788 switch.
3788 switch.
3789
3789
3790 .. container:: verbose
3790 .. container:: verbose
3791
3791
3792 Some examples:
3792 Some examples:
3793
3793
3794 - changesets with full descriptions and file lists::
3794 - changesets with full descriptions and file lists::
3795
3795
3796 hg log -v
3796 hg log -v
3797
3797
3798 - changesets ancestral to the working directory::
3798 - changesets ancestral to the working directory::
3799
3799
3800 hg log -f
3800 hg log -f
3801
3801
3802 - last 10 commits on the current branch::
3802 - last 10 commits on the current branch::
3803
3803
3804 hg log -l 10 -b .
3804 hg log -l 10 -b .
3805
3805
3806 - changesets showing all modifications of a file, including removals::
3806 - changesets showing all modifications of a file, including removals::
3807
3807
3808 hg log --removed file.c
3808 hg log --removed file.c
3809
3809
3810 - all changesets that touch a directory, with diffs, excluding merges::
3810 - all changesets that touch a directory, with diffs, excluding merges::
3811
3811
3812 hg log -Mp lib/
3812 hg log -Mp lib/
3813
3813
3814 - all revision numbers that match a keyword::
3814 - all revision numbers that match a keyword::
3815
3815
3816 hg log -k bug --template "{rev}\\n"
3816 hg log -k bug --template "{rev}\\n"
3817
3817
3818 - check if a given changeset is included is a tagged release::
3818 - check if a given changeset is included is a tagged release::
3819
3819
3820 hg log -r "a21ccf and ancestor(1.9)"
3820 hg log -r "a21ccf and ancestor(1.9)"
3821
3821
3822 - find all changesets by some user in a date range::
3822 - find all changesets by some user in a date range::
3823
3823
3824 hg log -k alice -d "may 2008 to jul 2008"
3824 hg log -k alice -d "may 2008 to jul 2008"
3825
3825
3826 - summary of all changesets after the last tag::
3826 - summary of all changesets after the last tag::
3827
3827
3828 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3828 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3829
3829
3830 See :hg:`help dates` for a list of formats valid for -d/--date.
3830 See :hg:`help dates` for a list of formats valid for -d/--date.
3831
3831
3832 See :hg:`help revisions` and :hg:`help revsets` for more about
3832 See :hg:`help revisions` and :hg:`help revsets` for more about
3833 specifying revisions.
3833 specifying revisions.
3834
3834
3835 Returns 0 on success.
3835 Returns 0 on success.
3836 """
3836 """
3837
3837
3838 matchfn = scmutil.match(repo[None], pats, opts)
3838 matchfn = scmutil.match(repo[None], pats, opts)
3839 limit = cmdutil.loglimit(opts)
3839 limit = cmdutil.loglimit(opts)
3840 count = 0
3840 count = 0
3841
3841
3842 endrev = None
3842 endrev = None
3843 if opts.get('copies') and opts.get('rev'):
3843 if opts.get('copies') and opts.get('rev'):
3844 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3844 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3845
3845
3846 df = False
3846 df = False
3847 if opts["date"]:
3847 if opts["date"]:
3848 df = util.matchdate(opts["date"])
3848 df = util.matchdate(opts["date"])
3849
3849
3850 branches = opts.get('branch', []) + opts.get('only_branch', [])
3850 branches = opts.get('branch', []) + opts.get('only_branch', [])
3851 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3851 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3852
3852
3853 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3853 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3854 def prep(ctx, fns):
3854 def prep(ctx, fns):
3855 rev = ctx.rev()
3855 rev = ctx.rev()
3856 parents = [p for p in repo.changelog.parentrevs(rev)
3856 parents = [p for p in repo.changelog.parentrevs(rev)
3857 if p != nullrev]
3857 if p != nullrev]
3858 if opts.get('no_merges') and len(parents) == 2:
3858 if opts.get('no_merges') and len(parents) == 2:
3859 return
3859 return
3860 if opts.get('only_merges') and len(parents) != 2:
3860 if opts.get('only_merges') and len(parents) != 2:
3861 return
3861 return
3862 if opts.get('branch') and ctx.branch() not in opts['branch']:
3862 if opts.get('branch') and ctx.branch() not in opts['branch']:
3863 return
3863 return
3864 if not opts.get('hidden') and ctx.hidden():
3864 if not opts.get('hidden') and ctx.hidden():
3865 return
3865 return
3866 if df and not df(ctx.date()[0]):
3866 if df and not df(ctx.date()[0]):
3867 return
3867 return
3868
3868
3869 lower = encoding.lower
3869 lower = encoding.lower
3870 if opts.get('user'):
3870 if opts.get('user'):
3871 luser = lower(ctx.user())
3871 luser = lower(ctx.user())
3872 for k in [lower(x) for x in opts['user']]:
3872 for k in [lower(x) for x in opts['user']]:
3873 if (k in luser):
3873 if (k in luser):
3874 break
3874 break
3875 else:
3875 else:
3876 return
3876 return
3877 if opts.get('keyword'):
3877 if opts.get('keyword'):
3878 luser = lower(ctx.user())
3878 luser = lower(ctx.user())
3879 ldesc = lower(ctx.description())
3879 ldesc = lower(ctx.description())
3880 lfiles = lower(" ".join(ctx.files()))
3880 lfiles = lower(" ".join(ctx.files()))
3881 for k in [lower(x) for x in opts['keyword']]:
3881 for k in [lower(x) for x in opts['keyword']]:
3882 if (k in luser or k in ldesc or k in lfiles):
3882 if (k in luser or k in ldesc or k in lfiles):
3883 break
3883 break
3884 else:
3884 else:
3885 return
3885 return
3886
3886
3887 copies = None
3887 copies = None
3888 if opts.get('copies') and rev:
3888 if opts.get('copies') and rev:
3889 copies = []
3889 copies = []
3890 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3890 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3891 for fn in ctx.files():
3891 for fn in ctx.files():
3892 rename = getrenamed(fn, rev)
3892 rename = getrenamed(fn, rev)
3893 if rename:
3893 if rename:
3894 copies.append((fn, rename[0]))
3894 copies.append((fn, rename[0]))
3895
3895
3896 revmatchfn = None
3896 revmatchfn = None
3897 if opts.get('patch') or opts.get('stat'):
3897 if opts.get('patch') or opts.get('stat'):
3898 if opts.get('follow') or opts.get('follow_first'):
3898 if opts.get('follow') or opts.get('follow_first'):
3899 # note: this might be wrong when following through merges
3899 # note: this might be wrong when following through merges
3900 revmatchfn = scmutil.match(repo[None], fns, default='path')
3900 revmatchfn = scmutil.match(repo[None], fns, default='path')
3901 else:
3901 else:
3902 revmatchfn = matchfn
3902 revmatchfn = matchfn
3903
3903
3904 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3904 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3905
3905
3906 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3906 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3907 if count == limit:
3907 if count == limit:
3908 break
3908 break
3909 if displayer.flush(ctx.rev()):
3909 if displayer.flush(ctx.rev()):
3910 count += 1
3910 count += 1
3911 displayer.close()
3911 displayer.close()
3912
3912
3913 @command('manifest',
3913 @command('manifest',
3914 [('r', 'rev', '', _('revision to display'), _('REV')),
3914 [('r', 'rev', '', _('revision to display'), _('REV')),
3915 ('', 'all', False, _("list files from all revisions"))],
3915 ('', 'all', False, _("list files from all revisions"))],
3916 _('[-r REV]'))
3916 _('[-r REV]'))
3917 def manifest(ui, repo, node=None, rev=None, **opts):
3917 def manifest(ui, repo, node=None, rev=None, **opts):
3918 """output the current or given revision of the project manifest
3918 """output the current or given revision of the project manifest
3919
3919
3920 Print a list of version controlled files for the given revision.
3920 Print a list of version controlled files for the given revision.
3921 If no revision is given, the first parent of the working directory
3921 If no revision is given, the first parent of the working directory
3922 is used, or the null revision if no revision is checked out.
3922 is used, or the null revision if no revision is checked out.
3923
3923
3924 With -v, print file permissions, symlink and executable bits.
3924 With -v, print file permissions, symlink and executable bits.
3925 With --debug, print file revision hashes.
3925 With --debug, print file revision hashes.
3926
3926
3927 If option --all is specified, the list of all files from all revisions
3927 If option --all is specified, the list of all files from all revisions
3928 is printed. This includes deleted and renamed files.
3928 is printed. This includes deleted and renamed files.
3929
3929
3930 Returns 0 on success.
3930 Returns 0 on success.
3931 """
3931 """
3932 if opts.get('all'):
3932 if opts.get('all'):
3933 if rev or node:
3933 if rev or node:
3934 raise util.Abort(_("can't specify a revision with --all"))
3934 raise util.Abort(_("can't specify a revision with --all"))
3935
3935
3936 res = []
3936 res = []
3937 prefix = "data/"
3937 prefix = "data/"
3938 suffix = ".i"
3938 suffix = ".i"
3939 plen = len(prefix)
3939 plen = len(prefix)
3940 slen = len(suffix)
3940 slen = len(suffix)
3941 lock = repo.lock()
3941 lock = repo.lock()
3942 try:
3942 try:
3943 for fn, b, size in repo.store.datafiles():
3943 for fn, b, size in repo.store.datafiles():
3944 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3944 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3945 res.append(fn[plen:-slen])
3945 res.append(fn[plen:-slen])
3946 finally:
3946 finally:
3947 lock.release()
3947 lock.release()
3948 for f in sorted(res):
3948 for f in sorted(res):
3949 ui.write("%s\n" % f)
3949 ui.write("%s\n" % f)
3950 return
3950 return
3951
3951
3952 if rev and node:
3952 if rev and node:
3953 raise util.Abort(_("please specify just one revision"))
3953 raise util.Abort(_("please specify just one revision"))
3954
3954
3955 if not node:
3955 if not node:
3956 node = rev
3956 node = rev
3957
3957
3958 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3958 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3959 ctx = scmutil.revsingle(repo, node)
3959 ctx = scmutil.revsingle(repo, node)
3960 for f in ctx:
3960 for f in ctx:
3961 if ui.debugflag:
3961 if ui.debugflag:
3962 ui.write("%40s " % hex(ctx.manifest()[f]))
3962 ui.write("%40s " % hex(ctx.manifest()[f]))
3963 if ui.verbose:
3963 if ui.verbose:
3964 ui.write(decor[ctx.flags(f)])
3964 ui.write(decor[ctx.flags(f)])
3965 ui.write("%s\n" % f)
3965 ui.write("%s\n" % f)
3966
3966
3967 @command('^merge',
3967 @command('^merge',
3968 [('f', 'force', None, _('force a merge with outstanding changes')),
3968 [('f', 'force', None, _('force a merge with outstanding changes')),
3969 ('r', 'rev', '', _('revision to merge'), _('REV')),
3969 ('r', 'rev', '', _('revision to merge'), _('REV')),
3970 ('P', 'preview', None,
3970 ('P', 'preview', None,
3971 _('review revisions to merge (no merge is performed)'))
3971 _('review revisions to merge (no merge is performed)'))
3972 ] + mergetoolopts,
3972 ] + mergetoolopts,
3973 _('[-P] [-f] [[-r] REV]'))
3973 _('[-P] [-f] [[-r] REV]'))
3974 def merge(ui, repo, node=None, **opts):
3974 def merge(ui, repo, node=None, **opts):
3975 """merge working directory with another revision
3975 """merge working directory with another revision
3976
3976
3977 The current working directory is updated with all changes made in
3977 The current working directory is updated with all changes made in
3978 the requested revision since the last common predecessor revision.
3978 the requested revision since the last common predecessor revision.
3979
3979
3980 Files that changed between either parent are marked as changed for
3980 Files that changed between either parent are marked as changed for
3981 the next commit and a commit must be performed before any further
3981 the next commit and a commit must be performed before any further
3982 updates to the repository are allowed. The next commit will have
3982 updates to the repository are allowed. The next commit will have
3983 two parents.
3983 two parents.
3984
3984
3985 ``--tool`` can be used to specify the merge tool used for file
3985 ``--tool`` can be used to specify the merge tool used for file
3986 merges. It overrides the HGMERGE environment variable and your
3986 merges. It overrides the HGMERGE environment variable and your
3987 configuration files. See :hg:`help merge-tools` for options.
3987 configuration files. See :hg:`help merge-tools` for options.
3988
3988
3989 If no revision is specified, the working directory's parent is a
3989 If no revision is specified, the working directory's parent is a
3990 head revision, and the current branch contains exactly one other
3990 head revision, and the current branch contains exactly one other
3991 head, the other head is merged with by default. Otherwise, an
3991 head, the other head is merged with by default. Otherwise, an
3992 explicit revision with which to merge with must be provided.
3992 explicit revision with which to merge with must be provided.
3993
3993
3994 :hg:`resolve` must be used to resolve unresolved files.
3994 :hg:`resolve` must be used to resolve unresolved files.
3995
3995
3996 To undo an uncommitted merge, use :hg:`update --clean .` which
3996 To undo an uncommitted merge, use :hg:`update --clean .` which
3997 will check out a clean copy of the original merge parent, losing
3997 will check out a clean copy of the original merge parent, losing
3998 all changes.
3998 all changes.
3999
3999
4000 Returns 0 on success, 1 if there are unresolved files.
4000 Returns 0 on success, 1 if there are unresolved files.
4001 """
4001 """
4002
4002
4003 if opts.get('rev') and node:
4003 if opts.get('rev') and node:
4004 raise util.Abort(_("please specify just one revision"))
4004 raise util.Abort(_("please specify just one revision"))
4005 if not node:
4005 if not node:
4006 node = opts.get('rev')
4006 node = opts.get('rev')
4007
4007
4008 if not node:
4008 if not node:
4009 branch = repo[None].branch()
4009 branch = repo[None].branch()
4010 bheads = repo.branchheads(branch)
4010 bheads = repo.branchheads(branch)
4011 if len(bheads) > 2:
4011 if len(bheads) > 2:
4012 raise util.Abort(_("branch '%s' has %d heads - "
4012 raise util.Abort(_("branch '%s' has %d heads - "
4013 "please merge with an explicit rev")
4013 "please merge with an explicit rev")
4014 % (branch, len(bheads)),
4014 % (branch, len(bheads)),
4015 hint=_("run 'hg heads .' to see heads"))
4015 hint=_("run 'hg heads .' to see heads"))
4016
4016
4017 parent = repo.dirstate.p1()
4017 parent = repo.dirstate.p1()
4018 if len(bheads) == 1:
4018 if len(bheads) == 1:
4019 if len(repo.heads()) > 1:
4019 if len(repo.heads()) > 1:
4020 raise util.Abort(_("branch '%s' has one head - "
4020 raise util.Abort(_("branch '%s' has one head - "
4021 "please merge with an explicit rev")
4021 "please merge with an explicit rev")
4022 % branch,
4022 % branch,
4023 hint=_("run 'hg heads' to see all heads"))
4023 hint=_("run 'hg heads' to see all heads"))
4024 msg, hint = _('nothing to merge'), None
4024 msg, hint = _('nothing to merge'), None
4025 if parent != repo.lookup(branch):
4025 if parent != repo.lookup(branch):
4026 hint = _("use 'hg update' instead")
4026 hint = _("use 'hg update' instead")
4027 raise util.Abort(msg, hint=hint)
4027 raise util.Abort(msg, hint=hint)
4028
4028
4029 if parent not in bheads:
4029 if parent not in bheads:
4030 raise util.Abort(_('working directory not at a head revision'),
4030 raise util.Abort(_('working directory not at a head revision'),
4031 hint=_("use 'hg update' or merge with an "
4031 hint=_("use 'hg update' or merge with an "
4032 "explicit revision"))
4032 "explicit revision"))
4033 node = parent == bheads[0] and bheads[-1] or bheads[0]
4033 node = parent == bheads[0] and bheads[-1] or bheads[0]
4034 else:
4034 else:
4035 node = scmutil.revsingle(repo, node).node()
4035 node = scmutil.revsingle(repo, node).node()
4036
4036
4037 if opts.get('preview'):
4037 if opts.get('preview'):
4038 # find nodes that are ancestors of p2 but not of p1
4038 # find nodes that are ancestors of p2 but not of p1
4039 p1 = repo.lookup('.')
4039 p1 = repo.lookup('.')
4040 p2 = repo.lookup(node)
4040 p2 = repo.lookup(node)
4041 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4041 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4042
4042
4043 displayer = cmdutil.show_changeset(ui, repo, opts)
4043 displayer = cmdutil.show_changeset(ui, repo, opts)
4044 for node in nodes:
4044 for node in nodes:
4045 displayer.show(repo[node])
4045 displayer.show(repo[node])
4046 displayer.close()
4046 displayer.close()
4047 return 0
4047 return 0
4048
4048
4049 try:
4049 try:
4050 # ui.forcemerge is an internal variable, do not document
4050 # ui.forcemerge is an internal variable, do not document
4051 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4051 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4052 return hg.merge(repo, node, force=opts.get('force'))
4052 return hg.merge(repo, node, force=opts.get('force'))
4053 finally:
4053 finally:
4054 ui.setconfig('ui', 'forcemerge', '')
4054 ui.setconfig('ui', 'forcemerge', '')
4055
4055
4056 @command('outgoing|out',
4056 @command('outgoing|out',
4057 [('f', 'force', None, _('run even when the destination is unrelated')),
4057 [('f', 'force', None, _('run even when the destination is unrelated')),
4058 ('r', 'rev', [],
4058 ('r', 'rev', [],
4059 _('a changeset intended to be included in the destination'), _('REV')),
4059 _('a changeset intended to be included in the destination'), _('REV')),
4060 ('n', 'newest-first', None, _('show newest record first')),
4060 ('n', 'newest-first', None, _('show newest record first')),
4061 ('B', 'bookmarks', False, _('compare bookmarks')),
4061 ('B', 'bookmarks', False, _('compare bookmarks')),
4062 ('b', 'branch', [], _('a specific branch you would like to push'),
4062 ('b', 'branch', [], _('a specific branch you would like to push'),
4063 _('BRANCH')),
4063 _('BRANCH')),
4064 ] + logopts + remoteopts + subrepoopts,
4064 ] + logopts + remoteopts + subrepoopts,
4065 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4065 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4066 def outgoing(ui, repo, dest=None, **opts):
4066 def outgoing(ui, repo, dest=None, **opts):
4067 """show changesets not found in the destination
4067 """show changesets not found in the destination
4068
4068
4069 Show changesets not found in the specified destination repository
4069 Show changesets not found in the specified destination repository
4070 or the default push location. These are the changesets that would
4070 or the default push location. These are the changesets that would
4071 be pushed if a push was requested.
4071 be pushed if a push was requested.
4072
4072
4073 See pull for details of valid destination formats.
4073 See pull for details of valid destination formats.
4074
4074
4075 Returns 0 if there are outgoing changes, 1 otherwise.
4075 Returns 0 if there are outgoing changes, 1 otherwise.
4076 """
4076 """
4077
4077
4078 if opts.get('bookmarks'):
4078 if opts.get('bookmarks'):
4079 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4079 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4080 dest, branches = hg.parseurl(dest, opts.get('branch'))
4080 dest, branches = hg.parseurl(dest, opts.get('branch'))
4081 other = hg.peer(repo, opts, dest)
4081 other = hg.peer(repo, opts, dest)
4082 if 'bookmarks' not in other.listkeys('namespaces'):
4082 if 'bookmarks' not in other.listkeys('namespaces'):
4083 ui.warn(_("remote doesn't support bookmarks\n"))
4083 ui.warn(_("remote doesn't support bookmarks\n"))
4084 return 0
4084 return 0
4085 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4085 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4086 return bookmarks.diff(ui, other, repo)
4086 return bookmarks.diff(ui, other, repo)
4087
4087
4088 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4088 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4089 try:
4089 try:
4090 return hg.outgoing(ui, repo, dest, opts)
4090 return hg.outgoing(ui, repo, dest, opts)
4091 finally:
4091 finally:
4092 del repo._subtoppath
4092 del repo._subtoppath
4093
4093
4094 @command('parents',
4094 @command('parents',
4095 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4095 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4096 ] + templateopts,
4096 ] + templateopts,
4097 _('[-r REV] [FILE]'))
4097 _('[-r REV] [FILE]'))
4098 def parents(ui, repo, file_=None, **opts):
4098 def parents(ui, repo, file_=None, **opts):
4099 """show the parents of the working directory or revision
4099 """show the parents of the working directory or revision
4100
4100
4101 Print the working directory's parent revisions. If a revision is
4101 Print the working directory's parent revisions. If a revision is
4102 given via -r/--rev, the parent of that revision will be printed.
4102 given via -r/--rev, the parent of that revision will be printed.
4103 If a file argument is given, the revision in which the file was
4103 If a file argument is given, the revision in which the file was
4104 last changed (before the working directory revision or the
4104 last changed (before the working directory revision or the
4105 argument to --rev if given) is printed.
4105 argument to --rev if given) is printed.
4106
4106
4107 Returns 0 on success.
4107 Returns 0 on success.
4108 """
4108 """
4109
4109
4110 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4110 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4111
4111
4112 if file_:
4112 if file_:
4113 m = scmutil.match(ctx, (file_,), opts)
4113 m = scmutil.match(ctx, (file_,), opts)
4114 if m.anypats() or len(m.files()) != 1:
4114 if m.anypats() or len(m.files()) != 1:
4115 raise util.Abort(_('can only specify an explicit filename'))
4115 raise util.Abort(_('can only specify an explicit filename'))
4116 file_ = m.files()[0]
4116 file_ = m.files()[0]
4117 filenodes = []
4117 filenodes = []
4118 for cp in ctx.parents():
4118 for cp in ctx.parents():
4119 if not cp:
4119 if not cp:
4120 continue
4120 continue
4121 try:
4121 try:
4122 filenodes.append(cp.filenode(file_))
4122 filenodes.append(cp.filenode(file_))
4123 except error.LookupError:
4123 except error.LookupError:
4124 pass
4124 pass
4125 if not filenodes:
4125 if not filenodes:
4126 raise util.Abort(_("'%s' not found in manifest!") % file_)
4126 raise util.Abort(_("'%s' not found in manifest!") % file_)
4127 fl = repo.file(file_)
4127 fl = repo.file(file_)
4128 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4128 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4129 else:
4129 else:
4130 p = [cp.node() for cp in ctx.parents()]
4130 p = [cp.node() for cp in ctx.parents()]
4131
4131
4132 displayer = cmdutil.show_changeset(ui, repo, opts)
4132 displayer = cmdutil.show_changeset(ui, repo, opts)
4133 for n in p:
4133 for n in p:
4134 if n != nullid:
4134 if n != nullid:
4135 displayer.show(repo[n])
4135 displayer.show(repo[n])
4136 displayer.close()
4136 displayer.close()
4137
4137
4138 @command('paths', [], _('[NAME]'))
4138 @command('paths', [], _('[NAME]'))
4139 def paths(ui, repo, search=None):
4139 def paths(ui, repo, search=None):
4140 """show aliases for remote repositories
4140 """show aliases for remote repositories
4141
4141
4142 Show definition of symbolic path name NAME. If no name is given,
4142 Show definition of symbolic path name NAME. If no name is given,
4143 show definition of all available names.
4143 show definition of all available names.
4144
4144
4145 Option -q/--quiet suppresses all output when searching for NAME
4145 Option -q/--quiet suppresses all output when searching for NAME
4146 and shows only the path names when listing all definitions.
4146 and shows only the path names when listing all definitions.
4147
4147
4148 Path names are defined in the [paths] section of your
4148 Path names are defined in the [paths] section of your
4149 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4149 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4150 repository, ``.hg/hgrc`` is used, too.
4150 repository, ``.hg/hgrc`` is used, too.
4151
4151
4152 The path names ``default`` and ``default-push`` have a special
4152 The path names ``default`` and ``default-push`` have a special
4153 meaning. When performing a push or pull operation, they are used
4153 meaning. When performing a push or pull operation, they are used
4154 as fallbacks if no location is specified on the command-line.
4154 as fallbacks if no location is specified on the command-line.
4155 When ``default-push`` is set, it will be used for push and
4155 When ``default-push`` is set, it will be used for push and
4156 ``default`` will be used for pull; otherwise ``default`` is used
4156 ``default`` will be used for pull; otherwise ``default`` is used
4157 as the fallback for both. When cloning a repository, the clone
4157 as the fallback for both. When cloning a repository, the clone
4158 source is written as ``default`` in ``.hg/hgrc``. Note that
4158 source is written as ``default`` in ``.hg/hgrc``. Note that
4159 ``default`` and ``default-push`` apply to all inbound (e.g.
4159 ``default`` and ``default-push`` apply to all inbound (e.g.
4160 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4160 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4161 :hg:`bundle`) operations.
4161 :hg:`bundle`) operations.
4162
4162
4163 See :hg:`help urls` for more information.
4163 See :hg:`help urls` for more information.
4164
4164
4165 Returns 0 on success.
4165 Returns 0 on success.
4166 """
4166 """
4167 if search:
4167 if search:
4168 for name, path in ui.configitems("paths"):
4168 for name, path in ui.configitems("paths"):
4169 if name == search:
4169 if name == search:
4170 ui.status("%s\n" % util.hidepassword(path))
4170 ui.status("%s\n" % util.hidepassword(path))
4171 return
4171 return
4172 if not ui.quiet:
4172 if not ui.quiet:
4173 ui.warn(_("not found!\n"))
4173 ui.warn(_("not found!\n"))
4174 return 1
4174 return 1
4175 else:
4175 else:
4176 for name, path in ui.configitems("paths"):
4176 for name, path in ui.configitems("paths"):
4177 if ui.quiet:
4177 if ui.quiet:
4178 ui.write("%s\n" % name)
4178 ui.write("%s\n" % name)
4179 else:
4179 else:
4180 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4180 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4181
4181
4182 @command('^phase',
4182 @command('^phase',
4183 [('p', 'public', False, _('set changeset phase to public')),
4183 [('p', 'public', False, _('set changeset phase to public')),
4184 ('d', 'draft', False, _('set changeset phase to draft')),
4184 ('d', 'draft', False, _('set changeset phase to draft')),
4185 ('s', 'secret', False, _('set changeset phase to secret')),
4185 ('s', 'secret', False, _('set changeset phase to secret')),
4186 ('f', 'force', False, _('allow to move boundary backward')),
4186 ('f', 'force', False, _('allow to move boundary backward')),
4187 ('r', 'rev', [], _('target revision'), _('REV')),
4187 ('r', 'rev', [], _('target revision'), _('REV')),
4188 ],
4188 ],
4189 _('[-p|-d|-s] [-f] [-r] REV...'))
4189 _('[-p|-d|-s] [-f] [-r] REV...'))
4190 def phase(ui, repo, *revs, **opts):
4190 def phase(ui, repo, *revs, **opts):
4191 """set or show the current phase name
4191 """set or show the current phase name
4192
4192
4193 With no argument, show the phase name of specified revisions.
4193 With no argument, show the phase name of specified revisions.
4194
4194
4195 With one of -p/--public, -d/--draft or -s/--secret, change the
4195 With one of -p/--public, -d/--draft or -s/--secret, change the
4196 phase value of the specified revisions.
4196 phase value of the specified revisions.
4197
4197
4198 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4198 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4199 lower phase to an higher phase. Phases are ordered as follows::
4199 lower phase to an higher phase. Phases are ordered as follows::
4200
4200
4201 public < draft < secret
4201 public < draft < secret
4202
4202
4203 Return 0 on success, 1 if no phases were changed.
4203 Return 0 on success, 1 if no phases were changed.
4204 """
4204 """
4205 # search for a unique phase argument
4205 # search for a unique phase argument
4206 targetphase = None
4206 targetphase = None
4207 for idx, name in enumerate(phases.phasenames):
4207 for idx, name in enumerate(phases.phasenames):
4208 if opts[name]:
4208 if opts[name]:
4209 if targetphase is not None:
4209 if targetphase is not None:
4210 raise util.Abort(_('only one phase can be specified'))
4210 raise util.Abort(_('only one phase can be specified'))
4211 targetphase = idx
4211 targetphase = idx
4212
4212
4213 # look for specified revision
4213 # look for specified revision
4214 revs = list(revs)
4214 revs = list(revs)
4215 revs.extend(opts['rev'])
4215 revs.extend(opts['rev'])
4216 if not revs:
4216 if not revs:
4217 raise util.Abort(_('no revisions specified!'))
4217 raise util.Abort(_('no revisions specified!'))
4218
4218
4219 lock = None
4219 lock = None
4220 ret = 0
4220 ret = 0
4221 if targetphase is None:
4221 if targetphase is None:
4222 # display
4222 # display
4223 for ctx in repo.set('%lr', revs):
4223 for ctx in repo.set('%lr', revs):
4224 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4224 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4225 else:
4225 else:
4226 lock = repo.lock()
4226 lock = repo.lock()
4227 try:
4227 try:
4228 # set phase
4228 # set phase
4229 nodes = [ctx.node() for ctx in repo.set('%lr', revs)]
4229 nodes = [ctx.node() for ctx in repo.set('%lr', revs)]
4230 if not nodes:
4230 if not nodes:
4231 raise util.Abort(_('empty revision set'))
4231 raise util.Abort(_('empty revision set'))
4232 olddata = repo._phaserev[:]
4232 olddata = repo._phaserev[:]
4233 phases.advanceboundary(repo, targetphase, nodes)
4233 phases.advanceboundary(repo, targetphase, nodes)
4234 if opts['force']:
4234 if opts['force']:
4235 phases.retractboundary(repo, targetphase, nodes)
4235 phases.retractboundary(repo, targetphase, nodes)
4236 finally:
4236 finally:
4237 lock.release()
4237 lock.release()
4238 if olddata is not None:
4238 if olddata is not None:
4239 changes = 0
4239 changes = 0
4240 newdata = repo._phaserev
4240 newdata = repo._phaserev
4241 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4241 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4242 if changes:
4242 if changes:
4243 ui.note(_('phase change for %i changesets\n') % changes)
4243 ui.note(_('phase change for %i changesets\n') % changes)
4244 else:
4244 else:
4245 ui.warn(_('no phases changed\n'))
4245 ui.warn(_('no phases changed\n'))
4246 ret = 1
4246 ret = 1
4247 return ret
4247 return ret
4248
4248
4249 def postincoming(ui, repo, modheads, optupdate, checkout):
4249 def postincoming(ui, repo, modheads, optupdate, checkout):
4250 if modheads == 0:
4250 if modheads == 0:
4251 return
4251 return
4252 if optupdate:
4252 if optupdate:
4253 try:
4253 try:
4254 return hg.update(repo, checkout)
4254 return hg.update(repo, checkout)
4255 except util.Abort, inst:
4255 except util.Abort, inst:
4256 ui.warn(_("not updating: %s\n" % str(inst)))
4256 ui.warn(_("not updating: %s\n" % str(inst)))
4257 return 0
4257 return 0
4258 if modheads > 1:
4258 if modheads > 1:
4259 currentbranchheads = len(repo.branchheads())
4259 currentbranchheads = len(repo.branchheads())
4260 if currentbranchheads == modheads:
4260 if currentbranchheads == modheads:
4261 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4261 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4262 elif currentbranchheads > 1:
4262 elif currentbranchheads > 1:
4263 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4263 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4264 else:
4264 else:
4265 ui.status(_("(run 'hg heads' to see heads)\n"))
4265 ui.status(_("(run 'hg heads' to see heads)\n"))
4266 else:
4266 else:
4267 ui.status(_("(run 'hg update' to get a working copy)\n"))
4267 ui.status(_("(run 'hg update' to get a working copy)\n"))
4268
4268
4269 @command('^pull',
4269 @command('^pull',
4270 [('u', 'update', None,
4270 [('u', 'update', None,
4271 _('update to new branch head if changesets were pulled')),
4271 _('update to new branch head if changesets were pulled')),
4272 ('f', 'force', None, _('run even when remote repository is unrelated')),
4272 ('f', 'force', None, _('run even when remote repository is unrelated')),
4273 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4273 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4274 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4274 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4275 ('b', 'branch', [], _('a specific branch you would like to pull'),
4275 ('b', 'branch', [], _('a specific branch you would like to pull'),
4276 _('BRANCH')),
4276 _('BRANCH')),
4277 ] + remoteopts,
4277 ] + remoteopts,
4278 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4278 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4279 def pull(ui, repo, source="default", **opts):
4279 def pull(ui, repo, source="default", **opts):
4280 """pull changes from the specified source
4280 """pull changes from the specified source
4281
4281
4282 Pull changes from a remote repository to a local one.
4282 Pull changes from a remote repository to a local one.
4283
4283
4284 This finds all changes from the repository at the specified path
4284 This finds all changes from the repository at the specified path
4285 or URL and adds them to a local repository (the current one unless
4285 or URL and adds them to a local repository (the current one unless
4286 -R is specified). By default, this does not update the copy of the
4286 -R is specified). By default, this does not update the copy of the
4287 project in the working directory.
4287 project in the working directory.
4288
4288
4289 Use :hg:`incoming` if you want to see what would have been added
4289 Use :hg:`incoming` if you want to see what would have been added
4290 by a pull at the time you issued this command. If you then decide
4290 by a pull at the time you issued this command. If you then decide
4291 to add those changes to the repository, you should use :hg:`pull
4291 to add those changes to the repository, you should use :hg:`pull
4292 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4292 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4293
4293
4294 If SOURCE is omitted, the 'default' path will be used.
4294 If SOURCE is omitted, the 'default' path will be used.
4295 See :hg:`help urls` for more information.
4295 See :hg:`help urls` for more information.
4296
4296
4297 Returns 0 on success, 1 if an update had unresolved files.
4297 Returns 0 on success, 1 if an update had unresolved files.
4298 """
4298 """
4299 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4299 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4300 other = hg.peer(repo, opts, source)
4300 other = hg.peer(repo, opts, source)
4301 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4301 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4302 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4302 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4303
4303
4304 if opts.get('bookmark'):
4304 if opts.get('bookmark'):
4305 if not revs:
4305 if not revs:
4306 revs = []
4306 revs = []
4307 rb = other.listkeys('bookmarks')
4307 rb = other.listkeys('bookmarks')
4308 for b in opts['bookmark']:
4308 for b in opts['bookmark']:
4309 if b not in rb:
4309 if b not in rb:
4310 raise util.Abort(_('remote bookmark %s not found!') % b)
4310 raise util.Abort(_('remote bookmark %s not found!') % b)
4311 revs.append(rb[b])
4311 revs.append(rb[b])
4312
4312
4313 if revs:
4313 if revs:
4314 try:
4314 try:
4315 revs = [other.lookup(rev) for rev in revs]
4315 revs = [other.lookup(rev) for rev in revs]
4316 except error.CapabilityError:
4316 except error.CapabilityError:
4317 err = _("other repository doesn't support revision lookup, "
4317 err = _("other repository doesn't support revision lookup, "
4318 "so a rev cannot be specified.")
4318 "so a rev cannot be specified.")
4319 raise util.Abort(err)
4319 raise util.Abort(err)
4320
4320
4321 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4321 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4322 bookmarks.updatefromremote(ui, repo, other, source)
4322 bookmarks.updatefromremote(ui, repo, other, source)
4323 if checkout:
4323 if checkout:
4324 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4324 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4325 repo._subtoppath = source
4325 repo._subtoppath = source
4326 try:
4326 try:
4327 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4327 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4328
4328
4329 finally:
4329 finally:
4330 del repo._subtoppath
4330 del repo._subtoppath
4331
4331
4332 # update specified bookmarks
4332 # update specified bookmarks
4333 if opts.get('bookmark'):
4333 if opts.get('bookmark'):
4334 for b in opts['bookmark']:
4334 for b in opts['bookmark']:
4335 # explicit pull overrides local bookmark if any
4335 # explicit pull overrides local bookmark if any
4336 ui.status(_("importing bookmark %s\n") % b)
4336 ui.status(_("importing bookmark %s\n") % b)
4337 repo._bookmarks[b] = repo[rb[b]].node()
4337 repo._bookmarks[b] = repo[rb[b]].node()
4338 bookmarks.write(repo)
4338 bookmarks.write(repo)
4339
4339
4340 return ret
4340 return ret
4341
4341
4342 @command('^push',
4342 @command('^push',
4343 [('f', 'force', None, _('force push')),
4343 [('f', 'force', None, _('force push')),
4344 ('r', 'rev', [],
4344 ('r', 'rev', [],
4345 _('a changeset intended to be included in the destination'),
4345 _('a changeset intended to be included in the destination'),
4346 _('REV')),
4346 _('REV')),
4347 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4347 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4348 ('b', 'branch', [],
4348 ('b', 'branch', [],
4349 _('a specific branch you would like to push'), _('BRANCH')),
4349 _('a specific branch you would like to push'), _('BRANCH')),
4350 ('', 'new-branch', False, _('allow pushing a new branch')),
4350 ('', 'new-branch', False, _('allow pushing a new branch')),
4351 ] + remoteopts,
4351 ] + remoteopts,
4352 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4352 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4353 def push(ui, repo, dest=None, **opts):
4353 def push(ui, repo, dest=None, **opts):
4354 """push changes to the specified destination
4354 """push changes to the specified destination
4355
4355
4356 Push changesets from the local repository to the specified
4356 Push changesets from the local repository to the specified
4357 destination.
4357 destination.
4358
4358
4359 This operation is symmetrical to pull: it is identical to a pull
4359 This operation is symmetrical to pull: it is identical to a pull
4360 in the destination repository from the current one.
4360 in the destination repository from the current one.
4361
4361
4362 By default, push will not allow creation of new heads at the
4362 By default, push will not allow creation of new heads at the
4363 destination, since multiple heads would make it unclear which head
4363 destination, since multiple heads would make it unclear which head
4364 to use. In this situation, it is recommended to pull and merge
4364 to use. In this situation, it is recommended to pull and merge
4365 before pushing.
4365 before pushing.
4366
4366
4367 Use --new-branch if you want to allow push to create a new named
4367 Use --new-branch if you want to allow push to create a new named
4368 branch that is not present at the destination. This allows you to
4368 branch that is not present at the destination. This allows you to
4369 only create a new branch without forcing other changes.
4369 only create a new branch without forcing other changes.
4370
4370
4371 Use -f/--force to override the default behavior and push all
4371 Use -f/--force to override the default behavior and push all
4372 changesets on all branches.
4372 changesets on all branches.
4373
4373
4374 If -r/--rev is used, the specified revision and all its ancestors
4374 If -r/--rev is used, the specified revision and all its ancestors
4375 will be pushed to the remote repository.
4375 will be pushed to the remote repository.
4376
4376
4377 Please see :hg:`help urls` for important details about ``ssh://``
4377 Please see :hg:`help urls` for important details about ``ssh://``
4378 URLs. If DESTINATION is omitted, a default path will be used.
4378 URLs. If DESTINATION is omitted, a default path will be used.
4379
4379
4380 Returns 0 if push was successful, 1 if nothing to push.
4380 Returns 0 if push was successful, 1 if nothing to push.
4381 """
4381 """
4382
4382
4383 if opts.get('bookmark'):
4383 if opts.get('bookmark'):
4384 for b in opts['bookmark']:
4384 for b in opts['bookmark']:
4385 # translate -B options to -r so changesets get pushed
4385 # translate -B options to -r so changesets get pushed
4386 if b in repo._bookmarks:
4386 if b in repo._bookmarks:
4387 opts.setdefault('rev', []).append(b)
4387 opts.setdefault('rev', []).append(b)
4388 else:
4388 else:
4389 # if we try to push a deleted bookmark, translate it to null
4389 # if we try to push a deleted bookmark, translate it to null
4390 # this lets simultaneous -r, -b options continue working
4390 # this lets simultaneous -r, -b options continue working
4391 opts.setdefault('rev', []).append("null")
4391 opts.setdefault('rev', []).append("null")
4392
4392
4393 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4393 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4394 dest, branches = hg.parseurl(dest, opts.get('branch'))
4394 dest, branches = hg.parseurl(dest, opts.get('branch'))
4395 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4395 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4396 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4396 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4397 other = hg.peer(repo, opts, dest)
4397 other = hg.peer(repo, opts, dest)
4398 if revs:
4398 if revs:
4399 revs = [repo.lookup(rev) for rev in revs]
4399 revs = [repo.lookup(rev) for rev in revs]
4400
4400
4401 repo._subtoppath = dest
4401 repo._subtoppath = dest
4402 try:
4402 try:
4403 # push subrepos depth-first for coherent ordering
4403 # push subrepos depth-first for coherent ordering
4404 c = repo['']
4404 c = repo['']
4405 subs = c.substate # only repos that are committed
4405 subs = c.substate # only repos that are committed
4406 for s in sorted(subs):
4406 for s in sorted(subs):
4407 if not c.sub(s).push(opts):
4407 if not c.sub(s).push(opts):
4408 return False
4408 return False
4409 finally:
4409 finally:
4410 del repo._subtoppath
4410 del repo._subtoppath
4411 result = repo.push(other, opts.get('force'), revs=revs,
4411 result = repo.push(other, opts.get('force'), revs=revs,
4412 newbranch=opts.get('new_branch'))
4412 newbranch=opts.get('new_branch'))
4413
4413
4414 result = (result == 0)
4414 result = (result == 0)
4415
4415
4416 if opts.get('bookmark'):
4416 if opts.get('bookmark'):
4417 rb = other.listkeys('bookmarks')
4417 rb = other.listkeys('bookmarks')
4418 for b in opts['bookmark']:
4418 for b in opts['bookmark']:
4419 # explicit push overrides remote bookmark if any
4419 # explicit push overrides remote bookmark if any
4420 if b in repo._bookmarks:
4420 if b in repo._bookmarks:
4421 ui.status(_("exporting bookmark %s\n") % b)
4421 ui.status(_("exporting bookmark %s\n") % b)
4422 new = repo[b].hex()
4422 new = repo[b].hex()
4423 elif b in rb:
4423 elif b in rb:
4424 ui.status(_("deleting remote bookmark %s\n") % b)
4424 ui.status(_("deleting remote bookmark %s\n") % b)
4425 new = '' # delete
4425 new = '' # delete
4426 else:
4426 else:
4427 ui.warn(_('bookmark %s does not exist on the local '
4427 ui.warn(_('bookmark %s does not exist on the local '
4428 'or remote repository!\n') % b)
4428 'or remote repository!\n') % b)
4429 return 2
4429 return 2
4430 old = rb.get(b, '')
4430 old = rb.get(b, '')
4431 r = other.pushkey('bookmarks', b, old, new)
4431 r = other.pushkey('bookmarks', b, old, new)
4432 if not r:
4432 if not r:
4433 ui.warn(_('updating bookmark %s failed!\n') % b)
4433 ui.warn(_('updating bookmark %s failed!\n') % b)
4434 if not result:
4434 if not result:
4435 result = 2
4435 result = 2
4436
4436
4437 return result
4437 return result
4438
4438
4439 @command('recover', [])
4439 @command('recover', [])
4440 def recover(ui, repo):
4440 def recover(ui, repo):
4441 """roll back an interrupted transaction
4441 """roll back an interrupted transaction
4442
4442
4443 Recover from an interrupted commit or pull.
4443 Recover from an interrupted commit or pull.
4444
4444
4445 This command tries to fix the repository status after an
4445 This command tries to fix the repository status after an
4446 interrupted operation. It should only be necessary when Mercurial
4446 interrupted operation. It should only be necessary when Mercurial
4447 suggests it.
4447 suggests it.
4448
4448
4449 Returns 0 if successful, 1 if nothing to recover or verify fails.
4449 Returns 0 if successful, 1 if nothing to recover or verify fails.
4450 """
4450 """
4451 if repo.recover():
4451 if repo.recover():
4452 return hg.verify(repo)
4452 return hg.verify(repo)
4453 return 1
4453 return 1
4454
4454
4455 @command('^remove|rm',
4455 @command('^remove|rm',
4456 [('A', 'after', None, _('record delete for missing files')),
4456 [('A', 'after', None, _('record delete for missing files')),
4457 ('f', 'force', None,
4457 ('f', 'force', None,
4458 _('remove (and delete) file even if added or modified')),
4458 _('remove (and delete) file even if added or modified')),
4459 ] + walkopts,
4459 ] + walkopts,
4460 _('[OPTION]... FILE...'))
4460 _('[OPTION]... FILE...'))
4461 def remove(ui, repo, *pats, **opts):
4461 def remove(ui, repo, *pats, **opts):
4462 """remove the specified files on the next commit
4462 """remove the specified files on the next commit
4463
4463
4464 Schedule the indicated files for removal from the current branch.
4464 Schedule the indicated files for removal from the current branch.
4465
4465
4466 This command schedules the files to be removed at the next commit.
4466 This command schedules the files to be removed at the next commit.
4467 To undo a remove before that, see :hg:`revert`. To undo added
4467 To undo a remove before that, see :hg:`revert`. To undo added
4468 files, see :hg:`forget`.
4468 files, see :hg:`forget`.
4469
4469
4470 .. container:: verbose
4470 .. container:: verbose
4471
4471
4472 -A/--after can be used to remove only files that have already
4472 -A/--after can be used to remove only files that have already
4473 been deleted, -f/--force can be used to force deletion, and -Af
4473 been deleted, -f/--force can be used to force deletion, and -Af
4474 can be used to remove files from the next revision without
4474 can be used to remove files from the next revision without
4475 deleting them from the working directory.
4475 deleting them from the working directory.
4476
4476
4477 The following table details the behavior of remove for different
4477 The following table details the behavior of remove for different
4478 file states (columns) and option combinations (rows). The file
4478 file states (columns) and option combinations (rows). The file
4479 states are Added [A], Clean [C], Modified [M] and Missing [!]
4479 states are Added [A], Clean [C], Modified [M] and Missing [!]
4480 (as reported by :hg:`status`). The actions are Warn, Remove
4480 (as reported by :hg:`status`). The actions are Warn, Remove
4481 (from branch) and Delete (from disk):
4481 (from branch) and Delete (from disk):
4482
4482
4483 ======= == == == ==
4483 ======= == == == ==
4484 A C M !
4484 A C M !
4485 ======= == == == ==
4485 ======= == == == ==
4486 none W RD W R
4486 none W RD W R
4487 -f R RD RD R
4487 -f R RD RD R
4488 -A W W W R
4488 -A W W W R
4489 -Af R R R R
4489 -Af R R R R
4490 ======= == == == ==
4490 ======= == == == ==
4491
4491
4492 Note that remove never deletes files in Added [A] state from the
4492 Note that remove never deletes files in Added [A] state from the
4493 working directory, not even if option --force is specified.
4493 working directory, not even if option --force is specified.
4494
4494
4495 Returns 0 on success, 1 if any warnings encountered.
4495 Returns 0 on success, 1 if any warnings encountered.
4496 """
4496 """
4497
4497
4498 ret = 0
4498 ret = 0
4499 after, force = opts.get('after'), opts.get('force')
4499 after, force = opts.get('after'), opts.get('force')
4500 if not pats and not after:
4500 if not pats and not after:
4501 raise util.Abort(_('no files specified'))
4501 raise util.Abort(_('no files specified'))
4502
4502
4503 m = scmutil.match(repo[None], pats, opts)
4503 m = scmutil.match(repo[None], pats, opts)
4504 s = repo.status(match=m, clean=True)
4504 s = repo.status(match=m, clean=True)
4505 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4505 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4506
4506
4507 for f in m.files():
4507 for f in m.files():
4508 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4508 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4509 if os.path.exists(m.rel(f)):
4509 if os.path.exists(m.rel(f)):
4510 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4510 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4511 ret = 1
4511 ret = 1
4512
4512
4513 if force:
4513 if force:
4514 list = modified + deleted + clean + added
4514 list = modified + deleted + clean + added
4515 elif after:
4515 elif after:
4516 list = deleted
4516 list = deleted
4517 for f in modified + added + clean:
4517 for f in modified + added + clean:
4518 ui.warn(_('not removing %s: file still exists (use -f'
4518 ui.warn(_('not removing %s: file still exists (use -f'
4519 ' to force removal)\n') % m.rel(f))
4519 ' to force removal)\n') % m.rel(f))
4520 ret = 1
4520 ret = 1
4521 else:
4521 else:
4522 list = deleted + clean
4522 list = deleted + clean
4523 for f in modified:
4523 for f in modified:
4524 ui.warn(_('not removing %s: file is modified (use -f'
4524 ui.warn(_('not removing %s: file is modified (use -f'
4525 ' to force removal)\n') % m.rel(f))
4525 ' to force removal)\n') % m.rel(f))
4526 ret = 1
4526 ret = 1
4527 for f in added:
4527 for f in added:
4528 ui.warn(_('not removing %s: file has been marked for add'
4528 ui.warn(_('not removing %s: file has been marked for add'
4529 ' (use forget to undo)\n') % m.rel(f))
4529 ' (use forget to undo)\n') % m.rel(f))
4530 ret = 1
4530 ret = 1
4531
4531
4532 for f in sorted(list):
4532 for f in sorted(list):
4533 if ui.verbose or not m.exact(f):
4533 if ui.verbose or not m.exact(f):
4534 ui.status(_('removing %s\n') % m.rel(f))
4534 ui.status(_('removing %s\n') % m.rel(f))
4535
4535
4536 wlock = repo.wlock()
4536 wlock = repo.wlock()
4537 try:
4537 try:
4538 if not after:
4538 if not after:
4539 for f in list:
4539 for f in list:
4540 if f in added:
4540 if f in added:
4541 continue # we never unlink added files on remove
4541 continue # we never unlink added files on remove
4542 try:
4542 try:
4543 util.unlinkpath(repo.wjoin(f))
4543 util.unlinkpath(repo.wjoin(f))
4544 except OSError, inst:
4544 except OSError, inst:
4545 if inst.errno != errno.ENOENT:
4545 if inst.errno != errno.ENOENT:
4546 raise
4546 raise
4547 repo[None].forget(list)
4547 repo[None].forget(list)
4548 finally:
4548 finally:
4549 wlock.release()
4549 wlock.release()
4550
4550
4551 return ret
4551 return ret
4552
4552
4553 @command('rename|move|mv',
4553 @command('rename|move|mv',
4554 [('A', 'after', None, _('record a rename that has already occurred')),
4554 [('A', 'after', None, _('record a rename that has already occurred')),
4555 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4555 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4556 ] + walkopts + dryrunopts,
4556 ] + walkopts + dryrunopts,
4557 _('[OPTION]... SOURCE... DEST'))
4557 _('[OPTION]... SOURCE... DEST'))
4558 def rename(ui, repo, *pats, **opts):
4558 def rename(ui, repo, *pats, **opts):
4559 """rename files; equivalent of copy + remove
4559 """rename files; equivalent of copy + remove
4560
4560
4561 Mark dest as copies of sources; mark sources for deletion. If dest
4561 Mark dest as copies of sources; mark sources for deletion. If dest
4562 is a directory, copies are put in that directory. If dest is a
4562 is a directory, copies are put in that directory. If dest is a
4563 file, there can only be one source.
4563 file, there can only be one source.
4564
4564
4565 By default, this command copies the contents of files as they
4565 By default, this command copies the contents of files as they
4566 exist in the working directory. If invoked with -A/--after, the
4566 exist in the working directory. If invoked with -A/--after, the
4567 operation is recorded, but no copying is performed.
4567 operation is recorded, but no copying is performed.
4568
4568
4569 This command takes effect at the next commit. To undo a rename
4569 This command takes effect at the next commit. To undo a rename
4570 before that, see :hg:`revert`.
4570 before that, see :hg:`revert`.
4571
4571
4572 Returns 0 on success, 1 if errors are encountered.
4572 Returns 0 on success, 1 if errors are encountered.
4573 """
4573 """
4574 wlock = repo.wlock(False)
4574 wlock = repo.wlock(False)
4575 try:
4575 try:
4576 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4576 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4577 finally:
4577 finally:
4578 wlock.release()
4578 wlock.release()
4579
4579
4580 @command('resolve',
4580 @command('resolve',
4581 [('a', 'all', None, _('select all unresolved files')),
4581 [('a', 'all', None, _('select all unresolved files')),
4582 ('l', 'list', None, _('list state of files needing merge')),
4582 ('l', 'list', None, _('list state of files needing merge')),
4583 ('m', 'mark', None, _('mark files as resolved')),
4583 ('m', 'mark', None, _('mark files as resolved')),
4584 ('u', 'unmark', None, _('mark files as unresolved')),
4584 ('u', 'unmark', None, _('mark files as unresolved')),
4585 ('n', 'no-status', None, _('hide status prefix'))]
4585 ('n', 'no-status', None, _('hide status prefix'))]
4586 + mergetoolopts + walkopts,
4586 + mergetoolopts + walkopts,
4587 _('[OPTION]... [FILE]...'))
4587 _('[OPTION]... [FILE]...'))
4588 def resolve(ui, repo, *pats, **opts):
4588 def resolve(ui, repo, *pats, **opts):
4589 """redo merges or set/view the merge status of files
4589 """redo merges or set/view the merge status of files
4590
4590
4591 Merges with unresolved conflicts are often the result of
4591 Merges with unresolved conflicts are often the result of
4592 non-interactive merging using the ``internal:merge`` configuration
4592 non-interactive merging using the ``internal:merge`` configuration
4593 setting, or a command-line merge tool like ``diff3``. The resolve
4593 setting, or a command-line merge tool like ``diff3``. The resolve
4594 command is used to manage the files involved in a merge, after
4594 command is used to manage the files involved in a merge, after
4595 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4595 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4596 working directory must have two parents).
4596 working directory must have two parents).
4597
4597
4598 The resolve command can be used in the following ways:
4598 The resolve command can be used in the following ways:
4599
4599
4600 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4600 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4601 files, discarding any previous merge attempts. Re-merging is not
4601 files, discarding any previous merge attempts. Re-merging is not
4602 performed for files already marked as resolved. Use ``--all/-a``
4602 performed for files already marked as resolved. Use ``--all/-a``
4603 to select all unresolved files. ``--tool`` can be used to specify
4603 to select all unresolved files. ``--tool`` can be used to specify
4604 the merge tool used for the given files. It overrides the HGMERGE
4604 the merge tool used for the given files. It overrides the HGMERGE
4605 environment variable and your configuration files. Previous file
4605 environment variable and your configuration files. Previous file
4606 contents are saved with a ``.orig`` suffix.
4606 contents are saved with a ``.orig`` suffix.
4607
4607
4608 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4608 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4609 (e.g. after having manually fixed-up the files). The default is
4609 (e.g. after having manually fixed-up the files). The default is
4610 to mark all unresolved files.
4610 to mark all unresolved files.
4611
4611
4612 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4612 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4613 default is to mark all resolved files.
4613 default is to mark all resolved files.
4614
4614
4615 - :hg:`resolve -l`: list files which had or still have conflicts.
4615 - :hg:`resolve -l`: list files which had or still have conflicts.
4616 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4616 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4617
4617
4618 Note that Mercurial will not let you commit files with unresolved
4618 Note that Mercurial will not let you commit files with unresolved
4619 merge conflicts. You must use :hg:`resolve -m ...` before you can
4619 merge conflicts. You must use :hg:`resolve -m ...` before you can
4620 commit after a conflicting merge.
4620 commit after a conflicting merge.
4621
4621
4622 Returns 0 on success, 1 if any files fail a resolve attempt.
4622 Returns 0 on success, 1 if any files fail a resolve attempt.
4623 """
4623 """
4624
4624
4625 all, mark, unmark, show, nostatus = \
4625 all, mark, unmark, show, nostatus = \
4626 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4626 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4627
4627
4628 if (show and (mark or unmark)) or (mark and unmark):
4628 if (show and (mark or unmark)) or (mark and unmark):
4629 raise util.Abort(_("too many options specified"))
4629 raise util.Abort(_("too many options specified"))
4630 if pats and all:
4630 if pats and all:
4631 raise util.Abort(_("can't specify --all and patterns"))
4631 raise util.Abort(_("can't specify --all and patterns"))
4632 if not (all or pats or show or mark or unmark):
4632 if not (all or pats or show or mark or unmark):
4633 raise util.Abort(_('no files or directories specified; '
4633 raise util.Abort(_('no files or directories specified; '
4634 'use --all to remerge all files'))
4634 'use --all to remerge all files'))
4635
4635
4636 ms = mergemod.mergestate(repo)
4636 ms = mergemod.mergestate(repo)
4637 m = scmutil.match(repo[None], pats, opts)
4637 m = scmutil.match(repo[None], pats, opts)
4638 ret = 0
4638 ret = 0
4639
4639
4640 for f in ms:
4640 for f in ms:
4641 if m(f):
4641 if m(f):
4642 if show:
4642 if show:
4643 if nostatus:
4643 if nostatus:
4644 ui.write("%s\n" % f)
4644 ui.write("%s\n" % f)
4645 else:
4645 else:
4646 ui.write("%s %s\n" % (ms[f].upper(), f),
4646 ui.write("%s %s\n" % (ms[f].upper(), f),
4647 label='resolve.' +
4647 label='resolve.' +
4648 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4648 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4649 elif mark:
4649 elif mark:
4650 ms.mark(f, "r")
4650 ms.mark(f, "r")
4651 elif unmark:
4651 elif unmark:
4652 ms.mark(f, "u")
4652 ms.mark(f, "u")
4653 else:
4653 else:
4654 wctx = repo[None]
4654 wctx = repo[None]
4655 mctx = wctx.parents()[-1]
4655 mctx = wctx.parents()[-1]
4656
4656
4657 # backup pre-resolve (merge uses .orig for its own purposes)
4657 # backup pre-resolve (merge uses .orig for its own purposes)
4658 a = repo.wjoin(f)
4658 a = repo.wjoin(f)
4659 util.copyfile(a, a + ".resolve")
4659 util.copyfile(a, a + ".resolve")
4660
4660
4661 try:
4661 try:
4662 # resolve file
4662 # resolve file
4663 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4663 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4664 if ms.resolve(f, wctx, mctx):
4664 if ms.resolve(f, wctx, mctx):
4665 ret = 1
4665 ret = 1
4666 finally:
4666 finally:
4667 ui.setconfig('ui', 'forcemerge', '')
4667 ui.setconfig('ui', 'forcemerge', '')
4668
4668
4669 # replace filemerge's .orig file with our resolve file
4669 # replace filemerge's .orig file with our resolve file
4670 util.rename(a + ".resolve", a + ".orig")
4670 util.rename(a + ".resolve", a + ".orig")
4671
4671
4672 ms.commit()
4672 ms.commit()
4673 return ret
4673 return ret
4674
4674
4675 @command('revert',
4675 @command('revert',
4676 [('a', 'all', None, _('revert all changes when no arguments given')),
4676 [('a', 'all', None, _('revert all changes when no arguments given')),
4677 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4677 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4678 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4678 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4679 ('C', 'no-backup', None, _('do not save backup copies of files')),
4679 ('C', 'no-backup', None, _('do not save backup copies of files')),
4680 ] + walkopts + dryrunopts,
4680 ] + walkopts + dryrunopts,
4681 _('[OPTION]... [-r REV] [NAME]...'))
4681 _('[OPTION]... [-r REV] [NAME]...'))
4682 def revert(ui, repo, *pats, **opts):
4682 def revert(ui, repo, *pats, **opts):
4683 """restore files to their checkout state
4683 """restore files to their checkout state
4684
4684
4685 .. note::
4685 .. note::
4686 To check out earlier revisions, you should use :hg:`update REV`.
4686 To check out earlier revisions, you should use :hg:`update REV`.
4687 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4687 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4688
4688
4689 With no revision specified, revert the specified files or directories
4689 With no revision specified, revert the specified files or directories
4690 to the contents they had in the parent of the working directory.
4690 to the contents they had in the parent of the working directory.
4691 This restores the contents of files to an unmodified
4691 This restores the contents of files to an unmodified
4692 state and unschedules adds, removes, copies, and renames. If the
4692 state and unschedules adds, removes, copies, and renames. If the
4693 working directory has two parents, you must explicitly specify a
4693 working directory has two parents, you must explicitly specify a
4694 revision.
4694 revision.
4695
4695
4696 Using the -r/--rev or -d/--date options, revert the given files or
4696 Using the -r/--rev or -d/--date options, revert the given files or
4697 directories to their states as of a specific revision. Because
4697 directories to their states as of a specific revision. Because
4698 revert does not change the working directory parents, this will
4698 revert does not change the working directory parents, this will
4699 cause these files to appear modified. This can be helpful to "back
4699 cause these files to appear modified. This can be helpful to "back
4700 out" some or all of an earlier change. See :hg:`backout` for a
4700 out" some or all of an earlier change. See :hg:`backout` for a
4701 related method.
4701 related method.
4702
4702
4703 Modified files are saved with a .orig suffix before reverting.
4703 Modified files are saved with a .orig suffix before reverting.
4704 To disable these backups, use --no-backup.
4704 To disable these backups, use --no-backup.
4705
4705
4706 See :hg:`help dates` for a list of formats valid for -d/--date.
4706 See :hg:`help dates` for a list of formats valid for -d/--date.
4707
4707
4708 Returns 0 on success.
4708 Returns 0 on success.
4709 """
4709 """
4710
4710
4711 if opts.get("date"):
4711 if opts.get("date"):
4712 if opts.get("rev"):
4712 if opts.get("rev"):
4713 raise util.Abort(_("you can't specify a revision and a date"))
4713 raise util.Abort(_("you can't specify a revision and a date"))
4714 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4714 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4715
4715
4716 parent, p2 = repo.dirstate.parents()
4716 parent, p2 = repo.dirstate.parents()
4717 if not opts.get('rev') and p2 != nullid:
4717 if not opts.get('rev') and p2 != nullid:
4718 # revert after merge is a trap for new users (issue2915)
4718 # revert after merge is a trap for new users (issue2915)
4719 raise util.Abort(_('uncommitted merge with no revision specified'),
4719 raise util.Abort(_('uncommitted merge with no revision specified'),
4720 hint=_('use "hg update" or see "hg help revert"'))
4720 hint=_('use "hg update" or see "hg help revert"'))
4721
4721
4722 ctx = scmutil.revsingle(repo, opts.get('rev'))
4722 ctx = scmutil.revsingle(repo, opts.get('rev'))
4723 node = ctx.node()
4723 node = ctx.node()
4724
4724
4725 if not pats and not opts.get('all'):
4725 if not pats and not opts.get('all'):
4726 msg = _("no files or directories specified")
4726 msg = _("no files or directories specified")
4727 if p2 != nullid:
4727 if p2 != nullid:
4728 hint = _("uncommitted merge, use --all to discard all changes,"
4728 hint = _("uncommitted merge, use --all to discard all changes,"
4729 " or 'hg update -C .' to abort the merge")
4729 " or 'hg update -C .' to abort the merge")
4730 raise util.Abort(msg, hint=hint)
4730 raise util.Abort(msg, hint=hint)
4731 dirty = util.any(repo.status())
4731 dirty = util.any(repo.status())
4732 if node != parent:
4732 if node != parent:
4733 if dirty:
4733 if dirty:
4734 hint = _("uncommitted changes, use --all to discard all"
4734 hint = _("uncommitted changes, use --all to discard all"
4735 " changes, or 'hg update %s' to update") % ctx.rev()
4735 " changes, or 'hg update %s' to update") % ctx.rev()
4736 else:
4736 else:
4737 hint = _("use --all to revert all files,"
4737 hint = _("use --all to revert all files,"
4738 " or 'hg update %s' to update") % ctx.rev()
4738 " or 'hg update %s' to update") % ctx.rev()
4739 elif dirty:
4739 elif dirty:
4740 hint = _("uncommitted changes, use --all to discard all changes")
4740 hint = _("uncommitted changes, use --all to discard all changes")
4741 else:
4741 else:
4742 hint = _("use --all to revert all files")
4742 hint = _("use --all to revert all files")
4743 raise util.Abort(msg, hint=hint)
4743 raise util.Abort(msg, hint=hint)
4744
4744
4745 mf = ctx.manifest()
4745 mf = ctx.manifest()
4746 if node == parent:
4746 if node == parent:
4747 pmf = mf
4747 pmf = mf
4748 else:
4748 else:
4749 pmf = None
4749 pmf = None
4750
4750
4751 # need all matching names in dirstate and manifest of target rev,
4751 # need all matching names in dirstate and manifest of target rev,
4752 # so have to walk both. do not print errors if files exist in one
4752 # so have to walk both. do not print errors if files exist in one
4753 # but not other.
4753 # but not other.
4754
4754
4755 names = {}
4755 names = {}
4756
4756
4757 wlock = repo.wlock()
4757 wlock = repo.wlock()
4758 try:
4758 try:
4759 # walk dirstate.
4759 # walk dirstate.
4760
4760
4761 m = scmutil.match(repo[None], pats, opts)
4761 m = scmutil.match(repo[None], pats, opts)
4762 m.bad = lambda x, y: False
4762 m.bad = lambda x, y: False
4763 for abs in repo.walk(m):
4763 for abs in repo.walk(m):
4764 names[abs] = m.rel(abs), m.exact(abs)
4764 names[abs] = m.rel(abs), m.exact(abs)
4765
4765
4766 # walk target manifest.
4766 # walk target manifest.
4767
4767
4768 def badfn(path, msg):
4768 def badfn(path, msg):
4769 if path in names:
4769 if path in names:
4770 return
4770 return
4771 if path in repo[node].substate:
4771 if path in repo[node].substate:
4772 ui.warn("%s: %s\n" % (m.rel(path),
4772 ui.warn("%s: %s\n" % (m.rel(path),
4773 'reverting subrepos is unsupported'))
4773 'reverting subrepos is unsupported'))
4774 return
4774 return
4775 path_ = path + '/'
4775 path_ = path + '/'
4776 for f in names:
4776 for f in names:
4777 if f.startswith(path_):
4777 if f.startswith(path_):
4778 return
4778 return
4779 ui.warn("%s: %s\n" % (m.rel(path), msg))
4779 ui.warn("%s: %s\n" % (m.rel(path), msg))
4780
4780
4781 m = scmutil.match(repo[node], pats, opts)
4781 m = scmutil.match(repo[node], pats, opts)
4782 m.bad = badfn
4782 m.bad = badfn
4783 for abs in repo[node].walk(m):
4783 for abs in repo[node].walk(m):
4784 if abs not in names:
4784 if abs not in names:
4785 names[abs] = m.rel(abs), m.exact(abs)
4785 names[abs] = m.rel(abs), m.exact(abs)
4786
4786
4787 m = scmutil.matchfiles(repo, names)
4787 m = scmutil.matchfiles(repo, names)
4788 changes = repo.status(match=m)[:4]
4788 changes = repo.status(match=m)[:4]
4789 modified, added, removed, deleted = map(set, changes)
4789 modified, added, removed, deleted = map(set, changes)
4790
4790
4791 # if f is a rename, also revert the source
4791 # if f is a rename, also revert the source
4792 cwd = repo.getcwd()
4792 cwd = repo.getcwd()
4793 for f in added:
4793 for f in added:
4794 src = repo.dirstate.copied(f)
4794 src = repo.dirstate.copied(f)
4795 if src and src not in names and repo.dirstate[src] == 'r':
4795 if src and src not in names and repo.dirstate[src] == 'r':
4796 removed.add(src)
4796 removed.add(src)
4797 names[src] = (repo.pathto(src, cwd), True)
4797 names[src] = (repo.pathto(src, cwd), True)
4798
4798
4799 def removeforget(abs):
4799 def removeforget(abs):
4800 if repo.dirstate[abs] == 'a':
4800 if repo.dirstate[abs] == 'a':
4801 return _('forgetting %s\n')
4801 return _('forgetting %s\n')
4802 return _('removing %s\n')
4802 return _('removing %s\n')
4803
4803
4804 revert = ([], _('reverting %s\n'))
4804 revert = ([], _('reverting %s\n'))
4805 add = ([], _('adding %s\n'))
4805 add = ([], _('adding %s\n'))
4806 remove = ([], removeforget)
4806 remove = ([], removeforget)
4807 undelete = ([], _('undeleting %s\n'))
4807 undelete = ([], _('undeleting %s\n'))
4808
4808
4809 disptable = (
4809 disptable = (
4810 # dispatch table:
4810 # dispatch table:
4811 # file state
4811 # file state
4812 # action if in target manifest
4812 # action if in target manifest
4813 # action if not in target manifest
4813 # action if not in target manifest
4814 # make backup if in target manifest
4814 # make backup if in target manifest
4815 # make backup if not in target manifest
4815 # make backup if not in target manifest
4816 (modified, revert, remove, True, True),
4816 (modified, revert, remove, True, True),
4817 (added, revert, remove, True, False),
4817 (added, revert, remove, True, False),
4818 (removed, undelete, None, False, False),
4818 (removed, undelete, None, False, False),
4819 (deleted, revert, remove, False, False),
4819 (deleted, revert, remove, False, False),
4820 )
4820 )
4821
4821
4822 for abs, (rel, exact) in sorted(names.items()):
4822 for abs, (rel, exact) in sorted(names.items()):
4823 mfentry = mf.get(abs)
4823 mfentry = mf.get(abs)
4824 target = repo.wjoin(abs)
4824 target = repo.wjoin(abs)
4825 def handle(xlist, dobackup):
4825 def handle(xlist, dobackup):
4826 xlist[0].append(abs)
4826 xlist[0].append(abs)
4827 if (dobackup and not opts.get('no_backup') and
4827 if (dobackup and not opts.get('no_backup') and
4828 os.path.lexists(target)):
4828 os.path.lexists(target)):
4829 bakname = "%s.orig" % rel
4829 bakname = "%s.orig" % rel
4830 ui.note(_('saving current version of %s as %s\n') %
4830 ui.note(_('saving current version of %s as %s\n') %
4831 (rel, bakname))
4831 (rel, bakname))
4832 if not opts.get('dry_run'):
4832 if not opts.get('dry_run'):
4833 util.rename(target, bakname)
4833 util.rename(target, bakname)
4834 if ui.verbose or not exact:
4834 if ui.verbose or not exact:
4835 msg = xlist[1]
4835 msg = xlist[1]
4836 if not isinstance(msg, basestring):
4836 if not isinstance(msg, basestring):
4837 msg = msg(abs)
4837 msg = msg(abs)
4838 ui.status(msg % rel)
4838 ui.status(msg % rel)
4839 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4839 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4840 if abs not in table:
4840 if abs not in table:
4841 continue
4841 continue
4842 # file has changed in dirstate
4842 # file has changed in dirstate
4843 if mfentry:
4843 if mfentry:
4844 handle(hitlist, backuphit)
4844 handle(hitlist, backuphit)
4845 elif misslist is not None:
4845 elif misslist is not None:
4846 handle(misslist, backupmiss)
4846 handle(misslist, backupmiss)
4847 break
4847 break
4848 else:
4848 else:
4849 if abs not in repo.dirstate:
4849 if abs not in repo.dirstate:
4850 if mfentry:
4850 if mfentry:
4851 handle(add, True)
4851 handle(add, True)
4852 elif exact:
4852 elif exact:
4853 ui.warn(_('file not managed: %s\n') % rel)
4853 ui.warn(_('file not managed: %s\n') % rel)
4854 continue
4854 continue
4855 # file has not changed in dirstate
4855 # file has not changed in dirstate
4856 if node == parent:
4856 if node == parent:
4857 if exact:
4857 if exact:
4858 ui.warn(_('no changes needed to %s\n') % rel)
4858 ui.warn(_('no changes needed to %s\n') % rel)
4859 continue
4859 continue
4860 if pmf is None:
4860 if pmf is None:
4861 # only need parent manifest in this unlikely case,
4861 # only need parent manifest in this unlikely case,
4862 # so do not read by default
4862 # so do not read by default
4863 pmf = repo[parent].manifest()
4863 pmf = repo[parent].manifest()
4864 if abs in pmf and mfentry:
4864 if abs in pmf and mfentry:
4865 # if version of file is same in parent and target
4865 # if version of file is same in parent and target
4866 # manifests, do nothing
4866 # manifests, do nothing
4867 if (pmf[abs] != mfentry or
4867 if (pmf[abs] != mfentry or
4868 pmf.flags(abs) != mf.flags(abs)):
4868 pmf.flags(abs) != mf.flags(abs)):
4869 handle(revert, False)
4869 handle(revert, False)
4870 else:
4870 else:
4871 handle(remove, False)
4871 handle(remove, False)
4872
4872
4873 if not opts.get('dry_run'):
4873 if not opts.get('dry_run'):
4874 def checkout(f):
4874 def checkout(f):
4875 fc = ctx[f]
4875 fc = ctx[f]
4876 repo.wwrite(f, fc.data(), fc.flags())
4876 repo.wwrite(f, fc.data(), fc.flags())
4877
4877
4878 audit_path = scmutil.pathauditor(repo.root)
4878 audit_path = scmutil.pathauditor(repo.root)
4879 for f in remove[0]:
4879 for f in remove[0]:
4880 if repo.dirstate[f] == 'a':
4880 if repo.dirstate[f] == 'a':
4881 repo.dirstate.drop(f)
4881 repo.dirstate.drop(f)
4882 continue
4882 continue
4883 audit_path(f)
4883 audit_path(f)
4884 try:
4884 try:
4885 util.unlinkpath(repo.wjoin(f))
4885 util.unlinkpath(repo.wjoin(f))
4886 except OSError:
4886 except OSError:
4887 pass
4887 pass
4888 repo.dirstate.remove(f)
4888 repo.dirstate.remove(f)
4889
4889
4890 normal = None
4890 normal = None
4891 if node == parent:
4891 if node == parent:
4892 # We're reverting to our parent. If possible, we'd like status
4892 # We're reverting to our parent. If possible, we'd like status
4893 # to report the file as clean. We have to use normallookup for
4893 # to report the file as clean. We have to use normallookup for
4894 # merges to avoid losing information about merged/dirty files.
4894 # merges to avoid losing information about merged/dirty files.
4895 if p2 != nullid:
4895 if p2 != nullid:
4896 normal = repo.dirstate.normallookup
4896 normal = repo.dirstate.normallookup
4897 else:
4897 else:
4898 normal = repo.dirstate.normal
4898 normal = repo.dirstate.normal
4899 for f in revert[0]:
4899 for f in revert[0]:
4900 checkout(f)
4900 checkout(f)
4901 if normal:
4901 if normal:
4902 normal(f)
4902 normal(f)
4903
4903
4904 for f in add[0]:
4904 for f in add[0]:
4905 checkout(f)
4905 checkout(f)
4906 repo.dirstate.add(f)
4906 repo.dirstate.add(f)
4907
4907
4908 normal = repo.dirstate.normallookup
4908 normal = repo.dirstate.normallookup
4909 if node == parent and p2 == nullid:
4909 if node == parent and p2 == nullid:
4910 normal = repo.dirstate.normal
4910 normal = repo.dirstate.normal
4911 for f in undelete[0]:
4911 for f in undelete[0]:
4912 checkout(f)
4912 checkout(f)
4913 normal(f)
4913 normal(f)
4914
4914
4915 finally:
4915 finally:
4916 wlock.release()
4916 wlock.release()
4917
4917
4918 @command('rollback', dryrunopts +
4918 @command('rollback', dryrunopts +
4919 [('f', 'force', False, _('ignore safety measures'))])
4919 [('f', 'force', False, _('ignore safety measures'))])
4920 def rollback(ui, repo, **opts):
4920 def rollback(ui, repo, **opts):
4921 """roll back the last transaction (dangerous)
4921 """roll back the last transaction (dangerous)
4922
4922
4923 This command should be used with care. There is only one level of
4923 This command should be used with care. There is only one level of
4924 rollback, and there is no way to undo a rollback. It will also
4924 rollback, and there is no way to undo a rollback. It will also
4925 restore the dirstate at the time of the last transaction, losing
4925 restore the dirstate at the time of the last transaction, losing
4926 any dirstate changes since that time. This command does not alter
4926 any dirstate changes since that time. This command does not alter
4927 the working directory.
4927 the working directory.
4928
4928
4929 Transactions are used to encapsulate the effects of all commands
4929 Transactions are used to encapsulate the effects of all commands
4930 that create new changesets or propagate existing changesets into a
4930 that create new changesets or propagate existing changesets into a
4931 repository. For example, the following commands are transactional,
4931 repository. For example, the following commands are transactional,
4932 and their effects can be rolled back:
4932 and their effects can be rolled back:
4933
4933
4934 - commit
4934 - commit
4935 - import
4935 - import
4936 - pull
4936 - pull
4937 - push (with this repository as the destination)
4937 - push (with this repository as the destination)
4938 - unbundle
4938 - unbundle
4939
4939
4940 To avoid permanent data loss, rollback will refuse to rollback a
4940 To avoid permanent data loss, rollback will refuse to rollback a
4941 commit transaction if it isn't checked out. Use --force to
4941 commit transaction if it isn't checked out. Use --force to
4942 override this protection.
4942 override this protection.
4943
4943
4944 This command is not intended for use on public repositories. Once
4944 This command is not intended for use on public repositories. Once
4945 changes are visible for pull by other users, rolling a transaction
4945 changes are visible for pull by other users, rolling a transaction
4946 back locally is ineffective (someone else may already have pulled
4946 back locally is ineffective (someone else may already have pulled
4947 the changes). Furthermore, a race is possible with readers of the
4947 the changes). Furthermore, a race is possible with readers of the
4948 repository; for example an in-progress pull from the repository
4948 repository; for example an in-progress pull from the repository
4949 may fail if a rollback is performed.
4949 may fail if a rollback is performed.
4950
4950
4951 Returns 0 on success, 1 if no rollback data is available.
4951 Returns 0 on success, 1 if no rollback data is available.
4952 """
4952 """
4953 return repo.rollback(dryrun=opts.get('dry_run'),
4953 return repo.rollback(dryrun=opts.get('dry_run'),
4954 force=opts.get('force'))
4954 force=opts.get('force'))
4955
4955
4956 @command('root', [])
4956 @command('root', [])
4957 def root(ui, repo):
4957 def root(ui, repo):
4958 """print the root (top) of the current working directory
4958 """print the root (top) of the current working directory
4959
4959
4960 Print the root directory of the current repository.
4960 Print the root directory of the current repository.
4961
4961
4962 Returns 0 on success.
4962 Returns 0 on success.
4963 """
4963 """
4964 ui.write(repo.root + "\n")
4964 ui.write(repo.root + "\n")
4965
4965
4966 @command('^serve',
4966 @command('^serve',
4967 [('A', 'accesslog', '', _('name of access log file to write to'),
4967 [('A', 'accesslog', '', _('name of access log file to write to'),
4968 _('FILE')),
4968 _('FILE')),
4969 ('d', 'daemon', None, _('run server in background')),
4969 ('d', 'daemon', None, _('run server in background')),
4970 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4970 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4971 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4971 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4972 # use string type, then we can check if something was passed
4972 # use string type, then we can check if something was passed
4973 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4973 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4974 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4974 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4975 _('ADDR')),
4975 _('ADDR')),
4976 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4976 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4977 _('PREFIX')),
4977 _('PREFIX')),
4978 ('n', 'name', '',
4978 ('n', 'name', '',
4979 _('name to show in web pages (default: working directory)'), _('NAME')),
4979 _('name to show in web pages (default: working directory)'), _('NAME')),
4980 ('', 'web-conf', '',
4980 ('', 'web-conf', '',
4981 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4981 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4982 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4982 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4983 _('FILE')),
4983 _('FILE')),
4984 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4984 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4985 ('', 'stdio', None, _('for remote clients')),
4985 ('', 'stdio', None, _('for remote clients')),
4986 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4986 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4987 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4987 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4988 ('', 'style', '', _('template style to use'), _('STYLE')),
4988 ('', 'style', '', _('template style to use'), _('STYLE')),
4989 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4989 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4990 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4990 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4991 _('[OPTION]...'))
4991 _('[OPTION]...'))
4992 def serve(ui, repo, **opts):
4992 def serve(ui, repo, **opts):
4993 """start stand-alone webserver
4993 """start stand-alone webserver
4994
4994
4995 Start a local HTTP repository browser and pull server. You can use
4995 Start a local HTTP repository browser and pull server. You can use
4996 this for ad-hoc sharing and browsing of repositories. It is
4996 this for ad-hoc sharing and browsing of repositories. It is
4997 recommended to use a real web server to serve a repository for
4997 recommended to use a real web server to serve a repository for
4998 longer periods of time.
4998 longer periods of time.
4999
4999
5000 Please note that the server does not implement access control.
5000 Please note that the server does not implement access control.
5001 This means that, by default, anybody can read from the server and
5001 This means that, by default, anybody can read from the server and
5002 nobody can write to it by default. Set the ``web.allow_push``
5002 nobody can write to it by default. Set the ``web.allow_push``
5003 option to ``*`` to allow everybody to push to the server. You
5003 option to ``*`` to allow everybody to push to the server. You
5004 should use a real web server if you need to authenticate users.
5004 should use a real web server if you need to authenticate users.
5005
5005
5006 By default, the server logs accesses to stdout and errors to
5006 By default, the server logs accesses to stdout and errors to
5007 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5007 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5008 files.
5008 files.
5009
5009
5010 To have the server choose a free port number to listen on, specify
5010 To have the server choose a free port number to listen on, specify
5011 a port number of 0; in this case, the server will print the port
5011 a port number of 0; in this case, the server will print the port
5012 number it uses.
5012 number it uses.
5013
5013
5014 Returns 0 on success.
5014 Returns 0 on success.
5015 """
5015 """
5016
5016
5017 if opts["stdio"] and opts["cmdserver"]:
5017 if opts["stdio"] and opts["cmdserver"]:
5018 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5018 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5019
5019
5020 def checkrepo():
5020 def checkrepo():
5021 if repo is None:
5021 if repo is None:
5022 raise error.RepoError(_("There is no Mercurial repository here"
5022 raise error.RepoError(_("There is no Mercurial repository here"
5023 " (.hg not found)"))
5023 " (.hg not found)"))
5024
5024
5025 if opts["stdio"]:
5025 if opts["stdio"]:
5026 checkrepo()
5026 checkrepo()
5027 s = sshserver.sshserver(ui, repo)
5027 s = sshserver.sshserver(ui, repo)
5028 s.serve_forever()
5028 s.serve_forever()
5029
5029
5030 if opts["cmdserver"]:
5030 if opts["cmdserver"]:
5031 checkrepo()
5031 checkrepo()
5032 s = commandserver.server(ui, repo, opts["cmdserver"])
5032 s = commandserver.server(ui, repo, opts["cmdserver"])
5033 return s.serve()
5033 return s.serve()
5034
5034
5035 # this way we can check if something was given in the command-line
5035 # this way we can check if something was given in the command-line
5036 if opts.get('port'):
5036 if opts.get('port'):
5037 opts['port'] = util.getport(opts.get('port'))
5037 opts['port'] = util.getport(opts.get('port'))
5038
5038
5039 baseui = repo and repo.baseui or ui
5039 baseui = repo and repo.baseui or ui
5040 optlist = ("name templates style address port prefix ipv6"
5040 optlist = ("name templates style address port prefix ipv6"
5041 " accesslog errorlog certificate encoding")
5041 " accesslog errorlog certificate encoding")
5042 for o in optlist.split():
5042 for o in optlist.split():
5043 val = opts.get(o, '')
5043 val = opts.get(o, '')
5044 if val in (None, ''): # should check against default options instead
5044 if val in (None, ''): # should check against default options instead
5045 continue
5045 continue
5046 baseui.setconfig("web", o, val)
5046 baseui.setconfig("web", o, val)
5047 if repo and repo.ui != baseui:
5047 if repo and repo.ui != baseui:
5048 repo.ui.setconfig("web", o, val)
5048 repo.ui.setconfig("web", o, val)
5049
5049
5050 o = opts.get('web_conf') or opts.get('webdir_conf')
5050 o = opts.get('web_conf') or opts.get('webdir_conf')
5051 if not o:
5051 if not o:
5052 if not repo:
5052 if not repo:
5053 raise error.RepoError(_("There is no Mercurial repository"
5053 raise error.RepoError(_("There is no Mercurial repository"
5054 " here (.hg not found)"))
5054 " here (.hg not found)"))
5055 o = repo.root
5055 o = repo.root
5056
5056
5057 app = hgweb.hgweb(o, baseui=ui)
5057 app = hgweb.hgweb(o, baseui=ui)
5058
5058
5059 class service(object):
5059 class service(object):
5060 def init(self):
5060 def init(self):
5061 util.setsignalhandler()
5061 util.setsignalhandler()
5062 self.httpd = hgweb.server.create_server(ui, app)
5062 self.httpd = hgweb.server.create_server(ui, app)
5063
5063
5064 if opts['port'] and not ui.verbose:
5064 if opts['port'] and not ui.verbose:
5065 return
5065 return
5066
5066
5067 if self.httpd.prefix:
5067 if self.httpd.prefix:
5068 prefix = self.httpd.prefix.strip('/') + '/'
5068 prefix = self.httpd.prefix.strip('/') + '/'
5069 else:
5069 else:
5070 prefix = ''
5070 prefix = ''
5071
5071
5072 port = ':%d' % self.httpd.port
5072 port = ':%d' % self.httpd.port
5073 if port == ':80':
5073 if port == ':80':
5074 port = ''
5074 port = ''
5075
5075
5076 bindaddr = self.httpd.addr
5076 bindaddr = self.httpd.addr
5077 if bindaddr == '0.0.0.0':
5077 if bindaddr == '0.0.0.0':
5078 bindaddr = '*'
5078 bindaddr = '*'
5079 elif ':' in bindaddr: # IPv6
5079 elif ':' in bindaddr: # IPv6
5080 bindaddr = '[%s]' % bindaddr
5080 bindaddr = '[%s]' % bindaddr
5081
5081
5082 fqaddr = self.httpd.fqaddr
5082 fqaddr = self.httpd.fqaddr
5083 if ':' in fqaddr:
5083 if ':' in fqaddr:
5084 fqaddr = '[%s]' % fqaddr
5084 fqaddr = '[%s]' % fqaddr
5085 if opts['port']:
5085 if opts['port']:
5086 write = ui.status
5086 write = ui.status
5087 else:
5087 else:
5088 write = ui.write
5088 write = ui.write
5089 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5089 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5090 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5090 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5091
5091
5092 def run(self):
5092 def run(self):
5093 self.httpd.serve_forever()
5093 self.httpd.serve_forever()
5094
5094
5095 service = service()
5095 service = service()
5096
5096
5097 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5097 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5098
5098
5099 @command('showconfig|debugconfig',
5099 @command('showconfig|debugconfig',
5100 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5100 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5101 _('[-u] [NAME]...'))
5101 _('[-u] [NAME]...'))
5102 def showconfig(ui, repo, *values, **opts):
5102 def showconfig(ui, repo, *values, **opts):
5103 """show combined config settings from all hgrc files
5103 """show combined config settings from all hgrc files
5104
5104
5105 With no arguments, print names and values of all config items.
5105 With no arguments, print names and values of all config items.
5106
5106
5107 With one argument of the form section.name, print just the value
5107 With one argument of the form section.name, print just the value
5108 of that config item.
5108 of that config item.
5109
5109
5110 With multiple arguments, print names and values of all config
5110 With multiple arguments, print names and values of all config
5111 items with matching section names.
5111 items with matching section names.
5112
5112
5113 With --debug, the source (filename and line number) is printed
5113 With --debug, the source (filename and line number) is printed
5114 for each config item.
5114 for each config item.
5115
5115
5116 Returns 0 on success.
5116 Returns 0 on success.
5117 """
5117 """
5118
5118
5119 for f in scmutil.rcpath():
5119 for f in scmutil.rcpath():
5120 ui.debug('read config from: %s\n' % f)
5120 ui.debug('read config from: %s\n' % f)
5121 untrusted = bool(opts.get('untrusted'))
5121 untrusted = bool(opts.get('untrusted'))
5122 if values:
5122 if values:
5123 sections = [v for v in values if '.' not in v]
5123 sections = [v for v in values if '.' not in v]
5124 items = [v for v in values if '.' in v]
5124 items = [v for v in values if '.' in v]
5125 if len(items) > 1 or items and sections:
5125 if len(items) > 1 or items and sections:
5126 raise util.Abort(_('only one config item permitted'))
5126 raise util.Abort(_('only one config item permitted'))
5127 for section, name, value in ui.walkconfig(untrusted=untrusted):
5127 for section, name, value in ui.walkconfig(untrusted=untrusted):
5128 value = str(value).replace('\n', '\\n')
5128 value = str(value).replace('\n', '\\n')
5129 sectname = section + '.' + name
5129 sectname = section + '.' + name
5130 if values:
5130 if values:
5131 for v in values:
5131 for v in values:
5132 if v == section:
5132 if v == section:
5133 ui.debug('%s: ' %
5133 ui.debug('%s: ' %
5134 ui.configsource(section, name, untrusted))
5134 ui.configsource(section, name, untrusted))
5135 ui.write('%s=%s\n' % (sectname, value))
5135 ui.write('%s=%s\n' % (sectname, value))
5136 elif v == sectname:
5136 elif v == sectname:
5137 ui.debug('%s: ' %
5137 ui.debug('%s: ' %
5138 ui.configsource(section, name, untrusted))
5138 ui.configsource(section, name, untrusted))
5139 ui.write(value, '\n')
5139 ui.write(value, '\n')
5140 else:
5140 else:
5141 ui.debug('%s: ' %
5141 ui.debug('%s: ' %
5142 ui.configsource(section, name, untrusted))
5142 ui.configsource(section, name, untrusted))
5143 ui.write('%s=%s\n' % (sectname, value))
5143 ui.write('%s=%s\n' % (sectname, value))
5144
5144
5145 @command('^status|st',
5145 @command('^status|st',
5146 [('A', 'all', None, _('show status of all files')),
5146 [('A', 'all', None, _('show status of all files')),
5147 ('m', 'modified', None, _('show only modified files')),
5147 ('m', 'modified', None, _('show only modified files')),
5148 ('a', 'added', None, _('show only added files')),
5148 ('a', 'added', None, _('show only added files')),
5149 ('r', 'removed', None, _('show only removed files')),
5149 ('r', 'removed', None, _('show only removed files')),
5150 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5150 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5151 ('c', 'clean', None, _('show only files without changes')),
5151 ('c', 'clean', None, _('show only files without changes')),
5152 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5152 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5153 ('i', 'ignored', None, _('show only ignored files')),
5153 ('i', 'ignored', None, _('show only ignored files')),
5154 ('n', 'no-status', None, _('hide status prefix')),
5154 ('n', 'no-status', None, _('hide status prefix')),
5155 ('C', 'copies', None, _('show source of copied files')),
5155 ('C', 'copies', None, _('show source of copied files')),
5156 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5156 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5157 ('', 'rev', [], _('show difference from revision'), _('REV')),
5157 ('', 'rev', [], _('show difference from revision'), _('REV')),
5158 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5158 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5159 ] + walkopts + subrepoopts,
5159 ] + walkopts + subrepoopts,
5160 _('[OPTION]... [FILE]...'))
5160 _('[OPTION]... [FILE]...'))
5161 def status(ui, repo, *pats, **opts):
5161 def status(ui, repo, *pats, **opts):
5162 """show changed files in the working directory
5162 """show changed files in the working directory
5163
5163
5164 Show status of files in the repository. If names are given, only
5164 Show status of files in the repository. If names are given, only
5165 files that match are shown. Files that are clean or ignored or
5165 files that match are shown. Files that are clean or ignored or
5166 the source of a copy/move operation, are not listed unless
5166 the source of a copy/move operation, are not listed unless
5167 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5167 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5168 Unless options described with "show only ..." are given, the
5168 Unless options described with "show only ..." are given, the
5169 options -mardu are used.
5169 options -mardu are used.
5170
5170
5171 Option -q/--quiet hides untracked (unknown and ignored) files
5171 Option -q/--quiet hides untracked (unknown and ignored) files
5172 unless explicitly requested with -u/--unknown or -i/--ignored.
5172 unless explicitly requested with -u/--unknown or -i/--ignored.
5173
5173
5174 .. note::
5174 .. note::
5175 status may appear to disagree with diff if permissions have
5175 status may appear to disagree with diff if permissions have
5176 changed or a merge has occurred. The standard diff format does
5176 changed or a merge has occurred. The standard diff format does
5177 not report permission changes and diff only reports changes
5177 not report permission changes and diff only reports changes
5178 relative to one merge parent.
5178 relative to one merge parent.
5179
5179
5180 If one revision is given, it is used as the base revision.
5180 If one revision is given, it is used as the base revision.
5181 If two revisions are given, the differences between them are
5181 If two revisions are given, the differences between them are
5182 shown. The --change option can also be used as a shortcut to list
5182 shown. The --change option can also be used as a shortcut to list
5183 the changed files of a revision from its first parent.
5183 the changed files of a revision from its first parent.
5184
5184
5185 The codes used to show the status of files are::
5185 The codes used to show the status of files are::
5186
5186
5187 M = modified
5187 M = modified
5188 A = added
5188 A = added
5189 R = removed
5189 R = removed
5190 C = clean
5190 C = clean
5191 ! = missing (deleted by non-hg command, but still tracked)
5191 ! = missing (deleted by non-hg command, but still tracked)
5192 ? = not tracked
5192 ? = not tracked
5193 I = ignored
5193 I = ignored
5194 = origin of the previous file listed as A (added)
5194 = origin of the previous file listed as A (added)
5195
5195
5196 .. container:: verbose
5196 .. container:: verbose
5197
5197
5198 Examples:
5198 Examples:
5199
5199
5200 - show changes in the working directory relative to a
5200 - show changes in the working directory relative to a
5201 changeset::
5201 changeset::
5202
5202
5203 hg status --rev 9353
5203 hg status --rev 9353
5204
5204
5205 - show all changes including copies in an existing changeset::
5205 - show all changes including copies in an existing changeset::
5206
5206
5207 hg status --copies --change 9353
5207 hg status --copies --change 9353
5208
5208
5209 - get a NUL separated list of added files, suitable for xargs::
5209 - get a NUL separated list of added files, suitable for xargs::
5210
5210
5211 hg status -an0
5211 hg status -an0
5212
5212
5213 Returns 0 on success.
5213 Returns 0 on success.
5214 """
5214 """
5215
5215
5216 revs = opts.get('rev')
5216 revs = opts.get('rev')
5217 change = opts.get('change')
5217 change = opts.get('change')
5218
5218
5219 if revs and change:
5219 if revs and change:
5220 msg = _('cannot specify --rev and --change at the same time')
5220 msg = _('cannot specify --rev and --change at the same time')
5221 raise util.Abort(msg)
5221 raise util.Abort(msg)
5222 elif change:
5222 elif change:
5223 node2 = scmutil.revsingle(repo, change, None).node()
5223 node2 = scmutil.revsingle(repo, change, None).node()
5224 node1 = repo[node2].p1().node()
5224 node1 = repo[node2].p1().node()
5225 else:
5225 else:
5226 node1, node2 = scmutil.revpair(repo, revs)
5226 node1, node2 = scmutil.revpair(repo, revs)
5227
5227
5228 cwd = (pats and repo.getcwd()) or ''
5228 cwd = (pats and repo.getcwd()) or ''
5229 end = opts.get('print0') and '\0' or '\n'
5229 end = opts.get('print0') and '\0' or '\n'
5230 copy = {}
5230 copy = {}
5231 states = 'modified added removed deleted unknown ignored clean'.split()
5231 states = 'modified added removed deleted unknown ignored clean'.split()
5232 show = [k for k in states if opts.get(k)]
5232 show = [k for k in states if opts.get(k)]
5233 if opts.get('all'):
5233 if opts.get('all'):
5234 show += ui.quiet and (states[:4] + ['clean']) or states
5234 show += ui.quiet and (states[:4] + ['clean']) or states
5235 if not show:
5235 if not show:
5236 show = ui.quiet and states[:4] or states[:5]
5236 show = ui.quiet and states[:4] or states[:5]
5237
5237
5238 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5238 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5239 'ignored' in show, 'clean' in show, 'unknown' in show,
5239 'ignored' in show, 'clean' in show, 'unknown' in show,
5240 opts.get('subrepos'))
5240 opts.get('subrepos'))
5241 changestates = zip(states, 'MAR!?IC', stat)
5241 changestates = zip(states, 'MAR!?IC', stat)
5242
5242
5243 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5243 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5244 copy = copies.pathcopies(repo[node1], repo[node2])
5244 copy = copies.pathcopies(repo[node1], repo[node2])
5245
5245
5246 for state, char, files in changestates:
5246 for state, char, files in changestates:
5247 if state in show:
5247 if state in show:
5248 format = "%s %%s%s" % (char, end)
5248 format = "%s %%s%s" % (char, end)
5249 if opts.get('no_status'):
5249 if opts.get('no_status'):
5250 format = "%%s%s" % end
5250 format = "%%s%s" % end
5251
5251
5252 for f in files:
5252 for f in files:
5253 ui.write(format % repo.pathto(f, cwd),
5253 ui.write(format % repo.pathto(f, cwd),
5254 label='status.' + state)
5254 label='status.' + state)
5255 if f in copy:
5255 if f in copy:
5256 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5256 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5257 label='status.copied')
5257 label='status.copied')
5258
5258
5259 @command('^summary|sum',
5259 @command('^summary|sum',
5260 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5260 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5261 def summary(ui, repo, **opts):
5261 def summary(ui, repo, **opts):
5262 """summarize working directory state
5262 """summarize working directory state
5263
5263
5264 This generates a brief summary of the working directory state,
5264 This generates a brief summary of the working directory state,
5265 including parents, branch, commit status, and available updates.
5265 including parents, branch, commit status, and available updates.
5266
5266
5267 With the --remote option, this will check the default paths for
5267 With the --remote option, this will check the default paths for
5268 incoming and outgoing changes. This can be time-consuming.
5268 incoming and outgoing changes. This can be time-consuming.
5269
5269
5270 Returns 0 on success.
5270 Returns 0 on success.
5271 """
5271 """
5272
5272
5273 ctx = repo[None]
5273 ctx = repo[None]
5274 parents = ctx.parents()
5274 parents = ctx.parents()
5275 pnode = parents[0].node()
5275 pnode = parents[0].node()
5276 marks = []
5276 marks = []
5277
5277
5278 for p in parents:
5278 for p in parents:
5279 # label with log.changeset (instead of log.parent) since this
5279 # label with log.changeset (instead of log.parent) since this
5280 # shows a working directory parent *changeset*:
5280 # shows a working directory parent *changeset*:
5281 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5281 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5282 label='log.changeset')
5282 label='log.changeset')
5283 ui.write(' '.join(p.tags()), label='log.tag')
5283 ui.write(' '.join(p.tags()), label='log.tag')
5284 if p.bookmarks():
5284 if p.bookmarks():
5285 marks.extend(p.bookmarks())
5285 marks.extend(p.bookmarks())
5286 if p.rev() == -1:
5286 if p.rev() == -1:
5287 if not len(repo):
5287 if not len(repo):
5288 ui.write(_(' (empty repository)'))
5288 ui.write(_(' (empty repository)'))
5289 else:
5289 else:
5290 ui.write(_(' (no revision checked out)'))
5290 ui.write(_(' (no revision checked out)'))
5291 ui.write('\n')
5291 ui.write('\n')
5292 if p.description():
5292 if p.description():
5293 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5293 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5294 label='log.summary')
5294 label='log.summary')
5295
5295
5296 branch = ctx.branch()
5296 branch = ctx.branch()
5297 bheads = repo.branchheads(branch)
5297 bheads = repo.branchheads(branch)
5298 m = _('branch: %s\n') % branch
5298 m = _('branch: %s\n') % branch
5299 if branch != 'default':
5299 if branch != 'default':
5300 ui.write(m, label='log.branch')
5300 ui.write(m, label='log.branch')
5301 else:
5301 else:
5302 ui.status(m, label='log.branch')
5302 ui.status(m, label='log.branch')
5303
5303
5304 if marks:
5304 if marks:
5305 current = repo._bookmarkcurrent
5305 current = repo._bookmarkcurrent
5306 ui.write(_('bookmarks:'), label='log.bookmark')
5306 ui.write(_('bookmarks:'), label='log.bookmark')
5307 if current is not None:
5307 if current is not None:
5308 try:
5308 try:
5309 marks.remove(current)
5309 marks.remove(current)
5310 ui.write(' *' + current, label='bookmarks.current')
5310 ui.write(' *' + current, label='bookmarks.current')
5311 except ValueError:
5311 except ValueError:
5312 # current bookmark not in parent ctx marks
5312 # current bookmark not in parent ctx marks
5313 pass
5313 pass
5314 for m in marks:
5314 for m in marks:
5315 ui.write(' ' + m, label='log.bookmark')
5315 ui.write(' ' + m, label='log.bookmark')
5316 ui.write('\n', label='log.bookmark')
5316 ui.write('\n', label='log.bookmark')
5317
5317
5318 st = list(repo.status(unknown=True))[:6]
5318 st = list(repo.status(unknown=True))[:6]
5319
5319
5320 c = repo.dirstate.copies()
5320 c = repo.dirstate.copies()
5321 copied, renamed = [], []
5321 copied, renamed = [], []
5322 for d, s in c.iteritems():
5322 for d, s in c.iteritems():
5323 if s in st[2]:
5323 if s in st[2]:
5324 st[2].remove(s)
5324 st[2].remove(s)
5325 renamed.append(d)
5325 renamed.append(d)
5326 else:
5326 else:
5327 copied.append(d)
5327 copied.append(d)
5328 if d in st[1]:
5328 if d in st[1]:
5329 st[1].remove(d)
5329 st[1].remove(d)
5330 st.insert(3, renamed)
5330 st.insert(3, renamed)
5331 st.insert(4, copied)
5331 st.insert(4, copied)
5332
5332
5333 ms = mergemod.mergestate(repo)
5333 ms = mergemod.mergestate(repo)
5334 st.append([f for f in ms if ms[f] == 'u'])
5334 st.append([f for f in ms if ms[f] == 'u'])
5335
5335
5336 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5336 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5337 st.append(subs)
5337 st.append(subs)
5338
5338
5339 labels = [ui.label(_('%d modified'), 'status.modified'),
5339 labels = [ui.label(_('%d modified'), 'status.modified'),
5340 ui.label(_('%d added'), 'status.added'),
5340 ui.label(_('%d added'), 'status.added'),
5341 ui.label(_('%d removed'), 'status.removed'),
5341 ui.label(_('%d removed'), 'status.removed'),
5342 ui.label(_('%d renamed'), 'status.copied'),
5342 ui.label(_('%d renamed'), 'status.copied'),
5343 ui.label(_('%d copied'), 'status.copied'),
5343 ui.label(_('%d copied'), 'status.copied'),
5344 ui.label(_('%d deleted'), 'status.deleted'),
5344 ui.label(_('%d deleted'), 'status.deleted'),
5345 ui.label(_('%d unknown'), 'status.unknown'),
5345 ui.label(_('%d unknown'), 'status.unknown'),
5346 ui.label(_('%d ignored'), 'status.ignored'),
5346 ui.label(_('%d ignored'), 'status.ignored'),
5347 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5347 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5348 ui.label(_('%d subrepos'), 'status.modified')]
5348 ui.label(_('%d subrepos'), 'status.modified')]
5349 t = []
5349 t = []
5350 for s, l in zip(st, labels):
5350 for s, l in zip(st, labels):
5351 if s:
5351 if s:
5352 t.append(l % len(s))
5352 t.append(l % len(s))
5353
5353
5354 t = ', '.join(t)
5354 t = ', '.join(t)
5355 cleanworkdir = False
5355 cleanworkdir = False
5356
5356
5357 if len(parents) > 1:
5357 if len(parents) > 1:
5358 t += _(' (merge)')
5358 t += _(' (merge)')
5359 elif branch != parents[0].branch():
5359 elif branch != parents[0].branch():
5360 t += _(' (new branch)')
5360 t += _(' (new branch)')
5361 elif (parents[0].extra().get('close') and
5361 elif (parents[0].extra().get('close') and
5362 pnode in repo.branchheads(branch, closed=True)):
5362 pnode in repo.branchheads(branch, closed=True)):
5363 t += _(' (head closed)')
5363 t += _(' (head closed)')
5364 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5364 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5365 t += _(' (clean)')
5365 t += _(' (clean)')
5366 cleanworkdir = True
5366 cleanworkdir = True
5367 elif pnode not in bheads:
5367 elif pnode not in bheads:
5368 t += _(' (new branch head)')
5368 t += _(' (new branch head)')
5369
5369
5370 if cleanworkdir:
5370 if cleanworkdir:
5371 ui.status(_('commit: %s\n') % t.strip())
5371 ui.status(_('commit: %s\n') % t.strip())
5372 else:
5372 else:
5373 ui.write(_('commit: %s\n') % t.strip())
5373 ui.write(_('commit: %s\n') % t.strip())
5374
5374
5375 # all ancestors of branch heads - all ancestors of parent = new csets
5375 # all ancestors of branch heads - all ancestors of parent = new csets
5376 new = [0] * len(repo)
5376 new = [0] * len(repo)
5377 cl = repo.changelog
5377 cl = repo.changelog
5378 for a in [cl.rev(n) for n in bheads]:
5378 for a in [cl.rev(n) for n in bheads]:
5379 new[a] = 1
5379 new[a] = 1
5380 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5380 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5381 new[a] = 1
5381 new[a] = 1
5382 for a in [p.rev() for p in parents]:
5382 for a in [p.rev() for p in parents]:
5383 if a >= 0:
5383 if a >= 0:
5384 new[a] = 0
5384 new[a] = 0
5385 for a in cl.ancestors(*[p.rev() for p in parents]):
5385 for a in cl.ancestors(*[p.rev() for p in parents]):
5386 new[a] = 0
5386 new[a] = 0
5387 new = sum(new)
5387 new = sum(new)
5388
5388
5389 if new == 0:
5389 if new == 0:
5390 ui.status(_('update: (current)\n'))
5390 ui.status(_('update: (current)\n'))
5391 elif pnode not in bheads:
5391 elif pnode not in bheads:
5392 ui.write(_('update: %d new changesets (update)\n') % new)
5392 ui.write(_('update: %d new changesets (update)\n') % new)
5393 else:
5393 else:
5394 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5394 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5395 (new, len(bheads)))
5395 (new, len(bheads)))
5396
5396
5397 if opts.get('remote'):
5397 if opts.get('remote'):
5398 t = []
5398 t = []
5399 source, branches = hg.parseurl(ui.expandpath('default'))
5399 source, branches = hg.parseurl(ui.expandpath('default'))
5400 other = hg.peer(repo, {}, source)
5400 other = hg.peer(repo, {}, source)
5401 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5401 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5402 ui.debug('comparing with %s\n' % util.hidepassword(source))
5402 ui.debug('comparing with %s\n' % util.hidepassword(source))
5403 repo.ui.pushbuffer()
5403 repo.ui.pushbuffer()
5404 commoninc = discovery.findcommonincoming(repo, other)
5404 commoninc = discovery.findcommonincoming(repo, other)
5405 _common, incoming, _rheads = commoninc
5405 _common, incoming, _rheads = commoninc
5406 repo.ui.popbuffer()
5406 repo.ui.popbuffer()
5407 if incoming:
5407 if incoming:
5408 t.append(_('1 or more incoming'))
5408 t.append(_('1 or more incoming'))
5409
5409
5410 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5410 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5411 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5411 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5412 if source != dest:
5412 if source != dest:
5413 other = hg.peer(repo, {}, dest)
5413 other = hg.peer(repo, {}, dest)
5414 commoninc = None
5414 commoninc = None
5415 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5415 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5416 repo.ui.pushbuffer()
5416 repo.ui.pushbuffer()
5417 outgoing = discovery.findcommonoutgoing(repo, other,
5417 outgoing = discovery.findcommonoutgoing(repo, other,
5418 commoninc=commoninc)
5418 commoninc=commoninc)
5419 repo.ui.popbuffer()
5419 repo.ui.popbuffer()
5420 o = outgoing.missing
5420 o = outgoing.missing
5421 if o:
5421 if o:
5422 t.append(_('%d outgoing') % len(o))
5422 t.append(_('%d outgoing') % len(o))
5423 if 'bookmarks' in other.listkeys('namespaces'):
5423 if 'bookmarks' in other.listkeys('namespaces'):
5424 lmarks = repo.listkeys('bookmarks')
5424 lmarks = repo.listkeys('bookmarks')
5425 rmarks = other.listkeys('bookmarks')
5425 rmarks = other.listkeys('bookmarks')
5426 diff = set(rmarks) - set(lmarks)
5426 diff = set(rmarks) - set(lmarks)
5427 if len(diff) > 0:
5427 if len(diff) > 0:
5428 t.append(_('%d incoming bookmarks') % len(diff))
5428 t.append(_('%d incoming bookmarks') % len(diff))
5429 diff = set(lmarks) - set(rmarks)
5429 diff = set(lmarks) - set(rmarks)
5430 if len(diff) > 0:
5430 if len(diff) > 0:
5431 t.append(_('%d outgoing bookmarks') % len(diff))
5431 t.append(_('%d outgoing bookmarks') % len(diff))
5432
5432
5433 if t:
5433 if t:
5434 ui.write(_('remote: %s\n') % (', '.join(t)))
5434 ui.write(_('remote: %s\n') % (', '.join(t)))
5435 else:
5435 else:
5436 ui.status(_('remote: (synced)\n'))
5436 ui.status(_('remote: (synced)\n'))
5437
5437
5438 @command('tag',
5438 @command('tag',
5439 [('f', 'force', None, _('force tag')),
5439 [('f', 'force', None, _('force tag')),
5440 ('l', 'local', None, _('make the tag local')),
5440 ('l', 'local', None, _('make the tag local')),
5441 ('r', 'rev', '', _('revision to tag'), _('REV')),
5441 ('r', 'rev', '', _('revision to tag'), _('REV')),
5442 ('', 'remove', None, _('remove a tag')),
5442 ('', 'remove', None, _('remove a tag')),
5443 # -l/--local is already there, commitopts cannot be used
5443 # -l/--local is already there, commitopts cannot be used
5444 ('e', 'edit', None, _('edit commit message')),
5444 ('e', 'edit', None, _('edit commit message')),
5445 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5445 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5446 ] + commitopts2,
5446 ] + commitopts2,
5447 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5447 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5448 def tag(ui, repo, name1, *names, **opts):
5448 def tag(ui, repo, name1, *names, **opts):
5449 """add one or more tags for the current or given revision
5449 """add one or more tags for the current or given revision
5450
5450
5451 Name a particular revision using <name>.
5451 Name a particular revision using <name>.
5452
5452
5453 Tags are used to name particular revisions of the repository and are
5453 Tags are used to name particular revisions of the repository and are
5454 very useful to compare different revisions, to go back to significant
5454 very useful to compare different revisions, to go back to significant
5455 earlier versions or to mark branch points as releases, etc. Changing
5455 earlier versions or to mark branch points as releases, etc. Changing
5456 an existing tag is normally disallowed; use -f/--force to override.
5456 an existing tag is normally disallowed; use -f/--force to override.
5457
5457
5458 If no revision is given, the parent of the working directory is
5458 If no revision is given, the parent of the working directory is
5459 used, or tip if no revision is checked out.
5459 used, or tip if no revision is checked out.
5460
5460
5461 To facilitate version control, distribution, and merging of tags,
5461 To facilitate version control, distribution, and merging of tags,
5462 they are stored as a file named ".hgtags" which is managed similarly
5462 they are stored as a file named ".hgtags" which is managed similarly
5463 to other project files and can be hand-edited if necessary. This
5463 to other project files and can be hand-edited if necessary. This
5464 also means that tagging creates a new commit. The file
5464 also means that tagging creates a new commit. The file
5465 ".hg/localtags" is used for local tags (not shared among
5465 ".hg/localtags" is used for local tags (not shared among
5466 repositories).
5466 repositories).
5467
5467
5468 Tag commits are usually made at the head of a branch. If the parent
5468 Tag commits are usually made at the head of a branch. If the parent
5469 of the working directory is not a branch head, :hg:`tag` aborts; use
5469 of the working directory is not a branch head, :hg:`tag` aborts; use
5470 -f/--force to force the tag commit to be based on a non-head
5470 -f/--force to force the tag commit to be based on a non-head
5471 changeset.
5471 changeset.
5472
5472
5473 See :hg:`help dates` for a list of formats valid for -d/--date.
5473 See :hg:`help dates` for a list of formats valid for -d/--date.
5474
5474
5475 Since tag names have priority over branch names during revision
5475 Since tag names have priority over branch names during revision
5476 lookup, using an existing branch name as a tag name is discouraged.
5476 lookup, using an existing branch name as a tag name is discouraged.
5477
5477
5478 Returns 0 on success.
5478 Returns 0 on success.
5479 """
5479 """
5480 wlock = lock = None
5480 wlock = lock = None
5481 try:
5481 try:
5482 wlock = repo.wlock()
5482 wlock = repo.wlock()
5483 lock = repo.lock()
5483 lock = repo.lock()
5484 rev_ = "."
5484 rev_ = "."
5485 names = [t.strip() for t in (name1,) + names]
5485 names = [t.strip() for t in (name1,) + names]
5486 if len(names) != len(set(names)):
5486 if len(names) != len(set(names)):
5487 raise util.Abort(_('tag names must be unique'))
5487 raise util.Abort(_('tag names must be unique'))
5488 for n in names:
5488 for n in names:
5489 if n in ['tip', '.', 'null']:
5489 if n in ['tip', '.', 'null']:
5490 raise util.Abort(_("the name '%s' is reserved") % n)
5490 raise util.Abort(_("the name '%s' is reserved") % n)
5491 if not n:
5491 if not n:
5492 raise util.Abort(_('tag names cannot consist entirely of '
5492 raise util.Abort(_('tag names cannot consist entirely of '
5493 'whitespace'))
5493 'whitespace'))
5494 if opts.get('rev') and opts.get('remove'):
5494 if opts.get('rev') and opts.get('remove'):
5495 raise util.Abort(_("--rev and --remove are incompatible"))
5495 raise util.Abort(_("--rev and --remove are incompatible"))
5496 if opts.get('rev'):
5496 if opts.get('rev'):
5497 rev_ = opts['rev']
5497 rev_ = opts['rev']
5498 message = opts.get('message')
5498 message = opts.get('message')
5499 if opts.get('remove'):
5499 if opts.get('remove'):
5500 expectedtype = opts.get('local') and 'local' or 'global'
5500 expectedtype = opts.get('local') and 'local' or 'global'
5501 for n in names:
5501 for n in names:
5502 if not repo.tagtype(n):
5502 if not repo.tagtype(n):
5503 raise util.Abort(_("tag '%s' does not exist") % n)
5503 raise util.Abort(_("tag '%s' does not exist") % n)
5504 if repo.tagtype(n) != expectedtype:
5504 if repo.tagtype(n) != expectedtype:
5505 if expectedtype == 'global':
5505 if expectedtype == 'global':
5506 raise util.Abort(_("tag '%s' is not a global tag") % n)
5506 raise util.Abort(_("tag '%s' is not a global tag") % n)
5507 else:
5507 else:
5508 raise util.Abort(_("tag '%s' is not a local tag") % n)
5508 raise util.Abort(_("tag '%s' is not a local tag") % n)
5509 rev_ = nullid
5509 rev_ = nullid
5510 if not message:
5510 if not message:
5511 # we don't translate commit messages
5511 # we don't translate commit messages
5512 message = 'Removed tag %s' % ', '.join(names)
5512 message = 'Removed tag %s' % ', '.join(names)
5513 elif not opts.get('force'):
5513 elif not opts.get('force'):
5514 for n in names:
5514 for n in names:
5515 if n in repo.tags():
5515 if n in repo.tags():
5516 raise util.Abort(_("tag '%s' already exists "
5516 raise util.Abort(_("tag '%s' already exists "
5517 "(use -f to force)") % n)
5517 "(use -f to force)") % n)
5518 if not opts.get('local'):
5518 if not opts.get('local'):
5519 p1, p2 = repo.dirstate.parents()
5519 p1, p2 = repo.dirstate.parents()
5520 if p2 != nullid:
5520 if p2 != nullid:
5521 raise util.Abort(_('uncommitted merge'))
5521 raise util.Abort(_('uncommitted merge'))
5522 bheads = repo.branchheads()
5522 bheads = repo.branchheads()
5523 if not opts.get('force') and bheads and p1 not in bheads:
5523 if not opts.get('force') and bheads and p1 not in bheads:
5524 raise util.Abort(_('not at a branch head (use -f to force)'))
5524 raise util.Abort(_('not at a branch head (use -f to force)'))
5525 r = scmutil.revsingle(repo, rev_).node()
5525 r = scmutil.revsingle(repo, rev_).node()
5526
5526
5527 if not message:
5527 if not message:
5528 # we don't translate commit messages
5528 # we don't translate commit messages
5529 message = ('Added tag %s for changeset %s' %
5529 message = ('Added tag %s for changeset %s' %
5530 (', '.join(names), short(r)))
5530 (', '.join(names), short(r)))
5531
5531
5532 date = opts.get('date')
5532 date = opts.get('date')
5533 if date:
5533 if date:
5534 date = util.parsedate(date)
5534 date = util.parsedate(date)
5535
5535
5536 if opts.get('edit'):
5536 if opts.get('edit'):
5537 message = ui.edit(message, ui.username())
5537 message = ui.edit(message, ui.username())
5538
5538
5539 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5539 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5540 finally:
5540 finally:
5541 release(lock, wlock)
5541 release(lock, wlock)
5542
5542
5543 @command('tags', [], '')
5543 @command('tags', [], '')
5544 def tags(ui, repo):
5544 def tags(ui, repo):
5545 """list repository tags
5545 """list repository tags
5546
5546
5547 This lists both regular and local tags. When the -v/--verbose
5547 This lists both regular and local tags. When the -v/--verbose
5548 switch is used, a third column "local" is printed for local tags.
5548 switch is used, a third column "local" is printed for local tags.
5549
5549
5550 Returns 0 on success.
5550 Returns 0 on success.
5551 """
5551 """
5552
5552
5553 hexfunc = ui.debugflag and hex or short
5553 hexfunc = ui.debugflag and hex or short
5554 tagtype = ""
5554 tagtype = ""
5555
5555
5556 for t, n in reversed(repo.tagslist()):
5556 for t, n in reversed(repo.tagslist()):
5557 if ui.quiet:
5557 if ui.quiet:
5558 ui.write("%s\n" % t, label='tags.normal')
5558 ui.write("%s\n" % t, label='tags.normal')
5559 continue
5559 continue
5560
5560
5561 hn = hexfunc(n)
5561 hn = hexfunc(n)
5562 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5562 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5563 rev = ui.label(r, 'log.changeset')
5563 rev = ui.label(r, 'log.changeset')
5564 spaces = " " * (30 - encoding.colwidth(t))
5564 spaces = " " * (30 - encoding.colwidth(t))
5565
5565
5566 tag = ui.label(t, 'tags.normal')
5566 tag = ui.label(t, 'tags.normal')
5567 if ui.verbose:
5567 if ui.verbose:
5568 if repo.tagtype(t) == 'local':
5568 if repo.tagtype(t) == 'local':
5569 tagtype = " local"
5569 tagtype = " local"
5570 tag = ui.label(t, 'tags.local')
5570 tag = ui.label(t, 'tags.local')
5571 else:
5571 else:
5572 tagtype = ""
5572 tagtype = ""
5573 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5573 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5574
5574
5575 @command('tip',
5575 @command('tip',
5576 [('p', 'patch', None, _('show patch')),
5576 [('p', 'patch', None, _('show patch')),
5577 ('g', 'git', None, _('use git extended diff format')),
5577 ('g', 'git', None, _('use git extended diff format')),
5578 ] + templateopts,
5578 ] + templateopts,
5579 _('[-p] [-g]'))
5579 _('[-p] [-g]'))
5580 def tip(ui, repo, **opts):
5580 def tip(ui, repo, **opts):
5581 """show the tip revision
5581 """show the tip revision
5582
5582
5583 The tip revision (usually just called the tip) is the changeset
5583 The tip revision (usually just called the tip) is the changeset
5584 most recently added to the repository (and therefore the most
5584 most recently added to the repository (and therefore the most
5585 recently changed head).
5585 recently changed head).
5586
5586
5587 If you have just made a commit, that commit will be the tip. If
5587 If you have just made a commit, that commit will be the tip. If
5588 you have just pulled changes from another repository, the tip of
5588 you have just pulled changes from another repository, the tip of
5589 that repository becomes the current tip. The "tip" tag is special
5589 that repository becomes the current tip. The "tip" tag is special
5590 and cannot be renamed or assigned to a different changeset.
5590 and cannot be renamed or assigned to a different changeset.
5591
5591
5592 Returns 0 on success.
5592 Returns 0 on success.
5593 """
5593 """
5594 displayer = cmdutil.show_changeset(ui, repo, opts)
5594 displayer = cmdutil.show_changeset(ui, repo, opts)
5595 displayer.show(repo[len(repo) - 1])
5595 displayer.show(repo[len(repo) - 1])
5596 displayer.close()
5596 displayer.close()
5597
5597
5598 @command('unbundle',
5598 @command('unbundle',
5599 [('u', 'update', None,
5599 [('u', 'update', None,
5600 _('update to new branch head if changesets were unbundled'))],
5600 _('update to new branch head if changesets were unbundled'))],
5601 _('[-u] FILE...'))
5601 _('[-u] FILE...'))
5602 def unbundle(ui, repo, fname1, *fnames, **opts):
5602 def unbundle(ui, repo, fname1, *fnames, **opts):
5603 """apply one or more changegroup files
5603 """apply one or more changegroup files
5604
5604
5605 Apply one or more compressed changegroup files generated by the
5605 Apply one or more compressed changegroup files generated by the
5606 bundle command.
5606 bundle command.
5607
5607
5608 Returns 0 on success, 1 if an update has unresolved files.
5608 Returns 0 on success, 1 if an update has unresolved files.
5609 """
5609 """
5610 fnames = (fname1,) + fnames
5610 fnames = (fname1,) + fnames
5611
5611
5612 lock = repo.lock()
5612 lock = repo.lock()
5613 wc = repo['.']
5613 wc = repo['.']
5614 try:
5614 try:
5615 for fname in fnames:
5615 for fname in fnames:
5616 f = url.open(ui, fname)
5616 f = url.open(ui, fname)
5617 gen = changegroup.readbundle(f, fname)
5617 gen = changegroup.readbundle(f, fname)
5618 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5618 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5619 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5619 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5620 finally:
5620 finally:
5621 lock.release()
5621 lock.release()
5622 return postincoming(ui, repo, modheads, opts.get('update'), None)
5622 return postincoming(ui, repo, modheads, opts.get('update'), None)
5623
5623
5624 @command('^update|up|checkout|co',
5624 @command('^update|up|checkout|co',
5625 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5625 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5626 ('c', 'check', None,
5626 ('c', 'check', None,
5627 _('update across branches if no uncommitted changes')),
5627 _('update across branches if no uncommitted changes')),
5628 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5628 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5629 ('r', 'rev', '', _('revision'), _('REV'))],
5629 ('r', 'rev', '', _('revision'), _('REV'))],
5630 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5630 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5631 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5631 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5632 """update working directory (or switch revisions)
5632 """update working directory (or switch revisions)
5633
5633
5634 Update the repository's working directory to the specified
5634 Update the repository's working directory to the specified
5635 changeset. If no changeset is specified, update to the tip of the
5635 changeset. If no changeset is specified, update to the tip of the
5636 current named branch.
5636 current named branch and move the current bookmark.
5637
5637
5638 If the changeset is not a descendant of the working directory's
5638 If the changeset is not a descendant of the working directory's
5639 parent, the update is aborted. With the -c/--check option, the
5639 parent, the update is aborted. With the -c/--check option, the
5640 working directory is checked for uncommitted changes; if none are
5640 working directory is checked for uncommitted changes; if none are
5641 found, the working directory is updated to the specified
5641 found, the working directory is updated to the specified
5642 changeset.
5642 changeset.
5643
5643
5644 Update sets the working directory's parent revison to the specified
5644 Update sets the working directory's parent revison to the specified
5645 changeset (see :hg:`help parents`).
5645 changeset (see :hg:`help parents`).
5646
5646
5647 The following rules apply when the working directory contains
5647 The following rules apply when the working directory contains
5648 uncommitted changes:
5648 uncommitted changes:
5649
5649
5650 1. If neither -c/--check nor -C/--clean is specified, and if
5650 1. If neither -c/--check nor -C/--clean is specified, and if
5651 the requested changeset is an ancestor or descendant of
5651 the requested changeset is an ancestor or descendant of
5652 the working directory's parent, the uncommitted changes
5652 the working directory's parent, the uncommitted changes
5653 are merged into the requested changeset and the merged
5653 are merged into the requested changeset and the merged
5654 result is left uncommitted. If the requested changeset is
5654 result is left uncommitted. If the requested changeset is
5655 not an ancestor or descendant (that is, it is on another
5655 not an ancestor or descendant (that is, it is on another
5656 branch), the update is aborted and the uncommitted changes
5656 branch), the update is aborted and the uncommitted changes
5657 are preserved.
5657 are preserved.
5658
5658
5659 2. With the -c/--check option, the update is aborted and the
5659 2. With the -c/--check option, the update is aborted and the
5660 uncommitted changes are preserved.
5660 uncommitted changes are preserved.
5661
5661
5662 3. With the -C/--clean option, uncommitted changes are discarded and
5662 3. With the -C/--clean option, uncommitted changes are discarded and
5663 the working directory is updated to the requested changeset.
5663 the working directory is updated to the requested changeset.
5664
5664
5665 Use null as the changeset to remove the working directory (like
5665 Use null as the changeset to remove the working directory (like
5666 :hg:`clone -U`).
5666 :hg:`clone -U`).
5667
5667
5668 If you want to revert just one file to an older revision, use
5668 If you want to revert just one file to an older revision, use
5669 :hg:`revert [-r REV] NAME`.
5669 :hg:`revert [-r REV] NAME`.
5670
5670
5671 See :hg:`help dates` for a list of formats valid for -d/--date.
5671 See :hg:`help dates` for a list of formats valid for -d/--date.
5672
5672
5673 Returns 0 on success, 1 if there are unresolved files.
5673 Returns 0 on success, 1 if there are unresolved files.
5674 """
5674 """
5675 if rev and node:
5675 if rev and node:
5676 raise util.Abort(_("please specify just one revision"))
5676 raise util.Abort(_("please specify just one revision"))
5677
5677
5678 if rev is None or rev == '':
5678 if rev is None or rev == '':
5679 rev = node
5679 rev = node
5680
5680
5681 # with no argument, we also move the current bookmark, if any
5682 movemarkfrom = None
5683 if node is None or node == '':
5684 movemarkfrom = repo['.'].node()
5685
5681 # if we defined a bookmark, we have to remember the original bookmark name
5686 # if we defined a bookmark, we have to remember the original bookmark name
5682 brev = rev
5687 brev = rev
5683 rev = scmutil.revsingle(repo, rev, rev).rev()
5688 rev = scmutil.revsingle(repo, rev, rev).rev()
5684
5689
5685 if check and clean:
5690 if check and clean:
5686 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5691 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5687
5692
5688 if check:
5693 if check:
5689 # we could use dirty() but we can ignore merge and branch trivia
5694 # we could use dirty() but we can ignore merge and branch trivia
5690 c = repo[None]
5695 c = repo[None]
5691 if c.modified() or c.added() or c.removed():
5696 if c.modified() or c.added() or c.removed():
5692 raise util.Abort(_("uncommitted local changes"))
5697 raise util.Abort(_("uncommitted local changes"))
5693
5698
5694 if date:
5699 if date:
5695 if rev is not None:
5700 if rev is not None:
5696 raise util.Abort(_("you can't specify a revision and a date"))
5701 raise util.Abort(_("you can't specify a revision and a date"))
5697 rev = cmdutil.finddate(ui, repo, date)
5702 rev = cmdutil.finddate(ui, repo, date)
5698
5703
5699 if clean or check:
5704 if clean or check:
5700 ret = hg.clean(repo, rev)
5705 ret = hg.clean(repo, rev)
5701 else:
5706 else:
5702 ret = hg.update(repo, rev)
5707 ret = hg.update(repo, rev)
5703
5708
5704 if brev in repo._bookmarks:
5709 if not ret and movemarkfrom:
5710 bookmarks.update(repo, [movemarkfrom], repo['.'].node())
5711 elif brev in repo._bookmarks:
5705 bookmarks.setcurrent(repo, brev)
5712 bookmarks.setcurrent(repo, brev)
5706
5713
5707 return ret
5714 return ret
5708
5715
5709 @command('verify', [])
5716 @command('verify', [])
5710 def verify(ui, repo):
5717 def verify(ui, repo):
5711 """verify the integrity of the repository
5718 """verify the integrity of the repository
5712
5719
5713 Verify the integrity of the current repository.
5720 Verify the integrity of the current repository.
5714
5721
5715 This will perform an extensive check of the repository's
5722 This will perform an extensive check of the repository's
5716 integrity, validating the hashes and checksums of each entry in
5723 integrity, validating the hashes and checksums of each entry in
5717 the changelog, manifest, and tracked files, as well as the
5724 the changelog, manifest, and tracked files, as well as the
5718 integrity of their crosslinks and indices.
5725 integrity of their crosslinks and indices.
5719
5726
5720 Returns 0 on success, 1 if errors are encountered.
5727 Returns 0 on success, 1 if errors are encountered.
5721 """
5728 """
5722 return hg.verify(repo)
5729 return hg.verify(repo)
5723
5730
5724 @command('version', [])
5731 @command('version', [])
5725 def version_(ui):
5732 def version_(ui):
5726 """output version and copyright information"""
5733 """output version and copyright information"""
5727 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5734 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5728 % util.version())
5735 % util.version())
5729 ui.status(_(
5736 ui.status(_(
5730 "(see http://mercurial.selenic.com for more information)\n"
5737 "(see http://mercurial.selenic.com for more information)\n"
5731 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5738 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5732 "This is free software; see the source for copying conditions. "
5739 "This is free software; see the source for copying conditions. "
5733 "There is NO\nwarranty; "
5740 "There is NO\nwarranty; "
5734 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5741 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5735 ))
5742 ))
5736
5743
5737 norepo = ("clone init version help debugcommands debugcomplete"
5744 norepo = ("clone init version help debugcommands debugcomplete"
5738 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5745 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5739 " debugknown debuggetbundle debugbundle")
5746 " debugknown debuggetbundle debugbundle")
5740 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5747 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5741 " debugdata debugindex debugindexdot debugrevlog")
5748 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,198 +1,198
1 $ "$TESTDIR/hghave" serve || exit 80
1 $ "$TESTDIR/hghave" serve || exit 80
2
2
3 initialize
3 initialize
4
4
5 $ hg init a
5 $ hg init a
6 $ cd a
6 $ cd a
7 $ echo 'test' > test
7 $ echo 'test' > test
8 $ hg commit -Am'test'
8 $ hg commit -Am'test'
9 adding test
9 adding test
10
10
11 set bookmarks
11 set bookmarks
12
12
13 $ hg bookmark X
13 $ hg bookmark X
14 $ hg bookmark Y
14 $ hg bookmark Y
15 $ hg bookmark Z
15 $ hg bookmark Z
16
16
17 import bookmark by name
17 import bookmark by name
18
18
19 $ hg init ../b
19 $ hg init ../b
20 $ cd ../b
20 $ cd ../b
21 $ hg book Y
21 $ hg book Y
22 $ hg book
22 $ hg book
23 * Y -1:000000000000
23 * Y -1:000000000000
24 $ hg pull ../a
24 $ hg pull ../a
25 pulling from ../a
25 pulling from ../a
26 requesting all changes
26 requesting all changes
27 adding changesets
27 adding changesets
28 adding manifests
28 adding manifests
29 adding file changes
29 adding file changes
30 added 1 changesets with 1 changes to 1 files
30 added 1 changesets with 1 changes to 1 files
31 updating bookmark Y
31 updating bookmark Y
32 (run 'hg update' to get a working copy)
32 (run 'hg update' to get a working copy)
33 $ hg bookmarks
33 $ hg bookmarks
34 Y 0:4e3505fd9583
34 Y 0:4e3505fd9583
35 $ hg debugpushkey ../a namespaces
35 $ hg debugpushkey ../a namespaces
36 bookmarks
36 bookmarks
37 phases
37 phases
38 namespaces
38 namespaces
39 $ hg debugpushkey ../a bookmarks
39 $ hg debugpushkey ../a bookmarks
40 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
40 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
41 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
41 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
42 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
42 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
43 $ hg pull -B X ../a
43 $ hg pull -B X ../a
44 pulling from ../a
44 pulling from ../a
45 no changes found
45 no changes found
46 importing bookmark X
46 importing bookmark X
47 $ hg bookmark
47 $ hg bookmark
48 X 0:4e3505fd9583
48 X 0:4e3505fd9583
49 Y 0:4e3505fd9583
49 Y 0:4e3505fd9583
50
50
51 export bookmark by name
51 export bookmark by name
52
52
53 $ hg bookmark W
53 $ hg bookmark W
54 $ hg bookmark foo
54 $ hg bookmark foo
55 $ hg bookmark foobar
55 $ hg bookmark foobar
56 $ hg push -B W ../a
56 $ hg push -B W ../a
57 pushing to ../a
57 pushing to ../a
58 searching for changes
58 searching for changes
59 no changes found
59 no changes found
60 exporting bookmark W
60 exporting bookmark W
61 $ hg -R ../a bookmarks
61 $ hg -R ../a bookmarks
62 W -1:000000000000
62 W -1:000000000000
63 X 0:4e3505fd9583
63 X 0:4e3505fd9583
64 Y 0:4e3505fd9583
64 Y 0:4e3505fd9583
65 * Z 0:4e3505fd9583
65 * Z 0:4e3505fd9583
66
66
67 delete a remote bookmark
67 delete a remote bookmark
68
68
69 $ hg book -d W
69 $ hg book -d W
70 $ hg push -B W ../a
70 $ hg push -B W ../a
71 pushing to ../a
71 pushing to ../a
72 searching for changes
72 searching for changes
73 no changes found
73 no changes found
74 deleting remote bookmark W
74 deleting remote bookmark W
75
75
76 push/pull name that doesn't exist
76 push/pull name that doesn't exist
77
77
78 $ hg push -B badname ../a
78 $ hg push -B badname ../a
79 pushing to ../a
79 pushing to ../a
80 searching for changes
80 searching for changes
81 no changes found
81 no changes found
82 bookmark badname does not exist on the local or remote repository!
82 bookmark badname does not exist on the local or remote repository!
83 [2]
83 [2]
84 $ hg pull -B anotherbadname ../a
84 $ hg pull -B anotherbadname ../a
85 pulling from ../a
85 pulling from ../a
86 abort: remote bookmark anotherbadname not found!
86 abort: remote bookmark anotherbadname not found!
87 [255]
87 [255]
88
88
89 divergent bookmarks
89 divergent bookmarks
90
90
91 $ cd ../a
91 $ cd ../a
92 $ echo c1 > f1
92 $ echo c1 > f1
93 $ hg ci -Am1
93 $ hg ci -Am1
94 adding f1
94 adding f1
95 $ hg book -f X
95 $ hg book -f X
96 $ hg book
96 $ hg book
97 * X 1:0d2164f0ce0d
97 * X 1:0d2164f0ce0d
98 Y 0:4e3505fd9583
98 Y 0:4e3505fd9583
99 Z 1:0d2164f0ce0d
99 Z 1:0d2164f0ce0d
100
100
101 $ cd ../b
101 $ cd ../b
102 $ hg up
102 $ hg up
103 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 $ echo c2 > f2
104 $ echo c2 > f2
105 $ hg ci -Am2
105 $ hg ci -Am2
106 adding f2
106 adding f2
107 $ hg book -f X
107 $ hg book -f X
108 $ hg book
108 $ hg book
109 * X 1:9b140be10808
109 * X 1:9b140be10808
110 Y 0:4e3505fd9583
110 Y 0:4e3505fd9583
111 foo -1:000000000000
111 foo -1:000000000000
112 foobar -1:000000000000
112 foobar 1:9b140be10808
113
113
114 $ hg pull --config paths.foo=../a foo
114 $ hg pull --config paths.foo=../a foo
115 pulling from $TESTTMP/a
115 pulling from $TESTTMP/a
116 searching for changes
116 searching for changes
117 adding changesets
117 adding changesets
118 adding manifests
118 adding manifests
119 adding file changes
119 adding file changes
120 added 1 changesets with 1 changes to 1 files (+1 heads)
120 added 1 changesets with 1 changes to 1 files (+1 heads)
121 divergent bookmark X stored as X@foo
121 divergent bookmark X stored as X@foo
122 (run 'hg heads' to see heads, 'hg merge' to merge)
122 (run 'hg heads' to see heads, 'hg merge' to merge)
123 $ hg book
123 $ hg book
124 * X 1:9b140be10808
124 * X 1:9b140be10808
125 X@foo 2:0d2164f0ce0d
125 X@foo 2:0d2164f0ce0d
126 Y 0:4e3505fd9583
126 Y 0:4e3505fd9583
127 foo -1:000000000000
127 foo -1:000000000000
128 foobar -1:000000000000
128 foobar 1:9b140be10808
129 $ hg push -f ../a
129 $ hg push -f ../a
130 pushing to ../a
130 pushing to ../a
131 searching for changes
131 searching for changes
132 adding changesets
132 adding changesets
133 adding manifests
133 adding manifests
134 adding file changes
134 adding file changes
135 added 1 changesets with 1 changes to 1 files (+1 heads)
135 added 1 changesets with 1 changes to 1 files (+1 heads)
136 $ hg -R ../a book
136 $ hg -R ../a book
137 * X 1:0d2164f0ce0d
137 * X 1:0d2164f0ce0d
138 Y 0:4e3505fd9583
138 Y 0:4e3505fd9583
139 Z 1:0d2164f0ce0d
139 Z 1:0d2164f0ce0d
140
140
141 hgweb
141 hgweb
142
142
143 $ cat <<EOF > .hg/hgrc
143 $ cat <<EOF > .hg/hgrc
144 > [web]
144 > [web]
145 > push_ssl = false
145 > push_ssl = false
146 > allow_push = *
146 > allow_push = *
147 > EOF
147 > EOF
148
148
149 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
149 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
150 $ cat ../hg.pid >> $DAEMON_PIDS
150 $ cat ../hg.pid >> $DAEMON_PIDS
151 $ cd ../a
151 $ cd ../a
152
152
153 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
153 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
154 bookmarks
154 bookmarks
155 phases
155 phases
156 namespaces
156 namespaces
157 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
157 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
158 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
158 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
159 X 9b140be1080824d768c5a4691a564088eede71f9
159 X 9b140be1080824d768c5a4691a564088eede71f9
160 foo 0000000000000000000000000000000000000000
160 foo 0000000000000000000000000000000000000000
161 foobar 0000000000000000000000000000000000000000
161 foobar 9b140be1080824d768c5a4691a564088eede71f9
162 $ hg out -B http://localhost:$HGPORT/
162 $ hg out -B http://localhost:$HGPORT/
163 comparing with http://localhost:$HGPORT/
163 comparing with http://localhost:$HGPORT/
164 searching for changed bookmarks
164 searching for changed bookmarks
165 Z 0d2164f0ce0d
165 Z 0d2164f0ce0d
166 $ hg push -B Z http://localhost:$HGPORT/
166 $ hg push -B Z http://localhost:$HGPORT/
167 pushing to http://localhost:$HGPORT/
167 pushing to http://localhost:$HGPORT/
168 searching for changes
168 searching for changes
169 no changes found
169 no changes found
170 exporting bookmark Z
170 exporting bookmark Z
171 $ hg book -d Z
171 $ hg book -d Z
172 $ hg in -B http://localhost:$HGPORT/
172 $ hg in -B http://localhost:$HGPORT/
173 comparing with http://localhost:$HGPORT/
173 comparing with http://localhost:$HGPORT/
174 searching for changed bookmarks
174 searching for changed bookmarks
175 Z 0d2164f0ce0d
175 Z 0d2164f0ce0d
176 foo 000000000000
176 foo 000000000000
177 foobar 000000000000
177 foobar 9b140be10808
178 $ hg pull -B Z http://localhost:$HGPORT/
178 $ hg pull -B Z http://localhost:$HGPORT/
179 pulling from http://localhost:$HGPORT/
179 pulling from http://localhost:$HGPORT/
180 no changes found
180 no changes found
181 divergent bookmark X stored as X@1
181 divergent bookmark X stored as X@1
182 importing bookmark Z
182 importing bookmark Z
183 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
183 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
184 requesting all changes
184 requesting all changes
185 adding changesets
185 adding changesets
186 adding manifests
186 adding manifests
187 adding file changes
187 adding file changes
188 added 3 changesets with 3 changes to 3 files (+1 heads)
188 added 3 changesets with 3 changes to 3 files (+1 heads)
189 updating to branch default
189 updating to branch default
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 $ hg -R cloned-bookmarks bookmarks
191 $ hg -R cloned-bookmarks bookmarks
192 X 1:9b140be10808
192 X 1:9b140be10808
193 Y 0:4e3505fd9583
193 Y 0:4e3505fd9583
194 Z 2:0d2164f0ce0d
194 Z 2:0d2164f0ce0d
195 foo -1:000000000000
195 foo -1:000000000000
196 foobar -1:000000000000
196 foobar 1:9b140be10808
197
197
198 $ kill `cat ../hg.pid`
198 $ kill `cat ../hg.pid`
General Comments 0
You need to be logged in to leave comments. Login now