##// END OF EJS Templates
debugobsolete: do not traceback on invalid node identifiers
Patrick Mezard -
r17292:8da6fe27 stable
parent child Browse files
Show More
@@ -1,5881 +1,5895 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 (eg. if
546 - mark the current revision, or a known revision, to be skipped (eg. 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 if delete:
792 if delete:
793 if mark is None:
793 if mark is None:
794 raise util.Abort(_("bookmark name required"))
794 raise util.Abort(_("bookmark name required"))
795 if mark not in marks:
795 if mark not in marks:
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
797 if mark == repo._bookmarkcurrent:
797 if mark == repo._bookmarkcurrent:
798 bookmarks.setcurrent(repo, None)
798 bookmarks.setcurrent(repo, None)
799 del marks[mark]
799 del marks[mark]
800 bookmarks.write(repo)
800 bookmarks.write(repo)
801 return
801 return
802
802
803 if rename:
803 if rename:
804 if rename not in marks:
804 if rename not in marks:
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
806 if mark in marks and not force:
806 if mark in marks and not force:
807 raise util.Abort(_("bookmark '%s' already exists "
807 raise util.Abort(_("bookmark '%s' already exists "
808 "(use -f to force)") % mark)
808 "(use -f to force)") % mark)
809 if mark is None:
809 if mark is None:
810 raise util.Abort(_("new bookmark name required"))
810 raise util.Abort(_("new bookmark name required"))
811 marks[mark] = marks[rename]
811 marks[mark] = marks[rename]
812 if repo._bookmarkcurrent == rename and not inactive:
812 if repo._bookmarkcurrent == rename and not inactive:
813 bookmarks.setcurrent(repo, mark)
813 bookmarks.setcurrent(repo, mark)
814 del marks[rename]
814 del marks[rename]
815 bookmarks.write(repo)
815 bookmarks.write(repo)
816 return
816 return
817
817
818 if mark is not None:
818 if mark is not None:
819 if "\n" in mark:
819 if "\n" in mark:
820 raise util.Abort(_("bookmark name cannot contain newlines"))
820 raise util.Abort(_("bookmark name cannot contain newlines"))
821 mark = mark.strip()
821 mark = mark.strip()
822 if not mark:
822 if not mark:
823 raise util.Abort(_("bookmark names cannot consist entirely of "
823 raise util.Abort(_("bookmark names cannot consist entirely of "
824 "whitespace"))
824 "whitespace"))
825 if inactive and mark == repo._bookmarkcurrent:
825 if inactive and mark == repo._bookmarkcurrent:
826 bookmarks.setcurrent(repo, None)
826 bookmarks.setcurrent(repo, None)
827 return
827 return
828 if mark in marks and not force:
828 if mark in marks and not force:
829 raise util.Abort(_("bookmark '%s' already exists "
829 raise util.Abort(_("bookmark '%s' already exists "
830 "(use -f to force)") % mark)
830 "(use -f to force)") % mark)
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
832 and not force):
832 and not force):
833 raise util.Abort(
833 raise util.Abort(
834 _("a bookmark cannot have the name of an existing branch"))
834 _("a bookmark cannot have the name of an existing branch"))
835 if rev:
835 if rev:
836 marks[mark] = repo.lookup(rev)
836 marks[mark] = repo.lookup(rev)
837 else:
837 else:
838 marks[mark] = cur
838 marks[mark] = cur
839 if not inactive and cur == marks[mark]:
839 if not inactive and cur == marks[mark]:
840 bookmarks.setcurrent(repo, mark)
840 bookmarks.setcurrent(repo, mark)
841 bookmarks.write(repo)
841 bookmarks.write(repo)
842 return
842 return
843
843
844 if mark is None:
844 if mark is None:
845 if rev:
845 if rev:
846 raise util.Abort(_("bookmark name required"))
846 raise util.Abort(_("bookmark name required"))
847 if len(marks) == 0:
847 if len(marks) == 0:
848 ui.status(_("no bookmarks set\n"))
848 ui.status(_("no bookmarks set\n"))
849 else:
849 else:
850 for bmark, n in sorted(marks.iteritems()):
850 for bmark, n in sorted(marks.iteritems()):
851 current = repo._bookmarkcurrent
851 current = repo._bookmarkcurrent
852 if bmark == current and n == cur:
852 if bmark == current and n == cur:
853 prefix, label = '*', 'bookmarks.current'
853 prefix, label = '*', 'bookmarks.current'
854 else:
854 else:
855 prefix, label = ' ', ''
855 prefix, label = ' ', ''
856
856
857 if ui.quiet:
857 if ui.quiet:
858 ui.write("%s\n" % bmark, label=label)
858 ui.write("%s\n" % bmark, label=label)
859 else:
859 else:
860 ui.write(" %s %-25s %d:%s\n" % (
860 ui.write(" %s %-25s %d:%s\n" % (
861 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
861 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
862 label=label)
862 label=label)
863 return
863 return
864
864
865 @command('branch',
865 @command('branch',
866 [('f', 'force', None,
866 [('f', 'force', None,
867 _('set branch name even if it shadows an existing branch')),
867 _('set branch name even if it shadows an existing branch')),
868 ('C', 'clean', None, _('reset branch name to parent branch name'))],
868 ('C', 'clean', None, _('reset branch name to parent branch name'))],
869 _('[-fC] [NAME]'))
869 _('[-fC] [NAME]'))
870 def branch(ui, repo, label=None, **opts):
870 def branch(ui, repo, label=None, **opts):
871 """set or show the current branch name
871 """set or show the current branch name
872
872
873 .. note::
873 .. note::
874 Branch names are permanent and global. Use :hg:`bookmark` to create a
874 Branch names are permanent and global. Use :hg:`bookmark` to create a
875 light-weight bookmark instead. See :hg:`help glossary` for more
875 light-weight bookmark instead. See :hg:`help glossary` for more
876 information about named branches and bookmarks.
876 information about named branches and bookmarks.
877
877
878 With no argument, show the current branch name. With one argument,
878 With no argument, show the current branch name. With one argument,
879 set the working directory branch name (the branch will not exist
879 set the working directory branch name (the branch will not exist
880 in the repository until the next commit). Standard practice
880 in the repository until the next commit). Standard practice
881 recommends that primary development take place on the 'default'
881 recommends that primary development take place on the 'default'
882 branch.
882 branch.
883
883
884 Unless -f/--force is specified, branch will not let you set a
884 Unless -f/--force is specified, branch will not let you set a
885 branch name that already exists, even if it's inactive.
885 branch name that already exists, even if it's inactive.
886
886
887 Use -C/--clean to reset the working directory branch to that of
887 Use -C/--clean to reset the working directory branch to that of
888 the parent of the working directory, negating a previous branch
888 the parent of the working directory, negating a previous branch
889 change.
889 change.
890
890
891 Use the command :hg:`update` to switch to an existing branch. Use
891 Use the command :hg:`update` to switch to an existing branch. Use
892 :hg:`commit --close-branch` to mark this branch as closed.
892 :hg:`commit --close-branch` to mark this branch as closed.
893
893
894 Returns 0 on success.
894 Returns 0 on success.
895 """
895 """
896 if not opts.get('clean') and not label:
896 if not opts.get('clean') and not label:
897 ui.write("%s\n" % repo.dirstate.branch())
897 ui.write("%s\n" % repo.dirstate.branch())
898 return
898 return
899
899
900 wlock = repo.wlock()
900 wlock = repo.wlock()
901 try:
901 try:
902 if opts.get('clean'):
902 if opts.get('clean'):
903 label = repo[None].p1().branch()
903 label = repo[None].p1().branch()
904 repo.dirstate.setbranch(label)
904 repo.dirstate.setbranch(label)
905 ui.status(_('reset working directory to branch %s\n') % label)
905 ui.status(_('reset working directory to branch %s\n') % label)
906 elif label:
906 elif label:
907 if not opts.get('force') and label in repo.branchmap():
907 if not opts.get('force') and label in repo.branchmap():
908 if label not in [p.branch() for p in repo.parents()]:
908 if label not in [p.branch() for p in repo.parents()]:
909 raise util.Abort(_('a branch of the same name already'
909 raise util.Abort(_('a branch of the same name already'
910 ' exists'),
910 ' exists'),
911 # i18n: "it" refers to an existing branch
911 # i18n: "it" refers to an existing branch
912 hint=_("use 'hg update' to switch to it"))
912 hint=_("use 'hg update' to switch to it"))
913 repo.dirstate.setbranch(label)
913 repo.dirstate.setbranch(label)
914 ui.status(_('marked working directory as branch %s\n') % label)
914 ui.status(_('marked working directory as branch %s\n') % label)
915 ui.status(_('(branches are permanent and global, '
915 ui.status(_('(branches are permanent and global, '
916 'did you want a bookmark?)\n'))
916 'did you want a bookmark?)\n'))
917 finally:
917 finally:
918 wlock.release()
918 wlock.release()
919
919
920 @command('branches',
920 @command('branches',
921 [('a', 'active', False, _('show only branches that have unmerged heads')),
921 [('a', 'active', False, _('show only branches that have unmerged heads')),
922 ('c', 'closed', False, _('show normal and closed branches'))],
922 ('c', 'closed', False, _('show normal and closed branches'))],
923 _('[-ac]'))
923 _('[-ac]'))
924 def branches(ui, repo, active=False, closed=False):
924 def branches(ui, repo, active=False, closed=False):
925 """list repository named branches
925 """list repository named branches
926
926
927 List the repository's named branches, indicating which ones are
927 List the repository's named branches, indicating which ones are
928 inactive. If -c/--closed is specified, also list branches which have
928 inactive. If -c/--closed is specified, also list branches which have
929 been marked closed (see :hg:`commit --close-branch`).
929 been marked closed (see :hg:`commit --close-branch`).
930
930
931 If -a/--active is specified, only show active branches. A branch
931 If -a/--active is specified, only show active branches. A branch
932 is considered active if it contains repository heads.
932 is considered active if it contains repository heads.
933
933
934 Use the command :hg:`update` to switch to an existing branch.
934 Use the command :hg:`update` to switch to an existing branch.
935
935
936 Returns 0.
936 Returns 0.
937 """
937 """
938
938
939 hexfunc = ui.debugflag and hex or short
939 hexfunc = ui.debugflag and hex or short
940
940
941 activebranches = set([repo[n].branch() for n in repo.heads()])
941 activebranches = set([repo[n].branch() for n in repo.heads()])
942 branches = []
942 branches = []
943 for tag, heads in repo.branchmap().iteritems():
943 for tag, heads in repo.branchmap().iteritems():
944 for h in reversed(heads):
944 for h in reversed(heads):
945 ctx = repo[h]
945 ctx = repo[h]
946 isopen = not ctx.closesbranch()
946 isopen = not ctx.closesbranch()
947 if isopen:
947 if isopen:
948 tip = ctx
948 tip = ctx
949 break
949 break
950 else:
950 else:
951 tip = repo[heads[-1]]
951 tip = repo[heads[-1]]
952 isactive = tag in activebranches and isopen
952 isactive = tag in activebranches and isopen
953 branches.append((tip, isactive, isopen))
953 branches.append((tip, isactive, isopen))
954 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
954 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
955 reverse=True)
955 reverse=True)
956
956
957 for ctx, isactive, isopen in branches:
957 for ctx, isactive, isopen in branches:
958 if (not active) or isactive:
958 if (not active) or isactive:
959 if isactive:
959 if isactive:
960 label = 'branches.active'
960 label = 'branches.active'
961 notice = ''
961 notice = ''
962 elif not isopen:
962 elif not isopen:
963 if not closed:
963 if not closed:
964 continue
964 continue
965 label = 'branches.closed'
965 label = 'branches.closed'
966 notice = _(' (closed)')
966 notice = _(' (closed)')
967 else:
967 else:
968 label = 'branches.inactive'
968 label = 'branches.inactive'
969 notice = _(' (inactive)')
969 notice = _(' (inactive)')
970 if ctx.branch() == repo.dirstate.branch():
970 if ctx.branch() == repo.dirstate.branch():
971 label = 'branches.current'
971 label = 'branches.current'
972 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
972 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
973 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
973 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
974 'log.changeset')
974 'log.changeset')
975 tag = ui.label(ctx.branch(), label)
975 tag = ui.label(ctx.branch(), label)
976 if ui.quiet:
976 if ui.quiet:
977 ui.write("%s\n" % tag)
977 ui.write("%s\n" % tag)
978 else:
978 else:
979 ui.write("%s %s%s\n" % (tag, rev, notice))
979 ui.write("%s %s%s\n" % (tag, rev, notice))
980
980
981 @command('bundle',
981 @command('bundle',
982 [('f', 'force', None, _('run even when the destination is unrelated')),
982 [('f', 'force', None, _('run even when the destination is unrelated')),
983 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
983 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
984 _('REV')),
984 _('REV')),
985 ('b', 'branch', [], _('a specific branch you would like to bundle'),
985 ('b', 'branch', [], _('a specific branch you would like to bundle'),
986 _('BRANCH')),
986 _('BRANCH')),
987 ('', 'base', [],
987 ('', 'base', [],
988 _('a base changeset assumed to be available at the destination'),
988 _('a base changeset assumed to be available at the destination'),
989 _('REV')),
989 _('REV')),
990 ('a', 'all', None, _('bundle all changesets in the repository')),
990 ('a', 'all', None, _('bundle all changesets in the repository')),
991 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
991 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
992 ] + remoteopts,
992 ] + remoteopts,
993 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
993 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
994 def bundle(ui, repo, fname, dest=None, **opts):
994 def bundle(ui, repo, fname, dest=None, **opts):
995 """create a changegroup file
995 """create a changegroup file
996
996
997 Generate a compressed changegroup file collecting changesets not
997 Generate a compressed changegroup file collecting changesets not
998 known to be in another repository.
998 known to be in another repository.
999
999
1000 If you omit the destination repository, then hg assumes the
1000 If you omit the destination repository, then hg assumes the
1001 destination will have all the nodes you specify with --base
1001 destination will have all the nodes you specify with --base
1002 parameters. To create a bundle containing all changesets, use
1002 parameters. To create a bundle containing all changesets, use
1003 -a/--all (or --base null).
1003 -a/--all (or --base null).
1004
1004
1005 You can change compression method with the -t/--type option.
1005 You can change compression method with the -t/--type option.
1006 The available compression methods are: none, bzip2, and
1006 The available compression methods are: none, bzip2, and
1007 gzip (by default, bundles are compressed using bzip2).
1007 gzip (by default, bundles are compressed using bzip2).
1008
1008
1009 The bundle file can then be transferred using conventional means
1009 The bundle file can then be transferred using conventional means
1010 and applied to another repository with the unbundle or pull
1010 and applied to another repository with the unbundle or pull
1011 command. This is useful when direct push and pull are not
1011 command. This is useful when direct push and pull are not
1012 available or when exporting an entire repository is undesirable.
1012 available or when exporting an entire repository is undesirable.
1013
1013
1014 Applying bundles preserves all changeset contents including
1014 Applying bundles preserves all changeset contents including
1015 permissions, copy/rename information, and revision history.
1015 permissions, copy/rename information, and revision history.
1016
1016
1017 Returns 0 on success, 1 if no changes found.
1017 Returns 0 on success, 1 if no changes found.
1018 """
1018 """
1019 revs = None
1019 revs = None
1020 if 'rev' in opts:
1020 if 'rev' in opts:
1021 revs = scmutil.revrange(repo, opts['rev'])
1021 revs = scmutil.revrange(repo, opts['rev'])
1022
1022
1023 bundletype = opts.get('type', 'bzip2').lower()
1023 bundletype = opts.get('type', 'bzip2').lower()
1024 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1024 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1025 bundletype = btypes.get(bundletype)
1025 bundletype = btypes.get(bundletype)
1026 if bundletype not in changegroup.bundletypes:
1026 if bundletype not in changegroup.bundletypes:
1027 raise util.Abort(_('unknown bundle type specified with --type'))
1027 raise util.Abort(_('unknown bundle type specified with --type'))
1028
1028
1029 if opts.get('all'):
1029 if opts.get('all'):
1030 base = ['null']
1030 base = ['null']
1031 else:
1031 else:
1032 base = scmutil.revrange(repo, opts.get('base'))
1032 base = scmutil.revrange(repo, opts.get('base'))
1033 if base:
1033 if base:
1034 if dest:
1034 if dest:
1035 raise util.Abort(_("--base is incompatible with specifying "
1035 raise util.Abort(_("--base is incompatible with specifying "
1036 "a destination"))
1036 "a destination"))
1037 common = [repo.lookup(rev) for rev in base]
1037 common = [repo.lookup(rev) for rev in base]
1038 heads = revs and map(repo.lookup, revs) or revs
1038 heads = revs and map(repo.lookup, revs) or revs
1039 cg = repo.getbundle('bundle', heads=heads, common=common)
1039 cg = repo.getbundle('bundle', heads=heads, common=common)
1040 outgoing = None
1040 outgoing = None
1041 else:
1041 else:
1042 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1042 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1043 dest, branches = hg.parseurl(dest, opts.get('branch'))
1043 dest, branches = hg.parseurl(dest, opts.get('branch'))
1044 other = hg.peer(repo, opts, dest)
1044 other = hg.peer(repo, opts, dest)
1045 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1045 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1046 heads = revs and map(repo.lookup, revs) or revs
1046 heads = revs and map(repo.lookup, revs) or revs
1047 outgoing = discovery.findcommonoutgoing(repo, other,
1047 outgoing = discovery.findcommonoutgoing(repo, other,
1048 onlyheads=heads,
1048 onlyheads=heads,
1049 force=opts.get('force'),
1049 force=opts.get('force'),
1050 portable=True)
1050 portable=True)
1051 cg = repo.getlocalbundle('bundle', outgoing)
1051 cg = repo.getlocalbundle('bundle', outgoing)
1052 if not cg:
1052 if not cg:
1053 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1053 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1054 return 1
1054 return 1
1055
1055
1056 changegroup.writebundle(cg, fname, bundletype)
1056 changegroup.writebundle(cg, fname, bundletype)
1057
1057
1058 @command('cat',
1058 @command('cat',
1059 [('o', 'output', '',
1059 [('o', 'output', '',
1060 _('print output to file with formatted name'), _('FORMAT')),
1060 _('print output to file with formatted name'), _('FORMAT')),
1061 ('r', 'rev', '', _('print the given revision'), _('REV')),
1061 ('r', 'rev', '', _('print the given revision'), _('REV')),
1062 ('', 'decode', None, _('apply any matching decode filter')),
1062 ('', 'decode', None, _('apply any matching decode filter')),
1063 ] + walkopts,
1063 ] + walkopts,
1064 _('[OPTION]... FILE...'))
1064 _('[OPTION]... FILE...'))
1065 def cat(ui, repo, file1, *pats, **opts):
1065 def cat(ui, repo, file1, *pats, **opts):
1066 """output the current or given revision of files
1066 """output the current or given revision of files
1067
1067
1068 Print the specified files as they were at the given revision. If
1068 Print the specified files as they were at the given revision. If
1069 no revision is given, the parent of the working directory is used,
1069 no revision is given, the parent of the working directory is used,
1070 or tip if no revision is checked out.
1070 or tip if no revision is checked out.
1071
1071
1072 Output may be to a file, in which case the name of the file is
1072 Output may be to a file, in which case the name of the file is
1073 given using a format string. The formatting rules are the same as
1073 given using a format string. The formatting rules are the same as
1074 for the export command, with the following additions:
1074 for the export command, with the following additions:
1075
1075
1076 :``%s``: basename of file being printed
1076 :``%s``: basename of file being printed
1077 :``%d``: dirname of file being printed, or '.' if in repository root
1077 :``%d``: dirname of file being printed, or '.' if in repository root
1078 :``%p``: root-relative path name of file being printed
1078 :``%p``: root-relative path name of file being printed
1079
1079
1080 Returns 0 on success.
1080 Returns 0 on success.
1081 """
1081 """
1082 ctx = scmutil.revsingle(repo, opts.get('rev'))
1082 ctx = scmutil.revsingle(repo, opts.get('rev'))
1083 err = 1
1083 err = 1
1084 m = scmutil.match(ctx, (file1,) + pats, opts)
1084 m = scmutil.match(ctx, (file1,) + pats, opts)
1085 for abs in ctx.walk(m):
1085 for abs in ctx.walk(m):
1086 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1086 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1087 pathname=abs)
1087 pathname=abs)
1088 data = ctx[abs].data()
1088 data = ctx[abs].data()
1089 if opts.get('decode'):
1089 if opts.get('decode'):
1090 data = repo.wwritedata(abs, data)
1090 data = repo.wwritedata(abs, data)
1091 fp.write(data)
1091 fp.write(data)
1092 fp.close()
1092 fp.close()
1093 err = 0
1093 err = 0
1094 return err
1094 return err
1095
1095
1096 @command('^clone',
1096 @command('^clone',
1097 [('U', 'noupdate', None,
1097 [('U', 'noupdate', None,
1098 _('the clone will include an empty working copy (only a repository)')),
1098 _('the clone will include an empty working copy (only a repository)')),
1099 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1099 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1100 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1100 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1101 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1101 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1102 ('', 'pull', None, _('use pull protocol to copy metadata')),
1102 ('', 'pull', None, _('use pull protocol to copy metadata')),
1103 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1103 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1104 ] + remoteopts,
1104 ] + remoteopts,
1105 _('[OPTION]... SOURCE [DEST]'))
1105 _('[OPTION]... SOURCE [DEST]'))
1106 def clone(ui, source, dest=None, **opts):
1106 def clone(ui, source, dest=None, **opts):
1107 """make a copy of an existing repository
1107 """make a copy of an existing repository
1108
1108
1109 Create a copy of an existing repository in a new directory.
1109 Create a copy of an existing repository in a new directory.
1110
1110
1111 If no destination directory name is specified, it defaults to the
1111 If no destination directory name is specified, it defaults to the
1112 basename of the source.
1112 basename of the source.
1113
1113
1114 The location of the source is added to the new repository's
1114 The location of the source is added to the new repository's
1115 ``.hg/hgrc`` file, as the default to be used for future pulls.
1115 ``.hg/hgrc`` file, as the default to be used for future pulls.
1116
1116
1117 Only local paths and ``ssh://`` URLs are supported as
1117 Only local paths and ``ssh://`` URLs are supported as
1118 destinations. For ``ssh://`` destinations, no working directory or
1118 destinations. For ``ssh://`` destinations, no working directory or
1119 ``.hg/hgrc`` will be created on the remote side.
1119 ``.hg/hgrc`` will be created on the remote side.
1120
1120
1121 To pull only a subset of changesets, specify one or more revisions
1121 To pull only a subset of changesets, specify one or more revisions
1122 identifiers with -r/--rev or branches with -b/--branch. The
1122 identifiers with -r/--rev or branches with -b/--branch. The
1123 resulting clone will contain only the specified changesets and
1123 resulting clone will contain only the specified changesets and
1124 their ancestors. These options (or 'clone src#rev dest') imply
1124 their ancestors. These options (or 'clone src#rev dest') imply
1125 --pull, even for local source repositories. Note that specifying a
1125 --pull, even for local source repositories. Note that specifying a
1126 tag will include the tagged changeset but not the changeset
1126 tag will include the tagged changeset but not the changeset
1127 containing the tag.
1127 containing the tag.
1128
1128
1129 To check out a particular version, use -u/--update, or
1129 To check out a particular version, use -u/--update, or
1130 -U/--noupdate to create a clone with no working directory.
1130 -U/--noupdate to create a clone with no working directory.
1131
1131
1132 .. container:: verbose
1132 .. container:: verbose
1133
1133
1134 For efficiency, hardlinks are used for cloning whenever the
1134 For efficiency, hardlinks are used for cloning whenever the
1135 source and destination are on the same filesystem (note this
1135 source and destination are on the same filesystem (note this
1136 applies only to the repository data, not to the working
1136 applies only to the repository data, not to the working
1137 directory). Some filesystems, such as AFS, implement hardlinking
1137 directory). Some filesystems, such as AFS, implement hardlinking
1138 incorrectly, but do not report errors. In these cases, use the
1138 incorrectly, but do not report errors. In these cases, use the
1139 --pull option to avoid hardlinking.
1139 --pull option to avoid hardlinking.
1140
1140
1141 In some cases, you can clone repositories and the working
1141 In some cases, you can clone repositories and the working
1142 directory using full hardlinks with ::
1142 directory using full hardlinks with ::
1143
1143
1144 $ cp -al REPO REPOCLONE
1144 $ cp -al REPO REPOCLONE
1145
1145
1146 This is the fastest way to clone, but it is not always safe. The
1146 This is the fastest way to clone, but it is not always safe. The
1147 operation is not atomic (making sure REPO is not modified during
1147 operation is not atomic (making sure REPO is not modified during
1148 the operation is up to you) and you have to make sure your
1148 the operation is up to you) and you have to make sure your
1149 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1149 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1150 so). Also, this is not compatible with certain extensions that
1150 so). Also, this is not compatible with certain extensions that
1151 place their metadata under the .hg directory, such as mq.
1151 place their metadata under the .hg directory, such as mq.
1152
1152
1153 Mercurial will update the working directory to the first applicable
1153 Mercurial will update the working directory to the first applicable
1154 revision from this list:
1154 revision from this list:
1155
1155
1156 a) null if -U or the source repository has no changesets
1156 a) null if -U or the source repository has no changesets
1157 b) if -u . and the source repository is local, the first parent of
1157 b) if -u . and the source repository is local, the first parent of
1158 the source repository's working directory
1158 the source repository's working directory
1159 c) the changeset specified with -u (if a branch name, this means the
1159 c) the changeset specified with -u (if a branch name, this means the
1160 latest head of that branch)
1160 latest head of that branch)
1161 d) the changeset specified with -r
1161 d) the changeset specified with -r
1162 e) the tipmost head specified with -b
1162 e) the tipmost head specified with -b
1163 f) the tipmost head specified with the url#branch source syntax
1163 f) the tipmost head specified with the url#branch source syntax
1164 g) the tipmost head of the default branch
1164 g) the tipmost head of the default branch
1165 h) tip
1165 h) tip
1166
1166
1167 Examples:
1167 Examples:
1168
1168
1169 - clone a remote repository to a new directory named hg/::
1169 - clone a remote repository to a new directory named hg/::
1170
1170
1171 hg clone http://selenic.com/hg
1171 hg clone http://selenic.com/hg
1172
1172
1173 - create a lightweight local clone::
1173 - create a lightweight local clone::
1174
1174
1175 hg clone project/ project-feature/
1175 hg clone project/ project-feature/
1176
1176
1177 - clone from an absolute path on an ssh server (note double-slash)::
1177 - clone from an absolute path on an ssh server (note double-slash)::
1178
1178
1179 hg clone ssh://user@server//home/projects/alpha/
1179 hg clone ssh://user@server//home/projects/alpha/
1180
1180
1181 - do a high-speed clone over a LAN while checking out a
1181 - do a high-speed clone over a LAN while checking out a
1182 specified version::
1182 specified version::
1183
1183
1184 hg clone --uncompressed http://server/repo -u 1.5
1184 hg clone --uncompressed http://server/repo -u 1.5
1185
1185
1186 - create a repository without changesets after a particular revision::
1186 - create a repository without changesets after a particular revision::
1187
1187
1188 hg clone -r 04e544 experimental/ good/
1188 hg clone -r 04e544 experimental/ good/
1189
1189
1190 - clone (and track) a particular named branch::
1190 - clone (and track) a particular named branch::
1191
1191
1192 hg clone http://selenic.com/hg#stable
1192 hg clone http://selenic.com/hg#stable
1193
1193
1194 See :hg:`help urls` for details on specifying URLs.
1194 See :hg:`help urls` for details on specifying URLs.
1195
1195
1196 Returns 0 on success.
1196 Returns 0 on success.
1197 """
1197 """
1198 if opts.get('noupdate') and opts.get('updaterev'):
1198 if opts.get('noupdate') and opts.get('updaterev'):
1199 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1199 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1200
1200
1201 r = hg.clone(ui, opts, source, dest,
1201 r = hg.clone(ui, opts, source, dest,
1202 pull=opts.get('pull'),
1202 pull=opts.get('pull'),
1203 stream=opts.get('uncompressed'),
1203 stream=opts.get('uncompressed'),
1204 rev=opts.get('rev'),
1204 rev=opts.get('rev'),
1205 update=opts.get('updaterev') or not opts.get('noupdate'),
1205 update=opts.get('updaterev') or not opts.get('noupdate'),
1206 branch=opts.get('branch'))
1206 branch=opts.get('branch'))
1207
1207
1208 return r is None
1208 return r is None
1209
1209
1210 @command('^commit|ci',
1210 @command('^commit|ci',
1211 [('A', 'addremove', None,
1211 [('A', 'addremove', None,
1212 _('mark new/missing files as added/removed before committing')),
1212 _('mark new/missing files as added/removed before committing')),
1213 ('', 'close-branch', None,
1213 ('', 'close-branch', None,
1214 _('mark a branch as closed, hiding it from the branch list')),
1214 _('mark a branch as closed, hiding it from the branch list')),
1215 ('', 'amend', None, _('amend the parent of the working dir')),
1215 ('', 'amend', None, _('amend the parent of the working dir')),
1216 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1216 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1217 _('[OPTION]... [FILE]...'))
1217 _('[OPTION]... [FILE]...'))
1218 def commit(ui, repo, *pats, **opts):
1218 def commit(ui, repo, *pats, **opts):
1219 """commit the specified files or all outstanding changes
1219 """commit the specified files or all outstanding changes
1220
1220
1221 Commit changes to the given files into the repository. Unlike a
1221 Commit changes to the given files into the repository. Unlike a
1222 centralized SCM, this operation is a local operation. See
1222 centralized SCM, this operation is a local operation. See
1223 :hg:`push` for a way to actively distribute your changes.
1223 :hg:`push` for a way to actively distribute your changes.
1224
1224
1225 If a list of files is omitted, all changes reported by :hg:`status`
1225 If a list of files is omitted, all changes reported by :hg:`status`
1226 will be committed.
1226 will be committed.
1227
1227
1228 If you are committing the result of a merge, do not provide any
1228 If you are committing the result of a merge, do not provide any
1229 filenames or -I/-X filters.
1229 filenames or -I/-X filters.
1230
1230
1231 If no commit message is specified, Mercurial starts your
1231 If no commit message is specified, Mercurial starts your
1232 configured editor where you can enter a message. In case your
1232 configured editor where you can enter a message. In case your
1233 commit fails, you will find a backup of your message in
1233 commit fails, you will find a backup of your message in
1234 ``.hg/last-message.txt``.
1234 ``.hg/last-message.txt``.
1235
1235
1236 The --amend flag can be used to amend the parent of the
1236 The --amend flag can be used to amend the parent of the
1237 working directory with a new commit that contains the changes
1237 working directory with a new commit that contains the changes
1238 in the parent in addition to those currently reported by :hg:`status`,
1238 in the parent in addition to those currently reported by :hg:`status`,
1239 if there are any. The old commit is stored in a backup bundle in
1239 if there are any. The old commit is stored in a backup bundle in
1240 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1240 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1241 on how to restore it).
1241 on how to restore it).
1242
1242
1243 Message, user and date are taken from the amended commit unless
1243 Message, user and date are taken from the amended commit unless
1244 specified. When a message isn't specified on the command line,
1244 specified. When a message isn't specified on the command line,
1245 the editor will open with the message of the amended commit.
1245 the editor will open with the message of the amended commit.
1246
1246
1247 It is not possible to amend public changesets (see :hg:`help phases`)
1247 It is not possible to amend public changesets (see :hg:`help phases`)
1248 or changesets that have children.
1248 or changesets that have children.
1249
1249
1250 See :hg:`help dates` for a list of formats valid for -d/--date.
1250 See :hg:`help dates` for a list of formats valid for -d/--date.
1251
1251
1252 Returns 0 on success, 1 if nothing changed.
1252 Returns 0 on success, 1 if nothing changed.
1253 """
1253 """
1254 if opts.get('subrepos'):
1254 if opts.get('subrepos'):
1255 # Let --subrepos on the command line overide config setting.
1255 # Let --subrepos on the command line overide config setting.
1256 ui.setconfig('ui', 'commitsubrepos', True)
1256 ui.setconfig('ui', 'commitsubrepos', True)
1257
1257
1258 extra = {}
1258 extra = {}
1259 if opts.get('close_branch'):
1259 if opts.get('close_branch'):
1260 if repo['.'].node() not in repo.branchheads():
1260 if repo['.'].node() not in repo.branchheads():
1261 # The topo heads set is included in the branch heads set of the
1261 # The topo heads set is included in the branch heads set of the
1262 # current branch, so it's sufficient to test branchheads
1262 # current branch, so it's sufficient to test branchheads
1263 raise util.Abort(_('can only close branch heads'))
1263 raise util.Abort(_('can only close branch heads'))
1264 extra['close'] = 1
1264 extra['close'] = 1
1265
1265
1266 branch = repo[None].branch()
1266 branch = repo[None].branch()
1267 bheads = repo.branchheads(branch)
1267 bheads = repo.branchheads(branch)
1268
1268
1269 if opts.get('amend'):
1269 if opts.get('amend'):
1270 if ui.configbool('ui', 'commitsubrepos'):
1270 if ui.configbool('ui', 'commitsubrepos'):
1271 raise util.Abort(_('cannot amend recursively'))
1271 raise util.Abort(_('cannot amend recursively'))
1272
1272
1273 old = repo['.']
1273 old = repo['.']
1274 if old.phase() == phases.public:
1274 if old.phase() == phases.public:
1275 raise util.Abort(_('cannot amend public changesets'))
1275 raise util.Abort(_('cannot amend public changesets'))
1276 if len(old.parents()) > 1:
1276 if len(old.parents()) > 1:
1277 raise util.Abort(_('cannot amend merge changesets'))
1277 raise util.Abort(_('cannot amend merge changesets'))
1278 if len(repo[None].parents()) > 1:
1278 if len(repo[None].parents()) > 1:
1279 raise util.Abort(_('cannot amend while merging'))
1279 raise util.Abort(_('cannot amend while merging'))
1280 if old.children():
1280 if old.children():
1281 raise util.Abort(_('cannot amend changeset with children'))
1281 raise util.Abort(_('cannot amend changeset with children'))
1282
1282
1283 e = cmdutil.commiteditor
1283 e = cmdutil.commiteditor
1284 if opts.get('force_editor'):
1284 if opts.get('force_editor'):
1285 e = cmdutil.commitforceeditor
1285 e = cmdutil.commitforceeditor
1286
1286
1287 def commitfunc(ui, repo, message, match, opts):
1287 def commitfunc(ui, repo, message, match, opts):
1288 editor = e
1288 editor = e
1289 # message contains text from -m or -l, if it's empty,
1289 # message contains text from -m or -l, if it's empty,
1290 # open the editor with the old message
1290 # open the editor with the old message
1291 if not message:
1291 if not message:
1292 message = old.description()
1292 message = old.description()
1293 editor = cmdutil.commitforceeditor
1293 editor = cmdutil.commitforceeditor
1294 return repo.commit(message,
1294 return repo.commit(message,
1295 opts.get('user') or old.user(),
1295 opts.get('user') or old.user(),
1296 opts.get('date') or old.date(),
1296 opts.get('date') or old.date(),
1297 match,
1297 match,
1298 editor=editor,
1298 editor=editor,
1299 extra=extra)
1299 extra=extra)
1300
1300
1301 current = repo._bookmarkcurrent
1301 current = repo._bookmarkcurrent
1302 marks = old.bookmarks()
1302 marks = old.bookmarks()
1303 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1303 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1304 if node == old.node():
1304 if node == old.node():
1305 ui.status(_("nothing changed\n"))
1305 ui.status(_("nothing changed\n"))
1306 return 1
1306 return 1
1307 elif marks:
1307 elif marks:
1308 ui.debug('moving bookmarks %r from %s to %s\n' %
1308 ui.debug('moving bookmarks %r from %s to %s\n' %
1309 (marks, old.hex(), hex(node)))
1309 (marks, old.hex(), hex(node)))
1310 for bm in marks:
1310 for bm in marks:
1311 repo._bookmarks[bm] = node
1311 repo._bookmarks[bm] = node
1312 if bm == current:
1312 if bm == current:
1313 bookmarks.setcurrent(repo, bm)
1313 bookmarks.setcurrent(repo, bm)
1314 bookmarks.write(repo)
1314 bookmarks.write(repo)
1315 else:
1315 else:
1316 e = cmdutil.commiteditor
1316 e = cmdutil.commiteditor
1317 if opts.get('force_editor'):
1317 if opts.get('force_editor'):
1318 e = cmdutil.commitforceeditor
1318 e = cmdutil.commitforceeditor
1319
1319
1320 def commitfunc(ui, repo, message, match, opts):
1320 def commitfunc(ui, repo, message, match, opts):
1321 return repo.commit(message, opts.get('user'), opts.get('date'),
1321 return repo.commit(message, opts.get('user'), opts.get('date'),
1322 match, editor=e, extra=extra)
1322 match, editor=e, extra=extra)
1323
1323
1324 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1324 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1325
1325
1326 if not node:
1326 if not node:
1327 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1327 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1328 if stat[3]:
1328 if stat[3]:
1329 ui.status(_("nothing changed (%d missing files, see "
1329 ui.status(_("nothing changed (%d missing files, see "
1330 "'hg status')\n") % len(stat[3]))
1330 "'hg status')\n") % len(stat[3]))
1331 else:
1331 else:
1332 ui.status(_("nothing changed\n"))
1332 ui.status(_("nothing changed\n"))
1333 return 1
1333 return 1
1334
1334
1335 ctx = repo[node]
1335 ctx = repo[node]
1336 parents = ctx.parents()
1336 parents = ctx.parents()
1337
1337
1338 if (not opts.get('amend') and bheads and node not in bheads and not
1338 if (not opts.get('amend') and bheads and node not in bheads and not
1339 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1339 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1340 ui.status(_('created new head\n'))
1340 ui.status(_('created new head\n'))
1341 # The message is not printed for initial roots. For the other
1341 # The message is not printed for initial roots. For the other
1342 # changesets, it is printed in the following situations:
1342 # changesets, it is printed in the following situations:
1343 #
1343 #
1344 # Par column: for the 2 parents with ...
1344 # Par column: for the 2 parents with ...
1345 # N: null or no parent
1345 # N: null or no parent
1346 # B: parent is on another named branch
1346 # B: parent is on another named branch
1347 # C: parent is a regular non head changeset
1347 # C: parent is a regular non head changeset
1348 # H: parent was a branch head of the current branch
1348 # H: parent was a branch head of the current branch
1349 # Msg column: whether we print "created new head" message
1349 # Msg column: whether we print "created new head" message
1350 # In the following, it is assumed that there already exists some
1350 # In the following, it is assumed that there already exists some
1351 # initial branch heads of the current branch, otherwise nothing is
1351 # initial branch heads of the current branch, otherwise nothing is
1352 # printed anyway.
1352 # printed anyway.
1353 #
1353 #
1354 # Par Msg Comment
1354 # Par Msg Comment
1355 # NN y additional topo root
1355 # NN y additional topo root
1356 #
1356 #
1357 # BN y additional branch root
1357 # BN y additional branch root
1358 # CN y additional topo head
1358 # CN y additional topo head
1359 # HN n usual case
1359 # HN n usual case
1360 #
1360 #
1361 # BB y weird additional branch root
1361 # BB y weird additional branch root
1362 # CB y branch merge
1362 # CB y branch merge
1363 # HB n merge with named branch
1363 # HB n merge with named branch
1364 #
1364 #
1365 # CC y additional head from merge
1365 # CC y additional head from merge
1366 # CH n merge with a head
1366 # CH n merge with a head
1367 #
1367 #
1368 # HH n head merge: head count decreases
1368 # HH n head merge: head count decreases
1369
1369
1370 if not opts.get('close_branch'):
1370 if not opts.get('close_branch'):
1371 for r in parents:
1371 for r in parents:
1372 if r.closesbranch() and r.branch() == branch:
1372 if r.closesbranch() and r.branch() == branch:
1373 ui.status(_('reopening closed branch head %d\n') % r)
1373 ui.status(_('reopening closed branch head %d\n') % r)
1374
1374
1375 if ui.debugflag:
1375 if ui.debugflag:
1376 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1376 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1377 elif ui.verbose:
1377 elif ui.verbose:
1378 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1378 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1379
1379
1380 @command('copy|cp',
1380 @command('copy|cp',
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1383 ] + walkopts + dryrunopts,
1383 ] + walkopts + dryrunopts,
1384 _('[OPTION]... [SOURCE]... DEST'))
1384 _('[OPTION]... [SOURCE]... DEST'))
1385 def copy(ui, repo, *pats, **opts):
1385 def copy(ui, repo, *pats, **opts):
1386 """mark files as copied for the next commit
1386 """mark files as copied for the next commit
1387
1387
1388 Mark dest as having copies of source files. If dest is a
1388 Mark dest as having copies of source files. If dest is a
1389 directory, copies are put in that directory. If dest is a file,
1389 directory, copies are put in that directory. If dest is a file,
1390 the source must be a single file.
1390 the source must be a single file.
1391
1391
1392 By default, this command copies the contents of files as they
1392 By default, this command copies the contents of files as they
1393 exist in the working directory. If invoked with -A/--after, the
1393 exist in the working directory. If invoked with -A/--after, the
1394 operation is recorded, but no copying is performed.
1394 operation is recorded, but no copying is performed.
1395
1395
1396 This command takes effect with the next commit. To undo a copy
1396 This command takes effect with the next commit. To undo a copy
1397 before that, see :hg:`revert`.
1397 before that, see :hg:`revert`.
1398
1398
1399 Returns 0 on success, 1 if errors are encountered.
1399 Returns 0 on success, 1 if errors are encountered.
1400 """
1400 """
1401 wlock = repo.wlock(False)
1401 wlock = repo.wlock(False)
1402 try:
1402 try:
1403 return cmdutil.copy(ui, repo, pats, opts)
1403 return cmdutil.copy(ui, repo, pats, opts)
1404 finally:
1404 finally:
1405 wlock.release()
1405 wlock.release()
1406
1406
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1408 def debugancestor(ui, repo, *args):
1408 def debugancestor(ui, repo, *args):
1409 """find the ancestor revision of two revisions in a given index"""
1409 """find the ancestor revision of two revisions in a given index"""
1410 if len(args) == 3:
1410 if len(args) == 3:
1411 index, rev1, rev2 = args
1411 index, rev1, rev2 = args
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1413 lookup = r.lookup
1413 lookup = r.lookup
1414 elif len(args) == 2:
1414 elif len(args) == 2:
1415 if not repo:
1415 if not repo:
1416 raise util.Abort(_("there is no Mercurial repository here "
1416 raise util.Abort(_("there is no Mercurial repository here "
1417 "(.hg not found)"))
1417 "(.hg not found)"))
1418 rev1, rev2 = args
1418 rev1, rev2 = args
1419 r = repo.changelog
1419 r = repo.changelog
1420 lookup = repo.lookup
1420 lookup = repo.lookup
1421 else:
1421 else:
1422 raise util.Abort(_('either two or three arguments required'))
1422 raise util.Abort(_('either two or three arguments required'))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1425
1425
1426 @command('debugbuilddag',
1426 @command('debugbuilddag',
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1430 _('[OPTION]... [TEXT]'))
1430 _('[OPTION]... [TEXT]'))
1431 def debugbuilddag(ui, repo, text=None,
1431 def debugbuilddag(ui, repo, text=None,
1432 mergeable_file=False,
1432 mergeable_file=False,
1433 overwritten_file=False,
1433 overwritten_file=False,
1434 new_file=False):
1434 new_file=False):
1435 """builds a repo with a given DAG from scratch in the current empty repo
1435 """builds a repo with a given DAG from scratch in the current empty repo
1436
1436
1437 The description of the DAG is read from stdin if not given on the
1437 The description of the DAG is read from stdin if not given on the
1438 command line.
1438 command line.
1439
1439
1440 Elements:
1440 Elements:
1441
1441
1442 - "+n" is a linear run of n nodes based on the current default parent
1442 - "+n" is a linear run of n nodes based on the current default parent
1443 - "." is a single node based on the current default parent
1443 - "." is a single node based on the current default parent
1444 - "$" resets the default parent to null (implied at the start);
1444 - "$" resets the default parent to null (implied at the start);
1445 otherwise the default parent is always the last node created
1445 otherwise the default parent is always the last node created
1446 - "<p" sets the default parent to the backref p
1446 - "<p" sets the default parent to the backref p
1447 - "*p" is a fork at parent p, which is a backref
1447 - "*p" is a fork at parent p, which is a backref
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1449 - "/p2" is a merge of the preceding node and p2
1449 - "/p2" is a merge of the preceding node and p2
1450 - ":tag" defines a local tag for the preceding node
1450 - ":tag" defines a local tag for the preceding node
1451 - "@branch" sets the named branch for subsequent nodes
1451 - "@branch" sets the named branch for subsequent nodes
1452 - "#...\\n" is a comment up to the end of the line
1452 - "#...\\n" is a comment up to the end of the line
1453
1453
1454 Whitespace between the above elements is ignored.
1454 Whitespace between the above elements is ignored.
1455
1455
1456 A backref is either
1456 A backref is either
1457
1457
1458 - a number n, which references the node curr-n, where curr is the current
1458 - a number n, which references the node curr-n, where curr is the current
1459 node, or
1459 node, or
1460 - the name of a local tag you placed earlier using ":tag", or
1460 - the name of a local tag you placed earlier using ":tag", or
1461 - empty to denote the default parent.
1461 - empty to denote the default parent.
1462
1462
1463 All string valued-elements are either strictly alphanumeric, or must
1463 All string valued-elements are either strictly alphanumeric, or must
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1465 """
1465 """
1466
1466
1467 if text is None:
1467 if text is None:
1468 ui.status(_("reading DAG from stdin\n"))
1468 ui.status(_("reading DAG from stdin\n"))
1469 text = ui.fin.read()
1469 text = ui.fin.read()
1470
1470
1471 cl = repo.changelog
1471 cl = repo.changelog
1472 if len(cl) > 0:
1472 if len(cl) > 0:
1473 raise util.Abort(_('repository is not empty'))
1473 raise util.Abort(_('repository is not empty'))
1474
1474
1475 # determine number of revs in DAG
1475 # determine number of revs in DAG
1476 total = 0
1476 total = 0
1477 for type, data in dagparser.parsedag(text):
1477 for type, data in dagparser.parsedag(text):
1478 if type == 'n':
1478 if type == 'n':
1479 total += 1
1479 total += 1
1480
1480
1481 if mergeable_file:
1481 if mergeable_file:
1482 linesperrev = 2
1482 linesperrev = 2
1483 # make a file with k lines per rev
1483 # make a file with k lines per rev
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1485 initialmergedlines.append("")
1485 initialmergedlines.append("")
1486
1486
1487 tags = []
1487 tags = []
1488
1488
1489 lock = tr = None
1489 lock = tr = None
1490 try:
1490 try:
1491 lock = repo.lock()
1491 lock = repo.lock()
1492 tr = repo.transaction("builddag")
1492 tr = repo.transaction("builddag")
1493
1493
1494 at = -1
1494 at = -1
1495 atbranch = 'default'
1495 atbranch = 'default'
1496 nodeids = []
1496 nodeids = []
1497 id = 0
1497 id = 0
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1499 for type, data in dagparser.parsedag(text):
1499 for type, data in dagparser.parsedag(text):
1500 if type == 'n':
1500 if type == 'n':
1501 ui.note('node %s\n' % str(data))
1501 ui.note('node %s\n' % str(data))
1502 id, ps = data
1502 id, ps = data
1503
1503
1504 files = []
1504 files = []
1505 fctxs = {}
1505 fctxs = {}
1506
1506
1507 p2 = None
1507 p2 = None
1508 if mergeable_file:
1508 if mergeable_file:
1509 fn = "mf"
1509 fn = "mf"
1510 p1 = repo[ps[0]]
1510 p1 = repo[ps[0]]
1511 if len(ps) > 1:
1511 if len(ps) > 1:
1512 p2 = repo[ps[1]]
1512 p2 = repo[ps[1]]
1513 pa = p1.ancestor(p2)
1513 pa = p1.ancestor(p2)
1514 base, local, other = [x[fn].data() for x in pa, p1, p2]
1514 base, local, other = [x[fn].data() for x in pa, p1, p2]
1515 m3 = simplemerge.Merge3Text(base, local, other)
1515 m3 = simplemerge.Merge3Text(base, local, other)
1516 ml = [l.strip() for l in m3.merge_lines()]
1516 ml = [l.strip() for l in m3.merge_lines()]
1517 ml.append("")
1517 ml.append("")
1518 elif at > 0:
1518 elif at > 0:
1519 ml = p1[fn].data().split("\n")
1519 ml = p1[fn].data().split("\n")
1520 else:
1520 else:
1521 ml = initialmergedlines
1521 ml = initialmergedlines
1522 ml[id * linesperrev] += " r%i" % id
1522 ml[id * linesperrev] += " r%i" % id
1523 mergedtext = "\n".join(ml)
1523 mergedtext = "\n".join(ml)
1524 files.append(fn)
1524 files.append(fn)
1525 fctxs[fn] = context.memfilectx(fn, mergedtext)
1525 fctxs[fn] = context.memfilectx(fn, mergedtext)
1526
1526
1527 if overwritten_file:
1527 if overwritten_file:
1528 fn = "of"
1528 fn = "of"
1529 files.append(fn)
1529 files.append(fn)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531
1531
1532 if new_file:
1532 if new_file:
1533 fn = "nf%i" % id
1533 fn = "nf%i" % id
1534 files.append(fn)
1534 files.append(fn)
1535 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1535 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1536 if len(ps) > 1:
1536 if len(ps) > 1:
1537 if not p2:
1537 if not p2:
1538 p2 = repo[ps[1]]
1538 p2 = repo[ps[1]]
1539 for fn in p2:
1539 for fn in p2:
1540 if fn.startswith("nf"):
1540 if fn.startswith("nf"):
1541 files.append(fn)
1541 files.append(fn)
1542 fctxs[fn] = p2[fn]
1542 fctxs[fn] = p2[fn]
1543
1543
1544 def fctxfn(repo, cx, path):
1544 def fctxfn(repo, cx, path):
1545 return fctxs.get(path)
1545 return fctxs.get(path)
1546
1546
1547 if len(ps) == 0 or ps[0] < 0:
1547 if len(ps) == 0 or ps[0] < 0:
1548 pars = [None, None]
1548 pars = [None, None]
1549 elif len(ps) == 1:
1549 elif len(ps) == 1:
1550 pars = [nodeids[ps[0]], None]
1550 pars = [nodeids[ps[0]], None]
1551 else:
1551 else:
1552 pars = [nodeids[p] for p in ps]
1552 pars = [nodeids[p] for p in ps]
1553 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1553 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1554 date=(id, 0),
1554 date=(id, 0),
1555 user="debugbuilddag",
1555 user="debugbuilddag",
1556 extra={'branch': atbranch})
1556 extra={'branch': atbranch})
1557 nodeid = repo.commitctx(cx)
1557 nodeid = repo.commitctx(cx)
1558 nodeids.append(nodeid)
1558 nodeids.append(nodeid)
1559 at = id
1559 at = id
1560 elif type == 'l':
1560 elif type == 'l':
1561 id, name = data
1561 id, name = data
1562 ui.note('tag %s\n' % name)
1562 ui.note('tag %s\n' % name)
1563 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1563 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1564 elif type == 'a':
1564 elif type == 'a':
1565 ui.note('branch %s\n' % data)
1565 ui.note('branch %s\n' % data)
1566 atbranch = data
1566 atbranch = data
1567 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1567 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1568 tr.close()
1568 tr.close()
1569
1569
1570 if tags:
1570 if tags:
1571 repo.opener.write("localtags", "".join(tags))
1571 repo.opener.write("localtags", "".join(tags))
1572 finally:
1572 finally:
1573 ui.progress(_('building'), None)
1573 ui.progress(_('building'), None)
1574 release(tr, lock)
1574 release(tr, lock)
1575
1575
1576 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1576 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1577 def debugbundle(ui, bundlepath, all=None, **opts):
1577 def debugbundle(ui, bundlepath, all=None, **opts):
1578 """lists the contents of a bundle"""
1578 """lists the contents of a bundle"""
1579 f = url.open(ui, bundlepath)
1579 f = url.open(ui, bundlepath)
1580 try:
1580 try:
1581 gen = changegroup.readbundle(f, bundlepath)
1581 gen = changegroup.readbundle(f, bundlepath)
1582 if all:
1582 if all:
1583 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1583 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1584
1584
1585 def showchunks(named):
1585 def showchunks(named):
1586 ui.write("\n%s\n" % named)
1586 ui.write("\n%s\n" % named)
1587 chain = None
1587 chain = None
1588 while True:
1588 while True:
1589 chunkdata = gen.deltachunk(chain)
1589 chunkdata = gen.deltachunk(chain)
1590 if not chunkdata:
1590 if not chunkdata:
1591 break
1591 break
1592 node = chunkdata['node']
1592 node = chunkdata['node']
1593 p1 = chunkdata['p1']
1593 p1 = chunkdata['p1']
1594 p2 = chunkdata['p2']
1594 p2 = chunkdata['p2']
1595 cs = chunkdata['cs']
1595 cs = chunkdata['cs']
1596 deltabase = chunkdata['deltabase']
1596 deltabase = chunkdata['deltabase']
1597 delta = chunkdata['delta']
1597 delta = chunkdata['delta']
1598 ui.write("%s %s %s %s %s %s\n" %
1598 ui.write("%s %s %s %s %s %s\n" %
1599 (hex(node), hex(p1), hex(p2),
1599 (hex(node), hex(p1), hex(p2),
1600 hex(cs), hex(deltabase), len(delta)))
1600 hex(cs), hex(deltabase), len(delta)))
1601 chain = node
1601 chain = node
1602
1602
1603 chunkdata = gen.changelogheader()
1603 chunkdata = gen.changelogheader()
1604 showchunks("changelog")
1604 showchunks("changelog")
1605 chunkdata = gen.manifestheader()
1605 chunkdata = gen.manifestheader()
1606 showchunks("manifest")
1606 showchunks("manifest")
1607 while True:
1607 while True:
1608 chunkdata = gen.filelogheader()
1608 chunkdata = gen.filelogheader()
1609 if not chunkdata:
1609 if not chunkdata:
1610 break
1610 break
1611 fname = chunkdata['filename']
1611 fname = chunkdata['filename']
1612 showchunks(fname)
1612 showchunks(fname)
1613 else:
1613 else:
1614 chunkdata = gen.changelogheader()
1614 chunkdata = gen.changelogheader()
1615 chain = None
1615 chain = None
1616 while True:
1616 while True:
1617 chunkdata = gen.deltachunk(chain)
1617 chunkdata = gen.deltachunk(chain)
1618 if not chunkdata:
1618 if not chunkdata:
1619 break
1619 break
1620 node = chunkdata['node']
1620 node = chunkdata['node']
1621 ui.write("%s\n" % hex(node))
1621 ui.write("%s\n" % hex(node))
1622 chain = node
1622 chain = node
1623 finally:
1623 finally:
1624 f.close()
1624 f.close()
1625
1625
1626 @command('debugcheckstate', [], '')
1626 @command('debugcheckstate', [], '')
1627 def debugcheckstate(ui, repo):
1627 def debugcheckstate(ui, repo):
1628 """validate the correctness of the current dirstate"""
1628 """validate the correctness of the current dirstate"""
1629 parent1, parent2 = repo.dirstate.parents()
1629 parent1, parent2 = repo.dirstate.parents()
1630 m1 = repo[parent1].manifest()
1630 m1 = repo[parent1].manifest()
1631 m2 = repo[parent2].manifest()
1631 m2 = repo[parent2].manifest()
1632 errors = 0
1632 errors = 0
1633 for f in repo.dirstate:
1633 for f in repo.dirstate:
1634 state = repo.dirstate[f]
1634 state = repo.dirstate[f]
1635 if state in "nr" and f not in m1:
1635 if state in "nr" and f not in m1:
1636 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1636 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1637 errors += 1
1637 errors += 1
1638 if state in "a" and f in m1:
1638 if state in "a" and f in m1:
1639 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1639 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1640 errors += 1
1640 errors += 1
1641 if state in "m" and f not in m1 and f not in m2:
1641 if state in "m" and f not in m1 and f not in m2:
1642 ui.warn(_("%s in state %s, but not in either manifest\n") %
1642 ui.warn(_("%s in state %s, but not in either manifest\n") %
1643 (f, state))
1643 (f, state))
1644 errors += 1
1644 errors += 1
1645 for f in m1:
1645 for f in m1:
1646 state = repo.dirstate[f]
1646 state = repo.dirstate[f]
1647 if state not in "nrm":
1647 if state not in "nrm":
1648 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1648 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1649 errors += 1
1649 errors += 1
1650 if errors:
1650 if errors:
1651 error = _(".hg/dirstate inconsistent with current parent's manifest")
1651 error = _(".hg/dirstate inconsistent with current parent's manifest")
1652 raise util.Abort(error)
1652 raise util.Abort(error)
1653
1653
1654 @command('debugcommands', [], _('[COMMAND]'))
1654 @command('debugcommands', [], _('[COMMAND]'))
1655 def debugcommands(ui, cmd='', *args):
1655 def debugcommands(ui, cmd='', *args):
1656 """list all available commands and options"""
1656 """list all available commands and options"""
1657 for cmd, vals in sorted(table.iteritems()):
1657 for cmd, vals in sorted(table.iteritems()):
1658 cmd = cmd.split('|')[0].strip('^')
1658 cmd = cmd.split('|')[0].strip('^')
1659 opts = ', '.join([i[1] for i in vals[1]])
1659 opts = ', '.join([i[1] for i in vals[1]])
1660 ui.write('%s: %s\n' % (cmd, opts))
1660 ui.write('%s: %s\n' % (cmd, opts))
1661
1661
1662 @command('debugcomplete',
1662 @command('debugcomplete',
1663 [('o', 'options', None, _('show the command options'))],
1663 [('o', 'options', None, _('show the command options'))],
1664 _('[-o] CMD'))
1664 _('[-o] CMD'))
1665 def debugcomplete(ui, cmd='', **opts):
1665 def debugcomplete(ui, cmd='', **opts):
1666 """returns the completion list associated with the given command"""
1666 """returns the completion list associated with the given command"""
1667
1667
1668 if opts.get('options'):
1668 if opts.get('options'):
1669 options = []
1669 options = []
1670 otables = [globalopts]
1670 otables = [globalopts]
1671 if cmd:
1671 if cmd:
1672 aliases, entry = cmdutil.findcmd(cmd, table, False)
1672 aliases, entry = cmdutil.findcmd(cmd, table, False)
1673 otables.append(entry[1])
1673 otables.append(entry[1])
1674 for t in otables:
1674 for t in otables:
1675 for o in t:
1675 for o in t:
1676 if "(DEPRECATED)" in o[3]:
1676 if "(DEPRECATED)" in o[3]:
1677 continue
1677 continue
1678 if o[0]:
1678 if o[0]:
1679 options.append('-%s' % o[0])
1679 options.append('-%s' % o[0])
1680 options.append('--%s' % o[1])
1680 options.append('--%s' % o[1])
1681 ui.write("%s\n" % "\n".join(options))
1681 ui.write("%s\n" % "\n".join(options))
1682 return
1682 return
1683
1683
1684 cmdlist = cmdutil.findpossible(cmd, table)
1684 cmdlist = cmdutil.findpossible(cmd, table)
1685 if ui.verbose:
1685 if ui.verbose:
1686 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1686 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1687 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1687 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1688
1688
1689 @command('debugdag',
1689 @command('debugdag',
1690 [('t', 'tags', None, _('use tags as labels')),
1690 [('t', 'tags', None, _('use tags as labels')),
1691 ('b', 'branches', None, _('annotate with branch names')),
1691 ('b', 'branches', None, _('annotate with branch names')),
1692 ('', 'dots', None, _('use dots for runs')),
1692 ('', 'dots', None, _('use dots for runs')),
1693 ('s', 'spaces', None, _('separate elements by spaces'))],
1693 ('s', 'spaces', None, _('separate elements by spaces'))],
1694 _('[OPTION]... [FILE [REV]...]'))
1694 _('[OPTION]... [FILE [REV]...]'))
1695 def debugdag(ui, repo, file_=None, *revs, **opts):
1695 def debugdag(ui, repo, file_=None, *revs, **opts):
1696 """format the changelog or an index DAG as a concise textual description
1696 """format the changelog or an index DAG as a concise textual description
1697
1697
1698 If you pass a revlog index, the revlog's DAG is emitted. If you list
1698 If you pass a revlog index, the revlog's DAG is emitted. If you list
1699 revision numbers, they get labelled in the output as rN.
1699 revision numbers, they get labelled in the output as rN.
1700
1700
1701 Otherwise, the changelog DAG of the current repo is emitted.
1701 Otherwise, the changelog DAG of the current repo is emitted.
1702 """
1702 """
1703 spaces = opts.get('spaces')
1703 spaces = opts.get('spaces')
1704 dots = opts.get('dots')
1704 dots = opts.get('dots')
1705 if file_:
1705 if file_:
1706 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1706 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1707 revs = set((int(r) for r in revs))
1707 revs = set((int(r) for r in revs))
1708 def events():
1708 def events():
1709 for r in rlog:
1709 for r in rlog:
1710 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1710 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1711 if p != -1)))
1711 if p != -1)))
1712 if r in revs:
1712 if r in revs:
1713 yield 'l', (r, "r%i" % r)
1713 yield 'l', (r, "r%i" % r)
1714 elif repo:
1714 elif repo:
1715 cl = repo.changelog
1715 cl = repo.changelog
1716 tags = opts.get('tags')
1716 tags = opts.get('tags')
1717 branches = opts.get('branches')
1717 branches = opts.get('branches')
1718 if tags:
1718 if tags:
1719 labels = {}
1719 labels = {}
1720 for l, n in repo.tags().items():
1720 for l, n in repo.tags().items():
1721 labels.setdefault(cl.rev(n), []).append(l)
1721 labels.setdefault(cl.rev(n), []).append(l)
1722 def events():
1722 def events():
1723 b = "default"
1723 b = "default"
1724 for r in cl:
1724 for r in cl:
1725 if branches:
1725 if branches:
1726 newb = cl.read(cl.node(r))[5]['branch']
1726 newb = cl.read(cl.node(r))[5]['branch']
1727 if newb != b:
1727 if newb != b:
1728 yield 'a', newb
1728 yield 'a', newb
1729 b = newb
1729 b = newb
1730 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1730 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1731 if p != -1)))
1731 if p != -1)))
1732 if tags:
1732 if tags:
1733 ls = labels.get(r)
1733 ls = labels.get(r)
1734 if ls:
1734 if ls:
1735 for l in ls:
1735 for l in ls:
1736 yield 'l', (r, l)
1736 yield 'l', (r, l)
1737 else:
1737 else:
1738 raise util.Abort(_('need repo for changelog dag'))
1738 raise util.Abort(_('need repo for changelog dag'))
1739
1739
1740 for line in dagparser.dagtextlines(events(),
1740 for line in dagparser.dagtextlines(events(),
1741 addspaces=spaces,
1741 addspaces=spaces,
1742 wraplabels=True,
1742 wraplabels=True,
1743 wrapannotations=True,
1743 wrapannotations=True,
1744 wrapnonlinear=dots,
1744 wrapnonlinear=dots,
1745 usedots=dots,
1745 usedots=dots,
1746 maxlinewidth=70):
1746 maxlinewidth=70):
1747 ui.write(line)
1747 ui.write(line)
1748 ui.write("\n")
1748 ui.write("\n")
1749
1749
1750 @command('debugdata',
1750 @command('debugdata',
1751 [('c', 'changelog', False, _('open changelog')),
1751 [('c', 'changelog', False, _('open changelog')),
1752 ('m', 'manifest', False, _('open manifest'))],
1752 ('m', 'manifest', False, _('open manifest'))],
1753 _('-c|-m|FILE REV'))
1753 _('-c|-m|FILE REV'))
1754 def debugdata(ui, repo, file_, rev = None, **opts):
1754 def debugdata(ui, repo, file_, rev = None, **opts):
1755 """dump the contents of a data file revision"""
1755 """dump the contents of a data file revision"""
1756 if opts.get('changelog') or opts.get('manifest'):
1756 if opts.get('changelog') or opts.get('manifest'):
1757 file_, rev = None, file_
1757 file_, rev = None, file_
1758 elif rev is None:
1758 elif rev is None:
1759 raise error.CommandError('debugdata', _('invalid arguments'))
1759 raise error.CommandError('debugdata', _('invalid arguments'))
1760 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1760 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1761 try:
1761 try:
1762 ui.write(r.revision(r.lookup(rev)))
1762 ui.write(r.revision(r.lookup(rev)))
1763 except KeyError:
1763 except KeyError:
1764 raise util.Abort(_('invalid revision identifier %s') % rev)
1764 raise util.Abort(_('invalid revision identifier %s') % rev)
1765
1765
1766 @command('debugdate',
1766 @command('debugdate',
1767 [('e', 'extended', None, _('try extended date formats'))],
1767 [('e', 'extended', None, _('try extended date formats'))],
1768 _('[-e] DATE [RANGE]'))
1768 _('[-e] DATE [RANGE]'))
1769 def debugdate(ui, date, range=None, **opts):
1769 def debugdate(ui, date, range=None, **opts):
1770 """parse and display a date"""
1770 """parse and display a date"""
1771 if opts["extended"]:
1771 if opts["extended"]:
1772 d = util.parsedate(date, util.extendeddateformats)
1772 d = util.parsedate(date, util.extendeddateformats)
1773 else:
1773 else:
1774 d = util.parsedate(date)
1774 d = util.parsedate(date)
1775 ui.write("internal: %s %s\n" % d)
1775 ui.write("internal: %s %s\n" % d)
1776 ui.write("standard: %s\n" % util.datestr(d))
1776 ui.write("standard: %s\n" % util.datestr(d))
1777 if range:
1777 if range:
1778 m = util.matchdate(range)
1778 m = util.matchdate(range)
1779 ui.write("match: %s\n" % m(d[0]))
1779 ui.write("match: %s\n" % m(d[0]))
1780
1780
1781 @command('debugdiscovery',
1781 @command('debugdiscovery',
1782 [('', 'old', None, _('use old-style discovery')),
1782 [('', 'old', None, _('use old-style discovery')),
1783 ('', 'nonheads', None,
1783 ('', 'nonheads', None,
1784 _('use old-style discovery with non-heads included')),
1784 _('use old-style discovery with non-heads included')),
1785 ] + remoteopts,
1785 ] + remoteopts,
1786 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1786 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1787 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1787 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1788 """runs the changeset discovery protocol in isolation"""
1788 """runs the changeset discovery protocol in isolation"""
1789 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1789 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1790 opts.get('branch'))
1790 opts.get('branch'))
1791 remote = hg.peer(repo, opts, remoteurl)
1791 remote = hg.peer(repo, opts, remoteurl)
1792 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1792 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1793
1793
1794 # make sure tests are repeatable
1794 # make sure tests are repeatable
1795 random.seed(12323)
1795 random.seed(12323)
1796
1796
1797 def doit(localheads, remoteheads, remote=remote):
1797 def doit(localheads, remoteheads, remote=remote):
1798 if opts.get('old'):
1798 if opts.get('old'):
1799 if localheads:
1799 if localheads:
1800 raise util.Abort('cannot use localheads with old style '
1800 raise util.Abort('cannot use localheads with old style '
1801 'discovery')
1801 'discovery')
1802 if not util.safehasattr(remote, 'branches'):
1802 if not util.safehasattr(remote, 'branches'):
1803 # enable in-client legacy support
1803 # enable in-client legacy support
1804 remote = localrepo.locallegacypeer(remote.local())
1804 remote = localrepo.locallegacypeer(remote.local())
1805 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1805 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1806 force=True)
1806 force=True)
1807 common = set(common)
1807 common = set(common)
1808 if not opts.get('nonheads'):
1808 if not opts.get('nonheads'):
1809 ui.write("unpruned common: %s\n" % " ".join([short(n)
1809 ui.write("unpruned common: %s\n" % " ".join([short(n)
1810 for n in common]))
1810 for n in common]))
1811 dag = dagutil.revlogdag(repo.changelog)
1811 dag = dagutil.revlogdag(repo.changelog)
1812 all = dag.ancestorset(dag.internalizeall(common))
1812 all = dag.ancestorset(dag.internalizeall(common))
1813 common = dag.externalizeall(dag.headsetofconnecteds(all))
1813 common = dag.externalizeall(dag.headsetofconnecteds(all))
1814 else:
1814 else:
1815 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1815 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1816 common = set(common)
1816 common = set(common)
1817 rheads = set(hds)
1817 rheads = set(hds)
1818 lheads = set(repo.heads())
1818 lheads = set(repo.heads())
1819 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1819 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1820 if lheads <= common:
1820 if lheads <= common:
1821 ui.write("local is subset\n")
1821 ui.write("local is subset\n")
1822 elif rheads <= common:
1822 elif rheads <= common:
1823 ui.write("remote is subset\n")
1823 ui.write("remote is subset\n")
1824
1824
1825 serverlogs = opts.get('serverlog')
1825 serverlogs = opts.get('serverlog')
1826 if serverlogs:
1826 if serverlogs:
1827 for filename in serverlogs:
1827 for filename in serverlogs:
1828 logfile = open(filename, 'r')
1828 logfile = open(filename, 'r')
1829 try:
1829 try:
1830 line = logfile.readline()
1830 line = logfile.readline()
1831 while line:
1831 while line:
1832 parts = line.strip().split(';')
1832 parts = line.strip().split(';')
1833 op = parts[1]
1833 op = parts[1]
1834 if op == 'cg':
1834 if op == 'cg':
1835 pass
1835 pass
1836 elif op == 'cgss':
1836 elif op == 'cgss':
1837 doit(parts[2].split(' '), parts[3].split(' '))
1837 doit(parts[2].split(' '), parts[3].split(' '))
1838 elif op == 'unb':
1838 elif op == 'unb':
1839 doit(parts[3].split(' '), parts[2].split(' '))
1839 doit(parts[3].split(' '), parts[2].split(' '))
1840 line = logfile.readline()
1840 line = logfile.readline()
1841 finally:
1841 finally:
1842 logfile.close()
1842 logfile.close()
1843
1843
1844 else:
1844 else:
1845 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1845 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1846 opts.get('remote_head'))
1846 opts.get('remote_head'))
1847 localrevs = opts.get('local_head')
1847 localrevs = opts.get('local_head')
1848 doit(localrevs, remoterevs)
1848 doit(localrevs, remoterevs)
1849
1849
1850 @command('debugfileset', [], ('REVSPEC'))
1850 @command('debugfileset', [], ('REVSPEC'))
1851 def debugfileset(ui, repo, expr):
1851 def debugfileset(ui, repo, expr):
1852 '''parse and apply a fileset specification'''
1852 '''parse and apply a fileset specification'''
1853 if ui.verbose:
1853 if ui.verbose:
1854 tree = fileset.parse(expr)[0]
1854 tree = fileset.parse(expr)[0]
1855 ui.note(tree, "\n")
1855 ui.note(tree, "\n")
1856
1856
1857 for f in fileset.getfileset(repo[None], expr):
1857 for f in fileset.getfileset(repo[None], expr):
1858 ui.write("%s\n" % f)
1858 ui.write("%s\n" % f)
1859
1859
1860 @command('debugfsinfo', [], _('[PATH]'))
1860 @command('debugfsinfo', [], _('[PATH]'))
1861 def debugfsinfo(ui, path = "."):
1861 def debugfsinfo(ui, path = "."):
1862 """show information detected about current filesystem"""
1862 """show information detected about current filesystem"""
1863 util.writefile('.debugfsinfo', '')
1863 util.writefile('.debugfsinfo', '')
1864 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1864 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1865 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1865 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1866 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1866 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1867 and 'yes' or 'no'))
1867 and 'yes' or 'no'))
1868 os.unlink('.debugfsinfo')
1868 os.unlink('.debugfsinfo')
1869
1869
1870 @command('debuggetbundle',
1870 @command('debuggetbundle',
1871 [('H', 'head', [], _('id of head node'), _('ID')),
1871 [('H', 'head', [], _('id of head node'), _('ID')),
1872 ('C', 'common', [], _('id of common node'), _('ID')),
1872 ('C', 'common', [], _('id of common node'), _('ID')),
1873 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1873 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1874 _('REPO FILE [-H|-C ID]...'))
1874 _('REPO FILE [-H|-C ID]...'))
1875 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1875 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1876 """retrieves a bundle from a repo
1876 """retrieves a bundle from a repo
1877
1877
1878 Every ID must be a full-length hex node id string. Saves the bundle to the
1878 Every ID must be a full-length hex node id string. Saves the bundle to the
1879 given file.
1879 given file.
1880 """
1880 """
1881 repo = hg.peer(ui, opts, repopath)
1881 repo = hg.peer(ui, opts, repopath)
1882 if not repo.capable('getbundle'):
1882 if not repo.capable('getbundle'):
1883 raise util.Abort("getbundle() not supported by target repository")
1883 raise util.Abort("getbundle() not supported by target repository")
1884 args = {}
1884 args = {}
1885 if common:
1885 if common:
1886 args['common'] = [bin(s) for s in common]
1886 args['common'] = [bin(s) for s in common]
1887 if head:
1887 if head:
1888 args['heads'] = [bin(s) for s in head]
1888 args['heads'] = [bin(s) for s in head]
1889 bundle = repo.getbundle('debug', **args)
1889 bundle = repo.getbundle('debug', **args)
1890
1890
1891 bundletype = opts.get('type', 'bzip2').lower()
1891 bundletype = opts.get('type', 'bzip2').lower()
1892 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1892 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1893 bundletype = btypes.get(bundletype)
1893 bundletype = btypes.get(bundletype)
1894 if bundletype not in changegroup.bundletypes:
1894 if bundletype not in changegroup.bundletypes:
1895 raise util.Abort(_('unknown bundle type specified with --type'))
1895 raise util.Abort(_('unknown bundle type specified with --type'))
1896 changegroup.writebundle(bundle, bundlepath, bundletype)
1896 changegroup.writebundle(bundle, bundlepath, bundletype)
1897
1897
1898 @command('debugignore', [], '')
1898 @command('debugignore', [], '')
1899 def debugignore(ui, repo, *values, **opts):
1899 def debugignore(ui, repo, *values, **opts):
1900 """display the combined ignore pattern"""
1900 """display the combined ignore pattern"""
1901 ignore = repo.dirstate._ignore
1901 ignore = repo.dirstate._ignore
1902 includepat = getattr(ignore, 'includepat', None)
1902 includepat = getattr(ignore, 'includepat', None)
1903 if includepat is not None:
1903 if includepat is not None:
1904 ui.write("%s\n" % includepat)
1904 ui.write("%s\n" % includepat)
1905 else:
1905 else:
1906 raise util.Abort(_("no ignore patterns found"))
1906 raise util.Abort(_("no ignore patterns found"))
1907
1907
1908 @command('debugindex',
1908 @command('debugindex',
1909 [('c', 'changelog', False, _('open changelog')),
1909 [('c', 'changelog', False, _('open changelog')),
1910 ('m', 'manifest', False, _('open manifest')),
1910 ('m', 'manifest', False, _('open manifest')),
1911 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1911 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1912 _('[-f FORMAT] -c|-m|FILE'))
1912 _('[-f FORMAT] -c|-m|FILE'))
1913 def debugindex(ui, repo, file_ = None, **opts):
1913 def debugindex(ui, repo, file_ = None, **opts):
1914 """dump the contents of an index file"""
1914 """dump the contents of an index file"""
1915 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1915 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1916 format = opts.get('format', 0)
1916 format = opts.get('format', 0)
1917 if format not in (0, 1):
1917 if format not in (0, 1):
1918 raise util.Abort(_("unknown format %d") % format)
1918 raise util.Abort(_("unknown format %d") % format)
1919
1919
1920 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1920 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1921 if generaldelta:
1921 if generaldelta:
1922 basehdr = ' delta'
1922 basehdr = ' delta'
1923 else:
1923 else:
1924 basehdr = ' base'
1924 basehdr = ' base'
1925
1925
1926 if format == 0:
1926 if format == 0:
1927 ui.write(" rev offset length " + basehdr + " linkrev"
1927 ui.write(" rev offset length " + basehdr + " linkrev"
1928 " nodeid p1 p2\n")
1928 " nodeid p1 p2\n")
1929 elif format == 1:
1929 elif format == 1:
1930 ui.write(" rev flag offset length"
1930 ui.write(" rev flag offset length"
1931 " size " + basehdr + " link p1 p2"
1931 " size " + basehdr + " link p1 p2"
1932 " nodeid\n")
1932 " nodeid\n")
1933
1933
1934 for i in r:
1934 for i in r:
1935 node = r.node(i)
1935 node = r.node(i)
1936 if generaldelta:
1936 if generaldelta:
1937 base = r.deltaparent(i)
1937 base = r.deltaparent(i)
1938 else:
1938 else:
1939 base = r.chainbase(i)
1939 base = r.chainbase(i)
1940 if format == 0:
1940 if format == 0:
1941 try:
1941 try:
1942 pp = r.parents(node)
1942 pp = r.parents(node)
1943 except Exception:
1943 except Exception:
1944 pp = [nullid, nullid]
1944 pp = [nullid, nullid]
1945 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1945 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1946 i, r.start(i), r.length(i), base, r.linkrev(i),
1946 i, r.start(i), r.length(i), base, r.linkrev(i),
1947 short(node), short(pp[0]), short(pp[1])))
1947 short(node), short(pp[0]), short(pp[1])))
1948 elif format == 1:
1948 elif format == 1:
1949 pr = r.parentrevs(i)
1949 pr = r.parentrevs(i)
1950 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1950 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1951 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1951 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1952 base, r.linkrev(i), pr[0], pr[1], short(node)))
1952 base, r.linkrev(i), pr[0], pr[1], short(node)))
1953
1953
1954 @command('debugindexdot', [], _('FILE'))
1954 @command('debugindexdot', [], _('FILE'))
1955 def debugindexdot(ui, repo, file_):
1955 def debugindexdot(ui, repo, file_):
1956 """dump an index DAG as a graphviz dot file"""
1956 """dump an index DAG as a graphviz dot file"""
1957 r = None
1957 r = None
1958 if repo:
1958 if repo:
1959 filelog = repo.file(file_)
1959 filelog = repo.file(file_)
1960 if len(filelog):
1960 if len(filelog):
1961 r = filelog
1961 r = filelog
1962 if not r:
1962 if not r:
1963 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1963 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1964 ui.write("digraph G {\n")
1964 ui.write("digraph G {\n")
1965 for i in r:
1965 for i in r:
1966 node = r.node(i)
1966 node = r.node(i)
1967 pp = r.parents(node)
1967 pp = r.parents(node)
1968 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1968 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1969 if pp[1] != nullid:
1969 if pp[1] != nullid:
1970 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1970 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1971 ui.write("}\n")
1971 ui.write("}\n")
1972
1972
1973 @command('debuginstall', [], '')
1973 @command('debuginstall', [], '')
1974 def debuginstall(ui):
1974 def debuginstall(ui):
1975 '''test Mercurial installation
1975 '''test Mercurial installation
1976
1976
1977 Returns 0 on success.
1977 Returns 0 on success.
1978 '''
1978 '''
1979
1979
1980 def writetemp(contents):
1980 def writetemp(contents):
1981 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1981 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1982 f = os.fdopen(fd, "wb")
1982 f = os.fdopen(fd, "wb")
1983 f.write(contents)
1983 f.write(contents)
1984 f.close()
1984 f.close()
1985 return name
1985 return name
1986
1986
1987 problems = 0
1987 problems = 0
1988
1988
1989 # encoding
1989 # encoding
1990 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1990 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1991 try:
1991 try:
1992 encoding.fromlocal("test")
1992 encoding.fromlocal("test")
1993 except util.Abort, inst:
1993 except util.Abort, inst:
1994 ui.write(" %s\n" % inst)
1994 ui.write(" %s\n" % inst)
1995 ui.write(_(" (check that your locale is properly set)\n"))
1995 ui.write(_(" (check that your locale is properly set)\n"))
1996 problems += 1
1996 problems += 1
1997
1997
1998 # compiled modules
1998 # compiled modules
1999 ui.status(_("checking installed modules (%s)...\n")
1999 ui.status(_("checking installed modules (%s)...\n")
2000 % os.path.dirname(__file__))
2000 % os.path.dirname(__file__))
2001 try:
2001 try:
2002 import bdiff, mpatch, base85, osutil
2002 import bdiff, mpatch, base85, osutil
2003 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2003 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2004 except Exception, inst:
2004 except Exception, inst:
2005 ui.write(" %s\n" % inst)
2005 ui.write(" %s\n" % inst)
2006 ui.write(_(" One or more extensions could not be found"))
2006 ui.write(_(" One or more extensions could not be found"))
2007 ui.write(_(" (check that you compiled the extensions)\n"))
2007 ui.write(_(" (check that you compiled the extensions)\n"))
2008 problems += 1
2008 problems += 1
2009
2009
2010 # templates
2010 # templates
2011 import templater
2011 import templater
2012 p = templater.templatepath()
2012 p = templater.templatepath()
2013 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2013 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2014 try:
2014 try:
2015 templater.templater(templater.templatepath("map-cmdline.default"))
2015 templater.templater(templater.templatepath("map-cmdline.default"))
2016 except Exception, inst:
2016 except Exception, inst:
2017 ui.write(" %s\n" % inst)
2017 ui.write(" %s\n" % inst)
2018 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2018 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2019 problems += 1
2019 problems += 1
2020
2020
2021 # editor
2021 # editor
2022 ui.status(_("checking commit editor...\n"))
2022 ui.status(_("checking commit editor...\n"))
2023 editor = ui.geteditor()
2023 editor = ui.geteditor()
2024 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2024 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2025 if not cmdpath:
2025 if not cmdpath:
2026 if editor == 'vi':
2026 if editor == 'vi':
2027 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2027 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2028 ui.write(_(" (specify a commit editor in your configuration"
2028 ui.write(_(" (specify a commit editor in your configuration"
2029 " file)\n"))
2029 " file)\n"))
2030 else:
2030 else:
2031 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2031 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2032 ui.write(_(" (specify a commit editor in your configuration"
2032 ui.write(_(" (specify a commit editor in your configuration"
2033 " file)\n"))
2033 " file)\n"))
2034 problems += 1
2034 problems += 1
2035
2035
2036 # check username
2036 # check username
2037 ui.status(_("checking username...\n"))
2037 ui.status(_("checking username...\n"))
2038 try:
2038 try:
2039 ui.username()
2039 ui.username()
2040 except util.Abort, e:
2040 except util.Abort, e:
2041 ui.write(" %s\n" % e)
2041 ui.write(" %s\n" % e)
2042 ui.write(_(" (specify a username in your configuration file)\n"))
2042 ui.write(_(" (specify a username in your configuration file)\n"))
2043 problems += 1
2043 problems += 1
2044
2044
2045 if not problems:
2045 if not problems:
2046 ui.status(_("no problems detected\n"))
2046 ui.status(_("no problems detected\n"))
2047 else:
2047 else:
2048 ui.write(_("%s problems detected,"
2048 ui.write(_("%s problems detected,"
2049 " please check your install!\n") % problems)
2049 " please check your install!\n") % problems)
2050
2050
2051 return problems
2051 return problems
2052
2052
2053 @command('debugknown', [], _('REPO ID...'))
2053 @command('debugknown', [], _('REPO ID...'))
2054 def debugknown(ui, repopath, *ids, **opts):
2054 def debugknown(ui, repopath, *ids, **opts):
2055 """test whether node ids are known to a repo
2055 """test whether node ids are known to a repo
2056
2056
2057 Every ID must be a full-length hex node id string. Returns a list of 0s
2057 Every ID must be a full-length hex node id string. Returns a list of 0s
2058 and 1s indicating unknown/known.
2058 and 1s indicating unknown/known.
2059 """
2059 """
2060 repo = hg.peer(ui, opts, repopath)
2060 repo = hg.peer(ui, opts, repopath)
2061 if not repo.capable('known'):
2061 if not repo.capable('known'):
2062 raise util.Abort("known() not supported by target repository")
2062 raise util.Abort("known() not supported by target repository")
2063 flags = repo.known([bin(s) for s in ids])
2063 flags = repo.known([bin(s) for s in ids])
2064 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2064 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2065
2065
2066 @command('debugobsolete', [] + commitopts2,
2066 @command('debugobsolete', [] + commitopts2,
2067 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2067 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2068 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2068 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2069 """create arbitrary obsolete marker"""
2069 """create arbitrary obsolete marker"""
2070 def parsenodeid(s):
2071 try:
2072 # We do not use revsingle/revrange functions here to accept
2073 # arbitrary node identifiers, possibly not present in the
2074 # local repository.
2075 n = bin(s)
2076 if len(n) != len(nullid):
2077 raise TypeError()
2078 return n
2079 except TypeError:
2080 raise util.Abort('changeset references must be full hexadecimal '
2081 'node identifiers')
2082
2070 if precursor is not None:
2083 if precursor is not None:
2071 metadata = {}
2084 metadata = {}
2072 if 'date' in opts:
2085 if 'date' in opts:
2073 metadata['date'] = opts['date']
2086 metadata['date'] = opts['date']
2074 metadata['user'] = opts['user'] or ui.username()
2087 metadata['user'] = opts['user'] or ui.username()
2075 succs = tuple(bin(succ) for succ in successors)
2088 succs = tuple(parsenodeid(succ) for succ in successors)
2076 l = repo.lock()
2089 l = repo.lock()
2077 try:
2090 try:
2078 tr = repo.transaction('debugobsolete')
2091 tr = repo.transaction('debugobsolete')
2079 try:
2092 try:
2080 repo.obsstore.create(tr, bin(precursor), succs, 0, metadata)
2093 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2094 metadata)
2081 tr.close()
2095 tr.close()
2082 finally:
2096 finally:
2083 tr.release()
2097 tr.release()
2084 finally:
2098 finally:
2085 l.release()
2099 l.release()
2086 else:
2100 else:
2087 for m in obsolete.allmarkers(repo):
2101 for m in obsolete.allmarkers(repo):
2088 ui.write(hex(m.precnode()))
2102 ui.write(hex(m.precnode()))
2089 for repl in m.succnodes():
2103 for repl in m.succnodes():
2090 ui.write(' ')
2104 ui.write(' ')
2091 ui.write(hex(repl))
2105 ui.write(hex(repl))
2092 ui.write(' %X ' % m._data[2])
2106 ui.write(' %X ' % m._data[2])
2093 ui.write(m.metadata())
2107 ui.write(m.metadata())
2094 ui.write('\n')
2108 ui.write('\n')
2095
2109
2096 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2110 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2097 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2111 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2098 '''access the pushkey key/value protocol
2112 '''access the pushkey key/value protocol
2099
2113
2100 With two args, list the keys in the given namespace.
2114 With two args, list the keys in the given namespace.
2101
2115
2102 With five args, set a key to new if it currently is set to old.
2116 With five args, set a key to new if it currently is set to old.
2103 Reports success or failure.
2117 Reports success or failure.
2104 '''
2118 '''
2105
2119
2106 target = hg.peer(ui, {}, repopath)
2120 target = hg.peer(ui, {}, repopath)
2107 if keyinfo:
2121 if keyinfo:
2108 key, old, new = keyinfo
2122 key, old, new = keyinfo
2109 r = target.pushkey(namespace, key, old, new)
2123 r = target.pushkey(namespace, key, old, new)
2110 ui.status(str(r) + '\n')
2124 ui.status(str(r) + '\n')
2111 return not r
2125 return not r
2112 else:
2126 else:
2113 for k, v in target.listkeys(namespace).iteritems():
2127 for k, v in target.listkeys(namespace).iteritems():
2114 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2128 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2115 v.encode('string-escape')))
2129 v.encode('string-escape')))
2116
2130
2117 @command('debugpvec', [], _('A B'))
2131 @command('debugpvec', [], _('A B'))
2118 def debugpvec(ui, repo, a, b=None):
2132 def debugpvec(ui, repo, a, b=None):
2119 ca = scmutil.revsingle(repo, a)
2133 ca = scmutil.revsingle(repo, a)
2120 cb = scmutil.revsingle(repo, b)
2134 cb = scmutil.revsingle(repo, b)
2121 pa = pvec.ctxpvec(ca)
2135 pa = pvec.ctxpvec(ca)
2122 pb = pvec.ctxpvec(cb)
2136 pb = pvec.ctxpvec(cb)
2123 if pa == pb:
2137 if pa == pb:
2124 rel = "="
2138 rel = "="
2125 elif pa > pb:
2139 elif pa > pb:
2126 rel = ">"
2140 rel = ">"
2127 elif pa < pb:
2141 elif pa < pb:
2128 rel = "<"
2142 rel = "<"
2129 elif pa | pb:
2143 elif pa | pb:
2130 rel = "|"
2144 rel = "|"
2131 ui.write(_("a: %s\n") % pa)
2145 ui.write(_("a: %s\n") % pa)
2132 ui.write(_("b: %s\n") % pb)
2146 ui.write(_("b: %s\n") % pb)
2133 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2147 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2134 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2148 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2135 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2149 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2136 pa.distance(pb), rel))
2150 pa.distance(pb), rel))
2137
2151
2138 @command('debugrebuildstate',
2152 @command('debugrebuildstate',
2139 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2153 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2140 _('[-r REV] [REV]'))
2154 _('[-r REV] [REV]'))
2141 def debugrebuildstate(ui, repo, rev="tip"):
2155 def debugrebuildstate(ui, repo, rev="tip"):
2142 """rebuild the dirstate as it would look like for the given revision"""
2156 """rebuild the dirstate as it would look like for the given revision"""
2143 ctx = scmutil.revsingle(repo, rev)
2157 ctx = scmutil.revsingle(repo, rev)
2144 wlock = repo.wlock()
2158 wlock = repo.wlock()
2145 try:
2159 try:
2146 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2160 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2147 finally:
2161 finally:
2148 wlock.release()
2162 wlock.release()
2149
2163
2150 @command('debugrename',
2164 @command('debugrename',
2151 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2165 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2152 _('[-r REV] FILE'))
2166 _('[-r REV] FILE'))
2153 def debugrename(ui, repo, file1, *pats, **opts):
2167 def debugrename(ui, repo, file1, *pats, **opts):
2154 """dump rename information"""
2168 """dump rename information"""
2155
2169
2156 ctx = scmutil.revsingle(repo, opts.get('rev'))
2170 ctx = scmutil.revsingle(repo, opts.get('rev'))
2157 m = scmutil.match(ctx, (file1,) + pats, opts)
2171 m = scmutil.match(ctx, (file1,) + pats, opts)
2158 for abs in ctx.walk(m):
2172 for abs in ctx.walk(m):
2159 fctx = ctx[abs]
2173 fctx = ctx[abs]
2160 o = fctx.filelog().renamed(fctx.filenode())
2174 o = fctx.filelog().renamed(fctx.filenode())
2161 rel = m.rel(abs)
2175 rel = m.rel(abs)
2162 if o:
2176 if o:
2163 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2177 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2164 else:
2178 else:
2165 ui.write(_("%s not renamed\n") % rel)
2179 ui.write(_("%s not renamed\n") % rel)
2166
2180
2167 @command('debugrevlog',
2181 @command('debugrevlog',
2168 [('c', 'changelog', False, _('open changelog')),
2182 [('c', 'changelog', False, _('open changelog')),
2169 ('m', 'manifest', False, _('open manifest')),
2183 ('m', 'manifest', False, _('open manifest')),
2170 ('d', 'dump', False, _('dump index data'))],
2184 ('d', 'dump', False, _('dump index data'))],
2171 _('-c|-m|FILE'))
2185 _('-c|-m|FILE'))
2172 def debugrevlog(ui, repo, file_ = None, **opts):
2186 def debugrevlog(ui, repo, file_ = None, **opts):
2173 """show data and statistics about a revlog"""
2187 """show data and statistics about a revlog"""
2174 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2188 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2175
2189
2176 if opts.get("dump"):
2190 if opts.get("dump"):
2177 numrevs = len(r)
2191 numrevs = len(r)
2178 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2192 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2179 " rawsize totalsize compression heads\n")
2193 " rawsize totalsize compression heads\n")
2180 ts = 0
2194 ts = 0
2181 heads = set()
2195 heads = set()
2182 for rev in xrange(numrevs):
2196 for rev in xrange(numrevs):
2183 dbase = r.deltaparent(rev)
2197 dbase = r.deltaparent(rev)
2184 if dbase == -1:
2198 if dbase == -1:
2185 dbase = rev
2199 dbase = rev
2186 cbase = r.chainbase(rev)
2200 cbase = r.chainbase(rev)
2187 p1, p2 = r.parentrevs(rev)
2201 p1, p2 = r.parentrevs(rev)
2188 rs = r.rawsize(rev)
2202 rs = r.rawsize(rev)
2189 ts = ts + rs
2203 ts = ts + rs
2190 heads -= set(r.parentrevs(rev))
2204 heads -= set(r.parentrevs(rev))
2191 heads.add(rev)
2205 heads.add(rev)
2192 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2206 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2193 (rev, p1, p2, r.start(rev), r.end(rev),
2207 (rev, p1, p2, r.start(rev), r.end(rev),
2194 r.start(dbase), r.start(cbase),
2208 r.start(dbase), r.start(cbase),
2195 r.start(p1), r.start(p2),
2209 r.start(p1), r.start(p2),
2196 rs, ts, ts / r.end(rev), len(heads)))
2210 rs, ts, ts / r.end(rev), len(heads)))
2197 return 0
2211 return 0
2198
2212
2199 v = r.version
2213 v = r.version
2200 format = v & 0xFFFF
2214 format = v & 0xFFFF
2201 flags = []
2215 flags = []
2202 gdelta = False
2216 gdelta = False
2203 if v & revlog.REVLOGNGINLINEDATA:
2217 if v & revlog.REVLOGNGINLINEDATA:
2204 flags.append('inline')
2218 flags.append('inline')
2205 if v & revlog.REVLOGGENERALDELTA:
2219 if v & revlog.REVLOGGENERALDELTA:
2206 gdelta = True
2220 gdelta = True
2207 flags.append('generaldelta')
2221 flags.append('generaldelta')
2208 if not flags:
2222 if not flags:
2209 flags = ['(none)']
2223 flags = ['(none)']
2210
2224
2211 nummerges = 0
2225 nummerges = 0
2212 numfull = 0
2226 numfull = 0
2213 numprev = 0
2227 numprev = 0
2214 nump1 = 0
2228 nump1 = 0
2215 nump2 = 0
2229 nump2 = 0
2216 numother = 0
2230 numother = 0
2217 nump1prev = 0
2231 nump1prev = 0
2218 nump2prev = 0
2232 nump2prev = 0
2219 chainlengths = []
2233 chainlengths = []
2220
2234
2221 datasize = [None, 0, 0L]
2235 datasize = [None, 0, 0L]
2222 fullsize = [None, 0, 0L]
2236 fullsize = [None, 0, 0L]
2223 deltasize = [None, 0, 0L]
2237 deltasize = [None, 0, 0L]
2224
2238
2225 def addsize(size, l):
2239 def addsize(size, l):
2226 if l[0] is None or size < l[0]:
2240 if l[0] is None or size < l[0]:
2227 l[0] = size
2241 l[0] = size
2228 if size > l[1]:
2242 if size > l[1]:
2229 l[1] = size
2243 l[1] = size
2230 l[2] += size
2244 l[2] += size
2231
2245
2232 numrevs = len(r)
2246 numrevs = len(r)
2233 for rev in xrange(numrevs):
2247 for rev in xrange(numrevs):
2234 p1, p2 = r.parentrevs(rev)
2248 p1, p2 = r.parentrevs(rev)
2235 delta = r.deltaparent(rev)
2249 delta = r.deltaparent(rev)
2236 if format > 0:
2250 if format > 0:
2237 addsize(r.rawsize(rev), datasize)
2251 addsize(r.rawsize(rev), datasize)
2238 if p2 != nullrev:
2252 if p2 != nullrev:
2239 nummerges += 1
2253 nummerges += 1
2240 size = r.length(rev)
2254 size = r.length(rev)
2241 if delta == nullrev:
2255 if delta == nullrev:
2242 chainlengths.append(0)
2256 chainlengths.append(0)
2243 numfull += 1
2257 numfull += 1
2244 addsize(size, fullsize)
2258 addsize(size, fullsize)
2245 else:
2259 else:
2246 chainlengths.append(chainlengths[delta] + 1)
2260 chainlengths.append(chainlengths[delta] + 1)
2247 addsize(size, deltasize)
2261 addsize(size, deltasize)
2248 if delta == rev - 1:
2262 if delta == rev - 1:
2249 numprev += 1
2263 numprev += 1
2250 if delta == p1:
2264 if delta == p1:
2251 nump1prev += 1
2265 nump1prev += 1
2252 elif delta == p2:
2266 elif delta == p2:
2253 nump2prev += 1
2267 nump2prev += 1
2254 elif delta == p1:
2268 elif delta == p1:
2255 nump1 += 1
2269 nump1 += 1
2256 elif delta == p2:
2270 elif delta == p2:
2257 nump2 += 1
2271 nump2 += 1
2258 elif delta != nullrev:
2272 elif delta != nullrev:
2259 numother += 1
2273 numother += 1
2260
2274
2261 # Adjust size min value for empty cases
2275 # Adjust size min value for empty cases
2262 for size in (datasize, fullsize, deltasize):
2276 for size in (datasize, fullsize, deltasize):
2263 if size[0] is None:
2277 if size[0] is None:
2264 size[0] = 0
2278 size[0] = 0
2265
2279
2266 numdeltas = numrevs - numfull
2280 numdeltas = numrevs - numfull
2267 numoprev = numprev - nump1prev - nump2prev
2281 numoprev = numprev - nump1prev - nump2prev
2268 totalrawsize = datasize[2]
2282 totalrawsize = datasize[2]
2269 datasize[2] /= numrevs
2283 datasize[2] /= numrevs
2270 fulltotal = fullsize[2]
2284 fulltotal = fullsize[2]
2271 fullsize[2] /= numfull
2285 fullsize[2] /= numfull
2272 deltatotal = deltasize[2]
2286 deltatotal = deltasize[2]
2273 if numrevs - numfull > 0:
2287 if numrevs - numfull > 0:
2274 deltasize[2] /= numrevs - numfull
2288 deltasize[2] /= numrevs - numfull
2275 totalsize = fulltotal + deltatotal
2289 totalsize = fulltotal + deltatotal
2276 avgchainlen = sum(chainlengths) / numrevs
2290 avgchainlen = sum(chainlengths) / numrevs
2277 compratio = totalrawsize / totalsize
2291 compratio = totalrawsize / totalsize
2278
2292
2279 basedfmtstr = '%%%dd\n'
2293 basedfmtstr = '%%%dd\n'
2280 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2294 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2281
2295
2282 def dfmtstr(max):
2296 def dfmtstr(max):
2283 return basedfmtstr % len(str(max))
2297 return basedfmtstr % len(str(max))
2284 def pcfmtstr(max, padding=0):
2298 def pcfmtstr(max, padding=0):
2285 return basepcfmtstr % (len(str(max)), ' ' * padding)
2299 return basepcfmtstr % (len(str(max)), ' ' * padding)
2286
2300
2287 def pcfmt(value, total):
2301 def pcfmt(value, total):
2288 return (value, 100 * float(value) / total)
2302 return (value, 100 * float(value) / total)
2289
2303
2290 ui.write('format : %d\n' % format)
2304 ui.write('format : %d\n' % format)
2291 ui.write('flags : %s\n' % ', '.join(flags))
2305 ui.write('flags : %s\n' % ', '.join(flags))
2292
2306
2293 ui.write('\n')
2307 ui.write('\n')
2294 fmt = pcfmtstr(totalsize)
2308 fmt = pcfmtstr(totalsize)
2295 fmt2 = dfmtstr(totalsize)
2309 fmt2 = dfmtstr(totalsize)
2296 ui.write('revisions : ' + fmt2 % numrevs)
2310 ui.write('revisions : ' + fmt2 % numrevs)
2297 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2311 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2298 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2312 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2299 ui.write('revisions : ' + fmt2 % numrevs)
2313 ui.write('revisions : ' + fmt2 % numrevs)
2300 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2314 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2301 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2315 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2302 ui.write('revision size : ' + fmt2 % totalsize)
2316 ui.write('revision size : ' + fmt2 % totalsize)
2303 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2317 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2304 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2318 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2305
2319
2306 ui.write('\n')
2320 ui.write('\n')
2307 fmt = dfmtstr(max(avgchainlen, compratio))
2321 fmt = dfmtstr(max(avgchainlen, compratio))
2308 ui.write('avg chain length : ' + fmt % avgchainlen)
2322 ui.write('avg chain length : ' + fmt % avgchainlen)
2309 ui.write('compression ratio : ' + fmt % compratio)
2323 ui.write('compression ratio : ' + fmt % compratio)
2310
2324
2311 if format > 0:
2325 if format > 0:
2312 ui.write('\n')
2326 ui.write('\n')
2313 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2327 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2314 % tuple(datasize))
2328 % tuple(datasize))
2315 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2329 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2316 % tuple(fullsize))
2330 % tuple(fullsize))
2317 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2331 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2318 % tuple(deltasize))
2332 % tuple(deltasize))
2319
2333
2320 if numdeltas > 0:
2334 if numdeltas > 0:
2321 ui.write('\n')
2335 ui.write('\n')
2322 fmt = pcfmtstr(numdeltas)
2336 fmt = pcfmtstr(numdeltas)
2323 fmt2 = pcfmtstr(numdeltas, 4)
2337 fmt2 = pcfmtstr(numdeltas, 4)
2324 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2338 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2325 if numprev > 0:
2339 if numprev > 0:
2326 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2340 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2327 numprev))
2341 numprev))
2328 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2342 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2329 numprev))
2343 numprev))
2330 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2344 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2331 numprev))
2345 numprev))
2332 if gdelta:
2346 if gdelta:
2333 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2347 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2334 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2348 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2335 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2349 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2336 numdeltas))
2350 numdeltas))
2337
2351
2338 @command('debugrevspec', [], ('REVSPEC'))
2352 @command('debugrevspec', [], ('REVSPEC'))
2339 def debugrevspec(ui, repo, expr):
2353 def debugrevspec(ui, repo, expr):
2340 """parse and apply a revision specification
2354 """parse and apply a revision specification
2341
2355
2342 Use --verbose to print the parsed tree before and after aliases
2356 Use --verbose to print the parsed tree before and after aliases
2343 expansion.
2357 expansion.
2344 """
2358 """
2345 if ui.verbose:
2359 if ui.verbose:
2346 tree = revset.parse(expr)[0]
2360 tree = revset.parse(expr)[0]
2347 ui.note(revset.prettyformat(tree), "\n")
2361 ui.note(revset.prettyformat(tree), "\n")
2348 newtree = revset.findaliases(ui, tree)
2362 newtree = revset.findaliases(ui, tree)
2349 if newtree != tree:
2363 if newtree != tree:
2350 ui.note(revset.prettyformat(newtree), "\n")
2364 ui.note(revset.prettyformat(newtree), "\n")
2351 func = revset.match(ui, expr)
2365 func = revset.match(ui, expr)
2352 for c in func(repo, range(len(repo))):
2366 for c in func(repo, range(len(repo))):
2353 ui.write("%s\n" % c)
2367 ui.write("%s\n" % c)
2354
2368
2355 @command('debugsetparents', [], _('REV1 [REV2]'))
2369 @command('debugsetparents', [], _('REV1 [REV2]'))
2356 def debugsetparents(ui, repo, rev1, rev2=None):
2370 def debugsetparents(ui, repo, rev1, rev2=None):
2357 """manually set the parents of the current working directory
2371 """manually set the parents of the current working directory
2358
2372
2359 This is useful for writing repository conversion tools, but should
2373 This is useful for writing repository conversion tools, but should
2360 be used with care.
2374 be used with care.
2361
2375
2362 Returns 0 on success.
2376 Returns 0 on success.
2363 """
2377 """
2364
2378
2365 r1 = scmutil.revsingle(repo, rev1).node()
2379 r1 = scmutil.revsingle(repo, rev1).node()
2366 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2380 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2367
2381
2368 wlock = repo.wlock()
2382 wlock = repo.wlock()
2369 try:
2383 try:
2370 repo.setparents(r1, r2)
2384 repo.setparents(r1, r2)
2371 finally:
2385 finally:
2372 wlock.release()
2386 wlock.release()
2373
2387
2374 @command('debugstate',
2388 @command('debugstate',
2375 [('', 'nodates', None, _('do not display the saved mtime')),
2389 [('', 'nodates', None, _('do not display the saved mtime')),
2376 ('', 'datesort', None, _('sort by saved mtime'))],
2390 ('', 'datesort', None, _('sort by saved mtime'))],
2377 _('[OPTION]...'))
2391 _('[OPTION]...'))
2378 def debugstate(ui, repo, nodates=None, datesort=None):
2392 def debugstate(ui, repo, nodates=None, datesort=None):
2379 """show the contents of the current dirstate"""
2393 """show the contents of the current dirstate"""
2380 timestr = ""
2394 timestr = ""
2381 showdate = not nodates
2395 showdate = not nodates
2382 if datesort:
2396 if datesort:
2383 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2397 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2384 else:
2398 else:
2385 keyfunc = None # sort by filename
2399 keyfunc = None # sort by filename
2386 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2400 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2387 if showdate:
2401 if showdate:
2388 if ent[3] == -1:
2402 if ent[3] == -1:
2389 # Pad or slice to locale representation
2403 # Pad or slice to locale representation
2390 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2404 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2391 time.localtime(0)))
2405 time.localtime(0)))
2392 timestr = 'unset'
2406 timestr = 'unset'
2393 timestr = (timestr[:locale_len] +
2407 timestr = (timestr[:locale_len] +
2394 ' ' * (locale_len - len(timestr)))
2408 ' ' * (locale_len - len(timestr)))
2395 else:
2409 else:
2396 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2410 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2397 time.localtime(ent[3]))
2411 time.localtime(ent[3]))
2398 if ent[1] & 020000:
2412 if ent[1] & 020000:
2399 mode = 'lnk'
2413 mode = 'lnk'
2400 else:
2414 else:
2401 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2415 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2402 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2416 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2403 for f in repo.dirstate.copies():
2417 for f in repo.dirstate.copies():
2404 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2418 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2405
2419
2406 @command('debugsub',
2420 @command('debugsub',
2407 [('r', 'rev', '',
2421 [('r', 'rev', '',
2408 _('revision to check'), _('REV'))],
2422 _('revision to check'), _('REV'))],
2409 _('[-r REV] [REV]'))
2423 _('[-r REV] [REV]'))
2410 def debugsub(ui, repo, rev=None):
2424 def debugsub(ui, repo, rev=None):
2411 ctx = scmutil.revsingle(repo, rev, None)
2425 ctx = scmutil.revsingle(repo, rev, None)
2412 for k, v in sorted(ctx.substate.items()):
2426 for k, v in sorted(ctx.substate.items()):
2413 ui.write('path %s\n' % k)
2427 ui.write('path %s\n' % k)
2414 ui.write(' source %s\n' % v[0])
2428 ui.write(' source %s\n' % v[0])
2415 ui.write(' revision %s\n' % v[1])
2429 ui.write(' revision %s\n' % v[1])
2416
2430
2417 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2431 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2418 def debugwalk(ui, repo, *pats, **opts):
2432 def debugwalk(ui, repo, *pats, **opts):
2419 """show how files match on given patterns"""
2433 """show how files match on given patterns"""
2420 m = scmutil.match(repo[None], pats, opts)
2434 m = scmutil.match(repo[None], pats, opts)
2421 items = list(repo.walk(m))
2435 items = list(repo.walk(m))
2422 if not items:
2436 if not items:
2423 return
2437 return
2424 f = lambda fn: fn
2438 f = lambda fn: fn
2425 if ui.configbool('ui', 'slash') and os.sep != '/':
2439 if ui.configbool('ui', 'slash') and os.sep != '/':
2426 f = lambda fn: util.normpath(fn)
2440 f = lambda fn: util.normpath(fn)
2427 fmt = 'f %%-%ds %%-%ds %%s' % (
2441 fmt = 'f %%-%ds %%-%ds %%s' % (
2428 max([len(abs) for abs in items]),
2442 max([len(abs) for abs in items]),
2429 max([len(m.rel(abs)) for abs in items]))
2443 max([len(m.rel(abs)) for abs in items]))
2430 for abs in items:
2444 for abs in items:
2431 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2445 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2432 ui.write("%s\n" % line.rstrip())
2446 ui.write("%s\n" % line.rstrip())
2433
2447
2434 @command('debugwireargs',
2448 @command('debugwireargs',
2435 [('', 'three', '', 'three'),
2449 [('', 'three', '', 'three'),
2436 ('', 'four', '', 'four'),
2450 ('', 'four', '', 'four'),
2437 ('', 'five', '', 'five'),
2451 ('', 'five', '', 'five'),
2438 ] + remoteopts,
2452 ] + remoteopts,
2439 _('REPO [OPTIONS]... [ONE [TWO]]'))
2453 _('REPO [OPTIONS]... [ONE [TWO]]'))
2440 def debugwireargs(ui, repopath, *vals, **opts):
2454 def debugwireargs(ui, repopath, *vals, **opts):
2441 repo = hg.peer(ui, opts, repopath)
2455 repo = hg.peer(ui, opts, repopath)
2442 for opt in remoteopts:
2456 for opt in remoteopts:
2443 del opts[opt[1]]
2457 del opts[opt[1]]
2444 args = {}
2458 args = {}
2445 for k, v in opts.iteritems():
2459 for k, v in opts.iteritems():
2446 if v:
2460 if v:
2447 args[k] = v
2461 args[k] = v
2448 # run twice to check that we don't mess up the stream for the next command
2462 # run twice to check that we don't mess up the stream for the next command
2449 res1 = repo.debugwireargs(*vals, **args)
2463 res1 = repo.debugwireargs(*vals, **args)
2450 res2 = repo.debugwireargs(*vals, **args)
2464 res2 = repo.debugwireargs(*vals, **args)
2451 ui.write("%s\n" % res1)
2465 ui.write("%s\n" % res1)
2452 if res1 != res2:
2466 if res1 != res2:
2453 ui.warn("%s\n" % res2)
2467 ui.warn("%s\n" % res2)
2454
2468
2455 @command('^diff',
2469 @command('^diff',
2456 [('r', 'rev', [], _('revision'), _('REV')),
2470 [('r', 'rev', [], _('revision'), _('REV')),
2457 ('c', 'change', '', _('change made by revision'), _('REV'))
2471 ('c', 'change', '', _('change made by revision'), _('REV'))
2458 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2472 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2459 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2473 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2460 def diff(ui, repo, *pats, **opts):
2474 def diff(ui, repo, *pats, **opts):
2461 """diff repository (or selected files)
2475 """diff repository (or selected files)
2462
2476
2463 Show differences between revisions for the specified files.
2477 Show differences between revisions for the specified files.
2464
2478
2465 Differences between files are shown using the unified diff format.
2479 Differences between files are shown using the unified diff format.
2466
2480
2467 .. note::
2481 .. note::
2468 diff may generate unexpected results for merges, as it will
2482 diff may generate unexpected results for merges, as it will
2469 default to comparing against the working directory's first
2483 default to comparing against the working directory's first
2470 parent changeset if no revisions are specified.
2484 parent changeset if no revisions are specified.
2471
2485
2472 When two revision arguments are given, then changes are shown
2486 When two revision arguments are given, then changes are shown
2473 between those revisions. If only one revision is specified then
2487 between those revisions. If only one revision is specified then
2474 that revision is compared to the working directory, and, when no
2488 that revision is compared to the working directory, and, when no
2475 revisions are specified, the working directory files are compared
2489 revisions are specified, the working directory files are compared
2476 to its parent.
2490 to its parent.
2477
2491
2478 Alternatively you can specify -c/--change with a revision to see
2492 Alternatively you can specify -c/--change with a revision to see
2479 the changes in that changeset relative to its first parent.
2493 the changes in that changeset relative to its first parent.
2480
2494
2481 Without the -a/--text option, diff will avoid generating diffs of
2495 Without the -a/--text option, diff will avoid generating diffs of
2482 files it detects as binary. With -a, diff will generate a diff
2496 files it detects as binary. With -a, diff will generate a diff
2483 anyway, probably with undesirable results.
2497 anyway, probably with undesirable results.
2484
2498
2485 Use the -g/--git option to generate diffs in the git extended diff
2499 Use the -g/--git option to generate diffs in the git extended diff
2486 format. For more information, read :hg:`help diffs`.
2500 format. For more information, read :hg:`help diffs`.
2487
2501
2488 .. container:: verbose
2502 .. container:: verbose
2489
2503
2490 Examples:
2504 Examples:
2491
2505
2492 - compare a file in the current working directory to its parent::
2506 - compare a file in the current working directory to its parent::
2493
2507
2494 hg diff foo.c
2508 hg diff foo.c
2495
2509
2496 - compare two historical versions of a directory, with rename info::
2510 - compare two historical versions of a directory, with rename info::
2497
2511
2498 hg diff --git -r 1.0:1.2 lib/
2512 hg diff --git -r 1.0:1.2 lib/
2499
2513
2500 - get change stats relative to the last change on some date::
2514 - get change stats relative to the last change on some date::
2501
2515
2502 hg diff --stat -r "date('may 2')"
2516 hg diff --stat -r "date('may 2')"
2503
2517
2504 - diff all newly-added files that contain a keyword::
2518 - diff all newly-added files that contain a keyword::
2505
2519
2506 hg diff "set:added() and grep(GNU)"
2520 hg diff "set:added() and grep(GNU)"
2507
2521
2508 - compare a revision and its parents::
2522 - compare a revision and its parents::
2509
2523
2510 hg diff -c 9353 # compare against first parent
2524 hg diff -c 9353 # compare against first parent
2511 hg diff -r 9353^:9353 # same using revset syntax
2525 hg diff -r 9353^:9353 # same using revset syntax
2512 hg diff -r 9353^2:9353 # compare against the second parent
2526 hg diff -r 9353^2:9353 # compare against the second parent
2513
2527
2514 Returns 0 on success.
2528 Returns 0 on success.
2515 """
2529 """
2516
2530
2517 revs = opts.get('rev')
2531 revs = opts.get('rev')
2518 change = opts.get('change')
2532 change = opts.get('change')
2519 stat = opts.get('stat')
2533 stat = opts.get('stat')
2520 reverse = opts.get('reverse')
2534 reverse = opts.get('reverse')
2521
2535
2522 if revs and change:
2536 if revs and change:
2523 msg = _('cannot specify --rev and --change at the same time')
2537 msg = _('cannot specify --rev and --change at the same time')
2524 raise util.Abort(msg)
2538 raise util.Abort(msg)
2525 elif change:
2539 elif change:
2526 node2 = scmutil.revsingle(repo, change, None).node()
2540 node2 = scmutil.revsingle(repo, change, None).node()
2527 node1 = repo[node2].p1().node()
2541 node1 = repo[node2].p1().node()
2528 else:
2542 else:
2529 node1, node2 = scmutil.revpair(repo, revs)
2543 node1, node2 = scmutil.revpair(repo, revs)
2530
2544
2531 if reverse:
2545 if reverse:
2532 node1, node2 = node2, node1
2546 node1, node2 = node2, node1
2533
2547
2534 diffopts = patch.diffopts(ui, opts)
2548 diffopts = patch.diffopts(ui, opts)
2535 m = scmutil.match(repo[node2], pats, opts)
2549 m = scmutil.match(repo[node2], pats, opts)
2536 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2550 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2537 listsubrepos=opts.get('subrepos'))
2551 listsubrepos=opts.get('subrepos'))
2538
2552
2539 @command('^export',
2553 @command('^export',
2540 [('o', 'output', '',
2554 [('o', 'output', '',
2541 _('print output to file with formatted name'), _('FORMAT')),
2555 _('print output to file with formatted name'), _('FORMAT')),
2542 ('', 'switch-parent', None, _('diff against the second parent')),
2556 ('', 'switch-parent', None, _('diff against the second parent')),
2543 ('r', 'rev', [], _('revisions to export'), _('REV')),
2557 ('r', 'rev', [], _('revisions to export'), _('REV')),
2544 ] + diffopts,
2558 ] + diffopts,
2545 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2559 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2546 def export(ui, repo, *changesets, **opts):
2560 def export(ui, repo, *changesets, **opts):
2547 """dump the header and diffs for one or more changesets
2561 """dump the header and diffs for one or more changesets
2548
2562
2549 Print the changeset header and diffs for one or more revisions.
2563 Print the changeset header and diffs for one or more revisions.
2550
2564
2551 The information shown in the changeset header is: author, date,
2565 The information shown in the changeset header is: author, date,
2552 branch name (if non-default), changeset hash, parent(s) and commit
2566 branch name (if non-default), changeset hash, parent(s) and commit
2553 comment.
2567 comment.
2554
2568
2555 .. note::
2569 .. note::
2556 export may generate unexpected diff output for merge
2570 export may generate unexpected diff output for merge
2557 changesets, as it will compare the merge changeset against its
2571 changesets, as it will compare the merge changeset against its
2558 first parent only.
2572 first parent only.
2559
2573
2560 Output may be to a file, in which case the name of the file is
2574 Output may be to a file, in which case the name of the file is
2561 given using a format string. The formatting rules are as follows:
2575 given using a format string. The formatting rules are as follows:
2562
2576
2563 :``%%``: literal "%" character
2577 :``%%``: literal "%" character
2564 :``%H``: changeset hash (40 hexadecimal digits)
2578 :``%H``: changeset hash (40 hexadecimal digits)
2565 :``%N``: number of patches being generated
2579 :``%N``: number of patches being generated
2566 :``%R``: changeset revision number
2580 :``%R``: changeset revision number
2567 :``%b``: basename of the exporting repository
2581 :``%b``: basename of the exporting repository
2568 :``%h``: short-form changeset hash (12 hexadecimal digits)
2582 :``%h``: short-form changeset hash (12 hexadecimal digits)
2569 :``%m``: first line of the commit message (only alphanumeric characters)
2583 :``%m``: first line of the commit message (only alphanumeric characters)
2570 :``%n``: zero-padded sequence number, starting at 1
2584 :``%n``: zero-padded sequence number, starting at 1
2571 :``%r``: zero-padded changeset revision number
2585 :``%r``: zero-padded changeset revision number
2572
2586
2573 Without the -a/--text option, export will avoid generating diffs
2587 Without the -a/--text option, export will avoid generating diffs
2574 of files it detects as binary. With -a, export will generate a
2588 of files it detects as binary. With -a, export will generate a
2575 diff anyway, probably with undesirable results.
2589 diff anyway, probably with undesirable results.
2576
2590
2577 Use the -g/--git option to generate diffs in the git extended diff
2591 Use the -g/--git option to generate diffs in the git extended diff
2578 format. See :hg:`help diffs` for more information.
2592 format. See :hg:`help diffs` for more information.
2579
2593
2580 With the --switch-parent option, the diff will be against the
2594 With the --switch-parent option, the diff will be against the
2581 second parent. It can be useful to review a merge.
2595 second parent. It can be useful to review a merge.
2582
2596
2583 .. container:: verbose
2597 .. container:: verbose
2584
2598
2585 Examples:
2599 Examples:
2586
2600
2587 - use export and import to transplant a bugfix to the current
2601 - use export and import to transplant a bugfix to the current
2588 branch::
2602 branch::
2589
2603
2590 hg export -r 9353 | hg import -
2604 hg export -r 9353 | hg import -
2591
2605
2592 - export all the changesets between two revisions to a file with
2606 - export all the changesets between two revisions to a file with
2593 rename information::
2607 rename information::
2594
2608
2595 hg export --git -r 123:150 > changes.txt
2609 hg export --git -r 123:150 > changes.txt
2596
2610
2597 - split outgoing changes into a series of patches with
2611 - split outgoing changes into a series of patches with
2598 descriptive names::
2612 descriptive names::
2599
2613
2600 hg export -r "outgoing()" -o "%n-%m.patch"
2614 hg export -r "outgoing()" -o "%n-%m.patch"
2601
2615
2602 Returns 0 on success.
2616 Returns 0 on success.
2603 """
2617 """
2604 changesets += tuple(opts.get('rev', []))
2618 changesets += tuple(opts.get('rev', []))
2605 revs = scmutil.revrange(repo, changesets)
2619 revs = scmutil.revrange(repo, changesets)
2606 if not revs:
2620 if not revs:
2607 raise util.Abort(_("export requires at least one changeset"))
2621 raise util.Abort(_("export requires at least one changeset"))
2608 if len(revs) > 1:
2622 if len(revs) > 1:
2609 ui.note(_('exporting patches:\n'))
2623 ui.note(_('exporting patches:\n'))
2610 else:
2624 else:
2611 ui.note(_('exporting patch:\n'))
2625 ui.note(_('exporting patch:\n'))
2612 cmdutil.export(repo, revs, template=opts.get('output'),
2626 cmdutil.export(repo, revs, template=opts.get('output'),
2613 switch_parent=opts.get('switch_parent'),
2627 switch_parent=opts.get('switch_parent'),
2614 opts=patch.diffopts(ui, opts))
2628 opts=patch.diffopts(ui, opts))
2615
2629
2616 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2630 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2617 def forget(ui, repo, *pats, **opts):
2631 def forget(ui, repo, *pats, **opts):
2618 """forget the specified files on the next commit
2632 """forget the specified files on the next commit
2619
2633
2620 Mark the specified files so they will no longer be tracked
2634 Mark the specified files so they will no longer be tracked
2621 after the next commit.
2635 after the next commit.
2622
2636
2623 This only removes files from the current branch, not from the
2637 This only removes files from the current branch, not from the
2624 entire project history, and it does not delete them from the
2638 entire project history, and it does not delete them from the
2625 working directory.
2639 working directory.
2626
2640
2627 To undo a forget before the next commit, see :hg:`add`.
2641 To undo a forget before the next commit, see :hg:`add`.
2628
2642
2629 .. container:: verbose
2643 .. container:: verbose
2630
2644
2631 Examples:
2645 Examples:
2632
2646
2633 - forget newly-added binary files::
2647 - forget newly-added binary files::
2634
2648
2635 hg forget "set:added() and binary()"
2649 hg forget "set:added() and binary()"
2636
2650
2637 - forget files that would be excluded by .hgignore::
2651 - forget files that would be excluded by .hgignore::
2638
2652
2639 hg forget "set:hgignore()"
2653 hg forget "set:hgignore()"
2640
2654
2641 Returns 0 on success.
2655 Returns 0 on success.
2642 """
2656 """
2643
2657
2644 if not pats:
2658 if not pats:
2645 raise util.Abort(_('no files specified'))
2659 raise util.Abort(_('no files specified'))
2646
2660
2647 m = scmutil.match(repo[None], pats, opts)
2661 m = scmutil.match(repo[None], pats, opts)
2648 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2662 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2649 return rejected and 1 or 0
2663 return rejected and 1 or 0
2650
2664
2651 @command(
2665 @command(
2652 'graft',
2666 'graft',
2653 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2667 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2654 ('c', 'continue', False, _('resume interrupted graft')),
2668 ('c', 'continue', False, _('resume interrupted graft')),
2655 ('e', 'edit', False, _('invoke editor on commit messages')),
2669 ('e', 'edit', False, _('invoke editor on commit messages')),
2656 ('', 'log', None, _('append graft info to log message')),
2670 ('', 'log', None, _('append graft info to log message')),
2657 ('D', 'currentdate', False,
2671 ('D', 'currentdate', False,
2658 _('record the current date as commit date')),
2672 _('record the current date as commit date')),
2659 ('U', 'currentuser', False,
2673 ('U', 'currentuser', False,
2660 _('record the current user as committer'), _('DATE'))]
2674 _('record the current user as committer'), _('DATE'))]
2661 + commitopts2 + mergetoolopts + dryrunopts,
2675 + commitopts2 + mergetoolopts + dryrunopts,
2662 _('[OPTION]... [-r] REV...'))
2676 _('[OPTION]... [-r] REV...'))
2663 def graft(ui, repo, *revs, **opts):
2677 def graft(ui, repo, *revs, **opts):
2664 '''copy changes from other branches onto the current branch
2678 '''copy changes from other branches onto the current branch
2665
2679
2666 This command uses Mercurial's merge logic to copy individual
2680 This command uses Mercurial's merge logic to copy individual
2667 changes from other branches without merging branches in the
2681 changes from other branches without merging branches in the
2668 history graph. This is sometimes known as 'backporting' or
2682 history graph. This is sometimes known as 'backporting' or
2669 'cherry-picking'. By default, graft will copy user, date, and
2683 'cherry-picking'. By default, graft will copy user, date, and
2670 description from the source changesets.
2684 description from the source changesets.
2671
2685
2672 Changesets that are ancestors of the current revision, that have
2686 Changesets that are ancestors of the current revision, that have
2673 already been grafted, or that are merges will be skipped.
2687 already been grafted, or that are merges will be skipped.
2674
2688
2675 If --log is specified, log messages will have a comment appended
2689 If --log is specified, log messages will have a comment appended
2676 of the form::
2690 of the form::
2677
2691
2678 (grafted from CHANGESETHASH)
2692 (grafted from CHANGESETHASH)
2679
2693
2680 If a graft merge results in conflicts, the graft process is
2694 If a graft merge results in conflicts, the graft process is
2681 interrupted so that the current merge can be manually resolved.
2695 interrupted so that the current merge can be manually resolved.
2682 Once all conflicts are addressed, the graft process can be
2696 Once all conflicts are addressed, the graft process can be
2683 continued with the -c/--continue option.
2697 continued with the -c/--continue option.
2684
2698
2685 .. note::
2699 .. note::
2686 The -c/--continue option does not reapply earlier options.
2700 The -c/--continue option does not reapply earlier options.
2687
2701
2688 .. container:: verbose
2702 .. container:: verbose
2689
2703
2690 Examples:
2704 Examples:
2691
2705
2692 - copy a single change to the stable branch and edit its description::
2706 - copy a single change to the stable branch and edit its description::
2693
2707
2694 hg update stable
2708 hg update stable
2695 hg graft --edit 9393
2709 hg graft --edit 9393
2696
2710
2697 - graft a range of changesets with one exception, updating dates::
2711 - graft a range of changesets with one exception, updating dates::
2698
2712
2699 hg graft -D "2085::2093 and not 2091"
2713 hg graft -D "2085::2093 and not 2091"
2700
2714
2701 - continue a graft after resolving conflicts::
2715 - continue a graft after resolving conflicts::
2702
2716
2703 hg graft -c
2717 hg graft -c
2704
2718
2705 - show the source of a grafted changeset::
2719 - show the source of a grafted changeset::
2706
2720
2707 hg log --debug -r tip
2721 hg log --debug -r tip
2708
2722
2709 Returns 0 on successful completion.
2723 Returns 0 on successful completion.
2710 '''
2724 '''
2711
2725
2712 revs = list(revs)
2726 revs = list(revs)
2713 revs.extend(opts['rev'])
2727 revs.extend(opts['rev'])
2714
2728
2715 if not opts.get('user') and opts.get('currentuser'):
2729 if not opts.get('user') and opts.get('currentuser'):
2716 opts['user'] = ui.username()
2730 opts['user'] = ui.username()
2717 if not opts.get('date') and opts.get('currentdate'):
2731 if not opts.get('date') and opts.get('currentdate'):
2718 opts['date'] = "%d %d" % util.makedate()
2732 opts['date'] = "%d %d" % util.makedate()
2719
2733
2720 editor = None
2734 editor = None
2721 if opts.get('edit'):
2735 if opts.get('edit'):
2722 editor = cmdutil.commitforceeditor
2736 editor = cmdutil.commitforceeditor
2723
2737
2724 cont = False
2738 cont = False
2725 if opts['continue']:
2739 if opts['continue']:
2726 cont = True
2740 cont = True
2727 if revs:
2741 if revs:
2728 raise util.Abort(_("can't specify --continue and revisions"))
2742 raise util.Abort(_("can't specify --continue and revisions"))
2729 # read in unfinished revisions
2743 # read in unfinished revisions
2730 try:
2744 try:
2731 nodes = repo.opener.read('graftstate').splitlines()
2745 nodes = repo.opener.read('graftstate').splitlines()
2732 revs = [repo[node].rev() for node in nodes]
2746 revs = [repo[node].rev() for node in nodes]
2733 except IOError, inst:
2747 except IOError, inst:
2734 if inst.errno != errno.ENOENT:
2748 if inst.errno != errno.ENOENT:
2735 raise
2749 raise
2736 raise util.Abort(_("no graft state found, can't continue"))
2750 raise util.Abort(_("no graft state found, can't continue"))
2737 else:
2751 else:
2738 cmdutil.bailifchanged(repo)
2752 cmdutil.bailifchanged(repo)
2739 if not revs:
2753 if not revs:
2740 raise util.Abort(_('no revisions specified'))
2754 raise util.Abort(_('no revisions specified'))
2741 revs = scmutil.revrange(repo, revs)
2755 revs = scmutil.revrange(repo, revs)
2742
2756
2743 # check for merges
2757 # check for merges
2744 for rev in repo.revs('%ld and merge()', revs):
2758 for rev in repo.revs('%ld and merge()', revs):
2745 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2759 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2746 revs.remove(rev)
2760 revs.remove(rev)
2747 if not revs:
2761 if not revs:
2748 return -1
2762 return -1
2749
2763
2750 # check for ancestors of dest branch
2764 # check for ancestors of dest branch
2751 for rev in repo.revs('::. and %ld', revs):
2765 for rev in repo.revs('::. and %ld', revs):
2752 ui.warn(_('skipping ancestor revision %s\n') % rev)
2766 ui.warn(_('skipping ancestor revision %s\n') % rev)
2753 revs.remove(rev)
2767 revs.remove(rev)
2754 if not revs:
2768 if not revs:
2755 return -1
2769 return -1
2756
2770
2757 # analyze revs for earlier grafts
2771 # analyze revs for earlier grafts
2758 ids = {}
2772 ids = {}
2759 for ctx in repo.set("%ld", revs):
2773 for ctx in repo.set("%ld", revs):
2760 ids[ctx.hex()] = ctx.rev()
2774 ids[ctx.hex()] = ctx.rev()
2761 n = ctx.extra().get('source')
2775 n = ctx.extra().get('source')
2762 if n:
2776 if n:
2763 ids[n] = ctx.rev()
2777 ids[n] = ctx.rev()
2764
2778
2765 # check ancestors for earlier grafts
2779 # check ancestors for earlier grafts
2766 ui.debug('scanning for duplicate grafts\n')
2780 ui.debug('scanning for duplicate grafts\n')
2767 for ctx in repo.set("::. - ::%ld", revs):
2781 for ctx in repo.set("::. - ::%ld", revs):
2768 n = ctx.extra().get('source')
2782 n = ctx.extra().get('source')
2769 if n in ids:
2783 if n in ids:
2770 r = repo[n].rev()
2784 r = repo[n].rev()
2771 if r in revs:
2785 if r in revs:
2772 ui.warn(_('skipping already grafted revision %s\n') % r)
2786 ui.warn(_('skipping already grafted revision %s\n') % r)
2773 revs.remove(r)
2787 revs.remove(r)
2774 elif ids[n] in revs:
2788 elif ids[n] in revs:
2775 ui.warn(_('skipping already grafted revision %s '
2789 ui.warn(_('skipping already grafted revision %s '
2776 '(same origin %d)\n') % (ids[n], r))
2790 '(same origin %d)\n') % (ids[n], r))
2777 revs.remove(ids[n])
2791 revs.remove(ids[n])
2778 elif ctx.hex() in ids:
2792 elif ctx.hex() in ids:
2779 r = ids[ctx.hex()]
2793 r = ids[ctx.hex()]
2780 ui.warn(_('skipping already grafted revision %s '
2794 ui.warn(_('skipping already grafted revision %s '
2781 '(was grafted from %d)\n') % (r, ctx.rev()))
2795 '(was grafted from %d)\n') % (r, ctx.rev()))
2782 revs.remove(r)
2796 revs.remove(r)
2783 if not revs:
2797 if not revs:
2784 return -1
2798 return -1
2785
2799
2786 wlock = repo.wlock()
2800 wlock = repo.wlock()
2787 try:
2801 try:
2788 for pos, ctx in enumerate(repo.set("%ld", revs)):
2802 for pos, ctx in enumerate(repo.set("%ld", revs)):
2789 current = repo['.']
2803 current = repo['.']
2790
2804
2791 ui.status(_('grafting revision %s\n') % ctx.rev())
2805 ui.status(_('grafting revision %s\n') % ctx.rev())
2792 if opts.get('dry_run'):
2806 if opts.get('dry_run'):
2793 continue
2807 continue
2794
2808
2795 # we don't merge the first commit when continuing
2809 # we don't merge the first commit when continuing
2796 if not cont:
2810 if not cont:
2797 # perform the graft merge with p1(rev) as 'ancestor'
2811 # perform the graft merge with p1(rev) as 'ancestor'
2798 try:
2812 try:
2799 # ui.forcemerge is an internal variable, do not document
2813 # ui.forcemerge is an internal variable, do not document
2800 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2814 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2801 stats = mergemod.update(repo, ctx.node(), True, True, False,
2815 stats = mergemod.update(repo, ctx.node(), True, True, False,
2802 ctx.p1().node())
2816 ctx.p1().node())
2803 finally:
2817 finally:
2804 repo.ui.setconfig('ui', 'forcemerge', '')
2818 repo.ui.setconfig('ui', 'forcemerge', '')
2805 # report any conflicts
2819 # report any conflicts
2806 if stats and stats[3] > 0:
2820 if stats and stats[3] > 0:
2807 # write out state for --continue
2821 # write out state for --continue
2808 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2822 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2809 repo.opener.write('graftstate', ''.join(nodelines))
2823 repo.opener.write('graftstate', ''.join(nodelines))
2810 raise util.Abort(
2824 raise util.Abort(
2811 _("unresolved conflicts, can't continue"),
2825 _("unresolved conflicts, can't continue"),
2812 hint=_('use hg resolve and hg graft --continue'))
2826 hint=_('use hg resolve and hg graft --continue'))
2813 else:
2827 else:
2814 cont = False
2828 cont = False
2815
2829
2816 # drop the second merge parent
2830 # drop the second merge parent
2817 repo.setparents(current.node(), nullid)
2831 repo.setparents(current.node(), nullid)
2818 repo.dirstate.write()
2832 repo.dirstate.write()
2819 # fix up dirstate for copies and renames
2833 # fix up dirstate for copies and renames
2820 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2834 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2821
2835
2822 # commit
2836 # commit
2823 source = ctx.extra().get('source')
2837 source = ctx.extra().get('source')
2824 if not source:
2838 if not source:
2825 source = ctx.hex()
2839 source = ctx.hex()
2826 extra = {'source': source}
2840 extra = {'source': source}
2827 user = ctx.user()
2841 user = ctx.user()
2828 if opts.get('user'):
2842 if opts.get('user'):
2829 user = opts['user']
2843 user = opts['user']
2830 date = ctx.date()
2844 date = ctx.date()
2831 if opts.get('date'):
2845 if opts.get('date'):
2832 date = opts['date']
2846 date = opts['date']
2833 message = ctx.description()
2847 message = ctx.description()
2834 if opts.get('log'):
2848 if opts.get('log'):
2835 message += '\n(grafted from %s)' % ctx.hex()
2849 message += '\n(grafted from %s)' % ctx.hex()
2836 node = repo.commit(text=message, user=user,
2850 node = repo.commit(text=message, user=user,
2837 date=date, extra=extra, editor=editor)
2851 date=date, extra=extra, editor=editor)
2838 if node is None:
2852 if node is None:
2839 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2853 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2840 finally:
2854 finally:
2841 wlock.release()
2855 wlock.release()
2842
2856
2843 # remove state when we complete successfully
2857 # remove state when we complete successfully
2844 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2858 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2845 util.unlinkpath(repo.join('graftstate'))
2859 util.unlinkpath(repo.join('graftstate'))
2846
2860
2847 return 0
2861 return 0
2848
2862
2849 @command('grep',
2863 @command('grep',
2850 [('0', 'print0', None, _('end fields with NUL')),
2864 [('0', 'print0', None, _('end fields with NUL')),
2851 ('', 'all', None, _('print all revisions that match')),
2865 ('', 'all', None, _('print all revisions that match')),
2852 ('a', 'text', None, _('treat all files as text')),
2866 ('a', 'text', None, _('treat all files as text')),
2853 ('f', 'follow', None,
2867 ('f', 'follow', None,
2854 _('follow changeset history,'
2868 _('follow changeset history,'
2855 ' or file history across copies and renames')),
2869 ' or file history across copies and renames')),
2856 ('i', 'ignore-case', None, _('ignore case when matching')),
2870 ('i', 'ignore-case', None, _('ignore case when matching')),
2857 ('l', 'files-with-matches', None,
2871 ('l', 'files-with-matches', None,
2858 _('print only filenames and revisions that match')),
2872 _('print only filenames and revisions that match')),
2859 ('n', 'line-number', None, _('print matching line numbers')),
2873 ('n', 'line-number', None, _('print matching line numbers')),
2860 ('r', 'rev', [],
2874 ('r', 'rev', [],
2861 _('only search files changed within revision range'), _('REV')),
2875 _('only search files changed within revision range'), _('REV')),
2862 ('u', 'user', None, _('list the author (long with -v)')),
2876 ('u', 'user', None, _('list the author (long with -v)')),
2863 ('d', 'date', None, _('list the date (short with -q)')),
2877 ('d', 'date', None, _('list the date (short with -q)')),
2864 ] + walkopts,
2878 ] + walkopts,
2865 _('[OPTION]... PATTERN [FILE]...'))
2879 _('[OPTION]... PATTERN [FILE]...'))
2866 def grep(ui, repo, pattern, *pats, **opts):
2880 def grep(ui, repo, pattern, *pats, **opts):
2867 """search for a pattern in specified files and revisions
2881 """search for a pattern in specified files and revisions
2868
2882
2869 Search revisions of files for a regular expression.
2883 Search revisions of files for a regular expression.
2870
2884
2871 This command behaves differently than Unix grep. It only accepts
2885 This command behaves differently than Unix grep. It only accepts
2872 Python/Perl regexps. It searches repository history, not the
2886 Python/Perl regexps. It searches repository history, not the
2873 working directory. It always prints the revision number in which a
2887 working directory. It always prints the revision number in which a
2874 match appears.
2888 match appears.
2875
2889
2876 By default, grep only prints output for the first revision of a
2890 By default, grep only prints output for the first revision of a
2877 file in which it finds a match. To get it to print every revision
2891 file in which it finds a match. To get it to print every revision
2878 that contains a change in match status ("-" for a match that
2892 that contains a change in match status ("-" for a match that
2879 becomes a non-match, or "+" for a non-match that becomes a match),
2893 becomes a non-match, or "+" for a non-match that becomes a match),
2880 use the --all flag.
2894 use the --all flag.
2881
2895
2882 Returns 0 if a match is found, 1 otherwise.
2896 Returns 0 if a match is found, 1 otherwise.
2883 """
2897 """
2884 reflags = re.M
2898 reflags = re.M
2885 if opts.get('ignore_case'):
2899 if opts.get('ignore_case'):
2886 reflags |= re.I
2900 reflags |= re.I
2887 try:
2901 try:
2888 regexp = re.compile(pattern, reflags)
2902 regexp = re.compile(pattern, reflags)
2889 except re.error, inst:
2903 except re.error, inst:
2890 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2904 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2891 return 1
2905 return 1
2892 sep, eol = ':', '\n'
2906 sep, eol = ':', '\n'
2893 if opts.get('print0'):
2907 if opts.get('print0'):
2894 sep = eol = '\0'
2908 sep = eol = '\0'
2895
2909
2896 getfile = util.lrucachefunc(repo.file)
2910 getfile = util.lrucachefunc(repo.file)
2897
2911
2898 def matchlines(body):
2912 def matchlines(body):
2899 begin = 0
2913 begin = 0
2900 linenum = 0
2914 linenum = 0
2901 while True:
2915 while True:
2902 match = regexp.search(body, begin)
2916 match = regexp.search(body, begin)
2903 if not match:
2917 if not match:
2904 break
2918 break
2905 mstart, mend = match.span()
2919 mstart, mend = match.span()
2906 linenum += body.count('\n', begin, mstart) + 1
2920 linenum += body.count('\n', begin, mstart) + 1
2907 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2921 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2908 begin = body.find('\n', mend) + 1 or len(body) + 1
2922 begin = body.find('\n', mend) + 1 or len(body) + 1
2909 lend = begin - 1
2923 lend = begin - 1
2910 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2924 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2911
2925
2912 class linestate(object):
2926 class linestate(object):
2913 def __init__(self, line, linenum, colstart, colend):
2927 def __init__(self, line, linenum, colstart, colend):
2914 self.line = line
2928 self.line = line
2915 self.linenum = linenum
2929 self.linenum = linenum
2916 self.colstart = colstart
2930 self.colstart = colstart
2917 self.colend = colend
2931 self.colend = colend
2918
2932
2919 def __hash__(self):
2933 def __hash__(self):
2920 return hash((self.linenum, self.line))
2934 return hash((self.linenum, self.line))
2921
2935
2922 def __eq__(self, other):
2936 def __eq__(self, other):
2923 return self.line == other.line
2937 return self.line == other.line
2924
2938
2925 matches = {}
2939 matches = {}
2926 copies = {}
2940 copies = {}
2927 def grepbody(fn, rev, body):
2941 def grepbody(fn, rev, body):
2928 matches[rev].setdefault(fn, [])
2942 matches[rev].setdefault(fn, [])
2929 m = matches[rev][fn]
2943 m = matches[rev][fn]
2930 for lnum, cstart, cend, line in matchlines(body):
2944 for lnum, cstart, cend, line in matchlines(body):
2931 s = linestate(line, lnum, cstart, cend)
2945 s = linestate(line, lnum, cstart, cend)
2932 m.append(s)
2946 m.append(s)
2933
2947
2934 def difflinestates(a, b):
2948 def difflinestates(a, b):
2935 sm = difflib.SequenceMatcher(None, a, b)
2949 sm = difflib.SequenceMatcher(None, a, b)
2936 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2950 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2937 if tag == 'insert':
2951 if tag == 'insert':
2938 for i in xrange(blo, bhi):
2952 for i in xrange(blo, bhi):
2939 yield ('+', b[i])
2953 yield ('+', b[i])
2940 elif tag == 'delete':
2954 elif tag == 'delete':
2941 for i in xrange(alo, ahi):
2955 for i in xrange(alo, ahi):
2942 yield ('-', a[i])
2956 yield ('-', a[i])
2943 elif tag == 'replace':
2957 elif tag == 'replace':
2944 for i in xrange(alo, ahi):
2958 for i in xrange(alo, ahi):
2945 yield ('-', a[i])
2959 yield ('-', a[i])
2946 for i in xrange(blo, bhi):
2960 for i in xrange(blo, bhi):
2947 yield ('+', b[i])
2961 yield ('+', b[i])
2948
2962
2949 def display(fn, ctx, pstates, states):
2963 def display(fn, ctx, pstates, states):
2950 rev = ctx.rev()
2964 rev = ctx.rev()
2951 datefunc = ui.quiet and util.shortdate or util.datestr
2965 datefunc = ui.quiet and util.shortdate or util.datestr
2952 found = False
2966 found = False
2953 filerevmatches = {}
2967 filerevmatches = {}
2954 def binary():
2968 def binary():
2955 flog = getfile(fn)
2969 flog = getfile(fn)
2956 return util.binary(flog.read(ctx.filenode(fn)))
2970 return util.binary(flog.read(ctx.filenode(fn)))
2957
2971
2958 if opts.get('all'):
2972 if opts.get('all'):
2959 iter = difflinestates(pstates, states)
2973 iter = difflinestates(pstates, states)
2960 else:
2974 else:
2961 iter = [('', l) for l in states]
2975 iter = [('', l) for l in states]
2962 for change, l in iter:
2976 for change, l in iter:
2963 cols = [fn, str(rev)]
2977 cols = [fn, str(rev)]
2964 before, match, after = None, None, None
2978 before, match, after = None, None, None
2965 if opts.get('line_number'):
2979 if opts.get('line_number'):
2966 cols.append(str(l.linenum))
2980 cols.append(str(l.linenum))
2967 if opts.get('all'):
2981 if opts.get('all'):
2968 cols.append(change)
2982 cols.append(change)
2969 if opts.get('user'):
2983 if opts.get('user'):
2970 cols.append(ui.shortuser(ctx.user()))
2984 cols.append(ui.shortuser(ctx.user()))
2971 if opts.get('date'):
2985 if opts.get('date'):
2972 cols.append(datefunc(ctx.date()))
2986 cols.append(datefunc(ctx.date()))
2973 if opts.get('files_with_matches'):
2987 if opts.get('files_with_matches'):
2974 c = (fn, rev)
2988 c = (fn, rev)
2975 if c in filerevmatches:
2989 if c in filerevmatches:
2976 continue
2990 continue
2977 filerevmatches[c] = 1
2991 filerevmatches[c] = 1
2978 else:
2992 else:
2979 before = l.line[:l.colstart]
2993 before = l.line[:l.colstart]
2980 match = l.line[l.colstart:l.colend]
2994 match = l.line[l.colstart:l.colend]
2981 after = l.line[l.colend:]
2995 after = l.line[l.colend:]
2982 ui.write(sep.join(cols))
2996 ui.write(sep.join(cols))
2983 if before is not None:
2997 if before is not None:
2984 if not opts.get('text') and binary():
2998 if not opts.get('text') and binary():
2985 ui.write(sep + " Binary file matches")
2999 ui.write(sep + " Binary file matches")
2986 else:
3000 else:
2987 ui.write(sep + before)
3001 ui.write(sep + before)
2988 ui.write(match, label='grep.match')
3002 ui.write(match, label='grep.match')
2989 ui.write(after)
3003 ui.write(after)
2990 ui.write(eol)
3004 ui.write(eol)
2991 found = True
3005 found = True
2992 return found
3006 return found
2993
3007
2994 skip = {}
3008 skip = {}
2995 revfiles = {}
3009 revfiles = {}
2996 matchfn = scmutil.match(repo[None], pats, opts)
3010 matchfn = scmutil.match(repo[None], pats, opts)
2997 found = False
3011 found = False
2998 follow = opts.get('follow')
3012 follow = opts.get('follow')
2999
3013
3000 def prep(ctx, fns):
3014 def prep(ctx, fns):
3001 rev = ctx.rev()
3015 rev = ctx.rev()
3002 pctx = ctx.p1()
3016 pctx = ctx.p1()
3003 parent = pctx.rev()
3017 parent = pctx.rev()
3004 matches.setdefault(rev, {})
3018 matches.setdefault(rev, {})
3005 matches.setdefault(parent, {})
3019 matches.setdefault(parent, {})
3006 files = revfiles.setdefault(rev, [])
3020 files = revfiles.setdefault(rev, [])
3007 for fn in fns:
3021 for fn in fns:
3008 flog = getfile(fn)
3022 flog = getfile(fn)
3009 try:
3023 try:
3010 fnode = ctx.filenode(fn)
3024 fnode = ctx.filenode(fn)
3011 except error.LookupError:
3025 except error.LookupError:
3012 continue
3026 continue
3013
3027
3014 copied = flog.renamed(fnode)
3028 copied = flog.renamed(fnode)
3015 copy = follow and copied and copied[0]
3029 copy = follow and copied and copied[0]
3016 if copy:
3030 if copy:
3017 copies.setdefault(rev, {})[fn] = copy
3031 copies.setdefault(rev, {})[fn] = copy
3018 if fn in skip:
3032 if fn in skip:
3019 if copy:
3033 if copy:
3020 skip[copy] = True
3034 skip[copy] = True
3021 continue
3035 continue
3022 files.append(fn)
3036 files.append(fn)
3023
3037
3024 if fn not in matches[rev]:
3038 if fn not in matches[rev]:
3025 grepbody(fn, rev, flog.read(fnode))
3039 grepbody(fn, rev, flog.read(fnode))
3026
3040
3027 pfn = copy or fn
3041 pfn = copy or fn
3028 if pfn not in matches[parent]:
3042 if pfn not in matches[parent]:
3029 try:
3043 try:
3030 fnode = pctx.filenode(pfn)
3044 fnode = pctx.filenode(pfn)
3031 grepbody(pfn, parent, flog.read(fnode))
3045 grepbody(pfn, parent, flog.read(fnode))
3032 except error.LookupError:
3046 except error.LookupError:
3033 pass
3047 pass
3034
3048
3035 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3049 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3036 rev = ctx.rev()
3050 rev = ctx.rev()
3037 parent = ctx.p1().rev()
3051 parent = ctx.p1().rev()
3038 for fn in sorted(revfiles.get(rev, [])):
3052 for fn in sorted(revfiles.get(rev, [])):
3039 states = matches[rev][fn]
3053 states = matches[rev][fn]
3040 copy = copies.get(rev, {}).get(fn)
3054 copy = copies.get(rev, {}).get(fn)
3041 if fn in skip:
3055 if fn in skip:
3042 if copy:
3056 if copy:
3043 skip[copy] = True
3057 skip[copy] = True
3044 continue
3058 continue
3045 pstates = matches.get(parent, {}).get(copy or fn, [])
3059 pstates = matches.get(parent, {}).get(copy or fn, [])
3046 if pstates or states:
3060 if pstates or states:
3047 r = display(fn, ctx, pstates, states)
3061 r = display(fn, ctx, pstates, states)
3048 found = found or r
3062 found = found or r
3049 if r and not opts.get('all'):
3063 if r and not opts.get('all'):
3050 skip[fn] = True
3064 skip[fn] = True
3051 if copy:
3065 if copy:
3052 skip[copy] = True
3066 skip[copy] = True
3053 del matches[rev]
3067 del matches[rev]
3054 del revfiles[rev]
3068 del revfiles[rev]
3055
3069
3056 return not found
3070 return not found
3057
3071
3058 @command('heads',
3072 @command('heads',
3059 [('r', 'rev', '',
3073 [('r', 'rev', '',
3060 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3074 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3061 ('t', 'topo', False, _('show topological heads only')),
3075 ('t', 'topo', False, _('show topological heads only')),
3062 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3076 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3063 ('c', 'closed', False, _('show normal and closed branch heads')),
3077 ('c', 'closed', False, _('show normal and closed branch heads')),
3064 ] + templateopts,
3078 ] + templateopts,
3065 _('[-ct] [-r STARTREV] [REV]...'))
3079 _('[-ct] [-r STARTREV] [REV]...'))
3066 def heads(ui, repo, *branchrevs, **opts):
3080 def heads(ui, repo, *branchrevs, **opts):
3067 """show current repository heads or show branch heads
3081 """show current repository heads or show branch heads
3068
3082
3069 With no arguments, show all repository branch heads.
3083 With no arguments, show all repository branch heads.
3070
3084
3071 Repository "heads" are changesets with no child changesets. They are
3085 Repository "heads" are changesets with no child changesets. They are
3072 where development generally takes place and are the usual targets
3086 where development generally takes place and are the usual targets
3073 for update and merge operations. Branch heads are changesets that have
3087 for update and merge operations. Branch heads are changesets that have
3074 no child changeset on the same branch.
3088 no child changeset on the same branch.
3075
3089
3076 If one or more REVs are given, only branch heads on the branches
3090 If one or more REVs are given, only branch heads on the branches
3077 associated with the specified changesets are shown. This means
3091 associated with the specified changesets are shown. This means
3078 that you can use :hg:`heads foo` to see the heads on a branch
3092 that you can use :hg:`heads foo` to see the heads on a branch
3079 named ``foo``.
3093 named ``foo``.
3080
3094
3081 If -c/--closed is specified, also show branch heads marked closed
3095 If -c/--closed is specified, also show branch heads marked closed
3082 (see :hg:`commit --close-branch`).
3096 (see :hg:`commit --close-branch`).
3083
3097
3084 If STARTREV is specified, only those heads that are descendants of
3098 If STARTREV is specified, only those heads that are descendants of
3085 STARTREV will be displayed.
3099 STARTREV will be displayed.
3086
3100
3087 If -t/--topo is specified, named branch mechanics will be ignored and only
3101 If -t/--topo is specified, named branch mechanics will be ignored and only
3088 changesets without children will be shown.
3102 changesets without children will be shown.
3089
3103
3090 Returns 0 if matching heads are found, 1 if not.
3104 Returns 0 if matching heads are found, 1 if not.
3091 """
3105 """
3092
3106
3093 start = None
3107 start = None
3094 if 'rev' in opts:
3108 if 'rev' in opts:
3095 start = scmutil.revsingle(repo, opts['rev'], None).node()
3109 start = scmutil.revsingle(repo, opts['rev'], None).node()
3096
3110
3097 if opts.get('topo'):
3111 if opts.get('topo'):
3098 heads = [repo[h] for h in repo.heads(start)]
3112 heads = [repo[h] for h in repo.heads(start)]
3099 else:
3113 else:
3100 heads = []
3114 heads = []
3101 for branch in repo.branchmap():
3115 for branch in repo.branchmap():
3102 heads += repo.branchheads(branch, start, opts.get('closed'))
3116 heads += repo.branchheads(branch, start, opts.get('closed'))
3103 heads = [repo[h] for h in heads]
3117 heads = [repo[h] for h in heads]
3104
3118
3105 if branchrevs:
3119 if branchrevs:
3106 branches = set(repo[br].branch() for br in branchrevs)
3120 branches = set(repo[br].branch() for br in branchrevs)
3107 heads = [h for h in heads if h.branch() in branches]
3121 heads = [h for h in heads if h.branch() in branches]
3108
3122
3109 if opts.get('active') and branchrevs:
3123 if opts.get('active') and branchrevs:
3110 dagheads = repo.heads(start)
3124 dagheads = repo.heads(start)
3111 heads = [h for h in heads if h.node() in dagheads]
3125 heads = [h for h in heads if h.node() in dagheads]
3112
3126
3113 if branchrevs:
3127 if branchrevs:
3114 haveheads = set(h.branch() for h in heads)
3128 haveheads = set(h.branch() for h in heads)
3115 if branches - haveheads:
3129 if branches - haveheads:
3116 headless = ', '.join(b for b in branches - haveheads)
3130 headless = ', '.join(b for b in branches - haveheads)
3117 msg = _('no open branch heads found on branches %s')
3131 msg = _('no open branch heads found on branches %s')
3118 if opts.get('rev'):
3132 if opts.get('rev'):
3119 msg += _(' (started at %s)') % opts['rev']
3133 msg += _(' (started at %s)') % opts['rev']
3120 ui.warn((msg + '\n') % headless)
3134 ui.warn((msg + '\n') % headless)
3121
3135
3122 if not heads:
3136 if not heads:
3123 return 1
3137 return 1
3124
3138
3125 heads = sorted(heads, key=lambda x: -x.rev())
3139 heads = sorted(heads, key=lambda x: -x.rev())
3126 displayer = cmdutil.show_changeset(ui, repo, opts)
3140 displayer = cmdutil.show_changeset(ui, repo, opts)
3127 for ctx in heads:
3141 for ctx in heads:
3128 displayer.show(ctx)
3142 displayer.show(ctx)
3129 displayer.close()
3143 displayer.close()
3130
3144
3131 @command('help',
3145 @command('help',
3132 [('e', 'extension', None, _('show only help for extensions')),
3146 [('e', 'extension', None, _('show only help for extensions')),
3133 ('c', 'command', None, _('show only help for commands')),
3147 ('c', 'command', None, _('show only help for commands')),
3134 ('k', 'keyword', '', _('show topics matching keyword')),
3148 ('k', 'keyword', '', _('show topics matching keyword')),
3135 ],
3149 ],
3136 _('[-ec] [TOPIC]'))
3150 _('[-ec] [TOPIC]'))
3137 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3151 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3138 """show help for a given topic or a help overview
3152 """show help for a given topic or a help overview
3139
3153
3140 With no arguments, print a list of commands with short help messages.
3154 With no arguments, print a list of commands with short help messages.
3141
3155
3142 Given a topic, extension, or command name, print help for that
3156 Given a topic, extension, or command name, print help for that
3143 topic.
3157 topic.
3144
3158
3145 Returns 0 if successful.
3159 Returns 0 if successful.
3146 """
3160 """
3147
3161
3148 textwidth = min(ui.termwidth(), 80) - 2
3162 textwidth = min(ui.termwidth(), 80) - 2
3149
3163
3150 def helpcmd(name):
3164 def helpcmd(name):
3151 try:
3165 try:
3152 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3166 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3153 except error.AmbiguousCommand, inst:
3167 except error.AmbiguousCommand, inst:
3154 # py3k fix: except vars can't be used outside the scope of the
3168 # py3k fix: except vars can't be used outside the scope of the
3155 # except block, nor can be used inside a lambda. python issue4617
3169 # except block, nor can be used inside a lambda. python issue4617
3156 prefix = inst.args[0]
3170 prefix = inst.args[0]
3157 select = lambda c: c.lstrip('^').startswith(prefix)
3171 select = lambda c: c.lstrip('^').startswith(prefix)
3158 rst = helplist(select)
3172 rst = helplist(select)
3159 return rst
3173 return rst
3160
3174
3161 rst = []
3175 rst = []
3162
3176
3163 # check if it's an invalid alias and display its error if it is
3177 # check if it's an invalid alias and display its error if it is
3164 if getattr(entry[0], 'badalias', False):
3178 if getattr(entry[0], 'badalias', False):
3165 if not unknowncmd:
3179 if not unknowncmd:
3166 ui.pushbuffer()
3180 ui.pushbuffer()
3167 entry[0](ui)
3181 entry[0](ui)
3168 rst.append(ui.popbuffer())
3182 rst.append(ui.popbuffer())
3169 return rst
3183 return rst
3170
3184
3171 # synopsis
3185 # synopsis
3172 if len(entry) > 2:
3186 if len(entry) > 2:
3173 if entry[2].startswith('hg'):
3187 if entry[2].startswith('hg'):
3174 rst.append("%s\n" % entry[2])
3188 rst.append("%s\n" % entry[2])
3175 else:
3189 else:
3176 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3190 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3177 else:
3191 else:
3178 rst.append('hg %s\n' % aliases[0])
3192 rst.append('hg %s\n' % aliases[0])
3179 # aliases
3193 # aliases
3180 if full and not ui.quiet and len(aliases) > 1:
3194 if full and not ui.quiet and len(aliases) > 1:
3181 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3195 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3182 rst.append('\n')
3196 rst.append('\n')
3183
3197
3184 # description
3198 # description
3185 doc = gettext(entry[0].__doc__)
3199 doc = gettext(entry[0].__doc__)
3186 if not doc:
3200 if not doc:
3187 doc = _("(no help text available)")
3201 doc = _("(no help text available)")
3188 if util.safehasattr(entry[0], 'definition'): # aliased command
3202 if util.safehasattr(entry[0], 'definition'): # aliased command
3189 if entry[0].definition.startswith('!'): # shell alias
3203 if entry[0].definition.startswith('!'): # shell alias
3190 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3204 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3191 else:
3205 else:
3192 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3206 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3193 doc = doc.splitlines(True)
3207 doc = doc.splitlines(True)
3194 if ui.quiet or not full:
3208 if ui.quiet or not full:
3195 rst.append(doc[0])
3209 rst.append(doc[0])
3196 else:
3210 else:
3197 rst.extend(doc)
3211 rst.extend(doc)
3198 rst.append('\n')
3212 rst.append('\n')
3199
3213
3200 # check if this command shadows a non-trivial (multi-line)
3214 # check if this command shadows a non-trivial (multi-line)
3201 # extension help text
3215 # extension help text
3202 try:
3216 try:
3203 mod = extensions.find(name)
3217 mod = extensions.find(name)
3204 doc = gettext(mod.__doc__) or ''
3218 doc = gettext(mod.__doc__) or ''
3205 if '\n' in doc.strip():
3219 if '\n' in doc.strip():
3206 msg = _('use "hg help -e %s" to show help for '
3220 msg = _('use "hg help -e %s" to show help for '
3207 'the %s extension') % (name, name)
3221 'the %s extension') % (name, name)
3208 rst.append('\n%s\n' % msg)
3222 rst.append('\n%s\n' % msg)
3209 except KeyError:
3223 except KeyError:
3210 pass
3224 pass
3211
3225
3212 # options
3226 # options
3213 if not ui.quiet and entry[1]:
3227 if not ui.quiet and entry[1]:
3214 rst.append('\n%s\n\n' % _("options:"))
3228 rst.append('\n%s\n\n' % _("options:"))
3215 rst.append(help.optrst(entry[1], ui.verbose))
3229 rst.append(help.optrst(entry[1], ui.verbose))
3216
3230
3217 if ui.verbose:
3231 if ui.verbose:
3218 rst.append('\n%s\n\n' % _("global options:"))
3232 rst.append('\n%s\n\n' % _("global options:"))
3219 rst.append(help.optrst(globalopts, ui.verbose))
3233 rst.append(help.optrst(globalopts, ui.verbose))
3220
3234
3221 if not ui.verbose:
3235 if not ui.verbose:
3222 if not full:
3236 if not full:
3223 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3237 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3224 % name)
3238 % name)
3225 elif not ui.quiet:
3239 elif not ui.quiet:
3226 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3240 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3227 % name)
3241 % name)
3228 return rst
3242 return rst
3229
3243
3230
3244
3231 def helplist(select=None):
3245 def helplist(select=None):
3232 # list of commands
3246 # list of commands
3233 if name == "shortlist":
3247 if name == "shortlist":
3234 header = _('basic commands:\n\n')
3248 header = _('basic commands:\n\n')
3235 else:
3249 else:
3236 header = _('list of commands:\n\n')
3250 header = _('list of commands:\n\n')
3237
3251
3238 h = {}
3252 h = {}
3239 cmds = {}
3253 cmds = {}
3240 for c, e in table.iteritems():
3254 for c, e in table.iteritems():
3241 f = c.split("|", 1)[0]
3255 f = c.split("|", 1)[0]
3242 if select and not select(f):
3256 if select and not select(f):
3243 continue
3257 continue
3244 if (not select and name != 'shortlist' and
3258 if (not select and name != 'shortlist' and
3245 e[0].__module__ != __name__):
3259 e[0].__module__ != __name__):
3246 continue
3260 continue
3247 if name == "shortlist" and not f.startswith("^"):
3261 if name == "shortlist" and not f.startswith("^"):
3248 continue
3262 continue
3249 f = f.lstrip("^")
3263 f = f.lstrip("^")
3250 if not ui.debugflag and f.startswith("debug"):
3264 if not ui.debugflag and f.startswith("debug"):
3251 continue
3265 continue
3252 doc = e[0].__doc__
3266 doc = e[0].__doc__
3253 if doc and 'DEPRECATED' in doc and not ui.verbose:
3267 if doc and 'DEPRECATED' in doc and not ui.verbose:
3254 continue
3268 continue
3255 doc = gettext(doc)
3269 doc = gettext(doc)
3256 if not doc:
3270 if not doc:
3257 doc = _("(no help text available)")
3271 doc = _("(no help text available)")
3258 h[f] = doc.splitlines()[0].rstrip()
3272 h[f] = doc.splitlines()[0].rstrip()
3259 cmds[f] = c.lstrip("^")
3273 cmds[f] = c.lstrip("^")
3260
3274
3261 rst = []
3275 rst = []
3262 if not h:
3276 if not h:
3263 if not ui.quiet:
3277 if not ui.quiet:
3264 rst.append(_('no commands defined\n'))
3278 rst.append(_('no commands defined\n'))
3265 return rst
3279 return rst
3266
3280
3267 if not ui.quiet:
3281 if not ui.quiet:
3268 rst.append(header)
3282 rst.append(header)
3269 fns = sorted(h)
3283 fns = sorted(h)
3270 for f in fns:
3284 for f in fns:
3271 if ui.verbose:
3285 if ui.verbose:
3272 commands = cmds[f].replace("|",", ")
3286 commands = cmds[f].replace("|",", ")
3273 rst.append(" :%s: %s\n" % (commands, h[f]))
3287 rst.append(" :%s: %s\n" % (commands, h[f]))
3274 else:
3288 else:
3275 rst.append(' :%s: %s\n' % (f, h[f]))
3289 rst.append(' :%s: %s\n' % (f, h[f]))
3276
3290
3277 if not name:
3291 if not name:
3278 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3292 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3279 if exts:
3293 if exts:
3280 rst.append('\n')
3294 rst.append('\n')
3281 rst.extend(exts)
3295 rst.extend(exts)
3282
3296
3283 rst.append(_("\nadditional help topics:\n\n"))
3297 rst.append(_("\nadditional help topics:\n\n"))
3284 topics = []
3298 topics = []
3285 for names, header, doc in help.helptable:
3299 for names, header, doc in help.helptable:
3286 topics.append((sorted(names, key=len, reverse=True)[0], header))
3300 topics.append((sorted(names, key=len, reverse=True)[0], header))
3287 for t, desc in topics:
3301 for t, desc in topics:
3288 rst.append(" :%s: %s\n" % (t, desc))
3302 rst.append(" :%s: %s\n" % (t, desc))
3289
3303
3290 optlist = []
3304 optlist = []
3291 if not ui.quiet:
3305 if not ui.quiet:
3292 if ui.verbose:
3306 if ui.verbose:
3293 optlist.append((_("global options:"), globalopts))
3307 optlist.append((_("global options:"), globalopts))
3294 if name == 'shortlist':
3308 if name == 'shortlist':
3295 optlist.append((_('use "hg help" for the full list '
3309 optlist.append((_('use "hg help" for the full list '
3296 'of commands'), ()))
3310 'of commands'), ()))
3297 else:
3311 else:
3298 if name == 'shortlist':
3312 if name == 'shortlist':
3299 msg = _('use "hg help" for the full list of commands '
3313 msg = _('use "hg help" for the full list of commands '
3300 'or "hg -v" for details')
3314 'or "hg -v" for details')
3301 elif name and not full:
3315 elif name and not full:
3302 msg = _('use "hg help %s" to show the full help '
3316 msg = _('use "hg help %s" to show the full help '
3303 'text') % name
3317 'text') % name
3304 else:
3318 else:
3305 msg = _('use "hg -v help%s" to show builtin aliases and '
3319 msg = _('use "hg -v help%s" to show builtin aliases and '
3306 'global options') % (name and " " + name or "")
3320 'global options') % (name and " " + name or "")
3307 optlist.append((msg, ()))
3321 optlist.append((msg, ()))
3308
3322
3309 if optlist:
3323 if optlist:
3310 for title, options in optlist:
3324 for title, options in optlist:
3311 rst.append('\n%s\n' % title)
3325 rst.append('\n%s\n' % title)
3312 if options:
3326 if options:
3313 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3327 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3314 return rst
3328 return rst
3315
3329
3316 def helptopic(name):
3330 def helptopic(name):
3317 for names, header, doc in help.helptable:
3331 for names, header, doc in help.helptable:
3318 if name in names:
3332 if name in names:
3319 break
3333 break
3320 else:
3334 else:
3321 raise error.UnknownCommand(name)
3335 raise error.UnknownCommand(name)
3322
3336
3323 rst = ["%s\n\n" % header]
3337 rst = ["%s\n\n" % header]
3324 # description
3338 # description
3325 if not doc:
3339 if not doc:
3326 rst.append(" %s\n" % _("(no help text available)"))
3340 rst.append(" %s\n" % _("(no help text available)"))
3327 if util.safehasattr(doc, '__call__'):
3341 if util.safehasattr(doc, '__call__'):
3328 rst += [" %s\n" % l for l in doc().splitlines()]
3342 rst += [" %s\n" % l for l in doc().splitlines()]
3329
3343
3330 try:
3344 try:
3331 cmdutil.findcmd(name, table)
3345 cmdutil.findcmd(name, table)
3332 rst.append(_('\nuse "hg help -c %s" to see help for '
3346 rst.append(_('\nuse "hg help -c %s" to see help for '
3333 'the %s command\n') % (name, name))
3347 'the %s command\n') % (name, name))
3334 except error.UnknownCommand:
3348 except error.UnknownCommand:
3335 pass
3349 pass
3336 return rst
3350 return rst
3337
3351
3338 def helpext(name):
3352 def helpext(name):
3339 try:
3353 try:
3340 mod = extensions.find(name)
3354 mod = extensions.find(name)
3341 doc = gettext(mod.__doc__) or _('no help text available')
3355 doc = gettext(mod.__doc__) or _('no help text available')
3342 except KeyError:
3356 except KeyError:
3343 mod = None
3357 mod = None
3344 doc = extensions.disabledext(name)
3358 doc = extensions.disabledext(name)
3345 if not doc:
3359 if not doc:
3346 raise error.UnknownCommand(name)
3360 raise error.UnknownCommand(name)
3347
3361
3348 if '\n' not in doc:
3362 if '\n' not in doc:
3349 head, tail = doc, ""
3363 head, tail = doc, ""
3350 else:
3364 else:
3351 head, tail = doc.split('\n', 1)
3365 head, tail = doc.split('\n', 1)
3352 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3366 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3353 if tail:
3367 if tail:
3354 rst.extend(tail.splitlines(True))
3368 rst.extend(tail.splitlines(True))
3355 rst.append('\n')
3369 rst.append('\n')
3356
3370
3357 if mod:
3371 if mod:
3358 try:
3372 try:
3359 ct = mod.cmdtable
3373 ct = mod.cmdtable
3360 except AttributeError:
3374 except AttributeError:
3361 ct = {}
3375 ct = {}
3362 modcmds = set([c.split('|', 1)[0] for c in ct])
3376 modcmds = set([c.split('|', 1)[0] for c in ct])
3363 rst.extend(helplist(modcmds.__contains__))
3377 rst.extend(helplist(modcmds.__contains__))
3364 else:
3378 else:
3365 rst.append(_('use "hg help extensions" for information on enabling '
3379 rst.append(_('use "hg help extensions" for information on enabling '
3366 'extensions\n'))
3380 'extensions\n'))
3367 return rst
3381 return rst
3368
3382
3369 def helpextcmd(name):
3383 def helpextcmd(name):
3370 cmd, ext, mod = extensions.disabledcmd(ui, name,
3384 cmd, ext, mod = extensions.disabledcmd(ui, name,
3371 ui.configbool('ui', 'strict'))
3385 ui.configbool('ui', 'strict'))
3372 doc = gettext(mod.__doc__).splitlines()[0]
3386 doc = gettext(mod.__doc__).splitlines()[0]
3373
3387
3374 rst = help.listexts(_("'%s' is provided by the following "
3388 rst = help.listexts(_("'%s' is provided by the following "
3375 "extension:") % cmd, {ext: doc}, indent=4)
3389 "extension:") % cmd, {ext: doc}, indent=4)
3376 rst.append('\n')
3390 rst.append('\n')
3377 rst.append(_('use "hg help extensions" for information on enabling '
3391 rst.append(_('use "hg help extensions" for information on enabling '
3378 'extensions\n'))
3392 'extensions\n'))
3379 return rst
3393 return rst
3380
3394
3381
3395
3382 rst = []
3396 rst = []
3383 kw = opts.get('keyword')
3397 kw = opts.get('keyword')
3384 if kw:
3398 if kw:
3385 matches = help.topicmatch(kw)
3399 matches = help.topicmatch(kw)
3386 for t, title in (('topics', _('Topics')),
3400 for t, title in (('topics', _('Topics')),
3387 ('commands', _('Commands')),
3401 ('commands', _('Commands')),
3388 ('extensions', _('Extensions')),
3402 ('extensions', _('Extensions')),
3389 ('extensioncommands', _('Extension Commands'))):
3403 ('extensioncommands', _('Extension Commands'))):
3390 if matches[t]:
3404 if matches[t]:
3391 rst.append('%s:\n\n' % title)
3405 rst.append('%s:\n\n' % title)
3392 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3406 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3393 rst.append('\n')
3407 rst.append('\n')
3394 elif name and name != 'shortlist':
3408 elif name and name != 'shortlist':
3395 i = None
3409 i = None
3396 if unknowncmd:
3410 if unknowncmd:
3397 queries = (helpextcmd,)
3411 queries = (helpextcmd,)
3398 elif opts.get('extension'):
3412 elif opts.get('extension'):
3399 queries = (helpext,)
3413 queries = (helpext,)
3400 elif opts.get('command'):
3414 elif opts.get('command'):
3401 queries = (helpcmd,)
3415 queries = (helpcmd,)
3402 else:
3416 else:
3403 queries = (helptopic, helpcmd, helpext, helpextcmd)
3417 queries = (helptopic, helpcmd, helpext, helpextcmd)
3404 for f in queries:
3418 for f in queries:
3405 try:
3419 try:
3406 rst = f(name)
3420 rst = f(name)
3407 i = None
3421 i = None
3408 break
3422 break
3409 except error.UnknownCommand, inst:
3423 except error.UnknownCommand, inst:
3410 i = inst
3424 i = inst
3411 if i:
3425 if i:
3412 raise i
3426 raise i
3413 else:
3427 else:
3414 # program name
3428 # program name
3415 if not ui.quiet:
3429 if not ui.quiet:
3416 rst = [_("Mercurial Distributed SCM\n"), '\n']
3430 rst = [_("Mercurial Distributed SCM\n"), '\n']
3417 rst.extend(helplist())
3431 rst.extend(helplist())
3418
3432
3419 keep = ui.verbose and ['verbose'] or []
3433 keep = ui.verbose and ['verbose'] or []
3420 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3434 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3421 ui.write(formatted)
3435 ui.write(formatted)
3422
3436
3423
3437
3424 @command('identify|id',
3438 @command('identify|id',
3425 [('r', 'rev', '',
3439 [('r', 'rev', '',
3426 _('identify the specified revision'), _('REV')),
3440 _('identify the specified revision'), _('REV')),
3427 ('n', 'num', None, _('show local revision number')),
3441 ('n', 'num', None, _('show local revision number')),
3428 ('i', 'id', None, _('show global revision id')),
3442 ('i', 'id', None, _('show global revision id')),
3429 ('b', 'branch', None, _('show branch')),
3443 ('b', 'branch', None, _('show branch')),
3430 ('t', 'tags', None, _('show tags')),
3444 ('t', 'tags', None, _('show tags')),
3431 ('B', 'bookmarks', None, _('show bookmarks')),
3445 ('B', 'bookmarks', None, _('show bookmarks')),
3432 ] + remoteopts,
3446 ] + remoteopts,
3433 _('[-nibtB] [-r REV] [SOURCE]'))
3447 _('[-nibtB] [-r REV] [SOURCE]'))
3434 def identify(ui, repo, source=None, rev=None,
3448 def identify(ui, repo, source=None, rev=None,
3435 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3449 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3436 """identify the working copy or specified revision
3450 """identify the working copy or specified revision
3437
3451
3438 Print a summary identifying the repository state at REV using one or
3452 Print a summary identifying the repository state at REV using one or
3439 two parent hash identifiers, followed by a "+" if the working
3453 two parent hash identifiers, followed by a "+" if the working
3440 directory has uncommitted changes, the branch name (if not default),
3454 directory has uncommitted changes, the branch name (if not default),
3441 a list of tags, and a list of bookmarks.
3455 a list of tags, and a list of bookmarks.
3442
3456
3443 When REV is not given, print a summary of the current state of the
3457 When REV is not given, print a summary of the current state of the
3444 repository.
3458 repository.
3445
3459
3446 Specifying a path to a repository root or Mercurial bundle will
3460 Specifying a path to a repository root or Mercurial bundle will
3447 cause lookup to operate on that repository/bundle.
3461 cause lookup to operate on that repository/bundle.
3448
3462
3449 .. container:: verbose
3463 .. container:: verbose
3450
3464
3451 Examples:
3465 Examples:
3452
3466
3453 - generate a build identifier for the working directory::
3467 - generate a build identifier for the working directory::
3454
3468
3455 hg id --id > build-id.dat
3469 hg id --id > build-id.dat
3456
3470
3457 - find the revision corresponding to a tag::
3471 - find the revision corresponding to a tag::
3458
3472
3459 hg id -n -r 1.3
3473 hg id -n -r 1.3
3460
3474
3461 - check the most recent revision of a remote repository::
3475 - check the most recent revision of a remote repository::
3462
3476
3463 hg id -r tip http://selenic.com/hg/
3477 hg id -r tip http://selenic.com/hg/
3464
3478
3465 Returns 0 if successful.
3479 Returns 0 if successful.
3466 """
3480 """
3467
3481
3468 if not repo and not source:
3482 if not repo and not source:
3469 raise util.Abort(_("there is no Mercurial repository here "
3483 raise util.Abort(_("there is no Mercurial repository here "
3470 "(.hg not found)"))
3484 "(.hg not found)"))
3471
3485
3472 hexfunc = ui.debugflag and hex or short
3486 hexfunc = ui.debugflag and hex or short
3473 default = not (num or id or branch or tags or bookmarks)
3487 default = not (num or id or branch or tags or bookmarks)
3474 output = []
3488 output = []
3475 revs = []
3489 revs = []
3476
3490
3477 if source:
3491 if source:
3478 source, branches = hg.parseurl(ui.expandpath(source))
3492 source, branches = hg.parseurl(ui.expandpath(source))
3479 peer = hg.peer(ui, opts, source)
3493 peer = hg.peer(ui, opts, source)
3480 repo = peer.local()
3494 repo = peer.local()
3481 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3495 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3482
3496
3483 if not repo:
3497 if not repo:
3484 if num or branch or tags:
3498 if num or branch or tags:
3485 raise util.Abort(
3499 raise util.Abort(
3486 _("can't query remote revision number, branch, or tags"))
3500 _("can't query remote revision number, branch, or tags"))
3487 if not rev and revs:
3501 if not rev and revs:
3488 rev = revs[0]
3502 rev = revs[0]
3489 if not rev:
3503 if not rev:
3490 rev = "tip"
3504 rev = "tip"
3491
3505
3492 remoterev = peer.lookup(rev)
3506 remoterev = peer.lookup(rev)
3493 if default or id:
3507 if default or id:
3494 output = [hexfunc(remoterev)]
3508 output = [hexfunc(remoterev)]
3495
3509
3496 def getbms():
3510 def getbms():
3497 bms = []
3511 bms = []
3498
3512
3499 if 'bookmarks' in peer.listkeys('namespaces'):
3513 if 'bookmarks' in peer.listkeys('namespaces'):
3500 hexremoterev = hex(remoterev)
3514 hexremoterev = hex(remoterev)
3501 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3515 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3502 if bmr == hexremoterev]
3516 if bmr == hexremoterev]
3503
3517
3504 return bms
3518 return bms
3505
3519
3506 if bookmarks:
3520 if bookmarks:
3507 output.extend(getbms())
3521 output.extend(getbms())
3508 elif default and not ui.quiet:
3522 elif default and not ui.quiet:
3509 # multiple bookmarks for a single parent separated by '/'
3523 # multiple bookmarks for a single parent separated by '/'
3510 bm = '/'.join(getbms())
3524 bm = '/'.join(getbms())
3511 if bm:
3525 if bm:
3512 output.append(bm)
3526 output.append(bm)
3513 else:
3527 else:
3514 if not rev:
3528 if not rev:
3515 ctx = repo[None]
3529 ctx = repo[None]
3516 parents = ctx.parents()
3530 parents = ctx.parents()
3517 changed = ""
3531 changed = ""
3518 if default or id or num:
3532 if default or id or num:
3519 if (util.any(repo.status())
3533 if (util.any(repo.status())
3520 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3534 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3521 changed = '+'
3535 changed = '+'
3522 if default or id:
3536 if default or id:
3523 output = ["%s%s" %
3537 output = ["%s%s" %
3524 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3538 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3525 if num:
3539 if num:
3526 output.append("%s%s" %
3540 output.append("%s%s" %
3527 ('+'.join([str(p.rev()) for p in parents]), changed))
3541 ('+'.join([str(p.rev()) for p in parents]), changed))
3528 else:
3542 else:
3529 ctx = scmutil.revsingle(repo, rev)
3543 ctx = scmutil.revsingle(repo, rev)
3530 if default or id:
3544 if default or id:
3531 output = [hexfunc(ctx.node())]
3545 output = [hexfunc(ctx.node())]
3532 if num:
3546 if num:
3533 output.append(str(ctx.rev()))
3547 output.append(str(ctx.rev()))
3534
3548
3535 if default and not ui.quiet:
3549 if default and not ui.quiet:
3536 b = ctx.branch()
3550 b = ctx.branch()
3537 if b != 'default':
3551 if b != 'default':
3538 output.append("(%s)" % b)
3552 output.append("(%s)" % b)
3539
3553
3540 # multiple tags for a single parent separated by '/'
3554 # multiple tags for a single parent separated by '/'
3541 t = '/'.join(ctx.tags())
3555 t = '/'.join(ctx.tags())
3542 if t:
3556 if t:
3543 output.append(t)
3557 output.append(t)
3544
3558
3545 # multiple bookmarks for a single parent separated by '/'
3559 # multiple bookmarks for a single parent separated by '/'
3546 bm = '/'.join(ctx.bookmarks())
3560 bm = '/'.join(ctx.bookmarks())
3547 if bm:
3561 if bm:
3548 output.append(bm)
3562 output.append(bm)
3549 else:
3563 else:
3550 if branch:
3564 if branch:
3551 output.append(ctx.branch())
3565 output.append(ctx.branch())
3552
3566
3553 if tags:
3567 if tags:
3554 output.extend(ctx.tags())
3568 output.extend(ctx.tags())
3555
3569
3556 if bookmarks:
3570 if bookmarks:
3557 output.extend(ctx.bookmarks())
3571 output.extend(ctx.bookmarks())
3558
3572
3559 ui.write("%s\n" % ' '.join(output))
3573 ui.write("%s\n" % ' '.join(output))
3560
3574
3561 @command('import|patch',
3575 @command('import|patch',
3562 [('p', 'strip', 1,
3576 [('p', 'strip', 1,
3563 _('directory strip option for patch. This has the same '
3577 _('directory strip option for patch. This has the same '
3564 'meaning as the corresponding patch option'), _('NUM')),
3578 'meaning as the corresponding patch option'), _('NUM')),
3565 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3579 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3566 ('e', 'edit', False, _('invoke editor on commit messages')),
3580 ('e', 'edit', False, _('invoke editor on commit messages')),
3567 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3581 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3568 ('', 'no-commit', None,
3582 ('', 'no-commit', None,
3569 _("don't commit, just update the working directory")),
3583 _("don't commit, just update the working directory")),
3570 ('', 'bypass', None,
3584 ('', 'bypass', None,
3571 _("apply patch without touching the working directory")),
3585 _("apply patch without touching the working directory")),
3572 ('', 'exact', None,
3586 ('', 'exact', None,
3573 _('apply patch to the nodes from which it was generated')),
3587 _('apply patch to the nodes from which it was generated')),
3574 ('', 'import-branch', None,
3588 ('', 'import-branch', None,
3575 _('use any branch information in patch (implied by --exact)'))] +
3589 _('use any branch information in patch (implied by --exact)'))] +
3576 commitopts + commitopts2 + similarityopts,
3590 commitopts + commitopts2 + similarityopts,
3577 _('[OPTION]... PATCH...'))
3591 _('[OPTION]... PATCH...'))
3578 def import_(ui, repo, patch1=None, *patches, **opts):
3592 def import_(ui, repo, patch1=None, *patches, **opts):
3579 """import an ordered set of patches
3593 """import an ordered set of patches
3580
3594
3581 Import a list of patches and commit them individually (unless
3595 Import a list of patches and commit them individually (unless
3582 --no-commit is specified).
3596 --no-commit is specified).
3583
3597
3584 If there are outstanding changes in the working directory, import
3598 If there are outstanding changes in the working directory, import
3585 will abort unless given the -f/--force flag.
3599 will abort unless given the -f/--force flag.
3586
3600
3587 You can import a patch straight from a mail message. Even patches
3601 You can import a patch straight from a mail message. Even patches
3588 as attachments work (to use the body part, it must have type
3602 as attachments work (to use the body part, it must have type
3589 text/plain or text/x-patch). From and Subject headers of email
3603 text/plain or text/x-patch). From and Subject headers of email
3590 message are used as default committer and commit message. All
3604 message are used as default committer and commit message. All
3591 text/plain body parts before first diff are added to commit
3605 text/plain body parts before first diff are added to commit
3592 message.
3606 message.
3593
3607
3594 If the imported patch was generated by :hg:`export`, user and
3608 If the imported patch was generated by :hg:`export`, user and
3595 description from patch override values from message headers and
3609 description from patch override values from message headers and
3596 body. Values given on command line with -m/--message and -u/--user
3610 body. Values given on command line with -m/--message and -u/--user
3597 override these.
3611 override these.
3598
3612
3599 If --exact is specified, import will set the working directory to
3613 If --exact is specified, import will set the working directory to
3600 the parent of each patch before applying it, and will abort if the
3614 the parent of each patch before applying it, and will abort if the
3601 resulting changeset has a different ID than the one recorded in
3615 resulting changeset has a different ID than the one recorded in
3602 the patch. This may happen due to character set problems or other
3616 the patch. This may happen due to character set problems or other
3603 deficiencies in the text patch format.
3617 deficiencies in the text patch format.
3604
3618
3605 Use --bypass to apply and commit patches directly to the
3619 Use --bypass to apply and commit patches directly to the
3606 repository, not touching the working directory. Without --exact,
3620 repository, not touching the working directory. Without --exact,
3607 patches will be applied on top of the working directory parent
3621 patches will be applied on top of the working directory parent
3608 revision.
3622 revision.
3609
3623
3610 With -s/--similarity, hg will attempt to discover renames and
3624 With -s/--similarity, hg will attempt to discover renames and
3611 copies in the patch in the same way as :hg:`addremove`.
3625 copies in the patch in the same way as :hg:`addremove`.
3612
3626
3613 To read a patch from standard input, use "-" as the patch name. If
3627 To read a patch from standard input, use "-" as the patch name. If
3614 a URL is specified, the patch will be downloaded from it.
3628 a URL is specified, the patch will be downloaded from it.
3615 See :hg:`help dates` for a list of formats valid for -d/--date.
3629 See :hg:`help dates` for a list of formats valid for -d/--date.
3616
3630
3617 .. container:: verbose
3631 .. container:: verbose
3618
3632
3619 Examples:
3633 Examples:
3620
3634
3621 - import a traditional patch from a website and detect renames::
3635 - import a traditional patch from a website and detect renames::
3622
3636
3623 hg import -s 80 http://example.com/bugfix.patch
3637 hg import -s 80 http://example.com/bugfix.patch
3624
3638
3625 - import a changeset from an hgweb server::
3639 - import a changeset from an hgweb server::
3626
3640
3627 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3641 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3628
3642
3629 - import all the patches in an Unix-style mbox::
3643 - import all the patches in an Unix-style mbox::
3630
3644
3631 hg import incoming-patches.mbox
3645 hg import incoming-patches.mbox
3632
3646
3633 - attempt to exactly restore an exported changeset (not always
3647 - attempt to exactly restore an exported changeset (not always
3634 possible)::
3648 possible)::
3635
3649
3636 hg import --exact proposed-fix.patch
3650 hg import --exact proposed-fix.patch
3637
3651
3638 Returns 0 on success.
3652 Returns 0 on success.
3639 """
3653 """
3640
3654
3641 if not patch1:
3655 if not patch1:
3642 raise util.Abort(_('need at least one patch to import'))
3656 raise util.Abort(_('need at least one patch to import'))
3643
3657
3644 patches = (patch1,) + patches
3658 patches = (patch1,) + patches
3645
3659
3646 date = opts.get('date')
3660 date = opts.get('date')
3647 if date:
3661 if date:
3648 opts['date'] = util.parsedate(date)
3662 opts['date'] = util.parsedate(date)
3649
3663
3650 editor = cmdutil.commiteditor
3664 editor = cmdutil.commiteditor
3651 if opts.get('edit'):
3665 if opts.get('edit'):
3652 editor = cmdutil.commitforceeditor
3666 editor = cmdutil.commitforceeditor
3653
3667
3654 update = not opts.get('bypass')
3668 update = not opts.get('bypass')
3655 if not update and opts.get('no_commit'):
3669 if not update and opts.get('no_commit'):
3656 raise util.Abort(_('cannot use --no-commit with --bypass'))
3670 raise util.Abort(_('cannot use --no-commit with --bypass'))
3657 try:
3671 try:
3658 sim = float(opts.get('similarity') or 0)
3672 sim = float(opts.get('similarity') or 0)
3659 except ValueError:
3673 except ValueError:
3660 raise util.Abort(_('similarity must be a number'))
3674 raise util.Abort(_('similarity must be a number'))
3661 if sim < 0 or sim > 100:
3675 if sim < 0 or sim > 100:
3662 raise util.Abort(_('similarity must be between 0 and 100'))
3676 raise util.Abort(_('similarity must be between 0 and 100'))
3663 if sim and not update:
3677 if sim and not update:
3664 raise util.Abort(_('cannot use --similarity with --bypass'))
3678 raise util.Abort(_('cannot use --similarity with --bypass'))
3665
3679
3666 if (opts.get('exact') or not opts.get('force')) and update:
3680 if (opts.get('exact') or not opts.get('force')) and update:
3667 cmdutil.bailifchanged(repo)
3681 cmdutil.bailifchanged(repo)
3668
3682
3669 base = opts["base"]
3683 base = opts["base"]
3670 strip = opts["strip"]
3684 strip = opts["strip"]
3671 wlock = lock = tr = None
3685 wlock = lock = tr = None
3672 msgs = []
3686 msgs = []
3673
3687
3674 def checkexact(repo, n, nodeid):
3688 def checkexact(repo, n, nodeid):
3675 if opts.get('exact') and hex(n) != nodeid:
3689 if opts.get('exact') and hex(n) != nodeid:
3676 repo.rollback()
3690 repo.rollback()
3677 raise util.Abort(_('patch is damaged or loses information'))
3691 raise util.Abort(_('patch is damaged or loses information'))
3678
3692
3679 def tryone(ui, hunk, parents):
3693 def tryone(ui, hunk, parents):
3680 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3694 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3681 patch.extract(ui, hunk)
3695 patch.extract(ui, hunk)
3682
3696
3683 if not tmpname:
3697 if not tmpname:
3684 return (None, None)
3698 return (None, None)
3685 msg = _('applied to working directory')
3699 msg = _('applied to working directory')
3686
3700
3687 try:
3701 try:
3688 cmdline_message = cmdutil.logmessage(ui, opts)
3702 cmdline_message = cmdutil.logmessage(ui, opts)
3689 if cmdline_message:
3703 if cmdline_message:
3690 # pickup the cmdline msg
3704 # pickup the cmdline msg
3691 message = cmdline_message
3705 message = cmdline_message
3692 elif message:
3706 elif message:
3693 # pickup the patch msg
3707 # pickup the patch msg
3694 message = message.strip()
3708 message = message.strip()
3695 else:
3709 else:
3696 # launch the editor
3710 # launch the editor
3697 message = None
3711 message = None
3698 ui.debug('message:\n%s\n' % message)
3712 ui.debug('message:\n%s\n' % message)
3699
3713
3700 if len(parents) == 1:
3714 if len(parents) == 1:
3701 parents.append(repo[nullid])
3715 parents.append(repo[nullid])
3702 if opts.get('exact'):
3716 if opts.get('exact'):
3703 if not nodeid or not p1:
3717 if not nodeid or not p1:
3704 raise util.Abort(_('not a Mercurial patch'))
3718 raise util.Abort(_('not a Mercurial patch'))
3705 p1 = repo[p1]
3719 p1 = repo[p1]
3706 p2 = repo[p2 or nullid]
3720 p2 = repo[p2 or nullid]
3707 elif p2:
3721 elif p2:
3708 try:
3722 try:
3709 p1 = repo[p1]
3723 p1 = repo[p1]
3710 p2 = repo[p2]
3724 p2 = repo[p2]
3711 # Without any options, consider p2 only if the
3725 # Without any options, consider p2 only if the
3712 # patch is being applied on top of the recorded
3726 # patch is being applied on top of the recorded
3713 # first parent.
3727 # first parent.
3714 if p1 != parents[0]:
3728 if p1 != parents[0]:
3715 p1 = parents[0]
3729 p1 = parents[0]
3716 p2 = repo[nullid]
3730 p2 = repo[nullid]
3717 except error.RepoError:
3731 except error.RepoError:
3718 p1, p2 = parents
3732 p1, p2 = parents
3719 else:
3733 else:
3720 p1, p2 = parents
3734 p1, p2 = parents
3721
3735
3722 n = None
3736 n = None
3723 if update:
3737 if update:
3724 if p1 != parents[0]:
3738 if p1 != parents[0]:
3725 hg.clean(repo, p1.node())
3739 hg.clean(repo, p1.node())
3726 if p2 != parents[1]:
3740 if p2 != parents[1]:
3727 repo.setparents(p1.node(), p2.node())
3741 repo.setparents(p1.node(), p2.node())
3728
3742
3729 if opts.get('exact') or opts.get('import_branch'):
3743 if opts.get('exact') or opts.get('import_branch'):
3730 repo.dirstate.setbranch(branch or 'default')
3744 repo.dirstate.setbranch(branch or 'default')
3731
3745
3732 files = set()
3746 files = set()
3733 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3747 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3734 eolmode=None, similarity=sim / 100.0)
3748 eolmode=None, similarity=sim / 100.0)
3735 files = list(files)
3749 files = list(files)
3736 if opts.get('no_commit'):
3750 if opts.get('no_commit'):
3737 if message:
3751 if message:
3738 msgs.append(message)
3752 msgs.append(message)
3739 else:
3753 else:
3740 if opts.get('exact') or p2:
3754 if opts.get('exact') or p2:
3741 # If you got here, you either use --force and know what
3755 # If you got here, you either use --force and know what
3742 # you are doing or used --exact or a merge patch while
3756 # you are doing or used --exact or a merge patch while
3743 # being updated to its first parent.
3757 # being updated to its first parent.
3744 m = None
3758 m = None
3745 else:
3759 else:
3746 m = scmutil.matchfiles(repo, files or [])
3760 m = scmutil.matchfiles(repo, files or [])
3747 n = repo.commit(message, opts.get('user') or user,
3761 n = repo.commit(message, opts.get('user') or user,
3748 opts.get('date') or date, match=m,
3762 opts.get('date') or date, match=m,
3749 editor=editor)
3763 editor=editor)
3750 checkexact(repo, n, nodeid)
3764 checkexact(repo, n, nodeid)
3751 else:
3765 else:
3752 if opts.get('exact') or opts.get('import_branch'):
3766 if opts.get('exact') or opts.get('import_branch'):
3753 branch = branch or 'default'
3767 branch = branch or 'default'
3754 else:
3768 else:
3755 branch = p1.branch()
3769 branch = p1.branch()
3756 store = patch.filestore()
3770 store = patch.filestore()
3757 try:
3771 try:
3758 files = set()
3772 files = set()
3759 try:
3773 try:
3760 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3774 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3761 files, eolmode=None)
3775 files, eolmode=None)
3762 except patch.PatchError, e:
3776 except patch.PatchError, e:
3763 raise util.Abort(str(e))
3777 raise util.Abort(str(e))
3764 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3778 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3765 message,
3779 message,
3766 opts.get('user') or user,
3780 opts.get('user') or user,
3767 opts.get('date') or date,
3781 opts.get('date') or date,
3768 branch, files, store,
3782 branch, files, store,
3769 editor=cmdutil.commiteditor)
3783 editor=cmdutil.commiteditor)
3770 repo.savecommitmessage(memctx.description())
3784 repo.savecommitmessage(memctx.description())
3771 n = memctx.commit()
3785 n = memctx.commit()
3772 checkexact(repo, n, nodeid)
3786 checkexact(repo, n, nodeid)
3773 finally:
3787 finally:
3774 store.close()
3788 store.close()
3775 if n:
3789 if n:
3776 # i18n: refers to a short changeset id
3790 # i18n: refers to a short changeset id
3777 msg = _('created %s') % short(n)
3791 msg = _('created %s') % short(n)
3778 return (msg, n)
3792 return (msg, n)
3779 finally:
3793 finally:
3780 os.unlink(tmpname)
3794 os.unlink(tmpname)
3781
3795
3782 try:
3796 try:
3783 try:
3797 try:
3784 wlock = repo.wlock()
3798 wlock = repo.wlock()
3785 if not opts.get('no_commit'):
3799 if not opts.get('no_commit'):
3786 lock = repo.lock()
3800 lock = repo.lock()
3787 tr = repo.transaction('import')
3801 tr = repo.transaction('import')
3788 parents = repo.parents()
3802 parents = repo.parents()
3789 for patchurl in patches:
3803 for patchurl in patches:
3790 if patchurl == '-':
3804 if patchurl == '-':
3791 ui.status(_('applying patch from stdin\n'))
3805 ui.status(_('applying patch from stdin\n'))
3792 patchfile = ui.fin
3806 patchfile = ui.fin
3793 patchurl = 'stdin' # for error message
3807 patchurl = 'stdin' # for error message
3794 else:
3808 else:
3795 patchurl = os.path.join(base, patchurl)
3809 patchurl = os.path.join(base, patchurl)
3796 ui.status(_('applying %s\n') % patchurl)
3810 ui.status(_('applying %s\n') % patchurl)
3797 patchfile = url.open(ui, patchurl)
3811 patchfile = url.open(ui, patchurl)
3798
3812
3799 haspatch = False
3813 haspatch = False
3800 for hunk in patch.split(patchfile):
3814 for hunk in patch.split(patchfile):
3801 (msg, node) = tryone(ui, hunk, parents)
3815 (msg, node) = tryone(ui, hunk, parents)
3802 if msg:
3816 if msg:
3803 haspatch = True
3817 haspatch = True
3804 ui.note(msg + '\n')
3818 ui.note(msg + '\n')
3805 if update or opts.get('exact'):
3819 if update or opts.get('exact'):
3806 parents = repo.parents()
3820 parents = repo.parents()
3807 else:
3821 else:
3808 parents = [repo[node]]
3822 parents = [repo[node]]
3809
3823
3810 if not haspatch:
3824 if not haspatch:
3811 raise util.Abort(_('%s: no diffs found') % patchurl)
3825 raise util.Abort(_('%s: no diffs found') % patchurl)
3812
3826
3813 if tr:
3827 if tr:
3814 tr.close()
3828 tr.close()
3815 if msgs:
3829 if msgs:
3816 repo.savecommitmessage('\n* * *\n'.join(msgs))
3830 repo.savecommitmessage('\n* * *\n'.join(msgs))
3817 except: # re-raises
3831 except: # re-raises
3818 # wlock.release() indirectly calls dirstate.write(): since
3832 # wlock.release() indirectly calls dirstate.write(): since
3819 # we're crashing, we do not want to change the working dir
3833 # we're crashing, we do not want to change the working dir
3820 # parent after all, so make sure it writes nothing
3834 # parent after all, so make sure it writes nothing
3821 repo.dirstate.invalidate()
3835 repo.dirstate.invalidate()
3822 raise
3836 raise
3823 finally:
3837 finally:
3824 if tr:
3838 if tr:
3825 tr.release()
3839 tr.release()
3826 release(lock, wlock)
3840 release(lock, wlock)
3827
3841
3828 @command('incoming|in',
3842 @command('incoming|in',
3829 [('f', 'force', None,
3843 [('f', 'force', None,
3830 _('run even if remote repository is unrelated')),
3844 _('run even if remote repository is unrelated')),
3831 ('n', 'newest-first', None, _('show newest record first')),
3845 ('n', 'newest-first', None, _('show newest record first')),
3832 ('', 'bundle', '',
3846 ('', 'bundle', '',
3833 _('file to store the bundles into'), _('FILE')),
3847 _('file to store the bundles into'), _('FILE')),
3834 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3848 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3835 ('B', 'bookmarks', False, _("compare bookmarks")),
3849 ('B', 'bookmarks', False, _("compare bookmarks")),
3836 ('b', 'branch', [],
3850 ('b', 'branch', [],
3837 _('a specific branch you would like to pull'), _('BRANCH')),
3851 _('a specific branch you would like to pull'), _('BRANCH')),
3838 ] + logopts + remoteopts + subrepoopts,
3852 ] + logopts + remoteopts + subrepoopts,
3839 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3853 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3840 def incoming(ui, repo, source="default", **opts):
3854 def incoming(ui, repo, source="default", **opts):
3841 """show new changesets found in source
3855 """show new changesets found in source
3842
3856
3843 Show new changesets found in the specified path/URL or the default
3857 Show new changesets found in the specified path/URL or the default
3844 pull location. These are the changesets that would have been pulled
3858 pull location. These are the changesets that would have been pulled
3845 if a pull at the time you issued this command.
3859 if a pull at the time you issued this command.
3846
3860
3847 For remote repository, using --bundle avoids downloading the
3861 For remote repository, using --bundle avoids downloading the
3848 changesets twice if the incoming is followed by a pull.
3862 changesets twice if the incoming is followed by a pull.
3849
3863
3850 See pull for valid source format details.
3864 See pull for valid source format details.
3851
3865
3852 Returns 0 if there are incoming changes, 1 otherwise.
3866 Returns 0 if there are incoming changes, 1 otherwise.
3853 """
3867 """
3854 if opts.get('graph'):
3868 if opts.get('graph'):
3855 cmdutil.checkunsupportedgraphflags([], opts)
3869 cmdutil.checkunsupportedgraphflags([], opts)
3856 def display(other, chlist, displayer):
3870 def display(other, chlist, displayer):
3857 revdag = cmdutil.graphrevs(other, chlist, opts)
3871 revdag = cmdutil.graphrevs(other, chlist, opts)
3858 showparents = [ctx.node() for ctx in repo[None].parents()]
3872 showparents = [ctx.node() for ctx in repo[None].parents()]
3859 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3873 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3860 graphmod.asciiedges)
3874 graphmod.asciiedges)
3861
3875
3862 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3876 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3863 return 0
3877 return 0
3864
3878
3865 if opts.get('bundle') and opts.get('subrepos'):
3879 if opts.get('bundle') and opts.get('subrepos'):
3866 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3880 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3867
3881
3868 if opts.get('bookmarks'):
3882 if opts.get('bookmarks'):
3869 source, branches = hg.parseurl(ui.expandpath(source),
3883 source, branches = hg.parseurl(ui.expandpath(source),
3870 opts.get('branch'))
3884 opts.get('branch'))
3871 other = hg.peer(repo, opts, source)
3885 other = hg.peer(repo, opts, source)
3872 if 'bookmarks' not in other.listkeys('namespaces'):
3886 if 'bookmarks' not in other.listkeys('namespaces'):
3873 ui.warn(_("remote doesn't support bookmarks\n"))
3887 ui.warn(_("remote doesn't support bookmarks\n"))
3874 return 0
3888 return 0
3875 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3889 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3876 return bookmarks.diff(ui, repo, other)
3890 return bookmarks.diff(ui, repo, other)
3877
3891
3878 repo._subtoppath = ui.expandpath(source)
3892 repo._subtoppath = ui.expandpath(source)
3879 try:
3893 try:
3880 return hg.incoming(ui, repo, source, opts)
3894 return hg.incoming(ui, repo, source, opts)
3881 finally:
3895 finally:
3882 del repo._subtoppath
3896 del repo._subtoppath
3883
3897
3884
3898
3885 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3899 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3886 def init(ui, dest=".", **opts):
3900 def init(ui, dest=".", **opts):
3887 """create a new repository in the given directory
3901 """create a new repository in the given directory
3888
3902
3889 Initialize a new repository in the given directory. If the given
3903 Initialize a new repository in the given directory. If the given
3890 directory does not exist, it will be created.
3904 directory does not exist, it will be created.
3891
3905
3892 If no directory is given, the current directory is used.
3906 If no directory is given, the current directory is used.
3893
3907
3894 It is possible to specify an ``ssh://`` URL as the destination.
3908 It is possible to specify an ``ssh://`` URL as the destination.
3895 See :hg:`help urls` for more information.
3909 See :hg:`help urls` for more information.
3896
3910
3897 Returns 0 on success.
3911 Returns 0 on success.
3898 """
3912 """
3899 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3913 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3900
3914
3901 @command('locate',
3915 @command('locate',
3902 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3916 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3903 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3917 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3904 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3918 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3905 ] + walkopts,
3919 ] + walkopts,
3906 _('[OPTION]... [PATTERN]...'))
3920 _('[OPTION]... [PATTERN]...'))
3907 def locate(ui, repo, *pats, **opts):
3921 def locate(ui, repo, *pats, **opts):
3908 """locate files matching specific patterns
3922 """locate files matching specific patterns
3909
3923
3910 Print files under Mercurial control in the working directory whose
3924 Print files under Mercurial control in the working directory whose
3911 names match the given patterns.
3925 names match the given patterns.
3912
3926
3913 By default, this command searches all directories in the working
3927 By default, this command searches all directories in the working
3914 directory. To search just the current directory and its
3928 directory. To search just the current directory and its
3915 subdirectories, use "--include .".
3929 subdirectories, use "--include .".
3916
3930
3917 If no patterns are given to match, this command prints the names
3931 If no patterns are given to match, this command prints the names
3918 of all files under Mercurial control in the working directory.
3932 of all files under Mercurial control in the working directory.
3919
3933
3920 If you want to feed the output of this command into the "xargs"
3934 If you want to feed the output of this command into the "xargs"
3921 command, use the -0 option to both this command and "xargs". This
3935 command, use the -0 option to both this command and "xargs". This
3922 will avoid the problem of "xargs" treating single filenames that
3936 will avoid the problem of "xargs" treating single filenames that
3923 contain whitespace as multiple filenames.
3937 contain whitespace as multiple filenames.
3924
3938
3925 Returns 0 if a match is found, 1 otherwise.
3939 Returns 0 if a match is found, 1 otherwise.
3926 """
3940 """
3927 end = opts.get('print0') and '\0' or '\n'
3941 end = opts.get('print0') and '\0' or '\n'
3928 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3942 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3929
3943
3930 ret = 1
3944 ret = 1
3931 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3945 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3932 m.bad = lambda x, y: False
3946 m.bad = lambda x, y: False
3933 for abs in repo[rev].walk(m):
3947 for abs in repo[rev].walk(m):
3934 if not rev and abs not in repo.dirstate:
3948 if not rev and abs not in repo.dirstate:
3935 continue
3949 continue
3936 if opts.get('fullpath'):
3950 if opts.get('fullpath'):
3937 ui.write(repo.wjoin(abs), end)
3951 ui.write(repo.wjoin(abs), end)
3938 else:
3952 else:
3939 ui.write(((pats and m.rel(abs)) or abs), end)
3953 ui.write(((pats and m.rel(abs)) or abs), end)
3940 ret = 0
3954 ret = 0
3941
3955
3942 return ret
3956 return ret
3943
3957
3944 @command('^log|history',
3958 @command('^log|history',
3945 [('f', 'follow', None,
3959 [('f', 'follow', None,
3946 _('follow changeset history, or file history across copies and renames')),
3960 _('follow changeset history, or file history across copies and renames')),
3947 ('', 'follow-first', None,
3961 ('', 'follow-first', None,
3948 _('only follow the first parent of merge changesets (DEPRECATED)')),
3962 _('only follow the first parent of merge changesets (DEPRECATED)')),
3949 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3963 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3950 ('C', 'copies', None, _('show copied files')),
3964 ('C', 'copies', None, _('show copied files')),
3951 ('k', 'keyword', [],
3965 ('k', 'keyword', [],
3952 _('do case-insensitive search for a given text'), _('TEXT')),
3966 _('do case-insensitive search for a given text'), _('TEXT')),
3953 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3967 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3954 ('', 'removed', None, _('include revisions where files were removed')),
3968 ('', 'removed', None, _('include revisions where files were removed')),
3955 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3969 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3956 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3970 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3957 ('', 'only-branch', [],
3971 ('', 'only-branch', [],
3958 _('show only changesets within the given named branch (DEPRECATED)'),
3972 _('show only changesets within the given named branch (DEPRECATED)'),
3959 _('BRANCH')),
3973 _('BRANCH')),
3960 ('b', 'branch', [],
3974 ('b', 'branch', [],
3961 _('show changesets within the given named branch'), _('BRANCH')),
3975 _('show changesets within the given named branch'), _('BRANCH')),
3962 ('P', 'prune', [],
3976 ('P', 'prune', [],
3963 _('do not display revision or any of its ancestors'), _('REV')),
3977 _('do not display revision or any of its ancestors'), _('REV')),
3964 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3978 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3965 ] + logopts + walkopts,
3979 ] + logopts + walkopts,
3966 _('[OPTION]... [FILE]'))
3980 _('[OPTION]... [FILE]'))
3967 def log(ui, repo, *pats, **opts):
3981 def log(ui, repo, *pats, **opts):
3968 """show revision history of entire repository or files
3982 """show revision history of entire repository or files
3969
3983
3970 Print the revision history of the specified files or the entire
3984 Print the revision history of the specified files or the entire
3971 project.
3985 project.
3972
3986
3973 If no revision range is specified, the default is ``tip:0`` unless
3987 If no revision range is specified, the default is ``tip:0`` unless
3974 --follow is set, in which case the working directory parent is
3988 --follow is set, in which case the working directory parent is
3975 used as the starting revision.
3989 used as the starting revision.
3976
3990
3977 File history is shown without following rename or copy history of
3991 File history is shown without following rename or copy history of
3978 files. Use -f/--follow with a filename to follow history across
3992 files. Use -f/--follow with a filename to follow history across
3979 renames and copies. --follow without a filename will only show
3993 renames and copies. --follow without a filename will only show
3980 ancestors or descendants of the starting revision.
3994 ancestors or descendants of the starting revision.
3981
3995
3982 By default this command prints revision number and changeset id,
3996 By default this command prints revision number and changeset id,
3983 tags, non-trivial parents, user, date and time, and a summary for
3997 tags, non-trivial parents, user, date and time, and a summary for
3984 each commit. When the -v/--verbose switch is used, the list of
3998 each commit. When the -v/--verbose switch is used, the list of
3985 changed files and full commit message are shown.
3999 changed files and full commit message are shown.
3986
4000
3987 .. note::
4001 .. note::
3988 log -p/--patch may generate unexpected diff output for merge
4002 log -p/--patch may generate unexpected diff output for merge
3989 changesets, as it will only compare the merge changeset against
4003 changesets, as it will only compare the merge changeset against
3990 its first parent. Also, only files different from BOTH parents
4004 its first parent. Also, only files different from BOTH parents
3991 will appear in files:.
4005 will appear in files:.
3992
4006
3993 .. note::
4007 .. note::
3994 for performance reasons, log FILE may omit duplicate changes
4008 for performance reasons, log FILE may omit duplicate changes
3995 made on branches and will not show deletions. To see all
4009 made on branches and will not show deletions. To see all
3996 changes including duplicates and deletions, use the --removed
4010 changes including duplicates and deletions, use the --removed
3997 switch.
4011 switch.
3998
4012
3999 .. container:: verbose
4013 .. container:: verbose
4000
4014
4001 Some examples:
4015 Some examples:
4002
4016
4003 - changesets with full descriptions and file lists::
4017 - changesets with full descriptions and file lists::
4004
4018
4005 hg log -v
4019 hg log -v
4006
4020
4007 - changesets ancestral to the working directory::
4021 - changesets ancestral to the working directory::
4008
4022
4009 hg log -f
4023 hg log -f
4010
4024
4011 - last 10 commits on the current branch::
4025 - last 10 commits on the current branch::
4012
4026
4013 hg log -l 10 -b .
4027 hg log -l 10 -b .
4014
4028
4015 - changesets showing all modifications of a file, including removals::
4029 - changesets showing all modifications of a file, including removals::
4016
4030
4017 hg log --removed file.c
4031 hg log --removed file.c
4018
4032
4019 - all changesets that touch a directory, with diffs, excluding merges::
4033 - all changesets that touch a directory, with diffs, excluding merges::
4020
4034
4021 hg log -Mp lib/
4035 hg log -Mp lib/
4022
4036
4023 - all revision numbers that match a keyword::
4037 - all revision numbers that match a keyword::
4024
4038
4025 hg log -k bug --template "{rev}\\n"
4039 hg log -k bug --template "{rev}\\n"
4026
4040
4027 - check if a given changeset is included is a tagged release::
4041 - check if a given changeset is included is a tagged release::
4028
4042
4029 hg log -r "a21ccf and ancestor(1.9)"
4043 hg log -r "a21ccf and ancestor(1.9)"
4030
4044
4031 - find all changesets by some user in a date range::
4045 - find all changesets by some user in a date range::
4032
4046
4033 hg log -k alice -d "may 2008 to jul 2008"
4047 hg log -k alice -d "may 2008 to jul 2008"
4034
4048
4035 - summary of all changesets after the last tag::
4049 - summary of all changesets after the last tag::
4036
4050
4037 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4051 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4038
4052
4039 See :hg:`help dates` for a list of formats valid for -d/--date.
4053 See :hg:`help dates` for a list of formats valid for -d/--date.
4040
4054
4041 See :hg:`help revisions` and :hg:`help revsets` for more about
4055 See :hg:`help revisions` and :hg:`help revsets` for more about
4042 specifying revisions.
4056 specifying revisions.
4043
4057
4044 See :hg:`help templates` for more about pre-packaged styles and
4058 See :hg:`help templates` for more about pre-packaged styles and
4045 specifying custom templates.
4059 specifying custom templates.
4046
4060
4047 Returns 0 on success.
4061 Returns 0 on success.
4048 """
4062 """
4049 if opts.get('graph'):
4063 if opts.get('graph'):
4050 return cmdutil.graphlog(ui, repo, *pats, **opts)
4064 return cmdutil.graphlog(ui, repo, *pats, **opts)
4051
4065
4052 matchfn = scmutil.match(repo[None], pats, opts)
4066 matchfn = scmutil.match(repo[None], pats, opts)
4053 limit = cmdutil.loglimit(opts)
4067 limit = cmdutil.loglimit(opts)
4054 count = 0
4068 count = 0
4055
4069
4056 getrenamed, endrev = None, None
4070 getrenamed, endrev = None, None
4057 if opts.get('copies'):
4071 if opts.get('copies'):
4058 if opts.get('rev'):
4072 if opts.get('rev'):
4059 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4073 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4060 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4074 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4061
4075
4062 df = False
4076 df = False
4063 if opts["date"]:
4077 if opts["date"]:
4064 df = util.matchdate(opts["date"])
4078 df = util.matchdate(opts["date"])
4065
4079
4066 branches = opts.get('branch', []) + opts.get('only_branch', [])
4080 branches = opts.get('branch', []) + opts.get('only_branch', [])
4067 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4081 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4068
4082
4069 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4083 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4070 def prep(ctx, fns):
4084 def prep(ctx, fns):
4071 rev = ctx.rev()
4085 rev = ctx.rev()
4072 parents = [p for p in repo.changelog.parentrevs(rev)
4086 parents = [p for p in repo.changelog.parentrevs(rev)
4073 if p != nullrev]
4087 if p != nullrev]
4074 if opts.get('no_merges') and len(parents) == 2:
4088 if opts.get('no_merges') and len(parents) == 2:
4075 return
4089 return
4076 if opts.get('only_merges') and len(parents) != 2:
4090 if opts.get('only_merges') and len(parents) != 2:
4077 return
4091 return
4078 if opts.get('branch') and ctx.branch() not in opts['branch']:
4092 if opts.get('branch') and ctx.branch() not in opts['branch']:
4079 return
4093 return
4080 if not opts.get('hidden') and ctx.hidden():
4094 if not opts.get('hidden') and ctx.hidden():
4081 return
4095 return
4082 if df and not df(ctx.date()[0]):
4096 if df and not df(ctx.date()[0]):
4083 return
4097 return
4084
4098
4085 lower = encoding.lower
4099 lower = encoding.lower
4086 if opts.get('user'):
4100 if opts.get('user'):
4087 luser = lower(ctx.user())
4101 luser = lower(ctx.user())
4088 for k in [lower(x) for x in opts['user']]:
4102 for k in [lower(x) for x in opts['user']]:
4089 if (k in luser):
4103 if (k in luser):
4090 break
4104 break
4091 else:
4105 else:
4092 return
4106 return
4093 if opts.get('keyword'):
4107 if opts.get('keyword'):
4094 luser = lower(ctx.user())
4108 luser = lower(ctx.user())
4095 ldesc = lower(ctx.description())
4109 ldesc = lower(ctx.description())
4096 lfiles = lower(" ".join(ctx.files()))
4110 lfiles = lower(" ".join(ctx.files()))
4097 for k in [lower(x) for x in opts['keyword']]:
4111 for k in [lower(x) for x in opts['keyword']]:
4098 if (k in luser or k in ldesc or k in lfiles):
4112 if (k in luser or k in ldesc or k in lfiles):
4099 break
4113 break
4100 else:
4114 else:
4101 return
4115 return
4102
4116
4103 copies = None
4117 copies = None
4104 if getrenamed is not None and rev:
4118 if getrenamed is not None and rev:
4105 copies = []
4119 copies = []
4106 for fn in ctx.files():
4120 for fn in ctx.files():
4107 rename = getrenamed(fn, rev)
4121 rename = getrenamed(fn, rev)
4108 if rename:
4122 if rename:
4109 copies.append((fn, rename[0]))
4123 copies.append((fn, rename[0]))
4110
4124
4111 revmatchfn = None
4125 revmatchfn = None
4112 if opts.get('patch') or opts.get('stat'):
4126 if opts.get('patch') or opts.get('stat'):
4113 if opts.get('follow') or opts.get('follow_first'):
4127 if opts.get('follow') or opts.get('follow_first'):
4114 # note: this might be wrong when following through merges
4128 # note: this might be wrong when following through merges
4115 revmatchfn = scmutil.match(repo[None], fns, default='path')
4129 revmatchfn = scmutil.match(repo[None], fns, default='path')
4116 else:
4130 else:
4117 revmatchfn = matchfn
4131 revmatchfn = matchfn
4118
4132
4119 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4133 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4120
4134
4121 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4135 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4122 if count == limit:
4136 if count == limit:
4123 break
4137 break
4124 if displayer.flush(ctx.rev()):
4138 if displayer.flush(ctx.rev()):
4125 count += 1
4139 count += 1
4126 displayer.close()
4140 displayer.close()
4127
4141
4128 @command('manifest',
4142 @command('manifest',
4129 [('r', 'rev', '', _('revision to display'), _('REV')),
4143 [('r', 'rev', '', _('revision to display'), _('REV')),
4130 ('', 'all', False, _("list files from all revisions"))],
4144 ('', 'all', False, _("list files from all revisions"))],
4131 _('[-r REV]'))
4145 _('[-r REV]'))
4132 def manifest(ui, repo, node=None, rev=None, **opts):
4146 def manifest(ui, repo, node=None, rev=None, **opts):
4133 """output the current or given revision of the project manifest
4147 """output the current or given revision of the project manifest
4134
4148
4135 Print a list of version controlled files for the given revision.
4149 Print a list of version controlled files for the given revision.
4136 If no revision is given, the first parent of the working directory
4150 If no revision is given, the first parent of the working directory
4137 is used, or the null revision if no revision is checked out.
4151 is used, or the null revision if no revision is checked out.
4138
4152
4139 With -v, print file permissions, symlink and executable bits.
4153 With -v, print file permissions, symlink and executable bits.
4140 With --debug, print file revision hashes.
4154 With --debug, print file revision hashes.
4141
4155
4142 If option --all is specified, the list of all files from all revisions
4156 If option --all is specified, the list of all files from all revisions
4143 is printed. This includes deleted and renamed files.
4157 is printed. This includes deleted and renamed files.
4144
4158
4145 Returns 0 on success.
4159 Returns 0 on success.
4146 """
4160 """
4147 if opts.get('all'):
4161 if opts.get('all'):
4148 if rev or node:
4162 if rev or node:
4149 raise util.Abort(_("can't specify a revision with --all"))
4163 raise util.Abort(_("can't specify a revision with --all"))
4150
4164
4151 res = []
4165 res = []
4152 prefix = "data/"
4166 prefix = "data/"
4153 suffix = ".i"
4167 suffix = ".i"
4154 plen = len(prefix)
4168 plen = len(prefix)
4155 slen = len(suffix)
4169 slen = len(suffix)
4156 lock = repo.lock()
4170 lock = repo.lock()
4157 try:
4171 try:
4158 for fn, b, size in repo.store.datafiles():
4172 for fn, b, size in repo.store.datafiles():
4159 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4173 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4160 res.append(fn[plen:-slen])
4174 res.append(fn[plen:-slen])
4161 finally:
4175 finally:
4162 lock.release()
4176 lock.release()
4163 for f in sorted(res):
4177 for f in sorted(res):
4164 ui.write("%s\n" % f)
4178 ui.write("%s\n" % f)
4165 return
4179 return
4166
4180
4167 if rev and node:
4181 if rev and node:
4168 raise util.Abort(_("please specify just one revision"))
4182 raise util.Abort(_("please specify just one revision"))
4169
4183
4170 if not node:
4184 if not node:
4171 node = rev
4185 node = rev
4172
4186
4173 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4187 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4174 ctx = scmutil.revsingle(repo, node)
4188 ctx = scmutil.revsingle(repo, node)
4175 for f in ctx:
4189 for f in ctx:
4176 if ui.debugflag:
4190 if ui.debugflag:
4177 ui.write("%40s " % hex(ctx.manifest()[f]))
4191 ui.write("%40s " % hex(ctx.manifest()[f]))
4178 if ui.verbose:
4192 if ui.verbose:
4179 ui.write(decor[ctx.flags(f)])
4193 ui.write(decor[ctx.flags(f)])
4180 ui.write("%s\n" % f)
4194 ui.write("%s\n" % f)
4181
4195
4182 @command('^merge',
4196 @command('^merge',
4183 [('f', 'force', None, _('force a merge with outstanding changes')),
4197 [('f', 'force', None, _('force a merge with outstanding changes')),
4184 ('r', 'rev', '', _('revision to merge'), _('REV')),
4198 ('r', 'rev', '', _('revision to merge'), _('REV')),
4185 ('P', 'preview', None,
4199 ('P', 'preview', None,
4186 _('review revisions to merge (no merge is performed)'))
4200 _('review revisions to merge (no merge is performed)'))
4187 ] + mergetoolopts,
4201 ] + mergetoolopts,
4188 _('[-P] [-f] [[-r] REV]'))
4202 _('[-P] [-f] [[-r] REV]'))
4189 def merge(ui, repo, node=None, **opts):
4203 def merge(ui, repo, node=None, **opts):
4190 """merge working directory with another revision
4204 """merge working directory with another revision
4191
4205
4192 The current working directory is updated with all changes made in
4206 The current working directory is updated with all changes made in
4193 the requested revision since the last common predecessor revision.
4207 the requested revision since the last common predecessor revision.
4194
4208
4195 Files that changed between either parent are marked as changed for
4209 Files that changed between either parent are marked as changed for
4196 the next commit and a commit must be performed before any further
4210 the next commit and a commit must be performed before any further
4197 updates to the repository are allowed. The next commit will have
4211 updates to the repository are allowed. The next commit will have
4198 two parents.
4212 two parents.
4199
4213
4200 ``--tool`` can be used to specify the merge tool used for file
4214 ``--tool`` can be used to specify the merge tool used for file
4201 merges. It overrides the HGMERGE environment variable and your
4215 merges. It overrides the HGMERGE environment variable and your
4202 configuration files. See :hg:`help merge-tools` for options.
4216 configuration files. See :hg:`help merge-tools` for options.
4203
4217
4204 If no revision is specified, the working directory's parent is a
4218 If no revision is specified, the working directory's parent is a
4205 head revision, and the current branch contains exactly one other
4219 head revision, and the current branch contains exactly one other
4206 head, the other head is merged with by default. Otherwise, an
4220 head, the other head is merged with by default. Otherwise, an
4207 explicit revision with which to merge with must be provided.
4221 explicit revision with which to merge with must be provided.
4208
4222
4209 :hg:`resolve` must be used to resolve unresolved files.
4223 :hg:`resolve` must be used to resolve unresolved files.
4210
4224
4211 To undo an uncommitted merge, use :hg:`update --clean .` which
4225 To undo an uncommitted merge, use :hg:`update --clean .` which
4212 will check out a clean copy of the original merge parent, losing
4226 will check out a clean copy of the original merge parent, losing
4213 all changes.
4227 all changes.
4214
4228
4215 Returns 0 on success, 1 if there are unresolved files.
4229 Returns 0 on success, 1 if there are unresolved files.
4216 """
4230 """
4217
4231
4218 if opts.get('rev') and node:
4232 if opts.get('rev') and node:
4219 raise util.Abort(_("please specify just one revision"))
4233 raise util.Abort(_("please specify just one revision"))
4220 if not node:
4234 if not node:
4221 node = opts.get('rev')
4235 node = opts.get('rev')
4222
4236
4223 if node:
4237 if node:
4224 node = scmutil.revsingle(repo, node).node()
4238 node = scmutil.revsingle(repo, node).node()
4225
4239
4226 if not node and repo._bookmarkcurrent:
4240 if not node and repo._bookmarkcurrent:
4227 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4241 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4228 curhead = repo[repo._bookmarkcurrent]
4242 curhead = repo[repo._bookmarkcurrent]
4229 if len(bmheads) == 2:
4243 if len(bmheads) == 2:
4230 if curhead == bmheads[0]:
4244 if curhead == bmheads[0]:
4231 node = bmheads[1]
4245 node = bmheads[1]
4232 else:
4246 else:
4233 node = bmheads[0]
4247 node = bmheads[0]
4234 elif len(bmheads) > 2:
4248 elif len(bmheads) > 2:
4235 raise util.Abort(_("multiple matching bookmarks to merge - "
4249 raise util.Abort(_("multiple matching bookmarks to merge - "
4236 "please merge with an explicit rev or bookmark"),
4250 "please merge with an explicit rev or bookmark"),
4237 hint=_("run 'hg heads' to see all heads"))
4251 hint=_("run 'hg heads' to see all heads"))
4238 elif len(bmheads) <= 1:
4252 elif len(bmheads) <= 1:
4239 raise util.Abort(_("no matching bookmark to merge - "
4253 raise util.Abort(_("no matching bookmark to merge - "
4240 "please merge with an explicit rev or bookmark"),
4254 "please merge with an explicit rev or bookmark"),
4241 hint=_("run 'hg heads' to see all heads"))
4255 hint=_("run 'hg heads' to see all heads"))
4242
4256
4243 if not node and not repo._bookmarkcurrent:
4257 if not node and not repo._bookmarkcurrent:
4244 branch = repo[None].branch()
4258 branch = repo[None].branch()
4245 bheads = repo.branchheads(branch)
4259 bheads = repo.branchheads(branch)
4246 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4260 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4247
4261
4248 if len(nbhs) > 2:
4262 if len(nbhs) > 2:
4249 raise util.Abort(_("branch '%s' has %d heads - "
4263 raise util.Abort(_("branch '%s' has %d heads - "
4250 "please merge with an explicit rev")
4264 "please merge with an explicit rev")
4251 % (branch, len(bheads)),
4265 % (branch, len(bheads)),
4252 hint=_("run 'hg heads .' to see heads"))
4266 hint=_("run 'hg heads .' to see heads"))
4253
4267
4254 parent = repo.dirstate.p1()
4268 parent = repo.dirstate.p1()
4255 if len(nbhs) == 1:
4269 if len(nbhs) == 1:
4256 if len(bheads) > 1:
4270 if len(bheads) > 1:
4257 raise util.Abort(_("heads are bookmarked - "
4271 raise util.Abort(_("heads are bookmarked - "
4258 "please merge with an explicit rev"),
4272 "please merge with an explicit rev"),
4259 hint=_("run 'hg heads' to see all heads"))
4273 hint=_("run 'hg heads' to see all heads"))
4260 if len(repo.heads()) > 1:
4274 if len(repo.heads()) > 1:
4261 raise util.Abort(_("branch '%s' has one head - "
4275 raise util.Abort(_("branch '%s' has one head - "
4262 "please merge with an explicit rev")
4276 "please merge with an explicit rev")
4263 % branch,
4277 % branch,
4264 hint=_("run 'hg heads' to see all heads"))
4278 hint=_("run 'hg heads' to see all heads"))
4265 msg, hint = _('nothing to merge'), None
4279 msg, hint = _('nothing to merge'), None
4266 if parent != repo.lookup(branch):
4280 if parent != repo.lookup(branch):
4267 hint = _("use 'hg update' instead")
4281 hint = _("use 'hg update' instead")
4268 raise util.Abort(msg, hint=hint)
4282 raise util.Abort(msg, hint=hint)
4269
4283
4270 if parent not in bheads:
4284 if parent not in bheads:
4271 raise util.Abort(_('working directory not at a head revision'),
4285 raise util.Abort(_('working directory not at a head revision'),
4272 hint=_("use 'hg update' or merge with an "
4286 hint=_("use 'hg update' or merge with an "
4273 "explicit revision"))
4287 "explicit revision"))
4274 if parent == nbhs[0]:
4288 if parent == nbhs[0]:
4275 node = nbhs[-1]
4289 node = nbhs[-1]
4276 else:
4290 else:
4277 node = nbhs[0]
4291 node = nbhs[0]
4278
4292
4279 if opts.get('preview'):
4293 if opts.get('preview'):
4280 # find nodes that are ancestors of p2 but not of p1
4294 # find nodes that are ancestors of p2 but not of p1
4281 p1 = repo.lookup('.')
4295 p1 = repo.lookup('.')
4282 p2 = repo.lookup(node)
4296 p2 = repo.lookup(node)
4283 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4297 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4284
4298
4285 displayer = cmdutil.show_changeset(ui, repo, opts)
4299 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 for node in nodes:
4300 for node in nodes:
4287 displayer.show(repo[node])
4301 displayer.show(repo[node])
4288 displayer.close()
4302 displayer.close()
4289 return 0
4303 return 0
4290
4304
4291 try:
4305 try:
4292 # ui.forcemerge is an internal variable, do not document
4306 # ui.forcemerge is an internal variable, do not document
4293 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4307 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4294 return hg.merge(repo, node, force=opts.get('force'))
4308 return hg.merge(repo, node, force=opts.get('force'))
4295 finally:
4309 finally:
4296 ui.setconfig('ui', 'forcemerge', '')
4310 ui.setconfig('ui', 'forcemerge', '')
4297
4311
4298 @command('outgoing|out',
4312 @command('outgoing|out',
4299 [('f', 'force', None, _('run even when the destination is unrelated')),
4313 [('f', 'force', None, _('run even when the destination is unrelated')),
4300 ('r', 'rev', [],
4314 ('r', 'rev', [],
4301 _('a changeset intended to be included in the destination'), _('REV')),
4315 _('a changeset intended to be included in the destination'), _('REV')),
4302 ('n', 'newest-first', None, _('show newest record first')),
4316 ('n', 'newest-first', None, _('show newest record first')),
4303 ('B', 'bookmarks', False, _('compare bookmarks')),
4317 ('B', 'bookmarks', False, _('compare bookmarks')),
4304 ('b', 'branch', [], _('a specific branch you would like to push'),
4318 ('b', 'branch', [], _('a specific branch you would like to push'),
4305 _('BRANCH')),
4319 _('BRANCH')),
4306 ] + logopts + remoteopts + subrepoopts,
4320 ] + logopts + remoteopts + subrepoopts,
4307 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4321 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4308 def outgoing(ui, repo, dest=None, **opts):
4322 def outgoing(ui, repo, dest=None, **opts):
4309 """show changesets not found in the destination
4323 """show changesets not found in the destination
4310
4324
4311 Show changesets not found in the specified destination repository
4325 Show changesets not found in the specified destination repository
4312 or the default push location. These are the changesets that would
4326 or the default push location. These are the changesets that would
4313 be pushed if a push was requested.
4327 be pushed if a push was requested.
4314
4328
4315 See pull for details of valid destination formats.
4329 See pull for details of valid destination formats.
4316
4330
4317 Returns 0 if there are outgoing changes, 1 otherwise.
4331 Returns 0 if there are outgoing changes, 1 otherwise.
4318 """
4332 """
4319 if opts.get('graph'):
4333 if opts.get('graph'):
4320 cmdutil.checkunsupportedgraphflags([], opts)
4334 cmdutil.checkunsupportedgraphflags([], opts)
4321 o = hg._outgoing(ui, repo, dest, opts)
4335 o = hg._outgoing(ui, repo, dest, opts)
4322 if o is None:
4336 if o is None:
4323 return
4337 return
4324
4338
4325 revdag = cmdutil.graphrevs(repo, o, opts)
4339 revdag = cmdutil.graphrevs(repo, o, opts)
4326 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4340 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4341 showparents = [ctx.node() for ctx in repo[None].parents()]
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4342 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4329 graphmod.asciiedges)
4343 graphmod.asciiedges)
4330 return 0
4344 return 0
4331
4345
4332 if opts.get('bookmarks'):
4346 if opts.get('bookmarks'):
4333 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4347 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4334 dest, branches = hg.parseurl(dest, opts.get('branch'))
4348 dest, branches = hg.parseurl(dest, opts.get('branch'))
4335 other = hg.peer(repo, opts, dest)
4349 other = hg.peer(repo, opts, dest)
4336 if 'bookmarks' not in other.listkeys('namespaces'):
4350 if 'bookmarks' not in other.listkeys('namespaces'):
4337 ui.warn(_("remote doesn't support bookmarks\n"))
4351 ui.warn(_("remote doesn't support bookmarks\n"))
4338 return 0
4352 return 0
4339 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4353 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4340 return bookmarks.diff(ui, other, repo)
4354 return bookmarks.diff(ui, other, repo)
4341
4355
4342 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4356 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4343 try:
4357 try:
4344 return hg.outgoing(ui, repo, dest, opts)
4358 return hg.outgoing(ui, repo, dest, opts)
4345 finally:
4359 finally:
4346 del repo._subtoppath
4360 del repo._subtoppath
4347
4361
4348 @command('parents',
4362 @command('parents',
4349 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4363 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4350 ] + templateopts,
4364 ] + templateopts,
4351 _('[-r REV] [FILE]'))
4365 _('[-r REV] [FILE]'))
4352 def parents(ui, repo, file_=None, **opts):
4366 def parents(ui, repo, file_=None, **opts):
4353 """show the parents of the working directory or revision
4367 """show the parents of the working directory or revision
4354
4368
4355 Print the working directory's parent revisions. If a revision is
4369 Print the working directory's parent revisions. If a revision is
4356 given via -r/--rev, the parent of that revision will be printed.
4370 given via -r/--rev, the parent of that revision will be printed.
4357 If a file argument is given, the revision in which the file was
4371 If a file argument is given, the revision in which the file was
4358 last changed (before the working directory revision or the
4372 last changed (before the working directory revision or the
4359 argument to --rev if given) is printed.
4373 argument to --rev if given) is printed.
4360
4374
4361 Returns 0 on success.
4375 Returns 0 on success.
4362 """
4376 """
4363
4377
4364 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4378 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4365
4379
4366 if file_:
4380 if file_:
4367 m = scmutil.match(ctx, (file_,), opts)
4381 m = scmutil.match(ctx, (file_,), opts)
4368 if m.anypats() or len(m.files()) != 1:
4382 if m.anypats() or len(m.files()) != 1:
4369 raise util.Abort(_('can only specify an explicit filename'))
4383 raise util.Abort(_('can only specify an explicit filename'))
4370 file_ = m.files()[0]
4384 file_ = m.files()[0]
4371 filenodes = []
4385 filenodes = []
4372 for cp in ctx.parents():
4386 for cp in ctx.parents():
4373 if not cp:
4387 if not cp:
4374 continue
4388 continue
4375 try:
4389 try:
4376 filenodes.append(cp.filenode(file_))
4390 filenodes.append(cp.filenode(file_))
4377 except error.LookupError:
4391 except error.LookupError:
4378 pass
4392 pass
4379 if not filenodes:
4393 if not filenodes:
4380 raise util.Abort(_("'%s' not found in manifest!") % file_)
4394 raise util.Abort(_("'%s' not found in manifest!") % file_)
4381 fl = repo.file(file_)
4395 fl = repo.file(file_)
4382 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4396 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4383 else:
4397 else:
4384 p = [cp.node() for cp in ctx.parents()]
4398 p = [cp.node() for cp in ctx.parents()]
4385
4399
4386 displayer = cmdutil.show_changeset(ui, repo, opts)
4400 displayer = cmdutil.show_changeset(ui, repo, opts)
4387 for n in p:
4401 for n in p:
4388 if n != nullid:
4402 if n != nullid:
4389 displayer.show(repo[n])
4403 displayer.show(repo[n])
4390 displayer.close()
4404 displayer.close()
4391
4405
4392 @command('paths', [], _('[NAME]'))
4406 @command('paths', [], _('[NAME]'))
4393 def paths(ui, repo, search=None):
4407 def paths(ui, repo, search=None):
4394 """show aliases for remote repositories
4408 """show aliases for remote repositories
4395
4409
4396 Show definition of symbolic path name NAME. If no name is given,
4410 Show definition of symbolic path name NAME. If no name is given,
4397 show definition of all available names.
4411 show definition of all available names.
4398
4412
4399 Option -q/--quiet suppresses all output when searching for NAME
4413 Option -q/--quiet suppresses all output when searching for NAME
4400 and shows only the path names when listing all definitions.
4414 and shows only the path names when listing all definitions.
4401
4415
4402 Path names are defined in the [paths] section of your
4416 Path names are defined in the [paths] section of your
4403 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4417 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4404 repository, ``.hg/hgrc`` is used, too.
4418 repository, ``.hg/hgrc`` is used, too.
4405
4419
4406 The path names ``default`` and ``default-push`` have a special
4420 The path names ``default`` and ``default-push`` have a special
4407 meaning. When performing a push or pull operation, they are used
4421 meaning. When performing a push or pull operation, they are used
4408 as fallbacks if no location is specified on the command-line.
4422 as fallbacks if no location is specified on the command-line.
4409 When ``default-push`` is set, it will be used for push and
4423 When ``default-push`` is set, it will be used for push and
4410 ``default`` will be used for pull; otherwise ``default`` is used
4424 ``default`` will be used for pull; otherwise ``default`` is used
4411 as the fallback for both. When cloning a repository, the clone
4425 as the fallback for both. When cloning a repository, the clone
4412 source is written as ``default`` in ``.hg/hgrc``. Note that
4426 source is written as ``default`` in ``.hg/hgrc``. Note that
4413 ``default`` and ``default-push`` apply to all inbound (e.g.
4427 ``default`` and ``default-push`` apply to all inbound (e.g.
4414 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4428 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4415 :hg:`bundle`) operations.
4429 :hg:`bundle`) operations.
4416
4430
4417 See :hg:`help urls` for more information.
4431 See :hg:`help urls` for more information.
4418
4432
4419 Returns 0 on success.
4433 Returns 0 on success.
4420 """
4434 """
4421 if search:
4435 if search:
4422 for name, path in ui.configitems("paths"):
4436 for name, path in ui.configitems("paths"):
4423 if name == search:
4437 if name == search:
4424 ui.status("%s\n" % util.hidepassword(path))
4438 ui.status("%s\n" % util.hidepassword(path))
4425 return
4439 return
4426 if not ui.quiet:
4440 if not ui.quiet:
4427 ui.warn(_("not found!\n"))
4441 ui.warn(_("not found!\n"))
4428 return 1
4442 return 1
4429 else:
4443 else:
4430 for name, path in ui.configitems("paths"):
4444 for name, path in ui.configitems("paths"):
4431 if ui.quiet:
4445 if ui.quiet:
4432 ui.write("%s\n" % name)
4446 ui.write("%s\n" % name)
4433 else:
4447 else:
4434 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4448 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4435
4449
4436 @command('^phase',
4450 @command('^phase',
4437 [('p', 'public', False, _('set changeset phase to public')),
4451 [('p', 'public', False, _('set changeset phase to public')),
4438 ('d', 'draft', False, _('set changeset phase to draft')),
4452 ('d', 'draft', False, _('set changeset phase to draft')),
4439 ('s', 'secret', False, _('set changeset phase to secret')),
4453 ('s', 'secret', False, _('set changeset phase to secret')),
4440 ('f', 'force', False, _('allow to move boundary backward')),
4454 ('f', 'force', False, _('allow to move boundary backward')),
4441 ('r', 'rev', [], _('target revision'), _('REV')),
4455 ('r', 'rev', [], _('target revision'), _('REV')),
4442 ],
4456 ],
4443 _('[-p|-d|-s] [-f] [-r] REV...'))
4457 _('[-p|-d|-s] [-f] [-r] REV...'))
4444 def phase(ui, repo, *revs, **opts):
4458 def phase(ui, repo, *revs, **opts):
4445 """set or show the current phase name
4459 """set or show the current phase name
4446
4460
4447 With no argument, show the phase name of specified revisions.
4461 With no argument, show the phase name of specified revisions.
4448
4462
4449 With one of -p/--public, -d/--draft or -s/--secret, change the
4463 With one of -p/--public, -d/--draft or -s/--secret, change the
4450 phase value of the specified revisions.
4464 phase value of the specified revisions.
4451
4465
4452 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4466 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4453 lower phase to an higher phase. Phases are ordered as follows::
4467 lower phase to an higher phase. Phases are ordered as follows::
4454
4468
4455 public < draft < secret
4469 public < draft < secret
4456
4470
4457 Return 0 on success, 1 if no phases were changed or some could not
4471 Return 0 on success, 1 if no phases were changed or some could not
4458 be changed.
4472 be changed.
4459 """
4473 """
4460 # search for a unique phase argument
4474 # search for a unique phase argument
4461 targetphase = None
4475 targetphase = None
4462 for idx, name in enumerate(phases.phasenames):
4476 for idx, name in enumerate(phases.phasenames):
4463 if opts[name]:
4477 if opts[name]:
4464 if targetphase is not None:
4478 if targetphase is not None:
4465 raise util.Abort(_('only one phase can be specified'))
4479 raise util.Abort(_('only one phase can be specified'))
4466 targetphase = idx
4480 targetphase = idx
4467
4481
4468 # look for specified revision
4482 # look for specified revision
4469 revs = list(revs)
4483 revs = list(revs)
4470 revs.extend(opts['rev'])
4484 revs.extend(opts['rev'])
4471 if not revs:
4485 if not revs:
4472 raise util.Abort(_('no revisions specified'))
4486 raise util.Abort(_('no revisions specified'))
4473
4487
4474 revs = scmutil.revrange(repo, revs)
4488 revs = scmutil.revrange(repo, revs)
4475
4489
4476 lock = None
4490 lock = None
4477 ret = 0
4491 ret = 0
4478 if targetphase is None:
4492 if targetphase is None:
4479 # display
4493 # display
4480 for r in revs:
4494 for r in revs:
4481 ctx = repo[r]
4495 ctx = repo[r]
4482 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4496 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4483 else:
4497 else:
4484 lock = repo.lock()
4498 lock = repo.lock()
4485 try:
4499 try:
4486 # set phase
4500 # set phase
4487 if not revs:
4501 if not revs:
4488 raise util.Abort(_('empty revision set'))
4502 raise util.Abort(_('empty revision set'))
4489 nodes = [repo[r].node() for r in revs]
4503 nodes = [repo[r].node() for r in revs]
4490 olddata = repo._phasecache.getphaserevs(repo)[:]
4504 olddata = repo._phasecache.getphaserevs(repo)[:]
4491 phases.advanceboundary(repo, targetphase, nodes)
4505 phases.advanceboundary(repo, targetphase, nodes)
4492 if opts['force']:
4506 if opts['force']:
4493 phases.retractboundary(repo, targetphase, nodes)
4507 phases.retractboundary(repo, targetphase, nodes)
4494 finally:
4508 finally:
4495 lock.release()
4509 lock.release()
4496 newdata = repo._phasecache.getphaserevs(repo)
4510 newdata = repo._phasecache.getphaserevs(repo)
4497 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4511 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4498 rejected = [n for n in nodes
4512 rejected = [n for n in nodes
4499 if newdata[repo[n].rev()] < targetphase]
4513 if newdata[repo[n].rev()] < targetphase]
4500 if rejected:
4514 if rejected:
4501 ui.warn(_('cannot move %i changesets to a more permissive '
4515 ui.warn(_('cannot move %i changesets to a more permissive '
4502 'phase, use --force\n') % len(rejected))
4516 'phase, use --force\n') % len(rejected))
4503 ret = 1
4517 ret = 1
4504 if changes:
4518 if changes:
4505 msg = _('phase changed for %i changesets\n') % changes
4519 msg = _('phase changed for %i changesets\n') % changes
4506 if ret:
4520 if ret:
4507 ui.status(msg)
4521 ui.status(msg)
4508 else:
4522 else:
4509 ui.note(msg)
4523 ui.note(msg)
4510 else:
4524 else:
4511 ui.warn(_('no phases changed\n'))
4525 ui.warn(_('no phases changed\n'))
4512 ret = 1
4526 ret = 1
4513 return ret
4527 return ret
4514
4528
4515 def postincoming(ui, repo, modheads, optupdate, checkout):
4529 def postincoming(ui, repo, modheads, optupdate, checkout):
4516 if modheads == 0:
4530 if modheads == 0:
4517 return
4531 return
4518 if optupdate:
4532 if optupdate:
4519 movemarkfrom = repo['.'].node()
4533 movemarkfrom = repo['.'].node()
4520 try:
4534 try:
4521 ret = hg.update(repo, checkout)
4535 ret = hg.update(repo, checkout)
4522 except util.Abort, inst:
4536 except util.Abort, inst:
4523 ui.warn(_("not updating: %s\n") % str(inst))
4537 ui.warn(_("not updating: %s\n") % str(inst))
4524 return 0
4538 return 0
4525 if not ret and not checkout:
4539 if not ret and not checkout:
4526 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4540 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4527 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4541 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4528 return ret
4542 return ret
4529 if modheads > 1:
4543 if modheads > 1:
4530 currentbranchheads = len(repo.branchheads())
4544 currentbranchheads = len(repo.branchheads())
4531 if currentbranchheads == modheads:
4545 if currentbranchheads == modheads:
4532 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4546 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4533 elif currentbranchheads > 1:
4547 elif currentbranchheads > 1:
4534 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4548 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4535 "merge)\n"))
4549 "merge)\n"))
4536 else:
4550 else:
4537 ui.status(_("(run 'hg heads' to see heads)\n"))
4551 ui.status(_("(run 'hg heads' to see heads)\n"))
4538 else:
4552 else:
4539 ui.status(_("(run 'hg update' to get a working copy)\n"))
4553 ui.status(_("(run 'hg update' to get a working copy)\n"))
4540
4554
4541 @command('^pull',
4555 @command('^pull',
4542 [('u', 'update', None,
4556 [('u', 'update', None,
4543 _('update to new branch head if changesets were pulled')),
4557 _('update to new branch head if changesets were pulled')),
4544 ('f', 'force', None, _('run even when remote repository is unrelated')),
4558 ('f', 'force', None, _('run even when remote repository is unrelated')),
4545 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4559 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4546 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4560 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4547 ('b', 'branch', [], _('a specific branch you would like to pull'),
4561 ('b', 'branch', [], _('a specific branch you would like to pull'),
4548 _('BRANCH')),
4562 _('BRANCH')),
4549 ] + remoteopts,
4563 ] + remoteopts,
4550 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4564 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4551 def pull(ui, repo, source="default", **opts):
4565 def pull(ui, repo, source="default", **opts):
4552 """pull changes from the specified source
4566 """pull changes from the specified source
4553
4567
4554 Pull changes from a remote repository to a local one.
4568 Pull changes from a remote repository to a local one.
4555
4569
4556 This finds all changes from the repository at the specified path
4570 This finds all changes from the repository at the specified path
4557 or URL and adds them to a local repository (the current one unless
4571 or URL and adds them to a local repository (the current one unless
4558 -R is specified). By default, this does not update the copy of the
4572 -R is specified). By default, this does not update the copy of the
4559 project in the working directory.
4573 project in the working directory.
4560
4574
4561 Use :hg:`incoming` if you want to see what would have been added
4575 Use :hg:`incoming` if you want to see what would have been added
4562 by a pull at the time you issued this command. If you then decide
4576 by a pull at the time you issued this command. If you then decide
4563 to add those changes to the repository, you should use :hg:`pull
4577 to add those changes to the repository, you should use :hg:`pull
4564 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4578 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4565
4579
4566 If SOURCE is omitted, the 'default' path will be used.
4580 If SOURCE is omitted, the 'default' path will be used.
4567 See :hg:`help urls` for more information.
4581 See :hg:`help urls` for more information.
4568
4582
4569 Returns 0 on success, 1 if an update had unresolved files.
4583 Returns 0 on success, 1 if an update had unresolved files.
4570 """
4584 """
4571 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4585 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4572 other = hg.peer(repo, opts, source)
4586 other = hg.peer(repo, opts, source)
4573 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4587 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4574 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4588 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4575
4589
4576 if opts.get('bookmark'):
4590 if opts.get('bookmark'):
4577 if not revs:
4591 if not revs:
4578 revs = []
4592 revs = []
4579 rb = other.listkeys('bookmarks')
4593 rb = other.listkeys('bookmarks')
4580 for b in opts['bookmark']:
4594 for b in opts['bookmark']:
4581 if b not in rb:
4595 if b not in rb:
4582 raise util.Abort(_('remote bookmark %s not found!') % b)
4596 raise util.Abort(_('remote bookmark %s not found!') % b)
4583 revs.append(rb[b])
4597 revs.append(rb[b])
4584
4598
4585 if revs:
4599 if revs:
4586 try:
4600 try:
4587 revs = [other.lookup(rev) for rev in revs]
4601 revs = [other.lookup(rev) for rev in revs]
4588 except error.CapabilityError:
4602 except error.CapabilityError:
4589 err = _("other repository doesn't support revision lookup, "
4603 err = _("other repository doesn't support revision lookup, "
4590 "so a rev cannot be specified.")
4604 "so a rev cannot be specified.")
4591 raise util.Abort(err)
4605 raise util.Abort(err)
4592
4606
4593 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4607 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4594 bookmarks.updatefromremote(ui, repo, other, source)
4608 bookmarks.updatefromremote(ui, repo, other, source)
4595 if checkout:
4609 if checkout:
4596 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4610 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4597 repo._subtoppath = source
4611 repo._subtoppath = source
4598 try:
4612 try:
4599 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4613 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4600
4614
4601 finally:
4615 finally:
4602 del repo._subtoppath
4616 del repo._subtoppath
4603
4617
4604 # update specified bookmarks
4618 # update specified bookmarks
4605 if opts.get('bookmark'):
4619 if opts.get('bookmark'):
4606 for b in opts['bookmark']:
4620 for b in opts['bookmark']:
4607 # explicit pull overrides local bookmark if any
4621 # explicit pull overrides local bookmark if any
4608 ui.status(_("importing bookmark %s\n") % b)
4622 ui.status(_("importing bookmark %s\n") % b)
4609 repo._bookmarks[b] = repo[rb[b]].node()
4623 repo._bookmarks[b] = repo[rb[b]].node()
4610 bookmarks.write(repo)
4624 bookmarks.write(repo)
4611
4625
4612 return ret
4626 return ret
4613
4627
4614 @command('^push',
4628 @command('^push',
4615 [('f', 'force', None, _('force push')),
4629 [('f', 'force', None, _('force push')),
4616 ('r', 'rev', [],
4630 ('r', 'rev', [],
4617 _('a changeset intended to be included in the destination'),
4631 _('a changeset intended to be included in the destination'),
4618 _('REV')),
4632 _('REV')),
4619 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4633 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4620 ('b', 'branch', [],
4634 ('b', 'branch', [],
4621 _('a specific branch you would like to push'), _('BRANCH')),
4635 _('a specific branch you would like to push'), _('BRANCH')),
4622 ('', 'new-branch', False, _('allow pushing a new branch')),
4636 ('', 'new-branch', False, _('allow pushing a new branch')),
4623 ] + remoteopts,
4637 ] + remoteopts,
4624 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4638 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4625 def push(ui, repo, dest=None, **opts):
4639 def push(ui, repo, dest=None, **opts):
4626 """push changes to the specified destination
4640 """push changes to the specified destination
4627
4641
4628 Push changesets from the local repository to the specified
4642 Push changesets from the local repository to the specified
4629 destination.
4643 destination.
4630
4644
4631 This operation is symmetrical to pull: it is identical to a pull
4645 This operation is symmetrical to pull: it is identical to a pull
4632 in the destination repository from the current one.
4646 in the destination repository from the current one.
4633
4647
4634 By default, push will not allow creation of new heads at the
4648 By default, push will not allow creation of new heads at the
4635 destination, since multiple heads would make it unclear which head
4649 destination, since multiple heads would make it unclear which head
4636 to use. In this situation, it is recommended to pull and merge
4650 to use. In this situation, it is recommended to pull and merge
4637 before pushing.
4651 before pushing.
4638
4652
4639 Use --new-branch if you want to allow push to create a new named
4653 Use --new-branch if you want to allow push to create a new named
4640 branch that is not present at the destination. This allows you to
4654 branch that is not present at the destination. This allows you to
4641 only create a new branch without forcing other changes.
4655 only create a new branch without forcing other changes.
4642
4656
4643 Use -f/--force to override the default behavior and push all
4657 Use -f/--force to override the default behavior and push all
4644 changesets on all branches.
4658 changesets on all branches.
4645
4659
4646 If -r/--rev is used, the specified revision and all its ancestors
4660 If -r/--rev is used, the specified revision and all its ancestors
4647 will be pushed to the remote repository.
4661 will be pushed to the remote repository.
4648
4662
4649 If -B/--bookmark is used, the specified bookmarked revision, its
4663 If -B/--bookmark is used, the specified bookmarked revision, its
4650 ancestors, and the bookmark will be pushed to the remote
4664 ancestors, and the bookmark will be pushed to the remote
4651 repository.
4665 repository.
4652
4666
4653 Please see :hg:`help urls` for important details about ``ssh://``
4667 Please see :hg:`help urls` for important details about ``ssh://``
4654 URLs. If DESTINATION is omitted, a default path will be used.
4668 URLs. If DESTINATION is omitted, a default path will be used.
4655
4669
4656 Returns 0 if push was successful, 1 if nothing to push.
4670 Returns 0 if push was successful, 1 if nothing to push.
4657 """
4671 """
4658
4672
4659 if opts.get('bookmark'):
4673 if opts.get('bookmark'):
4660 for b in opts['bookmark']:
4674 for b in opts['bookmark']:
4661 # translate -B options to -r so changesets get pushed
4675 # translate -B options to -r so changesets get pushed
4662 if b in repo._bookmarks:
4676 if b in repo._bookmarks:
4663 opts.setdefault('rev', []).append(b)
4677 opts.setdefault('rev', []).append(b)
4664 else:
4678 else:
4665 # if we try to push a deleted bookmark, translate it to null
4679 # if we try to push a deleted bookmark, translate it to null
4666 # this lets simultaneous -r, -b options continue working
4680 # this lets simultaneous -r, -b options continue working
4667 opts.setdefault('rev', []).append("null")
4681 opts.setdefault('rev', []).append("null")
4668
4682
4669 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4683 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4670 dest, branches = hg.parseurl(dest, opts.get('branch'))
4684 dest, branches = hg.parseurl(dest, opts.get('branch'))
4671 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4685 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4672 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4686 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4673 other = hg.peer(repo, opts, dest)
4687 other = hg.peer(repo, opts, dest)
4674 if revs:
4688 if revs:
4675 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4689 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4676
4690
4677 repo._subtoppath = dest
4691 repo._subtoppath = dest
4678 try:
4692 try:
4679 # push subrepos depth-first for coherent ordering
4693 # push subrepos depth-first for coherent ordering
4680 c = repo['']
4694 c = repo['']
4681 subs = c.substate # only repos that are committed
4695 subs = c.substate # only repos that are committed
4682 for s in sorted(subs):
4696 for s in sorted(subs):
4683 if c.sub(s).push(opts) == 0:
4697 if c.sub(s).push(opts) == 0:
4684 return False
4698 return False
4685 finally:
4699 finally:
4686 del repo._subtoppath
4700 del repo._subtoppath
4687 result = repo.push(other, opts.get('force'), revs=revs,
4701 result = repo.push(other, opts.get('force'), revs=revs,
4688 newbranch=opts.get('new_branch'))
4702 newbranch=opts.get('new_branch'))
4689
4703
4690 result = not result
4704 result = not result
4691
4705
4692 if opts.get('bookmark'):
4706 if opts.get('bookmark'):
4693 rb = other.listkeys('bookmarks')
4707 rb = other.listkeys('bookmarks')
4694 for b in opts['bookmark']:
4708 for b in opts['bookmark']:
4695 # explicit push overrides remote bookmark if any
4709 # explicit push overrides remote bookmark if any
4696 if b in repo._bookmarks:
4710 if b in repo._bookmarks:
4697 ui.status(_("exporting bookmark %s\n") % b)
4711 ui.status(_("exporting bookmark %s\n") % b)
4698 new = repo[b].hex()
4712 new = repo[b].hex()
4699 elif b in rb:
4713 elif b in rb:
4700 ui.status(_("deleting remote bookmark %s\n") % b)
4714 ui.status(_("deleting remote bookmark %s\n") % b)
4701 new = '' # delete
4715 new = '' # delete
4702 else:
4716 else:
4703 ui.warn(_('bookmark %s does not exist on the local '
4717 ui.warn(_('bookmark %s does not exist on the local '
4704 'or remote repository!\n') % b)
4718 'or remote repository!\n') % b)
4705 return 2
4719 return 2
4706 old = rb.get(b, '')
4720 old = rb.get(b, '')
4707 r = other.pushkey('bookmarks', b, old, new)
4721 r = other.pushkey('bookmarks', b, old, new)
4708 if not r:
4722 if not r:
4709 ui.warn(_('updating bookmark %s failed!\n') % b)
4723 ui.warn(_('updating bookmark %s failed!\n') % b)
4710 if not result:
4724 if not result:
4711 result = 2
4725 result = 2
4712
4726
4713 return result
4727 return result
4714
4728
4715 @command('recover', [])
4729 @command('recover', [])
4716 def recover(ui, repo):
4730 def recover(ui, repo):
4717 """roll back an interrupted transaction
4731 """roll back an interrupted transaction
4718
4732
4719 Recover from an interrupted commit or pull.
4733 Recover from an interrupted commit or pull.
4720
4734
4721 This command tries to fix the repository status after an
4735 This command tries to fix the repository status after an
4722 interrupted operation. It should only be necessary when Mercurial
4736 interrupted operation. It should only be necessary when Mercurial
4723 suggests it.
4737 suggests it.
4724
4738
4725 Returns 0 if successful, 1 if nothing to recover or verify fails.
4739 Returns 0 if successful, 1 if nothing to recover or verify fails.
4726 """
4740 """
4727 if repo.recover():
4741 if repo.recover():
4728 return hg.verify(repo)
4742 return hg.verify(repo)
4729 return 1
4743 return 1
4730
4744
4731 @command('^remove|rm',
4745 @command('^remove|rm',
4732 [('A', 'after', None, _('record delete for missing files')),
4746 [('A', 'after', None, _('record delete for missing files')),
4733 ('f', 'force', None,
4747 ('f', 'force', None,
4734 _('remove (and delete) file even if added or modified')),
4748 _('remove (and delete) file even if added or modified')),
4735 ] + walkopts,
4749 ] + walkopts,
4736 _('[OPTION]... FILE...'))
4750 _('[OPTION]... FILE...'))
4737 def remove(ui, repo, *pats, **opts):
4751 def remove(ui, repo, *pats, **opts):
4738 """remove the specified files on the next commit
4752 """remove the specified files on the next commit
4739
4753
4740 Schedule the indicated files for removal from the current branch.
4754 Schedule the indicated files for removal from the current branch.
4741
4755
4742 This command schedules the files to be removed at the next commit.
4756 This command schedules the files to be removed at the next commit.
4743 To undo a remove before that, see :hg:`revert`. To undo added
4757 To undo a remove before that, see :hg:`revert`. To undo added
4744 files, see :hg:`forget`.
4758 files, see :hg:`forget`.
4745
4759
4746 .. container:: verbose
4760 .. container:: verbose
4747
4761
4748 -A/--after can be used to remove only files that have already
4762 -A/--after can be used to remove only files that have already
4749 been deleted, -f/--force can be used to force deletion, and -Af
4763 been deleted, -f/--force can be used to force deletion, and -Af
4750 can be used to remove files from the next revision without
4764 can be used to remove files from the next revision without
4751 deleting them from the working directory.
4765 deleting them from the working directory.
4752
4766
4753 The following table details the behavior of remove for different
4767 The following table details the behavior of remove for different
4754 file states (columns) and option combinations (rows). The file
4768 file states (columns) and option combinations (rows). The file
4755 states are Added [A], Clean [C], Modified [M] and Missing [!]
4769 states are Added [A], Clean [C], Modified [M] and Missing [!]
4756 (as reported by :hg:`status`). The actions are Warn, Remove
4770 (as reported by :hg:`status`). The actions are Warn, Remove
4757 (from branch) and Delete (from disk):
4771 (from branch) and Delete (from disk):
4758
4772
4759 ======= == == == ==
4773 ======= == == == ==
4760 A C M !
4774 A C M !
4761 ======= == == == ==
4775 ======= == == == ==
4762 none W RD W R
4776 none W RD W R
4763 -f R RD RD R
4777 -f R RD RD R
4764 -A W W W R
4778 -A W W W R
4765 -Af R R R R
4779 -Af R R R R
4766 ======= == == == ==
4780 ======= == == == ==
4767
4781
4768 Note that remove never deletes files in Added [A] state from the
4782 Note that remove never deletes files in Added [A] state from the
4769 working directory, not even if option --force is specified.
4783 working directory, not even if option --force is specified.
4770
4784
4771 Returns 0 on success, 1 if any warnings encountered.
4785 Returns 0 on success, 1 if any warnings encountered.
4772 """
4786 """
4773
4787
4774 ret = 0
4788 ret = 0
4775 after, force = opts.get('after'), opts.get('force')
4789 after, force = opts.get('after'), opts.get('force')
4776 if not pats and not after:
4790 if not pats and not after:
4777 raise util.Abort(_('no files specified'))
4791 raise util.Abort(_('no files specified'))
4778
4792
4779 m = scmutil.match(repo[None], pats, opts)
4793 m = scmutil.match(repo[None], pats, opts)
4780 s = repo.status(match=m, clean=True)
4794 s = repo.status(match=m, clean=True)
4781 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4795 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4782
4796
4783 for f in m.files():
4797 for f in m.files():
4784 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4798 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4785 if os.path.exists(m.rel(f)):
4799 if os.path.exists(m.rel(f)):
4786 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4800 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4787 ret = 1
4801 ret = 1
4788
4802
4789 if force:
4803 if force:
4790 list = modified + deleted + clean + added
4804 list = modified + deleted + clean + added
4791 elif after:
4805 elif after:
4792 list = deleted
4806 list = deleted
4793 for f in modified + added + clean:
4807 for f in modified + added + clean:
4794 ui.warn(_('not removing %s: file still exists (use -f'
4808 ui.warn(_('not removing %s: file still exists (use -f'
4795 ' to force removal)\n') % m.rel(f))
4809 ' to force removal)\n') % m.rel(f))
4796 ret = 1
4810 ret = 1
4797 else:
4811 else:
4798 list = deleted + clean
4812 list = deleted + clean
4799 for f in modified:
4813 for f in modified:
4800 ui.warn(_('not removing %s: file is modified (use -f'
4814 ui.warn(_('not removing %s: file is modified (use -f'
4801 ' to force removal)\n') % m.rel(f))
4815 ' to force removal)\n') % m.rel(f))
4802 ret = 1
4816 ret = 1
4803 for f in added:
4817 for f in added:
4804 ui.warn(_('not removing %s: file has been marked for add'
4818 ui.warn(_('not removing %s: file has been marked for add'
4805 ' (use forget to undo)\n') % m.rel(f))
4819 ' (use forget to undo)\n') % m.rel(f))
4806 ret = 1
4820 ret = 1
4807
4821
4808 for f in sorted(list):
4822 for f in sorted(list):
4809 if ui.verbose or not m.exact(f):
4823 if ui.verbose or not m.exact(f):
4810 ui.status(_('removing %s\n') % m.rel(f))
4824 ui.status(_('removing %s\n') % m.rel(f))
4811
4825
4812 wlock = repo.wlock()
4826 wlock = repo.wlock()
4813 try:
4827 try:
4814 if not after:
4828 if not after:
4815 for f in list:
4829 for f in list:
4816 if f in added:
4830 if f in added:
4817 continue # we never unlink added files on remove
4831 continue # we never unlink added files on remove
4818 try:
4832 try:
4819 util.unlinkpath(repo.wjoin(f))
4833 util.unlinkpath(repo.wjoin(f))
4820 except OSError, inst:
4834 except OSError, inst:
4821 if inst.errno != errno.ENOENT:
4835 if inst.errno != errno.ENOENT:
4822 raise
4836 raise
4823 repo[None].forget(list)
4837 repo[None].forget(list)
4824 finally:
4838 finally:
4825 wlock.release()
4839 wlock.release()
4826
4840
4827 return ret
4841 return ret
4828
4842
4829 @command('rename|move|mv',
4843 @command('rename|move|mv',
4830 [('A', 'after', None, _('record a rename that has already occurred')),
4844 [('A', 'after', None, _('record a rename that has already occurred')),
4831 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4845 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4832 ] + walkopts + dryrunopts,
4846 ] + walkopts + dryrunopts,
4833 _('[OPTION]... SOURCE... DEST'))
4847 _('[OPTION]... SOURCE... DEST'))
4834 def rename(ui, repo, *pats, **opts):
4848 def rename(ui, repo, *pats, **opts):
4835 """rename files; equivalent of copy + remove
4849 """rename files; equivalent of copy + remove
4836
4850
4837 Mark dest as copies of sources; mark sources for deletion. If dest
4851 Mark dest as copies of sources; mark sources for deletion. If dest
4838 is a directory, copies are put in that directory. If dest is a
4852 is a directory, copies are put in that directory. If dest is a
4839 file, there can only be one source.
4853 file, there can only be one source.
4840
4854
4841 By default, this command copies the contents of files as they
4855 By default, this command copies the contents of files as they
4842 exist in the working directory. If invoked with -A/--after, the
4856 exist in the working directory. If invoked with -A/--after, the
4843 operation is recorded, but no copying is performed.
4857 operation is recorded, but no copying is performed.
4844
4858
4845 This command takes effect at the next commit. To undo a rename
4859 This command takes effect at the next commit. To undo a rename
4846 before that, see :hg:`revert`.
4860 before that, see :hg:`revert`.
4847
4861
4848 Returns 0 on success, 1 if errors are encountered.
4862 Returns 0 on success, 1 if errors are encountered.
4849 """
4863 """
4850 wlock = repo.wlock(False)
4864 wlock = repo.wlock(False)
4851 try:
4865 try:
4852 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4866 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4853 finally:
4867 finally:
4854 wlock.release()
4868 wlock.release()
4855
4869
4856 @command('resolve',
4870 @command('resolve',
4857 [('a', 'all', None, _('select all unresolved files')),
4871 [('a', 'all', None, _('select all unresolved files')),
4858 ('l', 'list', None, _('list state of files needing merge')),
4872 ('l', 'list', None, _('list state of files needing merge')),
4859 ('m', 'mark', None, _('mark files as resolved')),
4873 ('m', 'mark', None, _('mark files as resolved')),
4860 ('u', 'unmark', None, _('mark files as unresolved')),
4874 ('u', 'unmark', None, _('mark files as unresolved')),
4861 ('n', 'no-status', None, _('hide status prefix'))]
4875 ('n', 'no-status', None, _('hide status prefix'))]
4862 + mergetoolopts + walkopts,
4876 + mergetoolopts + walkopts,
4863 _('[OPTION]... [FILE]...'))
4877 _('[OPTION]... [FILE]...'))
4864 def resolve(ui, repo, *pats, **opts):
4878 def resolve(ui, repo, *pats, **opts):
4865 """redo merges or set/view the merge status of files
4879 """redo merges or set/view the merge status of files
4866
4880
4867 Merges with unresolved conflicts are often the result of
4881 Merges with unresolved conflicts are often the result of
4868 non-interactive merging using the ``internal:merge`` configuration
4882 non-interactive merging using the ``internal:merge`` configuration
4869 setting, or a command-line merge tool like ``diff3``. The resolve
4883 setting, or a command-line merge tool like ``diff3``. The resolve
4870 command is used to manage the files involved in a merge, after
4884 command is used to manage the files involved in a merge, after
4871 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4885 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4872 working directory must have two parents). See :hg:`help
4886 working directory must have two parents). See :hg:`help
4873 merge-tools` for information on configuring merge tools.
4887 merge-tools` for information on configuring merge tools.
4874
4888
4875 The resolve command can be used in the following ways:
4889 The resolve command can be used in the following ways:
4876
4890
4877 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4891 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4878 files, discarding any previous merge attempts. Re-merging is not
4892 files, discarding any previous merge attempts. Re-merging is not
4879 performed for files already marked as resolved. Use ``--all/-a``
4893 performed for files already marked as resolved. Use ``--all/-a``
4880 to select all unresolved files. ``--tool`` can be used to specify
4894 to select all unresolved files. ``--tool`` can be used to specify
4881 the merge tool used for the given files. It overrides the HGMERGE
4895 the merge tool used for the given files. It overrides the HGMERGE
4882 environment variable and your configuration files. Previous file
4896 environment variable and your configuration files. Previous file
4883 contents are saved with a ``.orig`` suffix.
4897 contents are saved with a ``.orig`` suffix.
4884
4898
4885 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4899 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4886 (e.g. after having manually fixed-up the files). The default is
4900 (e.g. after having manually fixed-up the files). The default is
4887 to mark all unresolved files.
4901 to mark all unresolved files.
4888
4902
4889 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4903 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4890 default is to mark all resolved files.
4904 default is to mark all resolved files.
4891
4905
4892 - :hg:`resolve -l`: list files which had or still have conflicts.
4906 - :hg:`resolve -l`: list files which had or still have conflicts.
4893 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4907 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4894
4908
4895 Note that Mercurial will not let you commit files with unresolved
4909 Note that Mercurial will not let you commit files with unresolved
4896 merge conflicts. You must use :hg:`resolve -m ...` before you can
4910 merge conflicts. You must use :hg:`resolve -m ...` before you can
4897 commit after a conflicting merge.
4911 commit after a conflicting merge.
4898
4912
4899 Returns 0 on success, 1 if any files fail a resolve attempt.
4913 Returns 0 on success, 1 if any files fail a resolve attempt.
4900 """
4914 """
4901
4915
4902 all, mark, unmark, show, nostatus = \
4916 all, mark, unmark, show, nostatus = \
4903 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4917 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4904
4918
4905 if (show and (mark or unmark)) or (mark and unmark):
4919 if (show and (mark or unmark)) or (mark and unmark):
4906 raise util.Abort(_("too many options specified"))
4920 raise util.Abort(_("too many options specified"))
4907 if pats and all:
4921 if pats and all:
4908 raise util.Abort(_("can't specify --all and patterns"))
4922 raise util.Abort(_("can't specify --all and patterns"))
4909 if not (all or pats or show or mark or unmark):
4923 if not (all or pats or show or mark or unmark):
4910 raise util.Abort(_('no files or directories specified; '
4924 raise util.Abort(_('no files or directories specified; '
4911 'use --all to remerge all files'))
4925 'use --all to remerge all files'))
4912
4926
4913 ms = mergemod.mergestate(repo)
4927 ms = mergemod.mergestate(repo)
4914 m = scmutil.match(repo[None], pats, opts)
4928 m = scmutil.match(repo[None], pats, opts)
4915 ret = 0
4929 ret = 0
4916
4930
4917 for f in ms:
4931 for f in ms:
4918 if m(f):
4932 if m(f):
4919 if show:
4933 if show:
4920 if nostatus:
4934 if nostatus:
4921 ui.write("%s\n" % f)
4935 ui.write("%s\n" % f)
4922 else:
4936 else:
4923 ui.write("%s %s\n" % (ms[f].upper(), f),
4937 ui.write("%s %s\n" % (ms[f].upper(), f),
4924 label='resolve.' +
4938 label='resolve.' +
4925 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4939 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4926 elif mark:
4940 elif mark:
4927 ms.mark(f, "r")
4941 ms.mark(f, "r")
4928 elif unmark:
4942 elif unmark:
4929 ms.mark(f, "u")
4943 ms.mark(f, "u")
4930 else:
4944 else:
4931 wctx = repo[None]
4945 wctx = repo[None]
4932 mctx = wctx.parents()[-1]
4946 mctx = wctx.parents()[-1]
4933
4947
4934 # backup pre-resolve (merge uses .orig for its own purposes)
4948 # backup pre-resolve (merge uses .orig for its own purposes)
4935 a = repo.wjoin(f)
4949 a = repo.wjoin(f)
4936 util.copyfile(a, a + ".resolve")
4950 util.copyfile(a, a + ".resolve")
4937
4951
4938 try:
4952 try:
4939 # resolve file
4953 # resolve file
4940 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4954 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4941 if ms.resolve(f, wctx, mctx):
4955 if ms.resolve(f, wctx, mctx):
4942 ret = 1
4956 ret = 1
4943 finally:
4957 finally:
4944 ui.setconfig('ui', 'forcemerge', '')
4958 ui.setconfig('ui', 'forcemerge', '')
4945
4959
4946 # replace filemerge's .orig file with our resolve file
4960 # replace filemerge's .orig file with our resolve file
4947 util.rename(a + ".resolve", a + ".orig")
4961 util.rename(a + ".resolve", a + ".orig")
4948
4962
4949 ms.commit()
4963 ms.commit()
4950 return ret
4964 return ret
4951
4965
4952 @command('revert',
4966 @command('revert',
4953 [('a', 'all', None, _('revert all changes when no arguments given')),
4967 [('a', 'all', None, _('revert all changes when no arguments given')),
4954 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4968 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4955 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4969 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4956 ('C', 'no-backup', None, _('do not save backup copies of files')),
4970 ('C', 'no-backup', None, _('do not save backup copies of files')),
4957 ] + walkopts + dryrunopts,
4971 ] + walkopts + dryrunopts,
4958 _('[OPTION]... [-r REV] [NAME]...'))
4972 _('[OPTION]... [-r REV] [NAME]...'))
4959 def revert(ui, repo, *pats, **opts):
4973 def revert(ui, repo, *pats, **opts):
4960 """restore files to their checkout state
4974 """restore files to their checkout state
4961
4975
4962 .. note::
4976 .. note::
4963
4977
4964 To check out earlier revisions, you should use :hg:`update REV`.
4978 To check out earlier revisions, you should use :hg:`update REV`.
4965 To cancel an uncommitted merge (and lose your changes), use
4979 To cancel an uncommitted merge (and lose your changes), use
4966 :hg:`update --clean .`.
4980 :hg:`update --clean .`.
4967
4981
4968 With no revision specified, revert the specified files or directories
4982 With no revision specified, revert the specified files or directories
4969 to the contents they had in the parent of the working directory.
4983 to the contents they had in the parent of the working directory.
4970 This restores the contents of files to an unmodified
4984 This restores the contents of files to an unmodified
4971 state and unschedules adds, removes, copies, and renames. If the
4985 state and unschedules adds, removes, copies, and renames. If the
4972 working directory has two parents, you must explicitly specify a
4986 working directory has two parents, you must explicitly specify a
4973 revision.
4987 revision.
4974
4988
4975 Using the -r/--rev or -d/--date options, revert the given files or
4989 Using the -r/--rev or -d/--date options, revert the given files or
4976 directories to their states as of a specific revision. Because
4990 directories to their states as of a specific revision. Because
4977 revert does not change the working directory parents, this will
4991 revert does not change the working directory parents, this will
4978 cause these files to appear modified. This can be helpful to "back
4992 cause these files to appear modified. This can be helpful to "back
4979 out" some or all of an earlier change. See :hg:`backout` for a
4993 out" some or all of an earlier change. See :hg:`backout` for a
4980 related method.
4994 related method.
4981
4995
4982 Modified files are saved with a .orig suffix before reverting.
4996 Modified files are saved with a .orig suffix before reverting.
4983 To disable these backups, use --no-backup.
4997 To disable these backups, use --no-backup.
4984
4998
4985 See :hg:`help dates` for a list of formats valid for -d/--date.
4999 See :hg:`help dates` for a list of formats valid for -d/--date.
4986
5000
4987 Returns 0 on success.
5001 Returns 0 on success.
4988 """
5002 """
4989
5003
4990 if opts.get("date"):
5004 if opts.get("date"):
4991 if opts.get("rev"):
5005 if opts.get("rev"):
4992 raise util.Abort(_("you can't specify a revision and a date"))
5006 raise util.Abort(_("you can't specify a revision and a date"))
4993 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5007 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4994
5008
4995 parent, p2 = repo.dirstate.parents()
5009 parent, p2 = repo.dirstate.parents()
4996 if not opts.get('rev') and p2 != nullid:
5010 if not opts.get('rev') and p2 != nullid:
4997 # revert after merge is a trap for new users (issue2915)
5011 # revert after merge is a trap for new users (issue2915)
4998 raise util.Abort(_('uncommitted merge with no revision specified'),
5012 raise util.Abort(_('uncommitted merge with no revision specified'),
4999 hint=_('use "hg update" or see "hg help revert"'))
5013 hint=_('use "hg update" or see "hg help revert"'))
5000
5014
5001 ctx = scmutil.revsingle(repo, opts.get('rev'))
5015 ctx = scmutil.revsingle(repo, opts.get('rev'))
5002
5016
5003 if not pats and not opts.get('all'):
5017 if not pats and not opts.get('all'):
5004 msg = _("no files or directories specified")
5018 msg = _("no files or directories specified")
5005 if p2 != nullid:
5019 if p2 != nullid:
5006 hint = _("uncommitted merge, use --all to discard all changes,"
5020 hint = _("uncommitted merge, use --all to discard all changes,"
5007 " or 'hg update -C .' to abort the merge")
5021 " or 'hg update -C .' to abort the merge")
5008 raise util.Abort(msg, hint=hint)
5022 raise util.Abort(msg, hint=hint)
5009 dirty = util.any(repo.status())
5023 dirty = util.any(repo.status())
5010 node = ctx.node()
5024 node = ctx.node()
5011 if node != parent:
5025 if node != parent:
5012 if dirty:
5026 if dirty:
5013 hint = _("uncommitted changes, use --all to discard all"
5027 hint = _("uncommitted changes, use --all to discard all"
5014 " changes, or 'hg update %s' to update") % ctx.rev()
5028 " changes, or 'hg update %s' to update") % ctx.rev()
5015 else:
5029 else:
5016 hint = _("use --all to revert all files,"
5030 hint = _("use --all to revert all files,"
5017 " or 'hg update %s' to update") % ctx.rev()
5031 " or 'hg update %s' to update") % ctx.rev()
5018 elif dirty:
5032 elif dirty:
5019 hint = _("uncommitted changes, use --all to discard all changes")
5033 hint = _("uncommitted changes, use --all to discard all changes")
5020 else:
5034 else:
5021 hint = _("use --all to revert all files")
5035 hint = _("use --all to revert all files")
5022 raise util.Abort(msg, hint=hint)
5036 raise util.Abort(msg, hint=hint)
5023
5037
5024 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5038 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5025
5039
5026 @command('rollback', dryrunopts +
5040 @command('rollback', dryrunopts +
5027 [('f', 'force', False, _('ignore safety measures'))])
5041 [('f', 'force', False, _('ignore safety measures'))])
5028 def rollback(ui, repo, **opts):
5042 def rollback(ui, repo, **opts):
5029 """roll back the last transaction (dangerous)
5043 """roll back the last transaction (dangerous)
5030
5044
5031 This command should be used with care. There is only one level of
5045 This command should be used with care. There is only one level of
5032 rollback, and there is no way to undo a rollback. It will also
5046 rollback, and there is no way to undo a rollback. It will also
5033 restore the dirstate at the time of the last transaction, losing
5047 restore the dirstate at the time of the last transaction, losing
5034 any dirstate changes since that time. This command does not alter
5048 any dirstate changes since that time. This command does not alter
5035 the working directory.
5049 the working directory.
5036
5050
5037 Transactions are used to encapsulate the effects of all commands
5051 Transactions are used to encapsulate the effects of all commands
5038 that create new changesets or propagate existing changesets into a
5052 that create new changesets or propagate existing changesets into a
5039 repository.
5053 repository.
5040
5054
5041 .. container:: verbose
5055 .. container:: verbose
5042
5056
5043 For example, the following commands are transactional, and their
5057 For example, the following commands are transactional, and their
5044 effects can be rolled back:
5058 effects can be rolled back:
5045
5059
5046 - commit
5060 - commit
5047 - import
5061 - import
5048 - pull
5062 - pull
5049 - push (with this repository as the destination)
5063 - push (with this repository as the destination)
5050 - unbundle
5064 - unbundle
5051
5065
5052 To avoid permanent data loss, rollback will refuse to rollback a
5066 To avoid permanent data loss, rollback will refuse to rollback a
5053 commit transaction if it isn't checked out. Use --force to
5067 commit transaction if it isn't checked out. Use --force to
5054 override this protection.
5068 override this protection.
5055
5069
5056 This command is not intended for use on public repositories. Once
5070 This command is not intended for use on public repositories. Once
5057 changes are visible for pull by other users, rolling a transaction
5071 changes are visible for pull by other users, rolling a transaction
5058 back locally is ineffective (someone else may already have pulled
5072 back locally is ineffective (someone else may already have pulled
5059 the changes). Furthermore, a race is possible with readers of the
5073 the changes). Furthermore, a race is possible with readers of the
5060 repository; for example an in-progress pull from the repository
5074 repository; for example an in-progress pull from the repository
5061 may fail if a rollback is performed.
5075 may fail if a rollback is performed.
5062
5076
5063 Returns 0 on success, 1 if no rollback data is available.
5077 Returns 0 on success, 1 if no rollback data is available.
5064 """
5078 """
5065 return repo.rollback(dryrun=opts.get('dry_run'),
5079 return repo.rollback(dryrun=opts.get('dry_run'),
5066 force=opts.get('force'))
5080 force=opts.get('force'))
5067
5081
5068 @command('root', [])
5082 @command('root', [])
5069 def root(ui, repo):
5083 def root(ui, repo):
5070 """print the root (top) of the current working directory
5084 """print the root (top) of the current working directory
5071
5085
5072 Print the root directory of the current repository.
5086 Print the root directory of the current repository.
5073
5087
5074 Returns 0 on success.
5088 Returns 0 on success.
5075 """
5089 """
5076 ui.write(repo.root + "\n")
5090 ui.write(repo.root + "\n")
5077
5091
5078 @command('^serve',
5092 @command('^serve',
5079 [('A', 'accesslog', '', _('name of access log file to write to'),
5093 [('A', 'accesslog', '', _('name of access log file to write to'),
5080 _('FILE')),
5094 _('FILE')),
5081 ('d', 'daemon', None, _('run server in background')),
5095 ('d', 'daemon', None, _('run server in background')),
5082 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5096 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5083 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5097 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5084 # use string type, then we can check if something was passed
5098 # use string type, then we can check if something was passed
5085 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5099 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5086 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5100 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5087 _('ADDR')),
5101 _('ADDR')),
5088 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5102 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5089 _('PREFIX')),
5103 _('PREFIX')),
5090 ('n', 'name', '',
5104 ('n', 'name', '',
5091 _('name to show in web pages (default: working directory)'), _('NAME')),
5105 _('name to show in web pages (default: working directory)'), _('NAME')),
5092 ('', 'web-conf', '',
5106 ('', 'web-conf', '',
5093 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5107 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5094 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5108 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5095 _('FILE')),
5109 _('FILE')),
5096 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5110 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5097 ('', 'stdio', None, _('for remote clients')),
5111 ('', 'stdio', None, _('for remote clients')),
5098 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5112 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5099 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5113 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5100 ('', 'style', '', _('template style to use'), _('STYLE')),
5114 ('', 'style', '', _('template style to use'), _('STYLE')),
5101 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5115 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5102 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5116 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5103 _('[OPTION]...'))
5117 _('[OPTION]...'))
5104 def serve(ui, repo, **opts):
5118 def serve(ui, repo, **opts):
5105 """start stand-alone webserver
5119 """start stand-alone webserver
5106
5120
5107 Start a local HTTP repository browser and pull server. You can use
5121 Start a local HTTP repository browser and pull server. You can use
5108 this for ad-hoc sharing and browsing of repositories. It is
5122 this for ad-hoc sharing and browsing of repositories. It is
5109 recommended to use a real web server to serve a repository for
5123 recommended to use a real web server to serve a repository for
5110 longer periods of time.
5124 longer periods of time.
5111
5125
5112 Please note that the server does not implement access control.
5126 Please note that the server does not implement access control.
5113 This means that, by default, anybody can read from the server and
5127 This means that, by default, anybody can read from the server and
5114 nobody can write to it by default. Set the ``web.allow_push``
5128 nobody can write to it by default. Set the ``web.allow_push``
5115 option to ``*`` to allow everybody to push to the server. You
5129 option to ``*`` to allow everybody to push to the server. You
5116 should use a real web server if you need to authenticate users.
5130 should use a real web server if you need to authenticate users.
5117
5131
5118 By default, the server logs accesses to stdout and errors to
5132 By default, the server logs accesses to stdout and errors to
5119 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5133 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5120 files.
5134 files.
5121
5135
5122 To have the server choose a free port number to listen on, specify
5136 To have the server choose a free port number to listen on, specify
5123 a port number of 0; in this case, the server will print the port
5137 a port number of 0; in this case, the server will print the port
5124 number it uses.
5138 number it uses.
5125
5139
5126 Returns 0 on success.
5140 Returns 0 on success.
5127 """
5141 """
5128
5142
5129 if opts["stdio"] and opts["cmdserver"]:
5143 if opts["stdio"] and opts["cmdserver"]:
5130 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5144 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5131
5145
5132 def checkrepo():
5146 def checkrepo():
5133 if repo is None:
5147 if repo is None:
5134 raise error.RepoError(_("there is no Mercurial repository here"
5148 raise error.RepoError(_("there is no Mercurial repository here"
5135 " (.hg not found)"))
5149 " (.hg not found)"))
5136
5150
5137 if opts["stdio"]:
5151 if opts["stdio"]:
5138 checkrepo()
5152 checkrepo()
5139 s = sshserver.sshserver(ui, repo)
5153 s = sshserver.sshserver(ui, repo)
5140 s.serve_forever()
5154 s.serve_forever()
5141
5155
5142 if opts["cmdserver"]:
5156 if opts["cmdserver"]:
5143 checkrepo()
5157 checkrepo()
5144 s = commandserver.server(ui, repo, opts["cmdserver"])
5158 s = commandserver.server(ui, repo, opts["cmdserver"])
5145 return s.serve()
5159 return s.serve()
5146
5160
5147 # this way we can check if something was given in the command-line
5161 # this way we can check if something was given in the command-line
5148 if opts.get('port'):
5162 if opts.get('port'):
5149 opts['port'] = util.getport(opts.get('port'))
5163 opts['port'] = util.getport(opts.get('port'))
5150
5164
5151 baseui = repo and repo.baseui or ui
5165 baseui = repo and repo.baseui or ui
5152 optlist = ("name templates style address port prefix ipv6"
5166 optlist = ("name templates style address port prefix ipv6"
5153 " accesslog errorlog certificate encoding")
5167 " accesslog errorlog certificate encoding")
5154 for o in optlist.split():
5168 for o in optlist.split():
5155 val = opts.get(o, '')
5169 val = opts.get(o, '')
5156 if val in (None, ''): # should check against default options instead
5170 if val in (None, ''): # should check against default options instead
5157 continue
5171 continue
5158 baseui.setconfig("web", o, val)
5172 baseui.setconfig("web", o, val)
5159 if repo and repo.ui != baseui:
5173 if repo and repo.ui != baseui:
5160 repo.ui.setconfig("web", o, val)
5174 repo.ui.setconfig("web", o, val)
5161
5175
5162 o = opts.get('web_conf') or opts.get('webdir_conf')
5176 o = opts.get('web_conf') or opts.get('webdir_conf')
5163 if not o:
5177 if not o:
5164 if not repo:
5178 if not repo:
5165 raise error.RepoError(_("there is no Mercurial repository"
5179 raise error.RepoError(_("there is no Mercurial repository"
5166 " here (.hg not found)"))
5180 " here (.hg not found)"))
5167 o = repo.root
5181 o = repo.root
5168
5182
5169 app = hgweb.hgweb(o, baseui=ui)
5183 app = hgweb.hgweb(o, baseui=ui)
5170
5184
5171 class service(object):
5185 class service(object):
5172 def init(self):
5186 def init(self):
5173 util.setsignalhandler()
5187 util.setsignalhandler()
5174 self.httpd = hgweb.server.create_server(ui, app)
5188 self.httpd = hgweb.server.create_server(ui, app)
5175
5189
5176 if opts['port'] and not ui.verbose:
5190 if opts['port'] and not ui.verbose:
5177 return
5191 return
5178
5192
5179 if self.httpd.prefix:
5193 if self.httpd.prefix:
5180 prefix = self.httpd.prefix.strip('/') + '/'
5194 prefix = self.httpd.prefix.strip('/') + '/'
5181 else:
5195 else:
5182 prefix = ''
5196 prefix = ''
5183
5197
5184 port = ':%d' % self.httpd.port
5198 port = ':%d' % self.httpd.port
5185 if port == ':80':
5199 if port == ':80':
5186 port = ''
5200 port = ''
5187
5201
5188 bindaddr = self.httpd.addr
5202 bindaddr = self.httpd.addr
5189 if bindaddr == '0.0.0.0':
5203 if bindaddr == '0.0.0.0':
5190 bindaddr = '*'
5204 bindaddr = '*'
5191 elif ':' in bindaddr: # IPv6
5205 elif ':' in bindaddr: # IPv6
5192 bindaddr = '[%s]' % bindaddr
5206 bindaddr = '[%s]' % bindaddr
5193
5207
5194 fqaddr = self.httpd.fqaddr
5208 fqaddr = self.httpd.fqaddr
5195 if ':' in fqaddr:
5209 if ':' in fqaddr:
5196 fqaddr = '[%s]' % fqaddr
5210 fqaddr = '[%s]' % fqaddr
5197 if opts['port']:
5211 if opts['port']:
5198 write = ui.status
5212 write = ui.status
5199 else:
5213 else:
5200 write = ui.write
5214 write = ui.write
5201 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5215 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5202 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5216 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5203
5217
5204 def run(self):
5218 def run(self):
5205 self.httpd.serve_forever()
5219 self.httpd.serve_forever()
5206
5220
5207 service = service()
5221 service = service()
5208
5222
5209 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5223 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5210
5224
5211 @command('showconfig|debugconfig',
5225 @command('showconfig|debugconfig',
5212 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5226 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5213 _('[-u] [NAME]...'))
5227 _('[-u] [NAME]...'))
5214 def showconfig(ui, repo, *values, **opts):
5228 def showconfig(ui, repo, *values, **opts):
5215 """show combined config settings from all hgrc files
5229 """show combined config settings from all hgrc files
5216
5230
5217 With no arguments, print names and values of all config items.
5231 With no arguments, print names and values of all config items.
5218
5232
5219 With one argument of the form section.name, print just the value
5233 With one argument of the form section.name, print just the value
5220 of that config item.
5234 of that config item.
5221
5235
5222 With multiple arguments, print names and values of all config
5236 With multiple arguments, print names and values of all config
5223 items with matching section names.
5237 items with matching section names.
5224
5238
5225 With --debug, the source (filename and line number) is printed
5239 With --debug, the source (filename and line number) is printed
5226 for each config item.
5240 for each config item.
5227
5241
5228 Returns 0 on success.
5242 Returns 0 on success.
5229 """
5243 """
5230
5244
5231 for f in scmutil.rcpath():
5245 for f in scmutil.rcpath():
5232 ui.debug('read config from: %s\n' % f)
5246 ui.debug('read config from: %s\n' % f)
5233 untrusted = bool(opts.get('untrusted'))
5247 untrusted = bool(opts.get('untrusted'))
5234 if values:
5248 if values:
5235 sections = [v for v in values if '.' not in v]
5249 sections = [v for v in values if '.' not in v]
5236 items = [v for v in values if '.' in v]
5250 items = [v for v in values if '.' in v]
5237 if len(items) > 1 or items and sections:
5251 if len(items) > 1 or items and sections:
5238 raise util.Abort(_('only one config item permitted'))
5252 raise util.Abort(_('only one config item permitted'))
5239 for section, name, value in ui.walkconfig(untrusted=untrusted):
5253 for section, name, value in ui.walkconfig(untrusted=untrusted):
5240 value = str(value).replace('\n', '\\n')
5254 value = str(value).replace('\n', '\\n')
5241 sectname = section + '.' + name
5255 sectname = section + '.' + name
5242 if values:
5256 if values:
5243 for v in values:
5257 for v in values:
5244 if v == section:
5258 if v == section:
5245 ui.debug('%s: ' %
5259 ui.debug('%s: ' %
5246 ui.configsource(section, name, untrusted))
5260 ui.configsource(section, name, untrusted))
5247 ui.write('%s=%s\n' % (sectname, value))
5261 ui.write('%s=%s\n' % (sectname, value))
5248 elif v == sectname:
5262 elif v == sectname:
5249 ui.debug('%s: ' %
5263 ui.debug('%s: ' %
5250 ui.configsource(section, name, untrusted))
5264 ui.configsource(section, name, untrusted))
5251 ui.write(value, '\n')
5265 ui.write(value, '\n')
5252 else:
5266 else:
5253 ui.debug('%s: ' %
5267 ui.debug('%s: ' %
5254 ui.configsource(section, name, untrusted))
5268 ui.configsource(section, name, untrusted))
5255 ui.write('%s=%s\n' % (sectname, value))
5269 ui.write('%s=%s\n' % (sectname, value))
5256
5270
5257 @command('^status|st',
5271 @command('^status|st',
5258 [('A', 'all', None, _('show status of all files')),
5272 [('A', 'all', None, _('show status of all files')),
5259 ('m', 'modified', None, _('show only modified files')),
5273 ('m', 'modified', None, _('show only modified files')),
5260 ('a', 'added', None, _('show only added files')),
5274 ('a', 'added', None, _('show only added files')),
5261 ('r', 'removed', None, _('show only removed files')),
5275 ('r', 'removed', None, _('show only removed files')),
5262 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5276 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5263 ('c', 'clean', None, _('show only files without changes')),
5277 ('c', 'clean', None, _('show only files without changes')),
5264 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5278 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5265 ('i', 'ignored', None, _('show only ignored files')),
5279 ('i', 'ignored', None, _('show only ignored files')),
5266 ('n', 'no-status', None, _('hide status prefix')),
5280 ('n', 'no-status', None, _('hide status prefix')),
5267 ('C', 'copies', None, _('show source of copied files')),
5281 ('C', 'copies', None, _('show source of copied files')),
5268 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5282 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5269 ('', 'rev', [], _('show difference from revision'), _('REV')),
5283 ('', 'rev', [], _('show difference from revision'), _('REV')),
5270 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5284 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5271 ] + walkopts + subrepoopts,
5285 ] + walkopts + subrepoopts,
5272 _('[OPTION]... [FILE]...'))
5286 _('[OPTION]... [FILE]...'))
5273 def status(ui, repo, *pats, **opts):
5287 def status(ui, repo, *pats, **opts):
5274 """show changed files in the working directory
5288 """show changed files in the working directory
5275
5289
5276 Show status of files in the repository. If names are given, only
5290 Show status of files in the repository. If names are given, only
5277 files that match are shown. Files that are clean or ignored or
5291 files that match are shown. Files that are clean or ignored or
5278 the source of a copy/move operation, are not listed unless
5292 the source of a copy/move operation, are not listed unless
5279 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5293 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5280 Unless options described with "show only ..." are given, the
5294 Unless options described with "show only ..." are given, the
5281 options -mardu are used.
5295 options -mardu are used.
5282
5296
5283 Option -q/--quiet hides untracked (unknown and ignored) files
5297 Option -q/--quiet hides untracked (unknown and ignored) files
5284 unless explicitly requested with -u/--unknown or -i/--ignored.
5298 unless explicitly requested with -u/--unknown or -i/--ignored.
5285
5299
5286 .. note::
5300 .. note::
5287 status may appear to disagree with diff if permissions have
5301 status may appear to disagree with diff if permissions have
5288 changed or a merge has occurred. The standard diff format does
5302 changed or a merge has occurred. The standard diff format does
5289 not report permission changes and diff only reports changes
5303 not report permission changes and diff only reports changes
5290 relative to one merge parent.
5304 relative to one merge parent.
5291
5305
5292 If one revision is given, it is used as the base revision.
5306 If one revision is given, it is used as the base revision.
5293 If two revisions are given, the differences between them are
5307 If two revisions are given, the differences between them are
5294 shown. The --change option can also be used as a shortcut to list
5308 shown. The --change option can also be used as a shortcut to list
5295 the changed files of a revision from its first parent.
5309 the changed files of a revision from its first parent.
5296
5310
5297 The codes used to show the status of files are::
5311 The codes used to show the status of files are::
5298
5312
5299 M = modified
5313 M = modified
5300 A = added
5314 A = added
5301 R = removed
5315 R = removed
5302 C = clean
5316 C = clean
5303 ! = missing (deleted by non-hg command, but still tracked)
5317 ! = missing (deleted by non-hg command, but still tracked)
5304 ? = not tracked
5318 ? = not tracked
5305 I = ignored
5319 I = ignored
5306 = origin of the previous file listed as A (added)
5320 = origin of the previous file listed as A (added)
5307
5321
5308 .. container:: verbose
5322 .. container:: verbose
5309
5323
5310 Examples:
5324 Examples:
5311
5325
5312 - show changes in the working directory relative to a
5326 - show changes in the working directory relative to a
5313 changeset::
5327 changeset::
5314
5328
5315 hg status --rev 9353
5329 hg status --rev 9353
5316
5330
5317 - show all changes including copies in an existing changeset::
5331 - show all changes including copies in an existing changeset::
5318
5332
5319 hg status --copies --change 9353
5333 hg status --copies --change 9353
5320
5334
5321 - get a NUL separated list of added files, suitable for xargs::
5335 - get a NUL separated list of added files, suitable for xargs::
5322
5336
5323 hg status -an0
5337 hg status -an0
5324
5338
5325 Returns 0 on success.
5339 Returns 0 on success.
5326 """
5340 """
5327
5341
5328 revs = opts.get('rev')
5342 revs = opts.get('rev')
5329 change = opts.get('change')
5343 change = opts.get('change')
5330
5344
5331 if revs and change:
5345 if revs and change:
5332 msg = _('cannot specify --rev and --change at the same time')
5346 msg = _('cannot specify --rev and --change at the same time')
5333 raise util.Abort(msg)
5347 raise util.Abort(msg)
5334 elif change:
5348 elif change:
5335 node2 = scmutil.revsingle(repo, change, None).node()
5349 node2 = scmutil.revsingle(repo, change, None).node()
5336 node1 = repo[node2].p1().node()
5350 node1 = repo[node2].p1().node()
5337 else:
5351 else:
5338 node1, node2 = scmutil.revpair(repo, revs)
5352 node1, node2 = scmutil.revpair(repo, revs)
5339
5353
5340 cwd = (pats and repo.getcwd()) or ''
5354 cwd = (pats and repo.getcwd()) or ''
5341 end = opts.get('print0') and '\0' or '\n'
5355 end = opts.get('print0') and '\0' or '\n'
5342 copy = {}
5356 copy = {}
5343 states = 'modified added removed deleted unknown ignored clean'.split()
5357 states = 'modified added removed deleted unknown ignored clean'.split()
5344 show = [k for k in states if opts.get(k)]
5358 show = [k for k in states if opts.get(k)]
5345 if opts.get('all'):
5359 if opts.get('all'):
5346 show += ui.quiet and (states[:4] + ['clean']) or states
5360 show += ui.quiet and (states[:4] + ['clean']) or states
5347 if not show:
5361 if not show:
5348 show = ui.quiet and states[:4] or states[:5]
5362 show = ui.quiet and states[:4] or states[:5]
5349
5363
5350 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5364 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5351 'ignored' in show, 'clean' in show, 'unknown' in show,
5365 'ignored' in show, 'clean' in show, 'unknown' in show,
5352 opts.get('subrepos'))
5366 opts.get('subrepos'))
5353 changestates = zip(states, 'MAR!?IC', stat)
5367 changestates = zip(states, 'MAR!?IC', stat)
5354
5368
5355 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5369 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5356 copy = copies.pathcopies(repo[node1], repo[node2])
5370 copy = copies.pathcopies(repo[node1], repo[node2])
5357
5371
5358 fm = ui.formatter('status', opts)
5372 fm = ui.formatter('status', opts)
5359 format = '%s %s' + end
5373 format = '%s %s' + end
5360 if opts.get('no_status'):
5374 if opts.get('no_status'):
5361 format = '%.0s%s' + end
5375 format = '%.0s%s' + end
5362
5376
5363 for state, char, files in changestates:
5377 for state, char, files in changestates:
5364 if state in show:
5378 if state in show:
5365 label = 'status.' + state
5379 label = 'status.' + state
5366 for f in files:
5380 for f in files:
5367 fm.startitem()
5381 fm.startitem()
5368 fm.write("status path", format, char,
5382 fm.write("status path", format, char,
5369 repo.pathto(f, cwd), label=label)
5383 repo.pathto(f, cwd), label=label)
5370 if f in copy:
5384 if f in copy:
5371 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5385 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5372 label='status.copied')
5386 label='status.copied')
5373 fm.end()
5387 fm.end()
5374
5388
5375 @command('^summary|sum',
5389 @command('^summary|sum',
5376 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5390 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5377 def summary(ui, repo, **opts):
5391 def summary(ui, repo, **opts):
5378 """summarize working directory state
5392 """summarize working directory state
5379
5393
5380 This generates a brief summary of the working directory state,
5394 This generates a brief summary of the working directory state,
5381 including parents, branch, commit status, and available updates.
5395 including parents, branch, commit status, and available updates.
5382
5396
5383 With the --remote option, this will check the default paths for
5397 With the --remote option, this will check the default paths for
5384 incoming and outgoing changes. This can be time-consuming.
5398 incoming and outgoing changes. This can be time-consuming.
5385
5399
5386 Returns 0 on success.
5400 Returns 0 on success.
5387 """
5401 """
5388
5402
5389 ctx = repo[None]
5403 ctx = repo[None]
5390 parents = ctx.parents()
5404 parents = ctx.parents()
5391 pnode = parents[0].node()
5405 pnode = parents[0].node()
5392 marks = []
5406 marks = []
5393
5407
5394 for p in parents:
5408 for p in parents:
5395 # label with log.changeset (instead of log.parent) since this
5409 # label with log.changeset (instead of log.parent) since this
5396 # shows a working directory parent *changeset*:
5410 # shows a working directory parent *changeset*:
5397 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5411 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5398 label='log.changeset')
5412 label='log.changeset')
5399 ui.write(' '.join(p.tags()), label='log.tag')
5413 ui.write(' '.join(p.tags()), label='log.tag')
5400 if p.bookmarks():
5414 if p.bookmarks():
5401 marks.extend(p.bookmarks())
5415 marks.extend(p.bookmarks())
5402 if p.rev() == -1:
5416 if p.rev() == -1:
5403 if not len(repo):
5417 if not len(repo):
5404 ui.write(_(' (empty repository)'))
5418 ui.write(_(' (empty repository)'))
5405 else:
5419 else:
5406 ui.write(_(' (no revision checked out)'))
5420 ui.write(_(' (no revision checked out)'))
5407 ui.write('\n')
5421 ui.write('\n')
5408 if p.description():
5422 if p.description():
5409 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5423 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5410 label='log.summary')
5424 label='log.summary')
5411
5425
5412 branch = ctx.branch()
5426 branch = ctx.branch()
5413 bheads = repo.branchheads(branch)
5427 bheads = repo.branchheads(branch)
5414 m = _('branch: %s\n') % branch
5428 m = _('branch: %s\n') % branch
5415 if branch != 'default':
5429 if branch != 'default':
5416 ui.write(m, label='log.branch')
5430 ui.write(m, label='log.branch')
5417 else:
5431 else:
5418 ui.status(m, label='log.branch')
5432 ui.status(m, label='log.branch')
5419
5433
5420 if marks:
5434 if marks:
5421 current = repo._bookmarkcurrent
5435 current = repo._bookmarkcurrent
5422 ui.write(_('bookmarks:'), label='log.bookmark')
5436 ui.write(_('bookmarks:'), label='log.bookmark')
5423 if current is not None:
5437 if current is not None:
5424 try:
5438 try:
5425 marks.remove(current)
5439 marks.remove(current)
5426 ui.write(' *' + current, label='bookmarks.current')
5440 ui.write(' *' + current, label='bookmarks.current')
5427 except ValueError:
5441 except ValueError:
5428 # current bookmark not in parent ctx marks
5442 # current bookmark not in parent ctx marks
5429 pass
5443 pass
5430 for m in marks:
5444 for m in marks:
5431 ui.write(' ' + m, label='log.bookmark')
5445 ui.write(' ' + m, label='log.bookmark')
5432 ui.write('\n', label='log.bookmark')
5446 ui.write('\n', label='log.bookmark')
5433
5447
5434 st = list(repo.status(unknown=True))[:6]
5448 st = list(repo.status(unknown=True))[:6]
5435
5449
5436 c = repo.dirstate.copies()
5450 c = repo.dirstate.copies()
5437 copied, renamed = [], []
5451 copied, renamed = [], []
5438 for d, s in c.iteritems():
5452 for d, s in c.iteritems():
5439 if s in st[2]:
5453 if s in st[2]:
5440 st[2].remove(s)
5454 st[2].remove(s)
5441 renamed.append(d)
5455 renamed.append(d)
5442 else:
5456 else:
5443 copied.append(d)
5457 copied.append(d)
5444 if d in st[1]:
5458 if d in st[1]:
5445 st[1].remove(d)
5459 st[1].remove(d)
5446 st.insert(3, renamed)
5460 st.insert(3, renamed)
5447 st.insert(4, copied)
5461 st.insert(4, copied)
5448
5462
5449 ms = mergemod.mergestate(repo)
5463 ms = mergemod.mergestate(repo)
5450 st.append([f for f in ms if ms[f] == 'u'])
5464 st.append([f for f in ms if ms[f] == 'u'])
5451
5465
5452 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5466 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5453 st.append(subs)
5467 st.append(subs)
5454
5468
5455 labels = [ui.label(_('%d modified'), 'status.modified'),
5469 labels = [ui.label(_('%d modified'), 'status.modified'),
5456 ui.label(_('%d added'), 'status.added'),
5470 ui.label(_('%d added'), 'status.added'),
5457 ui.label(_('%d removed'), 'status.removed'),
5471 ui.label(_('%d removed'), 'status.removed'),
5458 ui.label(_('%d renamed'), 'status.copied'),
5472 ui.label(_('%d renamed'), 'status.copied'),
5459 ui.label(_('%d copied'), 'status.copied'),
5473 ui.label(_('%d copied'), 'status.copied'),
5460 ui.label(_('%d deleted'), 'status.deleted'),
5474 ui.label(_('%d deleted'), 'status.deleted'),
5461 ui.label(_('%d unknown'), 'status.unknown'),
5475 ui.label(_('%d unknown'), 'status.unknown'),
5462 ui.label(_('%d ignored'), 'status.ignored'),
5476 ui.label(_('%d ignored'), 'status.ignored'),
5463 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5477 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5464 ui.label(_('%d subrepos'), 'status.modified')]
5478 ui.label(_('%d subrepos'), 'status.modified')]
5465 t = []
5479 t = []
5466 for s, l in zip(st, labels):
5480 for s, l in zip(st, labels):
5467 if s:
5481 if s:
5468 t.append(l % len(s))
5482 t.append(l % len(s))
5469
5483
5470 t = ', '.join(t)
5484 t = ', '.join(t)
5471 cleanworkdir = False
5485 cleanworkdir = False
5472
5486
5473 if len(parents) > 1:
5487 if len(parents) > 1:
5474 t += _(' (merge)')
5488 t += _(' (merge)')
5475 elif branch != parents[0].branch():
5489 elif branch != parents[0].branch():
5476 t += _(' (new branch)')
5490 t += _(' (new branch)')
5477 elif (parents[0].closesbranch() and
5491 elif (parents[0].closesbranch() and
5478 pnode in repo.branchheads(branch, closed=True)):
5492 pnode in repo.branchheads(branch, closed=True)):
5479 t += _(' (head closed)')
5493 t += _(' (head closed)')
5480 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5494 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5481 t += _(' (clean)')
5495 t += _(' (clean)')
5482 cleanworkdir = True
5496 cleanworkdir = True
5483 elif pnode not in bheads:
5497 elif pnode not in bheads:
5484 t += _(' (new branch head)')
5498 t += _(' (new branch head)')
5485
5499
5486 if cleanworkdir:
5500 if cleanworkdir:
5487 ui.status(_('commit: %s\n') % t.strip())
5501 ui.status(_('commit: %s\n') % t.strip())
5488 else:
5502 else:
5489 ui.write(_('commit: %s\n') % t.strip())
5503 ui.write(_('commit: %s\n') % t.strip())
5490
5504
5491 # all ancestors of branch heads - all ancestors of parent = new csets
5505 # all ancestors of branch heads - all ancestors of parent = new csets
5492 new = [0] * len(repo)
5506 new = [0] * len(repo)
5493 cl = repo.changelog
5507 cl = repo.changelog
5494 for a in [cl.rev(n) for n in bheads]:
5508 for a in [cl.rev(n) for n in bheads]:
5495 new[a] = 1
5509 new[a] = 1
5496 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5510 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5497 new[a] = 1
5511 new[a] = 1
5498 for a in [p.rev() for p in parents]:
5512 for a in [p.rev() for p in parents]:
5499 if a >= 0:
5513 if a >= 0:
5500 new[a] = 0
5514 new[a] = 0
5501 for a in cl.ancestors([p.rev() for p in parents]):
5515 for a in cl.ancestors([p.rev() for p in parents]):
5502 new[a] = 0
5516 new[a] = 0
5503 new = sum(new)
5517 new = sum(new)
5504
5518
5505 if new == 0:
5519 if new == 0:
5506 ui.status(_('update: (current)\n'))
5520 ui.status(_('update: (current)\n'))
5507 elif pnode not in bheads:
5521 elif pnode not in bheads:
5508 ui.write(_('update: %d new changesets (update)\n') % new)
5522 ui.write(_('update: %d new changesets (update)\n') % new)
5509 else:
5523 else:
5510 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5524 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5511 (new, len(bheads)))
5525 (new, len(bheads)))
5512
5526
5513 if opts.get('remote'):
5527 if opts.get('remote'):
5514 t = []
5528 t = []
5515 source, branches = hg.parseurl(ui.expandpath('default'))
5529 source, branches = hg.parseurl(ui.expandpath('default'))
5516 other = hg.peer(repo, {}, source)
5530 other = hg.peer(repo, {}, source)
5517 revs, checkout = hg.addbranchrevs(repo, other, branches,
5531 revs, checkout = hg.addbranchrevs(repo, other, branches,
5518 opts.get('rev'))
5532 opts.get('rev'))
5519 ui.debug('comparing with %s\n' % util.hidepassword(source))
5533 ui.debug('comparing with %s\n' % util.hidepassword(source))
5520 repo.ui.pushbuffer()
5534 repo.ui.pushbuffer()
5521 commoninc = discovery.findcommonincoming(repo, other)
5535 commoninc = discovery.findcommonincoming(repo, other)
5522 _common, incoming, _rheads = commoninc
5536 _common, incoming, _rheads = commoninc
5523 repo.ui.popbuffer()
5537 repo.ui.popbuffer()
5524 if incoming:
5538 if incoming:
5525 t.append(_('1 or more incoming'))
5539 t.append(_('1 or more incoming'))
5526
5540
5527 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5541 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5528 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5542 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5529 if source != dest:
5543 if source != dest:
5530 other = hg.peer(repo, {}, dest)
5544 other = hg.peer(repo, {}, dest)
5531 commoninc = None
5545 commoninc = None
5532 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5546 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5533 repo.ui.pushbuffer()
5547 repo.ui.pushbuffer()
5534 outgoing = discovery.findcommonoutgoing(repo, other,
5548 outgoing = discovery.findcommonoutgoing(repo, other,
5535 commoninc=commoninc)
5549 commoninc=commoninc)
5536 repo.ui.popbuffer()
5550 repo.ui.popbuffer()
5537 o = outgoing.missing
5551 o = outgoing.missing
5538 if o:
5552 if o:
5539 t.append(_('%d outgoing') % len(o))
5553 t.append(_('%d outgoing') % len(o))
5540 if 'bookmarks' in other.listkeys('namespaces'):
5554 if 'bookmarks' in other.listkeys('namespaces'):
5541 lmarks = repo.listkeys('bookmarks')
5555 lmarks = repo.listkeys('bookmarks')
5542 rmarks = other.listkeys('bookmarks')
5556 rmarks = other.listkeys('bookmarks')
5543 diff = set(rmarks) - set(lmarks)
5557 diff = set(rmarks) - set(lmarks)
5544 if len(diff) > 0:
5558 if len(diff) > 0:
5545 t.append(_('%d incoming bookmarks') % len(diff))
5559 t.append(_('%d incoming bookmarks') % len(diff))
5546 diff = set(lmarks) - set(rmarks)
5560 diff = set(lmarks) - set(rmarks)
5547 if len(diff) > 0:
5561 if len(diff) > 0:
5548 t.append(_('%d outgoing bookmarks') % len(diff))
5562 t.append(_('%d outgoing bookmarks') % len(diff))
5549
5563
5550 if t:
5564 if t:
5551 ui.write(_('remote: %s\n') % (', '.join(t)))
5565 ui.write(_('remote: %s\n') % (', '.join(t)))
5552 else:
5566 else:
5553 ui.status(_('remote: (synced)\n'))
5567 ui.status(_('remote: (synced)\n'))
5554
5568
5555 @command('tag',
5569 @command('tag',
5556 [('f', 'force', None, _('force tag')),
5570 [('f', 'force', None, _('force tag')),
5557 ('l', 'local', None, _('make the tag local')),
5571 ('l', 'local', None, _('make the tag local')),
5558 ('r', 'rev', '', _('revision to tag'), _('REV')),
5572 ('r', 'rev', '', _('revision to tag'), _('REV')),
5559 ('', 'remove', None, _('remove a tag')),
5573 ('', 'remove', None, _('remove a tag')),
5560 # -l/--local is already there, commitopts cannot be used
5574 # -l/--local is already there, commitopts cannot be used
5561 ('e', 'edit', None, _('edit commit message')),
5575 ('e', 'edit', None, _('edit commit message')),
5562 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5576 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5563 ] + commitopts2,
5577 ] + commitopts2,
5564 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5578 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5565 def tag(ui, repo, name1, *names, **opts):
5579 def tag(ui, repo, name1, *names, **opts):
5566 """add one or more tags for the current or given revision
5580 """add one or more tags for the current or given revision
5567
5581
5568 Name a particular revision using <name>.
5582 Name a particular revision using <name>.
5569
5583
5570 Tags are used to name particular revisions of the repository and are
5584 Tags are used to name particular revisions of the repository and are
5571 very useful to compare different revisions, to go back to significant
5585 very useful to compare different revisions, to go back to significant
5572 earlier versions or to mark branch points as releases, etc. Changing
5586 earlier versions or to mark branch points as releases, etc. Changing
5573 an existing tag is normally disallowed; use -f/--force to override.
5587 an existing tag is normally disallowed; use -f/--force to override.
5574
5588
5575 If no revision is given, the parent of the working directory is
5589 If no revision is given, the parent of the working directory is
5576 used, or tip if no revision is checked out.
5590 used, or tip if no revision is checked out.
5577
5591
5578 To facilitate version control, distribution, and merging of tags,
5592 To facilitate version control, distribution, and merging of tags,
5579 they are stored as a file named ".hgtags" which is managed similarly
5593 they are stored as a file named ".hgtags" which is managed similarly
5580 to other project files and can be hand-edited if necessary. This
5594 to other project files and can be hand-edited if necessary. This
5581 also means that tagging creates a new commit. The file
5595 also means that tagging creates a new commit. The file
5582 ".hg/localtags" is used for local tags (not shared among
5596 ".hg/localtags" is used for local tags (not shared among
5583 repositories).
5597 repositories).
5584
5598
5585 Tag commits are usually made at the head of a branch. If the parent
5599 Tag commits are usually made at the head of a branch. If the parent
5586 of the working directory is not a branch head, :hg:`tag` aborts; use
5600 of the working directory is not a branch head, :hg:`tag` aborts; use
5587 -f/--force to force the tag commit to be based on a non-head
5601 -f/--force to force the tag commit to be based on a non-head
5588 changeset.
5602 changeset.
5589
5603
5590 See :hg:`help dates` for a list of formats valid for -d/--date.
5604 See :hg:`help dates` for a list of formats valid for -d/--date.
5591
5605
5592 Since tag names have priority over branch names during revision
5606 Since tag names have priority over branch names during revision
5593 lookup, using an existing branch name as a tag name is discouraged.
5607 lookup, using an existing branch name as a tag name is discouraged.
5594
5608
5595 Returns 0 on success.
5609 Returns 0 on success.
5596 """
5610 """
5597 wlock = lock = None
5611 wlock = lock = None
5598 try:
5612 try:
5599 wlock = repo.wlock()
5613 wlock = repo.wlock()
5600 lock = repo.lock()
5614 lock = repo.lock()
5601 rev_ = "."
5615 rev_ = "."
5602 names = [t.strip() for t in (name1,) + names]
5616 names = [t.strip() for t in (name1,) + names]
5603 if len(names) != len(set(names)):
5617 if len(names) != len(set(names)):
5604 raise util.Abort(_('tag names must be unique'))
5618 raise util.Abort(_('tag names must be unique'))
5605 for n in names:
5619 for n in names:
5606 if n in ['tip', '.', 'null']:
5620 if n in ['tip', '.', 'null']:
5607 raise util.Abort(_("the name '%s' is reserved") % n)
5621 raise util.Abort(_("the name '%s' is reserved") % n)
5608 if not n:
5622 if not n:
5609 raise util.Abort(_('tag names cannot consist entirely of '
5623 raise util.Abort(_('tag names cannot consist entirely of '
5610 'whitespace'))
5624 'whitespace'))
5611 if opts.get('rev') and opts.get('remove'):
5625 if opts.get('rev') and opts.get('remove'):
5612 raise util.Abort(_("--rev and --remove are incompatible"))
5626 raise util.Abort(_("--rev and --remove are incompatible"))
5613 if opts.get('rev'):
5627 if opts.get('rev'):
5614 rev_ = opts['rev']
5628 rev_ = opts['rev']
5615 message = opts.get('message')
5629 message = opts.get('message')
5616 if opts.get('remove'):
5630 if opts.get('remove'):
5617 expectedtype = opts.get('local') and 'local' or 'global'
5631 expectedtype = opts.get('local') and 'local' or 'global'
5618 for n in names:
5632 for n in names:
5619 if not repo.tagtype(n):
5633 if not repo.tagtype(n):
5620 raise util.Abort(_("tag '%s' does not exist") % n)
5634 raise util.Abort(_("tag '%s' does not exist") % n)
5621 if repo.tagtype(n) != expectedtype:
5635 if repo.tagtype(n) != expectedtype:
5622 if expectedtype == 'global':
5636 if expectedtype == 'global':
5623 raise util.Abort(_("tag '%s' is not a global tag") % n)
5637 raise util.Abort(_("tag '%s' is not a global tag") % n)
5624 else:
5638 else:
5625 raise util.Abort(_("tag '%s' is not a local tag") % n)
5639 raise util.Abort(_("tag '%s' is not a local tag") % n)
5626 rev_ = nullid
5640 rev_ = nullid
5627 if not message:
5641 if not message:
5628 # we don't translate commit messages
5642 # we don't translate commit messages
5629 message = 'Removed tag %s' % ', '.join(names)
5643 message = 'Removed tag %s' % ', '.join(names)
5630 elif not opts.get('force'):
5644 elif not opts.get('force'):
5631 for n in names:
5645 for n in names:
5632 if n in repo.tags():
5646 if n in repo.tags():
5633 raise util.Abort(_("tag '%s' already exists "
5647 raise util.Abort(_("tag '%s' already exists "
5634 "(use -f to force)") % n)
5648 "(use -f to force)") % n)
5635 if not opts.get('local'):
5649 if not opts.get('local'):
5636 p1, p2 = repo.dirstate.parents()
5650 p1, p2 = repo.dirstate.parents()
5637 if p2 != nullid:
5651 if p2 != nullid:
5638 raise util.Abort(_('uncommitted merge'))
5652 raise util.Abort(_('uncommitted merge'))
5639 bheads = repo.branchheads()
5653 bheads = repo.branchheads()
5640 if not opts.get('force') and bheads and p1 not in bheads:
5654 if not opts.get('force') and bheads and p1 not in bheads:
5641 raise util.Abort(_('not at a branch head (use -f to force)'))
5655 raise util.Abort(_('not at a branch head (use -f to force)'))
5642 r = scmutil.revsingle(repo, rev_).node()
5656 r = scmutil.revsingle(repo, rev_).node()
5643
5657
5644 if not message:
5658 if not message:
5645 # we don't translate commit messages
5659 # we don't translate commit messages
5646 message = ('Added tag %s for changeset %s' %
5660 message = ('Added tag %s for changeset %s' %
5647 (', '.join(names), short(r)))
5661 (', '.join(names), short(r)))
5648
5662
5649 date = opts.get('date')
5663 date = opts.get('date')
5650 if date:
5664 if date:
5651 date = util.parsedate(date)
5665 date = util.parsedate(date)
5652
5666
5653 if opts.get('edit'):
5667 if opts.get('edit'):
5654 message = ui.edit(message, ui.username())
5668 message = ui.edit(message, ui.username())
5655
5669
5656 # don't allow tagging the null rev
5670 # don't allow tagging the null rev
5657 if (not opts.get('remove') and
5671 if (not opts.get('remove') and
5658 scmutil.revsingle(repo, rev_).rev() == nullrev):
5672 scmutil.revsingle(repo, rev_).rev() == nullrev):
5659 raise util.Abort(_("null revision specified"))
5673 raise util.Abort(_("null revision specified"))
5660
5674
5661 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5675 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5662 finally:
5676 finally:
5663 release(lock, wlock)
5677 release(lock, wlock)
5664
5678
5665 @command('tags', [], '')
5679 @command('tags', [], '')
5666 def tags(ui, repo):
5680 def tags(ui, repo):
5667 """list repository tags
5681 """list repository tags
5668
5682
5669 This lists both regular and local tags. When the -v/--verbose
5683 This lists both regular and local tags. When the -v/--verbose
5670 switch is used, a third column "local" is printed for local tags.
5684 switch is used, a third column "local" is printed for local tags.
5671
5685
5672 Returns 0 on success.
5686 Returns 0 on success.
5673 """
5687 """
5674
5688
5675 hexfunc = ui.debugflag and hex or short
5689 hexfunc = ui.debugflag and hex or short
5676 tagtype = ""
5690 tagtype = ""
5677
5691
5678 for t, n in reversed(repo.tagslist()):
5692 for t, n in reversed(repo.tagslist()):
5679 if ui.quiet:
5693 if ui.quiet:
5680 ui.write("%s\n" % t, label='tags.normal')
5694 ui.write("%s\n" % t, label='tags.normal')
5681 continue
5695 continue
5682
5696
5683 hn = hexfunc(n)
5697 hn = hexfunc(n)
5684 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5698 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5685 rev = ui.label(r, 'log.changeset')
5699 rev = ui.label(r, 'log.changeset')
5686 spaces = " " * (30 - encoding.colwidth(t))
5700 spaces = " " * (30 - encoding.colwidth(t))
5687
5701
5688 tag = ui.label(t, 'tags.normal')
5702 tag = ui.label(t, 'tags.normal')
5689 if ui.verbose:
5703 if ui.verbose:
5690 if repo.tagtype(t) == 'local':
5704 if repo.tagtype(t) == 'local':
5691 tagtype = " local"
5705 tagtype = " local"
5692 tag = ui.label(t, 'tags.local')
5706 tag = ui.label(t, 'tags.local')
5693 else:
5707 else:
5694 tagtype = ""
5708 tagtype = ""
5695 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5709 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5696
5710
5697 @command('tip',
5711 @command('tip',
5698 [('p', 'patch', None, _('show patch')),
5712 [('p', 'patch', None, _('show patch')),
5699 ('g', 'git', None, _('use git extended diff format')),
5713 ('g', 'git', None, _('use git extended diff format')),
5700 ] + templateopts,
5714 ] + templateopts,
5701 _('[-p] [-g]'))
5715 _('[-p] [-g]'))
5702 def tip(ui, repo, **opts):
5716 def tip(ui, repo, **opts):
5703 """show the tip revision
5717 """show the tip revision
5704
5718
5705 The tip revision (usually just called the tip) is the changeset
5719 The tip revision (usually just called the tip) is the changeset
5706 most recently added to the repository (and therefore the most
5720 most recently added to the repository (and therefore the most
5707 recently changed head).
5721 recently changed head).
5708
5722
5709 If you have just made a commit, that commit will be the tip. If
5723 If you have just made a commit, that commit will be the tip. If
5710 you have just pulled changes from another repository, the tip of
5724 you have just pulled changes from another repository, the tip of
5711 that repository becomes the current tip. The "tip" tag is special
5725 that repository becomes the current tip. The "tip" tag is special
5712 and cannot be renamed or assigned to a different changeset.
5726 and cannot be renamed or assigned to a different changeset.
5713
5727
5714 Returns 0 on success.
5728 Returns 0 on success.
5715 """
5729 """
5716 displayer = cmdutil.show_changeset(ui, repo, opts)
5730 displayer = cmdutil.show_changeset(ui, repo, opts)
5717 displayer.show(repo[len(repo) - 1])
5731 displayer.show(repo[len(repo) - 1])
5718 displayer.close()
5732 displayer.close()
5719
5733
5720 @command('unbundle',
5734 @command('unbundle',
5721 [('u', 'update', None,
5735 [('u', 'update', None,
5722 _('update to new branch head if changesets were unbundled'))],
5736 _('update to new branch head if changesets were unbundled'))],
5723 _('[-u] FILE...'))
5737 _('[-u] FILE...'))
5724 def unbundle(ui, repo, fname1, *fnames, **opts):
5738 def unbundle(ui, repo, fname1, *fnames, **opts):
5725 """apply one or more changegroup files
5739 """apply one or more changegroup files
5726
5740
5727 Apply one or more compressed changegroup files generated by the
5741 Apply one or more compressed changegroup files generated by the
5728 bundle command.
5742 bundle command.
5729
5743
5730 Returns 0 on success, 1 if an update has unresolved files.
5744 Returns 0 on success, 1 if an update has unresolved files.
5731 """
5745 """
5732 fnames = (fname1,) + fnames
5746 fnames = (fname1,) + fnames
5733
5747
5734 lock = repo.lock()
5748 lock = repo.lock()
5735 wc = repo['.']
5749 wc = repo['.']
5736 try:
5750 try:
5737 for fname in fnames:
5751 for fname in fnames:
5738 f = url.open(ui, fname)
5752 f = url.open(ui, fname)
5739 gen = changegroup.readbundle(f, fname)
5753 gen = changegroup.readbundle(f, fname)
5740 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5754 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5741 finally:
5755 finally:
5742 lock.release()
5756 lock.release()
5743 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5757 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5744 return postincoming(ui, repo, modheads, opts.get('update'), None)
5758 return postincoming(ui, repo, modheads, opts.get('update'), None)
5745
5759
5746 @command('^update|up|checkout|co',
5760 @command('^update|up|checkout|co',
5747 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5761 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5748 ('c', 'check', None,
5762 ('c', 'check', None,
5749 _('update across branches if no uncommitted changes')),
5763 _('update across branches if no uncommitted changes')),
5750 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5764 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5751 ('r', 'rev', '', _('revision'), _('REV'))],
5765 ('r', 'rev', '', _('revision'), _('REV'))],
5752 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5766 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5753 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5767 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5754 """update working directory (or switch revisions)
5768 """update working directory (or switch revisions)
5755
5769
5756 Update the repository's working directory to the specified
5770 Update the repository's working directory to the specified
5757 changeset. If no changeset is specified, update to the tip of the
5771 changeset. If no changeset is specified, update to the tip of the
5758 current named branch and move the current bookmark (see :hg:`help
5772 current named branch and move the current bookmark (see :hg:`help
5759 bookmarks`).
5773 bookmarks`).
5760
5774
5761 Update sets the working directory's parent revison to the specified
5775 Update sets the working directory's parent revison to the specified
5762 changeset (see :hg:`help parents`).
5776 changeset (see :hg:`help parents`).
5763
5777
5764 If the changeset is not a descendant or ancestor of the working
5778 If the changeset is not a descendant or ancestor of the working
5765 directory's parent, the update is aborted. With the -c/--check
5779 directory's parent, the update is aborted. With the -c/--check
5766 option, the working directory is checked for uncommitted changes; if
5780 option, the working directory is checked for uncommitted changes; if
5767 none are found, the working directory is updated to the specified
5781 none are found, the working directory is updated to the specified
5768 changeset.
5782 changeset.
5769
5783
5770 .. container:: verbose
5784 .. container:: verbose
5771
5785
5772 The following rules apply when the working directory contains
5786 The following rules apply when the working directory contains
5773 uncommitted changes:
5787 uncommitted changes:
5774
5788
5775 1. If neither -c/--check nor -C/--clean is specified, and if
5789 1. If neither -c/--check nor -C/--clean is specified, and if
5776 the requested changeset is an ancestor or descendant of
5790 the requested changeset is an ancestor or descendant of
5777 the working directory's parent, the uncommitted changes
5791 the working directory's parent, the uncommitted changes
5778 are merged into the requested changeset and the merged
5792 are merged into the requested changeset and the merged
5779 result is left uncommitted. If the requested changeset is
5793 result is left uncommitted. If the requested changeset is
5780 not an ancestor or descendant (that is, it is on another
5794 not an ancestor or descendant (that is, it is on another
5781 branch), the update is aborted and the uncommitted changes
5795 branch), the update is aborted and the uncommitted changes
5782 are preserved.
5796 are preserved.
5783
5797
5784 2. With the -c/--check option, the update is aborted and the
5798 2. With the -c/--check option, the update is aborted and the
5785 uncommitted changes are preserved.
5799 uncommitted changes are preserved.
5786
5800
5787 3. With the -C/--clean option, uncommitted changes are discarded and
5801 3. With the -C/--clean option, uncommitted changes are discarded and
5788 the working directory is updated to the requested changeset.
5802 the working directory is updated to the requested changeset.
5789
5803
5790 To cancel an uncommitted merge (and lose your changes), use
5804 To cancel an uncommitted merge (and lose your changes), use
5791 :hg:`update --clean .`.
5805 :hg:`update --clean .`.
5792
5806
5793 Use null as the changeset to remove the working directory (like
5807 Use null as the changeset to remove the working directory (like
5794 :hg:`clone -U`).
5808 :hg:`clone -U`).
5795
5809
5796 If you want to revert just one file to an older revision, use
5810 If you want to revert just one file to an older revision, use
5797 :hg:`revert [-r REV] NAME`.
5811 :hg:`revert [-r REV] NAME`.
5798
5812
5799 See :hg:`help dates` for a list of formats valid for -d/--date.
5813 See :hg:`help dates` for a list of formats valid for -d/--date.
5800
5814
5801 Returns 0 on success, 1 if there are unresolved files.
5815 Returns 0 on success, 1 if there are unresolved files.
5802 """
5816 """
5803 if rev and node:
5817 if rev and node:
5804 raise util.Abort(_("please specify just one revision"))
5818 raise util.Abort(_("please specify just one revision"))
5805
5819
5806 if rev is None or rev == '':
5820 if rev is None or rev == '':
5807 rev = node
5821 rev = node
5808
5822
5809 # with no argument, we also move the current bookmark, if any
5823 # with no argument, we also move the current bookmark, if any
5810 movemarkfrom = None
5824 movemarkfrom = None
5811 if rev is None or node == '':
5825 if rev is None or node == '':
5812 movemarkfrom = repo['.'].node()
5826 movemarkfrom = repo['.'].node()
5813
5827
5814 # if we defined a bookmark, we have to remember the original bookmark name
5828 # if we defined a bookmark, we have to remember the original bookmark name
5815 brev = rev
5829 brev = rev
5816 rev = scmutil.revsingle(repo, rev, rev).rev()
5830 rev = scmutil.revsingle(repo, rev, rev).rev()
5817
5831
5818 if check and clean:
5832 if check and clean:
5819 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5833 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5820
5834
5821 if date:
5835 if date:
5822 if rev is not None:
5836 if rev is not None:
5823 raise util.Abort(_("you can't specify a revision and a date"))
5837 raise util.Abort(_("you can't specify a revision and a date"))
5824 rev = cmdutil.finddate(ui, repo, date)
5838 rev = cmdutil.finddate(ui, repo, date)
5825
5839
5826 if check:
5840 if check:
5827 c = repo[None]
5841 c = repo[None]
5828 if c.dirty(merge=False, branch=False):
5842 if c.dirty(merge=False, branch=False):
5829 raise util.Abort(_("uncommitted local changes"))
5843 raise util.Abort(_("uncommitted local changes"))
5830 if rev is None:
5844 if rev is None:
5831 rev = repo[repo[None].branch()].rev()
5845 rev = repo[repo[None].branch()].rev()
5832 mergemod._checkunknown(repo, repo[None], repo[rev])
5846 mergemod._checkunknown(repo, repo[None], repo[rev])
5833
5847
5834 if clean:
5848 if clean:
5835 ret = hg.clean(repo, rev)
5849 ret = hg.clean(repo, rev)
5836 else:
5850 else:
5837 ret = hg.update(repo, rev)
5851 ret = hg.update(repo, rev)
5838
5852
5839 if not ret and movemarkfrom:
5853 if not ret and movemarkfrom:
5840 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5854 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5841 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5855 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5842 elif brev in repo._bookmarks:
5856 elif brev in repo._bookmarks:
5843 bookmarks.setcurrent(repo, brev)
5857 bookmarks.setcurrent(repo, brev)
5844 elif brev:
5858 elif brev:
5845 bookmarks.unsetcurrent(repo)
5859 bookmarks.unsetcurrent(repo)
5846
5860
5847 return ret
5861 return ret
5848
5862
5849 @command('verify', [])
5863 @command('verify', [])
5850 def verify(ui, repo):
5864 def verify(ui, repo):
5851 """verify the integrity of the repository
5865 """verify the integrity of the repository
5852
5866
5853 Verify the integrity of the current repository.
5867 Verify the integrity of the current repository.
5854
5868
5855 This will perform an extensive check of the repository's
5869 This will perform an extensive check of the repository's
5856 integrity, validating the hashes and checksums of each entry in
5870 integrity, validating the hashes and checksums of each entry in
5857 the changelog, manifest, and tracked files, as well as the
5871 the changelog, manifest, and tracked files, as well as the
5858 integrity of their crosslinks and indices.
5872 integrity of their crosslinks and indices.
5859
5873
5860 Returns 0 on success, 1 if errors are encountered.
5874 Returns 0 on success, 1 if errors are encountered.
5861 """
5875 """
5862 return hg.verify(repo)
5876 return hg.verify(repo)
5863
5877
5864 @command('version', [])
5878 @command('version', [])
5865 def version_(ui):
5879 def version_(ui):
5866 """output version and copyright information"""
5880 """output version and copyright information"""
5867 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5881 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5868 % util.version())
5882 % util.version())
5869 ui.status(_(
5883 ui.status(_(
5870 "(see http://mercurial.selenic.com for more information)\n"
5884 "(see http://mercurial.selenic.com for more information)\n"
5871 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5885 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5872 "This is free software; see the source for copying conditions. "
5886 "This is free software; see the source for copying conditions. "
5873 "There is NO\nwarranty; "
5887 "There is NO\nwarranty; "
5874 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5888 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5875 ))
5889 ))
5876
5890
5877 norepo = ("clone init version help debugcommands debugcomplete"
5891 norepo = ("clone init version help debugcommands debugcomplete"
5878 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5892 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5879 " debugknown debuggetbundle debugbundle")
5893 " debugknown debuggetbundle debugbundle")
5880 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5894 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5881 " debugdata debugindex debugindexdot debugrevlog")
5895 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,473 +1,479 b''
1 $ cat >> $HGRCPATH << EOF
1 $ cat >> $HGRCPATH << EOF
2 > [extensions]
2 > [extensions]
3 > graphlog=
3 > graphlog=
4 > [phases]
4 > [phases]
5 > # public changeset are not obsolete
5 > # public changeset are not obsolete
6 > publish=false
6 > publish=false
7 > EOF
7 > EOF
8 $ mkcommit() {
8 $ mkcommit() {
9 > echo "$1" > "$1"
9 > echo "$1" > "$1"
10 > hg add "$1"
10 > hg add "$1"
11 > hg ci -m "add $1"
11 > hg ci -m "add $1"
12 > }
12 > }
13 $ getid() {
13 $ getid() {
14 > hg id --debug -ir "desc('$1')"
14 > hg id --debug -ir "desc('$1')"
15 > }
15 > }
16
16
17 $ cat > debugkeys.py <<EOF
17 $ cat > debugkeys.py <<EOF
18 > def reposetup(ui, repo):
18 > def reposetup(ui, repo):
19 > class debugkeysrepo(repo.__class__):
19 > class debugkeysrepo(repo.__class__):
20 > def listkeys(self, namespace):
20 > def listkeys(self, namespace):
21 > ui.write('listkeys %s\n' % (namespace,))
21 > ui.write('listkeys %s\n' % (namespace,))
22 > return super(debugkeysrepo, self).listkeys(namespace)
22 > return super(debugkeysrepo, self).listkeys(namespace)
23 >
23 >
24 > if repo.local():
24 > if repo.local():
25 > repo.__class__ = debugkeysrepo
25 > repo.__class__ = debugkeysrepo
26 > EOF
26 > EOF
27
27
28 $ hg init tmpa
28 $ hg init tmpa
29 $ cd tmpa
29 $ cd tmpa
30
30
31 Killing a single changeset without replacement
31 Killing a single changeset without replacement
32
32
33 $ mkcommit kill_me
33 $ mkcommit kill_me
34 $ hg debugobsolete 0
35 abort: changeset references must be full hexadecimal node identifiers
36 [255]
37 $ hg debugobsolete '00'
38 abort: changeset references must be full hexadecimal node identifiers
39 [255]
34 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
40 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
35 $ hg debugobsolete
41 $ hg debugobsolete
36 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 {'date': '0 0', 'user': 'babar'}
42 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 {'date': '0 0', 'user': 'babar'}
37 $ cd ..
43 $ cd ..
38
44
39 Killing a single changeset with replacement
45 Killing a single changeset with replacement
40
46
41 $ hg init tmpb
47 $ hg init tmpb
42 $ cd tmpb
48 $ cd tmpb
43 $ mkcommit a
49 $ mkcommit a
44 $ mkcommit b
50 $ mkcommit b
45 $ mkcommit original_c
51 $ mkcommit original_c
46 $ hg up "desc('b')"
52 $ hg up "desc('b')"
47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
53 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
48 $ mkcommit new_c
54 $ mkcommit new_c
49 created new head
55 created new head
50 $ hg debugobsolete `getid original_c` `getid new_c` -d '56 12'
56 $ hg debugobsolete `getid original_c` `getid new_c` -d '56 12'
51 $ hg debugobsolete
57 $ hg debugobsolete
52 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
58 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
53
59
54 do it again (it read the obsstore before adding new changeset)
60 do it again (it read the obsstore before adding new changeset)
55
61
56 $ hg up '.^'
62 $ hg up '.^'
57 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
63 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
58 $ mkcommit new_2_c
64 $ mkcommit new_2_c
59 created new head
65 created new head
60 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
66 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
61 $ hg debugobsolete
67 $ hg debugobsolete
62 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
68 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
63 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
69 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
64
70
65 Register two markers with a missing node
71 Register two markers with a missing node
66
72
67 $ hg up '.^'
73 $ hg up '.^'
68 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
74 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
69 $ mkcommit new_3_c
75 $ mkcommit new_3_c
70 created new head
76 created new head
71 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
77 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
72 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
78 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
73 $ hg debugobsolete
79 $ hg debugobsolete
74 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
80 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
75 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
81 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
76 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
82 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
77 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
83 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
78
84
79 Check that graphlog detect that a changeset is obsolete:
85 Check that graphlog detect that a changeset is obsolete:
80
86
81 $ hg glog
87 $ hg glog
82 @ changeset: 5:5601fb93a350
88 @ changeset: 5:5601fb93a350
83 | tag: tip
89 | tag: tip
84 | parent: 1:7c3bad9141dc
90 | parent: 1:7c3bad9141dc
85 | user: test
91 | user: test
86 | date: Thu Jan 01 00:00:00 1970 +0000
92 | date: Thu Jan 01 00:00:00 1970 +0000
87 | summary: add new_3_c
93 | summary: add new_3_c
88 |
94 |
89 o changeset: 1:7c3bad9141dc
95 o changeset: 1:7c3bad9141dc
90 | user: test
96 | user: test
91 | date: Thu Jan 01 00:00:00 1970 +0000
97 | date: Thu Jan 01 00:00:00 1970 +0000
92 | summary: add b
98 | summary: add b
93 |
99 |
94 o changeset: 0:1f0dee641bb7
100 o changeset: 0:1f0dee641bb7
95 user: test
101 user: test
96 date: Thu Jan 01 00:00:00 1970 +0000
102 date: Thu Jan 01 00:00:00 1970 +0000
97 summary: add a
103 summary: add a
98
104
99
105
100 Check that public changeset are not accounted as obsolete:
106 Check that public changeset are not accounted as obsolete:
101
107
102 $ hg phase --public 2
108 $ hg phase --public 2
103 $ hg --config 'extensions.graphlog=' glog
109 $ hg --config 'extensions.graphlog=' glog
104 @ changeset: 5:5601fb93a350
110 @ changeset: 5:5601fb93a350
105 | tag: tip
111 | tag: tip
106 | parent: 1:7c3bad9141dc
112 | parent: 1:7c3bad9141dc
107 | user: test
113 | user: test
108 | date: Thu Jan 01 00:00:00 1970 +0000
114 | date: Thu Jan 01 00:00:00 1970 +0000
109 | summary: add new_3_c
115 | summary: add new_3_c
110 |
116 |
111 | o changeset: 2:245bde4270cd
117 | o changeset: 2:245bde4270cd
112 |/ user: test
118 |/ user: test
113 | date: Thu Jan 01 00:00:00 1970 +0000
119 | date: Thu Jan 01 00:00:00 1970 +0000
114 | summary: add original_c
120 | summary: add original_c
115 |
121 |
116 o changeset: 1:7c3bad9141dc
122 o changeset: 1:7c3bad9141dc
117 | user: test
123 | user: test
118 | date: Thu Jan 01 00:00:00 1970 +0000
124 | date: Thu Jan 01 00:00:00 1970 +0000
119 | summary: add b
125 | summary: add b
120 |
126 |
121 o changeset: 0:1f0dee641bb7
127 o changeset: 0:1f0dee641bb7
122 user: test
128 user: test
123 date: Thu Jan 01 00:00:00 1970 +0000
129 date: Thu Jan 01 00:00:00 1970 +0000
124 summary: add a
130 summary: add a
125
131
126
132
127 $ cd ..
133 $ cd ..
128
134
129 Exchange Test
135 Exchange Test
130 ============================
136 ============================
131
137
132 Destination repo does not have any data
138 Destination repo does not have any data
133 ---------------------------------------
139 ---------------------------------------
134
140
135 Try to pull markers
141 Try to pull markers
136 (extinct changeset are excluded but marker are pushed)
142 (extinct changeset are excluded but marker are pushed)
137
143
138 $ hg init tmpc
144 $ hg init tmpc
139 $ cd tmpc
145 $ cd tmpc
140 $ hg pull ../tmpb
146 $ hg pull ../tmpb
141 pulling from ../tmpb
147 pulling from ../tmpb
142 requesting all changes
148 requesting all changes
143 adding changesets
149 adding changesets
144 adding manifests
150 adding manifests
145 adding file changes
151 adding file changes
146 added 4 changesets with 4 changes to 4 files (+1 heads)
152 added 4 changesets with 4 changes to 4 files (+1 heads)
147 (run 'hg heads' to see heads, 'hg merge' to merge)
153 (run 'hg heads' to see heads, 'hg merge' to merge)
148 $ hg debugobsolete
154 $ hg debugobsolete
149 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
155 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
150 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
156 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
151 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
157 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
152 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
158 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
153
159
154 Rollback//Transaction support
160 Rollback//Transaction support
155
161
156 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
162 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
157 $ hg debugobsolete
163 $ hg debugobsolete
158 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
164 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
159 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
165 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
160 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
166 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
161 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
167 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
162 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 {'date': '1340 0', 'user': 'test'}
168 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 {'date': '1340 0', 'user': 'test'}
163 $ hg rollback -n
169 $ hg rollback -n
164 repository tip rolled back to revision 3 (undo debugobsolete)
170 repository tip rolled back to revision 3 (undo debugobsolete)
165 $ hg rollback
171 $ hg rollback
166 repository tip rolled back to revision 3 (undo debugobsolete)
172 repository tip rolled back to revision 3 (undo debugobsolete)
167 $ hg debugobsolete
173 $ hg debugobsolete
168 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
174 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
169 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
175 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
170 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
176 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
171 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
177 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
172
178
173 $ cd ..
179 $ cd ..
174
180
175 Try to pull markers
181 Try to pull markers
176
182
177 $ hg init tmpd
183 $ hg init tmpd
178 $ hg -R tmpb push tmpd
184 $ hg -R tmpb push tmpd
179 pushing to tmpd
185 pushing to tmpd
180 searching for changes
186 searching for changes
181 adding changesets
187 adding changesets
182 adding manifests
188 adding manifests
183 adding file changes
189 adding file changes
184 added 4 changesets with 4 changes to 4 files (+1 heads)
190 added 4 changesets with 4 changes to 4 files (+1 heads)
185 $ hg -R tmpd debugobsolete
191 $ hg -R tmpd debugobsolete
186 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
192 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
187 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
193 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
188 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
194 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
189 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
195 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
190
196
191 Check obsolete keys are exchanged only if source has an obsolete store
197 Check obsolete keys are exchanged only if source has an obsolete store
192
198
193 $ hg init empty
199 $ hg init empty
194 $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd
200 $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd
195 pushing to tmpd
201 pushing to tmpd
196 no changes found
202 no changes found
197 listkeys phases
203 listkeys phases
198 listkeys bookmarks
204 listkeys bookmarks
199 [1]
205 [1]
200
206
201 clone support
207 clone support
202 (markers are copied and extinct changesets are included to allow hardlinks)
208 (markers are copied and extinct changesets are included to allow hardlinks)
203
209
204 $ hg clone tmpb clone-dest
210 $ hg clone tmpb clone-dest
205 updating to branch default
211 updating to branch default
206 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
212 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 $ hg -R clone-dest log -G --hidden
213 $ hg -R clone-dest log -G --hidden
208 @ changeset: 5:5601fb93a350
214 @ changeset: 5:5601fb93a350
209 | tag: tip
215 | tag: tip
210 | parent: 1:7c3bad9141dc
216 | parent: 1:7c3bad9141dc
211 | user: test
217 | user: test
212 | date: Thu Jan 01 00:00:00 1970 +0000
218 | date: Thu Jan 01 00:00:00 1970 +0000
213 | summary: add new_3_c
219 | summary: add new_3_c
214 |
220 |
215 | x changeset: 4:ca819180edb9
221 | x changeset: 4:ca819180edb9
216 |/ parent: 1:7c3bad9141dc
222 |/ parent: 1:7c3bad9141dc
217 | user: test
223 | user: test
218 | date: Thu Jan 01 00:00:00 1970 +0000
224 | date: Thu Jan 01 00:00:00 1970 +0000
219 | summary: add new_2_c
225 | summary: add new_2_c
220 |
226 |
221 | x changeset: 3:cdbce2fbb163
227 | x changeset: 3:cdbce2fbb163
222 |/ parent: 1:7c3bad9141dc
228 |/ parent: 1:7c3bad9141dc
223 | user: test
229 | user: test
224 | date: Thu Jan 01 00:00:00 1970 +0000
230 | date: Thu Jan 01 00:00:00 1970 +0000
225 | summary: add new_c
231 | summary: add new_c
226 |
232 |
227 | o changeset: 2:245bde4270cd
233 | o changeset: 2:245bde4270cd
228 |/ user: test
234 |/ user: test
229 | date: Thu Jan 01 00:00:00 1970 +0000
235 | date: Thu Jan 01 00:00:00 1970 +0000
230 | summary: add original_c
236 | summary: add original_c
231 |
237 |
232 o changeset: 1:7c3bad9141dc
238 o changeset: 1:7c3bad9141dc
233 | user: test
239 | user: test
234 | date: Thu Jan 01 00:00:00 1970 +0000
240 | date: Thu Jan 01 00:00:00 1970 +0000
235 | summary: add b
241 | summary: add b
236 |
242 |
237 o changeset: 0:1f0dee641bb7
243 o changeset: 0:1f0dee641bb7
238 user: test
244 user: test
239 date: Thu Jan 01 00:00:00 1970 +0000
245 date: Thu Jan 01 00:00:00 1970 +0000
240 summary: add a
246 summary: add a
241
247
242 $ hg -R clone-dest debugobsolete
248 $ hg -R clone-dest debugobsolete
243 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
249 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
244 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
250 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
245 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
251 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
246 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
252 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
247
253
248
254
249 Destination repo have existing data
255 Destination repo have existing data
250 ---------------------------------------
256 ---------------------------------------
251
257
252 On pull
258 On pull
253
259
254 $ hg init tmpe
260 $ hg init tmpe
255 $ cd tmpe
261 $ cd tmpe
256 $ hg debugobsolete -d '1339 0' 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339
262 $ hg debugobsolete -d '1339 0' 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339
257 $ hg pull ../tmpb
263 $ hg pull ../tmpb
258 pulling from ../tmpb
264 pulling from ../tmpb
259 requesting all changes
265 requesting all changes
260 adding changesets
266 adding changesets
261 adding manifests
267 adding manifests
262 adding file changes
268 adding file changes
263 added 4 changesets with 4 changes to 4 files (+1 heads)
269 added 4 changesets with 4 changes to 4 files (+1 heads)
264 (run 'hg heads' to see heads, 'hg merge' to merge)
270 (run 'hg heads' to see heads, 'hg merge' to merge)
265 $ hg debugobsolete
271 $ hg debugobsolete
266 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}
272 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}
267 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
273 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
268 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
274 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
269 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
275 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
270 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
276 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
271
277
272
278
273 On push
279 On push
274
280
275 $ hg push ../tmpc
281 $ hg push ../tmpc
276 pushing to ../tmpc
282 pushing to ../tmpc
277 searching for changes
283 searching for changes
278 no changes found
284 no changes found
279 [1]
285 [1]
280 $ hg -R ../tmpc debugobsolete
286 $ hg -R ../tmpc debugobsolete
281 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
287 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
282 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
288 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
283 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
289 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
284 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
290 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
285 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}
291 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}
286
292
287 detect outgoing obsolete and unstable
293 detect outgoing obsolete and unstable
288 ---------------------------------------
294 ---------------------------------------
289
295
290
296
291 $ hg glog
297 $ hg glog
292 o changeset: 3:5601fb93a350
298 o changeset: 3:5601fb93a350
293 | tag: tip
299 | tag: tip
294 | parent: 1:7c3bad9141dc
300 | parent: 1:7c3bad9141dc
295 | user: test
301 | user: test
296 | date: Thu Jan 01 00:00:00 1970 +0000
302 | date: Thu Jan 01 00:00:00 1970 +0000
297 | summary: add new_3_c
303 | summary: add new_3_c
298 |
304 |
299 | o changeset: 2:245bde4270cd
305 | o changeset: 2:245bde4270cd
300 |/ user: test
306 |/ user: test
301 | date: Thu Jan 01 00:00:00 1970 +0000
307 | date: Thu Jan 01 00:00:00 1970 +0000
302 | summary: add original_c
308 | summary: add original_c
303 |
309 |
304 o changeset: 1:7c3bad9141dc
310 o changeset: 1:7c3bad9141dc
305 | user: test
311 | user: test
306 | date: Thu Jan 01 00:00:00 1970 +0000
312 | date: Thu Jan 01 00:00:00 1970 +0000
307 | summary: add b
313 | summary: add b
308 |
314 |
309 o changeset: 0:1f0dee641bb7
315 o changeset: 0:1f0dee641bb7
310 user: test
316 user: test
311 date: Thu Jan 01 00:00:00 1970 +0000
317 date: Thu Jan 01 00:00:00 1970 +0000
312 summary: add a
318 summary: add a
313
319
314 $ hg up 'desc("new_3_c")'
320 $ hg up 'desc("new_3_c")'
315 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
321 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
316 $ mkcommit original_d
322 $ mkcommit original_d
317 $ mkcommit original_e
323 $ mkcommit original_e
318 $ hg debugobsolete `getid original_d` -d '0 0'
324 $ hg debugobsolete `getid original_d` -d '0 0'
319 $ hg log -r 'obsolete()'
325 $ hg log -r 'obsolete()'
320 changeset: 4:7c694bff0650
326 changeset: 4:7c694bff0650
321 user: test
327 user: test
322 date: Thu Jan 01 00:00:00 1970 +0000
328 date: Thu Jan 01 00:00:00 1970 +0000
323 summary: add original_d
329 summary: add original_d
324
330
325 $ hg glog -r '::unstable()'
331 $ hg glog -r '::unstable()'
326 @ changeset: 5:6e572121998e
332 @ changeset: 5:6e572121998e
327 | tag: tip
333 | tag: tip
328 | user: test
334 | user: test
329 | date: Thu Jan 01 00:00:00 1970 +0000
335 | date: Thu Jan 01 00:00:00 1970 +0000
330 | summary: add original_e
336 | summary: add original_e
331 |
337 |
332 x changeset: 4:7c694bff0650
338 x changeset: 4:7c694bff0650
333 | user: test
339 | user: test
334 | date: Thu Jan 01 00:00:00 1970 +0000
340 | date: Thu Jan 01 00:00:00 1970 +0000
335 | summary: add original_d
341 | summary: add original_d
336 |
342 |
337 o changeset: 3:5601fb93a350
343 o changeset: 3:5601fb93a350
338 | parent: 1:7c3bad9141dc
344 | parent: 1:7c3bad9141dc
339 | user: test
345 | user: test
340 | date: Thu Jan 01 00:00:00 1970 +0000
346 | date: Thu Jan 01 00:00:00 1970 +0000
341 | summary: add new_3_c
347 | summary: add new_3_c
342 |
348 |
343 o changeset: 1:7c3bad9141dc
349 o changeset: 1:7c3bad9141dc
344 | user: test
350 | user: test
345 | date: Thu Jan 01 00:00:00 1970 +0000
351 | date: Thu Jan 01 00:00:00 1970 +0000
346 | summary: add b
352 | summary: add b
347 |
353 |
348 o changeset: 0:1f0dee641bb7
354 o changeset: 0:1f0dee641bb7
349 user: test
355 user: test
350 date: Thu Jan 01 00:00:00 1970 +0000
356 date: Thu Jan 01 00:00:00 1970 +0000
351 summary: add a
357 summary: add a
352
358
353
359
354 refuse to push obsolete changeset
360 refuse to push obsolete changeset
355
361
356 $ hg push ../tmpc/ -r 'desc("original_d")'
362 $ hg push ../tmpc/ -r 'desc("original_d")'
357 pushing to ../tmpc/
363 pushing to ../tmpc/
358 searching for changes
364 searching for changes
359 abort: push includes an obsolete changeset: 7c694bff0650!
365 abort: push includes an obsolete changeset: 7c694bff0650!
360 [255]
366 [255]
361
367
362 refuse to push unstable changeset
368 refuse to push unstable changeset
363
369
364 $ hg push ../tmpc/
370 $ hg push ../tmpc/
365 pushing to ../tmpc/
371 pushing to ../tmpc/
366 searching for changes
372 searching for changes
367 abort: push includes an unstable changeset: 6e572121998e!
373 abort: push includes an unstable changeset: 6e572121998e!
368 [255]
374 [255]
369
375
370 Test that extinct changeset are properly detected
376 Test that extinct changeset are properly detected
371
377
372 $ hg log -r 'extinct()'
378 $ hg log -r 'extinct()'
373
379
374 Don't try to push extinct changeset
380 Don't try to push extinct changeset
375
381
376 $ hg init ../tmpf
382 $ hg init ../tmpf
377 $ hg out ../tmpf
383 $ hg out ../tmpf
378 comparing with ../tmpf
384 comparing with ../tmpf
379 searching for changes
385 searching for changes
380 changeset: 0:1f0dee641bb7
386 changeset: 0:1f0dee641bb7
381 user: test
387 user: test
382 date: Thu Jan 01 00:00:00 1970 +0000
388 date: Thu Jan 01 00:00:00 1970 +0000
383 summary: add a
389 summary: add a
384
390
385 changeset: 1:7c3bad9141dc
391 changeset: 1:7c3bad9141dc
386 user: test
392 user: test
387 date: Thu Jan 01 00:00:00 1970 +0000
393 date: Thu Jan 01 00:00:00 1970 +0000
388 summary: add b
394 summary: add b
389
395
390 changeset: 2:245bde4270cd
396 changeset: 2:245bde4270cd
391 user: test
397 user: test
392 date: Thu Jan 01 00:00:00 1970 +0000
398 date: Thu Jan 01 00:00:00 1970 +0000
393 summary: add original_c
399 summary: add original_c
394
400
395 changeset: 3:5601fb93a350
401 changeset: 3:5601fb93a350
396 parent: 1:7c3bad9141dc
402 parent: 1:7c3bad9141dc
397 user: test
403 user: test
398 date: Thu Jan 01 00:00:00 1970 +0000
404 date: Thu Jan 01 00:00:00 1970 +0000
399 summary: add new_3_c
405 summary: add new_3_c
400
406
401 changeset: 4:7c694bff0650
407 changeset: 4:7c694bff0650
402 user: test
408 user: test
403 date: Thu Jan 01 00:00:00 1970 +0000
409 date: Thu Jan 01 00:00:00 1970 +0000
404 summary: add original_d
410 summary: add original_d
405
411
406 changeset: 5:6e572121998e
412 changeset: 5:6e572121998e
407 tag: tip
413 tag: tip
408 user: test
414 user: test
409 date: Thu Jan 01 00:00:00 1970 +0000
415 date: Thu Jan 01 00:00:00 1970 +0000
410 summary: add original_e
416 summary: add original_e
411
417
412 $ hg push ../tmpf -f # -f because be push unstable too
418 $ hg push ../tmpf -f # -f because be push unstable too
413 pushing to ../tmpf
419 pushing to ../tmpf
414 searching for changes
420 searching for changes
415 adding changesets
421 adding changesets
416 adding manifests
422 adding manifests
417 adding file changes
423 adding file changes
418 added 6 changesets with 6 changes to 6 files (+1 heads)
424 added 6 changesets with 6 changes to 6 files (+1 heads)
419
425
420 no warning displayed
426 no warning displayed
421
427
422 $ hg push ../tmpf
428 $ hg push ../tmpf
423 pushing to ../tmpf
429 pushing to ../tmpf
424 searching for changes
430 searching for changes
425 no changes found
431 no changes found
426 [1]
432 [1]
427
433
428 Do not warn about new head when the new head is a successors of a remote one
434 Do not warn about new head when the new head is a successors of a remote one
429
435
430 $ hg glog
436 $ hg glog
431 @ changeset: 5:6e572121998e
437 @ changeset: 5:6e572121998e
432 | tag: tip
438 | tag: tip
433 | user: test
439 | user: test
434 | date: Thu Jan 01 00:00:00 1970 +0000
440 | date: Thu Jan 01 00:00:00 1970 +0000
435 | summary: add original_e
441 | summary: add original_e
436 |
442 |
437 x changeset: 4:7c694bff0650
443 x changeset: 4:7c694bff0650
438 | user: test
444 | user: test
439 | date: Thu Jan 01 00:00:00 1970 +0000
445 | date: Thu Jan 01 00:00:00 1970 +0000
440 | summary: add original_d
446 | summary: add original_d
441 |
447 |
442 o changeset: 3:5601fb93a350
448 o changeset: 3:5601fb93a350
443 | parent: 1:7c3bad9141dc
449 | parent: 1:7c3bad9141dc
444 | user: test
450 | user: test
445 | date: Thu Jan 01 00:00:00 1970 +0000
451 | date: Thu Jan 01 00:00:00 1970 +0000
446 | summary: add new_3_c
452 | summary: add new_3_c
447 |
453 |
448 | o changeset: 2:245bde4270cd
454 | o changeset: 2:245bde4270cd
449 |/ user: test
455 |/ user: test
450 | date: Thu Jan 01 00:00:00 1970 +0000
456 | date: Thu Jan 01 00:00:00 1970 +0000
451 | summary: add original_c
457 | summary: add original_c
452 |
458 |
453 o changeset: 1:7c3bad9141dc
459 o changeset: 1:7c3bad9141dc
454 | user: test
460 | user: test
455 | date: Thu Jan 01 00:00:00 1970 +0000
461 | date: Thu Jan 01 00:00:00 1970 +0000
456 | summary: add b
462 | summary: add b
457 |
463 |
458 o changeset: 0:1f0dee641bb7
464 o changeset: 0:1f0dee641bb7
459 user: test
465 user: test
460 date: Thu Jan 01 00:00:00 1970 +0000
466 date: Thu Jan 01 00:00:00 1970 +0000
461 summary: add a
467 summary: add a
462
468
463 $ hg up -q 'desc(new_3_c)'
469 $ hg up -q 'desc(new_3_c)'
464 $ mkcommit obsolete_e
470 $ mkcommit obsolete_e
465 created new head
471 created new head
466 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'`
472 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'`
467 $ hg push ../tmpf
473 $ hg push ../tmpf
468 pushing to ../tmpf
474 pushing to ../tmpf
469 searching for changes
475 searching for changes
470 adding changesets
476 adding changesets
471 adding manifests
477 adding manifests
472 adding file changes
478 adding file changes
473 added 1 changesets with 1 changes to 1 files (+1 heads)
479 added 1 changesets with 1 changes to 1 files (+1 heads)
General Comments 0
You need to be logged in to leave comments. Login now