##// END OF EJS Templates
bookmarks: remove redundant check for newline...
Kevin Bullock -
r17814:f88ca484 default
parent child Browse files
Show More
@@ -1,5926 +1,5924 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ]
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 ('G', 'graph', None, _("show the revision DAG")),
101 ('G', 'graph', None, _("show the revision DAG")),
102 ] + templateopts
102 ] + templateopts
103
103
104 diffopts = [
104 diffopts = [
105 ('a', 'text', None, _('treat all files as text')),
105 ('a', 'text', None, _('treat all files as text')),
106 ('g', 'git', None, _('use git extended diff format')),
106 ('g', 'git', None, _('use git extended diff format')),
107 ('', 'nodates', None, _('omit dates from diff headers'))
107 ('', 'nodates', None, _('omit dates from diff headers'))
108 ]
108 ]
109
109
110 diffwsopts = [
110 diffwsopts = [
111 ('w', 'ignore-all-space', None,
111 ('w', 'ignore-all-space', None,
112 _('ignore white space when comparing lines')),
112 _('ignore white space when comparing lines')),
113 ('b', 'ignore-space-change', None,
113 ('b', 'ignore-space-change', None,
114 _('ignore changes in the amount of white space')),
114 _('ignore changes in the amount of white space')),
115 ('B', 'ignore-blank-lines', None,
115 ('B', 'ignore-blank-lines', None,
116 _('ignore changes whose lines are all blank')),
116 _('ignore changes whose lines are all blank')),
117 ]
117 ]
118
118
119 diffopts2 = [
119 diffopts2 = [
120 ('p', 'show-function', None, _('show which function each change is in')),
120 ('p', 'show-function', None, _('show which function each change is in')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ] + diffwsopts + [
122 ] + diffwsopts + [
123 ('U', 'unified', '',
123 ('U', 'unified', '',
124 _('number of lines of context to show'), _('NUM')),
124 _('number of lines of context to show'), _('NUM')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ]
126 ]
127
127
128 mergetoolopts = [
128 mergetoolopts = [
129 ('t', 'tool', '', _('specify merge tool')),
129 ('t', 'tool', '', _('specify merge tool')),
130 ]
130 ]
131
131
132 similarityopts = [
132 similarityopts = [
133 ('s', 'similarity', '',
133 ('s', 'similarity', '',
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 ]
135 ]
136
136
137 subrepoopts = [
137 subrepoopts = [
138 ('S', 'subrepos', None,
138 ('S', 'subrepos', None,
139 _('recurse into subrepositories'))
139 _('recurse into subrepositories'))
140 ]
140 ]
141
141
142 # Commands start here, listed alphabetically
142 # Commands start here, listed alphabetically
143
143
144 @command('^add',
144 @command('^add',
145 walkopts + subrepoopts + dryrunopts,
145 walkopts + subrepoopts + dryrunopts,
146 _('[OPTION]... [FILE]...'))
146 _('[OPTION]... [FILE]...'))
147 def add(ui, repo, *pats, **opts):
147 def add(ui, repo, *pats, **opts):
148 """add the specified files on the next commit
148 """add the specified files on the next commit
149
149
150 Schedule files to be version controlled and added to the
150 Schedule files to be version controlled and added to the
151 repository.
151 repository.
152
152
153 The files will be added to the repository at the next commit. To
153 The files will be added to the repository at the next commit. To
154 undo an add before that, see :hg:`forget`.
154 undo an add before that, see :hg:`forget`.
155
155
156 If no names are given, add all files to the repository.
156 If no names are given, add all files to the repository.
157
157
158 .. container:: verbose
158 .. container:: verbose
159
159
160 An example showing how new (unknown) files are added
160 An example showing how new (unknown) files are added
161 automatically by :hg:`add`::
161 automatically by :hg:`add`::
162
162
163 $ ls
163 $ ls
164 foo.c
164 foo.c
165 $ hg status
165 $ hg status
166 ? foo.c
166 ? foo.c
167 $ hg add
167 $ hg add
168 adding foo.c
168 adding foo.c
169 $ hg status
169 $ hg status
170 A foo.c
170 A foo.c
171
171
172 Returns 0 if all files are successfully added.
172 Returns 0 if all files are successfully added.
173 """
173 """
174
174
175 m = scmutil.match(repo[None], pats, opts)
175 m = scmutil.match(repo[None], pats, opts)
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 opts.get('subrepos'), prefix="", explicitonly=False)
177 opts.get('subrepos'), prefix="", explicitonly=False)
178 return rejected and 1 or 0
178 return rejected and 1 or 0
179
179
180 @command('addremove',
180 @command('addremove',
181 similarityopts + walkopts + dryrunopts,
181 similarityopts + walkopts + dryrunopts,
182 _('[OPTION]... [FILE]...'))
182 _('[OPTION]... [FILE]...'))
183 def addremove(ui, repo, *pats, **opts):
183 def addremove(ui, repo, *pats, **opts):
184 """add all new files, delete all missing files
184 """add all new files, delete all missing files
185
185
186 Add all new files and remove all missing files from the
186 Add all new files and remove all missing files from the
187 repository.
187 repository.
188
188
189 New files are ignored if they match any of the patterns in
189 New files are ignored if they match any of the patterns in
190 ``.hgignore``. As with add, these changes take effect at the next
190 ``.hgignore``. As with add, these changes take effect at the next
191 commit.
191 commit.
192
192
193 Use the -s/--similarity option to detect renamed files. This
193 Use the -s/--similarity option to detect renamed files. This
194 option takes a percentage between 0 (disabled) and 100 (files must
194 option takes a percentage between 0 (disabled) and 100 (files must
195 be identical) as its parameter. With a parameter greater than 0,
195 be identical) as its parameter. With a parameter greater than 0,
196 this compares every removed file with every added file and records
196 this compares every removed file with every added file and records
197 those similar enough as renames. Detecting renamed files this way
197 those similar enough as renames. Detecting renamed files this way
198 can be expensive. After using this option, :hg:`status -C` can be
198 can be expensive. After using this option, :hg:`status -C` can be
199 used to check which files were identified as moved or renamed. If
199 used to check which files were identified as moved or renamed. If
200 not specified, -s/--similarity defaults to 100 and only renames of
200 not specified, -s/--similarity defaults to 100 and only renames of
201 identical files are detected.
201 identical files are detected.
202
202
203 Returns 0 if all files are successfully added.
203 Returns 0 if all files are successfully added.
204 """
204 """
205 try:
205 try:
206 sim = float(opts.get('similarity') or 100)
206 sim = float(opts.get('similarity') or 100)
207 except ValueError:
207 except ValueError:
208 raise util.Abort(_('similarity must be a number'))
208 raise util.Abort(_('similarity must be a number'))
209 if sim < 0 or sim > 100:
209 if sim < 0 or sim > 100:
210 raise util.Abort(_('similarity must be between 0 and 100'))
210 raise util.Abort(_('similarity must be between 0 and 100'))
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212
212
213 @command('^annotate|blame',
213 @command('^annotate|blame',
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 ('', 'follow', None,
215 ('', 'follow', None,
216 _('follow copies/renames and list the filename (DEPRECATED)')),
216 _('follow copies/renames and list the filename (DEPRECATED)')),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('a', 'text', None, _('treat all files as text')),
218 ('a', 'text', None, _('treat all files as text')),
219 ('u', 'user', None, _('list the author (long with -v)')),
219 ('u', 'user', None, _('list the author (long with -v)')),
220 ('f', 'file', None, _('list the filename')),
220 ('f', 'file', None, _('list the filename')),
221 ('d', 'date', None, _('list the date (short with -q)')),
221 ('d', 'date', None, _('list the date (short with -q)')),
222 ('n', 'number', None, _('list the revision number (default)')),
222 ('n', 'number', None, _('list the revision number (default)')),
223 ('c', 'changeset', None, _('list the changeset')),
223 ('c', 'changeset', None, _('list the changeset')),
224 ('l', 'line-number', None, _('show line number at the first appearance'))
224 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ] + diffwsopts + walkopts,
225 ] + diffwsopts + walkopts,
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 def annotate(ui, repo, *pats, **opts):
227 def annotate(ui, repo, *pats, **opts):
228 """show changeset information by line for each file
228 """show changeset information by line for each file
229
229
230 List changes in files, showing the revision id responsible for
230 List changes in files, showing the revision id responsible for
231 each line
231 each line
232
232
233 This command is useful for discovering when a change was made and
233 This command is useful for discovering when a change was made and
234 by whom.
234 by whom.
235
235
236 Without the -a/--text option, annotate will avoid processing files
236 Without the -a/--text option, annotate will avoid processing files
237 it detects as binary. With -a, annotate will annotate the file
237 it detects as binary. With -a, annotate will annotate the file
238 anyway, although the results will probably be neither useful
238 anyway, although the results will probably be neither useful
239 nor desirable.
239 nor desirable.
240
240
241 Returns 0 on success.
241 Returns 0 on success.
242 """
242 """
243 if opts.get('follow'):
243 if opts.get('follow'):
244 # --follow is deprecated and now just an alias for -f/--file
244 # --follow is deprecated and now just an alias for -f/--file
245 # to mimic the behavior of Mercurial before version 1.5
245 # to mimic the behavior of Mercurial before version 1.5
246 opts['file'] = True
246 opts['file'] = True
247
247
248 datefunc = ui.quiet and util.shortdate or util.datestr
248 datefunc = ui.quiet and util.shortdate or util.datestr
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250
250
251 if not pats:
251 if not pats:
252 raise util.Abort(_('at least one filename or pattern is required'))
252 raise util.Abort(_('at least one filename or pattern is required'))
253
253
254 hexfn = ui.debugflag and hex or short
254 hexfn = ui.debugflag and hex or short
255
255
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 ('number', ' ', lambda x: str(x[0].rev())),
257 ('number', ' ', lambda x: str(x[0].rev())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('date', ' ', getdate),
259 ('date', ' ', getdate),
260 ('file', ' ', lambda x: x[0].path()),
260 ('file', ' ', lambda x: x[0].path()),
261 ('line_number', ':', lambda x: str(x[1])),
261 ('line_number', ':', lambda x: str(x[1])),
262 ]
262 ]
263
263
264 if (not opts.get('user') and not opts.get('changeset')
264 if (not opts.get('user') and not opts.get('changeset')
265 and not opts.get('date') and not opts.get('file')):
265 and not opts.get('date') and not opts.get('file')):
266 opts['number'] = True
266 opts['number'] = True
267
267
268 linenumber = opts.get('line_number') is not None
268 linenumber = opts.get('line_number') is not None
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
271
271
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274
274
275 def bad(x, y):
275 def bad(x, y):
276 raise util.Abort("%s: %s" % (x, y))
276 raise util.Abort("%s: %s" % (x, y))
277
277
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 m = scmutil.match(ctx, pats, opts)
279 m = scmutil.match(ctx, pats, opts)
280 m.bad = bad
280 m.bad = bad
281 follow = not opts.get('no_follow')
281 follow = not opts.get('no_follow')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
283 for abs in ctx.walk(m):
283 for abs in ctx.walk(m):
284 fctx = ctx[abs]
284 fctx = ctx[abs]
285 if not opts.get('text') and util.binary(fctx.data()):
285 if not opts.get('text') and util.binary(fctx.data()):
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 continue
287 continue
288
288
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 diffopts=diffopts)
290 diffopts=diffopts)
291 pieces = []
291 pieces = []
292
292
293 for f, sep in funcmap:
293 for f, sep in funcmap:
294 l = [f(n) for n, dummy in lines]
294 l = [f(n) for n, dummy in lines]
295 if l:
295 if l:
296 sized = [(x, encoding.colwidth(x)) for x in l]
296 sized = [(x, encoding.colwidth(x)) for x in l]
297 ml = max([w for x, w in sized])
297 ml = max([w for x, w in sized])
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 for x, w in sized])
299 for x, w in sized])
300
300
301 if pieces:
301 if pieces:
302 for p, l in zip(zip(*pieces), lines):
302 for p, l in zip(zip(*pieces), lines):
303 ui.write("%s: %s" % ("".join(p), l[1]))
303 ui.write("%s: %s" % ("".join(p), l[1]))
304
304
305 if lines and not lines[-1][1].endswith('\n'):
305 if lines and not lines[-1][1].endswith('\n'):
306 ui.write('\n')
306 ui.write('\n')
307
307
308 @command('archive',
308 @command('archive',
309 [('', 'no-decode', None, _('do not pass files through decoders')),
309 [('', 'no-decode', None, _('do not pass files through decoders')),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 _('PREFIX')),
311 _('PREFIX')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ] + subrepoopts + walkopts,
314 ] + subrepoopts + walkopts,
315 _('[OPTION]... DEST'))
315 _('[OPTION]... DEST'))
316 def archive(ui, repo, dest, **opts):
316 def archive(ui, repo, dest, **opts):
317 '''create an unversioned archive of a repository revision
317 '''create an unversioned archive of a repository revision
318
318
319 By default, the revision used is the parent of the working
319 By default, the revision used is the parent of the working
320 directory; use -r/--rev to specify a different revision.
320 directory; use -r/--rev to specify a different revision.
321
321
322 The archive type is automatically detected based on file
322 The archive type is automatically detected based on file
323 extension (or override using -t/--type).
323 extension (or override using -t/--type).
324
324
325 .. container:: verbose
325 .. container:: verbose
326
326
327 Examples:
327 Examples:
328
328
329 - create a zip file containing the 1.0 release::
329 - create a zip file containing the 1.0 release::
330
330
331 hg archive -r 1.0 project-1.0.zip
331 hg archive -r 1.0 project-1.0.zip
332
332
333 - create a tarball excluding .hg files::
333 - create a tarball excluding .hg files::
334
334
335 hg archive project.tar.gz -X ".hg*"
335 hg archive project.tar.gz -X ".hg*"
336
336
337 Valid types are:
337 Valid types are:
338
338
339 :``files``: a directory full of files (default)
339 :``files``: a directory full of files (default)
340 :``tar``: tar archive, uncompressed
340 :``tar``: tar archive, uncompressed
341 :``tbz2``: tar archive, compressed using bzip2
341 :``tbz2``: tar archive, compressed using bzip2
342 :``tgz``: tar archive, compressed using gzip
342 :``tgz``: tar archive, compressed using gzip
343 :``uzip``: zip archive, uncompressed
343 :``uzip``: zip archive, uncompressed
344 :``zip``: zip archive, compressed using deflate
344 :``zip``: zip archive, compressed using deflate
345
345
346 The exact name of the destination archive or directory is given
346 The exact name of the destination archive or directory is given
347 using a format string; see :hg:`help export` for details.
347 using a format string; see :hg:`help export` for details.
348
348
349 Each member added to an archive file has a directory prefix
349 Each member added to an archive file has a directory prefix
350 prepended. Use -p/--prefix to specify a format string for the
350 prepended. Use -p/--prefix to specify a format string for the
351 prefix. The default is the basename of the archive, with suffixes
351 prefix. The default is the basename of the archive, with suffixes
352 removed.
352 removed.
353
353
354 Returns 0 on success.
354 Returns 0 on success.
355 '''
355 '''
356
356
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 if not ctx:
358 if not ctx:
359 raise util.Abort(_('no working directory: please specify a revision'))
359 raise util.Abort(_('no working directory: please specify a revision'))
360 node = ctx.node()
360 node = ctx.node()
361 dest = cmdutil.makefilename(repo, dest, node)
361 dest = cmdutil.makefilename(repo, dest, node)
362 if os.path.realpath(dest) == repo.root:
362 if os.path.realpath(dest) == repo.root:
363 raise util.Abort(_('repository root cannot be destination'))
363 raise util.Abort(_('repository root cannot be destination'))
364
364
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 prefix = opts.get('prefix')
366 prefix = opts.get('prefix')
367
367
368 if dest == '-':
368 if dest == '-':
369 if kind == 'files':
369 if kind == 'files':
370 raise util.Abort(_('cannot archive plain files to stdout'))
370 raise util.Abort(_('cannot archive plain files to stdout'))
371 dest = cmdutil.makefileobj(repo, dest)
371 dest = cmdutil.makefileobj(repo, dest)
372 if not prefix:
372 if not prefix:
373 prefix = os.path.basename(repo.root) + '-%h'
373 prefix = os.path.basename(repo.root) + '-%h'
374
374
375 prefix = cmdutil.makefilename(repo, prefix, node)
375 prefix = cmdutil.makefilename(repo, prefix, node)
376 matchfn = scmutil.match(ctx, [], opts)
376 matchfn = scmutil.match(ctx, [], opts)
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 matchfn, prefix, subrepos=opts.get('subrepos'))
378 matchfn, prefix, subrepos=opts.get('subrepos'))
379
379
380 @command('backout',
380 @command('backout',
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 ('', 'parent', '',
382 ('', 'parent', '',
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 _('[OPTION]... [-r] REV'))
386 _('[OPTION]... [-r] REV'))
387 def backout(ui, repo, node=None, rev=None, **opts):
387 def backout(ui, repo, node=None, rev=None, **opts):
388 '''reverse effect of earlier changeset
388 '''reverse effect of earlier changeset
389
389
390 Prepare a new changeset with the effect of REV undone in the
390 Prepare a new changeset with the effect of REV undone in the
391 current working directory.
391 current working directory.
392
392
393 If REV is the parent of the working directory, then this new changeset
393 If REV is the parent of the working directory, then this new changeset
394 is committed automatically. Otherwise, hg needs to merge the
394 is committed automatically. Otherwise, hg needs to merge the
395 changes and the merged result is left uncommitted.
395 changes and the merged result is left uncommitted.
396
396
397 .. note::
397 .. note::
398 backout cannot be used to fix either an unwanted or
398 backout cannot be used to fix either an unwanted or
399 incorrect merge.
399 incorrect merge.
400
400
401 .. container:: verbose
401 .. container:: verbose
402
402
403 By default, the pending changeset will have one parent,
403 By default, the pending changeset will have one parent,
404 maintaining a linear history. With --merge, the pending
404 maintaining a linear history. With --merge, the pending
405 changeset will instead have two parents: the old parent of the
405 changeset will instead have two parents: the old parent of the
406 working directory and a new child of REV that simply undoes REV.
406 working directory and a new child of REV that simply undoes REV.
407
407
408 Before version 1.7, the behavior without --merge was equivalent
408 Before version 1.7, the behavior without --merge was equivalent
409 to specifying --merge followed by :hg:`update --clean .` to
409 to specifying --merge followed by :hg:`update --clean .` to
410 cancel the merge and leave the child of REV as a head to be
410 cancel the merge and leave the child of REV as a head to be
411 merged separately.
411 merged separately.
412
412
413 See :hg:`help dates` for a list of formats valid for -d/--date.
413 See :hg:`help dates` for a list of formats valid for -d/--date.
414
414
415 Returns 0 on success.
415 Returns 0 on success.
416 '''
416 '''
417 if rev and node:
417 if rev and node:
418 raise util.Abort(_("please specify just one revision"))
418 raise util.Abort(_("please specify just one revision"))
419
419
420 if not rev:
420 if not rev:
421 rev = node
421 rev = node
422
422
423 if not rev:
423 if not rev:
424 raise util.Abort(_("please specify a revision to backout"))
424 raise util.Abort(_("please specify a revision to backout"))
425
425
426 date = opts.get('date')
426 date = opts.get('date')
427 if date:
427 if date:
428 opts['date'] = util.parsedate(date)
428 opts['date'] = util.parsedate(date)
429
429
430 cmdutil.bailifchanged(repo)
430 cmdutil.bailifchanged(repo)
431 node = scmutil.revsingle(repo, rev).node()
431 node = scmutil.revsingle(repo, rev).node()
432
432
433 op1, op2 = repo.dirstate.parents()
433 op1, op2 = repo.dirstate.parents()
434 a = repo.changelog.ancestor(op1, node)
434 a = repo.changelog.ancestor(op1, node)
435 if a != node:
435 if a != node:
436 raise util.Abort(_('cannot backout change on a different branch'))
436 raise util.Abort(_('cannot backout change on a different branch'))
437
437
438 p1, p2 = repo.changelog.parents(node)
438 p1, p2 = repo.changelog.parents(node)
439 if p1 == nullid:
439 if p1 == nullid:
440 raise util.Abort(_('cannot backout a change with no parents'))
440 raise util.Abort(_('cannot backout a change with no parents'))
441 if p2 != nullid:
441 if p2 != nullid:
442 if not opts.get('parent'):
442 if not opts.get('parent'):
443 raise util.Abort(_('cannot backout a merge changeset'))
443 raise util.Abort(_('cannot backout a merge changeset'))
444 p = repo.lookup(opts['parent'])
444 p = repo.lookup(opts['parent'])
445 if p not in (p1, p2):
445 if p not in (p1, p2):
446 raise util.Abort(_('%s is not a parent of %s') %
446 raise util.Abort(_('%s is not a parent of %s') %
447 (short(p), short(node)))
447 (short(p), short(node)))
448 parent = p
448 parent = p
449 else:
449 else:
450 if opts.get('parent'):
450 if opts.get('parent'):
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 parent = p1
452 parent = p1
453
453
454 # the backout should appear on the same branch
454 # the backout should appear on the same branch
455 wlock = repo.wlock()
455 wlock = repo.wlock()
456 try:
456 try:
457 branch = repo.dirstate.branch()
457 branch = repo.dirstate.branch()
458 hg.clean(repo, node, show_stats=False)
458 hg.clean(repo, node, show_stats=False)
459 repo.dirstate.setbranch(branch)
459 repo.dirstate.setbranch(branch)
460 revert_opts = opts.copy()
460 revert_opts = opts.copy()
461 revert_opts['date'] = None
461 revert_opts['date'] = None
462 revert_opts['all'] = True
462 revert_opts['all'] = True
463 revert_opts['rev'] = hex(parent)
463 revert_opts['rev'] = hex(parent)
464 revert_opts['no_backup'] = None
464 revert_opts['no_backup'] = None
465 revert(ui, repo, **revert_opts)
465 revert(ui, repo, **revert_opts)
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 return hg.update(repo, op1)
469 return hg.update(repo, op1)
470 finally:
470 finally:
471 ui.setconfig('ui', 'forcemerge', '')
471 ui.setconfig('ui', 'forcemerge', '')
472
472
473 commit_opts = opts.copy()
473 commit_opts = opts.copy()
474 commit_opts['addremove'] = False
474 commit_opts['addremove'] = False
475 if not commit_opts['message'] and not commit_opts['logfile']:
475 if not commit_opts['message'] and not commit_opts['logfile']:
476 # we don't translate commit messages
476 # we don't translate commit messages
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
478 commit_opts['force_editor'] = True
478 commit_opts['force_editor'] = True
479 commit(ui, repo, **commit_opts)
479 commit(ui, repo, **commit_opts)
480 def nice(node):
480 def nice(node):
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
482 ui.status(_('changeset %s backs out changeset %s\n') %
482 ui.status(_('changeset %s backs out changeset %s\n') %
483 (nice(repo.changelog.tip()), nice(node)))
483 (nice(repo.changelog.tip()), nice(node)))
484 if opts.get('merge') and op1 != node:
484 if opts.get('merge') and op1 != node:
485 hg.clean(repo, op1, show_stats=False)
485 hg.clean(repo, op1, show_stats=False)
486 ui.status(_('merging with changeset %s\n')
486 ui.status(_('merging with changeset %s\n')
487 % nice(repo.changelog.tip()))
487 % nice(repo.changelog.tip()))
488 try:
488 try:
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
490 return hg.merge(repo, hex(repo.changelog.tip()))
490 return hg.merge(repo, hex(repo.changelog.tip()))
491 finally:
491 finally:
492 ui.setconfig('ui', 'forcemerge', '')
492 ui.setconfig('ui', 'forcemerge', '')
493 finally:
493 finally:
494 wlock.release()
494 wlock.release()
495 return 0
495 return 0
496
496
497 @command('bisect',
497 @command('bisect',
498 [('r', 'reset', False, _('reset bisect state')),
498 [('r', 'reset', False, _('reset bisect state')),
499 ('g', 'good', False, _('mark changeset good')),
499 ('g', 'good', False, _('mark changeset good')),
500 ('b', 'bad', False, _('mark changeset bad')),
500 ('b', 'bad', False, _('mark changeset bad')),
501 ('s', 'skip', False, _('skip testing changeset')),
501 ('s', 'skip', False, _('skip testing changeset')),
502 ('e', 'extend', False, _('extend the bisect range')),
502 ('e', 'extend', False, _('extend the bisect range')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
504 ('U', 'noupdate', False, _('do not update to target'))],
504 ('U', 'noupdate', False, _('do not update to target'))],
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
506 def bisect(ui, repo, rev=None, extra=None, command=None,
506 def bisect(ui, repo, rev=None, extra=None, command=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
508 noupdate=None):
508 noupdate=None):
509 """subdivision search of changesets
509 """subdivision search of changesets
510
510
511 This command helps to find changesets which introduce problems. To
511 This command helps to find changesets which introduce problems. To
512 use, mark the earliest changeset you know exhibits the problem as
512 use, mark the earliest changeset you know exhibits the problem as
513 bad, then mark the latest changeset which is free from the problem
513 bad, then mark the latest changeset which is free from the problem
514 as good. Bisect will update your working directory to a revision
514 as good. Bisect will update your working directory to a revision
515 for testing (unless the -U/--noupdate option is specified). Once
515 for testing (unless the -U/--noupdate option is specified). Once
516 you have performed tests, mark the working directory as good or
516 you have performed tests, mark the working directory as good or
517 bad, and bisect will either update to another candidate changeset
517 bad, and bisect will either update to another candidate changeset
518 or announce that it has found the bad revision.
518 or announce that it has found the bad revision.
519
519
520 As a shortcut, you can also use the revision argument to mark a
520 As a shortcut, you can also use the revision argument to mark a
521 revision as good or bad without checking it out first.
521 revision as good or bad without checking it out first.
522
522
523 If you supply a command, it will be used for automatic bisection.
523 If you supply a command, it will be used for automatic bisection.
524 The environment variable HG_NODE will contain the ID of the
524 The environment variable HG_NODE will contain the ID of the
525 changeset being tested. The exit status of the command will be
525 changeset being tested. The exit status of the command will be
526 used to mark revisions as good or bad: status 0 means good, 125
526 used to mark revisions as good or bad: status 0 means good, 125
527 means to skip the revision, 127 (command not found) will abort the
527 means to skip the revision, 127 (command not found) will abort the
528 bisection, and any other non-zero exit status means the revision
528 bisection, and any other non-zero exit status means the revision
529 is bad.
529 is bad.
530
530
531 .. container:: verbose
531 .. container:: verbose
532
532
533 Some examples:
533 Some examples:
534
534
535 - start a bisection with known bad revision 12, and good revision 34::
535 - start a bisection with known bad revision 12, and good revision 34::
536
536
537 hg bisect --bad 34
537 hg bisect --bad 34
538 hg bisect --good 12
538 hg bisect --good 12
539
539
540 - advance the current bisection by marking current revision as good or
540 - advance the current bisection by marking current revision as good or
541 bad::
541 bad::
542
542
543 hg bisect --good
543 hg bisect --good
544 hg bisect --bad
544 hg bisect --bad
545
545
546 - mark the current revision, or a known revision, to be skipped (e.g. if
546 - mark the current revision, or a known revision, to be skipped (e.g. if
547 that revision is not usable because of another issue)::
547 that revision is not usable because of another issue)::
548
548
549 hg bisect --skip
549 hg bisect --skip
550 hg bisect --skip 23
550 hg bisect --skip 23
551
551
552 - forget the current bisection::
552 - forget the current bisection::
553
553
554 hg bisect --reset
554 hg bisect --reset
555
555
556 - use 'make && make tests' to automatically find the first broken
556 - use 'make && make tests' to automatically find the first broken
557 revision::
557 revision::
558
558
559 hg bisect --reset
559 hg bisect --reset
560 hg bisect --bad 34
560 hg bisect --bad 34
561 hg bisect --good 12
561 hg bisect --good 12
562 hg bisect --command 'make && make tests'
562 hg bisect --command 'make && make tests'
563
563
564 - see all changesets whose states are already known in the current
564 - see all changesets whose states are already known in the current
565 bisection::
565 bisection::
566
566
567 hg log -r "bisect(pruned)"
567 hg log -r "bisect(pruned)"
568
568
569 - see the changeset currently being bisected (especially useful
569 - see the changeset currently being bisected (especially useful
570 if running with -U/--noupdate)::
570 if running with -U/--noupdate)::
571
571
572 hg log -r "bisect(current)"
572 hg log -r "bisect(current)"
573
573
574 - see all changesets that took part in the current bisection::
574 - see all changesets that took part in the current bisection::
575
575
576 hg log -r "bisect(range)"
576 hg log -r "bisect(range)"
577
577
578 - with the graphlog extension, you can even get a nice graph::
578 - with the graphlog extension, you can even get a nice graph::
579
579
580 hg log --graph -r "bisect(range)"
580 hg log --graph -r "bisect(range)"
581
581
582 See :hg:`help revsets` for more about the `bisect()` keyword.
582 See :hg:`help revsets` for more about the `bisect()` keyword.
583
583
584 Returns 0 on success.
584 Returns 0 on success.
585 """
585 """
586 def extendbisectrange(nodes, good):
586 def extendbisectrange(nodes, good):
587 # bisect is incomplete when it ends on a merge node and
587 # bisect is incomplete when it ends on a merge node and
588 # one of the parent was not checked.
588 # one of the parent was not checked.
589 parents = repo[nodes[0]].parents()
589 parents = repo[nodes[0]].parents()
590 if len(parents) > 1:
590 if len(parents) > 1:
591 side = good and state['bad'] or state['good']
591 side = good and state['bad'] or state['good']
592 num = len(set(i.node() for i in parents) & set(side))
592 num = len(set(i.node() for i in parents) & set(side))
593 if num == 1:
593 if num == 1:
594 return parents[0].ancestor(parents[1])
594 return parents[0].ancestor(parents[1])
595 return None
595 return None
596
596
597 def print_result(nodes, good):
597 def print_result(nodes, good):
598 displayer = cmdutil.show_changeset(ui, repo, {})
598 displayer = cmdutil.show_changeset(ui, repo, {})
599 if len(nodes) == 1:
599 if len(nodes) == 1:
600 # narrowed it down to a single revision
600 # narrowed it down to a single revision
601 if good:
601 if good:
602 ui.write(_("The first good revision is:\n"))
602 ui.write(_("The first good revision is:\n"))
603 else:
603 else:
604 ui.write(_("The first bad revision is:\n"))
604 ui.write(_("The first bad revision is:\n"))
605 displayer.show(repo[nodes[0]])
605 displayer.show(repo[nodes[0]])
606 extendnode = extendbisectrange(nodes, good)
606 extendnode = extendbisectrange(nodes, good)
607 if extendnode is not None:
607 if extendnode is not None:
608 ui.write(_('Not all ancestors of this changeset have been'
608 ui.write(_('Not all ancestors of this changeset have been'
609 ' checked.\nUse bisect --extend to continue the '
609 ' checked.\nUse bisect --extend to continue the '
610 'bisection from\nthe common ancestor, %s.\n')
610 'bisection from\nthe common ancestor, %s.\n')
611 % extendnode)
611 % extendnode)
612 else:
612 else:
613 # multiple possible revisions
613 # multiple possible revisions
614 if good:
614 if good:
615 ui.write(_("Due to skipped revisions, the first "
615 ui.write(_("Due to skipped revisions, the first "
616 "good revision could be any of:\n"))
616 "good revision could be any of:\n"))
617 else:
617 else:
618 ui.write(_("Due to skipped revisions, the first "
618 ui.write(_("Due to skipped revisions, the first "
619 "bad revision could be any of:\n"))
619 "bad revision could be any of:\n"))
620 for n in nodes:
620 for n in nodes:
621 displayer.show(repo[n])
621 displayer.show(repo[n])
622 displayer.close()
622 displayer.close()
623
623
624 def check_state(state, interactive=True):
624 def check_state(state, interactive=True):
625 if not state['good'] or not state['bad']:
625 if not state['good'] or not state['bad']:
626 if (good or bad or skip or reset) and interactive:
626 if (good or bad or skip or reset) and interactive:
627 return
627 return
628 if not state['good']:
628 if not state['good']:
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
630 else:
630 else:
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
632 return True
632 return True
633
633
634 # backward compatibility
634 # backward compatibility
635 if rev in "good bad reset init".split():
635 if rev in "good bad reset init".split():
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
637 cmd, rev, extra = rev, extra, None
637 cmd, rev, extra = rev, extra, None
638 if cmd == "good":
638 if cmd == "good":
639 good = True
639 good = True
640 elif cmd == "bad":
640 elif cmd == "bad":
641 bad = True
641 bad = True
642 else:
642 else:
643 reset = True
643 reset = True
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
645 raise util.Abort(_('incompatible arguments'))
645 raise util.Abort(_('incompatible arguments'))
646
646
647 if reset:
647 if reset:
648 p = repo.join("bisect.state")
648 p = repo.join("bisect.state")
649 if os.path.exists(p):
649 if os.path.exists(p):
650 os.unlink(p)
650 os.unlink(p)
651 return
651 return
652
652
653 state = hbisect.load_state(repo)
653 state = hbisect.load_state(repo)
654
654
655 if command:
655 if command:
656 changesets = 1
656 changesets = 1
657 try:
657 try:
658 node = state['current'][0]
658 node = state['current'][0]
659 except LookupError:
659 except LookupError:
660 if noupdate:
660 if noupdate:
661 raise util.Abort(_('current bisect revision is unknown - '
661 raise util.Abort(_('current bisect revision is unknown - '
662 'start a new bisect to fix'))
662 'start a new bisect to fix'))
663 node, p2 = repo.dirstate.parents()
663 node, p2 = repo.dirstate.parents()
664 if p2 != nullid:
664 if p2 != nullid:
665 raise util.Abort(_('current bisect revision is a merge'))
665 raise util.Abort(_('current bisect revision is a merge'))
666 try:
666 try:
667 while changesets:
667 while changesets:
668 # update state
668 # update state
669 state['current'] = [node]
669 state['current'] = [node]
670 hbisect.save_state(repo, state)
670 hbisect.save_state(repo, state)
671 status = util.system(command,
671 status = util.system(command,
672 environ={'HG_NODE': hex(node)},
672 environ={'HG_NODE': hex(node)},
673 out=ui.fout)
673 out=ui.fout)
674 if status == 125:
674 if status == 125:
675 transition = "skip"
675 transition = "skip"
676 elif status == 0:
676 elif status == 0:
677 transition = "good"
677 transition = "good"
678 # status < 0 means process was killed
678 # status < 0 means process was killed
679 elif status == 127:
679 elif status == 127:
680 raise util.Abort(_("failed to execute %s") % command)
680 raise util.Abort(_("failed to execute %s") % command)
681 elif status < 0:
681 elif status < 0:
682 raise util.Abort(_("%s killed") % command)
682 raise util.Abort(_("%s killed") % command)
683 else:
683 else:
684 transition = "bad"
684 transition = "bad"
685 ctx = scmutil.revsingle(repo, rev, node)
685 ctx = scmutil.revsingle(repo, rev, node)
686 rev = None # clear for future iterations
686 rev = None # clear for future iterations
687 state[transition].append(ctx.node())
687 state[transition].append(ctx.node())
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
689 check_state(state, interactive=False)
689 check_state(state, interactive=False)
690 # bisect
690 # bisect
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
692 # update to next check
692 # update to next check
693 node = nodes[0]
693 node = nodes[0]
694 if not noupdate:
694 if not noupdate:
695 cmdutil.bailifchanged(repo)
695 cmdutil.bailifchanged(repo)
696 hg.clean(repo, node, show_stats=False)
696 hg.clean(repo, node, show_stats=False)
697 finally:
697 finally:
698 state['current'] = [node]
698 state['current'] = [node]
699 hbisect.save_state(repo, state)
699 hbisect.save_state(repo, state)
700 print_result(nodes, good)
700 print_result(nodes, good)
701 return
701 return
702
702
703 # update state
703 # update state
704
704
705 if rev:
705 if rev:
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
707 else:
707 else:
708 nodes = [repo.lookup('.')]
708 nodes = [repo.lookup('.')]
709
709
710 if good or bad or skip:
710 if good or bad or skip:
711 if good:
711 if good:
712 state['good'] += nodes
712 state['good'] += nodes
713 elif bad:
713 elif bad:
714 state['bad'] += nodes
714 state['bad'] += nodes
715 elif skip:
715 elif skip:
716 state['skip'] += nodes
716 state['skip'] += nodes
717 hbisect.save_state(repo, state)
717 hbisect.save_state(repo, state)
718
718
719 if not check_state(state):
719 if not check_state(state):
720 return
720 return
721
721
722 # actually bisect
722 # actually bisect
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
724 if extend:
724 if extend:
725 if not changesets:
725 if not changesets:
726 extendnode = extendbisectrange(nodes, good)
726 extendnode = extendbisectrange(nodes, good)
727 if extendnode is not None:
727 if extendnode is not None:
728 ui.write(_("Extending search to changeset %d:%s\n"
728 ui.write(_("Extending search to changeset %d:%s\n"
729 % (extendnode.rev(), extendnode)))
729 % (extendnode.rev(), extendnode)))
730 state['current'] = [extendnode.node()]
730 state['current'] = [extendnode.node()]
731 hbisect.save_state(repo, state)
731 hbisect.save_state(repo, state)
732 if noupdate:
732 if noupdate:
733 return
733 return
734 cmdutil.bailifchanged(repo)
734 cmdutil.bailifchanged(repo)
735 return hg.clean(repo, extendnode.node())
735 return hg.clean(repo, extendnode.node())
736 raise util.Abort(_("nothing to extend"))
736 raise util.Abort(_("nothing to extend"))
737
737
738 if changesets == 0:
738 if changesets == 0:
739 print_result(nodes, good)
739 print_result(nodes, good)
740 else:
740 else:
741 assert len(nodes) == 1 # only a single node can be tested next
741 assert len(nodes) == 1 # only a single node can be tested next
742 node = nodes[0]
742 node = nodes[0]
743 # compute the approximate number of remaining tests
743 # compute the approximate number of remaining tests
744 tests, size = 0, 2
744 tests, size = 0, 2
745 while size <= changesets:
745 while size <= changesets:
746 tests, size = tests + 1, size * 2
746 tests, size = tests + 1, size * 2
747 rev = repo.changelog.rev(node)
747 rev = repo.changelog.rev(node)
748 ui.write(_("Testing changeset %d:%s "
748 ui.write(_("Testing changeset %d:%s "
749 "(%d changesets remaining, ~%d tests)\n")
749 "(%d changesets remaining, ~%d tests)\n")
750 % (rev, short(node), changesets, tests))
750 % (rev, short(node), changesets, tests))
751 state['current'] = [node]
751 state['current'] = [node]
752 hbisect.save_state(repo, state)
752 hbisect.save_state(repo, state)
753 if not noupdate:
753 if not noupdate:
754 cmdutil.bailifchanged(repo)
754 cmdutil.bailifchanged(repo)
755 return hg.clean(repo, node)
755 return hg.clean(repo, node)
756
756
757 @command('bookmarks',
757 @command('bookmarks',
758 [('f', 'force', False, _('force')),
758 [('f', 'force', False, _('force')),
759 ('r', 'rev', '', _('revision'), _('REV')),
759 ('r', 'rev', '', _('revision'), _('REV')),
760 ('d', 'delete', False, _('delete a given bookmark')),
760 ('d', 'delete', False, _('delete a given bookmark')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
765 rename=None, inactive=False):
765 rename=None, inactive=False):
766 '''track a line of development with movable markers
766 '''track a line of development with movable markers
767
767
768 Bookmarks are pointers to certain commits that move when committing.
768 Bookmarks are pointers to certain commits that move when committing.
769 Bookmarks are local. They can be renamed, copied and deleted. It is
769 Bookmarks are local. They can be renamed, copied and deleted. It is
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
771 :hg:`update NAME` to update to a given bookmark.
771 :hg:`update NAME` to update to a given bookmark.
772
772
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
774 directory's parent revision with the given name. If you specify
774 directory's parent revision with the given name. If you specify
775 a revision using -r REV (where REV may be an existing bookmark),
775 a revision using -r REV (where REV may be an existing bookmark),
776 the bookmark is assigned to that revision.
776 the bookmark is assigned to that revision.
777
777
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
779 push` and :hg:`help pull`). This requires both the local and remote
779 push` and :hg:`help pull`). This requires both the local and remote
780 repositories to support bookmarks. For versions prior to 1.8, this means
780 repositories to support bookmarks. For versions prior to 1.8, this means
781 the bookmarks extension must be enabled.
781 the bookmarks extension must be enabled.
782
782
783 With -i/--inactive, the new bookmark will not be made the active
783 With -i/--inactive, the new bookmark will not be made the active
784 bookmark. If -r/--rev is given, the new bookmark will not be made
784 bookmark. If -r/--rev is given, the new bookmark will not be made
785 active even if -i/--inactive is not given. If no NAME is given, the
785 active even if -i/--inactive is not given. If no NAME is given, the
786 current active bookmark will be marked inactive.
786 current active bookmark will be marked inactive.
787 '''
787 '''
788 hexfn = ui.debugflag and hex or short
788 hexfn = ui.debugflag and hex or short
789 marks = repo._bookmarks
789 marks = repo._bookmarks
790 cur = repo.changectx('.').node()
790 cur = repo.changectx('.').node()
791
791
792 def checkformat(mark):
792 def checkformat(mark):
793 if "\n" in mark:
794 raise util.Abort(_("bookmark name cannot contain newlines"))
795 mark = mark.strip()
793 mark = mark.strip()
796 if not mark:
794 if not mark:
797 raise util.Abort(_("bookmark names cannot consist entirely of "
795 raise util.Abort(_("bookmark names cannot consist entirely of "
798 "whitespace"))
796 "whitespace"))
799 return mark
797 return mark
800
798
801 def checkconflict(repo, mark, force=False):
799 def checkconflict(repo, mark, force=False):
802 if mark in marks and not force:
800 if mark in marks and not force:
803 raise util.Abort(_("bookmark '%s' already exists "
801 raise util.Abort(_("bookmark '%s' already exists "
804 "(use -f to force)") % mark)
802 "(use -f to force)") % mark)
805 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
803 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
806 and not force):
804 and not force):
807 raise util.Abort(
805 raise util.Abort(
808 _("a bookmark cannot have the name of an existing branch"))
806 _("a bookmark cannot have the name of an existing branch"))
809
807
810 if delete and rename:
808 if delete and rename:
811 raise util.Abort(_("--delete and --rename are incompatible"))
809 raise util.Abort(_("--delete and --rename are incompatible"))
812 if delete and rev:
810 if delete and rev:
813 raise util.Abort(_("--rev is incompatible with --delete"))
811 raise util.Abort(_("--rev is incompatible with --delete"))
814 if rename and rev:
812 if rename and rev:
815 raise util.Abort(_("--rev is incompatible with --rename"))
813 raise util.Abort(_("--rev is incompatible with --rename"))
816 if mark is None and (delete or rev):
814 if mark is None and (delete or rev):
817 raise util.Abort(_("bookmark name required"))
815 raise util.Abort(_("bookmark name required"))
818
816
819 if delete:
817 if delete:
820 if mark not in marks:
818 if mark not in marks:
821 raise util.Abort(_("bookmark '%s' does not exist") % mark)
819 raise util.Abort(_("bookmark '%s' does not exist") % mark)
822 if mark == repo._bookmarkcurrent:
820 if mark == repo._bookmarkcurrent:
823 bookmarks.setcurrent(repo, None)
821 bookmarks.setcurrent(repo, None)
824 del marks[mark]
822 del marks[mark]
825 bookmarks.write(repo)
823 bookmarks.write(repo)
826
824
827 elif rename:
825 elif rename:
828 if mark is None:
826 if mark is None:
829 raise util.Abort(_("new bookmark name required"))
827 raise util.Abort(_("new bookmark name required"))
830 mark = checkformat(mark)
828 mark = checkformat(mark)
831 if rename not in marks:
829 if rename not in marks:
832 raise util.Abort(_("bookmark '%s' does not exist") % rename)
830 raise util.Abort(_("bookmark '%s' does not exist") % rename)
833 checkconflict(repo, mark, force)
831 checkconflict(repo, mark, force)
834 marks[mark] = marks[rename]
832 marks[mark] = marks[rename]
835 if repo._bookmarkcurrent == rename and not inactive:
833 if repo._bookmarkcurrent == rename and not inactive:
836 bookmarks.setcurrent(repo, mark)
834 bookmarks.setcurrent(repo, mark)
837 del marks[rename]
835 del marks[rename]
838 bookmarks.write(repo)
836 bookmarks.write(repo)
839
837
840 elif mark is not None:
838 elif mark is not None:
841 mark = checkformat(mark)
839 mark = checkformat(mark)
842 if inactive and mark == repo._bookmarkcurrent:
840 if inactive and mark == repo._bookmarkcurrent:
843 bookmarks.setcurrent(repo, None)
841 bookmarks.setcurrent(repo, None)
844 return
842 return
845 checkconflict(repo, mark, force)
843 checkconflict(repo, mark, force)
846 if rev:
844 if rev:
847 marks[mark] = scmutil.revsingle(repo, rev).node()
845 marks[mark] = scmutil.revsingle(repo, rev).node()
848 else:
846 else:
849 marks[mark] = cur
847 marks[mark] = cur
850 if not inactive and cur == marks[mark]:
848 if not inactive and cur == marks[mark]:
851 bookmarks.setcurrent(repo, mark)
849 bookmarks.setcurrent(repo, mark)
852 bookmarks.write(repo)
850 bookmarks.write(repo)
853
851
854 else: # show bookmarks
852 else: # show bookmarks
855 if len(marks) == 0:
853 if len(marks) == 0:
856 ui.status(_("no bookmarks set\n"))
854 ui.status(_("no bookmarks set\n"))
857 elif inactive:
855 elif inactive:
858 if not repo._bookmarkcurrent:
856 if not repo._bookmarkcurrent:
859 ui.status(_("no active bookmark\n"))
857 ui.status(_("no active bookmark\n"))
860 else:
858 else:
861 bookmarks.setcurrent(repo, None)
859 bookmarks.setcurrent(repo, None)
862 else:
860 else:
863 for bmark, n in sorted(marks.iteritems()):
861 for bmark, n in sorted(marks.iteritems()):
864 current = repo._bookmarkcurrent
862 current = repo._bookmarkcurrent
865 if bmark == current and n == cur:
863 if bmark == current and n == cur:
866 prefix, label = '*', 'bookmarks.current'
864 prefix, label = '*', 'bookmarks.current'
867 else:
865 else:
868 prefix, label = ' ', ''
866 prefix, label = ' ', ''
869
867
870 if ui.quiet:
868 if ui.quiet:
871 ui.write("%s\n" % bmark, label=label)
869 ui.write("%s\n" % bmark, label=label)
872 else:
870 else:
873 ui.write(" %s %-25s %d:%s\n" % (
871 ui.write(" %s %-25s %d:%s\n" % (
874 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
872 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
875 label=label)
873 label=label)
876
874
877 @command('branch',
875 @command('branch',
878 [('f', 'force', None,
876 [('f', 'force', None,
879 _('set branch name even if it shadows an existing branch')),
877 _('set branch name even if it shadows an existing branch')),
880 ('C', 'clean', None, _('reset branch name to parent branch name'))],
878 ('C', 'clean', None, _('reset branch name to parent branch name'))],
881 _('[-fC] [NAME]'))
879 _('[-fC] [NAME]'))
882 def branch(ui, repo, label=None, **opts):
880 def branch(ui, repo, label=None, **opts):
883 """set or show the current branch name
881 """set or show the current branch name
884
882
885 .. note::
883 .. note::
886 Branch names are permanent and global. Use :hg:`bookmark` to create a
884 Branch names are permanent and global. Use :hg:`bookmark` to create a
887 light-weight bookmark instead. See :hg:`help glossary` for more
885 light-weight bookmark instead. See :hg:`help glossary` for more
888 information about named branches and bookmarks.
886 information about named branches and bookmarks.
889
887
890 With no argument, show the current branch name. With one argument,
888 With no argument, show the current branch name. With one argument,
891 set the working directory branch name (the branch will not exist
889 set the working directory branch name (the branch will not exist
892 in the repository until the next commit). Standard practice
890 in the repository until the next commit). Standard practice
893 recommends that primary development take place on the 'default'
891 recommends that primary development take place on the 'default'
894 branch.
892 branch.
895
893
896 Unless -f/--force is specified, branch will not let you set a
894 Unless -f/--force is specified, branch will not let you set a
897 branch name that already exists, even if it's inactive.
895 branch name that already exists, even if it's inactive.
898
896
899 Use -C/--clean to reset the working directory branch to that of
897 Use -C/--clean to reset the working directory branch to that of
900 the parent of the working directory, negating a previous branch
898 the parent of the working directory, negating a previous branch
901 change.
899 change.
902
900
903 Use the command :hg:`update` to switch to an existing branch. Use
901 Use the command :hg:`update` to switch to an existing branch. Use
904 :hg:`commit --close-branch` to mark this branch as closed.
902 :hg:`commit --close-branch` to mark this branch as closed.
905
903
906 Returns 0 on success.
904 Returns 0 on success.
907 """
905 """
908 if not opts.get('clean') and not label:
906 if not opts.get('clean') and not label:
909 ui.write("%s\n" % repo.dirstate.branch())
907 ui.write("%s\n" % repo.dirstate.branch())
910 return
908 return
911
909
912 wlock = repo.wlock()
910 wlock = repo.wlock()
913 try:
911 try:
914 if opts.get('clean'):
912 if opts.get('clean'):
915 label = repo[None].p1().branch()
913 label = repo[None].p1().branch()
916 repo.dirstate.setbranch(label)
914 repo.dirstate.setbranch(label)
917 ui.status(_('reset working directory to branch %s\n') % label)
915 ui.status(_('reset working directory to branch %s\n') % label)
918 elif label:
916 elif label:
919 if not opts.get('force') and label in repo.branchmap():
917 if not opts.get('force') and label in repo.branchmap():
920 if label not in [p.branch() for p in repo.parents()]:
918 if label not in [p.branch() for p in repo.parents()]:
921 raise util.Abort(_('a branch of the same name already'
919 raise util.Abort(_('a branch of the same name already'
922 ' exists'),
920 ' exists'),
923 # i18n: "it" refers to an existing branch
921 # i18n: "it" refers to an existing branch
924 hint=_("use 'hg update' to switch to it"))
922 hint=_("use 'hg update' to switch to it"))
925 repo.dirstate.setbranch(label)
923 repo.dirstate.setbranch(label)
926 ui.status(_('marked working directory as branch %s\n') % label)
924 ui.status(_('marked working directory as branch %s\n') % label)
927 ui.status(_('(branches are permanent and global, '
925 ui.status(_('(branches are permanent and global, '
928 'did you want a bookmark?)\n'))
926 'did you want a bookmark?)\n'))
929 finally:
927 finally:
930 wlock.release()
928 wlock.release()
931
929
932 @command('branches',
930 @command('branches',
933 [('a', 'active', False, _('show only branches that have unmerged heads')),
931 [('a', 'active', False, _('show only branches that have unmerged heads')),
934 ('c', 'closed', False, _('show normal and closed branches'))],
932 ('c', 'closed', False, _('show normal and closed branches'))],
935 _('[-ac]'))
933 _('[-ac]'))
936 def branches(ui, repo, active=False, closed=False):
934 def branches(ui, repo, active=False, closed=False):
937 """list repository named branches
935 """list repository named branches
938
936
939 List the repository's named branches, indicating which ones are
937 List the repository's named branches, indicating which ones are
940 inactive. If -c/--closed is specified, also list branches which have
938 inactive. If -c/--closed is specified, also list branches which have
941 been marked closed (see :hg:`commit --close-branch`).
939 been marked closed (see :hg:`commit --close-branch`).
942
940
943 If -a/--active is specified, only show active branches. A branch
941 If -a/--active is specified, only show active branches. A branch
944 is considered active if it contains repository heads.
942 is considered active if it contains repository heads.
945
943
946 Use the command :hg:`update` to switch to an existing branch.
944 Use the command :hg:`update` to switch to an existing branch.
947
945
948 Returns 0.
946 Returns 0.
949 """
947 """
950
948
951 hexfunc = ui.debugflag and hex or short
949 hexfunc = ui.debugflag and hex or short
952
950
953 activebranches = set([repo[n].branch() for n in repo.heads()])
951 activebranches = set([repo[n].branch() for n in repo.heads()])
954 branches = []
952 branches = []
955 for tag, heads in repo.branchmap().iteritems():
953 for tag, heads in repo.branchmap().iteritems():
956 for h in reversed(heads):
954 for h in reversed(heads):
957 ctx = repo[h]
955 ctx = repo[h]
958 isopen = not ctx.closesbranch()
956 isopen = not ctx.closesbranch()
959 if isopen:
957 if isopen:
960 tip = ctx
958 tip = ctx
961 break
959 break
962 else:
960 else:
963 tip = repo[heads[-1]]
961 tip = repo[heads[-1]]
964 isactive = tag in activebranches and isopen
962 isactive = tag in activebranches and isopen
965 branches.append((tip, isactive, isopen))
963 branches.append((tip, isactive, isopen))
966 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
964 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
967 reverse=True)
965 reverse=True)
968
966
969 for ctx, isactive, isopen in branches:
967 for ctx, isactive, isopen in branches:
970 if (not active) or isactive:
968 if (not active) or isactive:
971 if isactive:
969 if isactive:
972 label = 'branches.active'
970 label = 'branches.active'
973 notice = ''
971 notice = ''
974 elif not isopen:
972 elif not isopen:
975 if not closed:
973 if not closed:
976 continue
974 continue
977 label = 'branches.closed'
975 label = 'branches.closed'
978 notice = _(' (closed)')
976 notice = _(' (closed)')
979 else:
977 else:
980 label = 'branches.inactive'
978 label = 'branches.inactive'
981 notice = _(' (inactive)')
979 notice = _(' (inactive)')
982 if ctx.branch() == repo.dirstate.branch():
980 if ctx.branch() == repo.dirstate.branch():
983 label = 'branches.current'
981 label = 'branches.current'
984 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
982 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
985 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
983 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
986 'log.changeset changeset.%s' % ctx.phasestr())
984 'log.changeset changeset.%s' % ctx.phasestr())
987 tag = ui.label(ctx.branch(), label)
985 tag = ui.label(ctx.branch(), label)
988 if ui.quiet:
986 if ui.quiet:
989 ui.write("%s\n" % tag)
987 ui.write("%s\n" % tag)
990 else:
988 else:
991 ui.write("%s %s%s\n" % (tag, rev, notice))
989 ui.write("%s %s%s\n" % (tag, rev, notice))
992
990
993 @command('bundle',
991 @command('bundle',
994 [('f', 'force', None, _('run even when the destination is unrelated')),
992 [('f', 'force', None, _('run even when the destination is unrelated')),
995 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
993 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
996 _('REV')),
994 _('REV')),
997 ('b', 'branch', [], _('a specific branch you would like to bundle'),
995 ('b', 'branch', [], _('a specific branch you would like to bundle'),
998 _('BRANCH')),
996 _('BRANCH')),
999 ('', 'base', [],
997 ('', 'base', [],
1000 _('a base changeset assumed to be available at the destination'),
998 _('a base changeset assumed to be available at the destination'),
1001 _('REV')),
999 _('REV')),
1002 ('a', 'all', None, _('bundle all changesets in the repository')),
1000 ('a', 'all', None, _('bundle all changesets in the repository')),
1003 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1001 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1004 ] + remoteopts,
1002 ] + remoteopts,
1005 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1003 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1006 def bundle(ui, repo, fname, dest=None, **opts):
1004 def bundle(ui, repo, fname, dest=None, **opts):
1007 """create a changegroup file
1005 """create a changegroup file
1008
1006
1009 Generate a compressed changegroup file collecting changesets not
1007 Generate a compressed changegroup file collecting changesets not
1010 known to be in another repository.
1008 known to be in another repository.
1011
1009
1012 If you omit the destination repository, then hg assumes the
1010 If you omit the destination repository, then hg assumes the
1013 destination will have all the nodes you specify with --base
1011 destination will have all the nodes you specify with --base
1014 parameters. To create a bundle containing all changesets, use
1012 parameters. To create a bundle containing all changesets, use
1015 -a/--all (or --base null).
1013 -a/--all (or --base null).
1016
1014
1017 You can change compression method with the -t/--type option.
1015 You can change compression method with the -t/--type option.
1018 The available compression methods are: none, bzip2, and
1016 The available compression methods are: none, bzip2, and
1019 gzip (by default, bundles are compressed using bzip2).
1017 gzip (by default, bundles are compressed using bzip2).
1020
1018
1021 The bundle file can then be transferred using conventional means
1019 The bundle file can then be transferred using conventional means
1022 and applied to another repository with the unbundle or pull
1020 and applied to another repository with the unbundle or pull
1023 command. This is useful when direct push and pull are not
1021 command. This is useful when direct push and pull are not
1024 available or when exporting an entire repository is undesirable.
1022 available or when exporting an entire repository is undesirable.
1025
1023
1026 Applying bundles preserves all changeset contents including
1024 Applying bundles preserves all changeset contents including
1027 permissions, copy/rename information, and revision history.
1025 permissions, copy/rename information, and revision history.
1028
1026
1029 Returns 0 on success, 1 if no changes found.
1027 Returns 0 on success, 1 if no changes found.
1030 """
1028 """
1031 revs = None
1029 revs = None
1032 if 'rev' in opts:
1030 if 'rev' in opts:
1033 revs = scmutil.revrange(repo, opts['rev'])
1031 revs = scmutil.revrange(repo, opts['rev'])
1034
1032
1035 bundletype = opts.get('type', 'bzip2').lower()
1033 bundletype = opts.get('type', 'bzip2').lower()
1036 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1034 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1037 bundletype = btypes.get(bundletype)
1035 bundletype = btypes.get(bundletype)
1038 if bundletype not in changegroup.bundletypes:
1036 if bundletype not in changegroup.bundletypes:
1039 raise util.Abort(_('unknown bundle type specified with --type'))
1037 raise util.Abort(_('unknown bundle type specified with --type'))
1040
1038
1041 if opts.get('all'):
1039 if opts.get('all'):
1042 base = ['null']
1040 base = ['null']
1043 else:
1041 else:
1044 base = scmutil.revrange(repo, opts.get('base'))
1042 base = scmutil.revrange(repo, opts.get('base'))
1045 if base:
1043 if base:
1046 if dest:
1044 if dest:
1047 raise util.Abort(_("--base is incompatible with specifying "
1045 raise util.Abort(_("--base is incompatible with specifying "
1048 "a destination"))
1046 "a destination"))
1049 common = [repo.lookup(rev) for rev in base]
1047 common = [repo.lookup(rev) for rev in base]
1050 heads = revs and map(repo.lookup, revs) or revs
1048 heads = revs and map(repo.lookup, revs) or revs
1051 cg = repo.getbundle('bundle', heads=heads, common=common)
1049 cg = repo.getbundle('bundle', heads=heads, common=common)
1052 outgoing = None
1050 outgoing = None
1053 else:
1051 else:
1054 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1052 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1055 dest, branches = hg.parseurl(dest, opts.get('branch'))
1053 dest, branches = hg.parseurl(dest, opts.get('branch'))
1056 other = hg.peer(repo, opts, dest)
1054 other = hg.peer(repo, opts, dest)
1057 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1055 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1058 heads = revs and map(repo.lookup, revs) or revs
1056 heads = revs and map(repo.lookup, revs) or revs
1059 outgoing = discovery.findcommonoutgoing(repo, other,
1057 outgoing = discovery.findcommonoutgoing(repo, other,
1060 onlyheads=heads,
1058 onlyheads=heads,
1061 force=opts.get('force'),
1059 force=opts.get('force'),
1062 portable=True)
1060 portable=True)
1063 cg = repo.getlocalbundle('bundle', outgoing)
1061 cg = repo.getlocalbundle('bundle', outgoing)
1064 if not cg:
1062 if not cg:
1065 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1063 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1066 return 1
1064 return 1
1067
1065
1068 changegroup.writebundle(cg, fname, bundletype)
1066 changegroup.writebundle(cg, fname, bundletype)
1069
1067
1070 @command('cat',
1068 @command('cat',
1071 [('o', 'output', '',
1069 [('o', 'output', '',
1072 _('print output to file with formatted name'), _('FORMAT')),
1070 _('print output to file with formatted name'), _('FORMAT')),
1073 ('r', 'rev', '', _('print the given revision'), _('REV')),
1071 ('r', 'rev', '', _('print the given revision'), _('REV')),
1074 ('', 'decode', None, _('apply any matching decode filter')),
1072 ('', 'decode', None, _('apply any matching decode filter')),
1075 ] + walkopts,
1073 ] + walkopts,
1076 _('[OPTION]... FILE...'))
1074 _('[OPTION]... FILE...'))
1077 def cat(ui, repo, file1, *pats, **opts):
1075 def cat(ui, repo, file1, *pats, **opts):
1078 """output the current or given revision of files
1076 """output the current or given revision of files
1079
1077
1080 Print the specified files as they were at the given revision. If
1078 Print the specified files as they were at the given revision. If
1081 no revision is given, the parent of the working directory is used,
1079 no revision is given, the parent of the working directory is used,
1082 or tip if no revision is checked out.
1080 or tip if no revision is checked out.
1083
1081
1084 Output may be to a file, in which case the name of the file is
1082 Output may be to a file, in which case the name of the file is
1085 given using a format string. The formatting rules are the same as
1083 given using a format string. The formatting rules are the same as
1086 for the export command, with the following additions:
1084 for the export command, with the following additions:
1087
1085
1088 :``%s``: basename of file being printed
1086 :``%s``: basename of file being printed
1089 :``%d``: dirname of file being printed, or '.' if in repository root
1087 :``%d``: dirname of file being printed, or '.' if in repository root
1090 :``%p``: root-relative path name of file being printed
1088 :``%p``: root-relative path name of file being printed
1091
1089
1092 Returns 0 on success.
1090 Returns 0 on success.
1093 """
1091 """
1094 ctx = scmutil.revsingle(repo, opts.get('rev'))
1092 ctx = scmutil.revsingle(repo, opts.get('rev'))
1095 err = 1
1093 err = 1
1096 m = scmutil.match(ctx, (file1,) + pats, opts)
1094 m = scmutil.match(ctx, (file1,) + pats, opts)
1097 for abs in ctx.walk(m):
1095 for abs in ctx.walk(m):
1098 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1096 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1099 pathname=abs)
1097 pathname=abs)
1100 data = ctx[abs].data()
1098 data = ctx[abs].data()
1101 if opts.get('decode'):
1099 if opts.get('decode'):
1102 data = repo.wwritedata(abs, data)
1100 data = repo.wwritedata(abs, data)
1103 fp.write(data)
1101 fp.write(data)
1104 fp.close()
1102 fp.close()
1105 err = 0
1103 err = 0
1106 return err
1104 return err
1107
1105
1108 @command('^clone',
1106 @command('^clone',
1109 [('U', 'noupdate', None,
1107 [('U', 'noupdate', None,
1110 _('the clone will include an empty working copy (only a repository)')),
1108 _('the clone will include an empty working copy (only a repository)')),
1111 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1109 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1112 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1110 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1113 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1111 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1114 ('', 'pull', None, _('use pull protocol to copy metadata')),
1112 ('', 'pull', None, _('use pull protocol to copy metadata')),
1115 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1113 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1116 ] + remoteopts,
1114 ] + remoteopts,
1117 _('[OPTION]... SOURCE [DEST]'))
1115 _('[OPTION]... SOURCE [DEST]'))
1118 def clone(ui, source, dest=None, **opts):
1116 def clone(ui, source, dest=None, **opts):
1119 """make a copy of an existing repository
1117 """make a copy of an existing repository
1120
1118
1121 Create a copy of an existing repository in a new directory.
1119 Create a copy of an existing repository in a new directory.
1122
1120
1123 If no destination directory name is specified, it defaults to the
1121 If no destination directory name is specified, it defaults to the
1124 basename of the source.
1122 basename of the source.
1125
1123
1126 The location of the source is added to the new repository's
1124 The location of the source is added to the new repository's
1127 ``.hg/hgrc`` file, as the default to be used for future pulls.
1125 ``.hg/hgrc`` file, as the default to be used for future pulls.
1128
1126
1129 Only local paths and ``ssh://`` URLs are supported as
1127 Only local paths and ``ssh://`` URLs are supported as
1130 destinations. For ``ssh://`` destinations, no working directory or
1128 destinations. For ``ssh://`` destinations, no working directory or
1131 ``.hg/hgrc`` will be created on the remote side.
1129 ``.hg/hgrc`` will be created on the remote side.
1132
1130
1133 To pull only a subset of changesets, specify one or more revisions
1131 To pull only a subset of changesets, specify one or more revisions
1134 identifiers with -r/--rev or branches with -b/--branch. The
1132 identifiers with -r/--rev or branches with -b/--branch. The
1135 resulting clone will contain only the specified changesets and
1133 resulting clone will contain only the specified changesets and
1136 their ancestors. These options (or 'clone src#rev dest') imply
1134 their ancestors. These options (or 'clone src#rev dest') imply
1137 --pull, even for local source repositories. Note that specifying a
1135 --pull, even for local source repositories. Note that specifying a
1138 tag will include the tagged changeset but not the changeset
1136 tag will include the tagged changeset but not the changeset
1139 containing the tag.
1137 containing the tag.
1140
1138
1141 To check out a particular version, use -u/--update, or
1139 To check out a particular version, use -u/--update, or
1142 -U/--noupdate to create a clone with no working directory.
1140 -U/--noupdate to create a clone with no working directory.
1143
1141
1144 .. container:: verbose
1142 .. container:: verbose
1145
1143
1146 For efficiency, hardlinks are used for cloning whenever the
1144 For efficiency, hardlinks are used for cloning whenever the
1147 source and destination are on the same filesystem (note this
1145 source and destination are on the same filesystem (note this
1148 applies only to the repository data, not to the working
1146 applies only to the repository data, not to the working
1149 directory). Some filesystems, such as AFS, implement hardlinking
1147 directory). Some filesystems, such as AFS, implement hardlinking
1150 incorrectly, but do not report errors. In these cases, use the
1148 incorrectly, but do not report errors. In these cases, use the
1151 --pull option to avoid hardlinking.
1149 --pull option to avoid hardlinking.
1152
1150
1153 In some cases, you can clone repositories and the working
1151 In some cases, you can clone repositories and the working
1154 directory using full hardlinks with ::
1152 directory using full hardlinks with ::
1155
1153
1156 $ cp -al REPO REPOCLONE
1154 $ cp -al REPO REPOCLONE
1157
1155
1158 This is the fastest way to clone, but it is not always safe. The
1156 This is the fastest way to clone, but it is not always safe. The
1159 operation is not atomic (making sure REPO is not modified during
1157 operation is not atomic (making sure REPO is not modified during
1160 the operation is up to you) and you have to make sure your
1158 the operation is up to you) and you have to make sure your
1161 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1159 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1162 so). Also, this is not compatible with certain extensions that
1160 so). Also, this is not compatible with certain extensions that
1163 place their metadata under the .hg directory, such as mq.
1161 place their metadata under the .hg directory, such as mq.
1164
1162
1165 Mercurial will update the working directory to the first applicable
1163 Mercurial will update the working directory to the first applicable
1166 revision from this list:
1164 revision from this list:
1167
1165
1168 a) null if -U or the source repository has no changesets
1166 a) null if -U or the source repository has no changesets
1169 b) if -u . and the source repository is local, the first parent of
1167 b) if -u . and the source repository is local, the first parent of
1170 the source repository's working directory
1168 the source repository's working directory
1171 c) the changeset specified with -u (if a branch name, this means the
1169 c) the changeset specified with -u (if a branch name, this means the
1172 latest head of that branch)
1170 latest head of that branch)
1173 d) the changeset specified with -r
1171 d) the changeset specified with -r
1174 e) the tipmost head specified with -b
1172 e) the tipmost head specified with -b
1175 f) the tipmost head specified with the url#branch source syntax
1173 f) the tipmost head specified with the url#branch source syntax
1176 g) the tipmost head of the default branch
1174 g) the tipmost head of the default branch
1177 h) tip
1175 h) tip
1178
1176
1179 Examples:
1177 Examples:
1180
1178
1181 - clone a remote repository to a new directory named hg/::
1179 - clone a remote repository to a new directory named hg/::
1182
1180
1183 hg clone http://selenic.com/hg
1181 hg clone http://selenic.com/hg
1184
1182
1185 - create a lightweight local clone::
1183 - create a lightweight local clone::
1186
1184
1187 hg clone project/ project-feature/
1185 hg clone project/ project-feature/
1188
1186
1189 - clone from an absolute path on an ssh server (note double-slash)::
1187 - clone from an absolute path on an ssh server (note double-slash)::
1190
1188
1191 hg clone ssh://user@server//home/projects/alpha/
1189 hg clone ssh://user@server//home/projects/alpha/
1192
1190
1193 - do a high-speed clone over a LAN while checking out a
1191 - do a high-speed clone over a LAN while checking out a
1194 specified version::
1192 specified version::
1195
1193
1196 hg clone --uncompressed http://server/repo -u 1.5
1194 hg clone --uncompressed http://server/repo -u 1.5
1197
1195
1198 - create a repository without changesets after a particular revision::
1196 - create a repository without changesets after a particular revision::
1199
1197
1200 hg clone -r 04e544 experimental/ good/
1198 hg clone -r 04e544 experimental/ good/
1201
1199
1202 - clone (and track) a particular named branch::
1200 - clone (and track) a particular named branch::
1203
1201
1204 hg clone http://selenic.com/hg#stable
1202 hg clone http://selenic.com/hg#stable
1205
1203
1206 See :hg:`help urls` for details on specifying URLs.
1204 See :hg:`help urls` for details on specifying URLs.
1207
1205
1208 Returns 0 on success.
1206 Returns 0 on success.
1209 """
1207 """
1210 if opts.get('noupdate') and opts.get('updaterev'):
1208 if opts.get('noupdate') and opts.get('updaterev'):
1211 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1209 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1212
1210
1213 r = hg.clone(ui, opts, source, dest,
1211 r = hg.clone(ui, opts, source, dest,
1214 pull=opts.get('pull'),
1212 pull=opts.get('pull'),
1215 stream=opts.get('uncompressed'),
1213 stream=opts.get('uncompressed'),
1216 rev=opts.get('rev'),
1214 rev=opts.get('rev'),
1217 update=opts.get('updaterev') or not opts.get('noupdate'),
1215 update=opts.get('updaterev') or not opts.get('noupdate'),
1218 branch=opts.get('branch'))
1216 branch=opts.get('branch'))
1219
1217
1220 return r is None
1218 return r is None
1221
1219
1222 @command('^commit|ci',
1220 @command('^commit|ci',
1223 [('A', 'addremove', None,
1221 [('A', 'addremove', None,
1224 _('mark new/missing files as added/removed before committing')),
1222 _('mark new/missing files as added/removed before committing')),
1225 ('', 'close-branch', None,
1223 ('', 'close-branch', None,
1226 _('mark a branch as closed, hiding it from the branch list')),
1224 _('mark a branch as closed, hiding it from the branch list')),
1227 ('', 'amend', None, _('amend the parent of the working dir')),
1225 ('', 'amend', None, _('amend the parent of the working dir')),
1228 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1226 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1229 _('[OPTION]... [FILE]...'))
1227 _('[OPTION]... [FILE]...'))
1230 def commit(ui, repo, *pats, **opts):
1228 def commit(ui, repo, *pats, **opts):
1231 """commit the specified files or all outstanding changes
1229 """commit the specified files or all outstanding changes
1232
1230
1233 Commit changes to the given files into the repository. Unlike a
1231 Commit changes to the given files into the repository. Unlike a
1234 centralized SCM, this operation is a local operation. See
1232 centralized SCM, this operation is a local operation. See
1235 :hg:`push` for a way to actively distribute your changes.
1233 :hg:`push` for a way to actively distribute your changes.
1236
1234
1237 If a list of files is omitted, all changes reported by :hg:`status`
1235 If a list of files is omitted, all changes reported by :hg:`status`
1238 will be committed.
1236 will be committed.
1239
1237
1240 If you are committing the result of a merge, do not provide any
1238 If you are committing the result of a merge, do not provide any
1241 filenames or -I/-X filters.
1239 filenames or -I/-X filters.
1242
1240
1243 If no commit message is specified, Mercurial starts your
1241 If no commit message is specified, Mercurial starts your
1244 configured editor where you can enter a message. In case your
1242 configured editor where you can enter a message. In case your
1245 commit fails, you will find a backup of your message in
1243 commit fails, you will find a backup of your message in
1246 ``.hg/last-message.txt``.
1244 ``.hg/last-message.txt``.
1247
1245
1248 The --amend flag can be used to amend the parent of the
1246 The --amend flag can be used to amend the parent of the
1249 working directory with a new commit that contains the changes
1247 working directory with a new commit that contains the changes
1250 in the parent in addition to those currently reported by :hg:`status`,
1248 in the parent in addition to those currently reported by :hg:`status`,
1251 if there are any. The old commit is stored in a backup bundle in
1249 if there are any. The old commit is stored in a backup bundle in
1252 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1250 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1253 on how to restore it).
1251 on how to restore it).
1254
1252
1255 Message, user and date are taken from the amended commit unless
1253 Message, user and date are taken from the amended commit unless
1256 specified. When a message isn't specified on the command line,
1254 specified. When a message isn't specified on the command line,
1257 the editor will open with the message of the amended commit.
1255 the editor will open with the message of the amended commit.
1258
1256
1259 It is not possible to amend public changesets (see :hg:`help phases`)
1257 It is not possible to amend public changesets (see :hg:`help phases`)
1260 or changesets that have children.
1258 or changesets that have children.
1261
1259
1262 See :hg:`help dates` for a list of formats valid for -d/--date.
1260 See :hg:`help dates` for a list of formats valid for -d/--date.
1263
1261
1264 Returns 0 on success, 1 if nothing changed.
1262 Returns 0 on success, 1 if nothing changed.
1265 """
1263 """
1266 if opts.get('subrepos'):
1264 if opts.get('subrepos'):
1267 # Let --subrepos on the command line override config setting.
1265 # Let --subrepos on the command line override config setting.
1268 ui.setconfig('ui', 'commitsubrepos', True)
1266 ui.setconfig('ui', 'commitsubrepos', True)
1269
1267
1270 extra = {}
1268 extra = {}
1271 if opts.get('close_branch'):
1269 if opts.get('close_branch'):
1272 if repo['.'].node() not in repo.branchheads():
1270 if repo['.'].node() not in repo.branchheads():
1273 # The topo heads set is included in the branch heads set of the
1271 # The topo heads set is included in the branch heads set of the
1274 # current branch, so it's sufficient to test branchheads
1272 # current branch, so it's sufficient to test branchheads
1275 raise util.Abort(_('can only close branch heads'))
1273 raise util.Abort(_('can only close branch heads'))
1276 extra['close'] = 1
1274 extra['close'] = 1
1277
1275
1278 branch = repo[None].branch()
1276 branch = repo[None].branch()
1279 bheads = repo.branchheads(branch)
1277 bheads = repo.branchheads(branch)
1280
1278
1281 if opts.get('amend'):
1279 if opts.get('amend'):
1282 if ui.configbool('ui', 'commitsubrepos'):
1280 if ui.configbool('ui', 'commitsubrepos'):
1283 raise util.Abort(_('cannot amend recursively'))
1281 raise util.Abort(_('cannot amend recursively'))
1284
1282
1285 old = repo['.']
1283 old = repo['.']
1286 if old.phase() == phases.public:
1284 if old.phase() == phases.public:
1287 raise util.Abort(_('cannot amend public changesets'))
1285 raise util.Abort(_('cannot amend public changesets'))
1288 if len(old.parents()) > 1:
1286 if len(old.parents()) > 1:
1289 raise util.Abort(_('cannot amend merge changesets'))
1287 raise util.Abort(_('cannot amend merge changesets'))
1290 if len(repo[None].parents()) > 1:
1288 if len(repo[None].parents()) > 1:
1291 raise util.Abort(_('cannot amend while merging'))
1289 raise util.Abort(_('cannot amend while merging'))
1292 if old.children():
1290 if old.children():
1293 raise util.Abort(_('cannot amend changeset with children'))
1291 raise util.Abort(_('cannot amend changeset with children'))
1294
1292
1295 e = cmdutil.commiteditor
1293 e = cmdutil.commiteditor
1296 if opts.get('force_editor'):
1294 if opts.get('force_editor'):
1297 e = cmdutil.commitforceeditor
1295 e = cmdutil.commitforceeditor
1298
1296
1299 def commitfunc(ui, repo, message, match, opts):
1297 def commitfunc(ui, repo, message, match, opts):
1300 editor = e
1298 editor = e
1301 # message contains text from -m or -l, if it's empty,
1299 # message contains text from -m or -l, if it's empty,
1302 # open the editor with the old message
1300 # open the editor with the old message
1303 if not message:
1301 if not message:
1304 message = old.description()
1302 message = old.description()
1305 editor = cmdutil.commitforceeditor
1303 editor = cmdutil.commitforceeditor
1306 return repo.commit(message,
1304 return repo.commit(message,
1307 opts.get('user') or old.user(),
1305 opts.get('user') or old.user(),
1308 opts.get('date') or old.date(),
1306 opts.get('date') or old.date(),
1309 match,
1307 match,
1310 editor=editor,
1308 editor=editor,
1311 extra=extra)
1309 extra=extra)
1312
1310
1313 current = repo._bookmarkcurrent
1311 current = repo._bookmarkcurrent
1314 marks = old.bookmarks()
1312 marks = old.bookmarks()
1315 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1313 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1316 if node == old.node():
1314 if node == old.node():
1317 ui.status(_("nothing changed\n"))
1315 ui.status(_("nothing changed\n"))
1318 return 1
1316 return 1
1319 elif marks:
1317 elif marks:
1320 ui.debug('moving bookmarks %r from %s to %s\n' %
1318 ui.debug('moving bookmarks %r from %s to %s\n' %
1321 (marks, old.hex(), hex(node)))
1319 (marks, old.hex(), hex(node)))
1322 for bm in marks:
1320 for bm in marks:
1323 repo._bookmarks[bm] = node
1321 repo._bookmarks[bm] = node
1324 if bm == current:
1322 if bm == current:
1325 bookmarks.setcurrent(repo, bm)
1323 bookmarks.setcurrent(repo, bm)
1326 bookmarks.write(repo)
1324 bookmarks.write(repo)
1327 else:
1325 else:
1328 e = cmdutil.commiteditor
1326 e = cmdutil.commiteditor
1329 if opts.get('force_editor'):
1327 if opts.get('force_editor'):
1330 e = cmdutil.commitforceeditor
1328 e = cmdutil.commitforceeditor
1331
1329
1332 def commitfunc(ui, repo, message, match, opts):
1330 def commitfunc(ui, repo, message, match, opts):
1333 return repo.commit(message, opts.get('user'), opts.get('date'),
1331 return repo.commit(message, opts.get('user'), opts.get('date'),
1334 match, editor=e, extra=extra)
1332 match, editor=e, extra=extra)
1335
1333
1336 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1334 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1337
1335
1338 if not node:
1336 if not node:
1339 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1337 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1340 if stat[3]:
1338 if stat[3]:
1341 ui.status(_("nothing changed (%d missing files, see "
1339 ui.status(_("nothing changed (%d missing files, see "
1342 "'hg status')\n") % len(stat[3]))
1340 "'hg status')\n") % len(stat[3]))
1343 else:
1341 else:
1344 ui.status(_("nothing changed\n"))
1342 ui.status(_("nothing changed\n"))
1345 return 1
1343 return 1
1346
1344
1347 ctx = repo[node]
1345 ctx = repo[node]
1348 parents = ctx.parents()
1346 parents = ctx.parents()
1349
1347
1350 if (not opts.get('amend') and bheads and node not in bheads and not
1348 if (not opts.get('amend') and bheads and node not in bheads and not
1351 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1349 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1352 ui.status(_('created new head\n'))
1350 ui.status(_('created new head\n'))
1353 # The message is not printed for initial roots. For the other
1351 # The message is not printed for initial roots. For the other
1354 # changesets, it is printed in the following situations:
1352 # changesets, it is printed in the following situations:
1355 #
1353 #
1356 # Par column: for the 2 parents with ...
1354 # Par column: for the 2 parents with ...
1357 # N: null or no parent
1355 # N: null or no parent
1358 # B: parent is on another named branch
1356 # B: parent is on another named branch
1359 # C: parent is a regular non head changeset
1357 # C: parent is a regular non head changeset
1360 # H: parent was a branch head of the current branch
1358 # H: parent was a branch head of the current branch
1361 # Msg column: whether we print "created new head" message
1359 # Msg column: whether we print "created new head" message
1362 # In the following, it is assumed that there already exists some
1360 # In the following, it is assumed that there already exists some
1363 # initial branch heads of the current branch, otherwise nothing is
1361 # initial branch heads of the current branch, otherwise nothing is
1364 # printed anyway.
1362 # printed anyway.
1365 #
1363 #
1366 # Par Msg Comment
1364 # Par Msg Comment
1367 # N N y additional topo root
1365 # N N y additional topo root
1368 #
1366 #
1369 # B N y additional branch root
1367 # B N y additional branch root
1370 # C N y additional topo head
1368 # C N y additional topo head
1371 # H N n usual case
1369 # H N n usual case
1372 #
1370 #
1373 # B B y weird additional branch root
1371 # B B y weird additional branch root
1374 # C B y branch merge
1372 # C B y branch merge
1375 # H B n merge with named branch
1373 # H B n merge with named branch
1376 #
1374 #
1377 # C C y additional head from merge
1375 # C C y additional head from merge
1378 # C H n merge with a head
1376 # C H n merge with a head
1379 #
1377 #
1380 # H H n head merge: head count decreases
1378 # H H n head merge: head count decreases
1381
1379
1382 if not opts.get('close_branch'):
1380 if not opts.get('close_branch'):
1383 for r in parents:
1381 for r in parents:
1384 if r.closesbranch() and r.branch() == branch:
1382 if r.closesbranch() and r.branch() == branch:
1385 ui.status(_('reopening closed branch head %d\n') % r)
1383 ui.status(_('reopening closed branch head %d\n') % r)
1386
1384
1387 if ui.debugflag:
1385 if ui.debugflag:
1388 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1386 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1389 elif ui.verbose:
1387 elif ui.verbose:
1390 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1388 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1391
1389
1392 @command('copy|cp',
1390 @command('copy|cp',
1393 [('A', 'after', None, _('record a copy that has already occurred')),
1391 [('A', 'after', None, _('record a copy that has already occurred')),
1394 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1392 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1395 ] + walkopts + dryrunopts,
1393 ] + walkopts + dryrunopts,
1396 _('[OPTION]... [SOURCE]... DEST'))
1394 _('[OPTION]... [SOURCE]... DEST'))
1397 def copy(ui, repo, *pats, **opts):
1395 def copy(ui, repo, *pats, **opts):
1398 """mark files as copied for the next commit
1396 """mark files as copied for the next commit
1399
1397
1400 Mark dest as having copies of source files. If dest is a
1398 Mark dest as having copies of source files. If dest is a
1401 directory, copies are put in that directory. If dest is a file,
1399 directory, copies are put in that directory. If dest is a file,
1402 the source must be a single file.
1400 the source must be a single file.
1403
1401
1404 By default, this command copies the contents of files as they
1402 By default, this command copies the contents of files as they
1405 exist in the working directory. If invoked with -A/--after, the
1403 exist in the working directory. If invoked with -A/--after, the
1406 operation is recorded, but no copying is performed.
1404 operation is recorded, but no copying is performed.
1407
1405
1408 This command takes effect with the next commit. To undo a copy
1406 This command takes effect with the next commit. To undo a copy
1409 before that, see :hg:`revert`.
1407 before that, see :hg:`revert`.
1410
1408
1411 Returns 0 on success, 1 if errors are encountered.
1409 Returns 0 on success, 1 if errors are encountered.
1412 """
1410 """
1413 wlock = repo.wlock(False)
1411 wlock = repo.wlock(False)
1414 try:
1412 try:
1415 return cmdutil.copy(ui, repo, pats, opts)
1413 return cmdutil.copy(ui, repo, pats, opts)
1416 finally:
1414 finally:
1417 wlock.release()
1415 wlock.release()
1418
1416
1419 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1417 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1420 def debugancestor(ui, repo, *args):
1418 def debugancestor(ui, repo, *args):
1421 """find the ancestor revision of two revisions in a given index"""
1419 """find the ancestor revision of two revisions in a given index"""
1422 if len(args) == 3:
1420 if len(args) == 3:
1423 index, rev1, rev2 = args
1421 index, rev1, rev2 = args
1424 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1422 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1425 lookup = r.lookup
1423 lookup = r.lookup
1426 elif len(args) == 2:
1424 elif len(args) == 2:
1427 if not repo:
1425 if not repo:
1428 raise util.Abort(_("there is no Mercurial repository here "
1426 raise util.Abort(_("there is no Mercurial repository here "
1429 "(.hg not found)"))
1427 "(.hg not found)"))
1430 rev1, rev2 = args
1428 rev1, rev2 = args
1431 r = repo.changelog
1429 r = repo.changelog
1432 lookup = repo.lookup
1430 lookup = repo.lookup
1433 else:
1431 else:
1434 raise util.Abort(_('either two or three arguments required'))
1432 raise util.Abort(_('either two or three arguments required'))
1435 a = r.ancestor(lookup(rev1), lookup(rev2))
1433 a = r.ancestor(lookup(rev1), lookup(rev2))
1436 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1434 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1437
1435
1438 @command('debugbuilddag',
1436 @command('debugbuilddag',
1439 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1437 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1440 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1438 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1441 ('n', 'new-file', None, _('add new file at each rev'))],
1439 ('n', 'new-file', None, _('add new file at each rev'))],
1442 _('[OPTION]... [TEXT]'))
1440 _('[OPTION]... [TEXT]'))
1443 def debugbuilddag(ui, repo, text=None,
1441 def debugbuilddag(ui, repo, text=None,
1444 mergeable_file=False,
1442 mergeable_file=False,
1445 overwritten_file=False,
1443 overwritten_file=False,
1446 new_file=False):
1444 new_file=False):
1447 """builds a repo with a given DAG from scratch in the current empty repo
1445 """builds a repo with a given DAG from scratch in the current empty repo
1448
1446
1449 The description of the DAG is read from stdin if not given on the
1447 The description of the DAG is read from stdin if not given on the
1450 command line.
1448 command line.
1451
1449
1452 Elements:
1450 Elements:
1453
1451
1454 - "+n" is a linear run of n nodes based on the current default parent
1452 - "+n" is a linear run of n nodes based on the current default parent
1455 - "." is a single node based on the current default parent
1453 - "." is a single node based on the current default parent
1456 - "$" resets the default parent to null (implied at the start);
1454 - "$" resets the default parent to null (implied at the start);
1457 otherwise the default parent is always the last node created
1455 otherwise the default parent is always the last node created
1458 - "<p" sets the default parent to the backref p
1456 - "<p" sets the default parent to the backref p
1459 - "*p" is a fork at parent p, which is a backref
1457 - "*p" is a fork at parent p, which is a backref
1460 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1458 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1461 - "/p2" is a merge of the preceding node and p2
1459 - "/p2" is a merge of the preceding node and p2
1462 - ":tag" defines a local tag for the preceding node
1460 - ":tag" defines a local tag for the preceding node
1463 - "@branch" sets the named branch for subsequent nodes
1461 - "@branch" sets the named branch for subsequent nodes
1464 - "#...\\n" is a comment up to the end of the line
1462 - "#...\\n" is a comment up to the end of the line
1465
1463
1466 Whitespace between the above elements is ignored.
1464 Whitespace between the above elements is ignored.
1467
1465
1468 A backref is either
1466 A backref is either
1469
1467
1470 - a number n, which references the node curr-n, where curr is the current
1468 - a number n, which references the node curr-n, where curr is the current
1471 node, or
1469 node, or
1472 - the name of a local tag you placed earlier using ":tag", or
1470 - the name of a local tag you placed earlier using ":tag", or
1473 - empty to denote the default parent.
1471 - empty to denote the default parent.
1474
1472
1475 All string valued-elements are either strictly alphanumeric, or must
1473 All string valued-elements are either strictly alphanumeric, or must
1476 be enclosed in double quotes ("..."), with "\\" as escape character.
1474 be enclosed in double quotes ("..."), with "\\" as escape character.
1477 """
1475 """
1478
1476
1479 if text is None:
1477 if text is None:
1480 ui.status(_("reading DAG from stdin\n"))
1478 ui.status(_("reading DAG from stdin\n"))
1481 text = ui.fin.read()
1479 text = ui.fin.read()
1482
1480
1483 cl = repo.changelog
1481 cl = repo.changelog
1484 if len(cl) > 0:
1482 if len(cl) > 0:
1485 raise util.Abort(_('repository is not empty'))
1483 raise util.Abort(_('repository is not empty'))
1486
1484
1487 # determine number of revs in DAG
1485 # determine number of revs in DAG
1488 total = 0
1486 total = 0
1489 for type, data in dagparser.parsedag(text):
1487 for type, data in dagparser.parsedag(text):
1490 if type == 'n':
1488 if type == 'n':
1491 total += 1
1489 total += 1
1492
1490
1493 if mergeable_file:
1491 if mergeable_file:
1494 linesperrev = 2
1492 linesperrev = 2
1495 # make a file with k lines per rev
1493 # make a file with k lines per rev
1496 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1494 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1497 initialmergedlines.append("")
1495 initialmergedlines.append("")
1498
1496
1499 tags = []
1497 tags = []
1500
1498
1501 lock = tr = None
1499 lock = tr = None
1502 try:
1500 try:
1503 lock = repo.lock()
1501 lock = repo.lock()
1504 tr = repo.transaction("builddag")
1502 tr = repo.transaction("builddag")
1505
1503
1506 at = -1
1504 at = -1
1507 atbranch = 'default'
1505 atbranch = 'default'
1508 nodeids = []
1506 nodeids = []
1509 id = 0
1507 id = 0
1510 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1508 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1511 for type, data in dagparser.parsedag(text):
1509 for type, data in dagparser.parsedag(text):
1512 if type == 'n':
1510 if type == 'n':
1513 ui.note('node %s\n' % str(data))
1511 ui.note('node %s\n' % str(data))
1514 id, ps = data
1512 id, ps = data
1515
1513
1516 files = []
1514 files = []
1517 fctxs = {}
1515 fctxs = {}
1518
1516
1519 p2 = None
1517 p2 = None
1520 if mergeable_file:
1518 if mergeable_file:
1521 fn = "mf"
1519 fn = "mf"
1522 p1 = repo[ps[0]]
1520 p1 = repo[ps[0]]
1523 if len(ps) > 1:
1521 if len(ps) > 1:
1524 p2 = repo[ps[1]]
1522 p2 = repo[ps[1]]
1525 pa = p1.ancestor(p2)
1523 pa = p1.ancestor(p2)
1526 base, local, other = [x[fn].data() for x in pa, p1, p2]
1524 base, local, other = [x[fn].data() for x in pa, p1, p2]
1527 m3 = simplemerge.Merge3Text(base, local, other)
1525 m3 = simplemerge.Merge3Text(base, local, other)
1528 ml = [l.strip() for l in m3.merge_lines()]
1526 ml = [l.strip() for l in m3.merge_lines()]
1529 ml.append("")
1527 ml.append("")
1530 elif at > 0:
1528 elif at > 0:
1531 ml = p1[fn].data().split("\n")
1529 ml = p1[fn].data().split("\n")
1532 else:
1530 else:
1533 ml = initialmergedlines
1531 ml = initialmergedlines
1534 ml[id * linesperrev] += " r%i" % id
1532 ml[id * linesperrev] += " r%i" % id
1535 mergedtext = "\n".join(ml)
1533 mergedtext = "\n".join(ml)
1536 files.append(fn)
1534 files.append(fn)
1537 fctxs[fn] = context.memfilectx(fn, mergedtext)
1535 fctxs[fn] = context.memfilectx(fn, mergedtext)
1538
1536
1539 if overwritten_file:
1537 if overwritten_file:
1540 fn = "of"
1538 fn = "of"
1541 files.append(fn)
1539 files.append(fn)
1542 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1540 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1543
1541
1544 if new_file:
1542 if new_file:
1545 fn = "nf%i" % id
1543 fn = "nf%i" % id
1546 files.append(fn)
1544 files.append(fn)
1547 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1545 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1548 if len(ps) > 1:
1546 if len(ps) > 1:
1549 if not p2:
1547 if not p2:
1550 p2 = repo[ps[1]]
1548 p2 = repo[ps[1]]
1551 for fn in p2:
1549 for fn in p2:
1552 if fn.startswith("nf"):
1550 if fn.startswith("nf"):
1553 files.append(fn)
1551 files.append(fn)
1554 fctxs[fn] = p2[fn]
1552 fctxs[fn] = p2[fn]
1555
1553
1556 def fctxfn(repo, cx, path):
1554 def fctxfn(repo, cx, path):
1557 return fctxs.get(path)
1555 return fctxs.get(path)
1558
1556
1559 if len(ps) == 0 or ps[0] < 0:
1557 if len(ps) == 0 or ps[0] < 0:
1560 pars = [None, None]
1558 pars = [None, None]
1561 elif len(ps) == 1:
1559 elif len(ps) == 1:
1562 pars = [nodeids[ps[0]], None]
1560 pars = [nodeids[ps[0]], None]
1563 else:
1561 else:
1564 pars = [nodeids[p] for p in ps]
1562 pars = [nodeids[p] for p in ps]
1565 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1563 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1566 date=(id, 0),
1564 date=(id, 0),
1567 user="debugbuilddag",
1565 user="debugbuilddag",
1568 extra={'branch': atbranch})
1566 extra={'branch': atbranch})
1569 nodeid = repo.commitctx(cx)
1567 nodeid = repo.commitctx(cx)
1570 nodeids.append(nodeid)
1568 nodeids.append(nodeid)
1571 at = id
1569 at = id
1572 elif type == 'l':
1570 elif type == 'l':
1573 id, name = data
1571 id, name = data
1574 ui.note('tag %s\n' % name)
1572 ui.note('tag %s\n' % name)
1575 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1573 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1576 elif type == 'a':
1574 elif type == 'a':
1577 ui.note('branch %s\n' % data)
1575 ui.note('branch %s\n' % data)
1578 atbranch = data
1576 atbranch = data
1579 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1577 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1580 tr.close()
1578 tr.close()
1581
1579
1582 if tags:
1580 if tags:
1583 repo.opener.write("localtags", "".join(tags))
1581 repo.opener.write("localtags", "".join(tags))
1584 finally:
1582 finally:
1585 ui.progress(_('building'), None)
1583 ui.progress(_('building'), None)
1586 release(tr, lock)
1584 release(tr, lock)
1587
1585
1588 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1586 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1589 def debugbundle(ui, bundlepath, all=None, **opts):
1587 def debugbundle(ui, bundlepath, all=None, **opts):
1590 """lists the contents of a bundle"""
1588 """lists the contents of a bundle"""
1591 f = url.open(ui, bundlepath)
1589 f = url.open(ui, bundlepath)
1592 try:
1590 try:
1593 gen = changegroup.readbundle(f, bundlepath)
1591 gen = changegroup.readbundle(f, bundlepath)
1594 if all:
1592 if all:
1595 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1593 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1596
1594
1597 def showchunks(named):
1595 def showchunks(named):
1598 ui.write("\n%s\n" % named)
1596 ui.write("\n%s\n" % named)
1599 chain = None
1597 chain = None
1600 while True:
1598 while True:
1601 chunkdata = gen.deltachunk(chain)
1599 chunkdata = gen.deltachunk(chain)
1602 if not chunkdata:
1600 if not chunkdata:
1603 break
1601 break
1604 node = chunkdata['node']
1602 node = chunkdata['node']
1605 p1 = chunkdata['p1']
1603 p1 = chunkdata['p1']
1606 p2 = chunkdata['p2']
1604 p2 = chunkdata['p2']
1607 cs = chunkdata['cs']
1605 cs = chunkdata['cs']
1608 deltabase = chunkdata['deltabase']
1606 deltabase = chunkdata['deltabase']
1609 delta = chunkdata['delta']
1607 delta = chunkdata['delta']
1610 ui.write("%s %s %s %s %s %s\n" %
1608 ui.write("%s %s %s %s %s %s\n" %
1611 (hex(node), hex(p1), hex(p2),
1609 (hex(node), hex(p1), hex(p2),
1612 hex(cs), hex(deltabase), len(delta)))
1610 hex(cs), hex(deltabase), len(delta)))
1613 chain = node
1611 chain = node
1614
1612
1615 chunkdata = gen.changelogheader()
1613 chunkdata = gen.changelogheader()
1616 showchunks("changelog")
1614 showchunks("changelog")
1617 chunkdata = gen.manifestheader()
1615 chunkdata = gen.manifestheader()
1618 showchunks("manifest")
1616 showchunks("manifest")
1619 while True:
1617 while True:
1620 chunkdata = gen.filelogheader()
1618 chunkdata = gen.filelogheader()
1621 if not chunkdata:
1619 if not chunkdata:
1622 break
1620 break
1623 fname = chunkdata['filename']
1621 fname = chunkdata['filename']
1624 showchunks(fname)
1622 showchunks(fname)
1625 else:
1623 else:
1626 chunkdata = gen.changelogheader()
1624 chunkdata = gen.changelogheader()
1627 chain = None
1625 chain = None
1628 while True:
1626 while True:
1629 chunkdata = gen.deltachunk(chain)
1627 chunkdata = gen.deltachunk(chain)
1630 if not chunkdata:
1628 if not chunkdata:
1631 break
1629 break
1632 node = chunkdata['node']
1630 node = chunkdata['node']
1633 ui.write("%s\n" % hex(node))
1631 ui.write("%s\n" % hex(node))
1634 chain = node
1632 chain = node
1635 finally:
1633 finally:
1636 f.close()
1634 f.close()
1637
1635
1638 @command('debugcheckstate', [], '')
1636 @command('debugcheckstate', [], '')
1639 def debugcheckstate(ui, repo):
1637 def debugcheckstate(ui, repo):
1640 """validate the correctness of the current dirstate"""
1638 """validate the correctness of the current dirstate"""
1641 parent1, parent2 = repo.dirstate.parents()
1639 parent1, parent2 = repo.dirstate.parents()
1642 m1 = repo[parent1].manifest()
1640 m1 = repo[parent1].manifest()
1643 m2 = repo[parent2].manifest()
1641 m2 = repo[parent2].manifest()
1644 errors = 0
1642 errors = 0
1645 for f in repo.dirstate:
1643 for f in repo.dirstate:
1646 state = repo.dirstate[f]
1644 state = repo.dirstate[f]
1647 if state in "nr" and f not in m1:
1645 if state in "nr" and f not in m1:
1648 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1646 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1649 errors += 1
1647 errors += 1
1650 if state in "a" and f in m1:
1648 if state in "a" and f in m1:
1651 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1649 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1652 errors += 1
1650 errors += 1
1653 if state in "m" and f not in m1 and f not in m2:
1651 if state in "m" and f not in m1 and f not in m2:
1654 ui.warn(_("%s in state %s, but not in either manifest\n") %
1652 ui.warn(_("%s in state %s, but not in either manifest\n") %
1655 (f, state))
1653 (f, state))
1656 errors += 1
1654 errors += 1
1657 for f in m1:
1655 for f in m1:
1658 state = repo.dirstate[f]
1656 state = repo.dirstate[f]
1659 if state not in "nrm":
1657 if state not in "nrm":
1660 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1658 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1661 errors += 1
1659 errors += 1
1662 if errors:
1660 if errors:
1663 error = _(".hg/dirstate inconsistent with current parent's manifest")
1661 error = _(".hg/dirstate inconsistent with current parent's manifest")
1664 raise util.Abort(error)
1662 raise util.Abort(error)
1665
1663
1666 @command('debugcommands', [], _('[COMMAND]'))
1664 @command('debugcommands', [], _('[COMMAND]'))
1667 def debugcommands(ui, cmd='', *args):
1665 def debugcommands(ui, cmd='', *args):
1668 """list all available commands and options"""
1666 """list all available commands and options"""
1669 for cmd, vals in sorted(table.iteritems()):
1667 for cmd, vals in sorted(table.iteritems()):
1670 cmd = cmd.split('|')[0].strip('^')
1668 cmd = cmd.split('|')[0].strip('^')
1671 opts = ', '.join([i[1] for i in vals[1]])
1669 opts = ', '.join([i[1] for i in vals[1]])
1672 ui.write('%s: %s\n' % (cmd, opts))
1670 ui.write('%s: %s\n' % (cmd, opts))
1673
1671
1674 @command('debugcomplete',
1672 @command('debugcomplete',
1675 [('o', 'options', None, _('show the command options'))],
1673 [('o', 'options', None, _('show the command options'))],
1676 _('[-o] CMD'))
1674 _('[-o] CMD'))
1677 def debugcomplete(ui, cmd='', **opts):
1675 def debugcomplete(ui, cmd='', **opts):
1678 """returns the completion list associated with the given command"""
1676 """returns the completion list associated with the given command"""
1679
1677
1680 if opts.get('options'):
1678 if opts.get('options'):
1681 options = []
1679 options = []
1682 otables = [globalopts]
1680 otables = [globalopts]
1683 if cmd:
1681 if cmd:
1684 aliases, entry = cmdutil.findcmd(cmd, table, False)
1682 aliases, entry = cmdutil.findcmd(cmd, table, False)
1685 otables.append(entry[1])
1683 otables.append(entry[1])
1686 for t in otables:
1684 for t in otables:
1687 for o in t:
1685 for o in t:
1688 if "(DEPRECATED)" in o[3]:
1686 if "(DEPRECATED)" in o[3]:
1689 continue
1687 continue
1690 if o[0]:
1688 if o[0]:
1691 options.append('-%s' % o[0])
1689 options.append('-%s' % o[0])
1692 options.append('--%s' % o[1])
1690 options.append('--%s' % o[1])
1693 ui.write("%s\n" % "\n".join(options))
1691 ui.write("%s\n" % "\n".join(options))
1694 return
1692 return
1695
1693
1696 cmdlist = cmdutil.findpossible(cmd, table)
1694 cmdlist = cmdutil.findpossible(cmd, table)
1697 if ui.verbose:
1695 if ui.verbose:
1698 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1696 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1699 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1697 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1700
1698
1701 @command('debugdag',
1699 @command('debugdag',
1702 [('t', 'tags', None, _('use tags as labels')),
1700 [('t', 'tags', None, _('use tags as labels')),
1703 ('b', 'branches', None, _('annotate with branch names')),
1701 ('b', 'branches', None, _('annotate with branch names')),
1704 ('', 'dots', None, _('use dots for runs')),
1702 ('', 'dots', None, _('use dots for runs')),
1705 ('s', 'spaces', None, _('separate elements by spaces'))],
1703 ('s', 'spaces', None, _('separate elements by spaces'))],
1706 _('[OPTION]... [FILE [REV]...]'))
1704 _('[OPTION]... [FILE [REV]...]'))
1707 def debugdag(ui, repo, file_=None, *revs, **opts):
1705 def debugdag(ui, repo, file_=None, *revs, **opts):
1708 """format the changelog or an index DAG as a concise textual description
1706 """format the changelog or an index DAG as a concise textual description
1709
1707
1710 If you pass a revlog index, the revlog's DAG is emitted. If you list
1708 If you pass a revlog index, the revlog's DAG is emitted. If you list
1711 revision numbers, they get labeled in the output as rN.
1709 revision numbers, they get labeled in the output as rN.
1712
1710
1713 Otherwise, the changelog DAG of the current repo is emitted.
1711 Otherwise, the changelog DAG of the current repo is emitted.
1714 """
1712 """
1715 spaces = opts.get('spaces')
1713 spaces = opts.get('spaces')
1716 dots = opts.get('dots')
1714 dots = opts.get('dots')
1717 if file_:
1715 if file_:
1718 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1716 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1719 revs = set((int(r) for r in revs))
1717 revs = set((int(r) for r in revs))
1720 def events():
1718 def events():
1721 for r in rlog:
1719 for r in rlog:
1722 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1720 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1723 if p != -1)))
1721 if p != -1)))
1724 if r in revs:
1722 if r in revs:
1725 yield 'l', (r, "r%i" % r)
1723 yield 'l', (r, "r%i" % r)
1726 elif repo:
1724 elif repo:
1727 cl = repo.changelog
1725 cl = repo.changelog
1728 tags = opts.get('tags')
1726 tags = opts.get('tags')
1729 branches = opts.get('branches')
1727 branches = opts.get('branches')
1730 if tags:
1728 if tags:
1731 labels = {}
1729 labels = {}
1732 for l, n in repo.tags().items():
1730 for l, n in repo.tags().items():
1733 labels.setdefault(cl.rev(n), []).append(l)
1731 labels.setdefault(cl.rev(n), []).append(l)
1734 def events():
1732 def events():
1735 b = "default"
1733 b = "default"
1736 for r in cl:
1734 for r in cl:
1737 if branches:
1735 if branches:
1738 newb = cl.read(cl.node(r))[5]['branch']
1736 newb = cl.read(cl.node(r))[5]['branch']
1739 if newb != b:
1737 if newb != b:
1740 yield 'a', newb
1738 yield 'a', newb
1741 b = newb
1739 b = newb
1742 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1740 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1743 if p != -1)))
1741 if p != -1)))
1744 if tags:
1742 if tags:
1745 ls = labels.get(r)
1743 ls = labels.get(r)
1746 if ls:
1744 if ls:
1747 for l in ls:
1745 for l in ls:
1748 yield 'l', (r, l)
1746 yield 'l', (r, l)
1749 else:
1747 else:
1750 raise util.Abort(_('need repo for changelog dag'))
1748 raise util.Abort(_('need repo for changelog dag'))
1751
1749
1752 for line in dagparser.dagtextlines(events(),
1750 for line in dagparser.dagtextlines(events(),
1753 addspaces=spaces,
1751 addspaces=spaces,
1754 wraplabels=True,
1752 wraplabels=True,
1755 wrapannotations=True,
1753 wrapannotations=True,
1756 wrapnonlinear=dots,
1754 wrapnonlinear=dots,
1757 usedots=dots,
1755 usedots=dots,
1758 maxlinewidth=70):
1756 maxlinewidth=70):
1759 ui.write(line)
1757 ui.write(line)
1760 ui.write("\n")
1758 ui.write("\n")
1761
1759
1762 @command('debugdata',
1760 @command('debugdata',
1763 [('c', 'changelog', False, _('open changelog')),
1761 [('c', 'changelog', False, _('open changelog')),
1764 ('m', 'manifest', False, _('open manifest'))],
1762 ('m', 'manifest', False, _('open manifest'))],
1765 _('-c|-m|FILE REV'))
1763 _('-c|-m|FILE REV'))
1766 def debugdata(ui, repo, file_, rev = None, **opts):
1764 def debugdata(ui, repo, file_, rev = None, **opts):
1767 """dump the contents of a data file revision"""
1765 """dump the contents of a data file revision"""
1768 if opts.get('changelog') or opts.get('manifest'):
1766 if opts.get('changelog') or opts.get('manifest'):
1769 file_, rev = None, file_
1767 file_, rev = None, file_
1770 elif rev is None:
1768 elif rev is None:
1771 raise error.CommandError('debugdata', _('invalid arguments'))
1769 raise error.CommandError('debugdata', _('invalid arguments'))
1772 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1770 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1773 try:
1771 try:
1774 ui.write(r.revision(r.lookup(rev)))
1772 ui.write(r.revision(r.lookup(rev)))
1775 except KeyError:
1773 except KeyError:
1776 raise util.Abort(_('invalid revision identifier %s') % rev)
1774 raise util.Abort(_('invalid revision identifier %s') % rev)
1777
1775
1778 @command('debugdate',
1776 @command('debugdate',
1779 [('e', 'extended', None, _('try extended date formats'))],
1777 [('e', 'extended', None, _('try extended date formats'))],
1780 _('[-e] DATE [RANGE]'))
1778 _('[-e] DATE [RANGE]'))
1781 def debugdate(ui, date, range=None, **opts):
1779 def debugdate(ui, date, range=None, **opts):
1782 """parse and display a date"""
1780 """parse and display a date"""
1783 if opts["extended"]:
1781 if opts["extended"]:
1784 d = util.parsedate(date, util.extendeddateformats)
1782 d = util.parsedate(date, util.extendeddateformats)
1785 else:
1783 else:
1786 d = util.parsedate(date)
1784 d = util.parsedate(date)
1787 ui.write("internal: %s %s\n" % d)
1785 ui.write("internal: %s %s\n" % d)
1788 ui.write("standard: %s\n" % util.datestr(d))
1786 ui.write("standard: %s\n" % util.datestr(d))
1789 if range:
1787 if range:
1790 m = util.matchdate(range)
1788 m = util.matchdate(range)
1791 ui.write("match: %s\n" % m(d[0]))
1789 ui.write("match: %s\n" % m(d[0]))
1792
1790
1793 @command('debugdiscovery',
1791 @command('debugdiscovery',
1794 [('', 'old', None, _('use old-style discovery')),
1792 [('', 'old', None, _('use old-style discovery')),
1795 ('', 'nonheads', None,
1793 ('', 'nonheads', None,
1796 _('use old-style discovery with non-heads included')),
1794 _('use old-style discovery with non-heads included')),
1797 ] + remoteopts,
1795 ] + remoteopts,
1798 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1796 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1799 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1797 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1800 """runs the changeset discovery protocol in isolation"""
1798 """runs the changeset discovery protocol in isolation"""
1801 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1799 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1802 opts.get('branch'))
1800 opts.get('branch'))
1803 remote = hg.peer(repo, opts, remoteurl)
1801 remote = hg.peer(repo, opts, remoteurl)
1804 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1802 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1805
1803
1806 # make sure tests are repeatable
1804 # make sure tests are repeatable
1807 random.seed(12323)
1805 random.seed(12323)
1808
1806
1809 def doit(localheads, remoteheads, remote=remote):
1807 def doit(localheads, remoteheads, remote=remote):
1810 if opts.get('old'):
1808 if opts.get('old'):
1811 if localheads:
1809 if localheads:
1812 raise util.Abort('cannot use localheads with old style '
1810 raise util.Abort('cannot use localheads with old style '
1813 'discovery')
1811 'discovery')
1814 if not util.safehasattr(remote, 'branches'):
1812 if not util.safehasattr(remote, 'branches'):
1815 # enable in-client legacy support
1813 # enable in-client legacy support
1816 remote = localrepo.locallegacypeer(remote.local())
1814 remote = localrepo.locallegacypeer(remote.local())
1817 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1815 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1818 force=True)
1816 force=True)
1819 common = set(common)
1817 common = set(common)
1820 if not opts.get('nonheads'):
1818 if not opts.get('nonheads'):
1821 ui.write("unpruned common: %s\n" % " ".join([short(n)
1819 ui.write("unpruned common: %s\n" % " ".join([short(n)
1822 for n in common]))
1820 for n in common]))
1823 dag = dagutil.revlogdag(repo.changelog)
1821 dag = dagutil.revlogdag(repo.changelog)
1824 all = dag.ancestorset(dag.internalizeall(common))
1822 all = dag.ancestorset(dag.internalizeall(common))
1825 common = dag.externalizeall(dag.headsetofconnecteds(all))
1823 common = dag.externalizeall(dag.headsetofconnecteds(all))
1826 else:
1824 else:
1827 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1825 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1828 common = set(common)
1826 common = set(common)
1829 rheads = set(hds)
1827 rheads = set(hds)
1830 lheads = set(repo.heads())
1828 lheads = set(repo.heads())
1831 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1829 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1832 if lheads <= common:
1830 if lheads <= common:
1833 ui.write("local is subset\n")
1831 ui.write("local is subset\n")
1834 elif rheads <= common:
1832 elif rheads <= common:
1835 ui.write("remote is subset\n")
1833 ui.write("remote is subset\n")
1836
1834
1837 serverlogs = opts.get('serverlog')
1835 serverlogs = opts.get('serverlog')
1838 if serverlogs:
1836 if serverlogs:
1839 for filename in serverlogs:
1837 for filename in serverlogs:
1840 logfile = open(filename, 'r')
1838 logfile = open(filename, 'r')
1841 try:
1839 try:
1842 line = logfile.readline()
1840 line = logfile.readline()
1843 while line:
1841 while line:
1844 parts = line.strip().split(';')
1842 parts = line.strip().split(';')
1845 op = parts[1]
1843 op = parts[1]
1846 if op == 'cg':
1844 if op == 'cg':
1847 pass
1845 pass
1848 elif op == 'cgss':
1846 elif op == 'cgss':
1849 doit(parts[2].split(' '), parts[3].split(' '))
1847 doit(parts[2].split(' '), parts[3].split(' '))
1850 elif op == 'unb':
1848 elif op == 'unb':
1851 doit(parts[3].split(' '), parts[2].split(' '))
1849 doit(parts[3].split(' '), parts[2].split(' '))
1852 line = logfile.readline()
1850 line = logfile.readline()
1853 finally:
1851 finally:
1854 logfile.close()
1852 logfile.close()
1855
1853
1856 else:
1854 else:
1857 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1855 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1858 opts.get('remote_head'))
1856 opts.get('remote_head'))
1859 localrevs = opts.get('local_head')
1857 localrevs = opts.get('local_head')
1860 doit(localrevs, remoterevs)
1858 doit(localrevs, remoterevs)
1861
1859
1862 @command('debugfileset',
1860 @command('debugfileset',
1863 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1861 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1864 _('[-r REV] FILESPEC'))
1862 _('[-r REV] FILESPEC'))
1865 def debugfileset(ui, repo, expr, **opts):
1863 def debugfileset(ui, repo, expr, **opts):
1866 '''parse and apply a fileset specification'''
1864 '''parse and apply a fileset specification'''
1867 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1865 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1868 if ui.verbose:
1866 if ui.verbose:
1869 tree = fileset.parse(expr)[0]
1867 tree = fileset.parse(expr)[0]
1870 ui.note(tree, "\n")
1868 ui.note(tree, "\n")
1871
1869
1872 for f in fileset.getfileset(ctx, expr):
1870 for f in fileset.getfileset(ctx, expr):
1873 ui.write("%s\n" % f)
1871 ui.write("%s\n" % f)
1874
1872
1875 @command('debugfsinfo', [], _('[PATH]'))
1873 @command('debugfsinfo', [], _('[PATH]'))
1876 def debugfsinfo(ui, path = "."):
1874 def debugfsinfo(ui, path = "."):
1877 """show information detected about current filesystem"""
1875 """show information detected about current filesystem"""
1878 util.writefile('.debugfsinfo', '')
1876 util.writefile('.debugfsinfo', '')
1879 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1877 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1880 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1878 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1881 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1879 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1882 and 'yes' or 'no'))
1880 and 'yes' or 'no'))
1883 os.unlink('.debugfsinfo')
1881 os.unlink('.debugfsinfo')
1884
1882
1885 @command('debuggetbundle',
1883 @command('debuggetbundle',
1886 [('H', 'head', [], _('id of head node'), _('ID')),
1884 [('H', 'head', [], _('id of head node'), _('ID')),
1887 ('C', 'common', [], _('id of common node'), _('ID')),
1885 ('C', 'common', [], _('id of common node'), _('ID')),
1888 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1886 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1889 _('REPO FILE [-H|-C ID]...'))
1887 _('REPO FILE [-H|-C ID]...'))
1890 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1888 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1891 """retrieves a bundle from a repo
1889 """retrieves a bundle from a repo
1892
1890
1893 Every ID must be a full-length hex node id string. Saves the bundle to the
1891 Every ID must be a full-length hex node id string. Saves the bundle to the
1894 given file.
1892 given file.
1895 """
1893 """
1896 repo = hg.peer(ui, opts, repopath)
1894 repo = hg.peer(ui, opts, repopath)
1897 if not repo.capable('getbundle'):
1895 if not repo.capable('getbundle'):
1898 raise util.Abort("getbundle() not supported by target repository")
1896 raise util.Abort("getbundle() not supported by target repository")
1899 args = {}
1897 args = {}
1900 if common:
1898 if common:
1901 args['common'] = [bin(s) for s in common]
1899 args['common'] = [bin(s) for s in common]
1902 if head:
1900 if head:
1903 args['heads'] = [bin(s) for s in head]
1901 args['heads'] = [bin(s) for s in head]
1904 bundle = repo.getbundle('debug', **args)
1902 bundle = repo.getbundle('debug', **args)
1905
1903
1906 bundletype = opts.get('type', 'bzip2').lower()
1904 bundletype = opts.get('type', 'bzip2').lower()
1907 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1905 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1908 bundletype = btypes.get(bundletype)
1906 bundletype = btypes.get(bundletype)
1909 if bundletype not in changegroup.bundletypes:
1907 if bundletype not in changegroup.bundletypes:
1910 raise util.Abort(_('unknown bundle type specified with --type'))
1908 raise util.Abort(_('unknown bundle type specified with --type'))
1911 changegroup.writebundle(bundle, bundlepath, bundletype)
1909 changegroup.writebundle(bundle, bundlepath, bundletype)
1912
1910
1913 @command('debugignore', [], '')
1911 @command('debugignore', [], '')
1914 def debugignore(ui, repo, *values, **opts):
1912 def debugignore(ui, repo, *values, **opts):
1915 """display the combined ignore pattern"""
1913 """display the combined ignore pattern"""
1916 ignore = repo.dirstate._ignore
1914 ignore = repo.dirstate._ignore
1917 includepat = getattr(ignore, 'includepat', None)
1915 includepat = getattr(ignore, 'includepat', None)
1918 if includepat is not None:
1916 if includepat is not None:
1919 ui.write("%s\n" % includepat)
1917 ui.write("%s\n" % includepat)
1920 else:
1918 else:
1921 raise util.Abort(_("no ignore patterns found"))
1919 raise util.Abort(_("no ignore patterns found"))
1922
1920
1923 @command('debugindex',
1921 @command('debugindex',
1924 [('c', 'changelog', False, _('open changelog')),
1922 [('c', 'changelog', False, _('open changelog')),
1925 ('m', 'manifest', False, _('open manifest')),
1923 ('m', 'manifest', False, _('open manifest')),
1926 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1924 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1927 _('[-f FORMAT] -c|-m|FILE'))
1925 _('[-f FORMAT] -c|-m|FILE'))
1928 def debugindex(ui, repo, file_ = None, **opts):
1926 def debugindex(ui, repo, file_ = None, **opts):
1929 """dump the contents of an index file"""
1927 """dump the contents of an index file"""
1930 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1928 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1931 format = opts.get('format', 0)
1929 format = opts.get('format', 0)
1932 if format not in (0, 1):
1930 if format not in (0, 1):
1933 raise util.Abort(_("unknown format %d") % format)
1931 raise util.Abort(_("unknown format %d") % format)
1934
1932
1935 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1933 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1936 if generaldelta:
1934 if generaldelta:
1937 basehdr = ' delta'
1935 basehdr = ' delta'
1938 else:
1936 else:
1939 basehdr = ' base'
1937 basehdr = ' base'
1940
1938
1941 if format == 0:
1939 if format == 0:
1942 ui.write(" rev offset length " + basehdr + " linkrev"
1940 ui.write(" rev offset length " + basehdr + " linkrev"
1943 " nodeid p1 p2\n")
1941 " nodeid p1 p2\n")
1944 elif format == 1:
1942 elif format == 1:
1945 ui.write(" rev flag offset length"
1943 ui.write(" rev flag offset length"
1946 " size " + basehdr + " link p1 p2"
1944 " size " + basehdr + " link p1 p2"
1947 " nodeid\n")
1945 " nodeid\n")
1948
1946
1949 for i in r:
1947 for i in r:
1950 node = r.node(i)
1948 node = r.node(i)
1951 if generaldelta:
1949 if generaldelta:
1952 base = r.deltaparent(i)
1950 base = r.deltaparent(i)
1953 else:
1951 else:
1954 base = r.chainbase(i)
1952 base = r.chainbase(i)
1955 if format == 0:
1953 if format == 0:
1956 try:
1954 try:
1957 pp = r.parents(node)
1955 pp = r.parents(node)
1958 except Exception:
1956 except Exception:
1959 pp = [nullid, nullid]
1957 pp = [nullid, nullid]
1960 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1958 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1961 i, r.start(i), r.length(i), base, r.linkrev(i),
1959 i, r.start(i), r.length(i), base, r.linkrev(i),
1962 short(node), short(pp[0]), short(pp[1])))
1960 short(node), short(pp[0]), short(pp[1])))
1963 elif format == 1:
1961 elif format == 1:
1964 pr = r.parentrevs(i)
1962 pr = r.parentrevs(i)
1965 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1963 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1966 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1964 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1967 base, r.linkrev(i), pr[0], pr[1], short(node)))
1965 base, r.linkrev(i), pr[0], pr[1], short(node)))
1968
1966
1969 @command('debugindexdot', [], _('FILE'))
1967 @command('debugindexdot', [], _('FILE'))
1970 def debugindexdot(ui, repo, file_):
1968 def debugindexdot(ui, repo, file_):
1971 """dump an index DAG as a graphviz dot file"""
1969 """dump an index DAG as a graphviz dot file"""
1972 r = None
1970 r = None
1973 if repo:
1971 if repo:
1974 filelog = repo.file(file_)
1972 filelog = repo.file(file_)
1975 if len(filelog):
1973 if len(filelog):
1976 r = filelog
1974 r = filelog
1977 if not r:
1975 if not r:
1978 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1976 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1979 ui.write("digraph G {\n")
1977 ui.write("digraph G {\n")
1980 for i in r:
1978 for i in r:
1981 node = r.node(i)
1979 node = r.node(i)
1982 pp = r.parents(node)
1980 pp = r.parents(node)
1983 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1981 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1984 if pp[1] != nullid:
1982 if pp[1] != nullid:
1985 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1983 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1986 ui.write("}\n")
1984 ui.write("}\n")
1987
1985
1988 @command('debuginstall', [], '')
1986 @command('debuginstall', [], '')
1989 def debuginstall(ui):
1987 def debuginstall(ui):
1990 '''test Mercurial installation
1988 '''test Mercurial installation
1991
1989
1992 Returns 0 on success.
1990 Returns 0 on success.
1993 '''
1991 '''
1994
1992
1995 def writetemp(contents):
1993 def writetemp(contents):
1996 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1994 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1997 f = os.fdopen(fd, "wb")
1995 f = os.fdopen(fd, "wb")
1998 f.write(contents)
1996 f.write(contents)
1999 f.close()
1997 f.close()
2000 return name
1998 return name
2001
1999
2002 problems = 0
2000 problems = 0
2003
2001
2004 # encoding
2002 # encoding
2005 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2003 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2006 try:
2004 try:
2007 encoding.fromlocal("test")
2005 encoding.fromlocal("test")
2008 except util.Abort, inst:
2006 except util.Abort, inst:
2009 ui.write(" %s\n" % inst)
2007 ui.write(" %s\n" % inst)
2010 ui.write(_(" (check that your locale is properly set)\n"))
2008 ui.write(_(" (check that your locale is properly set)\n"))
2011 problems += 1
2009 problems += 1
2012
2010
2013 # Python lib
2011 # Python lib
2014 ui.status(_("checking Python lib (%s)...\n")
2012 ui.status(_("checking Python lib (%s)...\n")
2015 % os.path.dirname(os.__file__))
2013 % os.path.dirname(os.__file__))
2016
2014
2017 # compiled modules
2015 # compiled modules
2018 ui.status(_("checking installed modules (%s)...\n")
2016 ui.status(_("checking installed modules (%s)...\n")
2019 % os.path.dirname(__file__))
2017 % os.path.dirname(__file__))
2020 try:
2018 try:
2021 import bdiff, mpatch, base85, osutil
2019 import bdiff, mpatch, base85, osutil
2022 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2020 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2023 except Exception, inst:
2021 except Exception, inst:
2024 ui.write(" %s\n" % inst)
2022 ui.write(" %s\n" % inst)
2025 ui.write(_(" One or more extensions could not be found"))
2023 ui.write(_(" One or more extensions could not be found"))
2026 ui.write(_(" (check that you compiled the extensions)\n"))
2024 ui.write(_(" (check that you compiled the extensions)\n"))
2027 problems += 1
2025 problems += 1
2028
2026
2029 # templates
2027 # templates
2030 import templater
2028 import templater
2031 p = templater.templatepath()
2029 p = templater.templatepath()
2032 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2030 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2033 try:
2031 try:
2034 templater.templater(templater.templatepath("map-cmdline.default"))
2032 templater.templater(templater.templatepath("map-cmdline.default"))
2035 except Exception, inst:
2033 except Exception, inst:
2036 ui.write(" %s\n" % inst)
2034 ui.write(" %s\n" % inst)
2037 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2035 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2038 problems += 1
2036 problems += 1
2039
2037
2040 # editor
2038 # editor
2041 ui.status(_("checking commit editor...\n"))
2039 ui.status(_("checking commit editor...\n"))
2042 editor = ui.geteditor()
2040 editor = ui.geteditor()
2043 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2041 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2044 if not cmdpath:
2042 if not cmdpath:
2045 if editor == 'vi':
2043 if editor == 'vi':
2046 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2044 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2047 ui.write(_(" (specify a commit editor in your configuration"
2045 ui.write(_(" (specify a commit editor in your configuration"
2048 " file)\n"))
2046 " file)\n"))
2049 else:
2047 else:
2050 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2048 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2051 ui.write(_(" (specify a commit editor in your configuration"
2049 ui.write(_(" (specify a commit editor in your configuration"
2052 " file)\n"))
2050 " file)\n"))
2053 problems += 1
2051 problems += 1
2054
2052
2055 # check username
2053 # check username
2056 ui.status(_("checking username...\n"))
2054 ui.status(_("checking username...\n"))
2057 try:
2055 try:
2058 ui.username()
2056 ui.username()
2059 except util.Abort, e:
2057 except util.Abort, e:
2060 ui.write(" %s\n" % e)
2058 ui.write(" %s\n" % e)
2061 ui.write(_(" (specify a username in your configuration file)\n"))
2059 ui.write(_(" (specify a username in your configuration file)\n"))
2062 problems += 1
2060 problems += 1
2063
2061
2064 if not problems:
2062 if not problems:
2065 ui.status(_("no problems detected\n"))
2063 ui.status(_("no problems detected\n"))
2066 else:
2064 else:
2067 ui.write(_("%s problems detected,"
2065 ui.write(_("%s problems detected,"
2068 " please check your install!\n") % problems)
2066 " please check your install!\n") % problems)
2069
2067
2070 return problems
2068 return problems
2071
2069
2072 @command('debugknown', [], _('REPO ID...'))
2070 @command('debugknown', [], _('REPO ID...'))
2073 def debugknown(ui, repopath, *ids, **opts):
2071 def debugknown(ui, repopath, *ids, **opts):
2074 """test whether node ids are known to a repo
2072 """test whether node ids are known to a repo
2075
2073
2076 Every ID must be a full-length hex node id string. Returns a list of 0s
2074 Every ID must be a full-length hex node id string. Returns a list of 0s
2077 and 1s indicating unknown/known.
2075 and 1s indicating unknown/known.
2078 """
2076 """
2079 repo = hg.peer(ui, opts, repopath)
2077 repo = hg.peer(ui, opts, repopath)
2080 if not repo.capable('known'):
2078 if not repo.capable('known'):
2081 raise util.Abort("known() not supported by target repository")
2079 raise util.Abort("known() not supported by target repository")
2082 flags = repo.known([bin(s) for s in ids])
2080 flags = repo.known([bin(s) for s in ids])
2083 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2081 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2084
2082
2085 @command('debugobsolete', [] + commitopts2,
2083 @command('debugobsolete', [] + commitopts2,
2086 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2084 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2087 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2085 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2088 """create arbitrary obsolete marker"""
2086 """create arbitrary obsolete marker"""
2089 def parsenodeid(s):
2087 def parsenodeid(s):
2090 try:
2088 try:
2091 # We do not use revsingle/revrange functions here to accept
2089 # We do not use revsingle/revrange functions here to accept
2092 # arbitrary node identifiers, possibly not present in the
2090 # arbitrary node identifiers, possibly not present in the
2093 # local repository.
2091 # local repository.
2094 n = bin(s)
2092 n = bin(s)
2095 if len(n) != len(nullid):
2093 if len(n) != len(nullid):
2096 raise TypeError()
2094 raise TypeError()
2097 return n
2095 return n
2098 except TypeError:
2096 except TypeError:
2099 raise util.Abort('changeset references must be full hexadecimal '
2097 raise util.Abort('changeset references must be full hexadecimal '
2100 'node identifiers')
2098 'node identifiers')
2101
2099
2102 if precursor is not None:
2100 if precursor is not None:
2103 metadata = {}
2101 metadata = {}
2104 if 'date' in opts:
2102 if 'date' in opts:
2105 metadata['date'] = opts['date']
2103 metadata['date'] = opts['date']
2106 metadata['user'] = opts['user'] or ui.username()
2104 metadata['user'] = opts['user'] or ui.username()
2107 succs = tuple(parsenodeid(succ) for succ in successors)
2105 succs = tuple(parsenodeid(succ) for succ in successors)
2108 l = repo.lock()
2106 l = repo.lock()
2109 try:
2107 try:
2110 tr = repo.transaction('debugobsolete')
2108 tr = repo.transaction('debugobsolete')
2111 try:
2109 try:
2112 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2110 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2113 metadata)
2111 metadata)
2114 tr.close()
2112 tr.close()
2115 finally:
2113 finally:
2116 tr.release()
2114 tr.release()
2117 finally:
2115 finally:
2118 l.release()
2116 l.release()
2119 else:
2117 else:
2120 for m in obsolete.allmarkers(repo):
2118 for m in obsolete.allmarkers(repo):
2121 ui.write(hex(m.precnode()))
2119 ui.write(hex(m.precnode()))
2122 for repl in m.succnodes():
2120 for repl in m.succnodes():
2123 ui.write(' ')
2121 ui.write(' ')
2124 ui.write(hex(repl))
2122 ui.write(hex(repl))
2125 ui.write(' %X ' % m._data[2])
2123 ui.write(' %X ' % m._data[2])
2126 ui.write(m.metadata())
2124 ui.write(m.metadata())
2127 ui.write('\n')
2125 ui.write('\n')
2128
2126
2129 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2127 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2130 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2128 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2131 '''access the pushkey key/value protocol
2129 '''access the pushkey key/value protocol
2132
2130
2133 With two args, list the keys in the given namespace.
2131 With two args, list the keys in the given namespace.
2134
2132
2135 With five args, set a key to new if it currently is set to old.
2133 With five args, set a key to new if it currently is set to old.
2136 Reports success or failure.
2134 Reports success or failure.
2137 '''
2135 '''
2138
2136
2139 target = hg.peer(ui, {}, repopath)
2137 target = hg.peer(ui, {}, repopath)
2140 if keyinfo:
2138 if keyinfo:
2141 key, old, new = keyinfo
2139 key, old, new = keyinfo
2142 r = target.pushkey(namespace, key, old, new)
2140 r = target.pushkey(namespace, key, old, new)
2143 ui.status(str(r) + '\n')
2141 ui.status(str(r) + '\n')
2144 return not r
2142 return not r
2145 else:
2143 else:
2146 for k, v in target.listkeys(namespace).iteritems():
2144 for k, v in target.listkeys(namespace).iteritems():
2147 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2145 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2148 v.encode('string-escape')))
2146 v.encode('string-escape')))
2149
2147
2150 @command('debugpvec', [], _('A B'))
2148 @command('debugpvec', [], _('A B'))
2151 def debugpvec(ui, repo, a, b=None):
2149 def debugpvec(ui, repo, a, b=None):
2152 ca = scmutil.revsingle(repo, a)
2150 ca = scmutil.revsingle(repo, a)
2153 cb = scmutil.revsingle(repo, b)
2151 cb = scmutil.revsingle(repo, b)
2154 pa = pvec.ctxpvec(ca)
2152 pa = pvec.ctxpvec(ca)
2155 pb = pvec.ctxpvec(cb)
2153 pb = pvec.ctxpvec(cb)
2156 if pa == pb:
2154 if pa == pb:
2157 rel = "="
2155 rel = "="
2158 elif pa > pb:
2156 elif pa > pb:
2159 rel = ">"
2157 rel = ">"
2160 elif pa < pb:
2158 elif pa < pb:
2161 rel = "<"
2159 rel = "<"
2162 elif pa | pb:
2160 elif pa | pb:
2163 rel = "|"
2161 rel = "|"
2164 ui.write(_("a: %s\n") % pa)
2162 ui.write(_("a: %s\n") % pa)
2165 ui.write(_("b: %s\n") % pb)
2163 ui.write(_("b: %s\n") % pb)
2166 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2164 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2167 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2165 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2168 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2166 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2169 pa.distance(pb), rel))
2167 pa.distance(pb), rel))
2170
2168
2171 @command('debugrebuildstate',
2169 @command('debugrebuildstate',
2172 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2170 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2173 _('[-r REV] [REV]'))
2171 _('[-r REV] [REV]'))
2174 def debugrebuildstate(ui, repo, rev="tip"):
2172 def debugrebuildstate(ui, repo, rev="tip"):
2175 """rebuild the dirstate as it would look like for the given revision"""
2173 """rebuild the dirstate as it would look like for the given revision"""
2176 ctx = scmutil.revsingle(repo, rev)
2174 ctx = scmutil.revsingle(repo, rev)
2177 wlock = repo.wlock()
2175 wlock = repo.wlock()
2178 try:
2176 try:
2179 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2177 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2180 finally:
2178 finally:
2181 wlock.release()
2179 wlock.release()
2182
2180
2183 @command('debugrename',
2181 @command('debugrename',
2184 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2182 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2185 _('[-r REV] FILE'))
2183 _('[-r REV] FILE'))
2186 def debugrename(ui, repo, file1, *pats, **opts):
2184 def debugrename(ui, repo, file1, *pats, **opts):
2187 """dump rename information"""
2185 """dump rename information"""
2188
2186
2189 ctx = scmutil.revsingle(repo, opts.get('rev'))
2187 ctx = scmutil.revsingle(repo, opts.get('rev'))
2190 m = scmutil.match(ctx, (file1,) + pats, opts)
2188 m = scmutil.match(ctx, (file1,) + pats, opts)
2191 for abs in ctx.walk(m):
2189 for abs in ctx.walk(m):
2192 fctx = ctx[abs]
2190 fctx = ctx[abs]
2193 o = fctx.filelog().renamed(fctx.filenode())
2191 o = fctx.filelog().renamed(fctx.filenode())
2194 rel = m.rel(abs)
2192 rel = m.rel(abs)
2195 if o:
2193 if o:
2196 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2194 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2197 else:
2195 else:
2198 ui.write(_("%s not renamed\n") % rel)
2196 ui.write(_("%s not renamed\n") % rel)
2199
2197
2200 @command('debugrevlog',
2198 @command('debugrevlog',
2201 [('c', 'changelog', False, _('open changelog')),
2199 [('c', 'changelog', False, _('open changelog')),
2202 ('m', 'manifest', False, _('open manifest')),
2200 ('m', 'manifest', False, _('open manifest')),
2203 ('d', 'dump', False, _('dump index data'))],
2201 ('d', 'dump', False, _('dump index data'))],
2204 _('-c|-m|FILE'))
2202 _('-c|-m|FILE'))
2205 def debugrevlog(ui, repo, file_ = None, **opts):
2203 def debugrevlog(ui, repo, file_ = None, **opts):
2206 """show data and statistics about a revlog"""
2204 """show data and statistics about a revlog"""
2207 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2205 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2208
2206
2209 if opts.get("dump"):
2207 if opts.get("dump"):
2210 numrevs = len(r)
2208 numrevs = len(r)
2211 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2209 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2212 " rawsize totalsize compression heads\n")
2210 " rawsize totalsize compression heads\n")
2213 ts = 0
2211 ts = 0
2214 heads = set()
2212 heads = set()
2215 for rev in xrange(numrevs):
2213 for rev in xrange(numrevs):
2216 dbase = r.deltaparent(rev)
2214 dbase = r.deltaparent(rev)
2217 if dbase == -1:
2215 if dbase == -1:
2218 dbase = rev
2216 dbase = rev
2219 cbase = r.chainbase(rev)
2217 cbase = r.chainbase(rev)
2220 p1, p2 = r.parentrevs(rev)
2218 p1, p2 = r.parentrevs(rev)
2221 rs = r.rawsize(rev)
2219 rs = r.rawsize(rev)
2222 ts = ts + rs
2220 ts = ts + rs
2223 heads -= set(r.parentrevs(rev))
2221 heads -= set(r.parentrevs(rev))
2224 heads.add(rev)
2222 heads.add(rev)
2225 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2223 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2226 (rev, p1, p2, r.start(rev), r.end(rev),
2224 (rev, p1, p2, r.start(rev), r.end(rev),
2227 r.start(dbase), r.start(cbase),
2225 r.start(dbase), r.start(cbase),
2228 r.start(p1), r.start(p2),
2226 r.start(p1), r.start(p2),
2229 rs, ts, ts / r.end(rev), len(heads)))
2227 rs, ts, ts / r.end(rev), len(heads)))
2230 return 0
2228 return 0
2231
2229
2232 v = r.version
2230 v = r.version
2233 format = v & 0xFFFF
2231 format = v & 0xFFFF
2234 flags = []
2232 flags = []
2235 gdelta = False
2233 gdelta = False
2236 if v & revlog.REVLOGNGINLINEDATA:
2234 if v & revlog.REVLOGNGINLINEDATA:
2237 flags.append('inline')
2235 flags.append('inline')
2238 if v & revlog.REVLOGGENERALDELTA:
2236 if v & revlog.REVLOGGENERALDELTA:
2239 gdelta = True
2237 gdelta = True
2240 flags.append('generaldelta')
2238 flags.append('generaldelta')
2241 if not flags:
2239 if not flags:
2242 flags = ['(none)']
2240 flags = ['(none)']
2243
2241
2244 nummerges = 0
2242 nummerges = 0
2245 numfull = 0
2243 numfull = 0
2246 numprev = 0
2244 numprev = 0
2247 nump1 = 0
2245 nump1 = 0
2248 nump2 = 0
2246 nump2 = 0
2249 numother = 0
2247 numother = 0
2250 nump1prev = 0
2248 nump1prev = 0
2251 nump2prev = 0
2249 nump2prev = 0
2252 chainlengths = []
2250 chainlengths = []
2253
2251
2254 datasize = [None, 0, 0L]
2252 datasize = [None, 0, 0L]
2255 fullsize = [None, 0, 0L]
2253 fullsize = [None, 0, 0L]
2256 deltasize = [None, 0, 0L]
2254 deltasize = [None, 0, 0L]
2257
2255
2258 def addsize(size, l):
2256 def addsize(size, l):
2259 if l[0] is None or size < l[0]:
2257 if l[0] is None or size < l[0]:
2260 l[0] = size
2258 l[0] = size
2261 if size > l[1]:
2259 if size > l[1]:
2262 l[1] = size
2260 l[1] = size
2263 l[2] += size
2261 l[2] += size
2264
2262
2265 numrevs = len(r)
2263 numrevs = len(r)
2266 for rev in xrange(numrevs):
2264 for rev in xrange(numrevs):
2267 p1, p2 = r.parentrevs(rev)
2265 p1, p2 = r.parentrevs(rev)
2268 delta = r.deltaparent(rev)
2266 delta = r.deltaparent(rev)
2269 if format > 0:
2267 if format > 0:
2270 addsize(r.rawsize(rev), datasize)
2268 addsize(r.rawsize(rev), datasize)
2271 if p2 != nullrev:
2269 if p2 != nullrev:
2272 nummerges += 1
2270 nummerges += 1
2273 size = r.length(rev)
2271 size = r.length(rev)
2274 if delta == nullrev:
2272 if delta == nullrev:
2275 chainlengths.append(0)
2273 chainlengths.append(0)
2276 numfull += 1
2274 numfull += 1
2277 addsize(size, fullsize)
2275 addsize(size, fullsize)
2278 else:
2276 else:
2279 chainlengths.append(chainlengths[delta] + 1)
2277 chainlengths.append(chainlengths[delta] + 1)
2280 addsize(size, deltasize)
2278 addsize(size, deltasize)
2281 if delta == rev - 1:
2279 if delta == rev - 1:
2282 numprev += 1
2280 numprev += 1
2283 if delta == p1:
2281 if delta == p1:
2284 nump1prev += 1
2282 nump1prev += 1
2285 elif delta == p2:
2283 elif delta == p2:
2286 nump2prev += 1
2284 nump2prev += 1
2287 elif delta == p1:
2285 elif delta == p1:
2288 nump1 += 1
2286 nump1 += 1
2289 elif delta == p2:
2287 elif delta == p2:
2290 nump2 += 1
2288 nump2 += 1
2291 elif delta != nullrev:
2289 elif delta != nullrev:
2292 numother += 1
2290 numother += 1
2293
2291
2294 # Adjust size min value for empty cases
2292 # Adjust size min value for empty cases
2295 for size in (datasize, fullsize, deltasize):
2293 for size in (datasize, fullsize, deltasize):
2296 if size[0] is None:
2294 if size[0] is None:
2297 size[0] = 0
2295 size[0] = 0
2298
2296
2299 numdeltas = numrevs - numfull
2297 numdeltas = numrevs - numfull
2300 numoprev = numprev - nump1prev - nump2prev
2298 numoprev = numprev - nump1prev - nump2prev
2301 totalrawsize = datasize[2]
2299 totalrawsize = datasize[2]
2302 datasize[2] /= numrevs
2300 datasize[2] /= numrevs
2303 fulltotal = fullsize[2]
2301 fulltotal = fullsize[2]
2304 fullsize[2] /= numfull
2302 fullsize[2] /= numfull
2305 deltatotal = deltasize[2]
2303 deltatotal = deltasize[2]
2306 if numrevs - numfull > 0:
2304 if numrevs - numfull > 0:
2307 deltasize[2] /= numrevs - numfull
2305 deltasize[2] /= numrevs - numfull
2308 totalsize = fulltotal + deltatotal
2306 totalsize = fulltotal + deltatotal
2309 avgchainlen = sum(chainlengths) / numrevs
2307 avgchainlen = sum(chainlengths) / numrevs
2310 compratio = totalrawsize / totalsize
2308 compratio = totalrawsize / totalsize
2311
2309
2312 basedfmtstr = '%%%dd\n'
2310 basedfmtstr = '%%%dd\n'
2313 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2311 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2314
2312
2315 def dfmtstr(max):
2313 def dfmtstr(max):
2316 return basedfmtstr % len(str(max))
2314 return basedfmtstr % len(str(max))
2317 def pcfmtstr(max, padding=0):
2315 def pcfmtstr(max, padding=0):
2318 return basepcfmtstr % (len(str(max)), ' ' * padding)
2316 return basepcfmtstr % (len(str(max)), ' ' * padding)
2319
2317
2320 def pcfmt(value, total):
2318 def pcfmt(value, total):
2321 return (value, 100 * float(value) / total)
2319 return (value, 100 * float(value) / total)
2322
2320
2323 ui.write('format : %d\n' % format)
2321 ui.write('format : %d\n' % format)
2324 ui.write('flags : %s\n' % ', '.join(flags))
2322 ui.write('flags : %s\n' % ', '.join(flags))
2325
2323
2326 ui.write('\n')
2324 ui.write('\n')
2327 fmt = pcfmtstr(totalsize)
2325 fmt = pcfmtstr(totalsize)
2328 fmt2 = dfmtstr(totalsize)
2326 fmt2 = dfmtstr(totalsize)
2329 ui.write('revisions : ' + fmt2 % numrevs)
2327 ui.write('revisions : ' + fmt2 % numrevs)
2330 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2328 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2331 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2329 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2332 ui.write('revisions : ' + fmt2 % numrevs)
2330 ui.write('revisions : ' + fmt2 % numrevs)
2333 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2331 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2334 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2332 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2335 ui.write('revision size : ' + fmt2 % totalsize)
2333 ui.write('revision size : ' + fmt2 % totalsize)
2336 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2334 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2337 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2335 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2338
2336
2339 ui.write('\n')
2337 ui.write('\n')
2340 fmt = dfmtstr(max(avgchainlen, compratio))
2338 fmt = dfmtstr(max(avgchainlen, compratio))
2341 ui.write('avg chain length : ' + fmt % avgchainlen)
2339 ui.write('avg chain length : ' + fmt % avgchainlen)
2342 ui.write('compression ratio : ' + fmt % compratio)
2340 ui.write('compression ratio : ' + fmt % compratio)
2343
2341
2344 if format > 0:
2342 if format > 0:
2345 ui.write('\n')
2343 ui.write('\n')
2346 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2344 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2347 % tuple(datasize))
2345 % tuple(datasize))
2348 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2346 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2349 % tuple(fullsize))
2347 % tuple(fullsize))
2350 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2348 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2351 % tuple(deltasize))
2349 % tuple(deltasize))
2352
2350
2353 if numdeltas > 0:
2351 if numdeltas > 0:
2354 ui.write('\n')
2352 ui.write('\n')
2355 fmt = pcfmtstr(numdeltas)
2353 fmt = pcfmtstr(numdeltas)
2356 fmt2 = pcfmtstr(numdeltas, 4)
2354 fmt2 = pcfmtstr(numdeltas, 4)
2357 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2355 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2358 if numprev > 0:
2356 if numprev > 0:
2359 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2357 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2360 numprev))
2358 numprev))
2361 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2359 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2362 numprev))
2360 numprev))
2363 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2361 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2364 numprev))
2362 numprev))
2365 if gdelta:
2363 if gdelta:
2366 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2364 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2367 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2365 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2368 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2366 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2369 numdeltas))
2367 numdeltas))
2370
2368
2371 @command('debugrevspec', [], ('REVSPEC'))
2369 @command('debugrevspec', [], ('REVSPEC'))
2372 def debugrevspec(ui, repo, expr):
2370 def debugrevspec(ui, repo, expr):
2373 """parse and apply a revision specification
2371 """parse and apply a revision specification
2374
2372
2375 Use --verbose to print the parsed tree before and after aliases
2373 Use --verbose to print the parsed tree before and after aliases
2376 expansion.
2374 expansion.
2377 """
2375 """
2378 if ui.verbose:
2376 if ui.verbose:
2379 tree = revset.parse(expr)[0]
2377 tree = revset.parse(expr)[0]
2380 ui.note(revset.prettyformat(tree), "\n")
2378 ui.note(revset.prettyformat(tree), "\n")
2381 newtree = revset.findaliases(ui, tree)
2379 newtree = revset.findaliases(ui, tree)
2382 if newtree != tree:
2380 if newtree != tree:
2383 ui.note(revset.prettyformat(newtree), "\n")
2381 ui.note(revset.prettyformat(newtree), "\n")
2384 func = revset.match(ui, expr)
2382 func = revset.match(ui, expr)
2385 for c in func(repo, range(len(repo))):
2383 for c in func(repo, range(len(repo))):
2386 ui.write("%s\n" % c)
2384 ui.write("%s\n" % c)
2387
2385
2388 @command('debugsetparents', [], _('REV1 [REV2]'))
2386 @command('debugsetparents', [], _('REV1 [REV2]'))
2389 def debugsetparents(ui, repo, rev1, rev2=None):
2387 def debugsetparents(ui, repo, rev1, rev2=None):
2390 """manually set the parents of the current working directory
2388 """manually set the parents of the current working directory
2391
2389
2392 This is useful for writing repository conversion tools, but should
2390 This is useful for writing repository conversion tools, but should
2393 be used with care.
2391 be used with care.
2394
2392
2395 Returns 0 on success.
2393 Returns 0 on success.
2396 """
2394 """
2397
2395
2398 r1 = scmutil.revsingle(repo, rev1).node()
2396 r1 = scmutil.revsingle(repo, rev1).node()
2399 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2397 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2400
2398
2401 wlock = repo.wlock()
2399 wlock = repo.wlock()
2402 try:
2400 try:
2403 repo.setparents(r1, r2)
2401 repo.setparents(r1, r2)
2404 finally:
2402 finally:
2405 wlock.release()
2403 wlock.release()
2406
2404
2407 @command('debugstate',
2405 @command('debugstate',
2408 [('', 'nodates', None, _('do not display the saved mtime')),
2406 [('', 'nodates', None, _('do not display the saved mtime')),
2409 ('', 'datesort', None, _('sort by saved mtime'))],
2407 ('', 'datesort', None, _('sort by saved mtime'))],
2410 _('[OPTION]...'))
2408 _('[OPTION]...'))
2411 def debugstate(ui, repo, nodates=None, datesort=None):
2409 def debugstate(ui, repo, nodates=None, datesort=None):
2412 """show the contents of the current dirstate"""
2410 """show the contents of the current dirstate"""
2413 timestr = ""
2411 timestr = ""
2414 showdate = not nodates
2412 showdate = not nodates
2415 if datesort:
2413 if datesort:
2416 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2414 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2417 else:
2415 else:
2418 keyfunc = None # sort by filename
2416 keyfunc = None # sort by filename
2419 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2417 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2420 if showdate:
2418 if showdate:
2421 if ent[3] == -1:
2419 if ent[3] == -1:
2422 # Pad or slice to locale representation
2420 # Pad or slice to locale representation
2423 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2421 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2424 time.localtime(0)))
2422 time.localtime(0)))
2425 timestr = 'unset'
2423 timestr = 'unset'
2426 timestr = (timestr[:locale_len] +
2424 timestr = (timestr[:locale_len] +
2427 ' ' * (locale_len - len(timestr)))
2425 ' ' * (locale_len - len(timestr)))
2428 else:
2426 else:
2429 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2427 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2430 time.localtime(ent[3]))
2428 time.localtime(ent[3]))
2431 if ent[1] & 020000:
2429 if ent[1] & 020000:
2432 mode = 'lnk'
2430 mode = 'lnk'
2433 else:
2431 else:
2434 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2432 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2435 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2433 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2436 for f in repo.dirstate.copies():
2434 for f in repo.dirstate.copies():
2437 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2435 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2438
2436
2439 @command('debugsub',
2437 @command('debugsub',
2440 [('r', 'rev', '',
2438 [('r', 'rev', '',
2441 _('revision to check'), _('REV'))],
2439 _('revision to check'), _('REV'))],
2442 _('[-r REV] [REV]'))
2440 _('[-r REV] [REV]'))
2443 def debugsub(ui, repo, rev=None):
2441 def debugsub(ui, repo, rev=None):
2444 ctx = scmutil.revsingle(repo, rev, None)
2442 ctx = scmutil.revsingle(repo, rev, None)
2445 for k, v in sorted(ctx.substate.items()):
2443 for k, v in sorted(ctx.substate.items()):
2446 ui.write('path %s\n' % k)
2444 ui.write('path %s\n' % k)
2447 ui.write(' source %s\n' % v[0])
2445 ui.write(' source %s\n' % v[0])
2448 ui.write(' revision %s\n' % v[1])
2446 ui.write(' revision %s\n' % v[1])
2449
2447
2450 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2448 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2451 def debugwalk(ui, repo, *pats, **opts):
2449 def debugwalk(ui, repo, *pats, **opts):
2452 """show how files match on given patterns"""
2450 """show how files match on given patterns"""
2453 m = scmutil.match(repo[None], pats, opts)
2451 m = scmutil.match(repo[None], pats, opts)
2454 items = list(repo.walk(m))
2452 items = list(repo.walk(m))
2455 if not items:
2453 if not items:
2456 return
2454 return
2457 f = lambda fn: fn
2455 f = lambda fn: fn
2458 if ui.configbool('ui', 'slash') and os.sep != '/':
2456 if ui.configbool('ui', 'slash') and os.sep != '/':
2459 f = lambda fn: util.normpath(fn)
2457 f = lambda fn: util.normpath(fn)
2460 fmt = 'f %%-%ds %%-%ds %%s' % (
2458 fmt = 'f %%-%ds %%-%ds %%s' % (
2461 max([len(abs) for abs in items]),
2459 max([len(abs) for abs in items]),
2462 max([len(m.rel(abs)) for abs in items]))
2460 max([len(m.rel(abs)) for abs in items]))
2463 for abs in items:
2461 for abs in items:
2464 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2462 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2465 ui.write("%s\n" % line.rstrip())
2463 ui.write("%s\n" % line.rstrip())
2466
2464
2467 @command('debugwireargs',
2465 @command('debugwireargs',
2468 [('', 'three', '', 'three'),
2466 [('', 'three', '', 'three'),
2469 ('', 'four', '', 'four'),
2467 ('', 'four', '', 'four'),
2470 ('', 'five', '', 'five'),
2468 ('', 'five', '', 'five'),
2471 ] + remoteopts,
2469 ] + remoteopts,
2472 _('REPO [OPTIONS]... [ONE [TWO]]'))
2470 _('REPO [OPTIONS]... [ONE [TWO]]'))
2473 def debugwireargs(ui, repopath, *vals, **opts):
2471 def debugwireargs(ui, repopath, *vals, **opts):
2474 repo = hg.peer(ui, opts, repopath)
2472 repo = hg.peer(ui, opts, repopath)
2475 for opt in remoteopts:
2473 for opt in remoteopts:
2476 del opts[opt[1]]
2474 del opts[opt[1]]
2477 args = {}
2475 args = {}
2478 for k, v in opts.iteritems():
2476 for k, v in opts.iteritems():
2479 if v:
2477 if v:
2480 args[k] = v
2478 args[k] = v
2481 # run twice to check that we don't mess up the stream for the next command
2479 # run twice to check that we don't mess up the stream for the next command
2482 res1 = repo.debugwireargs(*vals, **args)
2480 res1 = repo.debugwireargs(*vals, **args)
2483 res2 = repo.debugwireargs(*vals, **args)
2481 res2 = repo.debugwireargs(*vals, **args)
2484 ui.write("%s\n" % res1)
2482 ui.write("%s\n" % res1)
2485 if res1 != res2:
2483 if res1 != res2:
2486 ui.warn("%s\n" % res2)
2484 ui.warn("%s\n" % res2)
2487
2485
2488 @command('^diff',
2486 @command('^diff',
2489 [('r', 'rev', [], _('revision'), _('REV')),
2487 [('r', 'rev', [], _('revision'), _('REV')),
2490 ('c', 'change', '', _('change made by revision'), _('REV'))
2488 ('c', 'change', '', _('change made by revision'), _('REV'))
2491 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2489 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2492 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2490 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2493 def diff(ui, repo, *pats, **opts):
2491 def diff(ui, repo, *pats, **opts):
2494 """diff repository (or selected files)
2492 """diff repository (or selected files)
2495
2493
2496 Show differences between revisions for the specified files.
2494 Show differences between revisions for the specified files.
2497
2495
2498 Differences between files are shown using the unified diff format.
2496 Differences between files are shown using the unified diff format.
2499
2497
2500 .. note::
2498 .. note::
2501 diff may generate unexpected results for merges, as it will
2499 diff may generate unexpected results for merges, as it will
2502 default to comparing against the working directory's first
2500 default to comparing against the working directory's first
2503 parent changeset if no revisions are specified.
2501 parent changeset if no revisions are specified.
2504
2502
2505 When two revision arguments are given, then changes are shown
2503 When two revision arguments are given, then changes are shown
2506 between those revisions. If only one revision is specified then
2504 between those revisions. If only one revision is specified then
2507 that revision is compared to the working directory, and, when no
2505 that revision is compared to the working directory, and, when no
2508 revisions are specified, the working directory files are compared
2506 revisions are specified, the working directory files are compared
2509 to its parent.
2507 to its parent.
2510
2508
2511 Alternatively you can specify -c/--change with a revision to see
2509 Alternatively you can specify -c/--change with a revision to see
2512 the changes in that changeset relative to its first parent.
2510 the changes in that changeset relative to its first parent.
2513
2511
2514 Without the -a/--text option, diff will avoid generating diffs of
2512 Without the -a/--text option, diff will avoid generating diffs of
2515 files it detects as binary. With -a, diff will generate a diff
2513 files it detects as binary. With -a, diff will generate a diff
2516 anyway, probably with undesirable results.
2514 anyway, probably with undesirable results.
2517
2515
2518 Use the -g/--git option to generate diffs in the git extended diff
2516 Use the -g/--git option to generate diffs in the git extended diff
2519 format. For more information, read :hg:`help diffs`.
2517 format. For more information, read :hg:`help diffs`.
2520
2518
2521 .. container:: verbose
2519 .. container:: verbose
2522
2520
2523 Examples:
2521 Examples:
2524
2522
2525 - compare a file in the current working directory to its parent::
2523 - compare a file in the current working directory to its parent::
2526
2524
2527 hg diff foo.c
2525 hg diff foo.c
2528
2526
2529 - compare two historical versions of a directory, with rename info::
2527 - compare two historical versions of a directory, with rename info::
2530
2528
2531 hg diff --git -r 1.0:1.2 lib/
2529 hg diff --git -r 1.0:1.2 lib/
2532
2530
2533 - get change stats relative to the last change on some date::
2531 - get change stats relative to the last change on some date::
2534
2532
2535 hg diff --stat -r "date('may 2')"
2533 hg diff --stat -r "date('may 2')"
2536
2534
2537 - diff all newly-added files that contain a keyword::
2535 - diff all newly-added files that contain a keyword::
2538
2536
2539 hg diff "set:added() and grep(GNU)"
2537 hg diff "set:added() and grep(GNU)"
2540
2538
2541 - compare a revision and its parents::
2539 - compare a revision and its parents::
2542
2540
2543 hg diff -c 9353 # compare against first parent
2541 hg diff -c 9353 # compare against first parent
2544 hg diff -r 9353^:9353 # same using revset syntax
2542 hg diff -r 9353^:9353 # same using revset syntax
2545 hg diff -r 9353^2:9353 # compare against the second parent
2543 hg diff -r 9353^2:9353 # compare against the second parent
2546
2544
2547 Returns 0 on success.
2545 Returns 0 on success.
2548 """
2546 """
2549
2547
2550 revs = opts.get('rev')
2548 revs = opts.get('rev')
2551 change = opts.get('change')
2549 change = opts.get('change')
2552 stat = opts.get('stat')
2550 stat = opts.get('stat')
2553 reverse = opts.get('reverse')
2551 reverse = opts.get('reverse')
2554
2552
2555 if revs and change:
2553 if revs and change:
2556 msg = _('cannot specify --rev and --change at the same time')
2554 msg = _('cannot specify --rev and --change at the same time')
2557 raise util.Abort(msg)
2555 raise util.Abort(msg)
2558 elif change:
2556 elif change:
2559 node2 = scmutil.revsingle(repo, change, None).node()
2557 node2 = scmutil.revsingle(repo, change, None).node()
2560 node1 = repo[node2].p1().node()
2558 node1 = repo[node2].p1().node()
2561 else:
2559 else:
2562 node1, node2 = scmutil.revpair(repo, revs)
2560 node1, node2 = scmutil.revpair(repo, revs)
2563
2561
2564 if reverse:
2562 if reverse:
2565 node1, node2 = node2, node1
2563 node1, node2 = node2, node1
2566
2564
2567 diffopts = patch.diffopts(ui, opts)
2565 diffopts = patch.diffopts(ui, opts)
2568 m = scmutil.match(repo[node2], pats, opts)
2566 m = scmutil.match(repo[node2], pats, opts)
2569 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2567 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2570 listsubrepos=opts.get('subrepos'))
2568 listsubrepos=opts.get('subrepos'))
2571
2569
2572 @command('^export',
2570 @command('^export',
2573 [('o', 'output', '',
2571 [('o', 'output', '',
2574 _('print output to file with formatted name'), _('FORMAT')),
2572 _('print output to file with formatted name'), _('FORMAT')),
2575 ('', 'switch-parent', None, _('diff against the second parent')),
2573 ('', 'switch-parent', None, _('diff against the second parent')),
2576 ('r', 'rev', [], _('revisions to export'), _('REV')),
2574 ('r', 'rev', [], _('revisions to export'), _('REV')),
2577 ] + diffopts,
2575 ] + diffopts,
2578 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2576 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2579 def export(ui, repo, *changesets, **opts):
2577 def export(ui, repo, *changesets, **opts):
2580 """dump the header and diffs for one or more changesets
2578 """dump the header and diffs for one or more changesets
2581
2579
2582 Print the changeset header and diffs for one or more revisions.
2580 Print the changeset header and diffs for one or more revisions.
2583
2581
2584 The information shown in the changeset header is: author, date,
2582 The information shown in the changeset header is: author, date,
2585 branch name (if non-default), changeset hash, parent(s) and commit
2583 branch name (if non-default), changeset hash, parent(s) and commit
2586 comment.
2584 comment.
2587
2585
2588 .. note::
2586 .. note::
2589 export may generate unexpected diff output for merge
2587 export may generate unexpected diff output for merge
2590 changesets, as it will compare the merge changeset against its
2588 changesets, as it will compare the merge changeset against its
2591 first parent only.
2589 first parent only.
2592
2590
2593 Output may be to a file, in which case the name of the file is
2591 Output may be to a file, in which case the name of the file is
2594 given using a format string. The formatting rules are as follows:
2592 given using a format string. The formatting rules are as follows:
2595
2593
2596 :``%%``: literal "%" character
2594 :``%%``: literal "%" character
2597 :``%H``: changeset hash (40 hexadecimal digits)
2595 :``%H``: changeset hash (40 hexadecimal digits)
2598 :``%N``: number of patches being generated
2596 :``%N``: number of patches being generated
2599 :``%R``: changeset revision number
2597 :``%R``: changeset revision number
2600 :``%b``: basename of the exporting repository
2598 :``%b``: basename of the exporting repository
2601 :``%h``: short-form changeset hash (12 hexadecimal digits)
2599 :``%h``: short-form changeset hash (12 hexadecimal digits)
2602 :``%m``: first line of the commit message (only alphanumeric characters)
2600 :``%m``: first line of the commit message (only alphanumeric characters)
2603 :``%n``: zero-padded sequence number, starting at 1
2601 :``%n``: zero-padded sequence number, starting at 1
2604 :``%r``: zero-padded changeset revision number
2602 :``%r``: zero-padded changeset revision number
2605
2603
2606 Without the -a/--text option, export will avoid generating diffs
2604 Without the -a/--text option, export will avoid generating diffs
2607 of files it detects as binary. With -a, export will generate a
2605 of files it detects as binary. With -a, export will generate a
2608 diff anyway, probably with undesirable results.
2606 diff anyway, probably with undesirable results.
2609
2607
2610 Use the -g/--git option to generate diffs in the git extended diff
2608 Use the -g/--git option to generate diffs in the git extended diff
2611 format. See :hg:`help diffs` for more information.
2609 format. See :hg:`help diffs` for more information.
2612
2610
2613 With the --switch-parent option, the diff will be against the
2611 With the --switch-parent option, the diff will be against the
2614 second parent. It can be useful to review a merge.
2612 second parent. It can be useful to review a merge.
2615
2613
2616 .. container:: verbose
2614 .. container:: verbose
2617
2615
2618 Examples:
2616 Examples:
2619
2617
2620 - use export and import to transplant a bugfix to the current
2618 - use export and import to transplant a bugfix to the current
2621 branch::
2619 branch::
2622
2620
2623 hg export -r 9353 | hg import -
2621 hg export -r 9353 | hg import -
2624
2622
2625 - export all the changesets between two revisions to a file with
2623 - export all the changesets between two revisions to a file with
2626 rename information::
2624 rename information::
2627
2625
2628 hg export --git -r 123:150 > changes.txt
2626 hg export --git -r 123:150 > changes.txt
2629
2627
2630 - split outgoing changes into a series of patches with
2628 - split outgoing changes into a series of patches with
2631 descriptive names::
2629 descriptive names::
2632
2630
2633 hg export -r "outgoing()" -o "%n-%m.patch"
2631 hg export -r "outgoing()" -o "%n-%m.patch"
2634
2632
2635 Returns 0 on success.
2633 Returns 0 on success.
2636 """
2634 """
2637 changesets += tuple(opts.get('rev', []))
2635 changesets += tuple(opts.get('rev', []))
2638 revs = scmutil.revrange(repo, changesets)
2636 revs = scmutil.revrange(repo, changesets)
2639 if not revs:
2637 if not revs:
2640 raise util.Abort(_("export requires at least one changeset"))
2638 raise util.Abort(_("export requires at least one changeset"))
2641 if len(revs) > 1:
2639 if len(revs) > 1:
2642 ui.note(_('exporting patches:\n'))
2640 ui.note(_('exporting patches:\n'))
2643 else:
2641 else:
2644 ui.note(_('exporting patch:\n'))
2642 ui.note(_('exporting patch:\n'))
2645 cmdutil.export(repo, revs, template=opts.get('output'),
2643 cmdutil.export(repo, revs, template=opts.get('output'),
2646 switch_parent=opts.get('switch_parent'),
2644 switch_parent=opts.get('switch_parent'),
2647 opts=patch.diffopts(ui, opts))
2645 opts=patch.diffopts(ui, opts))
2648
2646
2649 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2647 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2650 def forget(ui, repo, *pats, **opts):
2648 def forget(ui, repo, *pats, **opts):
2651 """forget the specified files on the next commit
2649 """forget the specified files on the next commit
2652
2650
2653 Mark the specified files so they will no longer be tracked
2651 Mark the specified files so they will no longer be tracked
2654 after the next commit.
2652 after the next commit.
2655
2653
2656 This only removes files from the current branch, not from the
2654 This only removes files from the current branch, not from the
2657 entire project history, and it does not delete them from the
2655 entire project history, and it does not delete them from the
2658 working directory.
2656 working directory.
2659
2657
2660 To undo a forget before the next commit, see :hg:`add`.
2658 To undo a forget before the next commit, see :hg:`add`.
2661
2659
2662 .. container:: verbose
2660 .. container:: verbose
2663
2661
2664 Examples:
2662 Examples:
2665
2663
2666 - forget newly-added binary files::
2664 - forget newly-added binary files::
2667
2665
2668 hg forget "set:added() and binary()"
2666 hg forget "set:added() and binary()"
2669
2667
2670 - forget files that would be excluded by .hgignore::
2668 - forget files that would be excluded by .hgignore::
2671
2669
2672 hg forget "set:hgignore()"
2670 hg forget "set:hgignore()"
2673
2671
2674 Returns 0 on success.
2672 Returns 0 on success.
2675 """
2673 """
2676
2674
2677 if not pats:
2675 if not pats:
2678 raise util.Abort(_('no files specified'))
2676 raise util.Abort(_('no files specified'))
2679
2677
2680 m = scmutil.match(repo[None], pats, opts)
2678 m = scmutil.match(repo[None], pats, opts)
2681 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2679 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2682 return rejected and 1 or 0
2680 return rejected and 1 or 0
2683
2681
2684 @command(
2682 @command(
2685 'graft',
2683 'graft',
2686 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2684 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2687 ('c', 'continue', False, _('resume interrupted graft')),
2685 ('c', 'continue', False, _('resume interrupted graft')),
2688 ('e', 'edit', False, _('invoke editor on commit messages')),
2686 ('e', 'edit', False, _('invoke editor on commit messages')),
2689 ('', 'log', None, _('append graft info to log message')),
2687 ('', 'log', None, _('append graft info to log message')),
2690 ('D', 'currentdate', False,
2688 ('D', 'currentdate', False,
2691 _('record the current date as commit date')),
2689 _('record the current date as commit date')),
2692 ('U', 'currentuser', False,
2690 ('U', 'currentuser', False,
2693 _('record the current user as committer'), _('DATE'))]
2691 _('record the current user as committer'), _('DATE'))]
2694 + commitopts2 + mergetoolopts + dryrunopts,
2692 + commitopts2 + mergetoolopts + dryrunopts,
2695 _('[OPTION]... [-r] REV...'))
2693 _('[OPTION]... [-r] REV...'))
2696 def graft(ui, repo, *revs, **opts):
2694 def graft(ui, repo, *revs, **opts):
2697 '''copy changes from other branches onto the current branch
2695 '''copy changes from other branches onto the current branch
2698
2696
2699 This command uses Mercurial's merge logic to copy individual
2697 This command uses Mercurial's merge logic to copy individual
2700 changes from other branches without merging branches in the
2698 changes from other branches without merging branches in the
2701 history graph. This is sometimes known as 'backporting' or
2699 history graph. This is sometimes known as 'backporting' or
2702 'cherry-picking'. By default, graft will copy user, date, and
2700 'cherry-picking'. By default, graft will copy user, date, and
2703 description from the source changesets.
2701 description from the source changesets.
2704
2702
2705 Changesets that are ancestors of the current revision, that have
2703 Changesets that are ancestors of the current revision, that have
2706 already been grafted, or that are merges will be skipped.
2704 already been grafted, or that are merges will be skipped.
2707
2705
2708 If --log is specified, log messages will have a comment appended
2706 If --log is specified, log messages will have a comment appended
2709 of the form::
2707 of the form::
2710
2708
2711 (grafted from CHANGESETHASH)
2709 (grafted from CHANGESETHASH)
2712
2710
2713 If a graft merge results in conflicts, the graft process is
2711 If a graft merge results in conflicts, the graft process is
2714 interrupted so that the current merge can be manually resolved.
2712 interrupted so that the current merge can be manually resolved.
2715 Once all conflicts are addressed, the graft process can be
2713 Once all conflicts are addressed, the graft process can be
2716 continued with the -c/--continue option.
2714 continued with the -c/--continue option.
2717
2715
2718 .. note::
2716 .. note::
2719 The -c/--continue option does not reapply earlier options.
2717 The -c/--continue option does not reapply earlier options.
2720
2718
2721 .. container:: verbose
2719 .. container:: verbose
2722
2720
2723 Examples:
2721 Examples:
2724
2722
2725 - copy a single change to the stable branch and edit its description::
2723 - copy a single change to the stable branch and edit its description::
2726
2724
2727 hg update stable
2725 hg update stable
2728 hg graft --edit 9393
2726 hg graft --edit 9393
2729
2727
2730 - graft a range of changesets with one exception, updating dates::
2728 - graft a range of changesets with one exception, updating dates::
2731
2729
2732 hg graft -D "2085::2093 and not 2091"
2730 hg graft -D "2085::2093 and not 2091"
2733
2731
2734 - continue a graft after resolving conflicts::
2732 - continue a graft after resolving conflicts::
2735
2733
2736 hg graft -c
2734 hg graft -c
2737
2735
2738 - show the source of a grafted changeset::
2736 - show the source of a grafted changeset::
2739
2737
2740 hg log --debug -r tip
2738 hg log --debug -r tip
2741
2739
2742 Returns 0 on successful completion.
2740 Returns 0 on successful completion.
2743 '''
2741 '''
2744
2742
2745 revs = list(revs)
2743 revs = list(revs)
2746 revs.extend(opts['rev'])
2744 revs.extend(opts['rev'])
2747
2745
2748 if not opts.get('user') and opts.get('currentuser'):
2746 if not opts.get('user') and opts.get('currentuser'):
2749 opts['user'] = ui.username()
2747 opts['user'] = ui.username()
2750 if not opts.get('date') and opts.get('currentdate'):
2748 if not opts.get('date') and opts.get('currentdate'):
2751 opts['date'] = "%d %d" % util.makedate()
2749 opts['date'] = "%d %d" % util.makedate()
2752
2750
2753 editor = None
2751 editor = None
2754 if opts.get('edit'):
2752 if opts.get('edit'):
2755 editor = cmdutil.commitforceeditor
2753 editor = cmdutil.commitforceeditor
2756
2754
2757 cont = False
2755 cont = False
2758 if opts['continue']:
2756 if opts['continue']:
2759 cont = True
2757 cont = True
2760 if revs:
2758 if revs:
2761 raise util.Abort(_("can't specify --continue and revisions"))
2759 raise util.Abort(_("can't specify --continue and revisions"))
2762 # read in unfinished revisions
2760 # read in unfinished revisions
2763 try:
2761 try:
2764 nodes = repo.opener.read('graftstate').splitlines()
2762 nodes = repo.opener.read('graftstate').splitlines()
2765 revs = [repo[node].rev() for node in nodes]
2763 revs = [repo[node].rev() for node in nodes]
2766 except IOError, inst:
2764 except IOError, inst:
2767 if inst.errno != errno.ENOENT:
2765 if inst.errno != errno.ENOENT:
2768 raise
2766 raise
2769 raise util.Abort(_("no graft state found, can't continue"))
2767 raise util.Abort(_("no graft state found, can't continue"))
2770 else:
2768 else:
2771 cmdutil.bailifchanged(repo)
2769 cmdutil.bailifchanged(repo)
2772 if not revs:
2770 if not revs:
2773 raise util.Abort(_('no revisions specified'))
2771 raise util.Abort(_('no revisions specified'))
2774 revs = scmutil.revrange(repo, revs)
2772 revs = scmutil.revrange(repo, revs)
2775
2773
2776 # check for merges
2774 # check for merges
2777 for rev in repo.revs('%ld and merge()', revs):
2775 for rev in repo.revs('%ld and merge()', revs):
2778 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2776 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2779 revs.remove(rev)
2777 revs.remove(rev)
2780 if not revs:
2778 if not revs:
2781 return -1
2779 return -1
2782
2780
2783 # check for ancestors of dest branch
2781 # check for ancestors of dest branch
2784 for rev in repo.revs('::. and %ld', revs):
2782 for rev in repo.revs('::. and %ld', revs):
2785 ui.warn(_('skipping ancestor revision %s\n') % rev)
2783 ui.warn(_('skipping ancestor revision %s\n') % rev)
2786 revs.remove(rev)
2784 revs.remove(rev)
2787 if not revs:
2785 if not revs:
2788 return -1
2786 return -1
2789
2787
2790 # analyze revs for earlier grafts
2788 # analyze revs for earlier grafts
2791 ids = {}
2789 ids = {}
2792 for ctx in repo.set("%ld", revs):
2790 for ctx in repo.set("%ld", revs):
2793 ids[ctx.hex()] = ctx.rev()
2791 ids[ctx.hex()] = ctx.rev()
2794 n = ctx.extra().get('source')
2792 n = ctx.extra().get('source')
2795 if n:
2793 if n:
2796 ids[n] = ctx.rev()
2794 ids[n] = ctx.rev()
2797
2795
2798 # check ancestors for earlier grafts
2796 # check ancestors for earlier grafts
2799 ui.debug('scanning for duplicate grafts\n')
2797 ui.debug('scanning for duplicate grafts\n')
2800 for ctx in repo.set("::. - ::%ld", revs):
2798 for ctx in repo.set("::. - ::%ld", revs):
2801 n = ctx.extra().get('source')
2799 n = ctx.extra().get('source')
2802 if n in ids:
2800 if n in ids:
2803 r = repo[n].rev()
2801 r = repo[n].rev()
2804 if r in revs:
2802 if r in revs:
2805 ui.warn(_('skipping already grafted revision %s\n') % r)
2803 ui.warn(_('skipping already grafted revision %s\n') % r)
2806 revs.remove(r)
2804 revs.remove(r)
2807 elif ids[n] in revs:
2805 elif ids[n] in revs:
2808 ui.warn(_('skipping already grafted revision %s '
2806 ui.warn(_('skipping already grafted revision %s '
2809 '(same origin %d)\n') % (ids[n], r))
2807 '(same origin %d)\n') % (ids[n], r))
2810 revs.remove(ids[n])
2808 revs.remove(ids[n])
2811 elif ctx.hex() in ids:
2809 elif ctx.hex() in ids:
2812 r = ids[ctx.hex()]
2810 r = ids[ctx.hex()]
2813 ui.warn(_('skipping already grafted revision %s '
2811 ui.warn(_('skipping already grafted revision %s '
2814 '(was grafted from %d)\n') % (r, ctx.rev()))
2812 '(was grafted from %d)\n') % (r, ctx.rev()))
2815 revs.remove(r)
2813 revs.remove(r)
2816 if not revs:
2814 if not revs:
2817 return -1
2815 return -1
2818
2816
2819 wlock = repo.wlock()
2817 wlock = repo.wlock()
2820 try:
2818 try:
2821 for pos, ctx in enumerate(repo.set("%ld", revs)):
2819 for pos, ctx in enumerate(repo.set("%ld", revs)):
2822 current = repo['.']
2820 current = repo['.']
2823
2821
2824 ui.status(_('grafting revision %s\n') % ctx.rev())
2822 ui.status(_('grafting revision %s\n') % ctx.rev())
2825 if opts.get('dry_run'):
2823 if opts.get('dry_run'):
2826 continue
2824 continue
2827
2825
2828 # we don't merge the first commit when continuing
2826 # we don't merge the first commit when continuing
2829 if not cont:
2827 if not cont:
2830 # perform the graft merge with p1(rev) as 'ancestor'
2828 # perform the graft merge with p1(rev) as 'ancestor'
2831 try:
2829 try:
2832 # ui.forcemerge is an internal variable, do not document
2830 # ui.forcemerge is an internal variable, do not document
2833 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2831 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2834 stats = mergemod.update(repo, ctx.node(), True, True, False,
2832 stats = mergemod.update(repo, ctx.node(), True, True, False,
2835 ctx.p1().node())
2833 ctx.p1().node())
2836 finally:
2834 finally:
2837 repo.ui.setconfig('ui', 'forcemerge', '')
2835 repo.ui.setconfig('ui', 'forcemerge', '')
2838 # report any conflicts
2836 # report any conflicts
2839 if stats and stats[3] > 0:
2837 if stats and stats[3] > 0:
2840 # write out state for --continue
2838 # write out state for --continue
2841 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2839 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2842 repo.opener.write('graftstate', ''.join(nodelines))
2840 repo.opener.write('graftstate', ''.join(nodelines))
2843 raise util.Abort(
2841 raise util.Abort(
2844 _("unresolved conflicts, can't continue"),
2842 _("unresolved conflicts, can't continue"),
2845 hint=_('use hg resolve and hg graft --continue'))
2843 hint=_('use hg resolve and hg graft --continue'))
2846 else:
2844 else:
2847 cont = False
2845 cont = False
2848
2846
2849 # drop the second merge parent
2847 # drop the second merge parent
2850 repo.setparents(current.node(), nullid)
2848 repo.setparents(current.node(), nullid)
2851 repo.dirstate.write()
2849 repo.dirstate.write()
2852 # fix up dirstate for copies and renames
2850 # fix up dirstate for copies and renames
2853 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2851 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2854
2852
2855 # commit
2853 # commit
2856 source = ctx.extra().get('source')
2854 source = ctx.extra().get('source')
2857 if not source:
2855 if not source:
2858 source = ctx.hex()
2856 source = ctx.hex()
2859 extra = {'source': source}
2857 extra = {'source': source}
2860 user = ctx.user()
2858 user = ctx.user()
2861 if opts.get('user'):
2859 if opts.get('user'):
2862 user = opts['user']
2860 user = opts['user']
2863 date = ctx.date()
2861 date = ctx.date()
2864 if opts.get('date'):
2862 if opts.get('date'):
2865 date = opts['date']
2863 date = opts['date']
2866 message = ctx.description()
2864 message = ctx.description()
2867 if opts.get('log'):
2865 if opts.get('log'):
2868 message += '\n(grafted from %s)' % ctx.hex()
2866 message += '\n(grafted from %s)' % ctx.hex()
2869 node = repo.commit(text=message, user=user,
2867 node = repo.commit(text=message, user=user,
2870 date=date, extra=extra, editor=editor)
2868 date=date, extra=extra, editor=editor)
2871 if node is None:
2869 if node is None:
2872 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2870 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2873 finally:
2871 finally:
2874 wlock.release()
2872 wlock.release()
2875
2873
2876 # remove state when we complete successfully
2874 # remove state when we complete successfully
2877 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2875 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2878 util.unlinkpath(repo.join('graftstate'))
2876 util.unlinkpath(repo.join('graftstate'))
2879
2877
2880 return 0
2878 return 0
2881
2879
2882 @command('grep',
2880 @command('grep',
2883 [('0', 'print0', None, _('end fields with NUL')),
2881 [('0', 'print0', None, _('end fields with NUL')),
2884 ('', 'all', None, _('print all revisions that match')),
2882 ('', 'all', None, _('print all revisions that match')),
2885 ('a', 'text', None, _('treat all files as text')),
2883 ('a', 'text', None, _('treat all files as text')),
2886 ('f', 'follow', None,
2884 ('f', 'follow', None,
2887 _('follow changeset history,'
2885 _('follow changeset history,'
2888 ' or file history across copies and renames')),
2886 ' or file history across copies and renames')),
2889 ('i', 'ignore-case', None, _('ignore case when matching')),
2887 ('i', 'ignore-case', None, _('ignore case when matching')),
2890 ('l', 'files-with-matches', None,
2888 ('l', 'files-with-matches', None,
2891 _('print only filenames and revisions that match')),
2889 _('print only filenames and revisions that match')),
2892 ('n', 'line-number', None, _('print matching line numbers')),
2890 ('n', 'line-number', None, _('print matching line numbers')),
2893 ('r', 'rev', [],
2891 ('r', 'rev', [],
2894 _('only search files changed within revision range'), _('REV')),
2892 _('only search files changed within revision range'), _('REV')),
2895 ('u', 'user', None, _('list the author (long with -v)')),
2893 ('u', 'user', None, _('list the author (long with -v)')),
2896 ('d', 'date', None, _('list the date (short with -q)')),
2894 ('d', 'date', None, _('list the date (short with -q)')),
2897 ] + walkopts,
2895 ] + walkopts,
2898 _('[OPTION]... PATTERN [FILE]...'))
2896 _('[OPTION]... PATTERN [FILE]...'))
2899 def grep(ui, repo, pattern, *pats, **opts):
2897 def grep(ui, repo, pattern, *pats, **opts):
2900 """search for a pattern in specified files and revisions
2898 """search for a pattern in specified files and revisions
2901
2899
2902 Search revisions of files for a regular expression.
2900 Search revisions of files for a regular expression.
2903
2901
2904 This command behaves differently than Unix grep. It only accepts
2902 This command behaves differently than Unix grep. It only accepts
2905 Python/Perl regexps. It searches repository history, not the
2903 Python/Perl regexps. It searches repository history, not the
2906 working directory. It always prints the revision number in which a
2904 working directory. It always prints the revision number in which a
2907 match appears.
2905 match appears.
2908
2906
2909 By default, grep only prints output for the first revision of a
2907 By default, grep only prints output for the first revision of a
2910 file in which it finds a match. To get it to print every revision
2908 file in which it finds a match. To get it to print every revision
2911 that contains a change in match status ("-" for a match that
2909 that contains a change in match status ("-" for a match that
2912 becomes a non-match, or "+" for a non-match that becomes a match),
2910 becomes a non-match, or "+" for a non-match that becomes a match),
2913 use the --all flag.
2911 use the --all flag.
2914
2912
2915 Returns 0 if a match is found, 1 otherwise.
2913 Returns 0 if a match is found, 1 otherwise.
2916 """
2914 """
2917 reflags = re.M
2915 reflags = re.M
2918 if opts.get('ignore_case'):
2916 if opts.get('ignore_case'):
2919 reflags |= re.I
2917 reflags |= re.I
2920 try:
2918 try:
2921 regexp = re.compile(pattern, reflags)
2919 regexp = re.compile(pattern, reflags)
2922 except re.error, inst:
2920 except re.error, inst:
2923 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2921 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2924 return 1
2922 return 1
2925 sep, eol = ':', '\n'
2923 sep, eol = ':', '\n'
2926 if opts.get('print0'):
2924 if opts.get('print0'):
2927 sep = eol = '\0'
2925 sep = eol = '\0'
2928
2926
2929 getfile = util.lrucachefunc(repo.file)
2927 getfile = util.lrucachefunc(repo.file)
2930
2928
2931 def matchlines(body):
2929 def matchlines(body):
2932 begin = 0
2930 begin = 0
2933 linenum = 0
2931 linenum = 0
2934 while True:
2932 while True:
2935 match = regexp.search(body, begin)
2933 match = regexp.search(body, begin)
2936 if not match:
2934 if not match:
2937 break
2935 break
2938 mstart, mend = match.span()
2936 mstart, mend = match.span()
2939 linenum += body.count('\n', begin, mstart) + 1
2937 linenum += body.count('\n', begin, mstart) + 1
2940 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2938 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2941 begin = body.find('\n', mend) + 1 or len(body) + 1
2939 begin = body.find('\n', mend) + 1 or len(body) + 1
2942 lend = begin - 1
2940 lend = begin - 1
2943 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2941 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2944
2942
2945 class linestate(object):
2943 class linestate(object):
2946 def __init__(self, line, linenum, colstart, colend):
2944 def __init__(self, line, linenum, colstart, colend):
2947 self.line = line
2945 self.line = line
2948 self.linenum = linenum
2946 self.linenum = linenum
2949 self.colstart = colstart
2947 self.colstart = colstart
2950 self.colend = colend
2948 self.colend = colend
2951
2949
2952 def __hash__(self):
2950 def __hash__(self):
2953 return hash((self.linenum, self.line))
2951 return hash((self.linenum, self.line))
2954
2952
2955 def __eq__(self, other):
2953 def __eq__(self, other):
2956 return self.line == other.line
2954 return self.line == other.line
2957
2955
2958 matches = {}
2956 matches = {}
2959 copies = {}
2957 copies = {}
2960 def grepbody(fn, rev, body):
2958 def grepbody(fn, rev, body):
2961 matches[rev].setdefault(fn, [])
2959 matches[rev].setdefault(fn, [])
2962 m = matches[rev][fn]
2960 m = matches[rev][fn]
2963 for lnum, cstart, cend, line in matchlines(body):
2961 for lnum, cstart, cend, line in matchlines(body):
2964 s = linestate(line, lnum, cstart, cend)
2962 s = linestate(line, lnum, cstart, cend)
2965 m.append(s)
2963 m.append(s)
2966
2964
2967 def difflinestates(a, b):
2965 def difflinestates(a, b):
2968 sm = difflib.SequenceMatcher(None, a, b)
2966 sm = difflib.SequenceMatcher(None, a, b)
2969 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2967 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2970 if tag == 'insert':
2968 if tag == 'insert':
2971 for i in xrange(blo, bhi):
2969 for i in xrange(blo, bhi):
2972 yield ('+', b[i])
2970 yield ('+', b[i])
2973 elif tag == 'delete':
2971 elif tag == 'delete':
2974 for i in xrange(alo, ahi):
2972 for i in xrange(alo, ahi):
2975 yield ('-', a[i])
2973 yield ('-', a[i])
2976 elif tag == 'replace':
2974 elif tag == 'replace':
2977 for i in xrange(alo, ahi):
2975 for i in xrange(alo, ahi):
2978 yield ('-', a[i])
2976 yield ('-', a[i])
2979 for i in xrange(blo, bhi):
2977 for i in xrange(blo, bhi):
2980 yield ('+', b[i])
2978 yield ('+', b[i])
2981
2979
2982 def display(fn, ctx, pstates, states):
2980 def display(fn, ctx, pstates, states):
2983 rev = ctx.rev()
2981 rev = ctx.rev()
2984 datefunc = ui.quiet and util.shortdate or util.datestr
2982 datefunc = ui.quiet and util.shortdate or util.datestr
2985 found = False
2983 found = False
2986 filerevmatches = {}
2984 filerevmatches = {}
2987 def binary():
2985 def binary():
2988 flog = getfile(fn)
2986 flog = getfile(fn)
2989 return util.binary(flog.read(ctx.filenode(fn)))
2987 return util.binary(flog.read(ctx.filenode(fn)))
2990
2988
2991 if opts.get('all'):
2989 if opts.get('all'):
2992 iter = difflinestates(pstates, states)
2990 iter = difflinestates(pstates, states)
2993 else:
2991 else:
2994 iter = [('', l) for l in states]
2992 iter = [('', l) for l in states]
2995 for change, l in iter:
2993 for change, l in iter:
2996 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
2994 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
2997 before, match, after = None, None, None
2995 before, match, after = None, None, None
2998
2996
2999 if opts.get('line_number'):
2997 if opts.get('line_number'):
3000 cols.append((str(l.linenum), 'grep.linenumber'))
2998 cols.append((str(l.linenum), 'grep.linenumber'))
3001 if opts.get('all'):
2999 if opts.get('all'):
3002 cols.append((change, 'grep.change'))
3000 cols.append((change, 'grep.change'))
3003 if opts.get('user'):
3001 if opts.get('user'):
3004 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3002 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3005 if opts.get('date'):
3003 if opts.get('date'):
3006 cols.append((datefunc(ctx.date()), 'grep.date'))
3004 cols.append((datefunc(ctx.date()), 'grep.date'))
3007 if opts.get('files_with_matches'):
3005 if opts.get('files_with_matches'):
3008 c = (fn, rev)
3006 c = (fn, rev)
3009 if c in filerevmatches:
3007 if c in filerevmatches:
3010 continue
3008 continue
3011 filerevmatches[c] = 1
3009 filerevmatches[c] = 1
3012 else:
3010 else:
3013 before = l.line[:l.colstart]
3011 before = l.line[:l.colstart]
3014 match = l.line[l.colstart:l.colend]
3012 match = l.line[l.colstart:l.colend]
3015 after = l.line[l.colend:]
3013 after = l.line[l.colend:]
3016 for col, label in cols[:-1]:
3014 for col, label in cols[:-1]:
3017 ui.write(col, label=label)
3015 ui.write(col, label=label)
3018 ui.write(sep, label='grep.sep')
3016 ui.write(sep, label='grep.sep')
3019 ui.write(cols[-1][0], label=cols[-1][1])
3017 ui.write(cols[-1][0], label=cols[-1][1])
3020 if before is not None:
3018 if before is not None:
3021 ui.write(sep, label='grep.sep')
3019 ui.write(sep, label='grep.sep')
3022 if not opts.get('text') and binary():
3020 if not opts.get('text') and binary():
3023 ui.write(" Binary file matches")
3021 ui.write(" Binary file matches")
3024 else:
3022 else:
3025 ui.write(before)
3023 ui.write(before)
3026 ui.write(match, label='grep.match')
3024 ui.write(match, label='grep.match')
3027 ui.write(after)
3025 ui.write(after)
3028 ui.write(eol)
3026 ui.write(eol)
3029 found = True
3027 found = True
3030 return found
3028 return found
3031
3029
3032 skip = {}
3030 skip = {}
3033 revfiles = {}
3031 revfiles = {}
3034 matchfn = scmutil.match(repo[None], pats, opts)
3032 matchfn = scmutil.match(repo[None], pats, opts)
3035 found = False
3033 found = False
3036 follow = opts.get('follow')
3034 follow = opts.get('follow')
3037
3035
3038 def prep(ctx, fns):
3036 def prep(ctx, fns):
3039 rev = ctx.rev()
3037 rev = ctx.rev()
3040 pctx = ctx.p1()
3038 pctx = ctx.p1()
3041 parent = pctx.rev()
3039 parent = pctx.rev()
3042 matches.setdefault(rev, {})
3040 matches.setdefault(rev, {})
3043 matches.setdefault(parent, {})
3041 matches.setdefault(parent, {})
3044 files = revfiles.setdefault(rev, [])
3042 files = revfiles.setdefault(rev, [])
3045 for fn in fns:
3043 for fn in fns:
3046 flog = getfile(fn)
3044 flog = getfile(fn)
3047 try:
3045 try:
3048 fnode = ctx.filenode(fn)
3046 fnode = ctx.filenode(fn)
3049 except error.LookupError:
3047 except error.LookupError:
3050 continue
3048 continue
3051
3049
3052 copied = flog.renamed(fnode)
3050 copied = flog.renamed(fnode)
3053 copy = follow and copied and copied[0]
3051 copy = follow and copied and copied[0]
3054 if copy:
3052 if copy:
3055 copies.setdefault(rev, {})[fn] = copy
3053 copies.setdefault(rev, {})[fn] = copy
3056 if fn in skip:
3054 if fn in skip:
3057 if copy:
3055 if copy:
3058 skip[copy] = True
3056 skip[copy] = True
3059 continue
3057 continue
3060 files.append(fn)
3058 files.append(fn)
3061
3059
3062 if fn not in matches[rev]:
3060 if fn not in matches[rev]:
3063 grepbody(fn, rev, flog.read(fnode))
3061 grepbody(fn, rev, flog.read(fnode))
3064
3062
3065 pfn = copy or fn
3063 pfn = copy or fn
3066 if pfn not in matches[parent]:
3064 if pfn not in matches[parent]:
3067 try:
3065 try:
3068 fnode = pctx.filenode(pfn)
3066 fnode = pctx.filenode(pfn)
3069 grepbody(pfn, parent, flog.read(fnode))
3067 grepbody(pfn, parent, flog.read(fnode))
3070 except error.LookupError:
3068 except error.LookupError:
3071 pass
3069 pass
3072
3070
3073 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3071 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3074 rev = ctx.rev()
3072 rev = ctx.rev()
3075 parent = ctx.p1().rev()
3073 parent = ctx.p1().rev()
3076 for fn in sorted(revfiles.get(rev, [])):
3074 for fn in sorted(revfiles.get(rev, [])):
3077 states = matches[rev][fn]
3075 states = matches[rev][fn]
3078 copy = copies.get(rev, {}).get(fn)
3076 copy = copies.get(rev, {}).get(fn)
3079 if fn in skip:
3077 if fn in skip:
3080 if copy:
3078 if copy:
3081 skip[copy] = True
3079 skip[copy] = True
3082 continue
3080 continue
3083 pstates = matches.get(parent, {}).get(copy or fn, [])
3081 pstates = matches.get(parent, {}).get(copy or fn, [])
3084 if pstates or states:
3082 if pstates or states:
3085 r = display(fn, ctx, pstates, states)
3083 r = display(fn, ctx, pstates, states)
3086 found = found or r
3084 found = found or r
3087 if r and not opts.get('all'):
3085 if r and not opts.get('all'):
3088 skip[fn] = True
3086 skip[fn] = True
3089 if copy:
3087 if copy:
3090 skip[copy] = True
3088 skip[copy] = True
3091 del matches[rev]
3089 del matches[rev]
3092 del revfiles[rev]
3090 del revfiles[rev]
3093
3091
3094 return not found
3092 return not found
3095
3093
3096 @command('heads',
3094 @command('heads',
3097 [('r', 'rev', '',
3095 [('r', 'rev', '',
3098 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3096 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3099 ('t', 'topo', False, _('show topological heads only')),
3097 ('t', 'topo', False, _('show topological heads only')),
3100 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3098 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3101 ('c', 'closed', False, _('show normal and closed branch heads')),
3099 ('c', 'closed', False, _('show normal and closed branch heads')),
3102 ] + templateopts,
3100 ] + templateopts,
3103 _('[-ct] [-r STARTREV] [REV]...'))
3101 _('[-ct] [-r STARTREV] [REV]...'))
3104 def heads(ui, repo, *branchrevs, **opts):
3102 def heads(ui, repo, *branchrevs, **opts):
3105 """show current repository heads or show branch heads
3103 """show current repository heads or show branch heads
3106
3104
3107 With no arguments, show all repository branch heads.
3105 With no arguments, show all repository branch heads.
3108
3106
3109 Repository "heads" are changesets with no child changesets. They are
3107 Repository "heads" are changesets with no child changesets. They are
3110 where development generally takes place and are the usual targets
3108 where development generally takes place and are the usual targets
3111 for update and merge operations. Branch heads are changesets that have
3109 for update and merge operations. Branch heads are changesets that have
3112 no child changeset on the same branch.
3110 no child changeset on the same branch.
3113
3111
3114 If one or more REVs are given, only branch heads on the branches
3112 If one or more REVs are given, only branch heads on the branches
3115 associated with the specified changesets are shown. This means
3113 associated with the specified changesets are shown. This means
3116 that you can use :hg:`heads foo` to see the heads on a branch
3114 that you can use :hg:`heads foo` to see the heads on a branch
3117 named ``foo``.
3115 named ``foo``.
3118
3116
3119 If -c/--closed is specified, also show branch heads marked closed
3117 If -c/--closed is specified, also show branch heads marked closed
3120 (see :hg:`commit --close-branch`).
3118 (see :hg:`commit --close-branch`).
3121
3119
3122 If STARTREV is specified, only those heads that are descendants of
3120 If STARTREV is specified, only those heads that are descendants of
3123 STARTREV will be displayed.
3121 STARTREV will be displayed.
3124
3122
3125 If -t/--topo is specified, named branch mechanics will be ignored and only
3123 If -t/--topo is specified, named branch mechanics will be ignored and only
3126 changesets without children will be shown.
3124 changesets without children will be shown.
3127
3125
3128 Returns 0 if matching heads are found, 1 if not.
3126 Returns 0 if matching heads are found, 1 if not.
3129 """
3127 """
3130
3128
3131 start = None
3129 start = None
3132 if 'rev' in opts:
3130 if 'rev' in opts:
3133 start = scmutil.revsingle(repo, opts['rev'], None).node()
3131 start = scmutil.revsingle(repo, opts['rev'], None).node()
3134
3132
3135 if opts.get('topo'):
3133 if opts.get('topo'):
3136 heads = [repo[h] for h in repo.heads(start)]
3134 heads = [repo[h] for h in repo.heads(start)]
3137 else:
3135 else:
3138 heads = []
3136 heads = []
3139 for branch in repo.branchmap():
3137 for branch in repo.branchmap():
3140 heads += repo.branchheads(branch, start, opts.get('closed'))
3138 heads += repo.branchheads(branch, start, opts.get('closed'))
3141 heads = [repo[h] for h in heads]
3139 heads = [repo[h] for h in heads]
3142
3140
3143 if branchrevs:
3141 if branchrevs:
3144 branches = set(repo[br].branch() for br in branchrevs)
3142 branches = set(repo[br].branch() for br in branchrevs)
3145 heads = [h for h in heads if h.branch() in branches]
3143 heads = [h for h in heads if h.branch() in branches]
3146
3144
3147 if opts.get('active') and branchrevs:
3145 if opts.get('active') and branchrevs:
3148 dagheads = repo.heads(start)
3146 dagheads = repo.heads(start)
3149 heads = [h for h in heads if h.node() in dagheads]
3147 heads = [h for h in heads if h.node() in dagheads]
3150
3148
3151 if branchrevs:
3149 if branchrevs:
3152 haveheads = set(h.branch() for h in heads)
3150 haveheads = set(h.branch() for h in heads)
3153 if branches - haveheads:
3151 if branches - haveheads:
3154 headless = ', '.join(b for b in branches - haveheads)
3152 headless = ', '.join(b for b in branches - haveheads)
3155 msg = _('no open branch heads found on branches %s')
3153 msg = _('no open branch heads found on branches %s')
3156 if opts.get('rev'):
3154 if opts.get('rev'):
3157 msg += _(' (started at %s)') % opts['rev']
3155 msg += _(' (started at %s)') % opts['rev']
3158 ui.warn((msg + '\n') % headless)
3156 ui.warn((msg + '\n') % headless)
3159
3157
3160 if not heads:
3158 if not heads:
3161 return 1
3159 return 1
3162
3160
3163 heads = sorted(heads, key=lambda x: -x.rev())
3161 heads = sorted(heads, key=lambda x: -x.rev())
3164 displayer = cmdutil.show_changeset(ui, repo, opts)
3162 displayer = cmdutil.show_changeset(ui, repo, opts)
3165 for ctx in heads:
3163 for ctx in heads:
3166 displayer.show(ctx)
3164 displayer.show(ctx)
3167 displayer.close()
3165 displayer.close()
3168
3166
3169 @command('help',
3167 @command('help',
3170 [('e', 'extension', None, _('show only help for extensions')),
3168 [('e', 'extension', None, _('show only help for extensions')),
3171 ('c', 'command', None, _('show only help for commands')),
3169 ('c', 'command', None, _('show only help for commands')),
3172 ('k', 'keyword', '', _('show topics matching keyword')),
3170 ('k', 'keyword', '', _('show topics matching keyword')),
3173 ],
3171 ],
3174 _('[-ec] [TOPIC]'))
3172 _('[-ec] [TOPIC]'))
3175 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3173 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3176 """show help for a given topic or a help overview
3174 """show help for a given topic or a help overview
3177
3175
3178 With no arguments, print a list of commands with short help messages.
3176 With no arguments, print a list of commands with short help messages.
3179
3177
3180 Given a topic, extension, or command name, print help for that
3178 Given a topic, extension, or command name, print help for that
3181 topic.
3179 topic.
3182
3180
3183 Returns 0 if successful.
3181 Returns 0 if successful.
3184 """
3182 """
3185
3183
3186 textwidth = min(ui.termwidth(), 80) - 2
3184 textwidth = min(ui.termwidth(), 80) - 2
3187
3185
3188 def helpcmd(name):
3186 def helpcmd(name):
3189 try:
3187 try:
3190 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3188 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3191 except error.AmbiguousCommand, inst:
3189 except error.AmbiguousCommand, inst:
3192 # py3k fix: except vars can't be used outside the scope of the
3190 # py3k fix: except vars can't be used outside the scope of the
3193 # except block, nor can be used inside a lambda. python issue4617
3191 # except block, nor can be used inside a lambda. python issue4617
3194 prefix = inst.args[0]
3192 prefix = inst.args[0]
3195 select = lambda c: c.lstrip('^').startswith(prefix)
3193 select = lambda c: c.lstrip('^').startswith(prefix)
3196 rst = helplist(select)
3194 rst = helplist(select)
3197 return rst
3195 return rst
3198
3196
3199 rst = []
3197 rst = []
3200
3198
3201 # check if it's an invalid alias and display its error if it is
3199 # check if it's an invalid alias and display its error if it is
3202 if getattr(entry[0], 'badalias', False):
3200 if getattr(entry[0], 'badalias', False):
3203 if not unknowncmd:
3201 if not unknowncmd:
3204 ui.pushbuffer()
3202 ui.pushbuffer()
3205 entry[0](ui)
3203 entry[0](ui)
3206 rst.append(ui.popbuffer())
3204 rst.append(ui.popbuffer())
3207 return rst
3205 return rst
3208
3206
3209 # synopsis
3207 # synopsis
3210 if len(entry) > 2:
3208 if len(entry) > 2:
3211 if entry[2].startswith('hg'):
3209 if entry[2].startswith('hg'):
3212 rst.append("%s\n" % entry[2])
3210 rst.append("%s\n" % entry[2])
3213 else:
3211 else:
3214 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3212 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3215 else:
3213 else:
3216 rst.append('hg %s\n' % aliases[0])
3214 rst.append('hg %s\n' % aliases[0])
3217 # aliases
3215 # aliases
3218 if full and not ui.quiet and len(aliases) > 1:
3216 if full and not ui.quiet and len(aliases) > 1:
3219 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3217 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3220 rst.append('\n')
3218 rst.append('\n')
3221
3219
3222 # description
3220 # description
3223 doc = gettext(entry[0].__doc__)
3221 doc = gettext(entry[0].__doc__)
3224 if not doc:
3222 if not doc:
3225 doc = _("(no help text available)")
3223 doc = _("(no help text available)")
3226 if util.safehasattr(entry[0], 'definition'): # aliased command
3224 if util.safehasattr(entry[0], 'definition'): # aliased command
3227 if entry[0].definition.startswith('!'): # shell alias
3225 if entry[0].definition.startswith('!'): # shell alias
3228 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3226 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3229 else:
3227 else:
3230 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3228 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3231 doc = doc.splitlines(True)
3229 doc = doc.splitlines(True)
3232 if ui.quiet or not full:
3230 if ui.quiet or not full:
3233 rst.append(doc[0])
3231 rst.append(doc[0])
3234 else:
3232 else:
3235 rst.extend(doc)
3233 rst.extend(doc)
3236 rst.append('\n')
3234 rst.append('\n')
3237
3235
3238 # check if this command shadows a non-trivial (multi-line)
3236 # check if this command shadows a non-trivial (multi-line)
3239 # extension help text
3237 # extension help text
3240 try:
3238 try:
3241 mod = extensions.find(name)
3239 mod = extensions.find(name)
3242 doc = gettext(mod.__doc__) or ''
3240 doc = gettext(mod.__doc__) or ''
3243 if '\n' in doc.strip():
3241 if '\n' in doc.strip():
3244 msg = _('use "hg help -e %s" to show help for '
3242 msg = _('use "hg help -e %s" to show help for '
3245 'the %s extension') % (name, name)
3243 'the %s extension') % (name, name)
3246 rst.append('\n%s\n' % msg)
3244 rst.append('\n%s\n' % msg)
3247 except KeyError:
3245 except KeyError:
3248 pass
3246 pass
3249
3247
3250 # options
3248 # options
3251 if not ui.quiet and entry[1]:
3249 if not ui.quiet and entry[1]:
3252 rst.append('\n%s\n\n' % _("options:"))
3250 rst.append('\n%s\n\n' % _("options:"))
3253 rst.append(help.optrst(entry[1], ui.verbose))
3251 rst.append(help.optrst(entry[1], ui.verbose))
3254
3252
3255 if ui.verbose:
3253 if ui.verbose:
3256 rst.append('\n%s\n\n' % _("global options:"))
3254 rst.append('\n%s\n\n' % _("global options:"))
3257 rst.append(help.optrst(globalopts, ui.verbose))
3255 rst.append(help.optrst(globalopts, ui.verbose))
3258
3256
3259 if not ui.verbose:
3257 if not ui.verbose:
3260 if not full:
3258 if not full:
3261 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3259 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3262 % name)
3260 % name)
3263 elif not ui.quiet:
3261 elif not ui.quiet:
3264 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3262 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3265 % name)
3263 % name)
3266 return rst
3264 return rst
3267
3265
3268
3266
3269 def helplist(select=None):
3267 def helplist(select=None):
3270 # list of commands
3268 # list of commands
3271 if name == "shortlist":
3269 if name == "shortlist":
3272 header = _('basic commands:\n\n')
3270 header = _('basic commands:\n\n')
3273 else:
3271 else:
3274 header = _('list of commands:\n\n')
3272 header = _('list of commands:\n\n')
3275
3273
3276 h = {}
3274 h = {}
3277 cmds = {}
3275 cmds = {}
3278 for c, e in table.iteritems():
3276 for c, e in table.iteritems():
3279 f = c.split("|", 1)[0]
3277 f = c.split("|", 1)[0]
3280 if select and not select(f):
3278 if select and not select(f):
3281 continue
3279 continue
3282 if (not select and name != 'shortlist' and
3280 if (not select and name != 'shortlist' and
3283 e[0].__module__ != __name__):
3281 e[0].__module__ != __name__):
3284 continue
3282 continue
3285 if name == "shortlist" and not f.startswith("^"):
3283 if name == "shortlist" and not f.startswith("^"):
3286 continue
3284 continue
3287 f = f.lstrip("^")
3285 f = f.lstrip("^")
3288 if not ui.debugflag and f.startswith("debug"):
3286 if not ui.debugflag and f.startswith("debug"):
3289 continue
3287 continue
3290 doc = e[0].__doc__
3288 doc = e[0].__doc__
3291 if doc and 'DEPRECATED' in doc and not ui.verbose:
3289 if doc and 'DEPRECATED' in doc and not ui.verbose:
3292 continue
3290 continue
3293 doc = gettext(doc)
3291 doc = gettext(doc)
3294 if not doc:
3292 if not doc:
3295 doc = _("(no help text available)")
3293 doc = _("(no help text available)")
3296 h[f] = doc.splitlines()[0].rstrip()
3294 h[f] = doc.splitlines()[0].rstrip()
3297 cmds[f] = c.lstrip("^")
3295 cmds[f] = c.lstrip("^")
3298
3296
3299 rst = []
3297 rst = []
3300 if not h:
3298 if not h:
3301 if not ui.quiet:
3299 if not ui.quiet:
3302 rst.append(_('no commands defined\n'))
3300 rst.append(_('no commands defined\n'))
3303 return rst
3301 return rst
3304
3302
3305 if not ui.quiet:
3303 if not ui.quiet:
3306 rst.append(header)
3304 rst.append(header)
3307 fns = sorted(h)
3305 fns = sorted(h)
3308 for f in fns:
3306 for f in fns:
3309 if ui.verbose:
3307 if ui.verbose:
3310 commands = cmds[f].replace("|",", ")
3308 commands = cmds[f].replace("|",", ")
3311 rst.append(" :%s: %s\n" % (commands, h[f]))
3309 rst.append(" :%s: %s\n" % (commands, h[f]))
3312 else:
3310 else:
3313 rst.append(' :%s: %s\n' % (f, h[f]))
3311 rst.append(' :%s: %s\n' % (f, h[f]))
3314
3312
3315 if not name:
3313 if not name:
3316 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3314 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3317 if exts:
3315 if exts:
3318 rst.append('\n')
3316 rst.append('\n')
3319 rst.extend(exts)
3317 rst.extend(exts)
3320
3318
3321 rst.append(_("\nadditional help topics:\n\n"))
3319 rst.append(_("\nadditional help topics:\n\n"))
3322 topics = []
3320 topics = []
3323 for names, header, doc in help.helptable:
3321 for names, header, doc in help.helptable:
3324 topics.append((names[0], header))
3322 topics.append((names[0], header))
3325 for t, desc in topics:
3323 for t, desc in topics:
3326 rst.append(" :%s: %s\n" % (t, desc))
3324 rst.append(" :%s: %s\n" % (t, desc))
3327
3325
3328 optlist = []
3326 optlist = []
3329 if not ui.quiet:
3327 if not ui.quiet:
3330 if ui.verbose:
3328 if ui.verbose:
3331 optlist.append((_("global options:"), globalopts))
3329 optlist.append((_("global options:"), globalopts))
3332 if name == 'shortlist':
3330 if name == 'shortlist':
3333 optlist.append((_('use "hg help" for the full list '
3331 optlist.append((_('use "hg help" for the full list '
3334 'of commands'), ()))
3332 'of commands'), ()))
3335 else:
3333 else:
3336 if name == 'shortlist':
3334 if name == 'shortlist':
3337 msg = _('use "hg help" for the full list of commands '
3335 msg = _('use "hg help" for the full list of commands '
3338 'or "hg -v" for details')
3336 'or "hg -v" for details')
3339 elif name and not full:
3337 elif name and not full:
3340 msg = _('use "hg help %s" to show the full help '
3338 msg = _('use "hg help %s" to show the full help '
3341 'text') % name
3339 'text') % name
3342 else:
3340 else:
3343 msg = _('use "hg -v help%s" to show builtin aliases and '
3341 msg = _('use "hg -v help%s" to show builtin aliases and '
3344 'global options') % (name and " " + name or "")
3342 'global options') % (name and " " + name or "")
3345 optlist.append((msg, ()))
3343 optlist.append((msg, ()))
3346
3344
3347 if optlist:
3345 if optlist:
3348 for title, options in optlist:
3346 for title, options in optlist:
3349 rst.append('\n%s\n' % title)
3347 rst.append('\n%s\n' % title)
3350 if options:
3348 if options:
3351 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3349 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3352 return rst
3350 return rst
3353
3351
3354 def helptopic(name):
3352 def helptopic(name):
3355 for names, header, doc in help.helptable:
3353 for names, header, doc in help.helptable:
3356 if name in names:
3354 if name in names:
3357 break
3355 break
3358 else:
3356 else:
3359 raise error.UnknownCommand(name)
3357 raise error.UnknownCommand(name)
3360
3358
3361 rst = ["%s\n\n" % header]
3359 rst = ["%s\n\n" % header]
3362 # description
3360 # description
3363 if not doc:
3361 if not doc:
3364 rst.append(" %s\n" % _("(no help text available)"))
3362 rst.append(" %s\n" % _("(no help text available)"))
3365 if util.safehasattr(doc, '__call__'):
3363 if util.safehasattr(doc, '__call__'):
3366 rst += [" %s\n" % l for l in doc().splitlines()]
3364 rst += [" %s\n" % l for l in doc().splitlines()]
3367
3365
3368 try:
3366 try:
3369 cmdutil.findcmd(name, table)
3367 cmdutil.findcmd(name, table)
3370 rst.append(_('\nuse "hg help -c %s" to see help for '
3368 rst.append(_('\nuse "hg help -c %s" to see help for '
3371 'the %s command\n') % (name, name))
3369 'the %s command\n') % (name, name))
3372 except error.UnknownCommand:
3370 except error.UnknownCommand:
3373 pass
3371 pass
3374 return rst
3372 return rst
3375
3373
3376 def helpext(name):
3374 def helpext(name):
3377 try:
3375 try:
3378 mod = extensions.find(name)
3376 mod = extensions.find(name)
3379 doc = gettext(mod.__doc__) or _('no help text available')
3377 doc = gettext(mod.__doc__) or _('no help text available')
3380 except KeyError:
3378 except KeyError:
3381 mod = None
3379 mod = None
3382 doc = extensions.disabledext(name)
3380 doc = extensions.disabledext(name)
3383 if not doc:
3381 if not doc:
3384 raise error.UnknownCommand(name)
3382 raise error.UnknownCommand(name)
3385
3383
3386 if '\n' not in doc:
3384 if '\n' not in doc:
3387 head, tail = doc, ""
3385 head, tail = doc, ""
3388 else:
3386 else:
3389 head, tail = doc.split('\n', 1)
3387 head, tail = doc.split('\n', 1)
3390 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3388 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3391 if tail:
3389 if tail:
3392 rst.extend(tail.splitlines(True))
3390 rst.extend(tail.splitlines(True))
3393 rst.append('\n')
3391 rst.append('\n')
3394
3392
3395 if mod:
3393 if mod:
3396 try:
3394 try:
3397 ct = mod.cmdtable
3395 ct = mod.cmdtable
3398 except AttributeError:
3396 except AttributeError:
3399 ct = {}
3397 ct = {}
3400 modcmds = set([c.split('|', 1)[0] for c in ct])
3398 modcmds = set([c.split('|', 1)[0] for c in ct])
3401 rst.extend(helplist(modcmds.__contains__))
3399 rst.extend(helplist(modcmds.__contains__))
3402 else:
3400 else:
3403 rst.append(_('use "hg help extensions" for information on enabling '
3401 rst.append(_('use "hg help extensions" for information on enabling '
3404 'extensions\n'))
3402 'extensions\n'))
3405 return rst
3403 return rst
3406
3404
3407 def helpextcmd(name):
3405 def helpextcmd(name):
3408 cmd, ext, mod = extensions.disabledcmd(ui, name,
3406 cmd, ext, mod = extensions.disabledcmd(ui, name,
3409 ui.configbool('ui', 'strict'))
3407 ui.configbool('ui', 'strict'))
3410 doc = gettext(mod.__doc__).splitlines()[0]
3408 doc = gettext(mod.__doc__).splitlines()[0]
3411
3409
3412 rst = help.listexts(_("'%s' is provided by the following "
3410 rst = help.listexts(_("'%s' is provided by the following "
3413 "extension:") % cmd, {ext: doc}, indent=4)
3411 "extension:") % cmd, {ext: doc}, indent=4)
3414 rst.append('\n')
3412 rst.append('\n')
3415 rst.append(_('use "hg help extensions" for information on enabling '
3413 rst.append(_('use "hg help extensions" for information on enabling '
3416 'extensions\n'))
3414 'extensions\n'))
3417 return rst
3415 return rst
3418
3416
3419
3417
3420 rst = []
3418 rst = []
3421 kw = opts.get('keyword')
3419 kw = opts.get('keyword')
3422 if kw:
3420 if kw:
3423 matches = help.topicmatch(kw)
3421 matches = help.topicmatch(kw)
3424 for t, title in (('topics', _('Topics')),
3422 for t, title in (('topics', _('Topics')),
3425 ('commands', _('Commands')),
3423 ('commands', _('Commands')),
3426 ('extensions', _('Extensions')),
3424 ('extensions', _('Extensions')),
3427 ('extensioncommands', _('Extension Commands'))):
3425 ('extensioncommands', _('Extension Commands'))):
3428 if matches[t]:
3426 if matches[t]:
3429 rst.append('%s:\n\n' % title)
3427 rst.append('%s:\n\n' % title)
3430 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3428 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3431 rst.append('\n')
3429 rst.append('\n')
3432 elif name and name != 'shortlist':
3430 elif name and name != 'shortlist':
3433 i = None
3431 i = None
3434 if unknowncmd:
3432 if unknowncmd:
3435 queries = (helpextcmd,)
3433 queries = (helpextcmd,)
3436 elif opts.get('extension'):
3434 elif opts.get('extension'):
3437 queries = (helpext,)
3435 queries = (helpext,)
3438 elif opts.get('command'):
3436 elif opts.get('command'):
3439 queries = (helpcmd,)
3437 queries = (helpcmd,)
3440 else:
3438 else:
3441 queries = (helptopic, helpcmd, helpext, helpextcmd)
3439 queries = (helptopic, helpcmd, helpext, helpextcmd)
3442 for f in queries:
3440 for f in queries:
3443 try:
3441 try:
3444 rst = f(name)
3442 rst = f(name)
3445 i = None
3443 i = None
3446 break
3444 break
3447 except error.UnknownCommand, inst:
3445 except error.UnknownCommand, inst:
3448 i = inst
3446 i = inst
3449 if i:
3447 if i:
3450 raise i
3448 raise i
3451 else:
3449 else:
3452 # program name
3450 # program name
3453 if not ui.quiet:
3451 if not ui.quiet:
3454 rst = [_("Mercurial Distributed SCM\n"), '\n']
3452 rst = [_("Mercurial Distributed SCM\n"), '\n']
3455 rst.extend(helplist())
3453 rst.extend(helplist())
3456
3454
3457 keep = ui.verbose and ['verbose'] or []
3455 keep = ui.verbose and ['verbose'] or []
3458 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3456 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3459 ui.write(formatted)
3457 ui.write(formatted)
3460
3458
3461
3459
3462 @command('identify|id',
3460 @command('identify|id',
3463 [('r', 'rev', '',
3461 [('r', 'rev', '',
3464 _('identify the specified revision'), _('REV')),
3462 _('identify the specified revision'), _('REV')),
3465 ('n', 'num', None, _('show local revision number')),
3463 ('n', 'num', None, _('show local revision number')),
3466 ('i', 'id', None, _('show global revision id')),
3464 ('i', 'id', None, _('show global revision id')),
3467 ('b', 'branch', None, _('show branch')),
3465 ('b', 'branch', None, _('show branch')),
3468 ('t', 'tags', None, _('show tags')),
3466 ('t', 'tags', None, _('show tags')),
3469 ('B', 'bookmarks', None, _('show bookmarks')),
3467 ('B', 'bookmarks', None, _('show bookmarks')),
3470 ] + remoteopts,
3468 ] + remoteopts,
3471 _('[-nibtB] [-r REV] [SOURCE]'))
3469 _('[-nibtB] [-r REV] [SOURCE]'))
3472 def identify(ui, repo, source=None, rev=None,
3470 def identify(ui, repo, source=None, rev=None,
3473 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3471 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3474 """identify the working copy or specified revision
3472 """identify the working copy or specified revision
3475
3473
3476 Print a summary identifying the repository state at REV using one or
3474 Print a summary identifying the repository state at REV using one or
3477 two parent hash identifiers, followed by a "+" if the working
3475 two parent hash identifiers, followed by a "+" if the working
3478 directory has uncommitted changes, the branch name (if not default),
3476 directory has uncommitted changes, the branch name (if not default),
3479 a list of tags, and a list of bookmarks.
3477 a list of tags, and a list of bookmarks.
3480
3478
3481 When REV is not given, print a summary of the current state of the
3479 When REV is not given, print a summary of the current state of the
3482 repository.
3480 repository.
3483
3481
3484 Specifying a path to a repository root or Mercurial bundle will
3482 Specifying a path to a repository root or Mercurial bundle will
3485 cause lookup to operate on that repository/bundle.
3483 cause lookup to operate on that repository/bundle.
3486
3484
3487 .. container:: verbose
3485 .. container:: verbose
3488
3486
3489 Examples:
3487 Examples:
3490
3488
3491 - generate a build identifier for the working directory::
3489 - generate a build identifier for the working directory::
3492
3490
3493 hg id --id > build-id.dat
3491 hg id --id > build-id.dat
3494
3492
3495 - find the revision corresponding to a tag::
3493 - find the revision corresponding to a tag::
3496
3494
3497 hg id -n -r 1.3
3495 hg id -n -r 1.3
3498
3496
3499 - check the most recent revision of a remote repository::
3497 - check the most recent revision of a remote repository::
3500
3498
3501 hg id -r tip http://selenic.com/hg/
3499 hg id -r tip http://selenic.com/hg/
3502
3500
3503 Returns 0 if successful.
3501 Returns 0 if successful.
3504 """
3502 """
3505
3503
3506 if not repo and not source:
3504 if not repo and not source:
3507 raise util.Abort(_("there is no Mercurial repository here "
3505 raise util.Abort(_("there is no Mercurial repository here "
3508 "(.hg not found)"))
3506 "(.hg not found)"))
3509
3507
3510 hexfunc = ui.debugflag and hex or short
3508 hexfunc = ui.debugflag and hex or short
3511 default = not (num or id or branch or tags or bookmarks)
3509 default = not (num or id or branch or tags or bookmarks)
3512 output = []
3510 output = []
3513 revs = []
3511 revs = []
3514
3512
3515 if source:
3513 if source:
3516 source, branches = hg.parseurl(ui.expandpath(source))
3514 source, branches = hg.parseurl(ui.expandpath(source))
3517 peer = hg.peer(ui, opts, source)
3515 peer = hg.peer(ui, opts, source)
3518 repo = peer.local()
3516 repo = peer.local()
3519 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3517 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3520
3518
3521 if not repo:
3519 if not repo:
3522 if num or branch or tags:
3520 if num or branch or tags:
3523 raise util.Abort(
3521 raise util.Abort(
3524 _("can't query remote revision number, branch, or tags"))
3522 _("can't query remote revision number, branch, or tags"))
3525 if not rev and revs:
3523 if not rev and revs:
3526 rev = revs[0]
3524 rev = revs[0]
3527 if not rev:
3525 if not rev:
3528 rev = "tip"
3526 rev = "tip"
3529
3527
3530 remoterev = peer.lookup(rev)
3528 remoterev = peer.lookup(rev)
3531 if default or id:
3529 if default or id:
3532 output = [hexfunc(remoterev)]
3530 output = [hexfunc(remoterev)]
3533
3531
3534 def getbms():
3532 def getbms():
3535 bms = []
3533 bms = []
3536
3534
3537 if 'bookmarks' in peer.listkeys('namespaces'):
3535 if 'bookmarks' in peer.listkeys('namespaces'):
3538 hexremoterev = hex(remoterev)
3536 hexremoterev = hex(remoterev)
3539 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3537 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3540 if bmr == hexremoterev]
3538 if bmr == hexremoterev]
3541
3539
3542 return bms
3540 return bms
3543
3541
3544 if bookmarks:
3542 if bookmarks:
3545 output.extend(getbms())
3543 output.extend(getbms())
3546 elif default and not ui.quiet:
3544 elif default and not ui.quiet:
3547 # multiple bookmarks for a single parent separated by '/'
3545 # multiple bookmarks for a single parent separated by '/'
3548 bm = '/'.join(getbms())
3546 bm = '/'.join(getbms())
3549 if bm:
3547 if bm:
3550 output.append(bm)
3548 output.append(bm)
3551 else:
3549 else:
3552 if not rev:
3550 if not rev:
3553 ctx = repo[None]
3551 ctx = repo[None]
3554 parents = ctx.parents()
3552 parents = ctx.parents()
3555 changed = ""
3553 changed = ""
3556 if default or id or num:
3554 if default or id or num:
3557 if (util.any(repo.status())
3555 if (util.any(repo.status())
3558 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3556 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3559 changed = '+'
3557 changed = '+'
3560 if default or id:
3558 if default or id:
3561 output = ["%s%s" %
3559 output = ["%s%s" %
3562 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3560 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3563 if num:
3561 if num:
3564 output.append("%s%s" %
3562 output.append("%s%s" %
3565 ('+'.join([str(p.rev()) for p in parents]), changed))
3563 ('+'.join([str(p.rev()) for p in parents]), changed))
3566 else:
3564 else:
3567 ctx = scmutil.revsingle(repo, rev)
3565 ctx = scmutil.revsingle(repo, rev)
3568 if default or id:
3566 if default or id:
3569 output = [hexfunc(ctx.node())]
3567 output = [hexfunc(ctx.node())]
3570 if num:
3568 if num:
3571 output.append(str(ctx.rev()))
3569 output.append(str(ctx.rev()))
3572
3570
3573 if default and not ui.quiet:
3571 if default and not ui.quiet:
3574 b = ctx.branch()
3572 b = ctx.branch()
3575 if b != 'default':
3573 if b != 'default':
3576 output.append("(%s)" % b)
3574 output.append("(%s)" % b)
3577
3575
3578 # multiple tags for a single parent separated by '/'
3576 # multiple tags for a single parent separated by '/'
3579 t = '/'.join(ctx.tags())
3577 t = '/'.join(ctx.tags())
3580 if t:
3578 if t:
3581 output.append(t)
3579 output.append(t)
3582
3580
3583 # multiple bookmarks for a single parent separated by '/'
3581 # multiple bookmarks for a single parent separated by '/'
3584 bm = '/'.join(ctx.bookmarks())
3582 bm = '/'.join(ctx.bookmarks())
3585 if bm:
3583 if bm:
3586 output.append(bm)
3584 output.append(bm)
3587 else:
3585 else:
3588 if branch:
3586 if branch:
3589 output.append(ctx.branch())
3587 output.append(ctx.branch())
3590
3588
3591 if tags:
3589 if tags:
3592 output.extend(ctx.tags())
3590 output.extend(ctx.tags())
3593
3591
3594 if bookmarks:
3592 if bookmarks:
3595 output.extend(ctx.bookmarks())
3593 output.extend(ctx.bookmarks())
3596
3594
3597 ui.write("%s\n" % ' '.join(output))
3595 ui.write("%s\n" % ' '.join(output))
3598
3596
3599 @command('import|patch',
3597 @command('import|patch',
3600 [('p', 'strip', 1,
3598 [('p', 'strip', 1,
3601 _('directory strip option for patch. This has the same '
3599 _('directory strip option for patch. This has the same '
3602 'meaning as the corresponding patch option'), _('NUM')),
3600 'meaning as the corresponding patch option'), _('NUM')),
3603 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3601 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3604 ('e', 'edit', False, _('invoke editor on commit messages')),
3602 ('e', 'edit', False, _('invoke editor on commit messages')),
3605 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3603 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3606 ('', 'no-commit', None,
3604 ('', 'no-commit', None,
3607 _("don't commit, just update the working directory")),
3605 _("don't commit, just update the working directory")),
3608 ('', 'bypass', None,
3606 ('', 'bypass', None,
3609 _("apply patch without touching the working directory")),
3607 _("apply patch without touching the working directory")),
3610 ('', 'exact', None,
3608 ('', 'exact', None,
3611 _('apply patch to the nodes from which it was generated')),
3609 _('apply patch to the nodes from which it was generated')),
3612 ('', 'import-branch', None,
3610 ('', 'import-branch', None,
3613 _('use any branch information in patch (implied by --exact)'))] +
3611 _('use any branch information in patch (implied by --exact)'))] +
3614 commitopts + commitopts2 + similarityopts,
3612 commitopts + commitopts2 + similarityopts,
3615 _('[OPTION]... PATCH...'))
3613 _('[OPTION]... PATCH...'))
3616 def import_(ui, repo, patch1=None, *patches, **opts):
3614 def import_(ui, repo, patch1=None, *patches, **opts):
3617 """import an ordered set of patches
3615 """import an ordered set of patches
3618
3616
3619 Import a list of patches and commit them individually (unless
3617 Import a list of patches and commit them individually (unless
3620 --no-commit is specified).
3618 --no-commit is specified).
3621
3619
3622 If there are outstanding changes in the working directory, import
3620 If there are outstanding changes in the working directory, import
3623 will abort unless given the -f/--force flag.
3621 will abort unless given the -f/--force flag.
3624
3622
3625 You can import a patch straight from a mail message. Even patches
3623 You can import a patch straight from a mail message. Even patches
3626 as attachments work (to use the body part, it must have type
3624 as attachments work (to use the body part, it must have type
3627 text/plain or text/x-patch). From and Subject headers of email
3625 text/plain or text/x-patch). From and Subject headers of email
3628 message are used as default committer and commit message. All
3626 message are used as default committer and commit message. All
3629 text/plain body parts before first diff are added to commit
3627 text/plain body parts before first diff are added to commit
3630 message.
3628 message.
3631
3629
3632 If the imported patch was generated by :hg:`export`, user and
3630 If the imported patch was generated by :hg:`export`, user and
3633 description from patch override values from message headers and
3631 description from patch override values from message headers and
3634 body. Values given on command line with -m/--message and -u/--user
3632 body. Values given on command line with -m/--message and -u/--user
3635 override these.
3633 override these.
3636
3634
3637 If --exact is specified, import will set the working directory to
3635 If --exact is specified, import will set the working directory to
3638 the parent of each patch before applying it, and will abort if the
3636 the parent of each patch before applying it, and will abort if the
3639 resulting changeset has a different ID than the one recorded in
3637 resulting changeset has a different ID than the one recorded in
3640 the patch. This may happen due to character set problems or other
3638 the patch. This may happen due to character set problems or other
3641 deficiencies in the text patch format.
3639 deficiencies in the text patch format.
3642
3640
3643 Use --bypass to apply and commit patches directly to the
3641 Use --bypass to apply and commit patches directly to the
3644 repository, not touching the working directory. Without --exact,
3642 repository, not touching the working directory. Without --exact,
3645 patches will be applied on top of the working directory parent
3643 patches will be applied on top of the working directory parent
3646 revision.
3644 revision.
3647
3645
3648 With -s/--similarity, hg will attempt to discover renames and
3646 With -s/--similarity, hg will attempt to discover renames and
3649 copies in the patch in the same way as :hg:`addremove`.
3647 copies in the patch in the same way as :hg:`addremove`.
3650
3648
3651 To read a patch from standard input, use "-" as the patch name. If
3649 To read a patch from standard input, use "-" as the patch name. If
3652 a URL is specified, the patch will be downloaded from it.
3650 a URL is specified, the patch will be downloaded from it.
3653 See :hg:`help dates` for a list of formats valid for -d/--date.
3651 See :hg:`help dates` for a list of formats valid for -d/--date.
3654
3652
3655 .. container:: verbose
3653 .. container:: verbose
3656
3654
3657 Examples:
3655 Examples:
3658
3656
3659 - import a traditional patch from a website and detect renames::
3657 - import a traditional patch from a website and detect renames::
3660
3658
3661 hg import -s 80 http://example.com/bugfix.patch
3659 hg import -s 80 http://example.com/bugfix.patch
3662
3660
3663 - import a changeset from an hgweb server::
3661 - import a changeset from an hgweb server::
3664
3662
3665 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3663 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3666
3664
3667 - import all the patches in an Unix-style mbox::
3665 - import all the patches in an Unix-style mbox::
3668
3666
3669 hg import incoming-patches.mbox
3667 hg import incoming-patches.mbox
3670
3668
3671 - attempt to exactly restore an exported changeset (not always
3669 - attempt to exactly restore an exported changeset (not always
3672 possible)::
3670 possible)::
3673
3671
3674 hg import --exact proposed-fix.patch
3672 hg import --exact proposed-fix.patch
3675
3673
3676 Returns 0 on success.
3674 Returns 0 on success.
3677 """
3675 """
3678
3676
3679 if not patch1:
3677 if not patch1:
3680 raise util.Abort(_('need at least one patch to import'))
3678 raise util.Abort(_('need at least one patch to import'))
3681
3679
3682 patches = (patch1,) + patches
3680 patches = (patch1,) + patches
3683
3681
3684 date = opts.get('date')
3682 date = opts.get('date')
3685 if date:
3683 if date:
3686 opts['date'] = util.parsedate(date)
3684 opts['date'] = util.parsedate(date)
3687
3685
3688 editor = cmdutil.commiteditor
3686 editor = cmdutil.commiteditor
3689 if opts.get('edit'):
3687 if opts.get('edit'):
3690 editor = cmdutil.commitforceeditor
3688 editor = cmdutil.commitforceeditor
3691
3689
3692 update = not opts.get('bypass')
3690 update = not opts.get('bypass')
3693 if not update and opts.get('no_commit'):
3691 if not update and opts.get('no_commit'):
3694 raise util.Abort(_('cannot use --no-commit with --bypass'))
3692 raise util.Abort(_('cannot use --no-commit with --bypass'))
3695 try:
3693 try:
3696 sim = float(opts.get('similarity') or 0)
3694 sim = float(opts.get('similarity') or 0)
3697 except ValueError:
3695 except ValueError:
3698 raise util.Abort(_('similarity must be a number'))
3696 raise util.Abort(_('similarity must be a number'))
3699 if sim < 0 or sim > 100:
3697 if sim < 0 or sim > 100:
3700 raise util.Abort(_('similarity must be between 0 and 100'))
3698 raise util.Abort(_('similarity must be between 0 and 100'))
3701 if sim and not update:
3699 if sim and not update:
3702 raise util.Abort(_('cannot use --similarity with --bypass'))
3700 raise util.Abort(_('cannot use --similarity with --bypass'))
3703
3701
3704 if (opts.get('exact') or not opts.get('force')) and update:
3702 if (opts.get('exact') or not opts.get('force')) and update:
3705 cmdutil.bailifchanged(repo)
3703 cmdutil.bailifchanged(repo)
3706
3704
3707 base = opts["base"]
3705 base = opts["base"]
3708 strip = opts["strip"]
3706 strip = opts["strip"]
3709 wlock = lock = tr = None
3707 wlock = lock = tr = None
3710 msgs = []
3708 msgs = []
3711
3709
3712 def checkexact(repo, n, nodeid):
3710 def checkexact(repo, n, nodeid):
3713 if opts.get('exact') and hex(n) != nodeid:
3711 if opts.get('exact') and hex(n) != nodeid:
3714 repo.rollback()
3712 repo.rollback()
3715 raise util.Abort(_('patch is damaged or loses information'))
3713 raise util.Abort(_('patch is damaged or loses information'))
3716
3714
3717 def tryone(ui, hunk, parents):
3715 def tryone(ui, hunk, parents):
3718 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3716 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3719 patch.extract(ui, hunk)
3717 patch.extract(ui, hunk)
3720
3718
3721 if not tmpname:
3719 if not tmpname:
3722 return (None, None)
3720 return (None, None)
3723 msg = _('applied to working directory')
3721 msg = _('applied to working directory')
3724
3722
3725 try:
3723 try:
3726 cmdline_message = cmdutil.logmessage(ui, opts)
3724 cmdline_message = cmdutil.logmessage(ui, opts)
3727 if cmdline_message:
3725 if cmdline_message:
3728 # pickup the cmdline msg
3726 # pickup the cmdline msg
3729 message = cmdline_message
3727 message = cmdline_message
3730 elif message:
3728 elif message:
3731 # pickup the patch msg
3729 # pickup the patch msg
3732 message = message.strip()
3730 message = message.strip()
3733 else:
3731 else:
3734 # launch the editor
3732 # launch the editor
3735 message = None
3733 message = None
3736 ui.debug('message:\n%s\n' % message)
3734 ui.debug('message:\n%s\n' % message)
3737
3735
3738 if len(parents) == 1:
3736 if len(parents) == 1:
3739 parents.append(repo[nullid])
3737 parents.append(repo[nullid])
3740 if opts.get('exact'):
3738 if opts.get('exact'):
3741 if not nodeid or not p1:
3739 if not nodeid or not p1:
3742 raise util.Abort(_('not a Mercurial patch'))
3740 raise util.Abort(_('not a Mercurial patch'))
3743 p1 = repo[p1]
3741 p1 = repo[p1]
3744 p2 = repo[p2 or nullid]
3742 p2 = repo[p2 or nullid]
3745 elif p2:
3743 elif p2:
3746 try:
3744 try:
3747 p1 = repo[p1]
3745 p1 = repo[p1]
3748 p2 = repo[p2]
3746 p2 = repo[p2]
3749 # Without any options, consider p2 only if the
3747 # Without any options, consider p2 only if the
3750 # patch is being applied on top of the recorded
3748 # patch is being applied on top of the recorded
3751 # first parent.
3749 # first parent.
3752 if p1 != parents[0]:
3750 if p1 != parents[0]:
3753 p1 = parents[0]
3751 p1 = parents[0]
3754 p2 = repo[nullid]
3752 p2 = repo[nullid]
3755 except error.RepoError:
3753 except error.RepoError:
3756 p1, p2 = parents
3754 p1, p2 = parents
3757 else:
3755 else:
3758 p1, p2 = parents
3756 p1, p2 = parents
3759
3757
3760 n = None
3758 n = None
3761 if update:
3759 if update:
3762 if p1 != parents[0]:
3760 if p1 != parents[0]:
3763 hg.clean(repo, p1.node())
3761 hg.clean(repo, p1.node())
3764 if p2 != parents[1]:
3762 if p2 != parents[1]:
3765 repo.setparents(p1.node(), p2.node())
3763 repo.setparents(p1.node(), p2.node())
3766
3764
3767 if opts.get('exact') or opts.get('import_branch'):
3765 if opts.get('exact') or opts.get('import_branch'):
3768 repo.dirstate.setbranch(branch or 'default')
3766 repo.dirstate.setbranch(branch or 'default')
3769
3767
3770 files = set()
3768 files = set()
3771 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3769 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3772 eolmode=None, similarity=sim / 100.0)
3770 eolmode=None, similarity=sim / 100.0)
3773 files = list(files)
3771 files = list(files)
3774 if opts.get('no_commit'):
3772 if opts.get('no_commit'):
3775 if message:
3773 if message:
3776 msgs.append(message)
3774 msgs.append(message)
3777 else:
3775 else:
3778 if opts.get('exact') or p2:
3776 if opts.get('exact') or p2:
3779 # If you got here, you either use --force and know what
3777 # If you got here, you either use --force and know what
3780 # you are doing or used --exact or a merge patch while
3778 # you are doing or used --exact or a merge patch while
3781 # being updated to its first parent.
3779 # being updated to its first parent.
3782 m = None
3780 m = None
3783 else:
3781 else:
3784 m = scmutil.matchfiles(repo, files or [])
3782 m = scmutil.matchfiles(repo, files or [])
3785 n = repo.commit(message, opts.get('user') or user,
3783 n = repo.commit(message, opts.get('user') or user,
3786 opts.get('date') or date, match=m,
3784 opts.get('date') or date, match=m,
3787 editor=editor)
3785 editor=editor)
3788 checkexact(repo, n, nodeid)
3786 checkexact(repo, n, nodeid)
3789 else:
3787 else:
3790 if opts.get('exact') or opts.get('import_branch'):
3788 if opts.get('exact') or opts.get('import_branch'):
3791 branch = branch or 'default'
3789 branch = branch or 'default'
3792 else:
3790 else:
3793 branch = p1.branch()
3791 branch = p1.branch()
3794 store = patch.filestore()
3792 store = patch.filestore()
3795 try:
3793 try:
3796 files = set()
3794 files = set()
3797 try:
3795 try:
3798 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3796 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3799 files, eolmode=None)
3797 files, eolmode=None)
3800 except patch.PatchError, e:
3798 except patch.PatchError, e:
3801 raise util.Abort(str(e))
3799 raise util.Abort(str(e))
3802 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3800 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3803 message,
3801 message,
3804 opts.get('user') or user,
3802 opts.get('user') or user,
3805 opts.get('date') or date,
3803 opts.get('date') or date,
3806 branch, files, store,
3804 branch, files, store,
3807 editor=cmdutil.commiteditor)
3805 editor=cmdutil.commiteditor)
3808 repo.savecommitmessage(memctx.description())
3806 repo.savecommitmessage(memctx.description())
3809 n = memctx.commit()
3807 n = memctx.commit()
3810 checkexact(repo, n, nodeid)
3808 checkexact(repo, n, nodeid)
3811 finally:
3809 finally:
3812 store.close()
3810 store.close()
3813 if n:
3811 if n:
3814 # i18n: refers to a short changeset id
3812 # i18n: refers to a short changeset id
3815 msg = _('created %s') % short(n)
3813 msg = _('created %s') % short(n)
3816 return (msg, n)
3814 return (msg, n)
3817 finally:
3815 finally:
3818 os.unlink(tmpname)
3816 os.unlink(tmpname)
3819
3817
3820 try:
3818 try:
3821 try:
3819 try:
3822 wlock = repo.wlock()
3820 wlock = repo.wlock()
3823 if not opts.get('no_commit'):
3821 if not opts.get('no_commit'):
3824 lock = repo.lock()
3822 lock = repo.lock()
3825 tr = repo.transaction('import')
3823 tr = repo.transaction('import')
3826 parents = repo.parents()
3824 parents = repo.parents()
3827 for patchurl in patches:
3825 for patchurl in patches:
3828 if patchurl == '-':
3826 if patchurl == '-':
3829 ui.status(_('applying patch from stdin\n'))
3827 ui.status(_('applying patch from stdin\n'))
3830 patchfile = ui.fin
3828 patchfile = ui.fin
3831 patchurl = 'stdin' # for error message
3829 patchurl = 'stdin' # for error message
3832 else:
3830 else:
3833 patchurl = os.path.join(base, patchurl)
3831 patchurl = os.path.join(base, patchurl)
3834 ui.status(_('applying %s\n') % patchurl)
3832 ui.status(_('applying %s\n') % patchurl)
3835 patchfile = url.open(ui, patchurl)
3833 patchfile = url.open(ui, patchurl)
3836
3834
3837 haspatch = False
3835 haspatch = False
3838 for hunk in patch.split(patchfile):
3836 for hunk in patch.split(patchfile):
3839 (msg, node) = tryone(ui, hunk, parents)
3837 (msg, node) = tryone(ui, hunk, parents)
3840 if msg:
3838 if msg:
3841 haspatch = True
3839 haspatch = True
3842 ui.note(msg + '\n')
3840 ui.note(msg + '\n')
3843 if update or opts.get('exact'):
3841 if update or opts.get('exact'):
3844 parents = repo.parents()
3842 parents = repo.parents()
3845 else:
3843 else:
3846 parents = [repo[node]]
3844 parents = [repo[node]]
3847
3845
3848 if not haspatch:
3846 if not haspatch:
3849 raise util.Abort(_('%s: no diffs found') % patchurl)
3847 raise util.Abort(_('%s: no diffs found') % patchurl)
3850
3848
3851 if tr:
3849 if tr:
3852 tr.close()
3850 tr.close()
3853 if msgs:
3851 if msgs:
3854 repo.savecommitmessage('\n* * *\n'.join(msgs))
3852 repo.savecommitmessage('\n* * *\n'.join(msgs))
3855 except: # re-raises
3853 except: # re-raises
3856 # wlock.release() indirectly calls dirstate.write(): since
3854 # wlock.release() indirectly calls dirstate.write(): since
3857 # we're crashing, we do not want to change the working dir
3855 # we're crashing, we do not want to change the working dir
3858 # parent after all, so make sure it writes nothing
3856 # parent after all, so make sure it writes nothing
3859 repo.dirstate.invalidate()
3857 repo.dirstate.invalidate()
3860 raise
3858 raise
3861 finally:
3859 finally:
3862 if tr:
3860 if tr:
3863 tr.release()
3861 tr.release()
3864 release(lock, wlock)
3862 release(lock, wlock)
3865
3863
3866 @command('incoming|in',
3864 @command('incoming|in',
3867 [('f', 'force', None,
3865 [('f', 'force', None,
3868 _('run even if remote repository is unrelated')),
3866 _('run even if remote repository is unrelated')),
3869 ('n', 'newest-first', None, _('show newest record first')),
3867 ('n', 'newest-first', None, _('show newest record first')),
3870 ('', 'bundle', '',
3868 ('', 'bundle', '',
3871 _('file to store the bundles into'), _('FILE')),
3869 _('file to store the bundles into'), _('FILE')),
3872 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3870 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3873 ('B', 'bookmarks', False, _("compare bookmarks")),
3871 ('B', 'bookmarks', False, _("compare bookmarks")),
3874 ('b', 'branch', [],
3872 ('b', 'branch', [],
3875 _('a specific branch you would like to pull'), _('BRANCH')),
3873 _('a specific branch you would like to pull'), _('BRANCH')),
3876 ] + logopts + remoteopts + subrepoopts,
3874 ] + logopts + remoteopts + subrepoopts,
3877 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3875 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3878 def incoming(ui, repo, source="default", **opts):
3876 def incoming(ui, repo, source="default", **opts):
3879 """show new changesets found in source
3877 """show new changesets found in source
3880
3878
3881 Show new changesets found in the specified path/URL or the default
3879 Show new changesets found in the specified path/URL or the default
3882 pull location. These are the changesets that would have been pulled
3880 pull location. These are the changesets that would have been pulled
3883 if a pull at the time you issued this command.
3881 if a pull at the time you issued this command.
3884
3882
3885 For remote repository, using --bundle avoids downloading the
3883 For remote repository, using --bundle avoids downloading the
3886 changesets twice if the incoming is followed by a pull.
3884 changesets twice if the incoming is followed by a pull.
3887
3885
3888 See pull for valid source format details.
3886 See pull for valid source format details.
3889
3887
3890 Returns 0 if there are incoming changes, 1 otherwise.
3888 Returns 0 if there are incoming changes, 1 otherwise.
3891 """
3889 """
3892 if opts.get('graph'):
3890 if opts.get('graph'):
3893 cmdutil.checkunsupportedgraphflags([], opts)
3891 cmdutil.checkunsupportedgraphflags([], opts)
3894 def display(other, chlist, displayer):
3892 def display(other, chlist, displayer):
3895 revdag = cmdutil.graphrevs(other, chlist, opts)
3893 revdag = cmdutil.graphrevs(other, chlist, opts)
3896 showparents = [ctx.node() for ctx in repo[None].parents()]
3894 showparents = [ctx.node() for ctx in repo[None].parents()]
3897 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3895 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3898 graphmod.asciiedges)
3896 graphmod.asciiedges)
3899
3897
3900 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3898 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3901 return 0
3899 return 0
3902
3900
3903 if opts.get('bundle') and opts.get('subrepos'):
3901 if opts.get('bundle') and opts.get('subrepos'):
3904 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3902 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3905
3903
3906 if opts.get('bookmarks'):
3904 if opts.get('bookmarks'):
3907 source, branches = hg.parseurl(ui.expandpath(source),
3905 source, branches = hg.parseurl(ui.expandpath(source),
3908 opts.get('branch'))
3906 opts.get('branch'))
3909 other = hg.peer(repo, opts, source)
3907 other = hg.peer(repo, opts, source)
3910 if 'bookmarks' not in other.listkeys('namespaces'):
3908 if 'bookmarks' not in other.listkeys('namespaces'):
3911 ui.warn(_("remote doesn't support bookmarks\n"))
3909 ui.warn(_("remote doesn't support bookmarks\n"))
3912 return 0
3910 return 0
3913 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3911 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3914 return bookmarks.diff(ui, repo, other)
3912 return bookmarks.diff(ui, repo, other)
3915
3913
3916 repo._subtoppath = ui.expandpath(source)
3914 repo._subtoppath = ui.expandpath(source)
3917 try:
3915 try:
3918 return hg.incoming(ui, repo, source, opts)
3916 return hg.incoming(ui, repo, source, opts)
3919 finally:
3917 finally:
3920 del repo._subtoppath
3918 del repo._subtoppath
3921
3919
3922
3920
3923 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3921 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3924 def init(ui, dest=".", **opts):
3922 def init(ui, dest=".", **opts):
3925 """create a new repository in the given directory
3923 """create a new repository in the given directory
3926
3924
3927 Initialize a new repository in the given directory. If the given
3925 Initialize a new repository in the given directory. If the given
3928 directory does not exist, it will be created.
3926 directory does not exist, it will be created.
3929
3927
3930 If no directory is given, the current directory is used.
3928 If no directory is given, the current directory is used.
3931
3929
3932 It is possible to specify an ``ssh://`` URL as the destination.
3930 It is possible to specify an ``ssh://`` URL as the destination.
3933 See :hg:`help urls` for more information.
3931 See :hg:`help urls` for more information.
3934
3932
3935 Returns 0 on success.
3933 Returns 0 on success.
3936 """
3934 """
3937 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3935 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3938
3936
3939 @command('locate',
3937 @command('locate',
3940 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3938 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3941 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3939 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3942 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3940 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3943 ] + walkopts,
3941 ] + walkopts,
3944 _('[OPTION]... [PATTERN]...'))
3942 _('[OPTION]... [PATTERN]...'))
3945 def locate(ui, repo, *pats, **opts):
3943 def locate(ui, repo, *pats, **opts):
3946 """locate files matching specific patterns
3944 """locate files matching specific patterns
3947
3945
3948 Print files under Mercurial control in the working directory whose
3946 Print files under Mercurial control in the working directory whose
3949 names match the given patterns.
3947 names match the given patterns.
3950
3948
3951 By default, this command searches all directories in the working
3949 By default, this command searches all directories in the working
3952 directory. To search just the current directory and its
3950 directory. To search just the current directory and its
3953 subdirectories, use "--include .".
3951 subdirectories, use "--include .".
3954
3952
3955 If no patterns are given to match, this command prints the names
3953 If no patterns are given to match, this command prints the names
3956 of all files under Mercurial control in the working directory.
3954 of all files under Mercurial control in the working directory.
3957
3955
3958 If you want to feed the output of this command into the "xargs"
3956 If you want to feed the output of this command into the "xargs"
3959 command, use the -0 option to both this command and "xargs". This
3957 command, use the -0 option to both this command and "xargs". This
3960 will avoid the problem of "xargs" treating single filenames that
3958 will avoid the problem of "xargs" treating single filenames that
3961 contain whitespace as multiple filenames.
3959 contain whitespace as multiple filenames.
3962
3960
3963 Returns 0 if a match is found, 1 otherwise.
3961 Returns 0 if a match is found, 1 otherwise.
3964 """
3962 """
3965 end = opts.get('print0') and '\0' or '\n'
3963 end = opts.get('print0') and '\0' or '\n'
3966 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3964 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3967
3965
3968 ret = 1
3966 ret = 1
3969 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3967 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3970 m.bad = lambda x, y: False
3968 m.bad = lambda x, y: False
3971 for abs in repo[rev].walk(m):
3969 for abs in repo[rev].walk(m):
3972 if not rev and abs not in repo.dirstate:
3970 if not rev and abs not in repo.dirstate:
3973 continue
3971 continue
3974 if opts.get('fullpath'):
3972 if opts.get('fullpath'):
3975 ui.write(repo.wjoin(abs), end)
3973 ui.write(repo.wjoin(abs), end)
3976 else:
3974 else:
3977 ui.write(((pats and m.rel(abs)) or abs), end)
3975 ui.write(((pats and m.rel(abs)) or abs), end)
3978 ret = 0
3976 ret = 0
3979
3977
3980 return ret
3978 return ret
3981
3979
3982 @command('^log|history',
3980 @command('^log|history',
3983 [('f', 'follow', None,
3981 [('f', 'follow', None,
3984 _('follow changeset history, or file history across copies and renames')),
3982 _('follow changeset history, or file history across copies and renames')),
3985 ('', 'follow-first', None,
3983 ('', 'follow-first', None,
3986 _('only follow the first parent of merge changesets (DEPRECATED)')),
3984 _('only follow the first parent of merge changesets (DEPRECATED)')),
3987 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3985 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3988 ('C', 'copies', None, _('show copied files')),
3986 ('C', 'copies', None, _('show copied files')),
3989 ('k', 'keyword', [],
3987 ('k', 'keyword', [],
3990 _('do case-insensitive search for a given text'), _('TEXT')),
3988 _('do case-insensitive search for a given text'), _('TEXT')),
3991 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3989 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3992 ('', 'removed', None, _('include revisions where files were removed')),
3990 ('', 'removed', None, _('include revisions where files were removed')),
3993 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3991 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3994 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3992 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3995 ('', 'only-branch', [],
3993 ('', 'only-branch', [],
3996 _('show only changesets within the given named branch (DEPRECATED)'),
3994 _('show only changesets within the given named branch (DEPRECATED)'),
3997 _('BRANCH')),
3995 _('BRANCH')),
3998 ('b', 'branch', [],
3996 ('b', 'branch', [],
3999 _('show changesets within the given named branch'), _('BRANCH')),
3997 _('show changesets within the given named branch'), _('BRANCH')),
4000 ('P', 'prune', [],
3998 ('P', 'prune', [],
4001 _('do not display revision or any of its ancestors'), _('REV')),
3999 _('do not display revision or any of its ancestors'), _('REV')),
4002 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
4000 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
4003 ] + logopts + walkopts,
4001 ] + logopts + walkopts,
4004 _('[OPTION]... [FILE]'))
4002 _('[OPTION]... [FILE]'))
4005 def log(ui, repo, *pats, **opts):
4003 def log(ui, repo, *pats, **opts):
4006 """show revision history of entire repository or files
4004 """show revision history of entire repository or files
4007
4005
4008 Print the revision history of the specified files or the entire
4006 Print the revision history of the specified files or the entire
4009 project.
4007 project.
4010
4008
4011 If no revision range is specified, the default is ``tip:0`` unless
4009 If no revision range is specified, the default is ``tip:0`` unless
4012 --follow is set, in which case the working directory parent is
4010 --follow is set, in which case the working directory parent is
4013 used as the starting revision.
4011 used as the starting revision.
4014
4012
4015 File history is shown without following rename or copy history of
4013 File history is shown without following rename or copy history of
4016 files. Use -f/--follow with a filename to follow history across
4014 files. Use -f/--follow with a filename to follow history across
4017 renames and copies. --follow without a filename will only show
4015 renames and copies. --follow without a filename will only show
4018 ancestors or descendants of the starting revision.
4016 ancestors or descendants of the starting revision.
4019
4017
4020 By default this command prints revision number and changeset id,
4018 By default this command prints revision number and changeset id,
4021 tags, non-trivial parents, user, date and time, and a summary for
4019 tags, non-trivial parents, user, date and time, and a summary for
4022 each commit. When the -v/--verbose switch is used, the list of
4020 each commit. When the -v/--verbose switch is used, the list of
4023 changed files and full commit message are shown.
4021 changed files and full commit message are shown.
4024
4022
4025 .. note::
4023 .. note::
4026 log -p/--patch may generate unexpected diff output for merge
4024 log -p/--patch may generate unexpected diff output for merge
4027 changesets, as it will only compare the merge changeset against
4025 changesets, as it will only compare the merge changeset against
4028 its first parent. Also, only files different from BOTH parents
4026 its first parent. Also, only files different from BOTH parents
4029 will appear in files:.
4027 will appear in files:.
4030
4028
4031 .. note::
4029 .. note::
4032 for performance reasons, log FILE may omit duplicate changes
4030 for performance reasons, log FILE may omit duplicate changes
4033 made on branches and will not show deletions. To see all
4031 made on branches and will not show deletions. To see all
4034 changes including duplicates and deletions, use the --removed
4032 changes including duplicates and deletions, use the --removed
4035 switch.
4033 switch.
4036
4034
4037 .. container:: verbose
4035 .. container:: verbose
4038
4036
4039 Some examples:
4037 Some examples:
4040
4038
4041 - changesets with full descriptions and file lists::
4039 - changesets with full descriptions and file lists::
4042
4040
4043 hg log -v
4041 hg log -v
4044
4042
4045 - changesets ancestral to the working directory::
4043 - changesets ancestral to the working directory::
4046
4044
4047 hg log -f
4045 hg log -f
4048
4046
4049 - last 10 commits on the current branch::
4047 - last 10 commits on the current branch::
4050
4048
4051 hg log -l 10 -b .
4049 hg log -l 10 -b .
4052
4050
4053 - changesets showing all modifications of a file, including removals::
4051 - changesets showing all modifications of a file, including removals::
4054
4052
4055 hg log --removed file.c
4053 hg log --removed file.c
4056
4054
4057 - all changesets that touch a directory, with diffs, excluding merges::
4055 - all changesets that touch a directory, with diffs, excluding merges::
4058
4056
4059 hg log -Mp lib/
4057 hg log -Mp lib/
4060
4058
4061 - all revision numbers that match a keyword::
4059 - all revision numbers that match a keyword::
4062
4060
4063 hg log -k bug --template "{rev}\\n"
4061 hg log -k bug --template "{rev}\\n"
4064
4062
4065 - check if a given changeset is included is a tagged release::
4063 - check if a given changeset is included is a tagged release::
4066
4064
4067 hg log -r "a21ccf and ancestor(1.9)"
4065 hg log -r "a21ccf and ancestor(1.9)"
4068
4066
4069 - find all changesets by some user in a date range::
4067 - find all changesets by some user in a date range::
4070
4068
4071 hg log -k alice -d "may 2008 to jul 2008"
4069 hg log -k alice -d "may 2008 to jul 2008"
4072
4070
4073 - summary of all changesets after the last tag::
4071 - summary of all changesets after the last tag::
4074
4072
4075 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4073 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4076
4074
4077 See :hg:`help dates` for a list of formats valid for -d/--date.
4075 See :hg:`help dates` for a list of formats valid for -d/--date.
4078
4076
4079 See :hg:`help revisions` and :hg:`help revsets` for more about
4077 See :hg:`help revisions` and :hg:`help revsets` for more about
4080 specifying revisions.
4078 specifying revisions.
4081
4079
4082 See :hg:`help templates` for more about pre-packaged styles and
4080 See :hg:`help templates` for more about pre-packaged styles and
4083 specifying custom templates.
4081 specifying custom templates.
4084
4082
4085 Returns 0 on success.
4083 Returns 0 on success.
4086 """
4084 """
4087 if opts.get('graph'):
4085 if opts.get('graph'):
4088 return cmdutil.graphlog(ui, repo, *pats, **opts)
4086 return cmdutil.graphlog(ui, repo, *pats, **opts)
4089
4087
4090 matchfn = scmutil.match(repo[None], pats, opts)
4088 matchfn = scmutil.match(repo[None], pats, opts)
4091 limit = cmdutil.loglimit(opts)
4089 limit = cmdutil.loglimit(opts)
4092 count = 0
4090 count = 0
4093
4091
4094 getrenamed, endrev = None, None
4092 getrenamed, endrev = None, None
4095 if opts.get('copies'):
4093 if opts.get('copies'):
4096 if opts.get('rev'):
4094 if opts.get('rev'):
4097 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4095 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4098 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4096 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4099
4097
4100 df = False
4098 df = False
4101 if opts.get("date"):
4099 if opts.get("date"):
4102 df = util.matchdate(opts["date"])
4100 df = util.matchdate(opts["date"])
4103
4101
4104 branches = opts.get('branch', []) + opts.get('only_branch', [])
4102 branches = opts.get('branch', []) + opts.get('only_branch', [])
4105 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4103 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4106
4104
4107 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4105 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4108 def prep(ctx, fns):
4106 def prep(ctx, fns):
4109 rev = ctx.rev()
4107 rev = ctx.rev()
4110 parents = [p for p in repo.changelog.parentrevs(rev)
4108 parents = [p for p in repo.changelog.parentrevs(rev)
4111 if p != nullrev]
4109 if p != nullrev]
4112 if opts.get('no_merges') and len(parents) == 2:
4110 if opts.get('no_merges') and len(parents) == 2:
4113 return
4111 return
4114 if opts.get('only_merges') and len(parents) != 2:
4112 if opts.get('only_merges') and len(parents) != 2:
4115 return
4113 return
4116 if opts.get('branch') and ctx.branch() not in opts['branch']:
4114 if opts.get('branch') and ctx.branch() not in opts['branch']:
4117 return
4115 return
4118 if not opts.get('hidden') and ctx.hidden():
4116 if not opts.get('hidden') and ctx.hidden():
4119 return
4117 return
4120 if df and not df(ctx.date()[0]):
4118 if df and not df(ctx.date()[0]):
4121 return
4119 return
4122
4120
4123 lower = encoding.lower
4121 lower = encoding.lower
4124 if opts.get('user'):
4122 if opts.get('user'):
4125 luser = lower(ctx.user())
4123 luser = lower(ctx.user())
4126 for k in [lower(x) for x in opts['user']]:
4124 for k in [lower(x) for x in opts['user']]:
4127 if (k in luser):
4125 if (k in luser):
4128 break
4126 break
4129 else:
4127 else:
4130 return
4128 return
4131 if opts.get('keyword'):
4129 if opts.get('keyword'):
4132 luser = lower(ctx.user())
4130 luser = lower(ctx.user())
4133 ldesc = lower(ctx.description())
4131 ldesc = lower(ctx.description())
4134 lfiles = lower(" ".join(ctx.files()))
4132 lfiles = lower(" ".join(ctx.files()))
4135 for k in [lower(x) for x in opts['keyword']]:
4133 for k in [lower(x) for x in opts['keyword']]:
4136 if (k in luser or k in ldesc or k in lfiles):
4134 if (k in luser or k in ldesc or k in lfiles):
4137 break
4135 break
4138 else:
4136 else:
4139 return
4137 return
4140
4138
4141 copies = None
4139 copies = None
4142 if getrenamed is not None and rev:
4140 if getrenamed is not None and rev:
4143 copies = []
4141 copies = []
4144 for fn in ctx.files():
4142 for fn in ctx.files():
4145 rename = getrenamed(fn, rev)
4143 rename = getrenamed(fn, rev)
4146 if rename:
4144 if rename:
4147 copies.append((fn, rename[0]))
4145 copies.append((fn, rename[0]))
4148
4146
4149 revmatchfn = None
4147 revmatchfn = None
4150 if opts.get('patch') or opts.get('stat'):
4148 if opts.get('patch') or opts.get('stat'):
4151 if opts.get('follow') or opts.get('follow_first'):
4149 if opts.get('follow') or opts.get('follow_first'):
4152 # note: this might be wrong when following through merges
4150 # note: this might be wrong when following through merges
4153 revmatchfn = scmutil.match(repo[None], fns, default='path')
4151 revmatchfn = scmutil.match(repo[None], fns, default='path')
4154 else:
4152 else:
4155 revmatchfn = matchfn
4153 revmatchfn = matchfn
4156
4154
4157 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4155 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4158
4156
4159 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4157 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4160 if count == limit:
4158 if count == limit:
4161 break
4159 break
4162 if displayer.flush(ctx.rev()):
4160 if displayer.flush(ctx.rev()):
4163 count += 1
4161 count += 1
4164 displayer.close()
4162 displayer.close()
4165
4163
4166 @command('manifest',
4164 @command('manifest',
4167 [('r', 'rev', '', _('revision to display'), _('REV')),
4165 [('r', 'rev', '', _('revision to display'), _('REV')),
4168 ('', 'all', False, _("list files from all revisions"))],
4166 ('', 'all', False, _("list files from all revisions"))],
4169 _('[-r REV]'))
4167 _('[-r REV]'))
4170 def manifest(ui, repo, node=None, rev=None, **opts):
4168 def manifest(ui, repo, node=None, rev=None, **opts):
4171 """output the current or given revision of the project manifest
4169 """output the current or given revision of the project manifest
4172
4170
4173 Print a list of version controlled files for the given revision.
4171 Print a list of version controlled files for the given revision.
4174 If no revision is given, the first parent of the working directory
4172 If no revision is given, the first parent of the working directory
4175 is used, or the null revision if no revision is checked out.
4173 is used, or the null revision if no revision is checked out.
4176
4174
4177 With -v, print file permissions, symlink and executable bits.
4175 With -v, print file permissions, symlink and executable bits.
4178 With --debug, print file revision hashes.
4176 With --debug, print file revision hashes.
4179
4177
4180 If option --all is specified, the list of all files from all revisions
4178 If option --all is specified, the list of all files from all revisions
4181 is printed. This includes deleted and renamed files.
4179 is printed. This includes deleted and renamed files.
4182
4180
4183 Returns 0 on success.
4181 Returns 0 on success.
4184 """
4182 """
4185 if opts.get('all'):
4183 if opts.get('all'):
4186 if rev or node:
4184 if rev or node:
4187 raise util.Abort(_("can't specify a revision with --all"))
4185 raise util.Abort(_("can't specify a revision with --all"))
4188
4186
4189 res = []
4187 res = []
4190 prefix = "data/"
4188 prefix = "data/"
4191 suffix = ".i"
4189 suffix = ".i"
4192 plen = len(prefix)
4190 plen = len(prefix)
4193 slen = len(suffix)
4191 slen = len(suffix)
4194 lock = repo.lock()
4192 lock = repo.lock()
4195 try:
4193 try:
4196 for fn, b, size in repo.store.datafiles():
4194 for fn, b, size in repo.store.datafiles():
4197 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4195 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4198 res.append(fn[plen:-slen])
4196 res.append(fn[plen:-slen])
4199 finally:
4197 finally:
4200 lock.release()
4198 lock.release()
4201 for f in res:
4199 for f in res:
4202 ui.write("%s\n" % f)
4200 ui.write("%s\n" % f)
4203 return
4201 return
4204
4202
4205 if rev and node:
4203 if rev and node:
4206 raise util.Abort(_("please specify just one revision"))
4204 raise util.Abort(_("please specify just one revision"))
4207
4205
4208 if not node:
4206 if not node:
4209 node = rev
4207 node = rev
4210
4208
4211 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4209 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4212 ctx = scmutil.revsingle(repo, node)
4210 ctx = scmutil.revsingle(repo, node)
4213 for f in ctx:
4211 for f in ctx:
4214 if ui.debugflag:
4212 if ui.debugflag:
4215 ui.write("%40s " % hex(ctx.manifest()[f]))
4213 ui.write("%40s " % hex(ctx.manifest()[f]))
4216 if ui.verbose:
4214 if ui.verbose:
4217 ui.write(decor[ctx.flags(f)])
4215 ui.write(decor[ctx.flags(f)])
4218 ui.write("%s\n" % f)
4216 ui.write("%s\n" % f)
4219
4217
4220 @command('^merge',
4218 @command('^merge',
4221 [('f', 'force', None, _('force a merge with outstanding changes')),
4219 [('f', 'force', None, _('force a merge with outstanding changes')),
4222 ('r', 'rev', '', _('revision to merge'), _('REV')),
4220 ('r', 'rev', '', _('revision to merge'), _('REV')),
4223 ('P', 'preview', None,
4221 ('P', 'preview', None,
4224 _('review revisions to merge (no merge is performed)'))
4222 _('review revisions to merge (no merge is performed)'))
4225 ] + mergetoolopts,
4223 ] + mergetoolopts,
4226 _('[-P] [-f] [[-r] REV]'))
4224 _('[-P] [-f] [[-r] REV]'))
4227 def merge(ui, repo, node=None, **opts):
4225 def merge(ui, repo, node=None, **opts):
4228 """merge working directory with another revision
4226 """merge working directory with another revision
4229
4227
4230 The current working directory is updated with all changes made in
4228 The current working directory is updated with all changes made in
4231 the requested revision since the last common predecessor revision.
4229 the requested revision since the last common predecessor revision.
4232
4230
4233 Files that changed between either parent are marked as changed for
4231 Files that changed between either parent are marked as changed for
4234 the next commit and a commit must be performed before any further
4232 the next commit and a commit must be performed before any further
4235 updates to the repository are allowed. The next commit will have
4233 updates to the repository are allowed. The next commit will have
4236 two parents.
4234 two parents.
4237
4235
4238 ``--tool`` can be used to specify the merge tool used for file
4236 ``--tool`` can be used to specify the merge tool used for file
4239 merges. It overrides the HGMERGE environment variable and your
4237 merges. It overrides the HGMERGE environment variable and your
4240 configuration files. See :hg:`help merge-tools` for options.
4238 configuration files. See :hg:`help merge-tools` for options.
4241
4239
4242 If no revision is specified, the working directory's parent is a
4240 If no revision is specified, the working directory's parent is a
4243 head revision, and the current branch contains exactly one other
4241 head revision, and the current branch contains exactly one other
4244 head, the other head is merged with by default. Otherwise, an
4242 head, the other head is merged with by default. Otherwise, an
4245 explicit revision with which to merge with must be provided.
4243 explicit revision with which to merge with must be provided.
4246
4244
4247 :hg:`resolve` must be used to resolve unresolved files.
4245 :hg:`resolve` must be used to resolve unresolved files.
4248
4246
4249 To undo an uncommitted merge, use :hg:`update --clean .` which
4247 To undo an uncommitted merge, use :hg:`update --clean .` which
4250 will check out a clean copy of the original merge parent, losing
4248 will check out a clean copy of the original merge parent, losing
4251 all changes.
4249 all changes.
4252
4250
4253 Returns 0 on success, 1 if there are unresolved files.
4251 Returns 0 on success, 1 if there are unresolved files.
4254 """
4252 """
4255
4253
4256 if opts.get('rev') and node:
4254 if opts.get('rev') and node:
4257 raise util.Abort(_("please specify just one revision"))
4255 raise util.Abort(_("please specify just one revision"))
4258 if not node:
4256 if not node:
4259 node = opts.get('rev')
4257 node = opts.get('rev')
4260
4258
4261 if node:
4259 if node:
4262 node = scmutil.revsingle(repo, node).node()
4260 node = scmutil.revsingle(repo, node).node()
4263
4261
4264 if not node and repo._bookmarkcurrent:
4262 if not node and repo._bookmarkcurrent:
4265 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4263 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4266 curhead = repo[repo._bookmarkcurrent]
4264 curhead = repo[repo._bookmarkcurrent]
4267 if len(bmheads) == 2:
4265 if len(bmheads) == 2:
4268 if curhead == bmheads[0]:
4266 if curhead == bmheads[0]:
4269 node = bmheads[1]
4267 node = bmheads[1]
4270 else:
4268 else:
4271 node = bmheads[0]
4269 node = bmheads[0]
4272 elif len(bmheads) > 2:
4270 elif len(bmheads) > 2:
4273 raise util.Abort(_("multiple matching bookmarks to merge - "
4271 raise util.Abort(_("multiple matching bookmarks to merge - "
4274 "please merge with an explicit rev or bookmark"),
4272 "please merge with an explicit rev or bookmark"),
4275 hint=_("run 'hg heads' to see all heads"))
4273 hint=_("run 'hg heads' to see all heads"))
4276 elif len(bmheads) <= 1:
4274 elif len(bmheads) <= 1:
4277 raise util.Abort(_("no matching bookmark to merge - "
4275 raise util.Abort(_("no matching bookmark to merge - "
4278 "please merge with an explicit rev or bookmark"),
4276 "please merge with an explicit rev or bookmark"),
4279 hint=_("run 'hg heads' to see all heads"))
4277 hint=_("run 'hg heads' to see all heads"))
4280
4278
4281 if not node and not repo._bookmarkcurrent:
4279 if not node and not repo._bookmarkcurrent:
4282 branch = repo[None].branch()
4280 branch = repo[None].branch()
4283 bheads = repo.branchheads(branch)
4281 bheads = repo.branchheads(branch)
4284 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4282 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4285
4283
4286 if len(nbhs) > 2:
4284 if len(nbhs) > 2:
4287 raise util.Abort(_("branch '%s' has %d heads - "
4285 raise util.Abort(_("branch '%s' has %d heads - "
4288 "please merge with an explicit rev")
4286 "please merge with an explicit rev")
4289 % (branch, len(bheads)),
4287 % (branch, len(bheads)),
4290 hint=_("run 'hg heads .' to see heads"))
4288 hint=_("run 'hg heads .' to see heads"))
4291
4289
4292 parent = repo.dirstate.p1()
4290 parent = repo.dirstate.p1()
4293 if len(nbhs) <= 1:
4291 if len(nbhs) <= 1:
4294 if len(bheads) > 1:
4292 if len(bheads) > 1:
4295 raise util.Abort(_("heads are bookmarked - "
4293 raise util.Abort(_("heads are bookmarked - "
4296 "please merge with an explicit rev"),
4294 "please merge with an explicit rev"),
4297 hint=_("run 'hg heads' to see all heads"))
4295 hint=_("run 'hg heads' to see all heads"))
4298 if len(repo.heads()) > 1:
4296 if len(repo.heads()) > 1:
4299 raise util.Abort(_("branch '%s' has one head - "
4297 raise util.Abort(_("branch '%s' has one head - "
4300 "please merge with an explicit rev")
4298 "please merge with an explicit rev")
4301 % branch,
4299 % branch,
4302 hint=_("run 'hg heads' to see all heads"))
4300 hint=_("run 'hg heads' to see all heads"))
4303 msg, hint = _('nothing to merge'), None
4301 msg, hint = _('nothing to merge'), None
4304 if parent != repo.lookup(branch):
4302 if parent != repo.lookup(branch):
4305 hint = _("use 'hg update' instead")
4303 hint = _("use 'hg update' instead")
4306 raise util.Abort(msg, hint=hint)
4304 raise util.Abort(msg, hint=hint)
4307
4305
4308 if parent not in bheads:
4306 if parent not in bheads:
4309 raise util.Abort(_('working directory not at a head revision'),
4307 raise util.Abort(_('working directory not at a head revision'),
4310 hint=_("use 'hg update' or merge with an "
4308 hint=_("use 'hg update' or merge with an "
4311 "explicit revision"))
4309 "explicit revision"))
4312 if parent == nbhs[0]:
4310 if parent == nbhs[0]:
4313 node = nbhs[-1]
4311 node = nbhs[-1]
4314 else:
4312 else:
4315 node = nbhs[0]
4313 node = nbhs[0]
4316
4314
4317 if opts.get('preview'):
4315 if opts.get('preview'):
4318 # find nodes that are ancestors of p2 but not of p1
4316 # find nodes that are ancestors of p2 but not of p1
4319 p1 = repo.lookup('.')
4317 p1 = repo.lookup('.')
4320 p2 = repo.lookup(node)
4318 p2 = repo.lookup(node)
4321 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4319 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4322
4320
4323 displayer = cmdutil.show_changeset(ui, repo, opts)
4321 displayer = cmdutil.show_changeset(ui, repo, opts)
4324 for node in nodes:
4322 for node in nodes:
4325 displayer.show(repo[node])
4323 displayer.show(repo[node])
4326 displayer.close()
4324 displayer.close()
4327 return 0
4325 return 0
4328
4326
4329 try:
4327 try:
4330 # ui.forcemerge is an internal variable, do not document
4328 # ui.forcemerge is an internal variable, do not document
4331 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4329 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4332 return hg.merge(repo, node, force=opts.get('force'))
4330 return hg.merge(repo, node, force=opts.get('force'))
4333 finally:
4331 finally:
4334 ui.setconfig('ui', 'forcemerge', '')
4332 ui.setconfig('ui', 'forcemerge', '')
4335
4333
4336 @command('outgoing|out',
4334 @command('outgoing|out',
4337 [('f', 'force', None, _('run even when the destination is unrelated')),
4335 [('f', 'force', None, _('run even when the destination is unrelated')),
4338 ('r', 'rev', [],
4336 ('r', 'rev', [],
4339 _('a changeset intended to be included in the destination'), _('REV')),
4337 _('a changeset intended to be included in the destination'), _('REV')),
4340 ('n', 'newest-first', None, _('show newest record first')),
4338 ('n', 'newest-first', None, _('show newest record first')),
4341 ('B', 'bookmarks', False, _('compare bookmarks')),
4339 ('B', 'bookmarks', False, _('compare bookmarks')),
4342 ('b', 'branch', [], _('a specific branch you would like to push'),
4340 ('b', 'branch', [], _('a specific branch you would like to push'),
4343 _('BRANCH')),
4341 _('BRANCH')),
4344 ] + logopts + remoteopts + subrepoopts,
4342 ] + logopts + remoteopts + subrepoopts,
4345 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4343 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4346 def outgoing(ui, repo, dest=None, **opts):
4344 def outgoing(ui, repo, dest=None, **opts):
4347 """show changesets not found in the destination
4345 """show changesets not found in the destination
4348
4346
4349 Show changesets not found in the specified destination repository
4347 Show changesets not found in the specified destination repository
4350 or the default push location. These are the changesets that would
4348 or the default push location. These are the changesets that would
4351 be pushed if a push was requested.
4349 be pushed if a push was requested.
4352
4350
4353 See pull for details of valid destination formats.
4351 See pull for details of valid destination formats.
4354
4352
4355 Returns 0 if there are outgoing changes, 1 otherwise.
4353 Returns 0 if there are outgoing changes, 1 otherwise.
4356 """
4354 """
4357 if opts.get('graph'):
4355 if opts.get('graph'):
4358 cmdutil.checkunsupportedgraphflags([], opts)
4356 cmdutil.checkunsupportedgraphflags([], opts)
4359 o = hg._outgoing(ui, repo, dest, opts)
4357 o = hg._outgoing(ui, repo, dest, opts)
4360 if o is None:
4358 if o is None:
4361 return
4359 return
4362
4360
4363 revdag = cmdutil.graphrevs(repo, o, opts)
4361 revdag = cmdutil.graphrevs(repo, o, opts)
4364 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4362 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4365 showparents = [ctx.node() for ctx in repo[None].parents()]
4363 showparents = [ctx.node() for ctx in repo[None].parents()]
4366 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4364 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4367 graphmod.asciiedges)
4365 graphmod.asciiedges)
4368 return 0
4366 return 0
4369
4367
4370 if opts.get('bookmarks'):
4368 if opts.get('bookmarks'):
4371 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4369 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4372 dest, branches = hg.parseurl(dest, opts.get('branch'))
4370 dest, branches = hg.parseurl(dest, opts.get('branch'))
4373 other = hg.peer(repo, opts, dest)
4371 other = hg.peer(repo, opts, dest)
4374 if 'bookmarks' not in other.listkeys('namespaces'):
4372 if 'bookmarks' not in other.listkeys('namespaces'):
4375 ui.warn(_("remote doesn't support bookmarks\n"))
4373 ui.warn(_("remote doesn't support bookmarks\n"))
4376 return 0
4374 return 0
4377 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4375 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4378 return bookmarks.diff(ui, other, repo)
4376 return bookmarks.diff(ui, other, repo)
4379
4377
4380 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4378 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4381 try:
4379 try:
4382 return hg.outgoing(ui, repo, dest, opts)
4380 return hg.outgoing(ui, repo, dest, opts)
4383 finally:
4381 finally:
4384 del repo._subtoppath
4382 del repo._subtoppath
4385
4383
4386 @command('parents',
4384 @command('parents',
4387 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4385 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4388 ] + templateopts,
4386 ] + templateopts,
4389 _('[-r REV] [FILE]'))
4387 _('[-r REV] [FILE]'))
4390 def parents(ui, repo, file_=None, **opts):
4388 def parents(ui, repo, file_=None, **opts):
4391 """show the parents of the working directory or revision
4389 """show the parents of the working directory or revision
4392
4390
4393 Print the working directory's parent revisions. If a revision is
4391 Print the working directory's parent revisions. If a revision is
4394 given via -r/--rev, the parent of that revision will be printed.
4392 given via -r/--rev, the parent of that revision will be printed.
4395 If a file argument is given, the revision in which the file was
4393 If a file argument is given, the revision in which the file was
4396 last changed (before the working directory revision or the
4394 last changed (before the working directory revision or the
4397 argument to --rev if given) is printed.
4395 argument to --rev if given) is printed.
4398
4396
4399 Returns 0 on success.
4397 Returns 0 on success.
4400 """
4398 """
4401
4399
4402 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4400 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4403
4401
4404 if file_:
4402 if file_:
4405 m = scmutil.match(ctx, (file_,), opts)
4403 m = scmutil.match(ctx, (file_,), opts)
4406 if m.anypats() or len(m.files()) != 1:
4404 if m.anypats() or len(m.files()) != 1:
4407 raise util.Abort(_('can only specify an explicit filename'))
4405 raise util.Abort(_('can only specify an explicit filename'))
4408 file_ = m.files()[0]
4406 file_ = m.files()[0]
4409 filenodes = []
4407 filenodes = []
4410 for cp in ctx.parents():
4408 for cp in ctx.parents():
4411 if not cp:
4409 if not cp:
4412 continue
4410 continue
4413 try:
4411 try:
4414 filenodes.append(cp.filenode(file_))
4412 filenodes.append(cp.filenode(file_))
4415 except error.LookupError:
4413 except error.LookupError:
4416 pass
4414 pass
4417 if not filenodes:
4415 if not filenodes:
4418 raise util.Abort(_("'%s' not found in manifest!") % file_)
4416 raise util.Abort(_("'%s' not found in manifest!") % file_)
4419 fl = repo.file(file_)
4417 fl = repo.file(file_)
4420 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4418 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4421 else:
4419 else:
4422 p = [cp.node() for cp in ctx.parents()]
4420 p = [cp.node() for cp in ctx.parents()]
4423
4421
4424 displayer = cmdutil.show_changeset(ui, repo, opts)
4422 displayer = cmdutil.show_changeset(ui, repo, opts)
4425 for n in p:
4423 for n in p:
4426 if n != nullid:
4424 if n != nullid:
4427 displayer.show(repo[n])
4425 displayer.show(repo[n])
4428 displayer.close()
4426 displayer.close()
4429
4427
4430 @command('paths', [], _('[NAME]'))
4428 @command('paths', [], _('[NAME]'))
4431 def paths(ui, repo, search=None):
4429 def paths(ui, repo, search=None):
4432 """show aliases for remote repositories
4430 """show aliases for remote repositories
4433
4431
4434 Show definition of symbolic path name NAME. If no name is given,
4432 Show definition of symbolic path name NAME. If no name is given,
4435 show definition of all available names.
4433 show definition of all available names.
4436
4434
4437 Option -q/--quiet suppresses all output when searching for NAME
4435 Option -q/--quiet suppresses all output when searching for NAME
4438 and shows only the path names when listing all definitions.
4436 and shows only the path names when listing all definitions.
4439
4437
4440 Path names are defined in the [paths] section of your
4438 Path names are defined in the [paths] section of your
4441 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4439 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4442 repository, ``.hg/hgrc`` is used, too.
4440 repository, ``.hg/hgrc`` is used, too.
4443
4441
4444 The path names ``default`` and ``default-push`` have a special
4442 The path names ``default`` and ``default-push`` have a special
4445 meaning. When performing a push or pull operation, they are used
4443 meaning. When performing a push or pull operation, they are used
4446 as fallbacks if no location is specified on the command-line.
4444 as fallbacks if no location is specified on the command-line.
4447 When ``default-push`` is set, it will be used for push and
4445 When ``default-push`` is set, it will be used for push and
4448 ``default`` will be used for pull; otherwise ``default`` is used
4446 ``default`` will be used for pull; otherwise ``default`` is used
4449 as the fallback for both. When cloning a repository, the clone
4447 as the fallback for both. When cloning a repository, the clone
4450 source is written as ``default`` in ``.hg/hgrc``. Note that
4448 source is written as ``default`` in ``.hg/hgrc``. Note that
4451 ``default`` and ``default-push`` apply to all inbound (e.g.
4449 ``default`` and ``default-push`` apply to all inbound (e.g.
4452 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4450 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4453 :hg:`bundle`) operations.
4451 :hg:`bundle`) operations.
4454
4452
4455 See :hg:`help urls` for more information.
4453 See :hg:`help urls` for more information.
4456
4454
4457 Returns 0 on success.
4455 Returns 0 on success.
4458 """
4456 """
4459 if search:
4457 if search:
4460 for name, path in ui.configitems("paths"):
4458 for name, path in ui.configitems("paths"):
4461 if name == search:
4459 if name == search:
4462 ui.status("%s\n" % util.hidepassword(path))
4460 ui.status("%s\n" % util.hidepassword(path))
4463 return
4461 return
4464 if not ui.quiet:
4462 if not ui.quiet:
4465 ui.warn(_("not found!\n"))
4463 ui.warn(_("not found!\n"))
4466 return 1
4464 return 1
4467 else:
4465 else:
4468 for name, path in ui.configitems("paths"):
4466 for name, path in ui.configitems("paths"):
4469 if ui.quiet:
4467 if ui.quiet:
4470 ui.write("%s\n" % name)
4468 ui.write("%s\n" % name)
4471 else:
4469 else:
4472 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4470 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4473
4471
4474 @command('^phase',
4472 @command('^phase',
4475 [('p', 'public', False, _('set changeset phase to public')),
4473 [('p', 'public', False, _('set changeset phase to public')),
4476 ('d', 'draft', False, _('set changeset phase to draft')),
4474 ('d', 'draft', False, _('set changeset phase to draft')),
4477 ('s', 'secret', False, _('set changeset phase to secret')),
4475 ('s', 'secret', False, _('set changeset phase to secret')),
4478 ('f', 'force', False, _('allow to move boundary backward')),
4476 ('f', 'force', False, _('allow to move boundary backward')),
4479 ('r', 'rev', [], _('target revision'), _('REV')),
4477 ('r', 'rev', [], _('target revision'), _('REV')),
4480 ],
4478 ],
4481 _('[-p|-d|-s] [-f] [-r] REV...'))
4479 _('[-p|-d|-s] [-f] [-r] REV...'))
4482 def phase(ui, repo, *revs, **opts):
4480 def phase(ui, repo, *revs, **opts):
4483 """set or show the current phase name
4481 """set or show the current phase name
4484
4482
4485 With no argument, show the phase name of specified revisions.
4483 With no argument, show the phase name of specified revisions.
4486
4484
4487 With one of -p/--public, -d/--draft or -s/--secret, change the
4485 With one of -p/--public, -d/--draft or -s/--secret, change the
4488 phase value of the specified revisions.
4486 phase value of the specified revisions.
4489
4487
4490 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4488 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4491 lower phase to an higher phase. Phases are ordered as follows::
4489 lower phase to an higher phase. Phases are ordered as follows::
4492
4490
4493 public < draft < secret
4491 public < draft < secret
4494
4492
4495 Return 0 on success, 1 if no phases were changed or some could not
4493 Return 0 on success, 1 if no phases were changed or some could not
4496 be changed.
4494 be changed.
4497 """
4495 """
4498 # search for a unique phase argument
4496 # search for a unique phase argument
4499 targetphase = None
4497 targetphase = None
4500 for idx, name in enumerate(phases.phasenames):
4498 for idx, name in enumerate(phases.phasenames):
4501 if opts[name]:
4499 if opts[name]:
4502 if targetphase is not None:
4500 if targetphase is not None:
4503 raise util.Abort(_('only one phase can be specified'))
4501 raise util.Abort(_('only one phase can be specified'))
4504 targetphase = idx
4502 targetphase = idx
4505
4503
4506 # look for specified revision
4504 # look for specified revision
4507 revs = list(revs)
4505 revs = list(revs)
4508 revs.extend(opts['rev'])
4506 revs.extend(opts['rev'])
4509 if not revs:
4507 if not revs:
4510 raise util.Abort(_('no revisions specified'))
4508 raise util.Abort(_('no revisions specified'))
4511
4509
4512 revs = scmutil.revrange(repo, revs)
4510 revs = scmutil.revrange(repo, revs)
4513
4511
4514 lock = None
4512 lock = None
4515 ret = 0
4513 ret = 0
4516 if targetphase is None:
4514 if targetphase is None:
4517 # display
4515 # display
4518 for r in revs:
4516 for r in revs:
4519 ctx = repo[r]
4517 ctx = repo[r]
4520 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4518 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4521 else:
4519 else:
4522 lock = repo.lock()
4520 lock = repo.lock()
4523 try:
4521 try:
4524 # set phase
4522 # set phase
4525 if not revs:
4523 if not revs:
4526 raise util.Abort(_('empty revision set'))
4524 raise util.Abort(_('empty revision set'))
4527 nodes = [repo[r].node() for r in revs]
4525 nodes = [repo[r].node() for r in revs]
4528 olddata = repo._phasecache.getphaserevs(repo)[:]
4526 olddata = repo._phasecache.getphaserevs(repo)[:]
4529 phases.advanceboundary(repo, targetphase, nodes)
4527 phases.advanceboundary(repo, targetphase, nodes)
4530 if opts['force']:
4528 if opts['force']:
4531 phases.retractboundary(repo, targetphase, nodes)
4529 phases.retractboundary(repo, targetphase, nodes)
4532 finally:
4530 finally:
4533 lock.release()
4531 lock.release()
4534 newdata = repo._phasecache.getphaserevs(repo)
4532 newdata = repo._phasecache.getphaserevs(repo)
4535 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4533 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4536 rejected = [n for n in nodes
4534 rejected = [n for n in nodes
4537 if newdata[repo[n].rev()] < targetphase]
4535 if newdata[repo[n].rev()] < targetphase]
4538 if rejected:
4536 if rejected:
4539 ui.warn(_('cannot move %i changesets to a more permissive '
4537 ui.warn(_('cannot move %i changesets to a more permissive '
4540 'phase, use --force\n') % len(rejected))
4538 'phase, use --force\n') % len(rejected))
4541 ret = 1
4539 ret = 1
4542 if changes:
4540 if changes:
4543 msg = _('phase changed for %i changesets\n') % changes
4541 msg = _('phase changed for %i changesets\n') % changes
4544 if ret:
4542 if ret:
4545 ui.status(msg)
4543 ui.status(msg)
4546 else:
4544 else:
4547 ui.note(msg)
4545 ui.note(msg)
4548 else:
4546 else:
4549 ui.warn(_('no phases changed\n'))
4547 ui.warn(_('no phases changed\n'))
4550 ret = 1
4548 ret = 1
4551 return ret
4549 return ret
4552
4550
4553 def postincoming(ui, repo, modheads, optupdate, checkout):
4551 def postincoming(ui, repo, modheads, optupdate, checkout):
4554 if modheads == 0:
4552 if modheads == 0:
4555 return
4553 return
4556 if optupdate:
4554 if optupdate:
4557 movemarkfrom = repo['.'].node()
4555 movemarkfrom = repo['.'].node()
4558 try:
4556 try:
4559 ret = hg.update(repo, checkout)
4557 ret = hg.update(repo, checkout)
4560 except util.Abort, inst:
4558 except util.Abort, inst:
4561 ui.warn(_("not updating: %s\n") % str(inst))
4559 ui.warn(_("not updating: %s\n") % str(inst))
4562 return 0
4560 return 0
4563 if not ret and not checkout:
4561 if not ret and not checkout:
4564 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4562 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4565 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4563 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4566 return ret
4564 return ret
4567 if modheads > 1:
4565 if modheads > 1:
4568 currentbranchheads = len(repo.branchheads())
4566 currentbranchheads = len(repo.branchheads())
4569 if currentbranchheads == modheads:
4567 if currentbranchheads == modheads:
4570 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4568 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4571 elif currentbranchheads > 1:
4569 elif currentbranchheads > 1:
4572 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4570 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4573 "merge)\n"))
4571 "merge)\n"))
4574 else:
4572 else:
4575 ui.status(_("(run 'hg heads' to see heads)\n"))
4573 ui.status(_("(run 'hg heads' to see heads)\n"))
4576 else:
4574 else:
4577 ui.status(_("(run 'hg update' to get a working copy)\n"))
4575 ui.status(_("(run 'hg update' to get a working copy)\n"))
4578
4576
4579 @command('^pull',
4577 @command('^pull',
4580 [('u', 'update', None,
4578 [('u', 'update', None,
4581 _('update to new branch head if changesets were pulled')),
4579 _('update to new branch head if changesets were pulled')),
4582 ('f', 'force', None, _('run even when remote repository is unrelated')),
4580 ('f', 'force', None, _('run even when remote repository is unrelated')),
4583 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4581 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4584 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4582 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4585 ('b', 'branch', [], _('a specific branch you would like to pull'),
4583 ('b', 'branch', [], _('a specific branch you would like to pull'),
4586 _('BRANCH')),
4584 _('BRANCH')),
4587 ] + remoteopts,
4585 ] + remoteopts,
4588 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4586 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4589 def pull(ui, repo, source="default", **opts):
4587 def pull(ui, repo, source="default", **opts):
4590 """pull changes from the specified source
4588 """pull changes from the specified source
4591
4589
4592 Pull changes from a remote repository to a local one.
4590 Pull changes from a remote repository to a local one.
4593
4591
4594 This finds all changes from the repository at the specified path
4592 This finds all changes from the repository at the specified path
4595 or URL and adds them to a local repository (the current one unless
4593 or URL and adds them to a local repository (the current one unless
4596 -R is specified). By default, this does not update the copy of the
4594 -R is specified). By default, this does not update the copy of the
4597 project in the working directory.
4595 project in the working directory.
4598
4596
4599 Use :hg:`incoming` if you want to see what would have been added
4597 Use :hg:`incoming` if you want to see what would have been added
4600 by a pull at the time you issued this command. If you then decide
4598 by a pull at the time you issued this command. If you then decide
4601 to add those changes to the repository, you should use :hg:`pull
4599 to add those changes to the repository, you should use :hg:`pull
4602 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4600 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4603
4601
4604 If SOURCE is omitted, the 'default' path will be used.
4602 If SOURCE is omitted, the 'default' path will be used.
4605 See :hg:`help urls` for more information.
4603 See :hg:`help urls` for more information.
4606
4604
4607 Returns 0 on success, 1 if an update had unresolved files.
4605 Returns 0 on success, 1 if an update had unresolved files.
4608 """
4606 """
4609 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4607 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4610 other = hg.peer(repo, opts, source)
4608 other = hg.peer(repo, opts, source)
4611 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4609 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4612 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4610 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4613
4611
4614 if opts.get('bookmark'):
4612 if opts.get('bookmark'):
4615 if not revs:
4613 if not revs:
4616 revs = []
4614 revs = []
4617 rb = other.listkeys('bookmarks')
4615 rb = other.listkeys('bookmarks')
4618 for b in opts['bookmark']:
4616 for b in opts['bookmark']:
4619 if b not in rb:
4617 if b not in rb:
4620 raise util.Abort(_('remote bookmark %s not found!') % b)
4618 raise util.Abort(_('remote bookmark %s not found!') % b)
4621 revs.append(rb[b])
4619 revs.append(rb[b])
4622
4620
4623 if revs:
4621 if revs:
4624 try:
4622 try:
4625 revs = [other.lookup(rev) for rev in revs]
4623 revs = [other.lookup(rev) for rev in revs]
4626 except error.CapabilityError:
4624 except error.CapabilityError:
4627 err = _("other repository doesn't support revision lookup, "
4625 err = _("other repository doesn't support revision lookup, "
4628 "so a rev cannot be specified.")
4626 "so a rev cannot be specified.")
4629 raise util.Abort(err)
4627 raise util.Abort(err)
4630
4628
4631 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4629 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4632 bookmarks.updatefromremote(ui, repo, other, source)
4630 bookmarks.updatefromremote(ui, repo, other, source)
4633 if checkout:
4631 if checkout:
4634 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4632 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4635 repo._subtoppath = source
4633 repo._subtoppath = source
4636 try:
4634 try:
4637 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4635 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4638
4636
4639 finally:
4637 finally:
4640 del repo._subtoppath
4638 del repo._subtoppath
4641
4639
4642 # update specified bookmarks
4640 # update specified bookmarks
4643 if opts.get('bookmark'):
4641 if opts.get('bookmark'):
4644 for b in opts['bookmark']:
4642 for b in opts['bookmark']:
4645 # explicit pull overrides local bookmark if any
4643 # explicit pull overrides local bookmark if any
4646 ui.status(_("importing bookmark %s\n") % b)
4644 ui.status(_("importing bookmark %s\n") % b)
4647 repo._bookmarks[b] = repo[rb[b]].node()
4645 repo._bookmarks[b] = repo[rb[b]].node()
4648 bookmarks.write(repo)
4646 bookmarks.write(repo)
4649
4647
4650 return ret
4648 return ret
4651
4649
4652 @command('^push',
4650 @command('^push',
4653 [('f', 'force', None, _('force push')),
4651 [('f', 'force', None, _('force push')),
4654 ('r', 'rev', [],
4652 ('r', 'rev', [],
4655 _('a changeset intended to be included in the destination'),
4653 _('a changeset intended to be included in the destination'),
4656 _('REV')),
4654 _('REV')),
4657 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4655 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4658 ('b', 'branch', [],
4656 ('b', 'branch', [],
4659 _('a specific branch you would like to push'), _('BRANCH')),
4657 _('a specific branch you would like to push'), _('BRANCH')),
4660 ('', 'new-branch', False, _('allow pushing a new branch')),
4658 ('', 'new-branch', False, _('allow pushing a new branch')),
4661 ] + remoteopts,
4659 ] + remoteopts,
4662 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4660 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4663 def push(ui, repo, dest=None, **opts):
4661 def push(ui, repo, dest=None, **opts):
4664 """push changes to the specified destination
4662 """push changes to the specified destination
4665
4663
4666 Push changesets from the local repository to the specified
4664 Push changesets from the local repository to the specified
4667 destination.
4665 destination.
4668
4666
4669 This operation is symmetrical to pull: it is identical to a pull
4667 This operation is symmetrical to pull: it is identical to a pull
4670 in the destination repository from the current one.
4668 in the destination repository from the current one.
4671
4669
4672 By default, push will not allow creation of new heads at the
4670 By default, push will not allow creation of new heads at the
4673 destination, since multiple heads would make it unclear which head
4671 destination, since multiple heads would make it unclear which head
4674 to use. In this situation, it is recommended to pull and merge
4672 to use. In this situation, it is recommended to pull and merge
4675 before pushing.
4673 before pushing.
4676
4674
4677 Use --new-branch if you want to allow push to create a new named
4675 Use --new-branch if you want to allow push to create a new named
4678 branch that is not present at the destination. This allows you to
4676 branch that is not present at the destination. This allows you to
4679 only create a new branch without forcing other changes.
4677 only create a new branch without forcing other changes.
4680
4678
4681 Use -f/--force to override the default behavior and push all
4679 Use -f/--force to override the default behavior and push all
4682 changesets on all branches.
4680 changesets on all branches.
4683
4681
4684 If -r/--rev is used, the specified revision and all its ancestors
4682 If -r/--rev is used, the specified revision and all its ancestors
4685 will be pushed to the remote repository.
4683 will be pushed to the remote repository.
4686
4684
4687 If -B/--bookmark is used, the specified bookmarked revision, its
4685 If -B/--bookmark is used, the specified bookmarked revision, its
4688 ancestors, and the bookmark will be pushed to the remote
4686 ancestors, and the bookmark will be pushed to the remote
4689 repository.
4687 repository.
4690
4688
4691 Please see :hg:`help urls` for important details about ``ssh://``
4689 Please see :hg:`help urls` for important details about ``ssh://``
4692 URLs. If DESTINATION is omitted, a default path will be used.
4690 URLs. If DESTINATION is omitted, a default path will be used.
4693
4691
4694 Returns 0 if push was successful, 1 if nothing to push.
4692 Returns 0 if push was successful, 1 if nothing to push.
4695 """
4693 """
4696
4694
4697 if opts.get('bookmark'):
4695 if opts.get('bookmark'):
4698 for b in opts['bookmark']:
4696 for b in opts['bookmark']:
4699 # translate -B options to -r so changesets get pushed
4697 # translate -B options to -r so changesets get pushed
4700 if b in repo._bookmarks:
4698 if b in repo._bookmarks:
4701 opts.setdefault('rev', []).append(b)
4699 opts.setdefault('rev', []).append(b)
4702 else:
4700 else:
4703 # if we try to push a deleted bookmark, translate it to null
4701 # if we try to push a deleted bookmark, translate it to null
4704 # this lets simultaneous -r, -b options continue working
4702 # this lets simultaneous -r, -b options continue working
4705 opts.setdefault('rev', []).append("null")
4703 opts.setdefault('rev', []).append("null")
4706
4704
4707 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4705 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4708 dest, branches = hg.parseurl(dest, opts.get('branch'))
4706 dest, branches = hg.parseurl(dest, opts.get('branch'))
4709 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4707 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4710 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4708 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4711 other = hg.peer(repo, opts, dest)
4709 other = hg.peer(repo, opts, dest)
4712 if revs:
4710 if revs:
4713 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4711 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4714
4712
4715 repo._subtoppath = dest
4713 repo._subtoppath = dest
4716 try:
4714 try:
4717 # push subrepos depth-first for coherent ordering
4715 # push subrepos depth-first for coherent ordering
4718 c = repo['']
4716 c = repo['']
4719 subs = c.substate # only repos that are committed
4717 subs = c.substate # only repos that are committed
4720 for s in sorted(subs):
4718 for s in sorted(subs):
4721 if c.sub(s).push(opts) == 0:
4719 if c.sub(s).push(opts) == 0:
4722 return False
4720 return False
4723 finally:
4721 finally:
4724 del repo._subtoppath
4722 del repo._subtoppath
4725 result = repo.push(other, opts.get('force'), revs=revs,
4723 result = repo.push(other, opts.get('force'), revs=revs,
4726 newbranch=opts.get('new_branch'))
4724 newbranch=opts.get('new_branch'))
4727
4725
4728 result = not result
4726 result = not result
4729
4727
4730 if opts.get('bookmark'):
4728 if opts.get('bookmark'):
4731 rb = other.listkeys('bookmarks')
4729 rb = other.listkeys('bookmarks')
4732 for b in opts['bookmark']:
4730 for b in opts['bookmark']:
4733 # explicit push overrides remote bookmark if any
4731 # explicit push overrides remote bookmark if any
4734 if b in repo._bookmarks:
4732 if b in repo._bookmarks:
4735 ui.status(_("exporting bookmark %s\n") % b)
4733 ui.status(_("exporting bookmark %s\n") % b)
4736 new = repo[b].hex()
4734 new = repo[b].hex()
4737 elif b in rb:
4735 elif b in rb:
4738 ui.status(_("deleting remote bookmark %s\n") % b)
4736 ui.status(_("deleting remote bookmark %s\n") % b)
4739 new = '' # delete
4737 new = '' # delete
4740 else:
4738 else:
4741 ui.warn(_('bookmark %s does not exist on the local '
4739 ui.warn(_('bookmark %s does not exist on the local '
4742 'or remote repository!\n') % b)
4740 'or remote repository!\n') % b)
4743 return 2
4741 return 2
4744 old = rb.get(b, '')
4742 old = rb.get(b, '')
4745 r = other.pushkey('bookmarks', b, old, new)
4743 r = other.pushkey('bookmarks', b, old, new)
4746 if not r:
4744 if not r:
4747 ui.warn(_('updating bookmark %s failed!\n') % b)
4745 ui.warn(_('updating bookmark %s failed!\n') % b)
4748 if not result:
4746 if not result:
4749 result = 2
4747 result = 2
4750
4748
4751 return result
4749 return result
4752
4750
4753 @command('recover', [])
4751 @command('recover', [])
4754 def recover(ui, repo):
4752 def recover(ui, repo):
4755 """roll back an interrupted transaction
4753 """roll back an interrupted transaction
4756
4754
4757 Recover from an interrupted commit or pull.
4755 Recover from an interrupted commit or pull.
4758
4756
4759 This command tries to fix the repository status after an
4757 This command tries to fix the repository status after an
4760 interrupted operation. It should only be necessary when Mercurial
4758 interrupted operation. It should only be necessary when Mercurial
4761 suggests it.
4759 suggests it.
4762
4760
4763 Returns 0 if successful, 1 if nothing to recover or verify fails.
4761 Returns 0 if successful, 1 if nothing to recover or verify fails.
4764 """
4762 """
4765 if repo.recover():
4763 if repo.recover():
4766 return hg.verify(repo)
4764 return hg.verify(repo)
4767 return 1
4765 return 1
4768
4766
4769 @command('^remove|rm',
4767 @command('^remove|rm',
4770 [('A', 'after', None, _('record delete for missing files')),
4768 [('A', 'after', None, _('record delete for missing files')),
4771 ('f', 'force', None,
4769 ('f', 'force', None,
4772 _('remove (and delete) file even if added or modified')),
4770 _('remove (and delete) file even if added or modified')),
4773 ] + walkopts,
4771 ] + walkopts,
4774 _('[OPTION]... FILE...'))
4772 _('[OPTION]... FILE...'))
4775 def remove(ui, repo, *pats, **opts):
4773 def remove(ui, repo, *pats, **opts):
4776 """remove the specified files on the next commit
4774 """remove the specified files on the next commit
4777
4775
4778 Schedule the indicated files for removal from the current branch.
4776 Schedule the indicated files for removal from the current branch.
4779
4777
4780 This command schedules the files to be removed at the next commit.
4778 This command schedules the files to be removed at the next commit.
4781 To undo a remove before that, see :hg:`revert`. To undo added
4779 To undo a remove before that, see :hg:`revert`. To undo added
4782 files, see :hg:`forget`.
4780 files, see :hg:`forget`.
4783
4781
4784 .. container:: verbose
4782 .. container:: verbose
4785
4783
4786 -A/--after can be used to remove only files that have already
4784 -A/--after can be used to remove only files that have already
4787 been deleted, -f/--force can be used to force deletion, and -Af
4785 been deleted, -f/--force can be used to force deletion, and -Af
4788 can be used to remove files from the next revision without
4786 can be used to remove files from the next revision without
4789 deleting them from the working directory.
4787 deleting them from the working directory.
4790
4788
4791 The following table details the behavior of remove for different
4789 The following table details the behavior of remove for different
4792 file states (columns) and option combinations (rows). The file
4790 file states (columns) and option combinations (rows). The file
4793 states are Added [A], Clean [C], Modified [M] and Missing [!]
4791 states are Added [A], Clean [C], Modified [M] and Missing [!]
4794 (as reported by :hg:`status`). The actions are Warn, Remove
4792 (as reported by :hg:`status`). The actions are Warn, Remove
4795 (from branch) and Delete (from disk):
4793 (from branch) and Delete (from disk):
4796
4794
4797 ======= == == == ==
4795 ======= == == == ==
4798 A C M !
4796 A C M !
4799 ======= == == == ==
4797 ======= == == == ==
4800 none W RD W R
4798 none W RD W R
4801 -f R RD RD R
4799 -f R RD RD R
4802 -A W W W R
4800 -A W W W R
4803 -Af R R R R
4801 -Af R R R R
4804 ======= == == == ==
4802 ======= == == == ==
4805
4803
4806 Note that remove never deletes files in Added [A] state from the
4804 Note that remove never deletes files in Added [A] state from the
4807 working directory, not even if option --force is specified.
4805 working directory, not even if option --force is specified.
4808
4806
4809 Returns 0 on success, 1 if any warnings encountered.
4807 Returns 0 on success, 1 if any warnings encountered.
4810 """
4808 """
4811
4809
4812 ret = 0
4810 ret = 0
4813 after, force = opts.get('after'), opts.get('force')
4811 after, force = opts.get('after'), opts.get('force')
4814 if not pats and not after:
4812 if not pats and not after:
4815 raise util.Abort(_('no files specified'))
4813 raise util.Abort(_('no files specified'))
4816
4814
4817 m = scmutil.match(repo[None], pats, opts)
4815 m = scmutil.match(repo[None], pats, opts)
4818 s = repo.status(match=m, clean=True)
4816 s = repo.status(match=m, clean=True)
4819 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4817 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4820
4818
4821 for f in m.files():
4819 for f in m.files():
4822 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4820 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4823 if os.path.exists(m.rel(f)):
4821 if os.path.exists(m.rel(f)):
4824 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4822 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4825 ret = 1
4823 ret = 1
4826
4824
4827 if force:
4825 if force:
4828 list = modified + deleted + clean + added
4826 list = modified + deleted + clean + added
4829 elif after:
4827 elif after:
4830 list = deleted
4828 list = deleted
4831 for f in modified + added + clean:
4829 for f in modified + added + clean:
4832 ui.warn(_('not removing %s: file still exists (use -f'
4830 ui.warn(_('not removing %s: file still exists (use -f'
4833 ' to force removal)\n') % m.rel(f))
4831 ' to force removal)\n') % m.rel(f))
4834 ret = 1
4832 ret = 1
4835 else:
4833 else:
4836 list = deleted + clean
4834 list = deleted + clean
4837 for f in modified:
4835 for f in modified:
4838 ui.warn(_('not removing %s: file is modified (use -f'
4836 ui.warn(_('not removing %s: file is modified (use -f'
4839 ' to force removal)\n') % m.rel(f))
4837 ' to force removal)\n') % m.rel(f))
4840 ret = 1
4838 ret = 1
4841 for f in added:
4839 for f in added:
4842 ui.warn(_('not removing %s: file has been marked for add'
4840 ui.warn(_('not removing %s: file has been marked for add'
4843 ' (use forget to undo)\n') % m.rel(f))
4841 ' (use forget to undo)\n') % m.rel(f))
4844 ret = 1
4842 ret = 1
4845
4843
4846 for f in sorted(list):
4844 for f in sorted(list):
4847 if ui.verbose or not m.exact(f):
4845 if ui.verbose or not m.exact(f):
4848 ui.status(_('removing %s\n') % m.rel(f))
4846 ui.status(_('removing %s\n') % m.rel(f))
4849
4847
4850 wlock = repo.wlock()
4848 wlock = repo.wlock()
4851 try:
4849 try:
4852 if not after:
4850 if not after:
4853 for f in list:
4851 for f in list:
4854 if f in added:
4852 if f in added:
4855 continue # we never unlink added files on remove
4853 continue # we never unlink added files on remove
4856 try:
4854 try:
4857 util.unlinkpath(repo.wjoin(f))
4855 util.unlinkpath(repo.wjoin(f))
4858 except OSError, inst:
4856 except OSError, inst:
4859 if inst.errno != errno.ENOENT:
4857 if inst.errno != errno.ENOENT:
4860 raise
4858 raise
4861 repo[None].forget(list)
4859 repo[None].forget(list)
4862 finally:
4860 finally:
4863 wlock.release()
4861 wlock.release()
4864
4862
4865 return ret
4863 return ret
4866
4864
4867 @command('rename|move|mv',
4865 @command('rename|move|mv',
4868 [('A', 'after', None, _('record a rename that has already occurred')),
4866 [('A', 'after', None, _('record a rename that has already occurred')),
4869 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4867 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4870 ] + walkopts + dryrunopts,
4868 ] + walkopts + dryrunopts,
4871 _('[OPTION]... SOURCE... DEST'))
4869 _('[OPTION]... SOURCE... DEST'))
4872 def rename(ui, repo, *pats, **opts):
4870 def rename(ui, repo, *pats, **opts):
4873 """rename files; equivalent of copy + remove
4871 """rename files; equivalent of copy + remove
4874
4872
4875 Mark dest as copies of sources; mark sources for deletion. If dest
4873 Mark dest as copies of sources; mark sources for deletion. If dest
4876 is a directory, copies are put in that directory. If dest is a
4874 is a directory, copies are put in that directory. If dest is a
4877 file, there can only be one source.
4875 file, there can only be one source.
4878
4876
4879 By default, this command copies the contents of files as they
4877 By default, this command copies the contents of files as they
4880 exist in the working directory. If invoked with -A/--after, the
4878 exist in the working directory. If invoked with -A/--after, the
4881 operation is recorded, but no copying is performed.
4879 operation is recorded, but no copying is performed.
4882
4880
4883 This command takes effect at the next commit. To undo a rename
4881 This command takes effect at the next commit. To undo a rename
4884 before that, see :hg:`revert`.
4882 before that, see :hg:`revert`.
4885
4883
4886 Returns 0 on success, 1 if errors are encountered.
4884 Returns 0 on success, 1 if errors are encountered.
4887 """
4885 """
4888 wlock = repo.wlock(False)
4886 wlock = repo.wlock(False)
4889 try:
4887 try:
4890 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4888 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4891 finally:
4889 finally:
4892 wlock.release()
4890 wlock.release()
4893
4891
4894 @command('resolve',
4892 @command('resolve',
4895 [('a', 'all', None, _('select all unresolved files')),
4893 [('a', 'all', None, _('select all unresolved files')),
4896 ('l', 'list', None, _('list state of files needing merge')),
4894 ('l', 'list', None, _('list state of files needing merge')),
4897 ('m', 'mark', None, _('mark files as resolved')),
4895 ('m', 'mark', None, _('mark files as resolved')),
4898 ('u', 'unmark', None, _('mark files as unresolved')),
4896 ('u', 'unmark', None, _('mark files as unresolved')),
4899 ('n', 'no-status', None, _('hide status prefix'))]
4897 ('n', 'no-status', None, _('hide status prefix'))]
4900 + mergetoolopts + walkopts,
4898 + mergetoolopts + walkopts,
4901 _('[OPTION]... [FILE]...'))
4899 _('[OPTION]... [FILE]...'))
4902 def resolve(ui, repo, *pats, **opts):
4900 def resolve(ui, repo, *pats, **opts):
4903 """redo merges or set/view the merge status of files
4901 """redo merges or set/view the merge status of files
4904
4902
4905 Merges with unresolved conflicts are often the result of
4903 Merges with unresolved conflicts are often the result of
4906 non-interactive merging using the ``internal:merge`` configuration
4904 non-interactive merging using the ``internal:merge`` configuration
4907 setting, or a command-line merge tool like ``diff3``. The resolve
4905 setting, or a command-line merge tool like ``diff3``. The resolve
4908 command is used to manage the files involved in a merge, after
4906 command is used to manage the files involved in a merge, after
4909 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4907 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4910 working directory must have two parents). See :hg:`help
4908 working directory must have two parents). See :hg:`help
4911 merge-tools` for information on configuring merge tools.
4909 merge-tools` for information on configuring merge tools.
4912
4910
4913 The resolve command can be used in the following ways:
4911 The resolve command can be used in the following ways:
4914
4912
4915 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4913 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4916 files, discarding any previous merge attempts. Re-merging is not
4914 files, discarding any previous merge attempts. Re-merging is not
4917 performed for files already marked as resolved. Use ``--all/-a``
4915 performed for files already marked as resolved. Use ``--all/-a``
4918 to select all unresolved files. ``--tool`` can be used to specify
4916 to select all unresolved files. ``--tool`` can be used to specify
4919 the merge tool used for the given files. It overrides the HGMERGE
4917 the merge tool used for the given files. It overrides the HGMERGE
4920 environment variable and your configuration files. Previous file
4918 environment variable and your configuration files. Previous file
4921 contents are saved with a ``.orig`` suffix.
4919 contents are saved with a ``.orig`` suffix.
4922
4920
4923 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4921 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4924 (e.g. after having manually fixed-up the files). The default is
4922 (e.g. after having manually fixed-up the files). The default is
4925 to mark all unresolved files.
4923 to mark all unresolved files.
4926
4924
4927 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4925 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4928 default is to mark all resolved files.
4926 default is to mark all resolved files.
4929
4927
4930 - :hg:`resolve -l`: list files which had or still have conflicts.
4928 - :hg:`resolve -l`: list files which had or still have conflicts.
4931 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4929 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4932
4930
4933 Note that Mercurial will not let you commit files with unresolved
4931 Note that Mercurial will not let you commit files with unresolved
4934 merge conflicts. You must use :hg:`resolve -m ...` before you can
4932 merge conflicts. You must use :hg:`resolve -m ...` before you can
4935 commit after a conflicting merge.
4933 commit after a conflicting merge.
4936
4934
4937 Returns 0 on success, 1 if any files fail a resolve attempt.
4935 Returns 0 on success, 1 if any files fail a resolve attempt.
4938 """
4936 """
4939
4937
4940 all, mark, unmark, show, nostatus = \
4938 all, mark, unmark, show, nostatus = \
4941 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4939 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4942
4940
4943 if (show and (mark or unmark)) or (mark and unmark):
4941 if (show and (mark or unmark)) or (mark and unmark):
4944 raise util.Abort(_("too many options specified"))
4942 raise util.Abort(_("too many options specified"))
4945 if pats and all:
4943 if pats and all:
4946 raise util.Abort(_("can't specify --all and patterns"))
4944 raise util.Abort(_("can't specify --all and patterns"))
4947 if not (all or pats or show or mark or unmark):
4945 if not (all or pats or show or mark or unmark):
4948 raise util.Abort(_('no files or directories specified; '
4946 raise util.Abort(_('no files or directories specified; '
4949 'use --all to remerge all files'))
4947 'use --all to remerge all files'))
4950
4948
4951 ms = mergemod.mergestate(repo)
4949 ms = mergemod.mergestate(repo)
4952 m = scmutil.match(repo[None], pats, opts)
4950 m = scmutil.match(repo[None], pats, opts)
4953 ret = 0
4951 ret = 0
4954
4952
4955 for f in ms:
4953 for f in ms:
4956 if m(f):
4954 if m(f):
4957 if show:
4955 if show:
4958 if nostatus:
4956 if nostatus:
4959 ui.write("%s\n" % f)
4957 ui.write("%s\n" % f)
4960 else:
4958 else:
4961 ui.write("%s %s\n" % (ms[f].upper(), f),
4959 ui.write("%s %s\n" % (ms[f].upper(), f),
4962 label='resolve.' +
4960 label='resolve.' +
4963 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4961 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4964 elif mark:
4962 elif mark:
4965 ms.mark(f, "r")
4963 ms.mark(f, "r")
4966 elif unmark:
4964 elif unmark:
4967 ms.mark(f, "u")
4965 ms.mark(f, "u")
4968 else:
4966 else:
4969 wctx = repo[None]
4967 wctx = repo[None]
4970 mctx = wctx.parents()[-1]
4968 mctx = wctx.parents()[-1]
4971
4969
4972 # backup pre-resolve (merge uses .orig for its own purposes)
4970 # backup pre-resolve (merge uses .orig for its own purposes)
4973 a = repo.wjoin(f)
4971 a = repo.wjoin(f)
4974 util.copyfile(a, a + ".resolve")
4972 util.copyfile(a, a + ".resolve")
4975
4973
4976 try:
4974 try:
4977 # resolve file
4975 # resolve file
4978 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4976 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4979 if ms.resolve(f, wctx, mctx):
4977 if ms.resolve(f, wctx, mctx):
4980 ret = 1
4978 ret = 1
4981 finally:
4979 finally:
4982 ui.setconfig('ui', 'forcemerge', '')
4980 ui.setconfig('ui', 'forcemerge', '')
4983 ms.commit()
4981 ms.commit()
4984
4982
4985 # replace filemerge's .orig file with our resolve file
4983 # replace filemerge's .orig file with our resolve file
4986 util.rename(a + ".resolve", a + ".orig")
4984 util.rename(a + ".resolve", a + ".orig")
4987
4985
4988 ms.commit()
4986 ms.commit()
4989 return ret
4987 return ret
4990
4988
4991 @command('revert',
4989 @command('revert',
4992 [('a', 'all', None, _('revert all changes when no arguments given')),
4990 [('a', 'all', None, _('revert all changes when no arguments given')),
4993 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4991 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4994 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4992 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4995 ('C', 'no-backup', None, _('do not save backup copies of files')),
4993 ('C', 'no-backup', None, _('do not save backup copies of files')),
4996 ] + walkopts + dryrunopts,
4994 ] + walkopts + dryrunopts,
4997 _('[OPTION]... [-r REV] [NAME]...'))
4995 _('[OPTION]... [-r REV] [NAME]...'))
4998 def revert(ui, repo, *pats, **opts):
4996 def revert(ui, repo, *pats, **opts):
4999 """restore files to their checkout state
4997 """restore files to their checkout state
5000
4998
5001 .. note::
4999 .. note::
5002
5000
5003 To check out earlier revisions, you should use :hg:`update REV`.
5001 To check out earlier revisions, you should use :hg:`update REV`.
5004 To cancel an uncommitted merge (and lose your changes), use
5002 To cancel an uncommitted merge (and lose your changes), use
5005 :hg:`update --clean .`.
5003 :hg:`update --clean .`.
5006
5004
5007 With no revision specified, revert the specified files or directories
5005 With no revision specified, revert the specified files or directories
5008 to the contents they had in the parent of the working directory.
5006 to the contents they had in the parent of the working directory.
5009 This restores the contents of files to an unmodified
5007 This restores the contents of files to an unmodified
5010 state and unschedules adds, removes, copies, and renames. If the
5008 state and unschedules adds, removes, copies, and renames. If the
5011 working directory has two parents, you must explicitly specify a
5009 working directory has two parents, you must explicitly specify a
5012 revision.
5010 revision.
5013
5011
5014 Using the -r/--rev or -d/--date options, revert the given files or
5012 Using the -r/--rev or -d/--date options, revert the given files or
5015 directories to their states as of a specific revision. Because
5013 directories to their states as of a specific revision. Because
5016 revert does not change the working directory parents, this will
5014 revert does not change the working directory parents, this will
5017 cause these files to appear modified. This can be helpful to "back
5015 cause these files to appear modified. This can be helpful to "back
5018 out" some or all of an earlier change. See :hg:`backout` for a
5016 out" some or all of an earlier change. See :hg:`backout` for a
5019 related method.
5017 related method.
5020
5018
5021 Modified files are saved with a .orig suffix before reverting.
5019 Modified files are saved with a .orig suffix before reverting.
5022 To disable these backups, use --no-backup.
5020 To disable these backups, use --no-backup.
5023
5021
5024 See :hg:`help dates` for a list of formats valid for -d/--date.
5022 See :hg:`help dates` for a list of formats valid for -d/--date.
5025
5023
5026 Returns 0 on success.
5024 Returns 0 on success.
5027 """
5025 """
5028
5026
5029 if opts.get("date"):
5027 if opts.get("date"):
5030 if opts.get("rev"):
5028 if opts.get("rev"):
5031 raise util.Abort(_("you can't specify a revision and a date"))
5029 raise util.Abort(_("you can't specify a revision and a date"))
5032 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5030 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5033
5031
5034 parent, p2 = repo.dirstate.parents()
5032 parent, p2 = repo.dirstate.parents()
5035 if not opts.get('rev') and p2 != nullid:
5033 if not opts.get('rev') and p2 != nullid:
5036 # revert after merge is a trap for new users (issue2915)
5034 # revert after merge is a trap for new users (issue2915)
5037 raise util.Abort(_('uncommitted merge with no revision specified'),
5035 raise util.Abort(_('uncommitted merge with no revision specified'),
5038 hint=_('use "hg update" or see "hg help revert"'))
5036 hint=_('use "hg update" or see "hg help revert"'))
5039
5037
5040 ctx = scmutil.revsingle(repo, opts.get('rev'))
5038 ctx = scmutil.revsingle(repo, opts.get('rev'))
5041
5039
5042 if not pats and not opts.get('all'):
5040 if not pats and not opts.get('all'):
5043 msg = _("no files or directories specified")
5041 msg = _("no files or directories specified")
5044 if p2 != nullid:
5042 if p2 != nullid:
5045 hint = _("uncommitted merge, use --all to discard all changes,"
5043 hint = _("uncommitted merge, use --all to discard all changes,"
5046 " or 'hg update -C .' to abort the merge")
5044 " or 'hg update -C .' to abort the merge")
5047 raise util.Abort(msg, hint=hint)
5045 raise util.Abort(msg, hint=hint)
5048 dirty = util.any(repo.status())
5046 dirty = util.any(repo.status())
5049 node = ctx.node()
5047 node = ctx.node()
5050 if node != parent:
5048 if node != parent:
5051 if dirty:
5049 if dirty:
5052 hint = _("uncommitted changes, use --all to discard all"
5050 hint = _("uncommitted changes, use --all to discard all"
5053 " changes, or 'hg update %s' to update") % ctx.rev()
5051 " changes, or 'hg update %s' to update") % ctx.rev()
5054 else:
5052 else:
5055 hint = _("use --all to revert all files,"
5053 hint = _("use --all to revert all files,"
5056 " or 'hg update %s' to update") % ctx.rev()
5054 " or 'hg update %s' to update") % ctx.rev()
5057 elif dirty:
5055 elif dirty:
5058 hint = _("uncommitted changes, use --all to discard all changes")
5056 hint = _("uncommitted changes, use --all to discard all changes")
5059 else:
5057 else:
5060 hint = _("use --all to revert all files")
5058 hint = _("use --all to revert all files")
5061 raise util.Abort(msg, hint=hint)
5059 raise util.Abort(msg, hint=hint)
5062
5060
5063 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5061 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5064
5062
5065 @command('rollback', dryrunopts +
5063 @command('rollback', dryrunopts +
5066 [('f', 'force', False, _('ignore safety measures'))])
5064 [('f', 'force', False, _('ignore safety measures'))])
5067 def rollback(ui, repo, **opts):
5065 def rollback(ui, repo, **opts):
5068 """roll back the last transaction (dangerous)
5066 """roll back the last transaction (dangerous)
5069
5067
5070 This command should be used with care. There is only one level of
5068 This command should be used with care. There is only one level of
5071 rollback, and there is no way to undo a rollback. It will also
5069 rollback, and there is no way to undo a rollback. It will also
5072 restore the dirstate at the time of the last transaction, losing
5070 restore the dirstate at the time of the last transaction, losing
5073 any dirstate changes since that time. This command does not alter
5071 any dirstate changes since that time. This command does not alter
5074 the working directory.
5072 the working directory.
5075
5073
5076 Transactions are used to encapsulate the effects of all commands
5074 Transactions are used to encapsulate the effects of all commands
5077 that create new changesets or propagate existing changesets into a
5075 that create new changesets or propagate existing changesets into a
5078 repository.
5076 repository.
5079
5077
5080 .. container:: verbose
5078 .. container:: verbose
5081
5079
5082 For example, the following commands are transactional, and their
5080 For example, the following commands are transactional, and their
5083 effects can be rolled back:
5081 effects can be rolled back:
5084
5082
5085 - commit
5083 - commit
5086 - import
5084 - import
5087 - pull
5085 - pull
5088 - push (with this repository as the destination)
5086 - push (with this repository as the destination)
5089 - unbundle
5087 - unbundle
5090
5088
5091 To avoid permanent data loss, rollback will refuse to rollback a
5089 To avoid permanent data loss, rollback will refuse to rollback a
5092 commit transaction if it isn't checked out. Use --force to
5090 commit transaction if it isn't checked out. Use --force to
5093 override this protection.
5091 override this protection.
5094
5092
5095 This command is not intended for use on public repositories. Once
5093 This command is not intended for use on public repositories. Once
5096 changes are visible for pull by other users, rolling a transaction
5094 changes are visible for pull by other users, rolling a transaction
5097 back locally is ineffective (someone else may already have pulled
5095 back locally is ineffective (someone else may already have pulled
5098 the changes). Furthermore, a race is possible with readers of the
5096 the changes). Furthermore, a race is possible with readers of the
5099 repository; for example an in-progress pull from the repository
5097 repository; for example an in-progress pull from the repository
5100 may fail if a rollback is performed.
5098 may fail if a rollback is performed.
5101
5099
5102 Returns 0 on success, 1 if no rollback data is available.
5100 Returns 0 on success, 1 if no rollback data is available.
5103 """
5101 """
5104 return repo.rollback(dryrun=opts.get('dry_run'),
5102 return repo.rollback(dryrun=opts.get('dry_run'),
5105 force=opts.get('force'))
5103 force=opts.get('force'))
5106
5104
5107 @command('root', [])
5105 @command('root', [])
5108 def root(ui, repo):
5106 def root(ui, repo):
5109 """print the root (top) of the current working directory
5107 """print the root (top) of the current working directory
5110
5108
5111 Print the root directory of the current repository.
5109 Print the root directory of the current repository.
5112
5110
5113 Returns 0 on success.
5111 Returns 0 on success.
5114 """
5112 """
5115 ui.write(repo.root + "\n")
5113 ui.write(repo.root + "\n")
5116
5114
5117 @command('^serve',
5115 @command('^serve',
5118 [('A', 'accesslog', '', _('name of access log file to write to'),
5116 [('A', 'accesslog', '', _('name of access log file to write to'),
5119 _('FILE')),
5117 _('FILE')),
5120 ('d', 'daemon', None, _('run server in background')),
5118 ('d', 'daemon', None, _('run server in background')),
5121 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5119 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5122 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5120 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5123 # use string type, then we can check if something was passed
5121 # use string type, then we can check if something was passed
5124 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5122 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5125 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5123 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5126 _('ADDR')),
5124 _('ADDR')),
5127 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5125 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5128 _('PREFIX')),
5126 _('PREFIX')),
5129 ('n', 'name', '',
5127 ('n', 'name', '',
5130 _('name to show in web pages (default: working directory)'), _('NAME')),
5128 _('name to show in web pages (default: working directory)'), _('NAME')),
5131 ('', 'web-conf', '',
5129 ('', 'web-conf', '',
5132 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5130 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5133 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5131 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5134 _('FILE')),
5132 _('FILE')),
5135 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5133 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5136 ('', 'stdio', None, _('for remote clients')),
5134 ('', 'stdio', None, _('for remote clients')),
5137 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5135 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5138 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5136 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5139 ('', 'style', '', _('template style to use'), _('STYLE')),
5137 ('', 'style', '', _('template style to use'), _('STYLE')),
5140 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5138 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5141 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5139 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5142 _('[OPTION]...'))
5140 _('[OPTION]...'))
5143 def serve(ui, repo, **opts):
5141 def serve(ui, repo, **opts):
5144 """start stand-alone webserver
5142 """start stand-alone webserver
5145
5143
5146 Start a local HTTP repository browser and pull server. You can use
5144 Start a local HTTP repository browser and pull server. You can use
5147 this for ad-hoc sharing and browsing of repositories. It is
5145 this for ad-hoc sharing and browsing of repositories. It is
5148 recommended to use a real web server to serve a repository for
5146 recommended to use a real web server to serve a repository for
5149 longer periods of time.
5147 longer periods of time.
5150
5148
5151 Please note that the server does not implement access control.
5149 Please note that the server does not implement access control.
5152 This means that, by default, anybody can read from the server and
5150 This means that, by default, anybody can read from the server and
5153 nobody can write to it by default. Set the ``web.allow_push``
5151 nobody can write to it by default. Set the ``web.allow_push``
5154 option to ``*`` to allow everybody to push to the server. You
5152 option to ``*`` to allow everybody to push to the server. You
5155 should use a real web server if you need to authenticate users.
5153 should use a real web server if you need to authenticate users.
5156
5154
5157 By default, the server logs accesses to stdout and errors to
5155 By default, the server logs accesses to stdout and errors to
5158 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5156 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5159 files.
5157 files.
5160
5158
5161 To have the server choose a free port number to listen on, specify
5159 To have the server choose a free port number to listen on, specify
5162 a port number of 0; in this case, the server will print the port
5160 a port number of 0; in this case, the server will print the port
5163 number it uses.
5161 number it uses.
5164
5162
5165 Returns 0 on success.
5163 Returns 0 on success.
5166 """
5164 """
5167
5165
5168 if opts["stdio"] and opts["cmdserver"]:
5166 if opts["stdio"] and opts["cmdserver"]:
5169 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5167 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5170
5168
5171 def checkrepo():
5169 def checkrepo():
5172 if repo is None:
5170 if repo is None:
5173 raise error.RepoError(_("there is no Mercurial repository here"
5171 raise error.RepoError(_("there is no Mercurial repository here"
5174 " (.hg not found)"))
5172 " (.hg not found)"))
5175
5173
5176 if opts["stdio"]:
5174 if opts["stdio"]:
5177 checkrepo()
5175 checkrepo()
5178 s = sshserver.sshserver(ui, repo)
5176 s = sshserver.sshserver(ui, repo)
5179 s.serve_forever()
5177 s.serve_forever()
5180
5178
5181 if opts["cmdserver"]:
5179 if opts["cmdserver"]:
5182 checkrepo()
5180 checkrepo()
5183 s = commandserver.server(ui, repo, opts["cmdserver"])
5181 s = commandserver.server(ui, repo, opts["cmdserver"])
5184 return s.serve()
5182 return s.serve()
5185
5183
5186 # this way we can check if something was given in the command-line
5184 # this way we can check if something was given in the command-line
5187 if opts.get('port'):
5185 if opts.get('port'):
5188 opts['port'] = util.getport(opts.get('port'))
5186 opts['port'] = util.getport(opts.get('port'))
5189
5187
5190 baseui = repo and repo.baseui or ui
5188 baseui = repo and repo.baseui or ui
5191 optlist = ("name templates style address port prefix ipv6"
5189 optlist = ("name templates style address port prefix ipv6"
5192 " accesslog errorlog certificate encoding")
5190 " accesslog errorlog certificate encoding")
5193 for o in optlist.split():
5191 for o in optlist.split():
5194 val = opts.get(o, '')
5192 val = opts.get(o, '')
5195 if val in (None, ''): # should check against default options instead
5193 if val in (None, ''): # should check against default options instead
5196 continue
5194 continue
5197 baseui.setconfig("web", o, val)
5195 baseui.setconfig("web", o, val)
5198 if repo and repo.ui != baseui:
5196 if repo and repo.ui != baseui:
5199 repo.ui.setconfig("web", o, val)
5197 repo.ui.setconfig("web", o, val)
5200
5198
5201 o = opts.get('web_conf') or opts.get('webdir_conf')
5199 o = opts.get('web_conf') or opts.get('webdir_conf')
5202 if not o:
5200 if not o:
5203 if not repo:
5201 if not repo:
5204 raise error.RepoError(_("there is no Mercurial repository"
5202 raise error.RepoError(_("there is no Mercurial repository"
5205 " here (.hg not found)"))
5203 " here (.hg not found)"))
5206 o = repo.root
5204 o = repo.root
5207
5205
5208 app = hgweb.hgweb(o, baseui=ui)
5206 app = hgweb.hgweb(o, baseui=ui)
5209
5207
5210 class service(object):
5208 class service(object):
5211 def init(self):
5209 def init(self):
5212 util.setsignalhandler()
5210 util.setsignalhandler()
5213 self.httpd = hgweb.server.create_server(ui, app)
5211 self.httpd = hgweb.server.create_server(ui, app)
5214
5212
5215 if opts['port'] and not ui.verbose:
5213 if opts['port'] and not ui.verbose:
5216 return
5214 return
5217
5215
5218 if self.httpd.prefix:
5216 if self.httpd.prefix:
5219 prefix = self.httpd.prefix.strip('/') + '/'
5217 prefix = self.httpd.prefix.strip('/') + '/'
5220 else:
5218 else:
5221 prefix = ''
5219 prefix = ''
5222
5220
5223 port = ':%d' % self.httpd.port
5221 port = ':%d' % self.httpd.port
5224 if port == ':80':
5222 if port == ':80':
5225 port = ''
5223 port = ''
5226
5224
5227 bindaddr = self.httpd.addr
5225 bindaddr = self.httpd.addr
5228 if bindaddr == '0.0.0.0':
5226 if bindaddr == '0.0.0.0':
5229 bindaddr = '*'
5227 bindaddr = '*'
5230 elif ':' in bindaddr: # IPv6
5228 elif ':' in bindaddr: # IPv6
5231 bindaddr = '[%s]' % bindaddr
5229 bindaddr = '[%s]' % bindaddr
5232
5230
5233 fqaddr = self.httpd.fqaddr
5231 fqaddr = self.httpd.fqaddr
5234 if ':' in fqaddr:
5232 if ':' in fqaddr:
5235 fqaddr = '[%s]' % fqaddr
5233 fqaddr = '[%s]' % fqaddr
5236 if opts['port']:
5234 if opts['port']:
5237 write = ui.status
5235 write = ui.status
5238 else:
5236 else:
5239 write = ui.write
5237 write = ui.write
5240 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5238 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5241 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5239 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5242
5240
5243 def run(self):
5241 def run(self):
5244 self.httpd.serve_forever()
5242 self.httpd.serve_forever()
5245
5243
5246 service = service()
5244 service = service()
5247
5245
5248 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5246 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5249
5247
5250 @command('showconfig|debugconfig',
5248 @command('showconfig|debugconfig',
5251 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5249 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5252 _('[-u] [NAME]...'))
5250 _('[-u] [NAME]...'))
5253 def showconfig(ui, repo, *values, **opts):
5251 def showconfig(ui, repo, *values, **opts):
5254 """show combined config settings from all hgrc files
5252 """show combined config settings from all hgrc files
5255
5253
5256 With no arguments, print names and values of all config items.
5254 With no arguments, print names and values of all config items.
5257
5255
5258 With one argument of the form section.name, print just the value
5256 With one argument of the form section.name, print just the value
5259 of that config item.
5257 of that config item.
5260
5258
5261 With multiple arguments, print names and values of all config
5259 With multiple arguments, print names and values of all config
5262 items with matching section names.
5260 items with matching section names.
5263
5261
5264 With --debug, the source (filename and line number) is printed
5262 With --debug, the source (filename and line number) is printed
5265 for each config item.
5263 for each config item.
5266
5264
5267 Returns 0 on success.
5265 Returns 0 on success.
5268 """
5266 """
5269
5267
5270 for f in scmutil.rcpath():
5268 for f in scmutil.rcpath():
5271 ui.debug('read config from: %s\n' % f)
5269 ui.debug('read config from: %s\n' % f)
5272 untrusted = bool(opts.get('untrusted'))
5270 untrusted = bool(opts.get('untrusted'))
5273 if values:
5271 if values:
5274 sections = [v for v in values if '.' not in v]
5272 sections = [v for v in values if '.' not in v]
5275 items = [v for v in values if '.' in v]
5273 items = [v for v in values if '.' in v]
5276 if len(items) > 1 or items and sections:
5274 if len(items) > 1 or items and sections:
5277 raise util.Abort(_('only one config item permitted'))
5275 raise util.Abort(_('only one config item permitted'))
5278 for section, name, value in ui.walkconfig(untrusted=untrusted):
5276 for section, name, value in ui.walkconfig(untrusted=untrusted):
5279 value = str(value).replace('\n', '\\n')
5277 value = str(value).replace('\n', '\\n')
5280 sectname = section + '.' + name
5278 sectname = section + '.' + name
5281 if values:
5279 if values:
5282 for v in values:
5280 for v in values:
5283 if v == section:
5281 if v == section:
5284 ui.debug('%s: ' %
5282 ui.debug('%s: ' %
5285 ui.configsource(section, name, untrusted))
5283 ui.configsource(section, name, untrusted))
5286 ui.write('%s=%s\n' % (sectname, value))
5284 ui.write('%s=%s\n' % (sectname, value))
5287 elif v == sectname:
5285 elif v == sectname:
5288 ui.debug('%s: ' %
5286 ui.debug('%s: ' %
5289 ui.configsource(section, name, untrusted))
5287 ui.configsource(section, name, untrusted))
5290 ui.write(value, '\n')
5288 ui.write(value, '\n')
5291 else:
5289 else:
5292 ui.debug('%s: ' %
5290 ui.debug('%s: ' %
5293 ui.configsource(section, name, untrusted))
5291 ui.configsource(section, name, untrusted))
5294 ui.write('%s=%s\n' % (sectname, value))
5292 ui.write('%s=%s\n' % (sectname, value))
5295
5293
5296 @command('^status|st',
5294 @command('^status|st',
5297 [('A', 'all', None, _('show status of all files')),
5295 [('A', 'all', None, _('show status of all files')),
5298 ('m', 'modified', None, _('show only modified files')),
5296 ('m', 'modified', None, _('show only modified files')),
5299 ('a', 'added', None, _('show only added files')),
5297 ('a', 'added', None, _('show only added files')),
5300 ('r', 'removed', None, _('show only removed files')),
5298 ('r', 'removed', None, _('show only removed files')),
5301 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5299 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5302 ('c', 'clean', None, _('show only files without changes')),
5300 ('c', 'clean', None, _('show only files without changes')),
5303 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5301 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5304 ('i', 'ignored', None, _('show only ignored files')),
5302 ('i', 'ignored', None, _('show only ignored files')),
5305 ('n', 'no-status', None, _('hide status prefix')),
5303 ('n', 'no-status', None, _('hide status prefix')),
5306 ('C', 'copies', None, _('show source of copied files')),
5304 ('C', 'copies', None, _('show source of copied files')),
5307 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5305 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5308 ('', 'rev', [], _('show difference from revision'), _('REV')),
5306 ('', 'rev', [], _('show difference from revision'), _('REV')),
5309 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5307 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5310 ] + walkopts + subrepoopts,
5308 ] + walkopts + subrepoopts,
5311 _('[OPTION]... [FILE]...'))
5309 _('[OPTION]... [FILE]...'))
5312 def status(ui, repo, *pats, **opts):
5310 def status(ui, repo, *pats, **opts):
5313 """show changed files in the working directory
5311 """show changed files in the working directory
5314
5312
5315 Show status of files in the repository. If names are given, only
5313 Show status of files in the repository. If names are given, only
5316 files that match are shown. Files that are clean or ignored or
5314 files that match are shown. Files that are clean or ignored or
5317 the source of a copy/move operation, are not listed unless
5315 the source of a copy/move operation, are not listed unless
5318 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5316 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5319 Unless options described with "show only ..." are given, the
5317 Unless options described with "show only ..." are given, the
5320 options -mardu are used.
5318 options -mardu are used.
5321
5319
5322 Option -q/--quiet hides untracked (unknown and ignored) files
5320 Option -q/--quiet hides untracked (unknown and ignored) files
5323 unless explicitly requested with -u/--unknown or -i/--ignored.
5321 unless explicitly requested with -u/--unknown or -i/--ignored.
5324
5322
5325 .. note::
5323 .. note::
5326 status may appear to disagree with diff if permissions have
5324 status may appear to disagree with diff if permissions have
5327 changed or a merge has occurred. The standard diff format does
5325 changed or a merge has occurred. The standard diff format does
5328 not report permission changes and diff only reports changes
5326 not report permission changes and diff only reports changes
5329 relative to one merge parent.
5327 relative to one merge parent.
5330
5328
5331 If one revision is given, it is used as the base revision.
5329 If one revision is given, it is used as the base revision.
5332 If two revisions are given, the differences between them are
5330 If two revisions are given, the differences between them are
5333 shown. The --change option can also be used as a shortcut to list
5331 shown. The --change option can also be used as a shortcut to list
5334 the changed files of a revision from its first parent.
5332 the changed files of a revision from its first parent.
5335
5333
5336 The codes used to show the status of files are::
5334 The codes used to show the status of files are::
5337
5335
5338 M = modified
5336 M = modified
5339 A = added
5337 A = added
5340 R = removed
5338 R = removed
5341 C = clean
5339 C = clean
5342 ! = missing (deleted by non-hg command, but still tracked)
5340 ! = missing (deleted by non-hg command, but still tracked)
5343 ? = not tracked
5341 ? = not tracked
5344 I = ignored
5342 I = ignored
5345 = origin of the previous file listed as A (added)
5343 = origin of the previous file listed as A (added)
5346
5344
5347 .. container:: verbose
5345 .. container:: verbose
5348
5346
5349 Examples:
5347 Examples:
5350
5348
5351 - show changes in the working directory relative to a
5349 - show changes in the working directory relative to a
5352 changeset::
5350 changeset::
5353
5351
5354 hg status --rev 9353
5352 hg status --rev 9353
5355
5353
5356 - show all changes including copies in an existing changeset::
5354 - show all changes including copies in an existing changeset::
5357
5355
5358 hg status --copies --change 9353
5356 hg status --copies --change 9353
5359
5357
5360 - get a NUL separated list of added files, suitable for xargs::
5358 - get a NUL separated list of added files, suitable for xargs::
5361
5359
5362 hg status -an0
5360 hg status -an0
5363
5361
5364 Returns 0 on success.
5362 Returns 0 on success.
5365 """
5363 """
5366
5364
5367 revs = opts.get('rev')
5365 revs = opts.get('rev')
5368 change = opts.get('change')
5366 change = opts.get('change')
5369
5367
5370 if revs and change:
5368 if revs and change:
5371 msg = _('cannot specify --rev and --change at the same time')
5369 msg = _('cannot specify --rev and --change at the same time')
5372 raise util.Abort(msg)
5370 raise util.Abort(msg)
5373 elif change:
5371 elif change:
5374 node2 = scmutil.revsingle(repo, change, None).node()
5372 node2 = scmutil.revsingle(repo, change, None).node()
5375 node1 = repo[node2].p1().node()
5373 node1 = repo[node2].p1().node()
5376 else:
5374 else:
5377 node1, node2 = scmutil.revpair(repo, revs)
5375 node1, node2 = scmutil.revpair(repo, revs)
5378
5376
5379 cwd = (pats and repo.getcwd()) or ''
5377 cwd = (pats and repo.getcwd()) or ''
5380 end = opts.get('print0') and '\0' or '\n'
5378 end = opts.get('print0') and '\0' or '\n'
5381 copy = {}
5379 copy = {}
5382 states = 'modified added removed deleted unknown ignored clean'.split()
5380 states = 'modified added removed deleted unknown ignored clean'.split()
5383 show = [k for k in states if opts.get(k)]
5381 show = [k for k in states if opts.get(k)]
5384 if opts.get('all'):
5382 if opts.get('all'):
5385 show += ui.quiet and (states[:4] + ['clean']) or states
5383 show += ui.quiet and (states[:4] + ['clean']) or states
5386 if not show:
5384 if not show:
5387 show = ui.quiet and states[:4] or states[:5]
5385 show = ui.quiet and states[:4] or states[:5]
5388
5386
5389 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5387 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5390 'ignored' in show, 'clean' in show, 'unknown' in show,
5388 'ignored' in show, 'clean' in show, 'unknown' in show,
5391 opts.get('subrepos'))
5389 opts.get('subrepos'))
5392 changestates = zip(states, 'MAR!?IC', stat)
5390 changestates = zip(states, 'MAR!?IC', stat)
5393
5391
5394 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5392 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5395 copy = copies.pathcopies(repo[node1], repo[node2])
5393 copy = copies.pathcopies(repo[node1], repo[node2])
5396
5394
5397 fm = ui.formatter('status', opts)
5395 fm = ui.formatter('status', opts)
5398 format = '%s %s' + end
5396 format = '%s %s' + end
5399 if opts.get('no_status'):
5397 if opts.get('no_status'):
5400 format = '%.0s%s' + end
5398 format = '%.0s%s' + end
5401
5399
5402 for state, char, files in changestates:
5400 for state, char, files in changestates:
5403 if state in show:
5401 if state in show:
5404 label = 'status.' + state
5402 label = 'status.' + state
5405 for f in files:
5403 for f in files:
5406 fm.startitem()
5404 fm.startitem()
5407 fm.write("status path", format, char,
5405 fm.write("status path", format, char,
5408 repo.pathto(f, cwd), label=label)
5406 repo.pathto(f, cwd), label=label)
5409 if f in copy:
5407 if f in copy:
5410 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5408 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5411 label='status.copied')
5409 label='status.copied')
5412 fm.end()
5410 fm.end()
5413
5411
5414 @command('^summary|sum',
5412 @command('^summary|sum',
5415 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5413 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5416 def summary(ui, repo, **opts):
5414 def summary(ui, repo, **opts):
5417 """summarize working directory state
5415 """summarize working directory state
5418
5416
5419 This generates a brief summary of the working directory state,
5417 This generates a brief summary of the working directory state,
5420 including parents, branch, commit status, and available updates.
5418 including parents, branch, commit status, and available updates.
5421
5419
5422 With the --remote option, this will check the default paths for
5420 With the --remote option, this will check the default paths for
5423 incoming and outgoing changes. This can be time-consuming.
5421 incoming and outgoing changes. This can be time-consuming.
5424
5422
5425 Returns 0 on success.
5423 Returns 0 on success.
5426 """
5424 """
5427
5425
5428 ctx = repo[None]
5426 ctx = repo[None]
5429 parents = ctx.parents()
5427 parents = ctx.parents()
5430 pnode = parents[0].node()
5428 pnode = parents[0].node()
5431 marks = []
5429 marks = []
5432
5430
5433 for p in parents:
5431 for p in parents:
5434 # label with log.changeset (instead of log.parent) since this
5432 # label with log.changeset (instead of log.parent) since this
5435 # shows a working directory parent *changeset*:
5433 # shows a working directory parent *changeset*:
5436 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5434 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5437 label='log.changeset changeset.%s' % p.phasestr())
5435 label='log.changeset changeset.%s' % p.phasestr())
5438 ui.write(' '.join(p.tags()), label='log.tag')
5436 ui.write(' '.join(p.tags()), label='log.tag')
5439 if p.bookmarks():
5437 if p.bookmarks():
5440 marks.extend(p.bookmarks())
5438 marks.extend(p.bookmarks())
5441 if p.rev() == -1:
5439 if p.rev() == -1:
5442 if not len(repo):
5440 if not len(repo):
5443 ui.write(_(' (empty repository)'))
5441 ui.write(_(' (empty repository)'))
5444 else:
5442 else:
5445 ui.write(_(' (no revision checked out)'))
5443 ui.write(_(' (no revision checked out)'))
5446 ui.write('\n')
5444 ui.write('\n')
5447 if p.description():
5445 if p.description():
5448 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5446 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5449 label='log.summary')
5447 label='log.summary')
5450
5448
5451 branch = ctx.branch()
5449 branch = ctx.branch()
5452 bheads = repo.branchheads(branch)
5450 bheads = repo.branchheads(branch)
5453 m = _('branch: %s\n') % branch
5451 m = _('branch: %s\n') % branch
5454 if branch != 'default':
5452 if branch != 'default':
5455 ui.write(m, label='log.branch')
5453 ui.write(m, label='log.branch')
5456 else:
5454 else:
5457 ui.status(m, label='log.branch')
5455 ui.status(m, label='log.branch')
5458
5456
5459 if marks:
5457 if marks:
5460 current = repo._bookmarkcurrent
5458 current = repo._bookmarkcurrent
5461 ui.write(_('bookmarks:'), label='log.bookmark')
5459 ui.write(_('bookmarks:'), label='log.bookmark')
5462 if current is not None:
5460 if current is not None:
5463 try:
5461 try:
5464 marks.remove(current)
5462 marks.remove(current)
5465 ui.write(' *' + current, label='bookmarks.current')
5463 ui.write(' *' + current, label='bookmarks.current')
5466 except ValueError:
5464 except ValueError:
5467 # current bookmark not in parent ctx marks
5465 # current bookmark not in parent ctx marks
5468 pass
5466 pass
5469 for m in marks:
5467 for m in marks:
5470 ui.write(' ' + m, label='log.bookmark')
5468 ui.write(' ' + m, label='log.bookmark')
5471 ui.write('\n', label='log.bookmark')
5469 ui.write('\n', label='log.bookmark')
5472
5470
5473 st = list(repo.status(unknown=True))[:6]
5471 st = list(repo.status(unknown=True))[:6]
5474
5472
5475 c = repo.dirstate.copies()
5473 c = repo.dirstate.copies()
5476 copied, renamed = [], []
5474 copied, renamed = [], []
5477 for d, s in c.iteritems():
5475 for d, s in c.iteritems():
5478 if s in st[2]:
5476 if s in st[2]:
5479 st[2].remove(s)
5477 st[2].remove(s)
5480 renamed.append(d)
5478 renamed.append(d)
5481 else:
5479 else:
5482 copied.append(d)
5480 copied.append(d)
5483 if d in st[1]:
5481 if d in st[1]:
5484 st[1].remove(d)
5482 st[1].remove(d)
5485 st.insert(3, renamed)
5483 st.insert(3, renamed)
5486 st.insert(4, copied)
5484 st.insert(4, copied)
5487
5485
5488 ms = mergemod.mergestate(repo)
5486 ms = mergemod.mergestate(repo)
5489 st.append([f for f in ms if ms[f] == 'u'])
5487 st.append([f for f in ms if ms[f] == 'u'])
5490
5488
5491 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5489 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5492 st.append(subs)
5490 st.append(subs)
5493
5491
5494 labels = [ui.label(_('%d modified'), 'status.modified'),
5492 labels = [ui.label(_('%d modified'), 'status.modified'),
5495 ui.label(_('%d added'), 'status.added'),
5493 ui.label(_('%d added'), 'status.added'),
5496 ui.label(_('%d removed'), 'status.removed'),
5494 ui.label(_('%d removed'), 'status.removed'),
5497 ui.label(_('%d renamed'), 'status.copied'),
5495 ui.label(_('%d renamed'), 'status.copied'),
5498 ui.label(_('%d copied'), 'status.copied'),
5496 ui.label(_('%d copied'), 'status.copied'),
5499 ui.label(_('%d deleted'), 'status.deleted'),
5497 ui.label(_('%d deleted'), 'status.deleted'),
5500 ui.label(_('%d unknown'), 'status.unknown'),
5498 ui.label(_('%d unknown'), 'status.unknown'),
5501 ui.label(_('%d ignored'), 'status.ignored'),
5499 ui.label(_('%d ignored'), 'status.ignored'),
5502 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5500 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5503 ui.label(_('%d subrepos'), 'status.modified')]
5501 ui.label(_('%d subrepos'), 'status.modified')]
5504 t = []
5502 t = []
5505 for s, l in zip(st, labels):
5503 for s, l in zip(st, labels):
5506 if s:
5504 if s:
5507 t.append(l % len(s))
5505 t.append(l % len(s))
5508
5506
5509 t = ', '.join(t)
5507 t = ', '.join(t)
5510 cleanworkdir = False
5508 cleanworkdir = False
5511
5509
5512 if len(parents) > 1:
5510 if len(parents) > 1:
5513 t += _(' (merge)')
5511 t += _(' (merge)')
5514 elif branch != parents[0].branch():
5512 elif branch != parents[0].branch():
5515 t += _(' (new branch)')
5513 t += _(' (new branch)')
5516 elif (parents[0].closesbranch() and
5514 elif (parents[0].closesbranch() and
5517 pnode in repo.branchheads(branch, closed=True)):
5515 pnode in repo.branchheads(branch, closed=True)):
5518 t += _(' (head closed)')
5516 t += _(' (head closed)')
5519 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5517 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5520 t += _(' (clean)')
5518 t += _(' (clean)')
5521 cleanworkdir = True
5519 cleanworkdir = True
5522 elif pnode not in bheads:
5520 elif pnode not in bheads:
5523 t += _(' (new branch head)')
5521 t += _(' (new branch head)')
5524
5522
5525 if cleanworkdir:
5523 if cleanworkdir:
5526 ui.status(_('commit: %s\n') % t.strip())
5524 ui.status(_('commit: %s\n') % t.strip())
5527 else:
5525 else:
5528 ui.write(_('commit: %s\n') % t.strip())
5526 ui.write(_('commit: %s\n') % t.strip())
5529
5527
5530 # all ancestors of branch heads - all ancestors of parent = new csets
5528 # all ancestors of branch heads - all ancestors of parent = new csets
5531 new = [0] * len(repo)
5529 new = [0] * len(repo)
5532 cl = repo.changelog
5530 cl = repo.changelog
5533 for a in [cl.rev(n) for n in bheads]:
5531 for a in [cl.rev(n) for n in bheads]:
5534 new[a] = 1
5532 new[a] = 1
5535 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5533 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5536 new[a] = 1
5534 new[a] = 1
5537 for a in [p.rev() for p in parents]:
5535 for a in [p.rev() for p in parents]:
5538 if a >= 0:
5536 if a >= 0:
5539 new[a] = 0
5537 new[a] = 0
5540 for a in cl.ancestors([p.rev() for p in parents]):
5538 for a in cl.ancestors([p.rev() for p in parents]):
5541 new[a] = 0
5539 new[a] = 0
5542 new = sum(new)
5540 new = sum(new)
5543
5541
5544 if new == 0:
5542 if new == 0:
5545 ui.status(_('update: (current)\n'))
5543 ui.status(_('update: (current)\n'))
5546 elif pnode not in bheads:
5544 elif pnode not in bheads:
5547 ui.write(_('update: %d new changesets (update)\n') % new)
5545 ui.write(_('update: %d new changesets (update)\n') % new)
5548 else:
5546 else:
5549 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5547 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5550 (new, len(bheads)))
5548 (new, len(bheads)))
5551
5549
5552 if opts.get('remote'):
5550 if opts.get('remote'):
5553 t = []
5551 t = []
5554 source, branches = hg.parseurl(ui.expandpath('default'))
5552 source, branches = hg.parseurl(ui.expandpath('default'))
5555 other = hg.peer(repo, {}, source)
5553 other = hg.peer(repo, {}, source)
5556 revs, checkout = hg.addbranchrevs(repo, other, branches,
5554 revs, checkout = hg.addbranchrevs(repo, other, branches,
5557 opts.get('rev'))
5555 opts.get('rev'))
5558 ui.debug('comparing with %s\n' % util.hidepassword(source))
5556 ui.debug('comparing with %s\n' % util.hidepassword(source))
5559 repo.ui.pushbuffer()
5557 repo.ui.pushbuffer()
5560 commoninc = discovery.findcommonincoming(repo, other)
5558 commoninc = discovery.findcommonincoming(repo, other)
5561 _common, incoming, _rheads = commoninc
5559 _common, incoming, _rheads = commoninc
5562 repo.ui.popbuffer()
5560 repo.ui.popbuffer()
5563 if incoming:
5561 if incoming:
5564 t.append(_('1 or more incoming'))
5562 t.append(_('1 or more incoming'))
5565
5563
5566 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5564 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5567 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5565 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5568 if source != dest:
5566 if source != dest:
5569 other = hg.peer(repo, {}, dest)
5567 other = hg.peer(repo, {}, dest)
5570 commoninc = None
5568 commoninc = None
5571 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5569 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5572 repo.ui.pushbuffer()
5570 repo.ui.pushbuffer()
5573 outgoing = discovery.findcommonoutgoing(repo, other,
5571 outgoing = discovery.findcommonoutgoing(repo, other,
5574 commoninc=commoninc)
5572 commoninc=commoninc)
5575 repo.ui.popbuffer()
5573 repo.ui.popbuffer()
5576 o = outgoing.missing
5574 o = outgoing.missing
5577 if o:
5575 if o:
5578 t.append(_('%d outgoing') % len(o))
5576 t.append(_('%d outgoing') % len(o))
5579 if 'bookmarks' in other.listkeys('namespaces'):
5577 if 'bookmarks' in other.listkeys('namespaces'):
5580 lmarks = repo.listkeys('bookmarks')
5578 lmarks = repo.listkeys('bookmarks')
5581 rmarks = other.listkeys('bookmarks')
5579 rmarks = other.listkeys('bookmarks')
5582 diff = set(rmarks) - set(lmarks)
5580 diff = set(rmarks) - set(lmarks)
5583 if len(diff) > 0:
5581 if len(diff) > 0:
5584 t.append(_('%d incoming bookmarks') % len(diff))
5582 t.append(_('%d incoming bookmarks') % len(diff))
5585 diff = set(lmarks) - set(rmarks)
5583 diff = set(lmarks) - set(rmarks)
5586 if len(diff) > 0:
5584 if len(diff) > 0:
5587 t.append(_('%d outgoing bookmarks') % len(diff))
5585 t.append(_('%d outgoing bookmarks') % len(diff))
5588
5586
5589 if t:
5587 if t:
5590 ui.write(_('remote: %s\n') % (', '.join(t)))
5588 ui.write(_('remote: %s\n') % (', '.join(t)))
5591 else:
5589 else:
5592 ui.status(_('remote: (synced)\n'))
5590 ui.status(_('remote: (synced)\n'))
5593
5591
5594 @command('tag',
5592 @command('tag',
5595 [('f', 'force', None, _('force tag')),
5593 [('f', 'force', None, _('force tag')),
5596 ('l', 'local', None, _('make the tag local')),
5594 ('l', 'local', None, _('make the tag local')),
5597 ('r', 'rev', '', _('revision to tag'), _('REV')),
5595 ('r', 'rev', '', _('revision to tag'), _('REV')),
5598 ('', 'remove', None, _('remove a tag')),
5596 ('', 'remove', None, _('remove a tag')),
5599 # -l/--local is already there, commitopts cannot be used
5597 # -l/--local is already there, commitopts cannot be used
5600 ('e', 'edit', None, _('edit commit message')),
5598 ('e', 'edit', None, _('edit commit message')),
5601 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5599 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5602 ] + commitopts2,
5600 ] + commitopts2,
5603 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5601 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5604 def tag(ui, repo, name1, *names, **opts):
5602 def tag(ui, repo, name1, *names, **opts):
5605 """add one or more tags for the current or given revision
5603 """add one or more tags for the current or given revision
5606
5604
5607 Name a particular revision using <name>.
5605 Name a particular revision using <name>.
5608
5606
5609 Tags are used to name particular revisions of the repository and are
5607 Tags are used to name particular revisions of the repository and are
5610 very useful to compare different revisions, to go back to significant
5608 very useful to compare different revisions, to go back to significant
5611 earlier versions or to mark branch points as releases, etc. Changing
5609 earlier versions or to mark branch points as releases, etc. Changing
5612 an existing tag is normally disallowed; use -f/--force to override.
5610 an existing tag is normally disallowed; use -f/--force to override.
5613
5611
5614 If no revision is given, the parent of the working directory is
5612 If no revision is given, the parent of the working directory is
5615 used, or tip if no revision is checked out.
5613 used, or tip if no revision is checked out.
5616
5614
5617 To facilitate version control, distribution, and merging of tags,
5615 To facilitate version control, distribution, and merging of tags,
5618 they are stored as a file named ".hgtags" which is managed similarly
5616 they are stored as a file named ".hgtags" which is managed similarly
5619 to other project files and can be hand-edited if necessary. This
5617 to other project files and can be hand-edited if necessary. This
5620 also means that tagging creates a new commit. The file
5618 also means that tagging creates a new commit. The file
5621 ".hg/localtags" is used for local tags (not shared among
5619 ".hg/localtags" is used for local tags (not shared among
5622 repositories).
5620 repositories).
5623
5621
5624 Tag commits are usually made at the head of a branch. If the parent
5622 Tag commits are usually made at the head of a branch. If the parent
5625 of the working directory is not a branch head, :hg:`tag` aborts; use
5623 of the working directory is not a branch head, :hg:`tag` aborts; use
5626 -f/--force to force the tag commit to be based on a non-head
5624 -f/--force to force the tag commit to be based on a non-head
5627 changeset.
5625 changeset.
5628
5626
5629 See :hg:`help dates` for a list of formats valid for -d/--date.
5627 See :hg:`help dates` for a list of formats valid for -d/--date.
5630
5628
5631 Since tag names have priority over branch names during revision
5629 Since tag names have priority over branch names during revision
5632 lookup, using an existing branch name as a tag name is discouraged.
5630 lookup, using an existing branch name as a tag name is discouraged.
5633
5631
5634 Returns 0 on success.
5632 Returns 0 on success.
5635 """
5633 """
5636 wlock = lock = None
5634 wlock = lock = None
5637 try:
5635 try:
5638 wlock = repo.wlock()
5636 wlock = repo.wlock()
5639 lock = repo.lock()
5637 lock = repo.lock()
5640 rev_ = "."
5638 rev_ = "."
5641 names = [t.strip() for t in (name1,) + names]
5639 names = [t.strip() for t in (name1,) + names]
5642 if len(names) != len(set(names)):
5640 if len(names) != len(set(names)):
5643 raise util.Abort(_('tag names must be unique'))
5641 raise util.Abort(_('tag names must be unique'))
5644 for n in names:
5642 for n in names:
5645 if n in ['tip', '.', 'null']:
5643 if n in ['tip', '.', 'null']:
5646 raise util.Abort(_("the name '%s' is reserved") % n)
5644 raise util.Abort(_("the name '%s' is reserved") % n)
5647 if not n:
5645 if not n:
5648 raise util.Abort(_('tag names cannot consist entirely of '
5646 raise util.Abort(_('tag names cannot consist entirely of '
5649 'whitespace'))
5647 'whitespace'))
5650 if opts.get('rev') and opts.get('remove'):
5648 if opts.get('rev') and opts.get('remove'):
5651 raise util.Abort(_("--rev and --remove are incompatible"))
5649 raise util.Abort(_("--rev and --remove are incompatible"))
5652 if opts.get('rev'):
5650 if opts.get('rev'):
5653 rev_ = opts['rev']
5651 rev_ = opts['rev']
5654 message = opts.get('message')
5652 message = opts.get('message')
5655 if opts.get('remove'):
5653 if opts.get('remove'):
5656 expectedtype = opts.get('local') and 'local' or 'global'
5654 expectedtype = opts.get('local') and 'local' or 'global'
5657 for n in names:
5655 for n in names:
5658 if not repo.tagtype(n):
5656 if not repo.tagtype(n):
5659 raise util.Abort(_("tag '%s' does not exist") % n)
5657 raise util.Abort(_("tag '%s' does not exist") % n)
5660 if repo.tagtype(n) != expectedtype:
5658 if repo.tagtype(n) != expectedtype:
5661 if expectedtype == 'global':
5659 if expectedtype == 'global':
5662 raise util.Abort(_("tag '%s' is not a global tag") % n)
5660 raise util.Abort(_("tag '%s' is not a global tag") % n)
5663 else:
5661 else:
5664 raise util.Abort(_("tag '%s' is not a local tag") % n)
5662 raise util.Abort(_("tag '%s' is not a local tag") % n)
5665 rev_ = nullid
5663 rev_ = nullid
5666 if not message:
5664 if not message:
5667 # we don't translate commit messages
5665 # we don't translate commit messages
5668 message = 'Removed tag %s' % ', '.join(names)
5666 message = 'Removed tag %s' % ', '.join(names)
5669 elif not opts.get('force'):
5667 elif not opts.get('force'):
5670 for n in names:
5668 for n in names:
5671 if n in repo.tags():
5669 if n in repo.tags():
5672 raise util.Abort(_("tag '%s' already exists "
5670 raise util.Abort(_("tag '%s' already exists "
5673 "(use -f to force)") % n)
5671 "(use -f to force)") % n)
5674 if not opts.get('local'):
5672 if not opts.get('local'):
5675 p1, p2 = repo.dirstate.parents()
5673 p1, p2 = repo.dirstate.parents()
5676 if p2 != nullid:
5674 if p2 != nullid:
5677 raise util.Abort(_('uncommitted merge'))
5675 raise util.Abort(_('uncommitted merge'))
5678 bheads = repo.branchheads()
5676 bheads = repo.branchheads()
5679 if not opts.get('force') and bheads and p1 not in bheads:
5677 if not opts.get('force') and bheads and p1 not in bheads:
5680 raise util.Abort(_('not at a branch head (use -f to force)'))
5678 raise util.Abort(_('not at a branch head (use -f to force)'))
5681 r = scmutil.revsingle(repo, rev_).node()
5679 r = scmutil.revsingle(repo, rev_).node()
5682
5680
5683 if not message:
5681 if not message:
5684 # we don't translate commit messages
5682 # we don't translate commit messages
5685 message = ('Added tag %s for changeset %s' %
5683 message = ('Added tag %s for changeset %s' %
5686 (', '.join(names), short(r)))
5684 (', '.join(names), short(r)))
5687
5685
5688 date = opts.get('date')
5686 date = opts.get('date')
5689 if date:
5687 if date:
5690 date = util.parsedate(date)
5688 date = util.parsedate(date)
5691
5689
5692 if opts.get('edit'):
5690 if opts.get('edit'):
5693 message = ui.edit(message, ui.username())
5691 message = ui.edit(message, ui.username())
5694
5692
5695 # don't allow tagging the null rev
5693 # don't allow tagging the null rev
5696 if (not opts.get('remove') and
5694 if (not opts.get('remove') and
5697 scmutil.revsingle(repo, rev_).rev() == nullrev):
5695 scmutil.revsingle(repo, rev_).rev() == nullrev):
5698 raise util.Abort(_("null revision specified"))
5696 raise util.Abort(_("null revision specified"))
5699
5697
5700 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5698 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5701 finally:
5699 finally:
5702 release(lock, wlock)
5700 release(lock, wlock)
5703
5701
5704 @command('tags', [], '')
5702 @command('tags', [], '')
5705 def tags(ui, repo):
5703 def tags(ui, repo):
5706 """list repository tags
5704 """list repository tags
5707
5705
5708 This lists both regular and local tags. When the -v/--verbose
5706 This lists both regular and local tags. When the -v/--verbose
5709 switch is used, a third column "local" is printed for local tags.
5707 switch is used, a third column "local" is printed for local tags.
5710
5708
5711 Returns 0 on success.
5709 Returns 0 on success.
5712 """
5710 """
5713
5711
5714 hexfunc = ui.debugflag and hex or short
5712 hexfunc = ui.debugflag and hex or short
5715 tagtype = ""
5713 tagtype = ""
5716
5714
5717 for t, n in reversed(repo.tagslist()):
5715 for t, n in reversed(repo.tagslist()):
5718 if ui.quiet:
5716 if ui.quiet:
5719 ui.write("%s\n" % t, label='tags.normal')
5717 ui.write("%s\n" % t, label='tags.normal')
5720 continue
5718 continue
5721
5719
5722 hn = hexfunc(n)
5720 hn = hexfunc(n)
5723 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5721 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5724 rev = ui.label(r, 'log.changeset changeset.%s' % repo[n].phasestr())
5722 rev = ui.label(r, 'log.changeset changeset.%s' % repo[n].phasestr())
5725 spaces = " " * (30 - encoding.colwidth(t))
5723 spaces = " " * (30 - encoding.colwidth(t))
5726
5724
5727 tag = ui.label(t, 'tags.normal')
5725 tag = ui.label(t, 'tags.normal')
5728 if ui.verbose:
5726 if ui.verbose:
5729 if repo.tagtype(t) == 'local':
5727 if repo.tagtype(t) == 'local':
5730 tagtype = " local"
5728 tagtype = " local"
5731 tag = ui.label(t, 'tags.local')
5729 tag = ui.label(t, 'tags.local')
5732 else:
5730 else:
5733 tagtype = ""
5731 tagtype = ""
5734 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5732 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5735
5733
5736 @command('tip',
5734 @command('tip',
5737 [('p', 'patch', None, _('show patch')),
5735 [('p', 'patch', None, _('show patch')),
5738 ('g', 'git', None, _('use git extended diff format')),
5736 ('g', 'git', None, _('use git extended diff format')),
5739 ] + templateopts,
5737 ] + templateopts,
5740 _('[-p] [-g]'))
5738 _('[-p] [-g]'))
5741 def tip(ui, repo, **opts):
5739 def tip(ui, repo, **opts):
5742 """show the tip revision
5740 """show the tip revision
5743
5741
5744 The tip revision (usually just called the tip) is the changeset
5742 The tip revision (usually just called the tip) is the changeset
5745 most recently added to the repository (and therefore the most
5743 most recently added to the repository (and therefore the most
5746 recently changed head).
5744 recently changed head).
5747
5745
5748 If you have just made a commit, that commit will be the tip. If
5746 If you have just made a commit, that commit will be the tip. If
5749 you have just pulled changes from another repository, the tip of
5747 you have just pulled changes from another repository, the tip of
5750 that repository becomes the current tip. The "tip" tag is special
5748 that repository becomes the current tip. The "tip" tag is special
5751 and cannot be renamed or assigned to a different changeset.
5749 and cannot be renamed or assigned to a different changeset.
5752
5750
5753 Returns 0 on success.
5751 Returns 0 on success.
5754 """
5752 """
5755 displayer = cmdutil.show_changeset(ui, repo, opts)
5753 displayer = cmdutil.show_changeset(ui, repo, opts)
5756 displayer.show(repo[len(repo) - 1])
5754 displayer.show(repo[len(repo) - 1])
5757 displayer.close()
5755 displayer.close()
5758
5756
5759 @command('unbundle',
5757 @command('unbundle',
5760 [('u', 'update', None,
5758 [('u', 'update', None,
5761 _('update to new branch head if changesets were unbundled'))],
5759 _('update to new branch head if changesets were unbundled'))],
5762 _('[-u] FILE...'))
5760 _('[-u] FILE...'))
5763 def unbundle(ui, repo, fname1, *fnames, **opts):
5761 def unbundle(ui, repo, fname1, *fnames, **opts):
5764 """apply one or more changegroup files
5762 """apply one or more changegroup files
5765
5763
5766 Apply one or more compressed changegroup files generated by the
5764 Apply one or more compressed changegroup files generated by the
5767 bundle command.
5765 bundle command.
5768
5766
5769 Returns 0 on success, 1 if an update has unresolved files.
5767 Returns 0 on success, 1 if an update has unresolved files.
5770 """
5768 """
5771 fnames = (fname1,) + fnames
5769 fnames = (fname1,) + fnames
5772
5770
5773 lock = repo.lock()
5771 lock = repo.lock()
5774 wc = repo['.']
5772 wc = repo['.']
5775 try:
5773 try:
5776 for fname in fnames:
5774 for fname in fnames:
5777 f = url.open(ui, fname)
5775 f = url.open(ui, fname)
5778 gen = changegroup.readbundle(f, fname)
5776 gen = changegroup.readbundle(f, fname)
5779 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5777 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5780 finally:
5778 finally:
5781 lock.release()
5779 lock.release()
5782 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5780 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5783 return postincoming(ui, repo, modheads, opts.get('update'), None)
5781 return postincoming(ui, repo, modheads, opts.get('update'), None)
5784
5782
5785 @command('^update|up|checkout|co',
5783 @command('^update|up|checkout|co',
5786 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5784 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5787 ('c', 'check', None,
5785 ('c', 'check', None,
5788 _('update across branches if no uncommitted changes')),
5786 _('update across branches if no uncommitted changes')),
5789 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5787 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5790 ('r', 'rev', '', _('revision'), _('REV'))],
5788 ('r', 'rev', '', _('revision'), _('REV'))],
5791 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5789 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5792 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5790 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5793 """update working directory (or switch revisions)
5791 """update working directory (or switch revisions)
5794
5792
5795 Update the repository's working directory to the specified
5793 Update the repository's working directory to the specified
5796 changeset. If no changeset is specified, update to the tip of the
5794 changeset. If no changeset is specified, update to the tip of the
5797 current named branch and move the current bookmark (see :hg:`help
5795 current named branch and move the current bookmark (see :hg:`help
5798 bookmarks`).
5796 bookmarks`).
5799
5797
5800 Update sets the working directory's parent revision to the specified
5798 Update sets the working directory's parent revision to the specified
5801 changeset (see :hg:`help parents`).
5799 changeset (see :hg:`help parents`).
5802
5800
5803 If the changeset is not a descendant or ancestor of the working
5801 If the changeset is not a descendant or ancestor of the working
5804 directory's parent, the update is aborted. With the -c/--check
5802 directory's parent, the update is aborted. With the -c/--check
5805 option, the working directory is checked for uncommitted changes; if
5803 option, the working directory is checked for uncommitted changes; if
5806 none are found, the working directory is updated to the specified
5804 none are found, the working directory is updated to the specified
5807 changeset.
5805 changeset.
5808
5806
5809 .. container:: verbose
5807 .. container:: verbose
5810
5808
5811 The following rules apply when the working directory contains
5809 The following rules apply when the working directory contains
5812 uncommitted changes:
5810 uncommitted changes:
5813
5811
5814 1. If neither -c/--check nor -C/--clean is specified, and if
5812 1. If neither -c/--check nor -C/--clean is specified, and if
5815 the requested changeset is an ancestor or descendant of
5813 the requested changeset is an ancestor or descendant of
5816 the working directory's parent, the uncommitted changes
5814 the working directory's parent, the uncommitted changes
5817 are merged into the requested changeset and the merged
5815 are merged into the requested changeset and the merged
5818 result is left uncommitted. If the requested changeset is
5816 result is left uncommitted. If the requested changeset is
5819 not an ancestor or descendant (that is, it is on another
5817 not an ancestor or descendant (that is, it is on another
5820 branch), the update is aborted and the uncommitted changes
5818 branch), the update is aborted and the uncommitted changes
5821 are preserved.
5819 are preserved.
5822
5820
5823 2. With the -c/--check option, the update is aborted and the
5821 2. With the -c/--check option, the update is aborted and the
5824 uncommitted changes are preserved.
5822 uncommitted changes are preserved.
5825
5823
5826 3. With the -C/--clean option, uncommitted changes are discarded and
5824 3. With the -C/--clean option, uncommitted changes are discarded and
5827 the working directory is updated to the requested changeset.
5825 the working directory is updated to the requested changeset.
5828
5826
5829 To cancel an uncommitted merge (and lose your changes), use
5827 To cancel an uncommitted merge (and lose your changes), use
5830 :hg:`update --clean .`.
5828 :hg:`update --clean .`.
5831
5829
5832 Use null as the changeset to remove the working directory (like
5830 Use null as the changeset to remove the working directory (like
5833 :hg:`clone -U`).
5831 :hg:`clone -U`).
5834
5832
5835 If you want to revert just one file to an older revision, use
5833 If you want to revert just one file to an older revision, use
5836 :hg:`revert [-r REV] NAME`.
5834 :hg:`revert [-r REV] NAME`.
5837
5835
5838 See :hg:`help dates` for a list of formats valid for -d/--date.
5836 See :hg:`help dates` for a list of formats valid for -d/--date.
5839
5837
5840 Returns 0 on success, 1 if there are unresolved files.
5838 Returns 0 on success, 1 if there are unresolved files.
5841 """
5839 """
5842 if rev and node:
5840 if rev and node:
5843 raise util.Abort(_("please specify just one revision"))
5841 raise util.Abort(_("please specify just one revision"))
5844
5842
5845 if rev is None or rev == '':
5843 if rev is None or rev == '':
5846 rev = node
5844 rev = node
5847
5845
5848 # with no argument, we also move the current bookmark, if any
5846 # with no argument, we also move the current bookmark, if any
5849 movemarkfrom = None
5847 movemarkfrom = None
5850 if rev is None:
5848 if rev is None:
5851 movemarkfrom = repo['.'].node()
5849 movemarkfrom = repo['.'].node()
5852
5850
5853 # if we defined a bookmark, we have to remember the original bookmark name
5851 # if we defined a bookmark, we have to remember the original bookmark name
5854 brev = rev
5852 brev = rev
5855 rev = scmutil.revsingle(repo, rev, rev).rev()
5853 rev = scmutil.revsingle(repo, rev, rev).rev()
5856
5854
5857 if check and clean:
5855 if check and clean:
5858 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5856 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5859
5857
5860 if date:
5858 if date:
5861 if rev is not None:
5859 if rev is not None:
5862 raise util.Abort(_("you can't specify a revision and a date"))
5860 raise util.Abort(_("you can't specify a revision and a date"))
5863 rev = cmdutil.finddate(ui, repo, date)
5861 rev = cmdutil.finddate(ui, repo, date)
5864
5862
5865 if check:
5863 if check:
5866 c = repo[None]
5864 c = repo[None]
5867 if c.dirty(merge=False, branch=False):
5865 if c.dirty(merge=False, branch=False):
5868 raise util.Abort(_("uncommitted local changes"))
5866 raise util.Abort(_("uncommitted local changes"))
5869 if rev is None:
5867 if rev is None:
5870 rev = repo[repo[None].branch()].rev()
5868 rev = repo[repo[None].branch()].rev()
5871 mergemod._checkunknown(repo, repo[None], repo[rev])
5869 mergemod._checkunknown(repo, repo[None], repo[rev])
5872
5870
5873 if clean:
5871 if clean:
5874 ret = hg.clean(repo, rev)
5872 ret = hg.clean(repo, rev)
5875 else:
5873 else:
5876 ret = hg.update(repo, rev)
5874 ret = hg.update(repo, rev)
5877
5875
5878 if not ret and movemarkfrom:
5876 if not ret and movemarkfrom:
5879 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5877 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5880 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5878 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5881 elif brev in repo._bookmarks:
5879 elif brev in repo._bookmarks:
5882 bookmarks.setcurrent(repo, brev)
5880 bookmarks.setcurrent(repo, brev)
5883 elif brev:
5881 elif brev:
5884 bookmarks.unsetcurrent(repo)
5882 bookmarks.unsetcurrent(repo)
5885
5883
5886 return ret
5884 return ret
5887
5885
5888 @command('verify', [])
5886 @command('verify', [])
5889 def verify(ui, repo):
5887 def verify(ui, repo):
5890 """verify the integrity of the repository
5888 """verify the integrity of the repository
5891
5889
5892 Verify the integrity of the current repository.
5890 Verify the integrity of the current repository.
5893
5891
5894 This will perform an extensive check of the repository's
5892 This will perform an extensive check of the repository's
5895 integrity, validating the hashes and checksums of each entry in
5893 integrity, validating the hashes and checksums of each entry in
5896 the changelog, manifest, and tracked files, as well as the
5894 the changelog, manifest, and tracked files, as well as the
5897 integrity of their crosslinks and indices.
5895 integrity of their crosslinks and indices.
5898
5896
5899 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5897 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5900 for more information about recovery from corruption of the
5898 for more information about recovery from corruption of the
5901 repository.
5899 repository.
5902
5900
5903 Returns 0 on success, 1 if errors are encountered.
5901 Returns 0 on success, 1 if errors are encountered.
5904 """
5902 """
5905 return hg.verify(repo)
5903 return hg.verify(repo)
5906
5904
5907 @command('version', [])
5905 @command('version', [])
5908 def version_(ui):
5906 def version_(ui):
5909 """output version and copyright information"""
5907 """output version and copyright information"""
5910 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5908 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5911 % util.version())
5909 % util.version())
5912 ui.status(_(
5910 ui.status(_(
5913 "(see http://mercurial.selenic.com for more information)\n"
5911 "(see http://mercurial.selenic.com for more information)\n"
5914 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5912 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5915 "This is free software; see the source for copying conditions. "
5913 "This is free software; see the source for copying conditions. "
5916 "There is NO\nwarranty; "
5914 "There is NO\nwarranty; "
5917 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5915 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5918 ))
5916 ))
5919
5917
5920 norepo = ("clone init version help debugcommands debugcomplete"
5918 norepo = ("clone init version help debugcommands debugcomplete"
5921 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5919 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5922 " debugknown debuggetbundle debugbundle")
5920 " debugknown debuggetbundle debugbundle")
5923 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5921 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5924 " debugdata debugindex debugindexdot debugrevlog")
5922 " debugdata debugindex debugindexdot debugrevlog")
5925 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5923 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5926 " remove resolve status debugwalk")
5924 " remove resolve status debugwalk")
@@ -1,520 +1,520 b''
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 bookmark rev -1
8 bookmark rev -1
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmarks
14 $ hg bookmarks
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmarks --color=always
20 > bookmarks --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22
22
23 $ echo a > a
23 $ echo a > a
24 $ hg add a
24 $ hg add a
25 $ hg commit -m 0
25 $ hg commit -m 0
26
26
27 bookmark X moved to rev 0
27 bookmark X moved to rev 0
28
28
29 $ hg bookmarks
29 $ hg bookmarks
30 * X 0:f7b1eb17ad24
30 * X 0:f7b1eb17ad24
31
31
32 look up bookmark
32 look up bookmark
33
33
34 $ hg log -r X
34 $ hg log -r X
35 changeset: 0:f7b1eb17ad24
35 changeset: 0:f7b1eb17ad24
36 bookmark: X
36 bookmark: X
37 tag: tip
37 tag: tip
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 0
40 summary: 0
41
41
42
42
43 second bookmark for rev 0
43 second bookmark for rev 0
44
44
45 $ hg bookmark X2
45 $ hg bookmark X2
46
46
47 bookmark rev -1 again
47 bookmark rev -1 again
48
48
49 $ hg bookmark -r null Y
49 $ hg bookmark -r null Y
50
50
51 list bookmarks
51 list bookmarks
52
52
53 $ hg bookmarks
53 $ hg bookmarks
54 X 0:f7b1eb17ad24
54 X 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
56 Y -1:000000000000
56 Y -1:000000000000
57
57
58 $ echo b > b
58 $ echo b > b
59 $ hg add b
59 $ hg add b
60 $ hg commit -m 1
60 $ hg commit -m 1
61
61
62 bookmarks revset
62 bookmarks revset
63
63
64 $ hg log -r 'bookmark()'
64 $ hg log -r 'bookmark()'
65 changeset: 0:f7b1eb17ad24
65 changeset: 0:f7b1eb17ad24
66 bookmark: X
66 bookmark: X
67 user: test
67 user: test
68 date: Thu Jan 01 00:00:00 1970 +0000
68 date: Thu Jan 01 00:00:00 1970 +0000
69 summary: 0
69 summary: 0
70
70
71 changeset: 1:925d80f479bb
71 changeset: 1:925d80f479bb
72 bookmark: X2
72 bookmark: X2
73 tag: tip
73 tag: tip
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: 1
76 summary: 1
77
77
78 $ hg log -r 'bookmark(Y)'
78 $ hg log -r 'bookmark(Y)'
79 $ hg log -r 'bookmark(X2)'
79 $ hg log -r 'bookmark(X2)'
80 changeset: 1:925d80f479bb
80 changeset: 1:925d80f479bb
81 bookmark: X2
81 bookmark: X2
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:00 1970 +0000
84 date: Thu Jan 01 00:00:00 1970 +0000
85 summary: 1
85 summary: 1
86
86
87 $ hg log -r 'bookmark("re:X")'
87 $ hg log -r 'bookmark("re:X")'
88 changeset: 0:f7b1eb17ad24
88 changeset: 0:f7b1eb17ad24
89 bookmark: X
89 bookmark: X
90 user: test
90 user: test
91 date: Thu Jan 01 00:00:00 1970 +0000
91 date: Thu Jan 01 00:00:00 1970 +0000
92 summary: 0
92 summary: 0
93
93
94 changeset: 1:925d80f479bb
94 changeset: 1:925d80f479bb
95 bookmark: X2
95 bookmark: X2
96 tag: tip
96 tag: tip
97 user: test
97 user: test
98 date: Thu Jan 01 00:00:00 1970 +0000
98 date: Thu Jan 01 00:00:00 1970 +0000
99 summary: 1
99 summary: 1
100
100
101 $ hg log -r 'bookmark(unknown)'
101 $ hg log -r 'bookmark(unknown)'
102 abort: bookmark 'unknown' does not exist
102 abort: bookmark 'unknown' does not exist
103 [255]
103 [255]
104
104
105 $ hg help revsets | grep 'bookmark('
105 $ hg help revsets | grep 'bookmark('
106 "bookmark([name])"
106 "bookmark([name])"
107
107
108 bookmarks X and X2 moved to rev 1, Y at rev -1
108 bookmarks X and X2 moved to rev 1, Y at rev -1
109
109
110 $ hg bookmarks
110 $ hg bookmarks
111 X 0:f7b1eb17ad24
111 X 0:f7b1eb17ad24
112 * X2 1:925d80f479bb
112 * X2 1:925d80f479bb
113 Y -1:000000000000
113 Y -1:000000000000
114
114
115 bookmark rev 0 again
115 bookmark rev 0 again
116
116
117 $ hg bookmark -r 0 Z
117 $ hg bookmark -r 0 Z
118
118
119 $ hg update X
119 $ hg update X
120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
121 $ echo c > c
121 $ echo c > c
122 $ hg add c
122 $ hg add c
123 $ hg commit -m 2
123 $ hg commit -m 2
124 created new head
124 created new head
125
125
126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
127
127
128 $ hg bookmarks
128 $ hg bookmarks
129 * X 2:db815d6d32e6
129 * X 2:db815d6d32e6
130 X2 1:925d80f479bb
130 X2 1:925d80f479bb
131 Y -1:000000000000
131 Y -1:000000000000
132 Z 0:f7b1eb17ad24
132 Z 0:f7b1eb17ad24
133
133
134 rename nonexistent bookmark
134 rename nonexistent bookmark
135
135
136 $ hg bookmark -m A B
136 $ hg bookmark -m A B
137 abort: bookmark 'A' does not exist
137 abort: bookmark 'A' does not exist
138 [255]
138 [255]
139
139
140 rename to existent bookmark
140 rename to existent bookmark
141
141
142 $ hg bookmark -m X Y
142 $ hg bookmark -m X Y
143 abort: bookmark 'Y' already exists (use -f to force)
143 abort: bookmark 'Y' already exists (use -f to force)
144 [255]
144 [255]
145
145
146 force rename to existent bookmark
146 force rename to existent bookmark
147
147
148 $ hg bookmark -f -m X Y
148 $ hg bookmark -f -m X Y
149
149
150 list bookmarks
150 list bookmarks
151
151
152 $ hg bookmark
152 $ hg bookmark
153 X2 1:925d80f479bb
153 X2 1:925d80f479bb
154 * Y 2:db815d6d32e6
154 * Y 2:db815d6d32e6
155 Z 0:f7b1eb17ad24
155 Z 0:f7b1eb17ad24
156
156
157 bookmarks from a revset
157 bookmarks from a revset
158 $ hg bookmark -r '.^1' REVSET
158 $ hg bookmark -r '.^1' REVSET
159 $ hg bookmark -r ':tip' TIP
159 $ hg bookmark -r ':tip' TIP
160 $ hg bookmarks
160 $ hg bookmarks
161 REVSET 0:f7b1eb17ad24
161 REVSET 0:f7b1eb17ad24
162 * TIP 2:db815d6d32e6
162 * TIP 2:db815d6d32e6
163 X2 1:925d80f479bb
163 X2 1:925d80f479bb
164 Y 2:db815d6d32e6
164 Y 2:db815d6d32e6
165 Z 0:f7b1eb17ad24
165 Z 0:f7b1eb17ad24
166
166
167 $ hg bookmark -d REVSET
167 $ hg bookmark -d REVSET
168 $ hg bookmark -d TIP
168 $ hg bookmark -d TIP
169
169
170 rename without new name
170 rename without new name
171
171
172 $ hg bookmark -m Y
172 $ hg bookmark -m Y
173 abort: new bookmark name required
173 abort: new bookmark name required
174 [255]
174 [255]
175
175
176 delete without name
176 delete without name
177
177
178 $ hg bookmark -d
178 $ hg bookmark -d
179 abort: bookmark name required
179 abort: bookmark name required
180 [255]
180 [255]
181
181
182 delete nonexistent bookmark
182 delete nonexistent bookmark
183
183
184 $ hg bookmark -d A
184 $ hg bookmark -d A
185 abort: bookmark 'A' does not exist
185 abort: bookmark 'A' does not exist
186 [255]
186 [255]
187
187
188 bookmark name with spaces should be stripped
188 bookmark name with spaces should be stripped
189
189
190 $ hg bookmark ' x y '
190 $ hg bookmark ' x y '
191
191
192 list bookmarks
192 list bookmarks
193
193
194 $ hg bookmarks
194 $ hg bookmarks
195 X2 1:925d80f479bb
195 X2 1:925d80f479bb
196 Y 2:db815d6d32e6
196 Y 2:db815d6d32e6
197 Z 0:f7b1eb17ad24
197 Z 0:f7b1eb17ad24
198 * x y 2:db815d6d32e6
198 * x y 2:db815d6d32e6
199
199
200 look up stripped bookmark name
200 look up stripped bookmark name
201
201
202 $ hg log -r '"x y"'
202 $ hg log -r '"x y"'
203 changeset: 2:db815d6d32e6
203 changeset: 2:db815d6d32e6
204 bookmark: Y
204 bookmark: Y
205 bookmark: x y
205 bookmark: x y
206 tag: tip
206 tag: tip
207 parent: 0:f7b1eb17ad24
207 parent: 0:f7b1eb17ad24
208 user: test
208 user: test
209 date: Thu Jan 01 00:00:00 1970 +0000
209 date: Thu Jan 01 00:00:00 1970 +0000
210 summary: 2
210 summary: 2
211
211
212
212
213 reject bookmark name with newline
213 reject bookmark name with newline
214
214
215 $ hg bookmark '
215 $ hg bookmark '
216 > '
216 > '
217 abort: bookmark name cannot contain newlines
217 abort: bookmark names cannot consist entirely of whitespace
218 [255]
218 [255]
219
219
220 $ hg bookmark -m Z '
220 $ hg bookmark -m Z '
221 > '
221 > '
222 abort: bookmark name cannot contain newlines
222 abort: bookmark names cannot consist entirely of whitespace
223 [255]
223 [255]
224
224
225 bookmark with existing name
225 bookmark with existing name
226
226
227 $ hg bookmark Z
227 $ hg bookmark Z
228 abort: bookmark 'Z' already exists (use -f to force)
228 abort: bookmark 'Z' already exists (use -f to force)
229 [255]
229 [255]
230
230
231 $ hg bookmark -m Y Z
231 $ hg bookmark -m Y Z
232 abort: bookmark 'Z' already exists (use -f to force)
232 abort: bookmark 'Z' already exists (use -f to force)
233 [255]
233 [255]
234
234
235 bookmark with name of branch
235 bookmark with name of branch
236
236
237 $ hg bookmark default
237 $ hg bookmark default
238 abort: a bookmark cannot have the name of an existing branch
238 abort: a bookmark cannot have the name of an existing branch
239 [255]
239 [255]
240
240
241 $ hg bookmark -m Y default
241 $ hg bookmark -m Y default
242 abort: a bookmark cannot have the name of an existing branch
242 abort: a bookmark cannot have the name of an existing branch
243 [255]
243 [255]
244
244
245 incompatible options
245 incompatible options
246
246
247 $ hg bookmark -m Y -d Z
247 $ hg bookmark -m Y -d Z
248 abort: --delete and --rename are incompatible
248 abort: --delete and --rename are incompatible
249 [255]
249 [255]
250
250
251 $ hg bookmark -r 1 -d Z
251 $ hg bookmark -r 1 -d Z
252 abort: --rev is incompatible with --delete
252 abort: --rev is incompatible with --delete
253 [255]
253 [255]
254
254
255 $ hg bookmark -r 1 -m Z Y
255 $ hg bookmark -r 1 -m Z Y
256 abort: --rev is incompatible with --rename
256 abort: --rev is incompatible with --rename
257 [255]
257 [255]
258
258
259 force bookmark with existing name
259 force bookmark with existing name
260
260
261 $ hg bookmark -f Z
261 $ hg bookmark -f Z
262
262
263 list bookmarks
263 list bookmarks
264
264
265 $ hg bookmark
265 $ hg bookmark
266 X2 1:925d80f479bb
266 X2 1:925d80f479bb
267 Y 2:db815d6d32e6
267 Y 2:db815d6d32e6
268 * Z 2:db815d6d32e6
268 * Z 2:db815d6d32e6
269 x y 2:db815d6d32e6
269 x y 2:db815d6d32e6
270
270
271 revision but no bookmark name
271 revision but no bookmark name
272
272
273 $ hg bookmark -r .
273 $ hg bookmark -r .
274 abort: bookmark name required
274 abort: bookmark name required
275 [255]
275 [255]
276
276
277 bookmark name with whitespace only
277 bookmark name with whitespace only
278
278
279 $ hg bookmark ' '
279 $ hg bookmark ' '
280 abort: bookmark names cannot consist entirely of whitespace
280 abort: bookmark names cannot consist entirely of whitespace
281 [255]
281 [255]
282
282
283 $ hg bookmark -m Y ' '
283 $ hg bookmark -m Y ' '
284 abort: bookmark names cannot consist entirely of whitespace
284 abort: bookmark names cannot consist entirely of whitespace
285 [255]
285 [255]
286
286
287 invalid bookmark
287 invalid bookmark
288
288
289 $ hg bookmark 'foo:bar'
289 $ hg bookmark 'foo:bar'
290 abort: bookmark 'foo:bar' contains illegal character
290 abort: bookmark 'foo:bar' contains illegal character
291 [255]
291 [255]
292
292
293 the bookmark extension should be ignored now that it is part of core
293 the bookmark extension should be ignored now that it is part of core
294
294
295 $ echo "[extensions]" >> $HGRCPATH
295 $ echo "[extensions]" >> $HGRCPATH
296 $ echo "bookmarks=" >> $HGRCPATH
296 $ echo "bookmarks=" >> $HGRCPATH
297 $ hg bookmarks
297 $ hg bookmarks
298 X2 1:925d80f479bb
298 X2 1:925d80f479bb
299 Y 2:db815d6d32e6
299 Y 2:db815d6d32e6
300 * Z 2:db815d6d32e6
300 * Z 2:db815d6d32e6
301 x y 2:db815d6d32e6
301 x y 2:db815d6d32e6
302
302
303 test summary
303 test summary
304
304
305 $ hg summary
305 $ hg summary
306 parent: 2:db815d6d32e6 tip
306 parent: 2:db815d6d32e6 tip
307 2
307 2
308 branch: default
308 branch: default
309 bookmarks: *Z Y x y
309 bookmarks: *Z Y x y
310 commit: (clean)
310 commit: (clean)
311 update: 1 new changesets, 2 branch heads (merge)
311 update: 1 new changesets, 2 branch heads (merge)
312
312
313 test id
313 test id
314
314
315 $ hg id
315 $ hg id
316 db815d6d32e6 tip Y/Z/x y
316 db815d6d32e6 tip Y/Z/x y
317
317
318 test rollback
318 test rollback
319
319
320 $ echo foo > f1
320 $ echo foo > f1
321 $ hg ci -Amr
321 $ hg ci -Amr
322 adding f1
322 adding f1
323 $ hg bookmark -f Y -r 1
323 $ hg bookmark -f Y -r 1
324 $ hg bookmark -f Z -r 1
324 $ hg bookmark -f Z -r 1
325 $ hg rollback
325 $ hg rollback
326 repository tip rolled back to revision 2 (undo commit)
326 repository tip rolled back to revision 2 (undo commit)
327 working directory now based on revision 2
327 working directory now based on revision 2
328 $ hg bookmarks
328 $ hg bookmarks
329 X2 1:925d80f479bb
329 X2 1:925d80f479bb
330 Y 2:db815d6d32e6
330 Y 2:db815d6d32e6
331 * Z 2:db815d6d32e6
331 * Z 2:db815d6d32e6
332 x y 2:db815d6d32e6
332 x y 2:db815d6d32e6
333
333
334 test clone
334 test clone
335
335
336 $ hg bookmark -r 2 -i @
336 $ hg bookmark -r 2 -i @
337 $ hg bookmark -r 2 -i a@
337 $ hg bookmark -r 2 -i a@
338 $ hg bookmarks
338 $ hg bookmarks
339 @ 2:db815d6d32e6
339 @ 2:db815d6d32e6
340 X2 1:925d80f479bb
340 X2 1:925d80f479bb
341 Y 2:db815d6d32e6
341 Y 2:db815d6d32e6
342 * Z 2:db815d6d32e6
342 * Z 2:db815d6d32e6
343 a@ 2:db815d6d32e6
343 a@ 2:db815d6d32e6
344 x y 2:db815d6d32e6
344 x y 2:db815d6d32e6
345 $ hg clone . cloned-bookmarks
345 $ hg clone . cloned-bookmarks
346 updating to branch default
346 updating to branch default
347 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
347 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 $ hg -R cloned-bookmarks bookmarks
348 $ hg -R cloned-bookmarks bookmarks
349 @ 2:db815d6d32e6
349 @ 2:db815d6d32e6
350 X2 1:925d80f479bb
350 X2 1:925d80f479bb
351 Y 2:db815d6d32e6
351 Y 2:db815d6d32e6
352 Z 2:db815d6d32e6
352 Z 2:db815d6d32e6
353 a@ 2:db815d6d32e6
353 a@ 2:db815d6d32e6
354 x y 2:db815d6d32e6
354 x y 2:db815d6d32e6
355
355
356 test clone with pull protocol
356 test clone with pull protocol
357
357
358 $ hg clone --pull . cloned-bookmarks-pull
358 $ hg clone --pull . cloned-bookmarks-pull
359 requesting all changes
359 requesting all changes
360 adding changesets
360 adding changesets
361 adding manifests
361 adding manifests
362 adding file changes
362 adding file changes
363 added 3 changesets with 3 changes to 3 files (+1 heads)
363 added 3 changesets with 3 changes to 3 files (+1 heads)
364 updating to branch default
364 updating to branch default
365 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
365 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
366 $ hg -R cloned-bookmarks-pull bookmarks
366 $ hg -R cloned-bookmarks-pull bookmarks
367 @ 2:db815d6d32e6
367 @ 2:db815d6d32e6
368 X2 1:925d80f479bb
368 X2 1:925d80f479bb
369 Y 2:db815d6d32e6
369 Y 2:db815d6d32e6
370 Z 2:db815d6d32e6
370 Z 2:db815d6d32e6
371 a@ 2:db815d6d32e6
371 a@ 2:db815d6d32e6
372 x y 2:db815d6d32e6
372 x y 2:db815d6d32e6
373
373
374 $ hg bookmark -d @
374 $ hg bookmark -d @
375 $ hg bookmark -d a@
375 $ hg bookmark -d a@
376
376
377 test clone with a specific revision
377 test clone with a specific revision
378
378
379 $ hg clone -r 925d80 . cloned-bookmarks-rev
379 $ hg clone -r 925d80 . cloned-bookmarks-rev
380 adding changesets
380 adding changesets
381 adding manifests
381 adding manifests
382 adding file changes
382 adding file changes
383 added 2 changesets with 2 changes to 2 files
383 added 2 changesets with 2 changes to 2 files
384 updating to branch default
384 updating to branch default
385 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
385 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
386 $ hg -R cloned-bookmarks-rev bookmarks
386 $ hg -R cloned-bookmarks-rev bookmarks
387 X2 1:925d80f479bb
387 X2 1:925d80f479bb
388
388
389 test clone with update to a bookmark
389 test clone with update to a bookmark
390
390
391 $ hg clone -u Z . cloned-bookmarks-update
391 $ hg clone -u Z . cloned-bookmarks-update
392 updating to branch default
392 updating to branch default
393 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
393 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
394 $ hg -R cloned-bookmarks-update bookmarks
394 $ hg -R cloned-bookmarks-update bookmarks
395 X2 1:925d80f479bb
395 X2 1:925d80f479bb
396 Y 2:db815d6d32e6
396 Y 2:db815d6d32e6
397 * Z 2:db815d6d32e6
397 * Z 2:db815d6d32e6
398 x y 2:db815d6d32e6
398 x y 2:db815d6d32e6
399
399
400 create bundle with two heads
400 create bundle with two heads
401
401
402 $ hg clone . tobundle
402 $ hg clone . tobundle
403 updating to branch default
403 updating to branch default
404 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 $ echo x > tobundle/x
405 $ echo x > tobundle/x
406 $ hg -R tobundle add tobundle/x
406 $ hg -R tobundle add tobundle/x
407 $ hg -R tobundle commit -m'x'
407 $ hg -R tobundle commit -m'x'
408 $ hg -R tobundle update -r -2
408 $ hg -R tobundle update -r -2
409 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
409 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
410 $ echo y > tobundle/y
410 $ echo y > tobundle/y
411 $ hg -R tobundle branch test
411 $ hg -R tobundle branch test
412 marked working directory as branch test
412 marked working directory as branch test
413 (branches are permanent and global, did you want a bookmark?)
413 (branches are permanent and global, did you want a bookmark?)
414 $ hg -R tobundle add tobundle/y
414 $ hg -R tobundle add tobundle/y
415 $ hg -R tobundle commit -m'y'
415 $ hg -R tobundle commit -m'y'
416 $ hg -R tobundle bundle tobundle.hg
416 $ hg -R tobundle bundle tobundle.hg
417 searching for changes
417 searching for changes
418 2 changesets found
418 2 changesets found
419 $ hg unbundle tobundle.hg
419 $ hg unbundle tobundle.hg
420 adding changesets
420 adding changesets
421 adding manifests
421 adding manifests
422 adding file changes
422 adding file changes
423 added 2 changesets with 2 changes to 2 files (+1 heads)
423 added 2 changesets with 2 changes to 2 files (+1 heads)
424 (run 'hg heads' to see heads, 'hg merge' to merge)
424 (run 'hg heads' to see heads, 'hg merge' to merge)
425 $ hg update
425 $ hg update
426 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
427 $ hg bookmarks
427 $ hg bookmarks
428 X2 1:925d80f479bb
428 X2 1:925d80f479bb
429 Y 2:db815d6d32e6
429 Y 2:db815d6d32e6
430 * Z 3:125c9a1d6df6
430 * Z 3:125c9a1d6df6
431 x y 2:db815d6d32e6
431 x y 2:db815d6d32e6
432
432
433 test wrongly formated bookmark
433 test wrongly formated bookmark
434
434
435 $ echo '' >> .hg/bookmarks
435 $ echo '' >> .hg/bookmarks
436 $ hg bookmarks
436 $ hg bookmarks
437 X2 1:925d80f479bb
437 X2 1:925d80f479bb
438 Y 2:db815d6d32e6
438 Y 2:db815d6d32e6
439 * Z 3:125c9a1d6df6
439 * Z 3:125c9a1d6df6
440 x y 2:db815d6d32e6
440 x y 2:db815d6d32e6
441 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
441 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
442 $ hg bookmarks
442 $ hg bookmarks
443 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
443 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
444 X2 1:925d80f479bb
444 X2 1:925d80f479bb
445 Y 2:db815d6d32e6
445 Y 2:db815d6d32e6
446 * Z 3:125c9a1d6df6
446 * Z 3:125c9a1d6df6
447 x y 2:db815d6d32e6
447 x y 2:db815d6d32e6
448
448
449 test missing revisions
449 test missing revisions
450
450
451 $ echo "925d80f479bc z" > .hg/bookmarks
451 $ echo "925d80f479bc z" > .hg/bookmarks
452 $ hg book
452 $ hg book
453 no bookmarks set
453 no bookmarks set
454
454
455 test stripping a non-checked-out but bookmarked revision
455 test stripping a non-checked-out but bookmarked revision
456
456
457 $ hg --config extensions.graphlog= log --graph
457 $ hg --config extensions.graphlog= log --graph
458 o changeset: 4:9ba5f110a0b3
458 o changeset: 4:9ba5f110a0b3
459 | branch: test
459 | branch: test
460 | tag: tip
460 | tag: tip
461 | parent: 2:db815d6d32e6
461 | parent: 2:db815d6d32e6
462 | user: test
462 | user: test
463 | date: Thu Jan 01 00:00:00 1970 +0000
463 | date: Thu Jan 01 00:00:00 1970 +0000
464 | summary: y
464 | summary: y
465 |
465 |
466 | @ changeset: 3:125c9a1d6df6
466 | @ changeset: 3:125c9a1d6df6
467 |/ user: test
467 |/ user: test
468 | date: Thu Jan 01 00:00:00 1970 +0000
468 | date: Thu Jan 01 00:00:00 1970 +0000
469 | summary: x
469 | summary: x
470 |
470 |
471 o changeset: 2:db815d6d32e6
471 o changeset: 2:db815d6d32e6
472 | parent: 0:f7b1eb17ad24
472 | parent: 0:f7b1eb17ad24
473 | user: test
473 | user: test
474 | date: Thu Jan 01 00:00:00 1970 +0000
474 | date: Thu Jan 01 00:00:00 1970 +0000
475 | summary: 2
475 | summary: 2
476 |
476 |
477 | o changeset: 1:925d80f479bb
477 | o changeset: 1:925d80f479bb
478 |/ user: test
478 |/ user: test
479 | date: Thu Jan 01 00:00:00 1970 +0000
479 | date: Thu Jan 01 00:00:00 1970 +0000
480 | summary: 1
480 | summary: 1
481 |
481 |
482 o changeset: 0:f7b1eb17ad24
482 o changeset: 0:f7b1eb17ad24
483 user: test
483 user: test
484 date: Thu Jan 01 00:00:00 1970 +0000
484 date: Thu Jan 01 00:00:00 1970 +0000
485 summary: 0
485 summary: 0
486
486
487 $ hg book should-end-on-two
487 $ hg book should-end-on-two
488 $ hg co --clean 4
488 $ hg co --clean 4
489 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
489 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
490 $ hg book four
490 $ hg book four
491 $ hg --config extensions.mq= strip 3
491 $ hg --config extensions.mq= strip 3
492 saved backup bundle to * (glob)
492 saved backup bundle to * (glob)
493 should-end-on-two should end up pointing to revision 2, as that's the
493 should-end-on-two should end up pointing to revision 2, as that's the
494 tipmost surviving ancestor of the stripped revision.
494 tipmost surviving ancestor of the stripped revision.
495 $ hg --config extensions.graphlog= log --graph
495 $ hg --config extensions.graphlog= log --graph
496 @ changeset: 3:9ba5f110a0b3
496 @ changeset: 3:9ba5f110a0b3
497 | branch: test
497 | branch: test
498 | bookmark: four
498 | bookmark: four
499 | tag: tip
499 | tag: tip
500 | user: test
500 | user: test
501 | date: Thu Jan 01 00:00:00 1970 +0000
501 | date: Thu Jan 01 00:00:00 1970 +0000
502 | summary: y
502 | summary: y
503 |
503 |
504 o changeset: 2:db815d6d32e6
504 o changeset: 2:db815d6d32e6
505 | bookmark: should-end-on-two
505 | bookmark: should-end-on-two
506 | parent: 0:f7b1eb17ad24
506 | parent: 0:f7b1eb17ad24
507 | user: test
507 | user: test
508 | date: Thu Jan 01 00:00:00 1970 +0000
508 | date: Thu Jan 01 00:00:00 1970 +0000
509 | summary: 2
509 | summary: 2
510 |
510 |
511 | o changeset: 1:925d80f479bb
511 | o changeset: 1:925d80f479bb
512 |/ user: test
512 |/ user: test
513 | date: Thu Jan 01 00:00:00 1970 +0000
513 | date: Thu Jan 01 00:00:00 1970 +0000
514 | summary: 1
514 | summary: 1
515 |
515 |
516 o changeset: 0:f7b1eb17ad24
516 o changeset: 0:f7b1eb17ad24
517 user: test
517 user: test
518 date: Thu Jan 01 00:00:00 1970 +0000
518 date: Thu Jan 01 00:00:00 1970 +0000
519 summary: 0
519 summary: 0
520
520
General Comments 0
You need to be logged in to leave comments. Login now